Skip to content

Commit

Permalink
Add optional depth fog
Browse files Browse the repository at this point in the history
  • Loading branch information
HybridEidolon authored and scriptsengineer committed Feb 18, 2024
1 parent 9283d0d commit 08f4560
Show file tree
Hide file tree
Showing 27 changed files with 405 additions and 32 deletions.
22 changes: 21 additions & 1 deletion doc/classes/Environment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,18 @@
This is useful to simulate [url=https://en.wikipedia.org/wiki/Aerial_perspective]aerial perspective[/url] in large scenes with low density fog. However, it is not very useful for high-density fog, as the sky will shine through. When set to [code]1.0[/code], the fog color comes completely from the [Sky]. If set to [code]0.0[/code], aerial perspective is disabled.
</member>
<member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.01">
The [i]exponential[/i] fog density to use. Higher values result in a more dense fog. Fog rendering is exponential as in real life.
The fog density to be used. This is demonstrated in different ways depending on the [member fog_mode] mode chosen:
[b]Exponential Fog Mode:[/b] Higher values result in denser fog. The fog rendering is exponential like in real life.
[b]Depth Fog mode:[/b] The maximum intensity of the deep fog, effect will appear in the distance (relative to the camera). At [code]1.0[/code] the fog will fully obscure the scene, at [code]0.0[/code] the fog will not be visible.
</member>
<member name="fog_depth_begin" type="float" setter="set_fog_depth_begin" getter="get_fog_depth_begin" default="10.0">
The fog's depth starting distance from the camera. Only available when [member fog_mode] is set to [constant FOG_MODE_DEPTH].
</member>
<member name="fog_depth_curve" type="float" setter="set_fog_depth_curve" getter="get_fog_depth_curve" default="1.0">
The fog depth's intensity curve. A number of presets are available in the Inspector by right-clicking the curve. Only available when [member fog_mode] is set to [constant FOG_MODE_DEPTH].
</member>
<member name="fog_depth_end" type="float" setter="set_fog_depth_end" getter="get_fog_depth_end" default="100.0">
The fog's depth end distance from the camera. If this value is set to [code]0[/code], it will be equal to the current camera's [member Camera3D.far] value. Only available when [member fog_mode] is set to [constant FOG_MODE_DEPTH].
</member>
<member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled" default="false">
If [code]true[/code], fog effects are enabled.
Expand All @@ -104,6 +115,9 @@
<member name="fog_light_energy" type="float" setter="set_fog_light_energy" getter="get_fog_light_energy" default="1.0">
The fog's brightness. Higher values result in brighter fog.
</member>
<member name="fog_mode" type="int" setter="set_fog_mode" getter="get_fog_mode" enum="Environment.FogMode" default="0">
The fog mode. See [enum FogMode] for possible values.
</member>
<member name="fog_sky_affect" type="float" setter="set_fog_sky_affect" getter="get_fog_sky_affect" default="1.0">
The factor to use when affecting the sky with non-volumetric fog. [code]1.0[/code] means that fog can fully obscure the sky. Lower values reduce the impact of fog on sky rendering, with [code]0.0[/code] not affecting sky rendering at all.
[b]Note:[/b] [member fog_sky_affect] has no visual effect if [member fog_aerial_perspective] is [code]1.0[/code].
Expand Down Expand Up @@ -412,6 +426,12 @@
<constant name="GLOW_BLEND_MODE_MIX" value="4" enum="GlowBlendMode">
Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect.
</constant>
<constant name="FOG_MODE_EXPONENTIAL" value="0" enum="FogMode">
Use a physically-based fog model defined primarily by fog density.
</constant>
<constant name="FOG_MODE_DEPTH" value="1" enum="FogMode">
Use a simple fog model defined by start and end positions and a custom curve. While not physically accurate, this model can be useful when you need more artistic control.
</constant>
<constant name="SDFGI_Y_SCALE_50_PERCENT" value="0" enum="SDFGIYScale">
Use 50% scale for SDFGI on the Y (vertical) axis. SDFGI cells will be twice as short as they are wide. This allows providing increased GI detail and reduced light leaking with thin floors and ceilings. This is usually the best choice for scenes that don't feature much verticality.
</constant>
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,7 @@
<param index="7" name="height_density" type="float" />
<param index="8" name="aerial_perspective" type="float" />
<param index="9" name="sky_affect" type="float" />
<param index="10" name="fog_mode" type="int" enum="RenderingServer.EnvironmentFogMode" default="0" />
<description>
Configures fog for the specified environment RID. See [code]fog_*[/code] properties in [Environment] for more information.
</description>
Expand Down Expand Up @@ -4889,6 +4890,12 @@
<constant name="ENV_GLOW_BLEND_MODE_MIX" value="4" enum="EnvironmentGlowBlendMode">
Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect.
</constant>
<constant name="ENV_FOG_MODE_EXPONENTIAL" value="0" enum="EnvironmentFogMode">
Use a physically-based fog model defined primarily by fog density.
</constant>
<constant name="ENV_FOG_MODE_DEPTH" value="1" enum="EnvironmentFogMode">
Use a simple fog model defined by start and end positions and a custom curve. While not physically accurate, this model can be useful when you need more artistic control.
</constant>
<constant name="ENV_TONE_MAPPER_LINEAR" value="0" enum="EnvironmentToneMapper">
Output color as they came in. This can cause bright lighting to look blown out, with noticeable clipping in the output colors.
</constant>
Expand Down
8 changes: 8 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1642,8 +1642,12 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
}

scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment);
scene_state.ubo.fog_mode = environment_get_fog_mode(p_render_data->environment);
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
scene_state.ubo.fog_depth_curve = environment_get_fog_depth_curve(p_render_data->environment);
scene_state.ubo.fog_depth_end = environment_get_fog_depth_end(p_render_data->environment) > 0.0 ? environment_get_fog_depth_end(p_render_data->environment) : scene_state.ubo.z_far;
scene_state.ubo.fog_depth_begin = MIN(environment_get_fog_depth_begin(p_render_data->environment), scene_state.ubo.fog_depth_end - 0.001);
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);

Expand Down Expand Up @@ -2598,6 +2602,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
if (render_data.environment.is_null() || (render_data.environment.is_valid() && !environment_get_fog_enabled(render_data.environment))) {
spec_constant_base_flags |= SceneShaderGLES3::DISABLE_FOG;
}

if (render_data.environment.is_valid() && environment_get_fog_mode(render_data.environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) {
spec_constant_base_flags |= SceneShaderGLES3::USE_DEPTH_FOG;
}
}
// Render Opaque Objects.
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant_base_flags, use_wireframe);
Expand Down
8 changes: 7 additions & 1 deletion drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,15 +398,21 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
float IBL_exposure_normalization;

uint32_t fog_enabled;
uint32_t fog_mode;
float fog_density;
float fog_height;

float fog_height_density;
float fog_depth_curve;
float pad;
float fog_depth_begin;

float fog_light_color[3];
float fog_depth_end;

float fog_sun_scatter;

float shadow_bias;
float pad;
uint32_t camera_visible_layers;
bool pancake_shadows;
};
Expand Down
26 changes: 23 additions & 3 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DISABLE_LIGHT_DIRECTIONAL = false
DISABLE_LIGHT_OMNI = false
DISABLE_LIGHT_SPOT = false
DISABLE_FOG = false
USE_DEPTH_FOG = false
USE_RADIANCE_MAP = true
USE_LIGHTMAP = false
USE_SH_LIGHTMAP = false
Expand Down Expand Up @@ -181,15 +182,21 @@ layout(std140) uniform SceneData { // ubo:2
float IBL_exposure_normalization;

bool fog_enabled;
uint fog_mode;
float fog_density;
float fog_height;
float fog_height_density;

float fog_depth_curve;
float pad;
float fog_depth_begin;

vec3 fog_light_color;
float fog_depth_end;

float fog_sun_scatter;

float shadow_bias;
float pad;
uint camera_visible_layers;
bool pancake_shadows;
}
Expand Down Expand Up @@ -666,15 +673,21 @@ layout(std140) uniform SceneData { // ubo:2
float IBL_exposure_normalization;

bool fog_enabled;
uint fog_mode;
float fog_density;
float fog_height;
float fog_height_density;

float fog_depth_curve;
float pad;
float fog_depth_begin;

vec3 fog_light_color;
float fog_depth_end;

float fog_sun_scatter;

float shadow_bias;
float pad;
uint camera_visible_layers;
bool pancake_shadows;
}
Expand Down Expand Up @@ -1250,7 +1263,14 @@ vec4 fog_process(vec3 vertex) {
}
#endif // !DISABLE_LIGHT_DIRECTIONAL

float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
float fog_amount = 0.0;

