Merge pull request #78436 from BastiaanOlij/fix_stereo_fog

Fix volumetric fog in stereo by projection vertex in combined space
This commit is contained in:
Rémi Verschelde 2023-06-20 09:21:39 +02:00
commit dca1e0bef7
No known key found for this signature in database
GPG key ID: C3336907360768E1
6 changed files with 51 additions and 24 deletions

View file

@ -1014,7 +1014,7 @@ SkyRD::~SkyRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency RD::get_singleton()->free(index_buffer); //array gets freed as dependency
} }
void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &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<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &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::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null()); ERR_FAIL_COND(p_env.is_null());
@ -1212,11 +1212,19 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
sky_scene_state.view_count = p_view_count; sky_scene_state.view_count = p_view_count;
sky_scene_state.cam_transform = p_cam_transform; 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 // Our info in our UBO is only used if we're rendering stereo
for (uint32_t i = 0; i < p_view_count; i++) { 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][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][1] = p_view_eye_offsets[i].y;
sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z; sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z;

View file

@ -139,26 +139,27 @@ private:
public: public:
struct SkySceneState { struct SkySceneState {
struct UBO { struct UBO {
float view_inv_projections[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128 float combined_reprojection[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128
float view_eye_offsets[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 160 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 uint32_t volumetric_fog_enabled; // 4 - 292
float volumetric_fog_inv_length; // 4 - 168 float volumetric_fog_inv_length; // 4 - 296
float volumetric_fog_detail_spread; // 4 - 172 float volumetric_fog_detail_spread; // 4 - 300
float volumetric_fog_sky_affect; // 4 - 176 float volumetric_fog_sky_affect; // 4 - 304
uint32_t fog_enabled; // 4 - 180 uint32_t fog_enabled; // 4 - 308
float fog_sky_affect; // 4 - 184 float fog_sky_affect; // 4 - 312
float fog_density; // 4 - 188 float fog_density; // 4 - 316
float fog_sun_scatter; // 4 - 192 float fog_sun_scatter; // 4 - 320
float fog_light_color[3]; // 12 - 204 float fog_light_color[3]; // 12 - 332
float fog_aerial_perspective; // 4 - 208 float fog_aerial_perspective; // 4 - 336
float z_far; // 4 - 212 float z_far; // 4 - 340
uint32_t directional_light_count; // 4 - 216 uint32_t directional_light_count; // 4 - 344
uint32_t pad1; // 4 - 220 uint32_t pad1; // 4 - 348
uint32_t pad2; // 4 - 224 uint32_t pad2; // 4 - 352
}; };
UBO ubo; UBO ubo;
@ -295,7 +296,7 @@ public:
void set_texture_format(RD::DataFormat p_texture_format); void set_texture_format(RD::DataFormat p_texture_format);
~SkyRD(); ~SkyRD();
void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &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<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &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<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0); void update_radiance_buffers(Ref<RenderSceneBuffersRD> 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<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0); void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0);
void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0); void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0);

View file

@ -1800,9 +1800,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
correction.set_depth_correction(true); correction.set_depth_correction(true);
Projection projection = correction * p_render_data->scene_data->cam_projection; 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 { } 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; sky_energy_multiplier *= bg_energy_multiplier;

View file

@ -856,9 +856,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
correction.set_depth_correction(true); correction.set_depth_correction(true);
Projection projection = correction * p_render_data->scene_data->cam_projection; 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 { } 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; sky_energy_multiplier *= bg_energy_multiplier;

View file

@ -83,6 +83,7 @@ layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUnifor
global_shader_uniforms; global_shader_uniforms;
layout(set = 0, binding = 2, std140) uniform SkySceneData { layout(set = 0, binding = 2, std140) uniform SkySceneData {
mat4 combined_reprojection[2];
mat4 view_inv_projections[2]; mat4 view_inv_projections[2];
vec4 view_eye_offsets[2]; vec4 view_eye_offsets[2];
@ -169,7 +170,12 @@ vec3 interleaved_gradient_noise(vec2 pos) {
#endif #endif
vec4 volumetric_fog_process(vec2 screen_uv) { 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); vec3 fog_pos = vec3(screen_uv, 1.0);
#endif
return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos); return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos);
} }

View file

@ -121,6 +121,7 @@ layout(location = 10) out flat uint instance_index_interp;
vec3 multiview_uv(vec2 uv) { vec3 multiview_uv(vec2 uv) {
return vec3(uv, ViewIndex); return vec3(uv, ViewIndex);
} }
layout(location = 11) out vec4 combined_projected;
#else // USE_MULTIVIEW #else // USE_MULTIVIEW
// Set to zero, not supported in non stereo // Set to zero, not supported in non stereo
#define ViewIndex 0 #define ViewIndex 0
@ -313,6 +314,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime
#endif #endif
#ifdef USE_MULTIVIEW #ifdef USE_MULTIVIEW
mat4 combined_projection = scene_data.projection_matrix;
mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; 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); gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif #endif
#ifdef USE_MULTIVIEW
combined_projected = combined_projection * vec4(vertex_interp, 1.0);
#endif
#ifdef MOTION_VECTORS #ifdef MOTION_VECTORS
screen_pos = gl_Position; screen_pos = gl_Position;
#endif #endif
@ -557,6 +563,7 @@ layout(location = 10) in flat uint instance_index_interp;
vec3 multiview_uv(vec2 uv) { vec3 multiview_uv(vec2 uv) {
return vec3(uv, ViewIndex); return vec3(uv, ViewIndex);
} }
layout(location = 11) in vec4 combined_projected;
#else // USE_MULTIVIEW #else // USE_MULTIVIEW
// Set to zero, not supported in non stereo // Set to zero, not supported in non stereo
#define ViewIndex 0 #define ViewIndex 0
@ -913,7 +920,12 @@ void fragment_shader(in SceneData scene_data) {
} }
if (implementation_data.volumetric_fog_enabled) { 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); vec4 volumetric_fog = volumetric_fog_process(screen_uv, -vertex.z);
#endif
if (scene_data.fog_enabled) { if (scene_data.fog_enabled) {
//must use the full blending equation here to blend fogs //must use the full blending equation here to blend fogs
vec4 res; vec4 res;