Skip to content

Commit

Permalink
Add Environment linear fog
Browse files Browse the repository at this point in the history
This nicely combines with exponential fog, allowing linear fog to completely obscure objects beyond a distance while exponential fog provides a more realistic effect in the interim.
`fog_amount = max(fog_exp, fog_linear)`
  • Loading branch information
briansemrau committed Oct 26, 2021
1 parent 64faa37 commit ca42aea
Show file tree
Hide file tree
Showing 25 changed files with 122 additions and 26 deletions.
7 changes: 7 additions & 0 deletions doc/classes/Environment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@
</member>
<member name="fog_light_energy" type="float" setter="set_fog_light_energy" getter="get_fog_light_energy" default="1.0">
</member>
<member name="fog_linear_end" type="float" setter="set_fog_linear_end" getter="get_fog_linear_end" default="0.0">
The linear fog far distance. When set to 0, linear fog is ignored. See [member fog_linear_start] to adjust the start distance.
When used with [member fog_density], linear fog and exponential fog are combined. If [member fog_density] is too low (or linear fog too aggressive), fog will appear entirely linear.
</member>
<member name="fog_linear_start" type="float" setter="set_fog_linear_start" getter="get_fog_linear_start" default="0.0">
The linear fog near distance. See [member fog_linear_end].
</member>
<member name="fog_sun_scatter" type="float" setter="set_fog_sun_scatter" getter="get_fog_sun_scatter" default="0.0">
</member>
<member name="glow_blend_mode" type="int" setter="set_glow_blend_mode" getter="get_glow_blend_mode" enum="Environment.GlowBlendMode" default="2">
Expand Down
2 changes: 2 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,8 @@
<argument index="6" name="height" type="float" />
<argument index="7" name="height_density" type="float" />
<argument index="8" name="aerial_perspective" type="float" />
<argument index="9" name="linear_start" type="float" />
<argument index="10" name="linear_end" type="float" />
<description>
</description>
</method>
Expand Down
41 changes: 40 additions & 1 deletion scene/resources/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,41 +719,52 @@ void Environment::set_fog_light_color(const Color &p_light_color) {
fog_light_color = p_light_color;
_update_fog();
}

Color Environment::get_fog_light_color() const {
return fog_light_color;
}

void Environment::set_fog_light_energy(float p_amount) {
fog_light_energy = p_amount;
_update_fog();
}

float Environment::get_fog_light_energy() const {
return fog_light_energy;
}

void Environment::set_fog_sun_scatter(float p_amount) {
fog_sun_scatter = p_amount;
_update_fog();
}

float Environment::get_fog_sun_scatter() const {
return fog_sun_scatter;
}

void Environment::set_fog_density(float p_amount) {
fog_density = p_amount;
_update_fog();
}

float Environment::get_fog_density() const {
return fog_density;
}

void Environment::set_fog_height(float p_amount) {
fog_height = p_amount;
_update_fog();
}

float Environment::get_fog_height() const {
return fog_height;
}

void Environment::set_fog_height_density(float p_amount) {
fog_height_density = p_amount;
_update_fog();
}

float Environment::get_fog_height_density() const {
return fog_height_density;
}
Expand All @@ -762,10 +773,29 @@ void Environment::set_fog_aerial_perspective(float p_aerial_perspective) {
fog_aerial_perspective = p_aerial_perspective;
_update_fog();
}

float Environment::get_fog_aerial_perspective() const {
return fog_aerial_perspective;
}

void Environment::set_fog_linear_start(float p_distance) {
fog_linear_start = p_distance;
_update_fog();
}

float Environment::get_fog_linear_start() const {
return fog_linear_start;
}

void Environment::set_fog_linear_end(float p_distance) {
fog_linear_end = p_distance;
_update_fog();
}

float Environment::get_fog_linear_end() const {
return fog_linear_end;
}

void Environment::_update_fog() {
RS::get_singleton()->environment_set_fog(
environment,
Expand All @@ -776,7 +806,9 @@ void Environment::_update_fog() {
fog_density,
fog_height,
fog_height_density,
fog_aerial_perspective);
fog_aerial_perspective,
fog_linear_start,
fog_linear_end);
}

// Volumetric Fog
Expand Down Expand Up @@ -1282,6 +1314,11 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fog_aerial_perspective", "aerial_perspective"), &Environment::set_fog_aerial_perspective);
ClassDB::bind_method(D_METHOD("get_fog_aerial_perspective"), &Environment::get_fog_aerial_perspective);