#ifdef USE_DEPTH_FOG
float fog_z = smoothstep(scene_data.fog_depth_begin, scene_data.fog_depth_end, length(vertex));
fog_amount = pow(fog_z, scene_data.fog_depth_curve) * scene_data.fog_density;
#else
fog_amount = 1 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
#endif // USE_DEPTH_FOG

if (abs(scene_data.fog_height_density) >= 0.0001) {
float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y;
Expand Down
7 changes: 7 additions & 0 deletions misc/extension_api_validation/4.2-stable.expected
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,10 @@ GH-86661
Validate extension JSON: Error: Field 'classes/Animation/methods/track_find_key/arguments': size changed value in new API, from 3 to 4.

Added optional argument to track_find_key to avoid finding keys out of the animation range. Compatibility method registered.


GH-84792
--------
Validate extension JSON: Error: Field 'classes/RenderingServer/methods/environment_set_fog/arguments': size changed value in new API, from 10 to 11.

Added fog mode argument. Compatibility method registered.
84 changes: 83 additions & 1 deletion scene/resources/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,21 @@ bool Environment::is_fog_enabled() const {
return fog_enabled;
}

void Environment::set_fog_mode(FogMode p_mode) {
if (fog_mode != p_mode && p_mode == FogMode::FOG_MODE_EXPONENTIAL) {
set_fog_density(0.01);
} else {
set_fog_density(1.0);
}
fog_mode = p_mode;
_update_fog();
notify_property_list_changed();
}

Environment::FogMode Environment::get_fog_mode() const {
return fog_mode;
}

void Environment::set_fog_light_color(const Color &p_light_color) {
fog_light_color = p_light_color;
_update_fog();
Expand Down Expand Up @@ -837,7 +852,51 @@ void Environment::_update_fog() {
fog_height,
fog_height_density,
fog_aerial_perspective,
fog_sky_affect);
fog_sky_affect,
RS::EnvironmentFogMode(fog_mode));
}

// Depth Fog

void Environment::set_fog_depth_curve(float p_curve) {
fog_depth_curve = p_curve;
_update_fog_depth();
}

float Environment::get_fog_depth_curve() const {
return fog_depth_curve;
}

void Environment::set_fog_depth_begin(float p_begin) {
fog_depth_begin = p_begin;
if (fog_depth_begin > fog_depth_end) {
set_fog_depth_end(fog_depth_begin);
}
_update_fog_depth();
}

float Environment::get_fog_depth_begin() const {
return fog_depth_begin;
}

void Environment::set_fog_depth_end(float p_end) {
fog_depth_end = p_end;
if (fog_depth_end < fog_depth_begin) {
set_fog_depth_begin(fog_depth_end);
}
_update_fog_depth();
}

float Environment::get_fog_depth_end() const {
return fog_depth_end;
}

void Environment::_update_fog_depth() {
RS::get_singleton()->environment_set_fog_depth(
environment,
fog_depth_curve,
fog_depth_begin,
fog_depth_end);
}

// Volumetric Fog
Expand Down Expand Up @@ -1040,6 +1099,12 @@ void Environment::_validate_property(PropertyInfo &p_property) const {
}
}

if (p_property.name == "fog_depth_curve" || p_property.name == "fog_depth_begin" || p_property.name == "fog_depth_end") {
if (fog_mode == FOG_MODE_EXPONENTIAL) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}

if (p_property.name == "ambient_light_color" || p_property.name == "ambient_light_energy") {
if (ambient_source == AMBIENT_SOURCE_DISABLED) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
Expand Down Expand Up @@ -1377,6 +1442,8 @@ void Environment::_bind_methods() {

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_mode", "mode"), &Environment::set_fog_mode);
ClassDB::bind_method(D_METHOD("get_fog_mode"), &Environment::get_fog_mode);
ClassDB::bind_method(D_METHOD("set_fog_light_color", "light_color"), &Environment::set_fog_light_color);
ClassDB::bind_method(D_METHOD("get_fog_light_color"), &Environment::get_fog_light_color);
ClassDB::bind_method(D_METHOD("set_fog_light_energy", "light_energy"), &Environment::set_fog_light_energy);
Expand All @@ -1399,8 +1466,16 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fog_sky_affect", "sky_affect"), &Environment::set_fog_sky_affect);
ClassDB::bind_method(D_METHOD("get_fog_sky_affect"), &Environment::get_fog_sky_affect);

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_depth_begin", "begin"), &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_end", "end"), &Environment::set_fog_depth_end);
ClassDB::bind_method(D_METHOD("get_fog_depth_end"), &Environment::get_fog_depth_end);

