From d09ad714bfa28df82adbbd4e5bf18a69233aae39 Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Sun, 2 Oct 2022 20:08:07 +1100 Subject: Fixing artifacts in SSR --- .../rendering/renderer_rd/effects/ss_effects.cpp | 38 ++++++++++++++++++---- servers/rendering/renderer_rd/effects/ss_effects.h | 3 ++ .../forward_clustered/render_forward_clustered.cpp | 5 ++- .../shaders/effects/screen_space_reflection.glsl | 34 ++++++++++++++----- 4 files changed, 61 insertions(+), 19 deletions(-) (limited to 'servers/rendering/renderer_rd') diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 1cbc52dec3..b48e539823 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -1457,6 +1457,17 @@ void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_q void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count) { // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view. + if (p_ssr_buffers.size != p_screen_size || p_ssr_buffers.roughness_quality != ssr_roughness_quality) { + ssr_free(p_ssr_buffers); + } + + if (p_ssr_buffers.output.is_valid()) { + // already allocated + return; + } + + p_ssr_buffers.size = p_screen_size; + p_ssr_buffers.roughness_quality = ssr_roughness_quality; if (p_ssr_buffers.depth_scaled.is_null()) { RD::TextureFormat tf; @@ -1581,8 +1592,13 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector({ default_sampler, p_normal_roughness_slices[v] })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1); - RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.output_slices[v] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur), 2); + if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.output_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2); + } else { + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.intermediate })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2); + } RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.depth_scaled })); RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector({ p_ssr_buffers.normal_scaled })); @@ -1624,17 +1640,25 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); - RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.output_slices[v] })); - RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector({ p_ssr_buffers.depth_scaled })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_scale_depth), 0); - if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + // read from output slices (our scale wrote into these) + RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.output_slices[v] })); + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector({ p_ssr_buffers.depth_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_scale_depth), 0); + + // write to intermediate (our roughness pass will output into output slices) RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.intermediate })); RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector({ p_ssr_buffers.blur_radius[0] })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1); } else { + // read from intermediate (our scale wrote into these) RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.intermediate })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1); + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector({ p_ssr_buffers.depth_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0); + + // We are not performing our blur so go directly to output. + RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.output_slices[v] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output), 1); } RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector({ p_ssr_buffers.normal_scaled })); diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h index 7c264b4d76..dfaf3881bb 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.h +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -148,6 +148,9 @@ public: void ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality); struct SSRRenderBuffers { + Size2i size; + RenderingServer::EnvironmentSSRRoughnessQuality roughness_quality = RenderingServer::ENV_SSR_ROUGHNESS_QUALITY_DISABLED; + RID normal_scaled; RID depth_scaled; RID blur_radius[2]; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index c1a7818921..e4bc51bcdb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1500,9 +1500,8 @@ void RenderForwardClustered::_process_ssr(Ref p_render_buf ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment)); Size2i half_size = Size2i(internal_size.x / 2, internal_size.y / 2); - if (rb_data->ss_effects_data.ssr.output.is_null()) { - ss_effects->ssr_allocate_buffers(rb_data->ss_effects_data.ssr, _render_buffers_get_color_format(), half_size, view_count); - } + ss_effects->ssr_allocate_buffers(rb_data->ss_effects_data.ssr, _render_buffers_get_color_format(), half_size, view_count); + RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS]; RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS]; for (uint32_t v = 0; v < view_count; v++) { diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index 9f86643e52..9d8294a7da 100644 --- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -121,7 +121,7 @@ void main() { // clip z and w advance to line advance vec2 line_advance = normalize(line_dir); // down to pixel - float step_size = length(line_advance) / length(line_dir); + float step_size = 1.0 / length(line_dir); float z_advance = z_dir * step_size; // adapt z advance to line advance float w_advance = w_dir * step_size; // adapt w advance to line advance @@ -139,6 +139,14 @@ void main() { float depth; vec2 prev_pos = pos; + if (ivec2(pos + line_advance - 0.5) == ssC) { + // It is possible for rounding to cause our first pixel to check to be the pixel we're reflecting. + // Make sure we skip it + pos += line_advance; + z += z_advance; + w += w_advance; + } + bool found = false; float steps_taken = 0.0; @@ -149,8 +157,8 @@ void main() { w += w_advance; // convert to linear depth - - depth = imageLoad(source_depth, ivec2(pos - 0.5)).r; + ivec2 test_pos = ivec2(pos - 0.5); + depth = imageLoad(source_depth, test_pos).r; if (sc_multiview) { depth = depth * 2.0 - 1.0; depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); @@ -161,13 +169,21 @@ void main() { z_to = z / w; if (depth > z_to) { - // if depth was surpassed - if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far * 0.95) { - // check the depth tolerance and far clip - // check that normal is valid - found = true; + // Test if our ray is hitting the "right" side of the surface, if not we're likely self reflecting and should skip. + vec4 test_normal_roughness = imageLoad(source_normal_roughness, test_pos); + vec3 test_normal = test_normal_roughness.xyz * 2.0 - 1.0; + test_normal = normalize(test_normal); + test_normal.y = -test_normal.y; //because this code reads flipped + + if (dot(ray_dir, test_normal) < 0.001) { + // if depth was surpassed + if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far * 0.95) { + // check the depth tolerance and far clip + // check that normal is valid + found = true; + } + break; } - break; } steps_taken += 1.0; -- cgit v1.2.3