diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 45e763d4e..b5a93e5e9 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -378,7 +378,7 @@ void main(void) color = base.rgb; - vec4 col = vec4(color.rgb * (varColor.rgb + ambientLight), 1.0); + vec4 col = vec4(color.rgb * min(varColor.rgb + ambientLight, 1.0), 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 c426b106f..f7a851b0e 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -381,7 +381,7 @@ void main(void) color = base.rgb; - vec4 col = vec4(color.rgb * (varColor.rgb + ambientLight), 1.0); + vec4 col = vec4(color.rgb * min(varColor.rgb + ambientLight, 1.0), 1.0); col.rgb *= vIDiff; #ifdef ENABLE_DYNAMIC_SHADOWS diff --git a/doc/lua_api.md b/doc/lua_api.md index 0d82c7ccf..18bffcbf8 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 = 255, r = 255, g = 255, b = 255}`) + * `color` sets the color of ambient light (ColorSpec) (default: `{a = 255, r = 255, g = 255, b = 255}`). Alpha is ignored. * `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 4dc768a98..2f942199e 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -249,13 +249,13 @@ void ClientEnvironment::step(float dtime) m_script->environment_step(dtime); // Update the ambient light - Lighting &lighting = getLocalPlayer()->getLighting(); + AmbientLight &ambient_light = getLocalPlayer()->getLighting().ambient_light; - auto new_ambient_light = encodeAmbientLight(lighting.ambient_light.luminance, lighting.ambient_light.color); + video::SColor new_ambient_light_clr = encodeAmbientLight(ambient_light.luminance, ambient_light.color); - if (new_ambient_light != m_ambient_light) { - m_ambient_light = new_ambient_light; - getClientMap().forceUpdateMapblocksMeshes(); + if (new_ambient_light_clr != m_ambient_light) { + getClientMap().forceUpdateLightColor(); + m_ambient_light = new_ambient_light_clr; } // Update lighting on local player (used for wield item) diff --git a/src/client/clientenvironment.h b/src/client/clientenvironment.h index aed9bec38..1927416a2 100644 --- a/src/client/clientenvironment.h +++ b/src/client/clientenvironment.h @@ -150,7 +150,7 @@ 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; } + video::SColor getAmbientLight() const { return m_ambient_light; } private: ClientMap *m_map; diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 5c10d5f47..8fc92d201 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -623,14 +623,6 @@ void ClientMap::updateDrawList() } } - // Force update meshes of all loaded mapblocks - if (m_update_mapblocks_meshes) { - m_update_mapblocks_meshes = false; - - for (auto &p : m_drawlist) - m_client->addUpdateMeshTask(p.first, false, true); - } - g_profiler->avg("MapBlocks occlusion culled [#]", blocks_occlusion_culled); g_profiler->avg("MapBlocks frustum culled [#]", blocks_frustum_culled); g_profiler->avg("MapBlocks drawn [#]", m_drawlist.size()); @@ -786,7 +778,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) // Pretty random but this should work somewhat nicely bool faraway = d >= BS * 50; if (block_mesh->isAnimationForced() || !faraway || - mesh_animate_count < (m_control.range_all ? 200 : 50)) { + mesh_animate_count < (m_control.range_all ? 200 : 50) || + m_force_update_light_color) { bool animated = block_mesh->animate(faraway, animation_time, crack, daynight_ratio, ambient_light); @@ -833,6 +826,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } } + m_force_update_light_color = false; + // Capture draw order for all solid meshes for (auto &map : grouped_buffers.maps) { for (auto &list : map) { diff --git a/src/client/clientmap.h b/src/client/clientmap.h index 91838df5f..bab8418e2 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -112,10 +112,10 @@ class ClientMap : public Map, public scene::ISceneNode f32 getWantedRange() const { return m_control.wanted_range; } f32 getCameraFov() const { return m_camera_fov; } - void forceUpdateMapblocksMeshes() { m_update_mapblocks_meshes = true; } - void onSettingChanged(const std::string &name); + void forceUpdateLightColor() { m_force_update_light_color = true; } + protected: // use drop() instead virtual ~ClientMap(); @@ -198,5 +198,5 @@ class ClientMap : public Map, public scene::ISceneNode bool m_loops_occlusion_culler; bool m_enable_raytraced_culling; - bool m_update_mapblocks_meshes; + bool m_force_update_light_color = false; }; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 0bf4955e5..8000026d0 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -290,7 +290,7 @@ void get_sunlight_color(video::SColorf *sunlight, u32 daynight_ratio){ } void final_color_blend(video::SColor *result, - u16 light, u32 daynight_ratio, const video::SColor &ambientLight) + u16 light, u32 daynight_ratio, video::SColor ambientLight) { video::SColorf dayLight; get_sunlight_color(&dayLight, daynight_ratio); @@ -827,7 +827,7 @@ MapBlockMesh::~MapBlockMesh() } bool MapBlockMesh::animate(bool faraway, float time, int crack, - u32 daynight_ratio, const video::SColor &ambient_light) + u32 daynight_ratio, video::SColor ambient_light) { if (!m_has_animation) { m_animation_force_timer = 100000; @@ -886,11 +886,11 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, } } + video::SColorf day_color; + get_sunlight_color(&day_color, daynight_ratio); + // Day-night transition if (!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio)) { - video::SColorf day_color; - get_sunlight_color(&day_color, daynight_ratio); - for (auto &daynight_diff : m_daynight_diffs) { auto *mesh = m_mesh[daynight_diff.first.first]; mesh->setDirty(scene::EBT_VERTEX); // force reload to VBO @@ -899,11 +899,24 @@ 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, ambient_light); + day_color, video::SColor(255, 0, 0, 0)); } m_last_daynight_ratio = daynight_ratio; } + // Ambient light + if (!m_enable_shaders) { + for (u32 i = 0; i < MAX_TILE_LAYERS; i++) + for (u32 j = 0; j < m_mesh[i]->getMeshBufferCount(); j++) { + scene::IMeshBuffer *buf = m_mesh[i]->getMeshBuffer(j); + video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices(); + + for (u32 k = 0; k < buf->getVertexCount(); k++) + final_color_blend(&(vertices[k].Color), vertices[k].Color, + day_color, ambient_light); + } + } + return true; } diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 34b99caf2..b86e48ac4 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, const video::SColor &ambient_light); + bool animate(bool faraway, float time, int crack, u32 daynight_ratio, video::SColor ambient_light); scene::IMesh *getMesh() { @@ -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, const video::SColor &ambientLight); + u16 light, u32 daynight_ratio, video::SColor ambientLight); /*! * Gives the final SColor shown on screen. diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 0b1b59541..70afaa281 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1806,12 +1806,6 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) *pkt >> lighting.shadow_intensity; if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.saturation; - if (pkt->getRemainingBytes() >= 1) { - *pkt >> lighting.ambient_light.luminance - >> lighting.ambient_light.color; - - getEnv().getClientMap().forceUpdateMapblocksMeshes(); - } if (pkt->getRemainingBytes() >= 24) { *pkt >> lighting.exposure.luminance_min >> lighting.exposure.luminance_max @@ -1822,4 +1816,8 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) } if (pkt->getRemainingBytes() >= 4) *pkt >> lighting.volumetric_light_strength; + if (pkt->getRemainingBytes() >= 1) { + *pkt >> lighting.ambient_light.luminance + >> lighting.ambient_light.color; + } } diff --git a/src/server.cpp b/src/server.cpp index 518dba666..ac6642d15 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1885,8 +1885,6 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) pkt << lighting.shadow_intensity; pkt << lighting.saturation; - pkt << lighting.ambient_light.luminance - << lighting.ambient_light.color; pkt << lighting.exposure.luminance_min << lighting.exposure.luminance_max @@ -1897,6 +1895,9 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting) pkt << lighting.volumetric_light_strength; + pkt << lighting.ambient_light.luminance + << lighting.ambient_light.color; + Send(&pkt); }