ADD_GROUP("Fog", "fog_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fog_mode", PROPERTY_HINT_ENUM, "Exponential,Depth"), "set_fog_mode", "get_fog_mode");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_fog_light_color", "get_fog_light_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_fog_light_energy", "get_fog_light_energy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_sun_scatter", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_fog_sun_scatter", "get_fog_sun_scatter");
Expand All @@ -1411,6 +1486,10 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_less,or_greater,suffix:m"), "set_fog_height", "get_fog_height");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "-16,16,0.0001,or_less,or_greater"), "set_fog_height_density", "get_fog_height_density");

ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_curve", PROPERTY_HINT_EXP_EASING), "set_fog_depth_curve", "get_fog_depth_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_begin", PROPERTY_HINT_RANGE, "0,4000,0.1,or_greater,or_less,suffix:m"), "set_fog_depth_begin", "get_fog_depth_begin");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_end", PROPERTY_HINT_RANGE, "0,4000,0.1,or_greater,or_less,suffix:m"), "set_fog_depth_end", "get_fog_depth_end");

ClassDB::bind_method(D_METHOD("set_volumetric_fog_enabled", "enabled"), &Environment::set_volumetric_fog_enabled);
ClassDB::bind_method(D_METHOD("is_volumetric_fog_enabled"), &Environment::is_volumetric_fog_enabled);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_emission", "color"), &Environment::set_volumetric_fog_emission);
Expand Down Expand Up @@ -1504,6 +1583,9 @@ void Environment::_bind_methods() {
BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE);
BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_MIX);

BIND_ENUM_CONSTANT(FOG_MODE_EXPONENTIAL);
BIND_ENUM_CONSTANT(FOG_MODE_DEPTH);

BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_50_PERCENT);
BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_75_PERCENT);
BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_100_PERCENT);
Expand Down
24 changes: 24 additions & 0 deletions scene/resources/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ class Environment : public Resource {
SDFGI_Y_SCALE_100_PERCENT,
};

enum FogMode {
FOG_MODE_EXPONENTIAL,
FOG_MODE_DEPTH,
};

enum GlowBlendMode {
GLOW_BLEND_MODE_ADDITIVE,
GLOW_BLEND_MODE_SCREEN,
Expand Down Expand Up @@ -172,6 +177,7 @@ class Environment : public Resource {

// Fog
bool fog_enabled = false;
FogMode fog_mode = FOG_MODE_EXPONENTIAL;
Color fog_light_color = Color(0.518, 0.553, 0.608);
float fog_light_energy = 1.0;
float fog_sun_scatter = 0.0;
Expand All @@ -183,6 +189,13 @@ class Environment : public Resource {

void _update_fog();

// Depth Fog
float fog_depth_curve = 1.0;
float fog_depth_begin = 10.0;
float fog_depth_end = 100.0;

void _update_fog_depth();

// Volumetric Fog
bool volumetric_fog_enabled = false;
float volumetric_fog_density = 0.05;
Expand Down Expand Up @@ -361,6 +374,8 @@ class Environment : public Resource {

void set_fog_enabled(bool p_enabled);
bool is_fog_enabled() const;
void set_fog_mode(FogMode p_mode);
FogMode get_fog_mode() const;
void set_fog_light_color(const Color &p_light_color);
Color get_fog_light_color() const;
void set_fog_light_energy(float p_amount);
Expand All @@ -379,6 +394,14 @@ class Environment : public Resource {
void set_fog_sky_affect(float p_sky_affect);
float get_fog_sky_affect() const;

// Depth Fog
void set_fog_depth_curve(float p_curve);
float get_fog_depth_curve() const;
void set_fog_depth_begin(float p_begin);
float get_fog_depth_begin() const;
void set_fog_depth_end(float p_end);
float get_fog_depth_end() const;

// Volumetric Fog
void set_volumetric_fog_enabled(bool p_enable);
bool is_volumetric_fog_enabled() const;
Expand Down Expand Up @@ -429,5 +452,6 @@ VARIANT_ENUM_CAST(Environment::ReflectionSource)
VARIANT_ENUM_CAST(Environment::ToneMapper)
VARIANT_ENUM_CAST(Environment::SDFGIYScale)
VARIANT_ENUM_CAST(Environment::GlowBlendMode)
VARIANT_ENUM_CAST(Environment::FogMode)

#endif // ENVIRONMENT_H
Loading

0 comments on commit 08f4560

Please sign in to comment.