2
0
Juan Linietsky 8 жил өмнө
parent
commit
840ac8c018

+ 61 - 0
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -944,6 +944,40 @@ void RasterizerSceneGLES3::environment_set_adjustment(RID p_env, bool p_enable,
 	env->color_correction = p_ramp;
 }
 
+void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {
+
+	Environment *env = environment_owner.getornull(p_env);
+	ERR_FAIL_COND(!env);
+
+	env->fog_enabled = p_enable;
+	env->fog_color = p_color;
+	env->fog_sun_color = p_sun_color;
+	env->fog_sun_amount = p_sun_amount;
+}
+
+void RasterizerSceneGLES3::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) {
+
+	Environment *env = environment_owner.getornull(p_env);
+	ERR_FAIL_COND(!env);
+
+	env->fog_depth_enabled = p_enable;
+	env->fog_depth_begin = p_depth_begin;
+	env->fog_depth_curve = p_depth_curve;
+	env->fog_transmit_enabled = p_transmit;
+	env->fog_transmit_curve = p_transmit_curve;
+}
+
+void RasterizerSceneGLES3::environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {
+
+	Environment *env = environment_owner.getornull(p_env);
+	ERR_FAIL_COND(!env);
+
+	env->fog_height_enabled = p_enable;
+	env->fog_height_min = p_min_height;
+	env->fog_height_max = p_max_height;
+	env->fog_height_curve = p_height_curve;
+}
+
 RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
 
 	LightInstance *light_instance = memnew(LightInstance);
@@ -2224,6 +2258,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
 		state.ubo_data.time[i] = storage->frame.time[i];
 	}
 
+	state.ubo_data.z_far = p_cam_projection.get_z_far();
 	//bg and ambient
 	if (env) {
 		state.ubo_data.bg_energy = env->bg_energy;
@@ -2255,6 +2290,30 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
 
 		state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution;
 		state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect;
+
+		//fog
+
+		Color linear_fog = env->fog_color.to_linear();
+		state.ubo_data.fog_color_enabled[0] = linear_fog.r;
+		state.ubo_data.fog_color_enabled[1] = linear_fog.g;
+		state.ubo_data.fog_color_enabled[2] = linear_fog.b;
+		state.ubo_data.fog_color_enabled[3] = env->fog_enabled ? 1.0 : 0.0;
+
+		Color linear_sun = env->fog_sun_color.to_linear();
+		state.ubo_data.fog_sun_color_amount[0] = linear_sun.r;
+		state.ubo_data.fog_sun_color_amount[1] = linear_sun.g;
+		state.ubo_data.fog_sun_color_amount[2] = linear_sun.b;
+		state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount;
+		state.ubo_data.fog_depth_enabled = env->fog_depth_enabled;
+		state.ubo_data.fog_depth_begin = env->fog_depth_begin;
+		state.ubo_data.fog_depth_curve = env->fog_depth_curve;
+		state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled;
+		state.ubo_data.fog_transmit_curve = env->fog_transmit_curve;
+		state.ubo_data.fog_height_enabled = env->fog_height_enabled;
+		state.ubo_data.fog_height_min = env->fog_height_min;
+		state.ubo_data.fog_height_max = env->fog_height_max;
+		state.ubo_data.fog_height_curve = env->fog_height_curve;
+
 	} else {
 		state.ubo_data.bg_energy = 1.0;
 		state.ubo_data.ambient_energy = 1.0;
@@ -2272,6 +2331,8 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
 
 		state.env_radiance_data.ambient_contribution = 0;
 		state.ubo_data.ambient_occlusion_affect_light = 0;
+
+		state.ubo_data.fog_color_enabled[3] = 0.0;
 	}
 
 	{

+ 52 - 0
drivers/gles3/rasterizer_scene_gles3.h

@@ -111,6 +111,9 @@ public:
 			float time[4];
 			float ambient_light_color[4];
 			float bg_color[4];
+			float fog_color_enabled[4];
+			float fog_sun_color_amount[4];
+
 			float ambient_energy;
 			float bg_energy;
 			float shadow_z_offset;
@@ -120,10 +123,22 @@ public:
 			float screen_pixel_size[2];
 			float shadow_atlas_pixel_size[2];
 			float shadow_directional_pixel_size[2];
+
+			float z_far;
 			float reflection_multiplier;
 			float subsurface_scatter_width;
 			float ambient_occlusion_affect_light;
 
+			bool fog_depth_enabled;
+			float fog_depth_begin;
+			float fog_depth_curve;
+			bool fog_transmit_enabled;
+			float fog_transmit_curve;
+			bool fog_height_enabled;
+			float fog_height_min;
+			float fog_height_max;
+			float fog_height_curve;
+
 		} ubo_data;
 
 		GLuint scene_ubo;
