diff options
Diffstat (limited to 'source/blender/draw/engines/eevee')
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; } |