diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index acd959d7f7de..6913d1f75c63 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -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. - 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. + + + The fog's depth starting distance from the camera. Only available when [member fog_mode] is set to [constant FOG_MODE_DEPTH]. + + + 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]. + + + 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]. If [code]true[/code], fog effects are enabled. @@ -104,6 +115,9 @@ The fog's brightness. Higher values result in brighter fog. + + The fog mode. See [enum FogMode] for possible values. + 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]. @@ -412,6 +426,12 @@ Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect. + + Use a physically-based fog model defined primarily by fog density. + + + 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. + 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. diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 54a11af629e3..11614b1c2fd5 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1145,6 +1145,7 @@ + Configures fog for the specified environment RID. See [code]fog_*[/code] properties in [Environment] for more information. @@ -4889,6 +4890,12 @@ Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect. + + Use a physically-based fog model defined primarily by fog density. + + + 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. + Output color as they came in. This can cause bright lighting to look blown out, with noticeable clipping in the output colors. diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 6cca1fef7ec6..efd554eac9fe 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -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); @@ -2598,6 +2602,10 @@ void RasterizerSceneGLES3::render_scene(const Ref &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); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 7880591dcba0..ed59aba266fb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -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; }; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index ffdac85c1e57..667cbb3d9066 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -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 @@ -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; } @@ -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; } @@ -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; diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected index 2b7a39944ab4..f79b6ae5e675 100644 --- a/misc/extension_api_validation/4.2-stable.expected +++ b/misc/extension_api_validation/4.2-stable.expected @@ -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. diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index b936c2decf85..910a6e303db2 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -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(); @@ -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 @@ -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; @@ -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); @@ -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"); @@ -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); @@ -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); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index b01c328b50fd..68b49f38d746 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -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, @@ -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; @@ -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; @@ -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); @@ -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; @@ -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 diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index e972d9107201..c454d35d2858 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -374,7 +374,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. uint32_t pipeline_color_pass_flags = 0; - uint32_t pipeline_specialization = 0; + uint32_t pipeline_specialization = p_params->spec_constant_base_flags; if constexpr (p_pass_mode == PASS_MODE_COLOR) { if (element_info.uses_softshadow) { @@ -1884,6 +1884,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid(); + uint32_t spec_constant_base_flags = 0; + { + if (p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) { + spec_constant_base_flags |= 1 << SPEC_CONSTANT_USE_DEPTH_FOG; + } + } + bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); if (depth_pre_pass) { //depth pre pass @@ -1906,7 +1913,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers); bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags); _render_list_with_draw_list(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? Vector() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); @@ -1972,7 +1979,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co uint32_t opaque_color_pass_flags = using_motion_pass ? (color_pass_flags & ~COLOR_PASS_FLAG_MOTION_VECTORS) : color_pass_flags; RID opaque_framebuffer = using_motion_pass ? rb_data->get_color_pass_fb(opaque_color_pass_flags) : color_framebuffer; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags); _render_list_with_draw_list(&render_list_params, opaque_framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pre_pass ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 1.0, 0); } @@ -1992,7 +1999,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_MOTION, p_render_data, radiance_texture, samplers, true); - RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags); _render_list_with_draw_list(&render_list_params, color_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); RD::get_singleton()->draw_command_end_label(); @@ -2125,7 +2132,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } RID alpha_framebuffer = rb_data.is_valid() ? rb_data->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer; - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags); _render_list_with_draw_list(&render_list_params, alpha_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index be553411027a..51fd0aaffb9e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -72,6 +72,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9, SPEC_CONSTANT_DECAL_FILTER = 10, SPEC_CONSTANT_PROJECTOR_FILTER = 11, + SPEC_CONSTANT_USE_DEPTH_FOG = 12, }; enum { @@ -210,8 +211,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { RD::FramebufferFormatID framebuffer_format = 0; uint32_t element_offset = 0; bool use_directional_soft_shadow = false; + uint32_t spec_constant_base_flags = 0; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_spec_constant_base_flags = 0) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; @@ -227,6 +229,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; element_offset = p_element_offset; use_directional_soft_shadow = p_use_directional_soft_shadows; + spec_constant_base_flags = p_spec_constant_base_flags; } }; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 29c5deb6c20b..fd81430983c9 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -899,6 +899,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (!is_environment(p_render_data->environment) || !environment_get_fog_enabled(p_render_data->environment)) { spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG; } + + if (p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) { + spec_constant_base_flags |= 1 << SPEC_CONSTANT_USE_DEPTH_FOG; + } } { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index ba5fefc83fb9..5c022046276d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -80,6 +80,7 @@ class RenderForwardMobile : public RendererSceneRenderRD { SPEC_CONSTANT_DISABLE_DECALS = 13, SPEC_CONSTANT_DISABLE_FOG = 14, + SPEC_CONSTANT_USE_DEPTH_FOG = 16, }; diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index cb95621219ca..6eae64c04e02 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -656,6 +656,7 @@ layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4; layout(constant_id = 10) const bool sc_decal_use_mipmaps = true; layout(constant_id = 11) const bool sc_projector_use_mipmaps = true; +layout(constant_id = 12) const bool sc_use_depth_fog = false; // not used in clustered renderer but we share some code with the mobile renderer that requires this. const float sc_luminance_multiplier = 1.0; @@ -848,7 +849,15 @@ vec4 fog_process(vec3 vertex) { } } - float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density)); + float fog_amount = 0.0; + + if (sc_use_depth_fog) { + float fog_z = smoothstep(scene_data_block.data.fog_depth_begin, scene_data_block.data.fog_depth_end, length(vertex)); + float fog_quad_amount = pow(fog_z, scene_data_block.data.fog_depth_curve) * scene_data_block.data.fog_density; + fog_amount = fog_quad_amount; + } else { + fog_amount = 1 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density)); + } if (abs(scene_data_block.data.fog_height_density) >= 0.0001) { float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y; diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index e9c69058f2ae..259edc63a0d5 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -525,6 +525,7 @@ layout(constant_id = 12) const bool sc_disable_directional_lights = false; layout(constant_id = 7) const bool sc_decal_use_mipmaps = true; layout(constant_id = 13) const bool sc_disable_decals = false; layout(constant_id = 14) const bool sc_disable_fog = false; +layout(constant_id = 16) const bool sc_use_depth_fog = false; #endif //!MODE_RENDER_DEPTH @@ -690,7 +691,15 @@ vec4 fog_process(vec3 vertex) { } } - float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density)); + float fog_amount = 0.0; + + if (sc_use_depth_fog) { + float fog_z = smoothstep(scene_data_block.data.fog_depth_begin, scene_data_block.data.fog_depth_end, length(vertex)); + float fog_quad_amount = pow(fog_z, scene_data_block.data.fog_depth_curve) * scene_data_block.data.fog_density; + fog_amount = fog_quad_amount; + } else { + fog_amount = 1 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density)); + } if (abs(scene_data_block.data.fog_height_density) >= 0.0001) { float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y; diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl index 70e670c3f756..67542d61fd03 100644 --- a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl @@ -49,24 +49,29 @@ struct SceneData { mediump float opaque_prepass_threshold; bool fog_enabled; + uint fog_mode; highp float fog_density; highp float fog_height; highp float fog_height_density; + highp float fog_depth_curve; + highp float pad; + highp float fog_depth_begin; + mediump vec3 fog_light_color; - mediump float fog_sun_scatter; + highp float fog_depth_end; + mediump float fog_sun_scatter; mediump float fog_aerial_perspective; highp float time; mediump float reflection_multiplier; // one normally, zero when rendering reflections - bool material_uv2_mode; vec2 taa_jitter; + bool material_uv2_mode; float emissive_exposure_normalization; - float IBL_exposure_normalization; + float IBL_exposure_normalization; bool pancake_shadows; uint camera_visible_layers; float pass_alpha_multiplier; - uint pad3; }; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index 506e78bae908..86f0f5acf2bc 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -168,11 +168,16 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p } ubo.fog_enabled = render_scene_render->environment_get_fog_enabled(p_env); + ubo.fog_mode = render_scene_render->environment_get_fog_mode(p_env); ubo.fog_density = render_scene_render->environment_get_fog_density(p_env); ubo.fog_height = render_scene_render->environment_get_fog_height(p_env); ubo.fog_height_density = render_scene_render->environment_get_fog_height_density(p_env); ubo.fog_aerial_perspective = render_scene_render->environment_get_fog_aerial_perspective(p_env); + ubo.fog_depth_curve = render_scene_render->environment_get_fog_depth_curve(p_env); + ubo.fog_depth_end = render_scene_render->environment_get_fog_depth_end(p_env) > 0.0 ? render_scene_render->environment_get_fog_depth_end(p_env) : ubo.z_far; + ubo.fog_depth_begin = MIN(render_scene_render->environment_get_fog_depth_begin(p_env), ubo.fog_depth_end - 0.001); + Color fog_color = render_scene_render->environment_get_fog_light_color(p_env).srgb_to_linear(); float fog_energy = render_scene_render->environment_get_fog_light_energy(p_env); diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h index f93f22816bce..9453966a86be 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -131,26 +131,31 @@ class RenderSceneDataRD { // Fog 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_sun_scatter; + float fog_depth_end; + float fog_sun_scatter; float fog_aerial_perspective; float time; float reflection_multiplier; - uint32_t material_uv2_mode; float taa_jitter[2]; + uint32_t material_uv2_mode; float emissive_exposure_normalization; // Needed to normalize emissive when using physical units. - float IBL_exposure_normalization; // Adjusts for baked exposure. + float IBL_exposure_normalization; // Adjusts for baked exposure. uint32_t pancake_shadows; uint32_t camera_visible_layers; float pass_alpha_multiplier; - uint32_t pad3; }; struct UBODATA { diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index a09823b00869..f48902a4efaf 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -1203,7 +1203,7 @@ class RendererSceneCull : public RenderingMethod { PASS1RC(float, environment_get_white, RID) // Fog - PASS10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float) + PASS11(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float, RS::EnvironmentFogMode) PASS1RC(bool, environment_get_fog_enabled, RID) PASS1RC(Color, environment_get_fog_light_color, RID) @@ -1214,10 +1214,17 @@ class RendererSceneCull : public RenderingMethod { PASS1RC(float, environment_get_fog_height, RID) PASS1RC(float, environment_get_fog_height_density, RID) PASS1RC(float, environment_get_fog_aerial_perspective, RID) + PASS1RC(RS::EnvironmentFogMode, environment_get_fog_mode, RID) PASS2(environment_set_volumetric_fog_volume_size, int, int) PASS1(environment_set_volumetric_fog_filter_active, bool) + // Depth Fog + PASS4(environment_set_fog_depth, RID, float, float, float) + PASS1RC(float, environment_get_fog_depth_curve, RID) + PASS1RC(float, environment_get_fog_depth_begin, RID) + PASS1RC(float, environment_get_fog_depth_end, RID) + // Volumentric Fog PASS14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float) diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index dce301d87b7c..95eb29a8915d 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -310,14 +310,18 @@ float RendererSceneRender::environment_get_white(RID p_env) const { // Fog -void RendererSceneRender::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_sky_affect) { - environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect); +void RendererSceneRender::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_sky_affect, RS::EnvironmentFogMode p_mode) { + environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, p_mode); } bool RendererSceneRender::environment_get_fog_enabled(RID p_env) const { return environment_storage.environment_get_fog_enabled(p_env); } +RS::EnvironmentFogMode RendererSceneRender::environment_get_fog_mode(RID p_env) const { + return environment_storage.environment_get_fog_mode(p_env); +} + Color RendererSceneRender::environment_get_fog_light_color(RID p_env) const { return environment_storage.environment_get_fog_light_color(p_env); } @@ -350,6 +354,24 @@ float RendererSceneRender::environment_get_fog_aerial_perspective(RID p_env) con return environment_storage.environment_get_fog_aerial_perspective(p_env); } +// Depth Fog + +void RendererSceneRender::environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) { + environment_storage.environment_set_fog_depth(p_env, p_curve, p_begin, p_end); +} + +float RendererSceneRender::environment_get_fog_depth_curve(RID p_env) const { + return environment_storage.environment_get_fog_depth_curve(p_env); +} + +float RendererSceneRender::environment_get_fog_depth_begin(RID p_env) const { + return environment_storage.environment_get_fog_depth_begin(p_env); +} + +float RendererSceneRender::environment_get_fog_depth_end(RID p_env) const { + return environment_storage.environment_get_fog_depth_end(p_env); +} + // Volumetric Fog void RendererSceneRender::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) { diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 900738364194..c6e2c23e9118 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -116,8 +116,9 @@ class RendererSceneRender { float environment_get_white(RID p_env) const; // Fog - 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_sky_affect); + 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_sky_affect, RS::EnvironmentFogMode p_mode); bool environment_get_fog_enabled(RID p_env) const; + RS::EnvironmentFogMode environment_get_fog_mode(RID p_env) const; Color environment_get_fog_light_color(RID p_env) const; float environment_get_fog_light_energy(RID p_env) const; float environment_get_fog_sun_scatter(RID p_env) const; @@ -127,6 +128,12 @@ class RendererSceneRender { float environment_get_fog_height_density(RID p_env) const; float environment_get_fog_aerial_perspective(RID p_env) const; + // Depth Fog + void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end); + float environment_get_fog_depth_curve(RID p_env) const; + float environment_get_fog_depth_begin(RID p_env) const; + float environment_get_fog_depth_end(RID p_env) const; + // Volumetric Fog void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect); bool environment_get_volumetric_fog_enabled(RID p_env) const; diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h index d1c6c1cbf902..be14a50eec22 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -154,9 +154,10 @@ class RenderingMethod { virtual float environment_get_white(RID p_env) const = 0; // Fog - 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_sky_affect) = 0; + 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_sky_affect, RS::EnvironmentFogMode p_mode = RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL) = 0; virtual bool environment_get_fog_enabled(RID p_env) const = 0; + virtual RS::EnvironmentFogMode environment_get_fog_mode(RID p_env) const = 0; virtual Color environment_get_fog_light_color(RID p_env) const = 0; virtual float environment_get_fog_light_energy(RID p_env) const = 0; virtual float environment_get_fog_sun_scatter(RID p_env) const = 0; @@ -166,6 +167,13 @@ class RenderingMethod { virtual float environment_get_fog_aerial_perspective(RID p_env) const = 0; virtual float environment_get_fog_sky_affect(RID p_env) const = 0; + // Depth Fog + virtual void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) = 0; + + virtual float environment_get_fog_depth_curve(RID p_env) const = 0; + virtual float environment_get_fog_depth_begin(RID p_env) const = 0; + virtual float environment_get_fog_depth_end(RID p_env) const = 0; + // Volumetric Fog virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 577e9accc0e3..c218007a789f 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -725,7 +725,9 @@ class RenderingServerDefault : public RenderingServer { FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) - FUNC10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float) + FUNC11(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float, EnvironmentFogMode) + + FUNC4(environment_set_fog_depth, RID, float, float, float) FUNC14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float) FUNC2(environment_set_volumetric_fog_volume_size, int, int) diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp index 0234f52ca1e7..ec26e3650943 100644 --- a/servers/rendering/storage/environment_storage.cpp +++ b/servers/rendering/storage/environment_storage.cpp @@ -205,10 +205,11 @@ float RendererEnvironmentStorage::environment_get_white(RID p_env) const { // Fog -void RendererEnvironmentStorage::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, float p_sky_affect) { +void RendererEnvironmentStorage::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, float p_sky_affect, RS::EnvironmentFogMode p_mode) { Environment *env = environment_owner.get_or_null(p_env); ERR_FAIL_NULL(env); env->fog_enabled = p_enable; + env->fog_mode = p_mode; env->fog_light_color = p_light_color; env->fog_light_energy = p_light_energy; env->fog_sun_scatter = p_sun_scatter; @@ -225,6 +226,12 @@ bool RendererEnvironmentStorage::environment_get_fog_enabled(RID p_env) const { return env->fog_enabled; } +RS::EnvironmentFogMode RendererEnvironmentStorage::environment_get_fog_mode(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_NULL_V(env, RS::ENV_FOG_MODE_EXPONENTIAL); + return env->fog_mode; +} + Color RendererEnvironmentStorage::environment_get_fog_light_color(RID p_env) const { Environment *env = environment_owner.get_or_null(p_env); ERR_FAIL_NULL_V(env, Color(0.5, 0.6, 0.7)); @@ -273,6 +280,34 @@ float RendererEnvironmentStorage::environment_get_fog_sky_affect(RID p_env) cons return env->fog_sky_affect; } +// Depth Fog + +void RendererEnvironmentStorage::environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_NULL(env); + env->fog_depth_curve = p_curve; + env->fog_depth_begin = p_begin; + env->fog_depth_end = p_end; +} + +float RendererEnvironmentStorage::environment_get_fog_depth_curve(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_NULL_V(env, 0.0); + return env->fog_depth_curve; +} + +float RendererEnvironmentStorage::environment_get_fog_depth_begin(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_NULL_V(env, 0.0); + return env->fog_depth_begin; +} + +float RendererEnvironmentStorage::environment_get_fog_depth_end(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_NULL_V(env, 0.0); + return env->fog_depth_end; +} + // Volumetric Fog void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) { diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h index d677dfc57b0d..c077e093daa7 100644 --- a/servers/rendering/storage/environment_storage.h +++ b/servers/rendering/storage/environment_storage.h @@ -62,6 +62,7 @@ class RendererEnvironmentStorage { // Fog bool fog_enabled = false; + RS::EnvironmentFogMode fog_mode = RS::EnvironmentFogMode::ENV_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; @@ -71,6 +72,11 @@ class RendererEnvironmentStorage { float fog_height_density = 0.0; //can be negative to invert effect float fog_aerial_perspective = 0.0; + // Depth Fog + float fog_depth_curve = 1.0; + float fog_depth_begin = 10.0; + float fog_depth_end = 100.0; + // Volumetric Fog bool volumetric_fog_enabled = false; float volumetric_fog_density = 0.01; @@ -192,8 +198,9 @@ class RendererEnvironmentStorage { float environment_get_white(RID p_env) const; // Fog - 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_sky_affect); + 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_sky_affect, RS::EnvironmentFogMode p_mode); bool environment_get_fog_enabled(RID p_env) const; + RS::EnvironmentFogMode environment_get_fog_mode(RID p_env) const; Color environment_get_fog_light_color(RID p_env) const; float environment_get_fog_light_energy(RID p_env) const; float environment_get_fog_sun_scatter(RID p_env) const; @@ -203,6 +210,12 @@ class RendererEnvironmentStorage { float environment_get_fog_height_density(RID p_env) const; float environment_get_fog_aerial_perspective(RID p_env) const; + // Depth Fog + void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end); + float environment_get_fog_depth_curve(RID p_env) const; + float environment_get_fog_depth_begin(RID p_env) const; + float environment_get_fog_depth_end(RID p_env) const; + // Volumetric Fog void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect); bool environment_get_volumetric_fog_enabled(RID p_env) const; diff --git a/servers/rendering_server.compat.inc b/servers/rendering_server.compat.inc new file mode 100644 index 000000000000..0cef3c906cb3 --- /dev/null +++ b/servers/rendering_server.compat.inc @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* rendering_server.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +void RenderingServer::_environment_set_fog_bind_compat_84792(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_sky_affect) { + environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL); +} + +void RenderingServer::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792); +} + +#endif diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index d03f8113f879..655b748d3f7b 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "rendering_server.h" +#include "rendering_server.compat.inc" #include "core/config/project_settings.h" #include "core/object/worker_thread_pool.h" @@ -2943,7 +2944,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment); ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr); ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao); - ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::environment_set_fog); + ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect", "fog_mode"), &RenderingServer::environment_set_fog, DEFVAL(RS::ENV_FOG_MODE_EXPONENTIAL)); ClassDB::bind_method(D_METHOD("environment_set_sdfgi", "env", "enable", "cascades", "min_cell_size", "y_scale", "use_occlusion", "bounce_feedback", "read_sky", "energy", "normal_bias", "probe_bias"), &RenderingServer::environment_set_sdfgi); ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject", "sky_affect"), &RenderingServer::environment_set_volumetric_fog); @@ -2986,6 +2987,9 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_REPLACE); BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_MIX); + BIND_ENUM_CONSTANT(ENV_FOG_MODE_EXPONENTIAL); + BIND_ENUM_CONSTANT(ENV_FOG_MODE_DEPTH); + BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_LINEAR); BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_REINHARD); BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_FILMIC); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 19b6c35339da..6b00213440d6 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -71,6 +71,11 @@ class RenderingServer : public Object { static RenderingServer *(*create_func)(); static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + void _environment_set_fog_bind_compat_84792(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_sky_affect); + static void _bind_compatibility_methods(); +#endif + public: static RenderingServer *get_singleton(); static RenderingServer *create(); @@ -1178,7 +1183,13 @@ class RenderingServer : public Object { virtual void environment_set_sdfgi_frames_to_update_light(EnvironmentSDFGIFramesToUpdateLight p_update) = 0; - 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_sky_affect) = 0; + enum EnvironmentFogMode { + ENV_FOG_MODE_EXPONENTIAL, + ENV_FOG_MODE_DEPTH, + }; + + 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_sky_affect, EnvironmentFogMode p_mode = EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL) = 0; + virtual void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) = 0; virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0; virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0; @@ -1730,6 +1741,7 @@ VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG); VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource); VARIANT_ENUM_CAST(RenderingServer::EnvironmentReflectionSource); VARIANT_ENUM_CAST(RenderingServer::EnvironmentGlowBlendMode); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentFogMode); VARIANT_ENUM_CAST(RenderingServer::EnvironmentToneMapper); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSRRoughnessQuality); VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSAOQuality);