diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index d638f42c8..45e763d4e 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -9,8 +9,7 @@ uniform float fogShadingParameter; uniform highp vec3 cameraOffset; uniform float animationTimer; -uniform float ambientLight; -uniform vec3 ambientColor; +uniform vec3 ambientLight; #ifdef ENABLE_DYNAMIC_SHADOWS // shadow texture uniform sampler2D ShadowMapSampler; @@ -378,10 +377,8 @@ void main(void) #endif color = base.rgb; - vec4 col = vec4(color.rgb * varColor.rgb, 1.0); - if (!(ambientColor.r == ambientColor.g && ambientColor.r == ambientColor.b)) - col.rgb += ambientLight * ambientColor.rgb; + vec4 col = vec4(color.rgb * (varColor.rgb + ambientLight), 1.0); #ifdef ENABLE_DYNAMIC_SHADOWS if (f_shadow_strength > 0.0) { diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 3a1163203..c426b106f 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -9,8 +9,7 @@ uniform float fogShadingParameter; uniform highp vec3 cameraOffset; uniform float animationTimer; -uniform float ambientLight; -uniform vec3 ambientColor; +uniform vec3 ambientLight; #ifdef ENABLE_DYNAMIC_SHADOWS // shadow texture uniform sampler2D ShadowMapSampler; @@ -381,9 +380,8 @@ void main(void) #endif color = base.rgb; - vec4 col = vec4(color.rgb * varColor.rgb, 1.0); - if (!(ambientColor.r == ambientColor.g && ambientColor.r == ambientColor.b)) - col.rgb += ambientLight * ambientColor.rgb; + + vec4 col = vec4(color.rgb * (varColor.rgb + ambientLight), 1.0); col.rgb *= vIDiff; #ifdef ENABLE_DYNAMIC_SHADOWS diff --git a/doc/lua_api.md b/doc/lua_api.md index 123e650b3..0d82c7ccf 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8397,7 +8397,7 @@ child will follow movement and rotation of that bone. * `light_definition` is a table with the following optional fields: * `ambient_light` is a table controlling amount and color of ambient light (global lighting) * `luminance` sets the amount of ambient light in range (0... LIGHT_SUN) like `light_source` has (default: `0`) - * `color` sets the color of ambient light (ColorSpec) (default: `{a = 0, r = 0, g = 0, b = 0}`) + * `color` sets the color of ambient light (ColorSpec) (default: `{a = 255, r = 255, g = 255, b = 255}`) * `saturation` sets the saturation (vividness; default: `1.0`). * values > 1 increase the saturation * values in [0,1] decrease the saturation diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 412cd57c1..4dc768a98 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -248,6 +248,16 @@ void ClientEnvironment::step(float dtime) if (m_client->modsLoaded()) m_script->environment_step(dtime); + // Update the ambient light + Lighting &lighting = getLocalPlayer()->getLighting(); + + auto new_ambient_light = encodeAmbientLight(lighting.ambient_light.luminance, lighting.ambient_light.color); + + if (new_ambient_light != m_ambient_light) { + m_ambient_light = new_ambient_light; + getClientMap().forceUpdateMapblocksMeshes(); + } + // Update lighting on local player (used for wield item) u32 day_night_ratio = getDayNightRatio(); { @@ -261,9 +271,8 @@ void ClientEnvironment::step(float dtime) node_at_lplayer = m_map->getNode(p); u16 light = getInteriorLight(node_at_lplayer, 0, m_client->ndef()); - lplayer->light_color = encode_light(light, 0, - lplayer->getLighting().ambient_light.luminance); // this transfers light.alpha - final_color_blend(&lplayer->light_color, light, day_night_ratio); + lplayer->light_color = encode_light(light, 0); // this transfers light.alpha + final_color_blend(&lplayer->light_color, light, day_night_ratio, m_ambient_light); } /* diff --git a/src/client/clientenvironment.h b/src/client/clientenvironment.h index bdb8b9726..aed9bec38 100644 --- a/src/client/clientenvironment.h +++ b/src/client/clientenvironment.h @@ -150,6 +150,8 @@ class ClientEnvironment : public Environment u64 getFrameTime() const { return m_frame_time; } u64 getFrameTimeDelta() const { return m_frame_dtime; } + const video::SColor& getAmbientLight() const { return m_ambient_light; } + private: ClientMap *m_map; LocalPlayer *m_local_player = nullptr; @@ -165,4 +167,5 @@ class ClientEnvironment : public Environment u64 m_frame_time = 0; u64 m_frame_dtime = 0; u64 m_frame_time_pause_accumulator = 0; + video::SColor m_ambient_light {0, 0, 0, 0}; }; diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 848e4ace9..5c10d5f47 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -727,6 +727,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) const float animation_time = m_client->getAnimationTime(); const int crack = m_client->getCrackLevel(); const u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); + const video::SColor &ambient_light = m_client->getEnv().getAmbientLight(); const v3f camera_position = m_camera_position; @@ -788,7 +789,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) mesh_animate_count < (m_control.range_all ? 200 : 50)) { bool animated = block_mesh->animate(faraway, animation_time, - crack, daynight_ratio); + crack, daynight_ratio, ambient_light); if (animated) mesh_animate_count++; } else { diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 848ac1c6d..d9ff6eede 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -907,10 +907,10 @@ void GenericCAO::updateLight(u32 day_night_ratio) // Encode light into color, adding a small boost // based on the entity glow. if (m_enable_shaders) - light = encode_light(light_at_pos, m_prop.glow, - m_env->getLocalPlayer()->getLighting().ambient_light.luminance); + light = encode_light(light_at_pos, m_prop.glow); else - final_color_blend(&light, light_at_pos, day_night_ratio); + final_color_blend(&light, light_at_pos, day_night_ratio, + m_client->getEnv().getAmbientLight()); if (light != m_last_light) { m_last_light = light; diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 054ef4628..c351c4b80 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -80,7 +80,6 @@ MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector nodedef(data->nodedef), meshmanip(mm), blockpos_nodes(data->m_blockpos * MAP_BLOCKSIZE), - player(data->m_client->getEnv().getLocalPlayer()), enable_mesh_cache(g_settings->getBool("enable_mesh_cache") && !data->m_smooth_lighting) // Mesh cache is not supported with smooth lighting { @@ -93,8 +92,7 @@ void MapblockMeshGenerator::useTile(int index, u8 set_flags, u8 reset_flags, boo else getTile(index, &cur_node.tile); if (!data->m_smooth_lighting) - cur_node.color = encode_light(cur_node.light, cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + cur_node.color = encode_light(cur_node.light, cur_node.f->light_source); for (auto &layer : cur_node.tile.layers) { layer.material_flags |= set_flags; @@ -303,8 +301,7 @@ LightInfo MapblockMeshGenerator::blendLight(const v3f &vertex_pos) video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos) { LightInfo light = blendLight(vertex_pos); - return encode_light(light.getPair(), cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + return encode_light(light.getPair(), cur_node.f->light_source); } video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos, @@ -312,8 +309,7 @@ video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos, { LightInfo light = blendLight(vertex_pos); video::SColor color = encode_light(light.getPair(MYMAX(0.0f, vertex_normal.Y)), - cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + cur_node.f->light_source); if (!cur_node.f->light_source) applyFacesShading(color, vertex_normal); return color; @@ -388,8 +384,7 @@ void MapblockMeshGenerator::drawAutoLightedCuboid(aabb3f box, const f32 *txc, for (int j = 0; j < 4; j++) { video::S3DVertex &vertex = vertices[j]; final_lights[j] = lights[light_indices[face][j]].getPair(MYMAX(0.0f, vertex.Normal.Y)); - vertex.Color = encode_light(final_lights[j], cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + vertex.Color = encode_light(final_lights[j], cur_node.f->light_source); if (!cur_node.f->light_source) applyFacesShading(vertex.Color, vertex.Normal); } @@ -399,8 +394,7 @@ void MapblockMeshGenerator::drawAutoLightedCuboid(aabb3f box, const f32 *txc, }); } else { drawCuboid(box, tiles, tile_count, txc, mask, [&] (int face, video::S3DVertex vertices[4]) { - video::SColor color = encode_light(cur_node.light, cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + video::SColor color = encode_light(cur_node.light, cur_node.f->light_source); if (!cur_node.f->light_source) applyFacesShading(color, vertices[0].Normal); for (int j = 0; j < 4; j++) { @@ -480,8 +474,7 @@ void MapblockMeshGenerator::drawSolidNode() auto final_lights = lights[face]; for (int j = 0; j < 4; j++) { video::S3DVertex &vertex = vertices[j]; - vertex.Color = encode_light(final_lights[j], cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + vertex.Color = encode_light(final_lights[j], cur_node.f->light_source); if (!cur_node.f->light_source) applyFacesShading(vertex.Color, vertex.Normal); } @@ -491,8 +484,7 @@ void MapblockMeshGenerator::drawSolidNode() }); } else { drawCuboid(box, tiles, 6, texture_coord_buf, mask, [&] (int face, video::S3DVertex vertices[4]) { - video::SColor color = encode_light(lights[face], cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + video::SColor color = encode_light(lights[face], cur_node.f->light_source); if (!cur_node.f->light_source) applyFacesShading(color, vertices[0].Normal); for (int j = 0; j < 4; j++) { @@ -574,10 +566,8 @@ void MapblockMeshGenerator::prepareLiquidNodeDrawing() cur_node.light = LightPair(getInteriorLight(ntop, 0, nodedef)); } - cur_liquid.color_top = encode_light(cur_node.light, cur_node.f->light_source, - player->getLighting().ambient_light.luminance); - cur_node.color = encode_light(cur_node.light, cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + cur_liquid.color_top = encode_light(cur_node.light, cur_node.f->light_source); + cur_node.color = encode_light(cur_node.light, cur_node.f->light_source); } void MapblockMeshGenerator::getLiquidNeighborhood() @@ -869,8 +859,7 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode() getTile(g_6dirs[face], &tiles[face]); if (!data->m_smooth_lighting) - cur_node.color = encode_light(cur_node.light, cur_node.f->light_source, - player->getLighting().ambient_light.luminance); + cur_node.color = encode_light(cur_node.light, cur_node.f->light_source); TileSpec glass_tiles[6]; for (auto &glass_tile : glass_tiles) diff --git a/src/client/content_mapblock.h b/src/client/content_mapblock.h index 686e68ea7..57c8b439e 100644 --- a/src/client/content_mapblock.h +++ b/src/client/content_mapblock.h @@ -76,7 +76,6 @@ class MapblockMeshGenerator const v3s16 blockpos_nodes; - LocalPlayer *player; // options const bool enable_mesh_cache; diff --git a/src/client/game.cpp b/src/client/game.cpp index 862234bf9..b4c385104 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -383,7 +383,6 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter m_animation_timer_delta_pixel{"animationTimerDelta"}; CachedPixelShaderSetting m_day_light{"dayLight"}; CachedPixelShaderSetting m_ambient_light{"ambientLight"}; - CachedPixelShaderSetting m_ambient_color{"ambientColor"}; CachedPixelShaderSetting m_minimap_yaw{"yawVec"}; CachedPixelShaderSetting m_camera_offset_pixel{"cameraOffset"}; CachedVertexShaderSetting m_camera_offset_vertex{"cameraOffset"}; @@ -475,20 +474,15 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter get_sunlight_color(&sunlight, daynight_ratio); m_day_light.set(sunlight, services); - auto lighting = m_client->getEnv().getLocalPlayer()->getLighting(); + auto ambient_light = m_client->getEnv().getAmbientLight(); - float ambient_light = lighting.ambient_light.luminance / 16.f; - - m_ambient_light.set(&ambient_light, services); - - video::SColor ambient_color = lighting.ambient_light.color; - - float ac_f[3] = { - ambient_color.getRed()/255.f, - ambient_color.getGreen()/255.f, - ambient_color.getBlue()/255.f + float ambient_light_f[3] = { + ambient_light.getRed() / 255.f, + ambient_light.getGreen() / 255.f, + ambient_light.getBlue() / 255.f }; - m_ambient_color.set(ac_f, services); + + m_ambient_light.set(ambient_light_f, services); u32 animation_timer = m_client->getEnv().getFrameTime() % 1000000; float animation_timer_f = (float)animation_timer / 100000.f; @@ -3542,7 +3536,7 @@ PointedThing Game::updatePointedThing( u32 daynight_ratio = client->getEnv().getDayNightRatio(); video::SColor c; - final_color_blend(&c, light_level, daynight_ratio); + final_color_blend(&c, light_level, daynight_ratio, client->getEnv().getAmbientLight()); // Modify final color a bit with time u32 timer = client->getEnv().getFrameTime() % 5000; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 17f31402a..0bf4955e5 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -290,16 +290,17 @@ void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){ } void final_color_blend(video::SColor *result, - u16 light, u32 daynight_ratio) + u16 light, u32 daynight_ratio, const video::SColor &ambientLight) { video::SColorf dayLight; get_sunlight_color(&dayLight, daynight_ratio); final_color_blend(result, - encode_light(light, 0, 0), dayLight); + encode_light(light, 0), dayLight, ambientLight); } void final_color_blend(video::SColor *result, - const video::SColor &data, const video::SColorf &dayLight) + const video::SColor &data, const video::SColorf &dayLight, + const video::SColor &ambientLight) { static const video::SColorf artificialColor(1.04f, 1.04f, 1.04f); @@ -320,9 +321,14 @@ void final_color_blend(video::SColor *result, b += emphase_blue_when_dark[irr::core::clamp((s32) ((r + g + b) / 3 * 255), 0, 255) / 8] / 255.0f; - result->setRed(core::clamp((s32) (r * 255.0f), 0, 255)); - result->setGreen(core::clamp((s32) (g * 255.0f), 0, 255)); - result->setBlue(core::clamp((s32) (b * 255.0f), 0, 255)); + // Add ambient light + r += ambientLight.getRed() / 255.f; + g += ambientLight.getGreen() / 255.f; + b += ambientLight.getBlue() / 255.f; + + result->setRed(core::clamp((s32)(r * 255.f), 0, 255)); + result->setGreen(core::clamp((s32)(g * 255.f), 0, 255)); + result->setBlue(core::clamp((s32)(b * 255.f), 0, 255)); } /* @@ -719,13 +725,15 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs video::SColorf sunlight; get_sunlight_color(&sunlight, 0); + auto ambientlight = client->getEnv().getAmbientLight(); + std::map colors; const u32 vertex_count = p.vertices.size(); for (u32 j = 0; j < vertex_count; j++) { video::SColor *vc = &p.vertices[j].Color; video::SColor copy = *vc; if (vc->getAlpha() == 0) // No sunlight - no need to animate - final_color_blend(vc, copy, sunlight); // Finalize color + final_color_blend(vc, copy, sunlight, ambientlight); // Finalize color else // Record color to animate colors[j] = copy; @@ -737,6 +745,17 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs m_daynight_diffs[{layer, i}] = std::move(colors); } + // Apply the ambient light to all vertices + /*auto ambient_light = data->m_client->getEnv().getAmbientLight(); + + for (u32 i = 0; i < p.vertices.size(); i++) { + video::SColor &vert_c = p.vertices[i].Color; + + vert_c.setRed(vert_c.getRed() + ambient_light.getRed()); + vert_c.setGreen(vert_c.getGreen() + ambient_light.getGreen()); + vert_c.setBlue(vert_c.getBlue() + ambient_light.getBlue()); + }*/ + // Create material video::SMaterial material; material.Lighting = false; @@ -808,7 +827,7 @@ MapBlockMesh::~MapBlockMesh() } bool MapBlockMesh::animate(bool faraway, float time, int crack, - u32 daynight_ratio) + u32 daynight_ratio, const video::SColor &ambient_light) { if (!m_has_animation) { m_animation_force_timer = 100000; @@ -880,7 +899,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices(); for (const auto &j : daynight_diff.second) final_color_blend(&(vertices[j.first].Color), j.second, - day_color); + day_color, ambient_light); } m_last_daynight_ratio = daynight_ratio; } @@ -949,7 +968,7 @@ void MapBlockMesh::consolidateTransparentBuffers() } } -video::SColor encode_light(u16 light, u8 emissive_light, u8 ambient_light) +video::SColor encode_light(u16 light, u8 emissive_light) { // Get components u32 day = (light & 0xff); @@ -958,15 +977,6 @@ video::SColor encode_light(u16 light, u8 emissive_light, u8 ambient_light) // Add emissive light night += emissive_light * 2.5f; - f32 ratio = ambient_light/16.f; - - u32 ambient_light_32 = ratio * 255; - - if (day < ambient_light_32) - day = ambient_light_32; - if (night < ambient_light_32) - night = ambient_light_32; - if (night > 255) night = 255; // Since we don't know if the day light is sunlight or @@ -988,6 +998,19 @@ video::SColor encode_light(u16 light, u8 emissive_light, u8 ambient_light) return video::SColor(r, b, b, b); } +video::SColor encodeAmbientLight(u8 light, video::SColor color) +{ + video::SColor res_color(0, 0, 0, 0); + + float light_f = light / 15.f; + + res_color.setRed(core::round32(light_f * color.getRed())); + res_color.setGreen(core::round32(light_f * color.getGreen())); + res_color.setBlue(core::round32(light_f * color.getBlue())); + + return res_color; +} + u8 get_solid_sides(MeshMakeData *data) { std::unordered_map results; diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index ad22628de..34b99caf2 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -190,7 +190,7 @@ class MapBlockMesh // daynight_ratio: 0 .. 1000 // crack: -1 .. CRACK_ANIMATION_LENGTH-1 (-1 for off) // Returns true if anything has been changed. - bool animate(bool faraway, float time, int crack, u32 daynight_ratio); + bool animate(bool faraway, float time, int crack, u32 daynight_ratio, const video::SColor &ambient_light); scene::IMesh *getMesh() { @@ -295,10 +295,10 @@ class MapBlockMesh * the last 8 bits are night light * \param emissive_light amount of light the surface emits, * from 0 to LIGHT_SUN. - * \param ambient_light amount of ambient light that the surface should have - * from 0 to LIGHT_SUN. */ -video::SColor encode_light(u16 light, u8 emissive_light, u8 ambient_light=0); +video::SColor encode_light(u16 light, u8 emissive_light); + +video::SColor encodeAmbientLight(u8 light, video::SColor color); // Compute light at node u16 getInteriorLight(MapNode n, s32 increment, const NodeDefManager *ndef); @@ -320,7 +320,7 @@ void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio); * night light */ void final_color_blend(video::SColor *result, - u16 light, u32 daynight_ratio); + u16 light, u32 daynight_ratio, const video::SColor &ambientLight); /*! * Gives the final SColor shown on screen. @@ -330,7 +330,8 @@ void final_color_blend(video::SColor *result, * \param dayLight color of the sunlight */ void final_color_blend(video::SColor *result, - const video::SColor &data, const video::SColorf &dayLight); + const video::SColor &data, const video::SColorf &dayLight, + const video::SColor &ambientLight); // Retrieves the TileSpec of a face of a node // Adds MATERIAL_FLAG_CRACK if the node is cracked diff --git a/src/lighting.h b/src/lighting.h index ecf0f5974..98802bb43 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -52,7 +52,8 @@ struct AutoExposure */ struct AmbientLight { - AmbientLight() : luminance(0), color(255, 255, 255, 255) {} + AmbientLight() : luminance(0), color(255, 255, 255, 255) + {} /// @brief Minimal threshold of luminance of ambience. Can be from 0 - 14. u8 luminance;