diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index c4a89996b5f0..b06cb8f39d5f 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -1307,24 +1307,24 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) { push_constant.store_ambient_texture = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_enabled(p_env); RID sky_uniform_set = gi->sdfgi_shader.integrate_default_sky_uniform_set; - push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_DISABLED; + push_constant.sky_flags = 0; push_constant.y_mult = y_mult; if (reads_sky && p_env.is_valid()) { push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy_multiplier(p_env); if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) { - push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; + push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_MODE_COLOR; Color c = RSG::texture_storage->get_default_clear_color().srgb_to_linear(); - push_constant.sky_color[0] = c.r; - push_constant.sky_color[1] = c.g; - push_constant.sky_color[2] = c.b; + push_constant.sky_color_or_orientation[0] = c.r; + push_constant.sky_color_or_orientation[1] = c.g; + push_constant.sky_color_or_orientation[2] = c.b; } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_COLOR) { - push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; + push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_MODE_COLOR; Color c = RendererSceneRenderRD::get_singleton()->environment_get_bg_color(p_env); - push_constant.sky_color[0] = c.r; - push_constant.sky_color[1] = c.g; - push_constant.sky_color[2] = c.b; + push_constant.sky_color_or_orientation[0] = c.r; + push_constant.sky_color_or_orientation[1] = c.g; + push_constant.sky_color_or_orientation[2] = c.b; } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_SKY) { if (p_sky && p_sky->radiance.is_valid()) { @@ -1350,7 +1350,16 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) { integrate_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 1); } sky_uniform_set = integrate_sky_uniform_set; - push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_SKY; + push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_MODE_SKY; + + // Encode sky orientation as quaternion in existing push constants. + const Basis sky_basis = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); + const Quaternion sky_quaternion = sky_basis.get_quaternion().inverse(); + push_constant.sky_color_or_orientation[0] = sky_quaternion.x; + push_constant.sky_color_or_orientation[1] = sky_quaternion.y; + push_constant.sky_color_or_orientation[2] = sky_quaternion.z; + // Ideally we would reconstruct the largest component for least error, but sky contribution to GI is low frequency so just needs to get the idea across. + push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_ORIENTATION_SIGN * (sky_quaternion.w < 0.0 ? 0 : 1); } } } @@ -1396,7 +1405,7 @@ void GI::SDFGI::store_probes() { push_constant.image_size[1] = probe_axis_count; push_constant.store_ambient_texture = false; - push_constant.sky_mode = 0; + push_constant.sky_flags = 0; push_constant.y_mult = y_mult; // Then store values into the lightprobe texture. Separating these steps has a small performance hit, but it allows for multiple bounces @@ -2092,11 +2101,11 @@ void GI::SDFGI::render_region(Ref p_render_buffers, int p_ ipush_constant.history_size = history_size; ipush_constant.ray_count = 0; ipush_constant.ray_bias = 0; - ipush_constant.sky_mode = 0; + ipush_constant.sky_flags = 0; ipush_constant.sky_energy = 0; - ipush_constant.sky_color[0] = 0; - ipush_constant.sky_color[1] = 0; - ipush_constant.sky_color[2] = 0; + ipush_constant.sky_color_or_orientation[0] = 0; + ipush_constant.sky_color_or_orientation[1] = 0; + ipush_constant.sky_color_or_orientation[2] = 0; ipush_constant.y_mult = y_mult; ipush_constant.store_ambient_texture = false; diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index f34bbde6f044..81a06a26f1d6 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -392,9 +392,9 @@ class GI : public RendererGI { }; struct IntegratePushConstant { enum { - SKY_MODE_DISABLED, - SKY_MODE_COLOR, - SKY_MODE_SKY, + SKY_FLAGS_MODE_COLOR = 0x01, + SKY_FLAGS_MODE_SKY = 0x02, + SKY_FLAGS_ORIENTATION_SIGN = 0x04, }; float grid_size[3]; @@ -410,12 +410,12 @@ class GI : public RendererGI { int32_t image_size[2]; int32_t world_offset[3]; - uint32_t sky_mode; + uint32_t sky_flags; int32_t scroll[3]; float sky_energy; - float sky_color[3]; + float sky_color_or_orientation[3]; float y_mult; uint32_t store_ambient_texture; diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl index 4bdb0dcc722c..aaaa7dfb4318 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl @@ -49,9 +49,9 @@ layout(set = 1, binding = 1) uniform sampler linear_sampler_mipmaps; #define HISTORY_BITS 10 -#define SKY_MODE_DISABLED 0 -#define SKY_MODE_COLOR 1 -#define SKY_MODE_SKY 2 +#define SKY_FLAGS_MODE_COLOR 0x01 +#define SKY_FLAGS_MODE_SKY 0x02 +#define SKY_FLAGS_ORIENTATION_SIGN 0x04 layout(push_constant, std430) uniform Params { vec3 grid_size; @@ -67,12 +67,12 @@ layout(push_constant, std430) uniform Params { ivec2 image_size; ivec3 world_offset; - uint sky_mode; + uint sky_flags; ivec3 scroll; float sky_energy; - vec3 sky_color; + vec3 sky_color_or_orientation; float y_mult; bool store_ambient_texture; @@ -265,17 +265,22 @@ void main() { } } - } else if (params.sky_mode == SKY_MODE_SKY) { + } else if (bool(params.sky_flags & SKY_FLAGS_MODE_SKY)) { + // Reconstruct sky orientation as quaternion and rotate ray_dir before sampling. + float sky_sign = bool(params.sky_flags & SKY_FLAGS_ORIENTATION_SIGN) ? 1.0 : -1.0; + vec4 sky_quat = vec4(params.sky_color_or_orientation, sky_sign * sqrt(1.0 - dot(params.sky_color_or_orientation, params.sky_color_or_orientation))); + vec3 sky_dir = cross(sky_quat.xyz, ray_dir); + sky_dir = ray_dir + ((sky_dir * sky_quat.w) + cross(sky_quat.xyz, sky_dir)) * 2.0; #ifdef USE_CUBEMAP_ARRAY - light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates. + light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(sky_dir, 0.0), 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates. #else - light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates. + light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), sky_dir, 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates. #endif light.rgb *= params.sky_energy; light.a = 0.0; - } else if (params.sky_mode == SKY_MODE_COLOR) { - light.rgb = params.sky_color; + } else if (bool(params.sky_flags & SKY_FLAGS_MODE_COLOR)) { + light.rgb = params.sky_color_or_orientation; light.rgb *= params.sky_energy; light.a = 0.0; } else {