diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 84b6ab4bd8b..2565e610f79 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -777,7 +777,6 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, ERR_FAIL_COND(p_env.is_null()); Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); - ERR_FAIL_NULL(sky); GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; @@ -851,6 +850,15 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::SKY_ENERGY_MULTIPLIER, p_sky_energy_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + Color fog_color = environment_get_fog_light_color(p_env).srgb_to_linear() * environment_get_fog_light_energy(p_env); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_ENABLED, environment_get_fog_enabled(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_AERIAL_PERSPECTIVE, environment_get_fog_aerial_perspective(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_LIGHT_COLOR, fog_color, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_SUN_SCATTER, environment_get_fog_sun_scatter(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_DENSITY, environment_get_fog_density(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_SKY_AFFECT, environment_get_fog_sky_affect(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::DIRECTIONAL_LIGHT_COUNT, sky_globals.directional_light_count, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + if (p_use_multiview) { glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -2587,7 +2595,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ scene_state.enable_gl_depth_draw(false); - if (draw_sky) { + if (draw_sky || draw_sky_fog_only) { RENDER_TIMESTAMP("Render Sky"); scene_state.enable_gl_depth_test(true); diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 9de65ba960d..f734e4b3554 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -108,11 +108,11 @@ uniform float sky_energy_multiplier; uniform float luminance_multiplier; uniform float fog_aerial_perspective; -uniform vec3 fog_light_color; +uniform vec4 fog_light_color; uniform float fog_sun_scatter; uniform bool fog_enabled; uniform float fog_density; -uniform float z_far; +uniform float fog_sky_affect; uniform uint directional_light_count; #ifdef USE_MULTIVIEW @@ -135,6 +135,24 @@ vec3 interleaved_gradient_noise(vec2 pos) { } #endif +#if !defined(DISABLE_FOG) +vec4 fog_process(vec3 view, vec3 sky_color) { + vec3 fog_color = mix(fog_light_color.rgb, sky_color, fog_aerial_perspective); + + if (fog_sun_scatter > 0.001) { + vec4 sun_scatter = vec4(0.0); + float sun_total = 0.0; + for (uint i = 0u; i < directional_light_count; i++) { + vec3 light_color = directional_lights.data[i].color_size.xyz * directional_lights.data[i].direction_energy.w; + float light_amount = pow(max(dot(view, directional_lights.data[i].direction_energy.xyz), 0.0), 8.0); + fog_color += light_color * light_amount * fog_sun_scatter; + } + } + + return vec4(fog_color, 1.0); +} +#endif // !DISABLE_FOG + void main() { vec3 cube_normal; #ifdef USE_MULTIVIEW @@ -203,6 +221,21 @@ void main() { // Convert to Linear for tonemapping so color matches scene shader better color = srgb_to_linear(color); + +#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS) + + // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. + if (fog_enabled) { + vec4 fog = fog_process(cube_normal, color.rgb); + color.rgb = mix(color.rgb, fog.rgb, fog.a * fog_sky_affect); + } + + if (custom_fog.a > 0.0) { + color.rgb = mix(color.rgb, custom_fog.rgb, custom_fog.a); + } + +#endif // DISABLE_FOG + color *= exposure; #ifdef APPLY_TONEMAPPING color = apply_tonemapping(color, white); diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 35457a24821..5aa37354948 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -255,10 +255,6 @@ void main() { frag_color.rgb = color; frag_color.a = alpha; - // For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer. - // For both mobile and clustered, we also bake in the exposure value for the environment and camera. - frag_color.rgb = frag_color.rgb * params.luminance_multiplier; - #if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS) // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. @@ -278,6 +274,10 @@ void main() { #endif // DISABLE_FOG + // For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer. + // For both mobile and clustered, we also bake in the exposure value for the environment and camera. + frag_color.rgb = frag_color.rgb * params.luminance_multiplier; + // Blending is disabled for Sky, so alpha doesn't blend. // Alpha is used for subsurface scattering so make sure it doesn't get applied to Sky. if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {