Fix volumetric fog in stereo by projection vertex in combined space

This commit is contained in:
Bastiaan Olij 2023-06-19 22:39:46 +10:00
parent 116f783db7
commit 66272ea26e
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
}
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::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<RenderSceneBuffersRD> 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;

View File

@ -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<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_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);

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;