diff options
Diffstat (limited to 'src/content_mapblock.cpp')
-rw-r--r-- | src/content_mapblock.cpp | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 69982c335..348748c91 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -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)); |