Browse Source

Fix volumetric fog in stereo by projection vertex in combined space

Bastiaan Olij 2 years ago
parent
commit
66272ea26e

+ 11 - 3
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<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;

+ 22 - 21
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
-
-			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 fog_enabled; // 4 - 180
-			float fog_sky_affect; // 4 - 184
-			float fog_density; // 4 - 188
-			float fog_sun_scatter; // 4 - 192
-
-			float fog_light_color[3]; // 12 - 204
-			float fog_aerial_perspective; // 4 - 208
-
-			float z_far; // 4 - 212
-			uint32_t directional_light_count; // 4 - 216
-			uint32_t pad1; // 4 - 220
-			uint32_t pad2; // 4 - 224
+			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 - 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 - 308
+			float fog_sky_affect; // 4 - 312
+			float fog_density; // 4 - 316
+			float fog_sun_scatter; // 4 - 320
+
+			float fog_light_color[3]; // 12 - 332
+			float fog_aerial_perspective; // 4 - 336
+
+			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);

+ 2 - 2
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;

+ 2 - 2
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;

+ 6 - 0
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);
 }

+ 12 - 0
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;