From 66272ea26e8a305cad4d658cc722961673aaf4ea Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Mon, 19 Jun 2023 22:39:46 +1000 Subject: [PATCH] Fix volumetric fog in stereo by projection vertex in combined space --- .../rendering/renderer_rd/environment/sky.cpp | 14 ++++++-- .../rendering/renderer_rd/environment/sky.h | 35 ++++++++++--------- .../render_forward_clustered.cpp | 4 +-- .../forward_mobile/render_forward_mobile.cpp | 4 +-- .../renderer_rd/shaders/environment/sky.glsl | 6 ++++ .../scene_forward_clustered.glsl | 12 +++++++ 6 files changed, 51 insertions(+), 24 deletions(-) diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index f79d6d311e9..d7eb0287d86 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1014,7 +1014,7 @@ SkyRD::~SkyRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency } -void SkyRD::setup_sky(RID p_env, Ref p_render_buffers, const PagedArray &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup_sky(RID p_env, Ref p_render_buffers, const PagedArray &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); @@ -1212,11 +1212,19 @@ void SkyRD::setup_sky(RID p_env, Ref p_render_buffers, con sky_scene_state.view_count = p_view_count; sky_scene_state.cam_transform = p_cam_transform; - sky_scene_state.cam_projection = p_view_projections[0]; // We only use this when rendering a single view + sky_scene_state.cam_projection = p_cam_projection; // We only use this when rendering a single view // Our info in our UBO is only used if we're rendering stereo for (uint32_t i = 0; i < p_view_count; i++) { - RendererRD::MaterialStorage::store_camera(p_view_projections[i].inverse(), sky_scene_state.ubo.view_inv_projections[i]); + Projection view_inv_projection = p_view_projections[i].inverse(); + if (p_view_count > 1) { + RendererRD::MaterialStorage::store_camera(p_cam_projection * view_inv_projection, sky_scene_state.ubo.combined_reprojection[i]); + } else { + Projection ident; + RendererRD::MaterialStorage::store_camera(ident, sky_scene_state.ubo.combined_reprojection[i]); + } + + RendererRD::MaterialStorage::store_camera(view_inv_projection, sky_scene_state.ubo.view_inv_projections[i]); sky_scene_state.ubo.view_eye_offsets[i][0] = p_view_eye_offsets[i].x; sky_scene_state.ubo.view_eye_offsets[i][1] = p_view_eye_offsets[i].y; sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z; diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index 4ace59dfa56..afc6274886c 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -139,26 +139,27 @@ private: public: struct SkySceneState { struct UBO { - float view_inv_projections[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128 - float view_eye_offsets[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 160 + float combined_reprojection[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128 + float view_inv_projections[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 256 + float view_eye_offsets[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 288 - uint32_t volumetric_fog_enabled; // 4 - 164 - float volumetric_fog_inv_length; // 4 - 168 - float volumetric_fog_detail_spread; // 4 - 172 - float volumetric_fog_sky_affect; // 4 - 176 + uint32_t volumetric_fog_enabled; // 4 - 292 + float volumetric_fog_inv_length; // 4 - 296 + float volumetric_fog_detail_spread; // 4 - 300 + float volumetric_fog_sky_affect; // 4 - 304 - uint32_t fog_enabled; // 4 - 180 - float fog_sky_affect; // 4 - 184 - float fog_density; // 4 - 188 - float fog_sun_scatter; // 4 - 192 + uint32_t fog_enabled; // 4 - 308 + float fog_sky_affect; // 4 - 312 + float fog_density; // 4 - 316 + float fog_sun_scatter; // 4 - 320 - float fog_light_color[3]; // 12 - 204 - float fog_aerial_perspective; // 4 - 208 + float fog_light_color[3]; // 12 - 332 + float fog_aerial_perspective; // 4 - 336 - float z_far; // 4 - 212 - uint32_t directional_light_count; // 4 - 216 - uint32_t pad1; // 4 - 220 - uint32_t pad2; // 4 - 224 + float z_far; // 4 - 340 + uint32_t directional_light_count; // 4 - 344 + uint32_t pad1; // 4 - 348 + uint32_t pad2; // 4 - 352 }; UBO ubo; @@ -295,7 +296,7 @@ public: void set_texture_format(RD::DataFormat p_texture_format); ~SkyRD(); - void setup_sky(RID p_env, Ref p_render_buffers, const PagedArray &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void setup_sky(RID p_env, Ref p_render_buffers, const PagedArray &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); void update_radiance_buffers(Ref p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0); void update_res_buffers(Ref p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0); void draw_sky(RD::DrawListID p_draw_list, Ref p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0); 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 4f47a80c13d..4b25f516594 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1800,9 +1800,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co correction.set_depth_correction(true); Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, this); } else { - sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, this); } sky_energy_multiplier *= bg_energy_multiplier; 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 77dd39b8d92..d2b7ef35063 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -856,9 +856,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color correction.set_depth_correction(true); Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, this); } else { - sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, this); } sky_energy_multiplier *= bg_energy_multiplier; diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 01301e21875..b38aa0ad759 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -83,6 +83,7 @@ layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUnifor global_shader_uniforms; layout(set = 0, binding = 2, std140) uniform SkySceneData { + mat4 combined_reprojection[2]; mat4 view_inv_projections[2]; vec4 view_eye_offsets[2]; @@ -169,7 +170,12 @@ vec3 interleaved_gradient_noise(vec2 pos) { #endif vec4 volumetric_fog_process(vec2 screen_uv) { +#ifdef USE_MULTIVIEW + vec4 reprojected = sky_scene_data.combined_reprojection[ViewIndex] * (vec4(screen_uv * 2.0 - 1.0, 1.0, 1.0) * sky_scene_data.z_far); + vec3 fog_pos = vec3(reprojected.xy / reprojected.w, 1.0) * 0.5 + 0.5; +#else vec3 fog_pos = vec3(screen_uv, 1.0); +#endif return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos); } 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 269c08c334c..dd78e7a90f6 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 @@ -121,6 +121,7 @@ layout(location = 10) out flat uint instance_index_interp; vec3 multiview_uv(vec2 uv) { return vec3(uv, ViewIndex); } +layout(location = 11) out vec4 combined_projected; #else // USE_MULTIVIEW // Set to zero, not supported in non stereo #define ViewIndex 0 @@ -313,6 +314,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime #endif #ifdef USE_MULTIVIEW + mat4 combined_projection = scene_data.projection_matrix; mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; @@ -434,6 +436,10 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime gl_Position = projection_matrix * vec4(vertex_interp, 1.0); #endif +#ifdef USE_MULTIVIEW + combined_projected = combined_projection * vec4(vertex_interp, 1.0); +#endif + #ifdef MOTION_VECTORS screen_pos = gl_Position; #endif @@ -557,6 +563,7 @@ layout(location = 10) in flat uint instance_index_interp; vec3 multiview_uv(vec2 uv) { return vec3(uv, ViewIndex); } +layout(location = 11) in vec4 combined_projected; #else // USE_MULTIVIEW // Set to zero, not supported in non stereo #define ViewIndex 0 @@ -913,7 +920,12 @@ void fragment_shader(in SceneData scene_data) { } if (implementation_data.volumetric_fog_enabled) { +#ifdef USE_MULTIVIEW + vec2 center_uv = (combined_projected.xy / combined_projected.w) * 0.5 + 0.5; + vec4 volumetric_fog = volumetric_fog_process(center_uv, -vertex.z); +#else vec4 volumetric_fog = volumetric_fog_process(screen_uv, -vertex.z); +#endif if (scene_data.fog_enabled) { //must use the full blending equation here to blend fogs vec4 res;