Browse Source

Fix sampling bug when SSAO is using half size

clayjohn 2 years ago
parent
commit
c9c14410e9

+ 19 - 13
servers/rendering/renderer_rd/effects/ss_effects.cpp

@@ -484,7 +484,7 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin
 		downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);
 	}
 
-	float depth_linearize_mul = -p_projection.columns[3][2];
+	float depth_linearize_mul = -p_projection.columns[3][2] * 0.5;
 	float depth_linearize_add = p_projection.columns[2][2];
 	if (depth_linearize_mul * depth_linearize_add < 0) {
 		depth_linearize_add = -depth_linearize_add;
@@ -668,8 +668,14 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
 		ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
 		ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
 
-		ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
-		ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+		ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
+		ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
+		if (ssil_half_size) {
+			ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
+			ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
+		}
+		ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75;
+		ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75;
 		float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
 		float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
 		ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
@@ -680,9 +686,6 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
 		ssil.gather_push_constant.z_far = p_projection.get_z_far();
 		ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
 
-		ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
-		ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
 		ssil.gather_push_constant.radius = p_settings.radius;
 		float radius_near_limit = (p_settings.radius * 1.2f);
 		if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {
@@ -733,7 +736,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
 			RD::Uniform u_depth_texture_view;
 			u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 			u_depth_texture_view.binding = 0;
-			u_depth_texture_view.append_id(default_sampler);
+			u_depth_texture_view.append_id(ss_effects.mirror_sampler);
 			u_depth_texture_view.append_id(depth_texture_view);
 
 			RD::Uniform u_normal_buffer;
@@ -1056,8 +1059,14 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
 		ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
 		ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
 
-		ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
-		ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+		ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
+		ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
+		if (ssao_half_size) {
+			ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
+			ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
+		}
+		ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75;
+		ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75;
 		float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
 		float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
 		ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
@@ -1066,9 +1075,6 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
 		ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
 		ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
 
-		ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
-		ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
 		ssao.gather_push_constant.radius = p_settings.radius;
 		float radius_near_limit = (p_settings.radius * 1.2f);
 		if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {
@@ -1105,7 +1111,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
 			RD::Uniform u_depth_texture_view;
 			u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 			u_depth_texture_view.binding = 0;
-			u_depth_texture_view.append_id(default_sampler);
+			u_depth_texture_view.append_id(ss_effects.mirror_sampler);
 			u_depth_texture_view.append_id(depth_texture_view);
 
 			RD::Uniform u_normal_buffer;

+ 5 - 10
servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl

@@ -161,17 +161,11 @@ void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid)
 	still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y;
 
 	p_output_coord /= 2;
-	groupMemoryBarrier();
-	barrier();
 
 	if (still_alive) {
+		// Use the previous average, not ideal, but still not bad.
 		float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0];
-		float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 8];
-		float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 0];
-		float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 8];
-
-		float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11));
-		imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg));
+		imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(sample_00));
 	}
 #endif
 }
@@ -190,6 +184,7 @@ void prepare_depths(vec4 p_samples, uvec2 p_tid) {
 
 void main() {
 #ifdef USE_HALF_BUFFERS
+// Half buffers means that we divide depth into two half res buffers (we only capture 1/4 of pixels).
 #ifdef USE_HALF_SIZE
 	float sample_00 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 0, 4 * gl_GlobalInvocationID.y + 0), 0).x;
 	float sample_11 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 2, 4 * gl_GlobalInvocationID.y + 2), 0).x;
@@ -219,11 +214,11 @@ void main() {
 
 	vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size;
 	vec4 samples = textureGather(source_depth, uv);
-#endif
+#endif //USE_HALF_SIZE
 #ifdef GENERATE_MIPS
 	prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy);
 #else
 	prepare_depths(samples, gl_GlobalInvocationID.xy);
 #endif
-#endif
+#endif //USE_HALF_BUFFERS
 }