ClassDB::bind_method(D_METHOD("set_fog_linear_start", "distance"), &Environment::set_fog_linear_start);
ClassDB::bind_method(D_METHOD("get_fog_linear_start"), &Environment::get_fog_linear_start);
ClassDB::bind_method(D_METHOD("set_fog_linear_end", "distance"), &Environment::set_fog_linear_end);
ClassDB::bind_method(D_METHOD("get_fog_linear_end"), &Environment::get_fog_linear_end);

ADD_GROUP("Fog", "fog_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_fog_light_color", "get_fog_light_color");
Expand All @@ -1292,6 +1329,8 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_aerial_perspective", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_fog_aerial_perspective", "get_fog_aerial_perspective");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater"), "set_fog_height", "get_fog_height");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "-16,16,0.0001,or_lesser,or_greater"), "set_fog_height_density", "get_fog_height_density");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_linear_start", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_fog_linear_start", "get_fog_linear_start");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_linear_end", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_fog_linear_end", "get_fog_linear_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);
Expand Down
6 changes: 6 additions & 0 deletions scene/resources/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class Environment : public Resource {
float fog_height = 0.0;
float fog_height_density = 0.0; //can be negative to invert effect
float fog_aerial_perspective = 0.0;
float fog_linear_start = 0.0;
float fog_linear_end = 0.0;

void _update_fog();

Expand Down Expand Up @@ -369,6 +371,10 @@ class Environment : public Resource {
float get_fog_height_density() const;
void set_fog_aerial_perspective(float p_aerial_perspective);
float get_fog_aerial_perspective() const;
void set_fog_linear_start(float p_distance);
float get_fog_linear_start() const;
void set_fog_linear_end(float p_distance);
float get_fog_linear_end() const;

// Volumetric Fog
void set_volumetric_fog_enabled(bool p_enable);
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/rasterizer_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class RasterizerSceneDummy : public RendererSceneRender {

void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}

void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_linear_start, float p_linear_end) override {}
void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override {}
void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,8 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
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);
scene_state.ubo.fog_linear_start = environment_get_fog_linear_start(p_render_data->environment);
scene_state.ubo.fog_linear_end = environment_get_fog_linear_end(p_render_data->environment);

Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,14 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float fog_sun_scatter;

float fog_aerial_perspective;

float fog_linear_start;
float fog_linear_end;
float time;
float reflection_multiplier;

float reflection_multiplier;
uint32_t pancake_shadows;
uint32_t pad1;
uint32_t pad2;
};

struct PushConstant {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,8 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
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);
scene_state.ubo.fog_linear_start = environment_get_fog_linear_start(p_render_data->environment);
scene_state.ubo.fog_linear_end = environment_get_fog_linear_end(p_render_data->environment);

Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,15 @@ class RenderForwardMobile : public RendererSceneRenderRD {
float fog_sun_scatter;

float fog_aerial_perspective;
float fog_linear_start;
float fog_linear_end;
uint32_t material_uv2_mode;

float time;
float reflection_multiplier;

uint32_t pancake_shadows;
uint32_t pad1;
uint32_t pad2;
uint32_t pad3;
};

UBO ubo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,17 @@ void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, RS::EnvironmentSDFGICa
sdfgi_y_scale = p_y_scale;
}

void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_linear_start, float p_linear_end) {
fog_enabled = p_enable;
fog_light_color = p_light_color;
fog_light_energy = p_light_energy;
fog_sun_scatter = p_sun_scatter;
fog_density = p_density;
fog_height = p_height;
fog_height_density = p_height_density;
fog_aerial_perspective = p_fog_aerial_perspective;
fog_aerial_perspective = p_aerial_perspective;
fog_linear_start = p_linear_start;
fog_linear_end = p_linear_end;
}

void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ class RendererSceneEnvironmentRD {
float fog_height = 0.0;
float fog_height_density = 0.0; //can be negative to invert effect
float fog_aerial_perspective = 0.0;
float fog_linear_start = 0.0;
float fog_linear_end = 0.0;

/// Volumetric Fog
///
Expand Down Expand Up @@ -145,7 +147,7 @@ class RendererSceneEnvironmentRD {
void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
void set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective);
void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_linear_start, float p_linear_end);
void set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount);
void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
Expand Down
16 changes: 14 additions & 2 deletions servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,11 @@ void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::
env->set_sdfgi(p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias);
}

