|
@@ -151,7 +151,7 @@ void MapblockMeshGenerator::drawQuad(v3f *coords, const v3s16 &normal,
|
|
|
// the faces in the list is up-down-right-left-back-front
|
|
|
// (compatible with ContentFeatures).
|
|
|
void MapblockMeshGenerator::drawCuboid(const aabb3f &box,
|
|
|
- TileSpec *tiles, int tilecount, const LightPair *lights, const f32 *txc)
|
|
|
+ TileSpec *tiles, int tilecount, const LightInfo *lights, const f32 *txc)
|
|
|
{
|
|
|
assert(tilecount >= 1 && tilecount <= 6); // pre-condition
|
|
|
|
|
@@ -263,10 +263,12 @@ void MapblockMeshGenerator::drawCuboid(const aabb3f &box,
|
|
|
|
|
|
if (data->m_smooth_lighting) {
|
|
|
for (int j = 0; j < 24; ++j) {
|
|
|
- vertices[j].Color = encode_light(lights[light_indices[j]],
|
|
|
+ video::S3DVertex &vertex = vertices[j];
|
|
|
+ vertex.Color = encode_light(
|
|
|
+ lights[light_indices[j]].getPair(MYMAX(0.0f, vertex.Normal.Y)),
|
|
|
f->light_source);
|
|
|
if (!f->light_source)
|
|
|
- applyFacesShading(vertices[j].Color, vertices[j].Normal);
|
|
|
+ applyFacesShading(vertex.Color, vertex.Normal);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -280,30 +282,45 @@ void MapblockMeshGenerator::drawCuboid(const aabb3f &box,
|
|
|
// Gets the base lighting values for a node
|
|
|
void MapblockMeshGenerator::getSmoothLightFrame()
|
|
|
{
|
|
|
+ for (int k = 0; k < 8; ++k)
|
|
|
+ frame.sunlight[k] = false;
|
|
|
for (int k = 0; k < 8; ++k) {
|
|
|
LightPair light(getSmoothLightTransparent(blockpos_nodes + p, light_dirs[k], data));
|
|
|
- frame.lightsA[k] = light.lightA;
|
|
|
- frame.lightsB[k] = light.lightB;
|
|
|
+ frame.lightsDay[k] = light.lightDay;
|
|
|
+ frame.lightsNight[k] = light.lightNight;
|
|
|
+ // If there is direct sunlight and no ambient occlusion at some corner,
|
|
|
+ // mark the vertical edge (top and bottom corners) containing it.
|
|
|
+ if (light.lightDay == 255) {
|
|
|
+ frame.sunlight[k] = true;
|
|
|
+ frame.sunlight[k ^ 2] = true;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Calculates vertex light level
|
|
|
// vertex_pos - vertex position in the node (coordinates are clamped to [0.0, 1.0] or so)
|
|
|
-LightPair MapblockMeshGenerator::blendLight(const v3f &vertex_pos)
|
|
|
+LightInfo MapblockMeshGenerator::blendLight(const v3f &vertex_pos)
|
|
|
{
|
|
|
+ // Light levels at (logical) node corners are known. Here,
|
|
|
+ // trilinear interpolation is used to calculate light level
|
|
|
+ // at a given point in the node.
|
|
|
f32 x = core::clamp(vertex_pos.X / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, 1.0 + SMOOTH_LIGHTING_OVERSIZE);
|
|
|
f32 y = core::clamp(vertex_pos.Y / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, 1.0 + SMOOTH_LIGHTING_OVERSIZE);
|
|
|
f32 z = core::clamp(vertex_pos.Z / BS + 0.5, 0.0 - SMOOTH_LIGHTING_OVERSIZE, 1.0 + SMOOTH_LIGHTING_OVERSIZE);
|
|
|
- f32 lightA = 0.0;
|
|
|
- f32 lightB = 0.0;
|
|
|
+ f32 lightDay = 0.0; // daylight
|
|
|
+ f32 lightNight = 0.0;
|
|
|
+ f32 lightBoosted = 0.0; // daylight + direct sunlight, if any
|
|
|
for (int k = 0; k < 8; ++k) {
|
|
|
f32 dx = (k & 4) ? x : 1 - x;
|
|
|
f32 dy = (k & 2) ? y : 1 - y;
|
|
|
f32 dz = (k & 1) ? z : 1 - z;
|
|
|
- lightA += dx * dy * dz * frame.lightsA[k];
|
|
|
- lightB += dx * dy * dz * frame.lightsB[k];
|
|
|
+ // Use direct sunlight (255), if any; use daylight otherwise.
|
|
|
+ f32 light_boosted = frame.sunlight[k] ? 255 : frame.lightsDay[k];
|
|
|
+ lightDay += dx * dy * dz * frame.lightsDay[k];
|
|
|
+ lightNight += dx * dy * dz * frame.lightsNight[k];
|
|
|
+ lightBoosted += dx * dy * dz * light_boosted;
|
|
|
}
|
|
|
- return LightPair(lightA, lightB);
|
|
|
+ return LightInfo{lightDay, lightNight, lightBoosted};
|
|
|
}
|
|
|
|
|
|
// Calculates vertex color to be used in mapblock mesh
|
|
@@ -311,14 +328,15 @@ LightPair MapblockMeshGenerator::blendLight(const v3f &vertex_pos)
|
|
|
// tile_color - node's tile color
|
|
|
video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos)
|
|
|
{
|
|
|
- LightPair light = blendLight(vertex_pos);
|
|
|
- return encode_light(light, f->light_source);
|
|
|
+ LightInfo light = blendLight(vertex_pos);
|
|
|
+ return encode_light(light.getPair(), f->light_source);
|
|
|
}
|
|
|
|
|
|
video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos,
|
|
|
const v3f &vertex_normal)
|
|
|
{
|
|
|
- video::SColor color = blendLightColor(vertex_pos);
|
|
|
+ LightInfo light = blendLight(vertex_pos);
|
|
|
+ video::SColor color = encode_light(light.getPair(MYMAX(0.0f, vertex_normal.Y)), f->light_source);
|
|
|
if (!f->light_source)
|
|
|
applyFacesShading(color, vertex_normal);
|
|
|
return color;
|
|
@@ -365,7 +383,7 @@ void MapblockMeshGenerator::drawAutoLightedCuboid(aabb3f box, const f32 *txc,
|
|
|
tile_count = 1;
|
|
|
}
|
|
|
if (data->m_smooth_lighting) {
|
|
|
- LightPair lights[8];
|
|
|
+ LightInfo lights[8];
|
|
|
for (int j = 0; j < 8; ++j) {
|
|
|
v3f d;
|
|
|
d.X = (j & 4) ? dx2 : dx1;
|
|
@@ -403,7 +421,7 @@ void MapblockMeshGenerator::prepareLiquidNodeDrawing()
|
|
|
// If this liquid emits light and doesn't contain light, draw
|
|
|
// it at what it emits, for an increased effect
|
|
|
u8 e = decode_light(f->light_source);
|
|
|
- light = LightPair(std::max(e, light.lightA), std::max(e, light.lightB));
|
|
|
+ light = LightPair(std::max(e, light.lightDay), std::max(e, light.lightNight));
|
|
|
} else if (nodedef->get(ntop).param_type == CPT_LIGHT) {
|
|
|
// Otherwise, use the light of the node on top if possible
|
|
|
light = LightPair(getInteriorLight(ntop, 0, nodedef));
|