diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2021-03-10 19:31:37 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2021-03-10 19:57:09 +0300 |
commit | 56bf4f3fb32641483aeb7870f9a6372a2867fbbc (patch) | |
tree | 79b7bca0b818fa5ddad4bdc802a1a5065af95113 /source/blender | |
parent | 793335f3e243f7a6f13d3d8a82c2bcb9925784bc (diff) |
EEVEE: ScreenSpaceReflections: Add back support for planar reflections
We now have a new buffer to output reflection depth. This buffer is
only usefull for non planar SSR but we use it to tag the planar rays.
This also touch the raytrace algo for planars to avoid degenerate
lines on vert sharp reflections.
Diffstat (limited to 'source/blender')
4 files changed, 40 insertions, 34 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index eb1c51f49dd..1ffd4a071f1 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -737,6 +737,7 @@ typedef struct EEVEE_EffectsInfo { struct GPUTexture *ssr_normal_input; /* Textures from pool */ struct GPUTexture *ssr_specrough_input; struct GPUTexture *ssr_hit_output; + struct GPUTexture *ssr_hit_depth; /* Temporal Anti Aliasing */ int taa_reproject_sample; int taa_current_sample; diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 00004b28ef3..94b0161faf8 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -97,11 +97,13 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Ray-tracing output. */ effects->ssr_hit_output = DRW_texture_pool_query_2d(UNPACK2(tracing_res), GPU_RGBA16F, owner); + effects->ssr_hit_depth = DRW_texture_pool_query_2d(UNPACK2(tracing_res), GPU_R16F, owner); GPU_framebuffer_ensure_config(&fbl->screen_tracing_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->ssr_hit_output), + GPU_ATTACHMENT_TEXTURE(effects->ssr_hit_depth), }); return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_RADIANCE_BUFFER | EFFECT_DOUBLE_BUFFER | @@ -173,6 +175,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &vedata->txl->planar_pool); DRW_shgroup_uniform_texture_ref(grp, "planarDepth", &vedata->txl->planar_depth); DRW_shgroup_uniform_texture_ref_ex(grp, "hitBuffer", &effects->ssr_hit_output, no_filter); + DRW_shgroup_uniform_texture_ref_ex(grp, "hitDepth", &effects->ssr_hit_depth, no_filter); DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &txl->filtered_radiance); DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool); diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl index cb090a320ce..11048a46f8e 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -25,6 +25,8 @@ uniform ivec2 halfresOffset; struct HitData { /** Hit direction scaled by intersection time. */ vec3 hit_dir; + /** Screen space [0..1] depth of the reflection hit position, or -1.0 for planar reflections. */ + float hit_depth; /** Inverse probability of ray spawning in this direction. */ float ray_pdf_inv; /** True if ray has hit valid geometry. */ @@ -33,27 +35,24 @@ struct HitData { bool is_planar; }; -vec4 encode_hit_data(HitData data) +void encode_hit_data(HitData data, vec3 hit_sP, vec3 vP, out vec4 hit_data, out float hit_depth) { - vec4 encoded_data; - encoded_data.xyz = data.hit_dir; - /* Encode planar in Z sign. */ - /* TODO fixme */ - // encoded_data.z = data.is_planar ? -encoded_data.z : encoded_data.z; + vec3 hit_vP = get_view_space_from_depth(hit_sP.xy, hit_sP.z); + hit_data.xyz = hit_vP - vP; + hit_depth = data.is_planar ? -1.0 : hit_sP.z; /* Record 1.0 / pdf to reduce the computation in the resolve phase. */ /* Encode hit validity in sign. */ - encoded_data.w = data.ray_pdf_inv * ((data.is_hit) ? 1.0 : -1.0); - return encoded_data; + hit_data.w = data.ray_pdf_inv * ((data.is_hit) ? 1.0 : -1.0); } -HitData decode_hit_data(vec4 encoded_data) +HitData decode_hit_data(vec4 hit_data, float hit_depth) { HitData data; - data.hit_dir.xyz = encoded_data.xyz; - /* TODO fixme */ - data.is_planar = false; - data.ray_pdf_inv = abs(encoded_data.w); - data.is_hit = (encoded_data.w > 0.0); + data.hit_dir.xyz = hit_data.xyz; + data.hit_depth = hit_depth; + data.is_planar = (hit_depth == -1.0); + data.ray_pdf_inv = abs(hit_data.w); + data.is_hit = (hit_data.w > 0.0); return data; } @@ -63,6 +62,7 @@ uniform sampler2D normalBuffer; uniform sampler2D specroughBuffer; layout(location = 0) out vec4 hitData; +layout(location = 1) out float hitDepth; void do_planar_ssr(int index, vec3 vV, @@ -89,14 +89,13 @@ void do_planar_ssr(int index, params.trace_quality = ssrQuality; params.roughness = alpha * alpha; + vec3 hit_sP; HitData data; data.is_planar = true; data.ray_pdf_inv = safe_rcp(pdf); - data.is_hit = raytrace_planar(ray, params, index, data.hit_dir); - data.hit_dir = get_view_space_from_depth(data.hit_dir.xy, data.hit_dir.z); - data.hit_dir -= ray.origin; + data.is_hit = raytrace_planar(ray, params, index, hit_sP); - hitData = encode_hit_data(data); + encode_hit_data(data, hit_sP, ray.origin, hitData, hitDepth); } void do_ssr(vec3 vV, vec3 vN, vec3 vT, vec3 vB, vec3 vP, float alpha, vec4 rand) @@ -116,14 +115,13 @@ void do_ssr(vec3 vV, vec3 vN, vec3 vT, vec3 vB, vec3 vP, float alpha, vec4 rand) params.trace_quality = ssrQuality; params.roughness = alpha * alpha; + vec3 hit_sP; HitData data; - data.is_planar = true; + data.is_planar = false; data.ray_pdf_inv = safe_rcp(pdf); - data.is_hit = raytrace(ray, params, true, data.hit_dir); - data.hit_dir = get_view_space_from_depth(data.hit_dir.xy, data.hit_dir.z); - data.hit_dir -= ray.origin; + data.is_hit = raytrace(ray, params, true, hit_sP); - hitData = encode_hit_data(data); + encode_hit_data(data, hit_sP, ray.origin, hitData, hitDepth); } in vec4 uvcoordsvar; @@ -135,12 +133,12 @@ void main() HitData data; data.is_planar = false; - data.ray_pdf_inv = safe_rcp(0.0); + data.ray_pdf_inv = 0.0; data.is_hit = false; data.hit_dir = vec3(0.0, 0.0, 0.0); /* Default: not hits. */ - hitData = encode_hit_data(data); + encode_hit_data(data, data.hit_dir, data.hit_dir, hitData, hitDepth); /* Early out */ /* We can't do discard because we don't clear the render target. */ @@ -212,6 +210,7 @@ uniform sampler2D colorBuffer; /* previous frame */ uniform sampler2D normalBuffer; uniform sampler2D specroughBuffer; uniform sampler2D hitBuffer; +uniform sampler2D hitDepth; in vec4 uvcoordsvar; @@ -264,7 +263,9 @@ void resolve_reflection_sample(int planar_index, inout float weight_accum, inout vec4 ssr_accum) { - HitData data = decode_hit_data(texture(hitBuffer, sample_uv * ssrUvScale)); + vec4 hit_data = texture(hitBuffer, sample_uv * ssrUvScale); + float hit_depth = texture(hitDepth, sample_uv * ssrUvScale).r; + HitData data = decode_hit_data(hit_data, hit_depth); float hit_dist = length(data.hit_dir); diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index dce50a7051e..e2aad867901 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -43,12 +43,12 @@ void raytrace_screenspace_ray_finalize(inout ScreenSpaceRay ray) ray.direction.zw += bias; ray.direction -= ray.origin; - float ray_len_sqr = len_squared(ray.direction.xyz); /* If the line is degenerate, make it cover at least one pixel * to not have to handle zero-pixel extent as a special case later */ - if (ray_len_sqr < 0.00001) { - ray.direction.xy = vec2(0.0, 0.0001); + if (len_squared(ray.direction.xy) < 0.00001) { + ray.direction.xy = vec2(0.0, 0.01); } + float ray_len_sqr = len_squared(ray.direction.xyz); /* Make ray.direction cover one pixel. */ bool is_more_vertical = abs(ray.direction.x) < abs(ray.direction.y); ray.direction /= (is_more_vertical) ? abs(ray.direction.y) : abs(ray.direction.x); @@ -166,8 +166,6 @@ bool raytrace_planar(Ray ray, RayTraceParameters params, int planar_ref_id, out } ScreenSpaceRay ssray = raytrace_screenspace_ray_create(ray); - /* Avoid no iteration. */ - ssray.max_time = max(ssray.max_time, 1.1); /* Planar Reflections have X mirrored. */ ssray.origin.x = 1.0 - ssray.origin.x; @@ -177,9 +175,10 @@ bool raytrace_planar(Ray ray, RayTraceParameters params, int planar_ref_id, out float depth_sample = get_depth_from_view_z(ray.origin.z); float delta = depth_sample - ssray.origin.z; - /* Cross at least one pixel. */ - float t = 1.001, time = 1.001; - bool hit = false; + float t = 0.0, time = 0.0; + /* On very sharp reflections, the ray can be perfectly aligned with the view direction + * making the tracing useless. Bypass tracing in this case. */ + bool hit = (ssray.max_time < 1.0); const float max_steps = 255.0; for (float iter = 1.0; !hit && (time < ssray.max_time) && (iter < max_steps); iter++) { float stride = 1.0 + iter * params.trace_quality; @@ -205,6 +204,8 @@ bool raytrace_planar(Ray ray, RayTraceParameters params, int planar_ref_id, out time = mix(prev_time, time, saturate(prev_delta / (prev_delta - delta))); hit_position = ssray.origin.xyz + ssray.direction.xyz * time; + /* Planar Reflections have X mirrored. */ + hit_position.x = 1.0 - hit_position.x; return hit; } |