@@ -396,6 +411,21 @@ public:
 		float adjustments_saturation;
 		RID color_correction;
 
+		bool fog_enabled;
+		Color fog_color;
+		Color fog_sun_color;
+		float fog_sun_amount;
+
+		bool fog_depth_enabled;
+		float fog_depth_begin;
+		float fog_depth_curve;
+		bool fog_transmit_enabled;
+		float fog_transmit_curve;
+		bool fog_height_enabled;
+		float fog_height_min;
+		float fog_height_max;
+		float fog_height_curve;
+
 		Environment() {
 			bg_mode = VS::ENV_BG_CLEAR_COLOR;
 			sky_scale = 1.0;
@@ -457,6 +487,24 @@ public:
 			adjustments_brightness = 1.0;
 			adjustments_contrast = 1.0;
 			adjustments_saturation = 1.0;
+
+			fog_enabled = false;
+			fog_color = Color(0.5, 0.5, 0.5);
+			fog_sun_color = Color(0.8, 0.8, 0.0);
+			fog_sun_amount = 0;
+
+			fog_depth_enabled = true;
+
+			fog_depth_begin = 10;
+			fog_depth_curve = 1;
+
+			fog_transmit_enabled = true;
+			fog_transmit_curve = 1;
+
+			fog_height_enabled = false;
+			fog_height_min = 0;
+			fog_height_max = 100;
+			fog_height_curve = 1;
 		}
 	};
 
@@ -484,6 +532,10 @@ public:
 
 	virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp);
 
