Fix sampling bug when SSAO is using half size

This commit is contained in:
clayjohn 2023-02-16 00:16:35 -08:00
parent f2aae8fa5c
commit c9c14410e9
2 changed files with 24 additions and 23 deletions

View File

@ -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); 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]; float depth_linearize_add = p_projection.columns[2][2];
if (depth_linearize_mul * depth_linearize_add < 0) { if (depth_linearize_mul * depth_linearize_add < 0) {
depth_linearize_add = -depth_linearize_add; 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[0] = p_settings.full_screen_size.x;
ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; 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[0] = 2.0 / p_settings.full_screen_size.x;
ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; 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_x = 1.0 / p_projection.columns[0][0];
float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; 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; 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.z_far = p_projection.get_z_far();
ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); 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; ssil.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f); float radius_near_limit = (p_settings.radius * 1.2f);
if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) { 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; RD::Uniform u_depth_texture_view;
u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u_depth_texture_view.binding = 0; 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); u_depth_texture_view.append_id(depth_texture_view);
RD::Uniform u_normal_buffer; 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[0] = p_settings.full_screen_size.x;
ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; 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[0] = 2.0 / p_settings.full_screen_size.x;
ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; 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_x = 1.0 / p_projection.columns[0][0];
float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; 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; 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.NDC_to_view_add[1] = tan_half_fov_y;
ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); 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; ssao.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f); float radius_near_limit = (p_settings.radius * 1.2f);
if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) { 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; RD::Uniform u_depth_texture_view;
u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u_depth_texture_view.binding = 0; 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); u_depth_texture_view.append_id(depth_texture_view);
RD::Uniform u_normal_buffer; RD::Uniform u_normal_buffer;

View File

@ -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; still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y;
p_output_coord /= 2; p_output_coord /= 2;
groupMemoryBarrier();
barrier();
if (still_alive) { 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_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]; imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(sample_00));
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));
} }
#endif #endif
} }
@ -190,6 +184,7 @@ void prepare_depths(vec4 p_samples, uvec2 p_tid) {
void main() { void main() {
#ifdef USE_HALF_BUFFERS #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 #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_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; 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; vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size;
vec4 samples = textureGather(source_depth, uv); vec4 samples = textureGather(source_depth, uv);
#endif #endif //USE_HALF_SIZE
#ifdef GENERATE_MIPS #ifdef GENERATE_MIPS
prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy); prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy);
#else #else
prepare_depths(samples, gl_GlobalInvocationID.xy); prepare_depths(samples, gl_GlobalInvocationID.xy);
#endif #endif
#endif #endif //USE_HALF_BUFFERS
} }