void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_linear_start, float p_linear_end) {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);

env->set_fog(p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_fog_aerial_perspective);
env->set_fog(p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_linear_start, p_linear_end);
}

bool RendererSceneRenderRD::environment_is_fog_enabled(RID p_env) const {
Expand Down Expand Up @@ -365,6 +365,18 @@ float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) c
return env->fog_aerial_perspective;
}

float RendererSceneRenderRD::environment_get_fog_linear_start(RID p_env) const {
const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_linear_start;
}

float RendererSceneRenderRD::environment_get_fog_linear_end(RID p_env) const {
const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->fog_linear_end;
}

void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
Expand Down
4 changes: 3 additions & 1 deletion servers/rendering/renderer_rd/renderer_scene_render_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
virtual void environment_glow_set_use_high_quality(bool p_enable) override;

virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override;
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_linear_start, float p_linear_end) override;
bool environment_is_fog_enabled(RID p_env) const;
Color environment_get_fog_light_color(RID p_env) const;
float environment_get_fog_light_energy(RID p_env) const;
Expand All @@ -903,6 +903,8 @@ class RendererSceneRenderRD : public RendererSceneRender {
float environment_get_fog_height(RID p_env) const;
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
float environment_get_fog_linear_start(RID p_env) const;
float environment_get_fog_linear_end(RID p_env) const;

virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override;

Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,8 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_scene_state.ubo.fog_enabled = p_env->fog_enabled;
sky_scene_state.ubo.fog_density = p_env->fog_density;
sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective;
sky_scene_state.ubo.fog_linear_start = p_env->fog_linear_start;
sky_scene_state.ubo.fog_linear_end = p_env->fog_linear_end;
Color fog_color = p_env->fog_light_color.to_linear();
float fog_energy = p_env->fog_light_energy;
sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
Expand Down
5 changes: 5 additions & 0 deletions servers/rendering/renderer_rd/renderer_scene_sky_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,14 @@ class RendererSceneSkyRD {

uint32_t fog_enabled;
float fog_density;
float fog_linear_start;
float fog_linear_end;

float z_far;

uint32_t directional_light_count;
uint32_t pad1;
uint32_t pad2;
};

UBO ubo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,10 @@ vec4 fog_process(vec3 vertex) {

if (scene_data.fog_aerial_perspective > 0.0) {
vec3 sky_fog_color = vec3(0.0);
vec3 cube_view = scene_data.radiance_inverse_xform * vertex;
vec3 cube_view = scene_data.radiance_inverse_xform * normalize(vertex);
// mip_level always reads from the second mipmap and higher so the fog is always slightly blurred
float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near));
float z_far = scene_data.fog_linear_end > 0.0 ? scene_data.fog_linear_end : scene_data.z_far;
float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, max(0.0, 1.0 - (length(vertex) - scene_data.z_near) / (z_far - scene_data.z_near)));
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
float lod, blend;
blend = modf(mip_level * MAX_ROUGHNESS_LOD, lod);
Expand All @@ -525,6 +526,10 @@ vec4 fog_process(vec3 vertex) {
}

float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
if (scene_data.fog_linear_end >= 0.0001) {
float fog_linear = clamp((length(vertex) - scene_data.fog_linear_start) / (scene_data.fog_linear_end - scene_data.fog_linear_start), 0, 1);
fog_amount = max(fog_amount, fog_linear);
}

if (abs(scene_data.fog_height_density) >= 0.0001) {
float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,14 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
float fog_sun_scatter;

float fog_aerial_perspective;

float fog_linear_start;
float fog_linear_end;
float time;
float reflection_multiplier; // one normally, zero when rendering reflections

float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
uint pad1;
uint pad2;
}
scene_data;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,14 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
mediump float fog_sun_scatter;

mediump float fog_aerial_perspective;
highp float fog_linear_start;
highp float fog_linear_end;
bool material_uv2_mode;

highp float time;
mediump float reflection_multiplier; // one normally, zero when rendering reflections

bool pancake_shadows;
uint pad1;
uint pad2;
uint pad3;
}
scene_data;

Expand Down
Loading

0 comments on commit ca42aea

Please sign in to comment.