+	virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount);
+	virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve);
+	virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve);
+
 	/* LIGHT INSTANCE */
 
 	struct LightDataUBO {

+ 70 - 0
drivers/gles3/shaders/scene.glsl

@@ -67,6 +67,10 @@ layout(std140) uniform SceneData { //ubo:0
 
 	highp vec4 ambient_light_color;
 	highp vec4 bg_color;
+
+	vec4 fog_color_enabled;
+	vec4 fog_sun_color_amount;
+
 	float ambient_energy;
 	float bg_energy;
 
@@ -79,10 +83,21 @@ layout(std140) uniform SceneData { //ubo:0
 	vec2 shadow_atlas_pixel_size;
 	vec2 directional_shadow_pixel_size;
 
+	float z_far;
 	float reflection_multiplier;
 	float subsurface_scatter_width;
 	float ambient_occlusion_affect_light;
 
+	bool fog_depth_enabled;
+	float fog_depth_begin;
+	float fog_depth_curve;
+	bool fog_transmit_enabled;
+	float fog_transmit_curve;
+	bool fog_height_enabled;
+	float fog_height_min;
+	float fog_height_max;
+	float fog_height_curve;
+
 };
 
 uniform highp mat4 world_transform;
@@ -425,6 +440,8 @@ layout(std140) uniform SceneData {
 	highp vec4 ambient_light_color;
 	highp vec4 bg_color;
 
+	vec4 fog_color_enabled;
+	vec4 fog_sun_color_amount;
 
 	float ambient_energy;
 	float bg_energy;
@@ -438,10 +455,20 @@ layout(std140) uniform SceneData {
 	vec2 shadow_atlas_pixel_size;
 	vec2 directional_shadow_pixel_size;
 
+	float z_far;
 	float reflection_multiplier;
 	float subsurface_scatter_width;
 	float ambient_occlusion_affect_light;
 
+	bool fog_depth_enabled;
+	float fog_depth_begin;
+	float fog_depth_curve;
+	bool fog_transmit_enabled;
+	float fog_transmit_curve;
+	bool fog_height_enabled;
+	float fog_height_min;
+	float fog_height_max;
+	float fog_height_curve;
 };
 
 //directional light data
@@ -1615,6 +1642,49 @@ FRAGMENT_SHADER_CODE
 		specular_light *= min(1.0,50.0 * f0.g) * brdf.y + brdf.x * f0;
 	}
 
+	if (fog_color_enabled.a > 0.5) {
+
+		float fog_amount=0;
+
+
+
+#ifdef USE_LIGHT_DIRECTIONAL
+
+		vec3 fog_color = mix( fog_color_enabled.rgb, fog_sun_color_amount.rgb,fog_sun_color_amount.a * pow(max( dot(normalize(vertex),-light_direction_attenuation.xyz), 0.0),8.0) );
+#else
+
+		vec3 fog_color = fog_color_enabled.rgb;
+#endif
+
+		//apply fog
+
+		if (fog_depth_enabled) {
+
+			float fog_z = smoothstep(fog_depth_begin,z_far,-vertex.z);
+
+			fog_amount = pow(fog_z,fog_depth_curve);
+			if (fog_transmit_enabled) {
+				vec3 total_light = emission + ambient_light + specular_light + diffuse_light;
+				float transmit = pow(fog_z,fog_transmit_curve);
+				fog_color = mix(max(total_light,fog_color),fog_color,transmit);
+			}
+		}
+
+		if (fog_height_enabled) {
+			float y = (camera_matrix * vec4(vertex,1.0)).y;
+			fog_amount = max(fog_amount,pow(1.0-smoothstep(fog_height_min,fog_height_max,y),fog_height_curve));
+		}
+
+		float rev_amount = 1.0 - fog_amount;
+
+
+		emission = emission * rev_amount + fog_color * fog_amount;
+		ambient_light*=rev_amount;
+		specular_light*rev_amount;
+		diffuse_light*=rev_amount;
+
+	}
+
 #ifdef USE_MULTIPLE_RENDER_TARGETS
 
 #if defined(ENABLE_AO)

+ 239 - 0
scene/resources/environment.cpp

@@ -217,6 +217,7 @@ void Environment::set_adjustment_enable(bool p_enable) {
 
 	adjustment_enabled = p_enable;
 	VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID());
+	_change_notify();
 }
 
 bool Environment::is_adjustment_enabled() const {
@@ -283,12 +284,39 @@ void Environment::_validate_property(PropertyInfo &property) const {
 			property.usage = PROPERTY_USAGE_NOEDITOR;
 		}
 	}
+
+	static const char *hide_prefixes[] = {
+		"fog_",
+		"auto_exposure_",
+		"ss_reflections_",
+		"ssao_",
+		"dof_blur_far_",
+		"dof_blur_near_",
+		"glow_",
+		"adjustment_",
+		NULL
+
+	};
+
+	const char **prefixes = hide_prefixes;
+	while (*prefixes) {
+		String prefix = String(*prefixes);
+
+		String enabled = prefix + "enabled";
+		if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) {
+			property.usage = PROPERTY_USAGE_NOEDITOR;
+			return;
+		}
+
+		prefixes++;
+	}
 }
 
 void Environment::set_ssr_enabled(bool p_enable) {
 
 	ssr_enabled = p_enable;
 	VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_accel, ssr_fade, ssr_depth_tolerance, ssr_smooth, ssr_roughness);
