Browse Source

Allow fog color to be overriden properly (#14296)

sfan5 3 months ago
parent
commit
9e3a11534f

+ 2 - 2
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;

+ 2 - 2
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;

+ 4 - 2
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

+ 4 - 2
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
 

+ 15 - 26
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<float, 4> m_sky_bg_color{"skyBgColor"};
+	CachedPixelShaderSetting<float, 4> m_fog_color{"fogColor"};
 	CachedPixelShaderSetting<float> m_fog_distance{"fogDistance"};
 	CachedPixelShaderSetting<float>
 		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
 		);

+ 3 - 0
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:

+ 12 - 5
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;

+ 31 - 28
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;
-		u16 texture_count;
-		std::string texture;
+		return;
+	}
 
-		*pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >>
-			skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type;
+	SkyboxParams skybox;
 
-		if (skybox.type == "skybox") {
-			*pkt >> texture_count;
-			for (int 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;
-		}
+	*pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >>
+		skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type;
 
-		if (pkt->getRemainingBytes() >= 4) {
-			*pkt >> skybox.body_orbit_tilt;
+	if (skybox.type == "skybox") {
+		u16 texture_count;
+		std::string texture;
+		*pkt >> texture_count;
+		for (u16 i = 0; i < texture_count; i++) {
+			*pkt >> texture;
+			skybox.textures.emplace_back(texture);
 		}
+	} 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() >= 6) {
-			*pkt >> skybox.fog_distance >> skybox.fog_start;
-		}
+	if (pkt->getRemainingBytes() >= 4) {
+		*pkt >> skybox.body_orbit_tilt;
+	}
 
-		ClientEvent *event = new ClientEvent();
-		event->type = CE_SET_SKY;
-		event->set_sky = new SkyboxParams(skybox);
-		m_client_event_queue.push(event);
+	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)

+ 11 - 5
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");

+ 7 - 8
src/server.cpp

@@ -1826,22 +1826,21 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams &params)
 		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);

+ 2 - 1
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;
 	}