From 9e3a11534f47bbbaa6fca53fa71550779028e965 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 23 Jan 2024 22:33:33 +0100 Subject: [PATCH] Allow fog color to be overriden properly (#14296) --- .../shaders/nodes_shader/opengl_fragment.glsl | 4 +- .../object_shader/opengl_fragment.glsl | 4 +- doc/lua_api.md | 6 +- src/client/clouds.cpp | 6 +- src/client/game.cpp | 41 +++++------- src/client/renderingengine.h | 3 + src/client/sky.h | 17 +++-- src/network/clientpackethandler.cpp | 65 ++++++++++--------- src/script/lua_api/l_object.cpp | 16 +++-- src/server.cpp | 15 ++--- src/skyparams.h | 3 +- 11 files changed, 96 insertions(+), 84 deletions(-) diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index 8990e5bc0..0e75efedf 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -1,7 +1,7 @@ uniform sampler2D baseTexture; uniform vec3 dayLight; -uniform vec4 skyBgColor; +uniform vec4 fogColor; uniform float fogDistance; uniform float fogShadingParameter; uniform vec3 eyePosition; @@ -448,7 +448,7 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - col = mix(skyBgColor, col, clarity); + col = mix(fogColor, col, clarity); col = vec4(col.rgb, base.a); gl_FragData[0] = col; diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 80c18a181..61e00485b 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -1,7 +1,7 @@ uniform sampler2D baseTexture; uniform vec3 dayLight; -uniform vec4 skyBgColor; +uniform vec4 fogColor; uniform float fogDistance; uniform float fogShadingParameter; uniform vec3 eyePosition; @@ -449,7 +449,7 @@ void main(void) // Note: clarity = (1 - fogginess) float clarity = clamp(fogShadingParameter - fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0); - col = mix(skyBgColor, col, clarity); + col = mix(fogColor, col, clarity); col = vec4(col.rgb, base.a); gl_FragData[0] = col; diff --git a/doc/lua_api.md b/doc/lua_api.md index de67f7656..d5a25ed9f 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -7892,8 +7892,7 @@ child will follow movement and rotation of that bone. whether `set_sky` accepts this format. Check the legacy format otherwise. * Passing no arguments resets the sky to its default values. * `sky_parameters` is a table with the following optional fields: - * `base_color`: ColorSpec, changes fog in "skybox" and "plain". - (default: `#ffffff`) + * `base_color`: ColorSpec, meaning depends on `type` (default: `#ffffff`) * `body_orbit_tilt`: Float, rotation angle of sun/moon orbit in degrees. By default, orbit is controlled by a client-side setting, and this field is not set. After a value is assigned, it can only be changed to another float value. @@ -7950,6 +7949,9 @@ child will follow movement and rotation of that bone. Any value between [0.0, 0.99] set the fog_start as a fraction of the viewing_range. Any value < 0, resets the behavior to being client-controlled. (default: -1) + * `fog_color`: ColorSpec, override the color of the fog. + Unlike `base_color` above this will apply regardless of the skybox type. + (default: `"#00000000"`, which means no override) * `set_sky(base_color, type, {texture names}, clouds)` * Deprecated. Use `set_sky(sky_parameters)` * `base_color`: ColorSpec, defaults to white diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index fe243c715..f07c2bcaf 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -165,9 +165,11 @@ void Clouds::render() driver->getFog(fog_color, fog_type, fog_start, fog_end, fog_density, fog_pixelfog, fog_rangefog); - // Set our own fog - driver->setFog(fog_color, fog_type, cloud_full_radius * 0.5, + // Set our own fog, unless it was already disabled + if (fog_start < FOG_RANGE_ALL) { + driver->setFog(fog_color, fog_type, cloud_full_radius * 0.5, cloud_full_radius*1.2, fog_density, fog_pixelfog, fog_rangefog); + } // Read noise diff --git a/src/client/game.cpp b/src/client/game.cpp index 54bff7557..d84c493a7 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -374,7 +374,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter bool *m_force_fog_off; f32 *m_fog_range; bool m_fog_enabled; - CachedPixelShaderSetting m_sky_bg_color{"skyBgColor"}; + CachedPixelShaderSetting m_fog_color{"fogColor"}; CachedPixelShaderSetting m_fog_distance{"fogDistance"}; CachedPixelShaderSetting m_fog_shading_parameter{"fogShadingParameter"}; @@ -475,20 +475,13 @@ public: void onSetConstants(video::IMaterialRendererServices *services) override { - // Background color - video::SColor bgcolor = m_sky->getBgColor(); - video::SColorf bgcolorf(bgcolor); - float bgcolorfa[4] = { - bgcolorf.r, - bgcolorf.g, - bgcolorf.b, - bgcolorf.a, + video::SColorf fogcolorf(m_sky->getFogColor()); + float fogcolorfa[4] = { + fogcolorf.r, fogcolorf.g, fogcolorf.b, fogcolorf.a, }; - m_sky_bg_color.set(bgcolorfa, services); + m_fog_color.set(fogcolorfa, services); - // Fog distance float fog_distance = 10000 * BS; - if (m_fog_enabled && !*m_force_fog_off) fog_distance = *m_fog_range; @@ -983,7 +976,6 @@ private: bool *kill; std::string *error_message; bool *reconnect_requested; - scene::ISceneNode *skybox; PausedNodesList paused_animated_nodes; bool simple_singleplayer_mode; @@ -1522,7 +1514,6 @@ bool Game::createClient(const GameStartData &start_data) */ sky = new Sky(-1, m_rendering_engine, texture_src, shader_src); scsf->setSky(sky); - skybox = NULL; // This is used/set later on in the main run loop /* Pre-calculated values */ @@ -3045,10 +3036,6 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) // Whether clouds are visible in front of a custom skybox. sky->setCloudsEnabled(event->set_sky->clouds); - if (skybox) { - skybox->remove(); - skybox = NULL; - } // Clear the old textures out in case we switch rendering type. sky->clearSkyboxTextures(); // Handle according to type @@ -3108,6 +3095,8 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) else sky->setFogStart(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); + sky->setFogColor(event->set_sky->fog_color); + delete event->set_sky; } @@ -4055,7 +4044,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, draw_control->wanted_range = MYMIN(draw_control->wanted_range, sky->getFogDistance()); } if (draw_control->range_all && sky->getFogDistance() < 0) { - runData.fog_range = 100000 * BS; + runData.fog_range = FOG_RANGE_ALL; } else { runData.fog_range = draw_control->wanted_range * BS; } @@ -4297,7 +4286,7 @@ void Game::updateShadows() void Game::drawScene(ProfilerGraph *graph, RunStats *stats) { - const video::SColor bg_color = this->sky->getBgColor(); + const video::SColor fog_color = this->sky->getFogColor(); const video::SColor sky_color = this->sky->getSkyColor(); /* @@ -4305,21 +4294,21 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats) */ if (this->m_cache_enable_fog) { this->driver->setFog( - bg_color, + fog_color, video::EFT_FOG_LINEAR, this->runData.fog_range * this->sky->getFogStart(), this->runData.fog_range * 1.0f, - 0.01f, + 0.f, // unused false, // pixel fog true // range fog ); } else { this->driver->setFog( - bg_color, + fog_color, video::EFT_FOG_LINEAR, - 100000 * BS, - 110000 * BS, - 0.01f, + FOG_RANGE_ALL, + FOG_RANGE_ALL + 100 * BS, + 0.f, // unused false, // pixel fog false // range fog ); diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 801649ad4..06c3157d5 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -43,6 +43,9 @@ class Minimap; class RenderingCore; +// Instead of a mechanism to disable fog we just set it to be really far away +#define FOG_RANGE_ALL (100000 * BS) + class RenderingEngine { public: diff --git a/src/client/sky.h b/src/client/sky.h index b76a5311b..c9064c038 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -54,12 +54,12 @@ public: float getBrightness() { return m_brightness; } - const video::SColor &getBgColor() const + video::SColor getBgColor() const { return m_visible ? m_bgcolor : m_fallback_bg_color; } - const video::SColor &getSkyColor() const + video::SColor getSkyColor() const { return m_visible ? m_skycolor : m_fallback_bg_color; } @@ -90,6 +90,7 @@ public: const video::SColorf &getCloudColor() const { return m_cloudcolor_f; } void setVisible(bool visible) { m_visible = visible; } + // Set only from set_sky API void setCloudsEnabled(bool clouds_enabled) { m_clouds_enabled = clouds_enabled; } void setFallbackBgColor(video::SColor fallback_bg_color) @@ -111,17 +112,23 @@ public: const std::string &use_sun_tint); void setInClouds(bool clouds) { m_in_clouds = clouds; } void clearSkyboxTextures() { m_sky_params.textures.clear(); } - void addTextureToSkybox(const std::string &texture, int material_id, + void addTextureToSkybox(const std::string &texture, int material_id, ITextureSource *tsrc); const video::SColorf &getCurrentStarColor() const { return m_star_color; } + + // Note: the Sky class doesn't use these values. It just stores them. void setFogDistance(s16 fog_distance) { m_sky_params.fog_distance = fog_distance; } s16 getFogDistance() const { return m_sky_params.fog_distance; } void setFogStart(float fog_start) { m_sky_params.fog_start = fog_start; } float getFogStart() const { return m_sky_params.fog_start; } - void setVolumetricLightStrength(float volumetric_light_strength) { m_sky_params.volumetric_light_strength = volumetric_light_strength; } - float getVolumetricLightStrength() const { return m_sky_params.volumetric_light_strength; } + void setFogColor(video::SColor v) { m_sky_params.fog_color = v; } + video::SColor getFogColor() const { + if (m_sky_params.fog_color.getAlpha() > 0) + return m_sky_params.fog_color; + return getBgColor(); + } private: aabb3f m_box; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 89ee9c801..d28ff66ef 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1391,41 +1391,44 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) star_event->type = CE_SET_STARS; star_event->star_params = new StarParams(stars); m_client_event_queue.push(star_event); - } else { - SkyboxParams skybox; + return; + } + + SkyboxParams skybox; + + *pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >> + skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type; + + if (skybox.type == "skybox") { u16 texture_count; std::string texture; - - *pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >> - skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type; - - if (skybox.type == "skybox") { - *pkt >> texture_count; - for (int i = 0; i < texture_count; i++) { - *pkt >> texture; - skybox.textures.emplace_back(texture); - } + *pkt >> texture_count; + for (u16 i = 0; i < texture_count; i++) { + *pkt >> texture; + skybox.textures.emplace_back(texture); } - else if (skybox.type == "regular") { - *pkt >> skybox.sky_color.day_sky >> skybox.sky_color.day_horizon - >> skybox.sky_color.dawn_sky >> skybox.sky_color.dawn_horizon - >> skybox.sky_color.night_sky >> skybox.sky_color.night_horizon - >> skybox.sky_color.indoors; - } - - if (pkt->getRemainingBytes() >= 4) { - *pkt >> skybox.body_orbit_tilt; - } - - if (pkt->getRemainingBytes() >= 6) { - *pkt >> skybox.fog_distance >> skybox.fog_start; - } - - ClientEvent *event = new ClientEvent(); - event->type = CE_SET_SKY; - event->set_sky = new SkyboxParams(skybox); - m_client_event_queue.push(event); + } else if (skybox.type == "regular") { + auto &c = skybox.sky_color; + *pkt >> c.day_sky >> c.day_horizon >> c.dawn_sky >> c.dawn_horizon + >> c.night_sky >> c.night_horizon >> c.indoors; } + + if (pkt->getRemainingBytes() >= 4) { + *pkt >> skybox.body_orbit_tilt; + } + + if (pkt->getRemainingBytes() >= 6) { + *pkt >> skybox.fog_distance >> skybox.fog_start; + } + + if (pkt->getRemainingBytes() >= 4) { + *pkt >> skybox.fog_color; + } + + ClientEvent *event = new ClientEvent(); + event->type = CE_SET_SKY; + event->set_sky = new SkyboxParams(skybox); + m_client_event_queue.push(event); } void Client::handleCommand_HudSetSun(NetworkPacket *pkt) diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 3d89bc279..764cf87fe 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1995,15 +1995,21 @@ int ObjectRef::l_set_sky(lua_State *L) if (!lua_isnil(L, -1)) sky_params.fog_tint_type = luaL_checkstring(L, -1); lua_pop(L, 1); - - // pop "sky_color" table - lua_pop(L, 1); } + lua_pop(L, 1); + lua_getfield(L, 2, "fog"); if (lua_istable(L, -1)) { - sky_params.fog_distance = getintfield_default(L, -1, "fog_distance", sky_params.fog_distance); - sky_params.fog_start = getfloatfield_default(L, -1, "fog_start", sky_params.fog_start); + sky_params.fog_distance = getintfield_default(L, -1, + "fog_distance", sky_params.fog_distance); + sky_params.fog_start = getfloatfield_default(L, -1, + "fog_start", sky_params.fog_start); + + lua_getfield(L, -1, "fog_color"); + read_color(L, -1, &sky_params.fog_color); + lua_pop(L, 1); } + lua_pop(L, 1); } else { // Handle old set_sky calls, and log deprecated: log_deprecated(L, "Deprecated call to set_sky, please check lua_api.md"); diff --git a/src/server.cpp b/src/server.cpp index 4c0788e8d..c30753246 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1826,22 +1826,21 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) pkt << params.clouds; } else { // Handle current clients and future clients pkt << params.bgcolor << params.type - << params.clouds << params.fog_sun_tint - << params.fog_moon_tint << params.fog_tint_type; + << params.clouds << params.fog_sun_tint + << params.fog_moon_tint << params.fog_tint_type; if (params.type == "skybox") { pkt << (u16) params.textures.size(); for (const std::string &texture : params.textures) pkt << texture; } else if (params.type == "regular") { - pkt << params.sky_color.day_sky << params.sky_color.day_horizon - << params.sky_color.dawn_sky << params.sky_color.dawn_horizon - << params.sky_color.night_sky << params.sky_color.night_horizon - << params.sky_color.indoors; + auto &c = params.sky_color; + pkt << c.day_sky << c.day_horizon << c.dawn_sky << c.dawn_horizon + << c.night_sky << c.night_horizon << c.indoors; } - pkt << params.body_orbit_tilt; - pkt << params.fog_distance << params.fog_start; + pkt << params.body_orbit_tilt << params.fog_distance << params.fog_start + << params.fog_color; } Send(&pkt); diff --git a/src/skyparams.h b/src/skyparams.h index ff9a921ae..a4d0fadac 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -46,7 +46,7 @@ struct SkyboxParams float body_orbit_tilt { INVALID_SKYBOX_TILT }; s16 fog_distance { -1 }; float fog_start { -1.0f }; - float volumetric_light_strength { 0.0f }; + video::SColor fog_color; // override, only used if alpha > 0 }; struct SunParams @@ -102,6 +102,7 @@ public: sky.fog_sun_tint = video::SColor(255, 244, 125, 29); sky.fog_moon_tint = video::SColorf(0.5, 0.6, 0.8, 1).toSColor(); sky.fog_tint_type = "default"; + sky.fog_color = video::SColor(0); return sky; }