+	_change_notify();
 }
 
 bool Environment::is_ssr_enabled() const {
@@ -360,6 +388,7 @@ void Environment::set_ssao_enabled(bool p_enable) {
 
 	ssao_enabled = p_enable;
 	VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, ssao_blur);
+	_change_notify();
 }
 
 bool Environment::is_ssao_enabled() const {
@@ -453,6 +482,7 @@ void Environment::set_glow_enabled(bool p_enabled) {
 
 	glow_enabled = p_enabled;
 	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_treshold, glow_hdr_bleed_treshold, glow_bicubic_upscale);
+	_change_notify();
 }
 
 bool Environment::is_glow_enabled() const {
@@ -558,6 +588,7 @@ void Environment::set_dof_blur_far_enabled(bool p_enable) {
 
 	dof_blur_far_enabled = p_enable;
 	VS::get_singleton()->environment_set_dof_blur_far(environment, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_far_amount, VS::EnvironmentDOFBlurQuality(dof_blur_far_quality));
+	_change_notify();
 }
 
 bool Environment::is_dof_blur_far_enabled() const {
@@ -610,6 +641,7 @@ void Environment::set_dof_blur_near_enabled(bool p_enable) {
 
 	dof_blur_near_enabled = p_enable;
 	VS::get_singleton()->environment_set_dof_blur_near(environment, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_near_amount, VS::EnvironmentDOFBlurQuality(dof_blur_near_quality));
+	_change_notify();
 }
 
 bool Environment::is_dof_blur_near_enabled() const {
@@ -661,6 +693,138 @@ Environment::DOFBlurQuality Environment::get_dof_blur_near_quality() const {
 	return dof_blur_near_quality;
 }
 
+void Environment::set_fog_enabled(bool p_enabled) {
+
+	fog_enabled = p_enabled;
+	VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount);
+	_change_notify();
+}
+
+bool Environment::is_fog_enabled() const {
+
+	return fog_enabled;
+}
+
+void Environment::set_fog_color(const Color &p_color) {
+
+	fog_color = p_color;
+	VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount);
+}
+Color Environment::get_fog_color() const {
+
+	return fog_color;
+}
+
+void Environment::set_fog_sun_color(const Color &p_color) {
+
+	fog_sun_color = p_color;
+	VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount);
+}
+Color Environment::get_fog_sun_color() const {
+
+	return fog_sun_color;
+}
+
+void Environment::set_fog_sun_amount(float p_amount) {
+
+	fog_sun_amount = p_amount;
+	VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount);
+}
+float Environment::get_fog_sun_amount() const {
+
+	return fog_sun_amount;
+}
+
+void Environment::set_fog_depth_enabled(bool p_enabled) {
+
+	fog_depth_enabled = p_enabled;
+	VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve);
+}
+bool Environment::is_fog_depth_enabled() const {
+
+	return fog_depth_enabled;
+}
+
+void Environment::set_fog_depth_begin(float p_distance) {
+
+	fog_depth_begin = p_distance;
+	VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve);
+}
+float Environment::get_fog_depth_begin() const {
+
+	return fog_depth_begin;
+}
+
+void Environment::set_fog_depth_curve(float p_curve) {
+
+	fog_depth_curve = p_curve;
+	VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve);
+}
+float Environment::get_fog_depth_curve() const {
+
+	return fog_depth_curve;
+}
+
+void Environment::set_fog_transmit_enabled(bool p_enabled) {
+
+	fog_transmit_enabled = p_enabled;
+	VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve);
+}
+bool Environment::is_fog_transmit_enabled() const {
+
+	return fog_transmit_enabled;
+}
+
+void Environment::set_fog_transmit_curve(float p_curve) {
+
+	fog_transmit_curve = p_curve;
+	VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve);
+}
+float Environment::get_fog_transmit_curve() const {
+
+	return fog_transmit_curve;
+}
+
+void Environment::set_fog_height_enabled(bool p_enabled) {
+
+	fog_height_enabled = p_enabled;
+	VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve);
+}
+bool Environment::is_fog_height_enabled() const {
+
+	return fog_height_enabled;
+}
+
+void Environment::set_fog_height_min(float p_distance) {
+
+	fog_height_min = p_distance;
+	VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve);
+}
+float Environment::get_fog_height_min() const {
+
+	return fog_height_min;
+}
+
+void Environment::set_fog_height_max(float p_distance) {
+
+	fog_height_max = p_distance;
+	VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve);
+}
+float Environment::get_fog_height_max() const {
+
+	return fog_height_max;
+}
+
+void Environment::set_fog_height_curve(float p_distance) {
+
+	fog_height_curve = p_distance;
+	VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve);
+}
+float Environment::get_fog_height_curve() const {
+
+	return fog_height_curve;
+}
+
 void Environment::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background);
@@ -695,6 +859,60 @@ void Environment::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_sky_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_sky_contribution", "get_ambient_light_sky_contribution");
 
