diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl index d1f95572b..9c115b8d1 100644 --- a/client/shaders/nodes_shader/opengl_fragment.glsl +++ b/client/shaders/nodes_shader/opengl_fragment.glsl @@ -3,6 +3,7 @@ uniform sampler2D baseTexture; uniform vec3 dayLight; uniform vec4 skyBgColor; uniform float fogDistance; +uniform float fogShadingParameter; uniform vec3 eyePosition; // The cameraOffset is the current center of the visible world. @@ -49,9 +50,6 @@ varying vec3 tsEyeVec; varying vec3 lightVec; varying vec3 tsLightVec; -const float fogStart = FOG_START; -const float fogShadingParameter = 1.0 / ( 1.0 - fogStart); - #ifdef ENABLE_DYNAMIC_SHADOWS // assuming near is always 1.0 diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl index 1aadf7004..80c18a181 100644 --- a/client/shaders/object_shader/opengl_fragment.glsl +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -3,6 +3,7 @@ uniform sampler2D baseTexture; uniform vec3 dayLight; uniform vec4 skyBgColor; uniform float fogDistance; +uniform float fogShadingParameter; uniform vec3 eyePosition; // The cameraOffset is the current center of the visible world. @@ -48,9 +49,6 @@ varying float nightRatio; varying float vIDiff; -const float fogStart = FOG_START; -const float fogShadingParameter = 1.0 / (1.0 - fogStart); - #ifdef ENABLE_DYNAMIC_SHADOWS // assuming near is always 1.0 diff --git a/doc/lua_api.md b/doc/lua_api.md index b2ae1e8d3..0ce144f84 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -7740,6 +7740,18 @@ child will follow movement and rotation of that bone. abides by, `"custom"` uses `sun_tint` and `moon_tint`, while `"default"` uses the classic Minetest sun and moon tinting. Will use tonemaps, if set to `"default"`. (default: `"default"`) + * `fog`: A table with following optional fields: + * `fog_distance`: integer, set an upper bound the client's viewing_range (inluding range_all). + By default, fog_distance is controlled by the client's viewing_range, and this field is not set. + Any value >= 0 sets the desired upper bound for the client's viewing_range and disables range_all. + Any value < 0, resets the behavior to being client-controlled. + (default: -1) + * `fog_start`: float, override the client's fog_start. + Fraction of the visible distance at which fog starts to be rendered. + By default, fog_start is controlled by the client's `fog_start` setting, and this field is not set. + 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) * `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/game.cpp b/src/client/game.cpp index 0ea712cca..c9bcaba86 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -372,6 +372,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter bool m_fog_enabled; CachedPixelShaderSetting m_sky_bg_color; CachedPixelShaderSetting m_fog_distance; + CachedPixelShaderSetting m_fog_shading_parameter; CachedVertexShaderSetting m_animation_timer_vertex; CachedPixelShaderSetting m_animation_timer_pixel; CachedVertexShaderSetting m_animation_timer_delta_vertex; @@ -431,6 +432,7 @@ public: m_fog_range(fog_range), m_sky_bg_color("skyBgColor"), m_fog_distance("fogDistance"), + m_fog_shading_parameter("fogShadingParameter"), m_animation_timer_vertex("animationTimer"), m_animation_timer_pixel("animationTimer"), m_animation_timer_delta_vertex("animationTimerDelta"), @@ -496,7 +498,10 @@ public: if (m_fog_enabled && !*m_force_fog_off) fog_distance = *m_fog_range; + float fog_shading_parameter = 1.0 / ( 1.0 - m_sky->getFogStart()); + m_fog_distance.set(&fog_distance, services); + m_fog_shading_parameter.set(&fog_shading_parameter, services); u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio(); video::SColorf sunlight; @@ -961,7 +966,6 @@ private: f32 m_cache_joystick_frustum_sensitivity; f32 m_repeat_place_time; f32 m_cache_cam_smoothing; - f32 m_cache_fog_start; bool m_invert_mouse; bool m_enable_hotbar_mouse_wheel; @@ -2490,6 +2494,9 @@ void Game::increaseViewRange() range_new = 4000; std::wstring msg = fwgettext("Viewing range is at maximum: %d", range_new); m_game_ui->showStatusText(msg); + } else if (sky->getFogDistance() >= 0 && range_new > sky->getFogDistance()) { + std::wstring msg = fwgettext("Viewing range changed to %d, but limited to %d set by server", range_new, sky->getFogDistance()); + m_game_ui->showStatusText(msg); } else { std::wstring msg = fwgettext("Viewing range changed to %d", range_new); m_game_ui->showStatusText(msg); @@ -2507,6 +2514,9 @@ void Game::decreaseViewRange() range_new = 20; std::wstring msg = fwgettext("Viewing range is at minimum: %d", range_new); m_game_ui->showStatusText(msg); + } else if (sky->getFogDistance() >= 0 && range_new > sky->getFogDistance()) { + std::wstring msg = fwgettext("Viewing range changed to %d, but limited to %d set by server", range_new, sky->getFogDistance()); + m_game_ui->showStatusText(msg); } else { std::wstring msg = fwgettext("Viewing range changed to %d", range_new); m_game_ui->showStatusText(msg); @@ -2518,10 +2528,15 @@ void Game::decreaseViewRange() void Game::toggleFullViewRange() { draw_control->range_all = !draw_control->range_all; - if (draw_control->range_all) - m_game_ui->showTranslatedStatusText("Enabled unlimited viewing range"); - else + if (draw_control->range_all) { + if (sky->getFogDistance() >= 0) { + m_game_ui->showTranslatedStatusText("The server has disabled unlimited viewing range"); + } else { + m_game_ui->showTranslatedStatusText("Enabled unlimited viewing range"); + } + } else { m_game_ui->showTranslatedStatusText("Disabled unlimited viewing range"); + } } @@ -2996,6 +3011,20 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) // Orbit Tilt: sky->setBodyOrbitTilt(event->set_sky->body_orbit_tilt); + // fog + // do not override a potentially smaller client setting. + sky->setFogDistance(event->set_sky->fog_distance); + + // if the fog distance is reset, switch back to the client's viewing_range + if (event->set_sky->fog_distance < 0) + draw_control->wanted_range = g_settings->getS16("viewing_range"); + + if (event->set_sky->fog_start >= 0) + sky->setFogStart(rangelim(event->set_sky->fog_start, 0.0f, 0.99f)); + else + sky->setFogStart(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); + + delete event->set_sky; } @@ -3915,7 +3944,10 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, Fog range */ - if (draw_control->range_all) { + if (sky->getFogDistance() >= 0) { + draw_control->wanted_range = MYMIN(draw_control->wanted_range, sky->getFogDistance()); + } + if (draw_control->range_all && sky->getFogDistance() < 0) { runData.fog_range = 100000 * BS; } else { runData.fog_range = draw_control->wanted_range * BS; @@ -4006,12 +4038,11 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, /* Fog */ - if (m_cache_enable_fog) { driver->setFog( sky->getBgColor(), video::EFT_FOG_LINEAR, - runData.fog_range * m_cache_fog_start, + runData.fog_range * sky->getFogStart(), runData.fog_range * 1.0, 0.01, false, // pixel fog @@ -4284,15 +4315,12 @@ void Game::readSettings() m_cache_enable_noclip = g_settings->getBool("noclip"); m_cache_enable_free_move = g_settings->getBool("free_move"); - m_cache_fog_start = g_settings->getFloat("fog_start"); - m_cache_cam_smoothing = 0; if (g_settings->getBool("cinematic")) m_cache_cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing"); else m_cache_cam_smoothing = 1 - g_settings->getFloat("camera_smoothing"); - m_cache_fog_start = rangelim(m_cache_fog_start, 0.0f, 0.99f); m_cache_cam_smoothing = rangelim(m_cache_cam_smoothing, 0.01f, 1.0f); m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0); diff --git a/src/client/shader.cpp b/src/client/shader.cpp index 1ef5056c6..746569223 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -752,8 +752,6 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, shaders_header << "#define ENABLE_WAVING_PLANTS " << g_settings->getBool("enable_waving_plants") << "\n"; shaders_header << "#define ENABLE_TONE_MAPPING " << g_settings->getBool("tone_mapping") << "\n"; - shaders_header << "#define FOG_START " << core::clamp(g_settings->getFloat("fog_start"), 0.0f, 0.99f) << "\n"; - if (g_settings->getBool("enable_dynamic_shadows")) { shaders_header << "#define ENABLE_DYNAMIC_SHADOWS 1\n"; if (g_settings->getBool("shadow_map_color")) diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 0cdec0ac9..af9ac19d6 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -98,6 +98,7 @@ Sky::Sky(s32 id, RenderingEngine *rendering_engine, ITextureSource *tsrc, IShade m_directional_colored_fog = g_settings->getBool("directional_colored_fog"); m_sky_params.body_orbit_tilt = g_settings->getFloat("shadow_sky_body_orbit_tilt", -60., 60.); + m_sky_params.fog_start = rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f); setStarCount(1000); } diff --git a/src/client/sky.h b/src/client/sky.h index 9102db4d4..a5b92ace2 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -114,6 +114,11 @@ public: void addTextureToSkybox(const std::string &texture, int material_id, ITextureSource *tsrc); const video::SColorf &getCurrentStarColor() const { return m_star_color; } + 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; } private: aabb3f m_box; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index bba9c198b..33d470e9f 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1395,9 +1395,13 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) >> skybox.sky_color.indoors; } - try { + if (pkt->getRemainingBytes() >= 4) { *pkt >> skybox.body_orbit_tilt; - } catch (PacketError &e) {} + } + + if (pkt->getRemainingBytes() >= 6) { + *pkt >> skybox.fog_distance >> skybox.fog_start; + } ClientEvent *event = new ClientEvent(); event->type = CE_SET_SKY; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 7bb467c2e..08140f3bc 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1803,6 +1803,11 @@ int ObjectRef::l_set_sky(lua_State *L) // pop "sky_color" table 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); + } } else { // Handle old set_sky calls, and log deprecated: log_deprecated(L, "Deprecated call to set_sky, please check lua_api.md"); @@ -1923,7 +1928,6 @@ int ObjectRef::l_get_sky(lua_State *L) lua_pushnumber(L, skybox_params.body_orbit_tilt); lua_setfield(L, -2, "body_orbit_tilt"); } - lua_newtable(L); s16 i = 1; for (const std::string &texture : skybox_params.textures) { @@ -1936,6 +1940,14 @@ int ObjectRef::l_get_sky(lua_State *L) push_sky_color(L, skybox_params); lua_setfield(L, -2, "sky_color"); + + lua_newtable(L); // fog + lua_pushinteger(L, skybox_params.fog_distance >= 0 ? skybox_params.fog_distance : -1); + lua_setfield(L, -2, "fog_distance"); + lua_pushnumber(L, skybox_params.fog_start >= 0 ? skybox_params.fog_start : -1.0f); + lua_setfield(L, -2, "fog_start"); + lua_setfield(L, -2, "fog"); + return 1; } diff --git a/src/server.cpp b/src/server.cpp index 7152aeae6..3380ac63c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1846,6 +1846,7 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) } pkt << params.body_orbit_tilt; + pkt << params.fog_distance << params.fog_start; } Send(&pkt); diff --git a/src/skyparams.h b/src/skyparams.h index 0adb3f038..554904bc0 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -44,6 +44,8 @@ struct SkyboxParams video::SColor fog_moon_tint; std::string fog_tint_type; float body_orbit_tilt { INVALID_SKYBOX_TILT }; + s16 fog_distance { -1 }; + float fog_start { -1.0f }; }; struct SunParams