From 02d0c826fe43aea243bc79887b40cacb8ce14fce Mon Sep 17 00:00:00 2001 From: Andrey2470T Date: Sat, 3 Feb 2024 20:06:54 +0300 Subject: [PATCH] Ambient light and server control for that --- .../shaders/nodes_shader/opengl_fragment.glsl | 4 ++- .../object_shader/opengl_fragment.glsl | 4 ++- src/client/clientenvironment.cpp | 3 +- src/client/content_cao.cpp | 3 +- src/client/content_mapblock.cpp | 31 +++++++++++++------ src/client/content_mapblock.h | 2 ++ src/client/game.cpp | 10 ++++++ src/client/mapblock_mesh.cpp | 15 +++++++-- src/client/mapblock_mesh.h | 4 ++- src/lighting.h | 15 +++++++++ src/network/clientpackethandler.cpp | 3 ++ src/script/lua_api/l_object.cpp | 13 ++++++++ src/server.cpp | 2 ++ 13 files changed, 92 insertions(+), 17 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 46977b147..e1bbab09f 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -8,6 +8,8 @@ uniform float fogShadingParameter; // The cameraOffset is the current center of the visible world. uniform highp vec3 cameraOffset; uniform float animationTimer; + +uniform vec3 ambientColor; #ifdef ENABLE_DYNAMIC_SHADOWS // shadow texture uniform sampler2D ShadowMapSampler; @@ -375,7 +377,7 @@ void main(void) #endif color = base.rgb; - vec4 col = vec4(color.rgb * varColor.rgb, 1.0); + vec4 col = vec4(color.rgb * varColor.rgb * ambientColor.rgb, 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 2b8af3fa9..2beaeddd0 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -8,6 +8,8 @@ uniform float fogShadingParameter; // The cameraOffset is the current center of the visible world. uniform highp vec3 cameraOffset; uniform float animationTimer; + +uniform vec3 ambientColor; #ifdef ENABLE_DYNAMIC_SHADOWS // shadow texture uniform sampler2D ShadowMapSampler; @@ -378,7 +380,7 @@ void main(void) #endif color = base.rgb; - vec4 col = vec4(color.rgb * varColor.rgb, 1.0); + vec4 col = vec4(color.rgb * varColor.rgb * ambientColor.rgb, 1.0); col.rgb *= vIDiff; #ifdef ENABLE_DYNAMIC_SHADOWS diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 7e1676ffe..aa6ea157b 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -261,7 +261,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); // this transfers light.alpha + lplayer->light_color = encode_light(light, 0, + m_client->getEnv().getLocalPlayer()->getLighting().ambient_light.luminance); // this transfers light.alpha final_color_blend(&lplayer->light_color, light, day_night_ratio); } diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 0044cc16e..8644d50de 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -907,7 +907,8 @@ 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); + light = encode_light(light_at_pos, m_prop.glow, + m_client->getEnv().getLocalPlayer()->getLighting().ambient_light.luminance); else final_color_blend(&light, light_at_pos, day_night_ratio); diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index c351c4b80..054ef4628 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -80,6 +80,7 @@ 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 { @@ -92,7 +93,8 @@ 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); + cur_node.color = encode_light(cur_node.light, cur_node.f->light_source, + player->getLighting().ambient_light.luminance); for (auto &layer : cur_node.tile.layers) { layer.material_flags |= set_flags; @@ -301,7 +303,8 @@ 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); + return encode_light(light.getPair(), cur_node.f->light_source, + player->getLighting().ambient_light.luminance); } video::SColor MapblockMeshGenerator::blendLightColor(const v3f &vertex_pos, @@ -309,7 +312,8 @@ 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); + cur_node.f->light_source, + player->getLighting().ambient_light.luminance); if (!cur_node.f->light_source) applyFacesShading(color, vertex_normal); return color; @@ -384,7 +388,8 @@ 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); + vertex.Color = encode_light(final_lights[j], cur_node.f->light_source, + player->getLighting().ambient_light.luminance); if (!cur_node.f->light_source) applyFacesShading(vertex.Color, vertex.Normal); } @@ -394,7 +399,8 @@ 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); + video::SColor color = encode_light(cur_node.light, cur_node.f->light_source, + player->getLighting().ambient_light.luminance); if (!cur_node.f->light_source) applyFacesShading(color, vertices[0].Normal); for (int j = 0; j < 4; j++) { @@ -474,7 +480,8 @@ 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); + vertex.Color = encode_light(final_lights[j], cur_node.f->light_source, + player->getLighting().ambient_light.luminance); if (!cur_node.f->light_source) applyFacesShading(vertex.Color, vertex.Normal); } @@ -484,7 +491,8 @@ 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); + video::SColor color = encode_light(lights[face], cur_node.f->light_source, + player->getLighting().ambient_light.luminance); if (!cur_node.f->light_source) applyFacesShading(color, vertices[0].Normal); for (int j = 0; j < 4; j++) { @@ -566,8 +574,10 @@ 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); - cur_node.color = encode_light(cur_node.light, cur_node.f->light_source); + 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); } void MapblockMeshGenerator::getLiquidNeighborhood() @@ -859,7 +869,8 @@ 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); + cur_node.color = encode_light(cur_node.light, cur_node.f->light_source, + player->getLighting().ambient_light.luminance); 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 730330a03..686e68ea7 100644 --- a/src/client/content_mapblock.h +++ b/src/client/content_mapblock.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include +#include "client/localplayer.h" struct MeshMakeData; struct MeshCollector; @@ -75,6 +76,7 @@ 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 d35bf8e08..861136fb3 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -382,6 +382,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting m_animation_timer_delta_pixel{"animationTimerDelta"}; CachedPixelShaderSetting m_day_light{"dayLight"}; + CachedPixelShaderSetting m_ambient_color{"ambientColor"}; CachedPixelShaderSetting m_minimap_yaw{"yawVec"}; CachedPixelShaderSetting m_camera_offset_pixel{"cameraOffset"}; CachedVertexShaderSetting m_camera_offset_vertex{"cameraOffset"}; @@ -473,6 +474,15 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter get_sunlight_color(&sunlight, daynight_ratio); m_day_light.set(sunlight, services); + video::SColor ambient_color = m_client->getEnv().getLocalPlayer()->getLighting().ambient_light.color; + + float ac_f[3] = { + ambient_color.getRed()/255.f, + ambient_color.getGreen()/255.f, + ambient_color.getBlue()/255.f + }; + m_ambient_color.set(ac_f, services); + u32 animation_timer = m_client->getEnv().getFrameTime() % 1000000; float animation_timer_f = (float)animation_timer / 100000.f; m_animation_timer_vertex.set(&animation_timer_f, services); diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index f06dcfa58..17f31402a 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -295,7 +295,7 @@ void final_color_blend(video::SColor *result, video::SColorf dayLight; get_sunlight_color(&dayLight, daynight_ratio); final_color_blend(result, - encode_light(light, 0), dayLight); + encode_light(light, 0, 0), dayLight); } void final_color_blend(video::SColor *result, @@ -949,13 +949,24 @@ void MapBlockMesh::consolidateTransparentBuffers() } } -video::SColor encode_light(u16 light, u8 emissive_light) +video::SColor encode_light(u16 light, u8 emissive_light, u8 ambient_light) { // Get components u32 day = (light & 0xff); u32 night = (light >> 8); + // 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 diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 7cd368762..ad22628de 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -295,8 +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); +video::SColor encode_light(u16 light, u8 emissive_light, u8 ambient_light=0); // Compute light at node u16 getInteriorLight(MapNode n, s32 increment, const NodeDefManager *ndef); diff --git a/src/lighting.h b/src/lighting.h index 262a48b5d..ecf0f5974 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #pragma once +#include "irrlichttypes_bloated.h" /** @@ -46,11 +47,25 @@ struct AutoExposure AutoExposure(); }; +/* + * Parameters for adjusting ambient light affecting on colors of map nodes and entities + */ +struct AmbientLight +{ + AmbientLight() : luminance(0), color(255, 255, 255, 255) {} + /// @brief Minimal threshold of luminance of ambience. Can be from 0 - 14. + u8 luminance; + + /// @brief Color of ambient light. Default is white color. + video::SColor color; +}; + /** Describes ambient light settings for a player */ struct Lighting { AutoExposure exposure; + AmbientLight ambient_light; float shadow_intensity {0.0f}; float saturation {1.0f}; float volumetric_light_strength {0.0f}; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 90f2bed5b..92236ce04 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1805,6 +1805,9 @@ 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; if (pkt->getRemainingBytes() >= 24) { *pkt >> lighting.exposure.luminance_min >> lighting.exposure.luminance_max diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index bc5ddba5c..ada44cd81 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server/player_sao.h" #include "server/serverinventorymgr.h" #include "server/unit_sao.h" +#include "light.h" /* ObjectRef @@ -2534,6 +2535,18 @@ int ObjectRef::l_set_lighting(lua_State *L) } lua_pop(L, 1); // shadows + lua_getfield(L, 2, "ambient_light"); + if(lua_istable(L, -1)) { + getintfield(L, -1, "luminance", lighting.ambient_light.luminance); + lighting.ambient_light.luminance = rangelim(lighting.ambient_light.luminance, 0, LIGHT_SUN); + + lua_getfield(L, -1, "color"); + if (!lua_isnil(L, -1)) + read_color(L, -1, &lighting.ambient_light.color); + lua_pop(L, 1); + } + lua_pop(L, 1); // ambient light + getfloatfield(L, -1, "saturation", lighting.saturation); lua_getfield(L, 2, "exposure"); diff --git a/src/server.cpp b/src/server.cpp index 316f349b2..518dba666 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1885,6 +1885,8 @@ 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