+	ClassDB::bind_method(D_METHOD("set_fog_enabled", "enabled"), &Environment::set_fog_enabled);
+	ClassDB::bind_method(D_METHOD("is_fog_enabled"), &Environment::is_fog_enabled);
+
+	ClassDB::bind_method(D_METHOD("set_fog_color", "color"), &Environment::set_fog_color);
+	ClassDB::bind_method(D_METHOD("get_fog_color"), &Environment::get_fog_color);
+
+	ClassDB::bind_method(D_METHOD("set_fog_sun_color", "color"), &Environment::set_fog_sun_color);
+	ClassDB::bind_method(D_METHOD("get_fog_sun_color"), &Environment::get_fog_sun_color);
+
+	ClassDB::bind_method(D_METHOD("set_fog_sun_amount", "amount"), &Environment::set_fog_sun_amount);
+	ClassDB::bind_method(D_METHOD("get_fog_sun_amount"), &Environment::get_fog_sun_amount);
+
+	ClassDB::bind_method(D_METHOD("set_fog_depth_enabled", "enabled"), &Environment::set_fog_depth_enabled);
+	ClassDB::bind_method(D_METHOD("is_fog_depth_enabled"), &Environment::is_fog_depth_enabled);
+
+	ClassDB::bind_method(D_METHOD("set_fog_depth_begin", "distance"), &Environment::set_fog_depth_begin);
+	ClassDB::bind_method(D_METHOD("get_fog_depth_begin"), &Environment::get_fog_depth_begin);
+
+	ClassDB::bind_method(D_METHOD("set_fog_depth_curve", "curve"), &Environment::set_fog_depth_curve);
+	ClassDB::bind_method(D_METHOD("get_fog_depth_curve"), &Environment::get_fog_depth_curve);
+
+	ClassDB::bind_method(D_METHOD("set_fog_transmit_enabled", "enabled"), &Environment::set_fog_transmit_enabled);
+	ClassDB::bind_method(D_METHOD("is_fog_transmit_enabled"), &Environment::is_fog_transmit_enabled);
+
+	ClassDB::bind_method(D_METHOD("set_fog_transmit_curve", "curve"), &Environment::set_fog_transmit_curve);
+	ClassDB::bind_method(D_METHOD("get_fog_transmit_curve"), &Environment::get_fog_transmit_curve);
+
+	ClassDB::bind_method(D_METHOD("set_fog_height_enabled", "enabled"), &Environment::set_fog_height_enabled);
+	ClassDB::bind_method(D_METHOD("is_fog_height_enabled"), &Environment::is_fog_height_enabled);
+
+	ClassDB::bind_method(D_METHOD("set_fog_height_min", "height"), &Environment::set_fog_height_min);
+	ClassDB::bind_method(D_METHOD("get_fog_height_min"), &Environment::get_fog_height_min);
+
+	ClassDB::bind_method(D_METHOD("set_fog_height_max", "height"), &Environment::set_fog_height_max);
+	ClassDB::bind_method(D_METHOD("get_fog_height_max"), &Environment::get_fog_height_max);
+
+	ClassDB::bind_method(D_METHOD("set_fog_height_curve", "curve"), &Environment::set_fog_height_curve);
+	ClassDB::bind_method(D_METHOD("get_fog_height_curve"), &Environment::get_fog_height_curve);
+
+	ADD_GROUP("Fog", "fog_");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled");
+	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_color"), "set_fog_color", "get_fog_color");
+	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_sun_color"), "set_fog_sun_color", "get_fog_sun_color");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_sun_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fog_sun_amount", "get_fog_sun_amount");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_depth_enabled"), "set_fog_depth_enabled", "is_fog_depth_enabled");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_depth_begin", PROPERTY_HINT_RANGE, "0,4000,0.1"), "set_fog_depth_begin", "get_fog_depth_begin");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_depth_curve", PROPERTY_HINT_EXP_EASING), "set_fog_depth_curve", "get_fog_depth_curve");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_transmit_enabled"), "set_fog_transmit_enabled", "is_fog_transmit_enabled");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_transmit_curve", PROPERTY_HINT_EXP_EASING), "set_fog_transmit_curve", "get_fog_transmit_curve");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_height_enabled"), "set_fog_height_enabled", "is_fog_height_enabled");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_min", PROPERTY_HINT_RANGE, "-4000,4000,0.1"), "set_fog_height_min", "get_fog_height_min");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_max", PROPERTY_HINT_RANGE, "-4000,4000,0.1"), "set_fog_height_max", "get_fog_height_max");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_curve", PROPERTY_HINT_EXP_EASING), "set_fog_height_curve", "get_fog_height_curve");
+
 	ClassDB::bind_method(D_METHOD("set_tonemapper", "mode"), &Environment::set_tonemapper);
 	ClassDB::bind_method(D_METHOD("get_tonemapper"), &Environment::get_tonemapper);
 
