diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index 1cc2976c81f..2246e308176 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -176,6 +176,9 @@ If [code]true[/code], the object receives no ambient light. + + If [code]true[/code], the object will not be affected by fog (neither volumetric nor depth fog). This is useful for unshaded or transparent materials (e.g. particles), which without this setting will be affected even if fully transparent. + If [code]true[/code], the object receives no shadow that would otherwise be cast onto it. @@ -697,7 +700,10 @@ Enables multichannel signed distance field rendering shader. - + + Disables receiving depth-based or volumetric fog. + + Represents the size of the [enum Flags] enum. diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 7cba77be2ff..8d3eabc55bc 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -962,7 +962,9 @@ void main() { float clearcoat_roughness = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); +#ifndef FOG_DISABLED vec4 fog = vec4(0.0); +#endif // !FOG_DISABLED #if defined(CUSTOM_RADIANCE_USED) vec4 custom_radiance = vec4(0.0); #endif @@ -1075,6 +1077,7 @@ void main() { #ifndef MODE_RENDER_DEPTH +#ifndef FOG_DISABLED #ifndef CUSTOM_FOG_USED #ifndef DISABLE_FOG // fog must be processed as early as possible and then packed. @@ -1088,6 +1091,7 @@ void main() { uint fog_rg = packHalf2x16(fog.rg); uint fog_ba = packHalf2x16(fog.ba); +#endif // !FOG_DISABLED // Convert colors to linear albedo = srgb_to_linear(albedo); @@ -1300,6 +1304,8 @@ void main() { frag_color.rgb += emission + ambient_light; #endif #endif //MODE_UNSHADED + +#ifndef FOG_DISABLED fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba)); #ifndef DISABLE_FOG @@ -1310,7 +1316,8 @@ void main() { frag_color.rgb *= (1.0 - fog.a); #endif // BASE_PASS } -#endif +#endif // !DISABLE_FOG +#endif // !FOG_DISABLED // Tonemap before writing as we are writing to an sRGB framebuffer frag_color.rgb *= exposure; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index a36004209bb..32b62ee6056 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1358,6 +1358,7 @@ MaterialStorage::MaterialStorage() { actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; + actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n"; actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 65da0bc3c8a..39b3acfe3fa 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -777,6 +777,9 @@ void BaseMaterial3D::_update_shader() { if (flags[FLAG_USE_SHADOW_TO_OPACITY]) { code += ",shadow_to_opacity"; } + if (flags[FLAG_DISABLE_FOG]) { + code += ",fog_disabled"; + } if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) { code += ",depth_prepass_alpha"; @@ -2725,6 +2728,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Toon"), "set_diffuse_mode", "get_diffuse_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Toon,Disabled"), "set_specular_mode", "get_specular_mode"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_fog"), "set_flag", "get_flag", FLAG_DISABLE_FOG); ADD_GROUP("Vertex Color", "vertex_color"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); @@ -2977,6 +2981,7 @@ void BaseMaterial3D::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_SUBSURFACE_MODE_SKIN); BIND_ENUM_CONSTANT(FLAG_PARTICLE_TRAILS_MODE); BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_MSDF); + BIND_ENUM_CONSTANT(FLAG_DISABLE_FOG); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); diff --git a/scene/resources/material.h b/scene/resources/material.h index 28ceb1f1194..18fbc02a129 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -256,6 +256,7 @@ public: FLAG_SUBSURFACE_MODE_SKIN, FLAG_PARTICLE_TRAILS_MODE, FLAG_ALBEDO_TEXTURE_MSDF, + FLAG_DISABLE_FOG, FLAG_MAX }; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 12f8f6a366c..509072bbece 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -707,6 +707,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n"; + actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n"; actions.base_texture_binding_index = 1; actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 32d2289f75c..ffbe7f7e596 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -610,6 +610,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n"; + actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n"; actions.base_texture_binding_index = 1; actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET; 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 8f3c704afeb..cfba408fe12 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 @@ -802,7 +802,9 @@ void fragment_shader(in SceneData scene_data) { float clearcoat_roughness = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); +#ifndef FOG_DISABLED vec4 fog = vec4(0.0); +#endif // !FOG_DISABLED #if defined(CUSTOM_RADIANCE_USED) vec4 custom_radiance = vec4(0.0); #endif @@ -962,6 +964,7 @@ void fragment_shader(in SceneData scene_data) { /////////////////////// FOG ////////////////////// #ifndef MODE_RENDER_DEPTH +#ifndef FOG_DISABLED #ifndef CUSTOM_FOG_USED // fog must be processed as early as possible and then packed. // to maximize VGPR usage @@ -997,6 +1000,7 @@ void fragment_shader(in SceneData scene_data) { uint fog_rg = packHalf2x16(fog.rg); uint fog_ba = packHalf2x16(fog.ba); +#endif //!FOG_DISABLED #endif //!MODE_RENDER_DEPTH /////////////////////// DECALS //////////////////////////////// @@ -2250,8 +2254,10 @@ void fragment_shader(in SceneData scene_data) { diffuse_light *= 1.0 - metallic; ambient_light *= 1.0 - metallic; +#ifndef FOG_DISABLED //restore fog fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba)); +#endif //!FOG_DISABLED #ifdef MODE_SEPARATE_SPECULAR @@ -2268,8 +2274,10 @@ void fragment_shader(in SceneData scene_data) { specular_buffer = vec4(specular_light, metallic); #endif +#ifndef FOG_DISABLED diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a); specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a); +#endif //!FOG_DISABLED #else //MODE_SEPARATE_SPECULAR @@ -2280,8 +2288,10 @@ void fragment_shader(in SceneData scene_data) { //frag_color = vec4(1.0); #endif //USE_NO_SHADING +#ifndef FOG_DISABLED // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); +#endif //!FOG_DISABLED #endif //MODE_SEPARATE_SPECULAR 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 0283482d76f..cdf81bb6ece 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 @@ -694,7 +694,9 @@ void main() { float clearcoat_roughness = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); +#ifndef FOG_DISABLED vec4 fog = vec4(0.0); +#endif // !FOG_DISABLED #if defined(CUSTOM_RADIANCE_USED) vec4 custom_radiance = vec4(0.0); #endif @@ -860,6 +862,7 @@ void main() { /////////////////////// FOG ////////////////////// #ifndef MODE_RENDER_DEPTH +#ifndef FOG_DISABLED #ifndef CUSTOM_FOG_USED // fog must be processed as early as possible and then packed. // to maximize VGPR usage @@ -874,6 +877,7 @@ void main() { uint fog_rg = packHalf2x16(fog.rg); uint fog_ba = packHalf2x16(fog.ba); +#endif //!FOG_DISABLED #endif //!MODE_RENDER_DEPTH /////////////////////// DECALS //////////////////////////////// @@ -1744,8 +1748,10 @@ void main() { diffuse_light *= 1.0 - metallic; ambient_light *= 1.0 - metallic; +#ifndef FOG_DISABLED //restore fog fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba)); +#endif // !FOG_DISABLED #ifdef MODE_MULTIPLE_RENDER_TARGETS @@ -1762,8 +1768,10 @@ void main() { specular_buffer = vec4(specular_light, metallic); #endif // MODE_UNSHADED +#ifndef FOG_DISABLED diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a); specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a); +#endif // !FOG_DISABLED #else //MODE_MULTIPLE_RENDER_TARGETS @@ -1773,8 +1781,10 @@ void main() { frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); #endif // MODE_UNSHADED +#ifndef FOG_DISABLED // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); +#endif // !FOG_DISABLED // On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking // We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index c256d373440..728089f5162 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -227,6 +227,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("alpha_to_coverage") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("alpha_to_coverage_and_one") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("debug_shadow_splits") }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("fog_disabled") }); } /************ CANVAS ITEM **************************/