EEVEE: ScreenSpaceReflections: Add back multi ray-hitpoint reuse

We now reuse 9 hitpoints from the neighboorhood using a blue noise
sample distribution as mentionned in the reference presentation.

Reusing more rays does however make some area a bit more blury.

The resulting noise is quite lower compared to previous implementation
which was only reusing 4 hits.
This commit is contained in:
Clément Foucault 2021-03-13 11:44:46 +01:00
parent b79f209041
commit 267a9e14f5
Notes: blender-bot 2023-02-14 09:29:42 +01:00
Referenced by issue #88219, Regression: Massive drops in Animation playback (fps) in the viewport
4 changed files with 74 additions and 17 deletions

View File

@ -723,7 +723,6 @@ typedef struct EEVEE_EffectsInfo {
bool reflection_trace_full;
bool ssr_was_persp;
bool ssr_was_valid_double_buffer;
int ssr_neighbor_ofs;
struct GPUTexture *ssr_normal_input; /* Textures from pool */
struct GPUTexture *ssr_specrough_input;
struct GPUTexture *ssr_hit_output;

View File

@ -32,11 +32,6 @@
#include "GPU_texture.h"
#include "eevee_private.h"
static struct {
/* These are just references, not actually allocated */
struct GPUTexture *depth_src;
} e_data = {NULL}; /* Engine data */
int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
@ -186,7 +181,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
DRW_shgroup_uniform_int(grp, "samplePoolOffset", &effects->taa_current_sample, 1);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
@ -216,9 +211,6 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
EEVEE_EffectsInfo *effects = stl->effects;
if (((effects->enabled_effects & EFFECT_SSR) != 0) && stl->g_data->valid_double_buffer) {
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
e_data.depth_src = dtxl->depth;
DRW_stats_group_start("SSR");
/* Raytrace. */

View File

@ -46,3 +46,56 @@ HitData decode_hit_data(vec4 hit_data, float hit_depth)
data.is_hit = (hit_data.w > 0.0);
return data;
}
/* Blue noise categorised into 4 sets of samples.
* See "Stochastic all the things" presentation slide 32-37. */
const int resolve_samples_count = 9;
const vec2 resolve_sample_offsets[36] = vec2[36](
/* Set 1. */
/* First Ring (2x2). */
vec2(0, 0),
/* Second Ring (6x6). */
vec2(-1, 3),
vec2(1, 3),
vec2(-1, 1),
vec2(3, 1),
vec2(-2, 0),
vec2(3, 0),
vec2(2, -1),
vec2(1, -2),
/* Set 2. */
/* First Ring (2x2). */
vec2(1, 1),
/* Second Ring (6x6). */
vec2(-2, 3),
vec2(3, 3),
vec2(0, 2),
vec2(2, 2),
vec2(-2, -1),
vec2(1, -1),
vec2(0, -2),
vec2(3, -2),
/* Set 3. */
/* First Ring (2x2). */
vec2(0, 1),
/* Second Ring (6x6). */
vec2(0, 3),
vec2(3, 2),
vec2(-2, 1),
vec2(2, 1),
vec2(-1, 0),
vec2(-2, -2),
vec2(0, -1),
vec2(2, -2),
/* Set 4. */
/* First Ring (2x2). */
vec2(1, 0),
/* Second Ring (6x6). */
vec2(2, 3),
vec2(-2, 2),
vec2(-1, 2),
vec2(1, 2),
vec2(2, 0),
vec2(-1, -1),
vec2(3, -1),
vec2(-1, -2));

View File

@ -24,6 +24,8 @@ uniform sampler2D specroughBuffer;
uniform sampler2D hitBuffer;
uniform sampler2D hitDepth;
uniform int samplePoolOffset;
in vec4 uvcoordsvar;
out vec4 fragColor;
@ -75,8 +77,8 @@ void resolve_reflection_sample(int planar_index,
inout float weight_accum,
inout vec4 ssr_accum)
{
vec4 hit_data = texture(hitBuffer, sample_uv * ssrUvScale);
float hit_depth = texture(hitDepth, sample_uv * ssrUvScale).r;
vec4 hit_data = texture(hitBuffer, sample_uv);
float hit_depth = texture(hitDepth, sample_uv).r;
HitData data = decode_hit_data(hit_data, hit_depth);
float hit_dist = length(data.hit_dir);
@ -86,9 +88,12 @@ void resolve_reflection_sample(int planar_index,
float weight = bsdf * data.ray_pdf_inv;
/* Do not reuse hitpoint from planar reflections for normal reflections and vice versa. */
if ((planar_index == -1 && data.is_planar) || (planar_index != -1 && !data.is_planar)) {
return;
}
/* Do not add light if ray has failed but still weight it. */
if (!data.is_hit || (planar_index == -1 && data.is_planar) ||
(planar_index != -1 && !data.is_planar)) {
if (!data.is_hit) {
weight_accum += weight;
return;
}
@ -155,10 +160,18 @@ void raytrace_resolve(ClosureInputGlossy cl_in,
float cone_tan = sqrt(1.0 - cone_cos * cone_cos) / cone_cos;
cone_tan *= mix(saturate(dot(vN, -vV) * 2.0), 1.0, roughness); /* Elongation fit */
vec2 sample_uv = uvcoordsvar.xy;
int sample_pool = int((uint(gl_FragCoord.x) & 1u) + (uint(gl_FragCoord.y) & 1u) * 2u);
sample_pool = (sample_pool + (samplePoolOffset / 5)) % 4;
resolve_reflection_sample(
planar_index, sample_uv, vP, vN, vV, roughness_squared, cone_tan, weight_acc, ssr_accum);
for (int i = 0; i < resolve_samples_count; i++) {
int sample_id = sample_pool * resolve_samples_count + i;
vec2 texture_size = vec2(textureSize(hitBuffer, 0));
vec2 sample_texel = texture_size * uvcoordsvar.xy * ssrUvScale;
vec2 sample_uv = (sample_texel + resolve_sample_offsets[sample_id]) / texture_size;
resolve_reflection_sample(
planar_index, sample_uv, vP, vN, vV, roughness_squared, cone_tan, weight_acc, ssr_accum);
}
}
/* Compute SSR contribution */