@@ -997,6 +1215,27 @@ Environment::Environment() {
 	dof_blur_near_transition = 1;
 	dof_blur_near_amount = 0.1;
 	dof_blur_near_quality = DOF_BLUR_QUALITY_MEDIUM;
+
+	fog_enabled = false;
+	fog_color = Color(0.5, 0.5, 0.5);
+	fog_sun_color = Color(0.8, 0.8, 0.0);
+	fog_sun_amount = 0;
+
+	fog_depth_enabled = true;
+
+	fog_depth_begin = 10;
+	fog_depth_curve = 1;
+
+	fog_transmit_enabled = false;
+	fog_transmit_curve = 1;
+
+	fog_height_enabled = false;
+	fog_height_min = 0;
+	fog_height_max = 100;
+	fog_height_curve = 1;
+
+	set_fog_color(Color(0.5, 0.6, 0.7));
+	set_fog_sun_color(Color(1.0, 0.9, 0.7));
 }
 
 Environment::~Environment() {

+ 56 - 0
scene/resources/environment.h

@@ -138,6 +138,23 @@ private:
 	float dof_blur_near_amount;
 	DOFBlurQuality dof_blur_near_quality;
 
+	bool fog_enabled;
+	Color fog_color;
+	Color fog_sun_color;
+	float fog_sun_amount;
+
+	bool fog_depth_enabled;
+	float fog_depth_begin;
+	float fog_depth_curve;
+
+	bool fog_transmit_enabled;
+	float fog_transmit_curve;
+
+	bool fog_height_enabled;
+	float fog_height_min;
+	float fog_height_max;
+	float fog_height_curve;
+
 protected:
 	static void _bind_methods();
 	virtual void _validate_property(PropertyInfo &property) const;
@@ -307,6 +324,45 @@ public:
 	void set_dof_blur_near_quality(DOFBlurQuality p_quality);
 	DOFBlurQuality get_dof_blur_near_quality() const;
 
+	void set_fog_enabled(bool p_enabled);
+	bool is_fog_enabled() const;
+
+	void set_fog_color(const Color &p_color);
+	Color get_fog_color() const;
+
+	void set_fog_sun_color(const Color &p_color);
+	Color get_fog_sun_color() const;
+
+	void set_fog_sun_amount(float p_amount);
+	float get_fog_sun_amount() const;
+
+	void set_fog_depth_enabled(bool p_enabled);
+	bool is_fog_depth_enabled() const;
+
+	void set_fog_depth_begin(float p_distance);
+	float get_fog_depth_begin() const;
+
+	void set_fog_depth_curve(float p_curve);
+	float get_fog_depth_curve() const;
+
+	void set_fog_transmit_enabled(bool p_enabled);
+	bool is_fog_transmit_enabled() const;
+
+	void set_fog_transmit_curve(float p_curve);
+	float get_fog_transmit_curve() const;
+
+	void set_fog_height_enabled(bool p_enabled);
+	bool is_fog_height_enabled() const;
+
+	void set_fog_height_min(float p_distance);
+	float get_fog_height_min() const;
+
+	void set_fog_height_max(float p_distance);
+	float get_fog_height_max() const;
+
+	void set_fog_height_curve(float p_distance);
+	float get_fog_height_curve() const;
+
 	virtual RID get_rid() const;
 
 	Environment();

+ 4 - 0
servers/visual/rasterizer.h

@@ -71,6 +71,10 @@ public:
 
 	virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0;
 
+	virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
+	virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
+	virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
+
 	struct InstanceBase : RID_Data {
 
 		VS::InstanceType base_type;

+ 4 - 0
servers/visual/visual_server_raster.h

@@ -950,6 +950,10 @@ public:
 
 	BIND6(environment_set_adjustment, RID, bool, float, float, float, RID)
 
+	BIND5(environment_set_fog, RID, bool, const Color &, const Color &, float)
+	BIND6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+	BIND5(environment_set_fog_height, RID, bool, float, float, float)
+
 /* SCENARIO API */
 
 #undef BINDBASE

+ 4 - 0
servers/visual_server.h

@@ -638,6 +638,10 @@ public:
 	virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_accel, float p_fade, float p_depth_tolerance, bool p_smooth, bool p_roughness) = 0;
 	virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, bool p_blur) = 0;
 
+	virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0;
+	virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
+	virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
+
 	/* SCENARIO API */
 
 	virtual RID scenario_create() = 0;