Eevee: SSR: Refine Raytrace Algorithm.
We track the previous ray position offseted by the thickness. If the sampled depth is between this value and the current ray position then we have a hit. This fixes rays that are almost colinear with the view vector. Thickness is now only important for rays that are comming back to the camera. As a consequence, this simplify a lot of things. Also include some refactor.
This commit is contained in:
parent
292f5ab758
commit
99f37bf2a2
|
@ -780,7 +780,7 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
|
|||
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
|
||||
DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
|
||||
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
|
||||
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &txl->color_double_buffer);
|
||||
DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer);
|
||||
DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
|
||||
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
|
||||
DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1);
|
||||
|
|
|
@ -29,6 +29,13 @@ flat in int shFace; /* Shadow layer we are rendering to. */
|
|||
|
||||
uniform vec2 mipRatio[10];
|
||||
|
||||
/* Buffers */
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D depthBuffer;
|
||||
uniform sampler2D maxzBuffer;
|
||||
uniform sampler2D minzBuffer;
|
||||
uniform sampler2DArray planarDepth;
|
||||
|
||||
#define cameraForward normalize(ViewMatrixInverse[2].xyz)
|
||||
#define cameraPos ViewMatrixInverse[3].xyz
|
||||
#define cameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward)
|
||||
|
|
|
@ -7,26 +7,6 @@
|
|||
uniform sampler2DArray utilTex;
|
||||
#endif /* UTIL_TEX */
|
||||
|
||||
uniform int rayCount;
|
||||
uniform float maxRoughness;
|
||||
|
||||
#define BRDF_BIAS 0.7
|
||||
|
||||
vec3 generate_ray(vec3 V, vec3 N, float a2, vec3 rand, out float pdf)
|
||||
{
|
||||
float NH;
|
||||
vec3 T, B;
|
||||
make_orthonormal_basis(N, T, B); /* Generate tangent space */
|
||||
|
||||
/* Importance sampling bias */
|
||||
rand.x = mix(rand.x, 0.0, BRDF_BIAS);
|
||||
|
||||
/* TODO distribution of visible normals */
|
||||
vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
|
||||
pdf = min(1024e32, pdf_ggx_reflect(NH, a2)); /* Theoretical limit of 16bit float */
|
||||
return reflect(-V, H);
|
||||
}
|
||||
|
||||
#define MAX_MIP 9.0
|
||||
|
||||
#ifdef STEP_RAYTRACE
|
||||
|
@ -41,51 +21,57 @@ layout(location = 1) out vec4 hitData1;
|
|||
layout(location = 2) out vec4 hitData2;
|
||||
layout(location = 3) out vec4 hitData3;
|
||||
|
||||
bool has_hit_backface(vec3 hit_pos, vec3 R, vec3 V)
|
||||
vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec3 rand, float ofs)
|
||||
{
|
||||
vec2 hit_co = project_point(ProjectionMatrix, hit_pos).xy * 0.5 + 0.5;
|
||||
vec3 hit_N = normal_decode(textureLod(normalBuffer, hit_co, 0.0).rg, V);
|
||||
return (dot(-R, hit_N) < 0.0);
|
||||
}
|
||||
float pdf, NH;
|
||||
float jitter = fract(rand.x + ofs);
|
||||
|
||||
vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 planeNormal, vec3 viewPosition, float a2, vec3 rand, float ray_nbr)
|
||||
{
|
||||
float pdf;
|
||||
vec3 R = generate_ray(V, N, a2, rand, pdf);
|
||||
/* Importance sampling bias */
|
||||
rand.x = mix(rand.x, 0.0, BRDF_BIAS);
|
||||
|
||||
vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
|
||||
pdf = pdf_ggx_reflect(NH, a2);
|
||||
|
||||
vec3 R = reflect(-V, H);
|
||||
R = reflect(R, planeNormal);
|
||||
|
||||
/* If ray is bad (i.e. going below the plane) regenerate. */
|
||||
if (dot(R, planeNormal) > 0.0) {
|
||||
vec3 H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */
|
||||
pdf = pdf_ggx_reflect(NH, a2);
|
||||
|
||||
R = reflect(-V, H);
|
||||
R = reflect(R, planeNormal);
|
||||
}
|
||||
|
||||
pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */
|
||||
pdf *= -1.0; /* Tag as planar ray. */
|
||||
|
||||
/* If ray is bad (i.e. going below the plane) do not trace. */
|
||||
if (dot(R, planeNormal) > 0.0) {
|
||||
vec3 R = generate_ray(V, N, a2, rand * vec3(1.0, -1.0, -1.0), pdf);
|
||||
}
|
||||
|
||||
vec3 hit_pos;
|
||||
if (abs(dot(-R, V)) < 0.9999) {
|
||||
/* Since viewspace hit position can land behind the camera in this case,
|
||||
* we save the reflected view position (visualize it as the hit position
|
||||
* below the reflection plane). This way it's garanted that the hit will
|
||||
* be in front of the camera. That let us tag the bad rays with a negative
|
||||
* sign in the Z component. */
|
||||
hit_pos = raycast(index, viewPosition, R, fract(rand.x + (ray_nbr / float(rayCount))), a2);
|
||||
}
|
||||
else {
|
||||
vec2 uvs = project_point(ProjectionMatrix, viewPosition).xy * 0.5 + 0.5;
|
||||
float raw_depth = textureLod(planarDepth, vec3(uvs, float(index)), 0.0).r;
|
||||
hit_pos = get_view_space_from_depth(uvs, raw_depth);
|
||||
hit_pos.z *= (raw_depth < 1.0) ? 1.0 : -1.0;
|
||||
}
|
||||
/* Since viewspace hit position can land behind the camera in this case,
|
||||
* we save the reflected view position (visualize it as the hit position
|
||||
* below the reflection plane). This way it's garanted that the hit will
|
||||
* be in front of the camera. That let us tag the bad rays with a negative
|
||||
* sign in the Z component. */
|
||||
vec3 hit_pos = raycast(index, viewPosition, R, 1e16, jitter, a2);
|
||||
|
||||
return vec4(hit_pos, pdf);
|
||||
}
|
||||
|
||||
vec4 do_ssr(vec3 V, vec3 N, vec3 viewPosition, float a2, vec3 rand, float ray_nbr)
|
||||
vec4 do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec3 rand, float ofs)
|
||||
{
|
||||
float pdf;
|
||||
vec3 R = generate_ray(V, N, a2, rand, pdf);
|
||||
float pdf, NH;
|
||||
float jitter = fract(rand.x + ofs);
|
||||
|
||||
vec3 hit_pos = raycast(-1, viewPosition, R, fract(rand.x + (ray_nbr / float(rayCount))), a2);
|
||||
/* Importance sampling bias */
|
||||
rand.x = mix(rand.x, 0.0, BRDF_BIAS);
|
||||
|
||||
vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
|
||||
pdf = pdf_ggx_reflect(NH, a2);
|
||||
|
||||
vec3 R = reflect(-V, H);
|
||||
pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */
|
||||
|
||||
vec3 hit_pos = raycast(-1, viewPosition, R, ssrThickness, jitter, a2);
|
||||
|
||||
return vec4(hit_pos, pdf);
|
||||
}
|
||||
|
@ -138,6 +124,11 @@ void main()
|
|||
vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition);
|
||||
vec3 wN = transform_direction(ViewMatrixInverse, N);
|
||||
|
||||
vec3 T, B;
|
||||
make_orthonormal_basis(N, T, B); /* Generate tangent space */
|
||||
|
||||
float ray_ofs = 1.0 / float(rayCount);
|
||||
|
||||
/* Planar Reflections */
|
||||
for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) {
|
||||
PlanarData pd = planars_data[i];
|
||||
|
@ -152,24 +143,24 @@ void main()
|
|||
vec3 planeNormal = transform_direction(ViewMatrix, pd.pl_normal);
|
||||
|
||||
/* TODO : Raytrace together if textureGather is supported. */
|
||||
hitData0 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand, 0.0);
|
||||
if (rayCount > 1) hitData1 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0);
|
||||
if (rayCount > 2) hitData2 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0);
|
||||
if (rayCount > 3) hitData3 = do_planar_ssr(i, V, N, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0);
|
||||
hitData0 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand, 0.0);
|
||||
if (rayCount > 1) hitData1 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
|
||||
if (rayCount > 2) hitData2 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
|
||||
if (rayCount > 3) hitData3 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO : Raytrace together if textureGather is supported. */
|
||||
hitData0 = do_ssr(V, N, viewPosition, a2, rand, 0.0);
|
||||
if (rayCount > 1) hitData1 = do_ssr(V, N, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0);
|
||||
if (rayCount > 2) hitData2 = do_ssr(V, N, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0);
|
||||
if (rayCount > 3) hitData3 = do_ssr(V, N, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0);
|
||||
hitData0 = do_ssr(V, N, T, B, viewPosition, a2, rand, 0.0);
|
||||
if (rayCount > 1) hitData1 = do_ssr(V, N, T, B, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
|
||||
if (rayCount > 2) hitData2 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
|
||||
if (rayCount > 3) hitData3 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
|
||||
}
|
||||
|
||||
#else /* STEP_RESOLVE */
|
||||
|
||||
uniform sampler2D colorBuffer; /* previous frame */
|
||||
uniform sampler2D prevColorBuffer; /* previous frame */
|
||||
uniform sampler2D normalBuffer;
|
||||
uniform sampler2D specroughBuffer;
|
||||
|
||||
|
@ -181,9 +172,6 @@ uniform sampler2D hitBuffer3;
|
|||
uniform int probe_count;
|
||||
uniform int planar_count;
|
||||
|
||||
uniform float borderFadeFactor;
|
||||
uniform float fireflyFactor;
|
||||
|
||||
uniform mat4 PastViewProjectionMatrix;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
@ -242,17 +230,6 @@ float brightness(vec3 c)
|
|||
return max(max(c.r, c.g), c.b);
|
||||
}
|
||||
|
||||
float screen_border_mask(vec2 hit_co)
|
||||
{
|
||||
const float margin = 0.003;
|
||||
float atten = borderFadeFactor + margin; /* Screen percentage */
|
||||
hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co));
|
||||
|
||||
float screenfade = hit_co.x * hit_co.y;
|
||||
|
||||
return screenfade;
|
||||
}
|
||||
|
||||
vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N)
|
||||
{
|
||||
/* TODO real reprojection with motion vectors, etc... */
|
||||
|
@ -321,7 +298,7 @@ vec4 get_ssr_sample(
|
|||
sample = textureLod(probePlanars, vec3(ref_uvs, planar_index), mip).rgb;
|
||||
}
|
||||
else {
|
||||
sample = textureLod(colorBuffer, ref_uvs, mip).rgb;
|
||||
sample = textureLod(prevColorBuffer, ref_uvs, mip).rgb;
|
||||
}
|
||||
|
||||
/* Clamped brightness. */
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
#define MAX_REFINE_STEP 32 /* Should be max allowed stride */
|
||||
|
||||
uniform vec4 ssrParameters;
|
||||
|
||||
uniform sampler2D depthBuffer;
|
||||
uniform sampler2D maxzBuffer;
|
||||
uniform sampler2D minzBuffer;
|
||||
uniform sampler2DArray planarDepth;
|
||||
uniform int rayCount;
|
||||
|
||||
#define ssrQuality ssrParameters.x
|
||||
#define ssrThickness ssrParameters.y
|
||||
#define ssrPixelSize ssrParameters.zw
|
||||
|
||||
uniform float maxRoughness;
|
||||
uniform float borderFadeFactor;
|
||||
uniform float fireflyFactor;
|
||||
|
||||
float sample_depth(vec2 uv, int index, float lod)
|
||||
{
|
||||
if (index > -1) {
|
||||
|
@ -24,26 +24,6 @@ float sample_depth(vec2 uv, int index, float lod)
|
|||
}
|
||||
}
|
||||
|
||||
float sample_minz_depth(vec2 uv, int index)
|
||||
{
|
||||
if (index > -1) {
|
||||
return textureLod(planarDepth, vec3(uv, index), 0.0).r;
|
||||
}
|
||||
else {
|
||||
return textureLod(minzBuffer, uv, 0.0).r;
|
||||
}
|
||||
}
|
||||
|
||||
float sample_maxz_depth(vec2 uv, int index)
|
||||
{
|
||||
if (index > -1) {
|
||||
return textureLod(planarDepth, vec3(uv, index), 0.0).r;
|
||||
}
|
||||
else {
|
||||
return textureLod(maxzBuffer, uv, 0.0).r;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 sample_depth_grouped(vec4 uv1, vec4 uv2, int index, float lod)
|
||||
{
|
||||
vec4 depths;
|
||||
|
@ -82,7 +62,7 @@ float refine_isect(float prev_delta, float curr_delta)
|
|||
return saturate(prev_delta / (prev_delta - curr_delta));
|
||||
}
|
||||
|
||||
void prepare_raycast(vec3 ray_origin, vec3 ray_dir, out vec4 ss_step, out vec4 ss_ray, out float max_time)
|
||||
void prepare_raycast(vec3 ray_origin, vec3 ray_dir, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time)
|
||||
{
|
||||
/* Negate the ray direction if it goes towards the camera.
|
||||
* This way we don't need to care if the projected point
|
||||
|
@ -91,27 +71,42 @@ void prepare_raycast(vec3 ray_origin, vec3 ray_dir, out vec4 ss_step, out vec4 s
|
|||
vec3 ray_end = z_sign * ray_dir * 1e16 + ray_origin;
|
||||
|
||||
/* Project into screen space. */
|
||||
vec3 ss_start = project_point(ProjectionMatrix, ray_origin);
|
||||
vec3 ss_end = project_point(ProjectionMatrix, ray_end);
|
||||
/* 4th component is current stride */
|
||||
ss_step = vec4(z_sign * normalize(ss_end - ss_start), 1.0);
|
||||
vec4 ss_start, ss_end;
|
||||
ss_start.xyz = project_point(ProjectionMatrix, ray_origin);
|
||||
ss_end.xyz = project_point(ProjectionMatrix, ray_end);
|
||||
|
||||
/* We interpolate the ray Z + thickness values to check if depth is within threshold. */
|
||||
ray_origin.z -= thickness;
|
||||
ray_end.z -= thickness;
|
||||
ss_start.w = project_point(ProjectionMatrix, ray_origin).z;
|
||||
ss_end.w = project_point(ProjectionMatrix, ray_end).z;
|
||||
|
||||
/* XXX This is a hack a better method is welcome ! */
|
||||
/* We take the delta between the offseted depth and the depth and substract it from the ray depth.
|
||||
* This will change the world space thickness appearance a bit but we can have negative
|
||||
* values without worries. We cannot do this in viewspace because of the perspective division. */
|
||||
ss_start.w = 2.0 * ss_start.z - ss_start.w;
|
||||
ss_end.w = 2.0 * ss_end.z - ss_end.w;
|
||||
|
||||
ss_step = ss_end - ss_start;
|
||||
ss_step = z_sign * ss_step / length(ss_step.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 */
|
||||
ss_step.xy += vec2((dot(ss_step.xy, ss_step.xy) < 0.00001) ? 0.001 : 0.0);
|
||||
ss_step.xy += vec2((dot(ss_step.xy, ss_step.xy) < 0.000001) ? 0.001 : 0.0);
|
||||
|
||||
/* Make ss_step cover one pixel. */
|
||||
ss_step.xyz /= max(abs(ss_step.x), abs(ss_step.y));
|
||||
ss_step.xyz *= ((abs(ss_step.x) > abs(ss_step.y)) ? ssrPixelSize.x : ssrPixelSize.y);
|
||||
ss_step /= max(abs(ss_step.x), abs(ss_step.y));
|
||||
ss_step *= ((abs(ss_step.x) > abs(ss_step.y)) ? ssrPixelSize.x : ssrPixelSize.y);
|
||||
|
||||
/* Clipping to frustum sides. */
|
||||
max_time = line_unit_box_intersect_dist(ss_start, ss_step.xyz) - 1.0;
|
||||
max_time = line_unit_box_intersect_dist(ss_start.xyz, ss_step.xyz);
|
||||
|
||||
/* Convert to texture coords. Z component included
|
||||
* since this is how it's stored in the depth buffer.
|
||||
* 4th component how far we are on the ray */
|
||||
ss_ray = vec4(ss_start * 0.5 + 0.5, 0.0);
|
||||
ss_step.xyz *= 0.5;
|
||||
ss_ray = ss_start * 0.5 + 0.5;
|
||||
ss_step *= 0.5;
|
||||
}
|
||||
|
||||
/* See times_and_deltas. */
|
||||
|
@ -120,30 +115,35 @@ void prepare_raycast(vec3 ray_origin, vec3 ray_dir, out vec4 ss_step, out vec4 s
|
|||
#define curr_delta times_and_deltas.z
|
||||
#define prev_delta times_and_deltas.w
|
||||
|
||||
// #define GROUPED_FETCHES
|
||||
// #define GROUPED_FETCHES /* is still slower, need to see where is the bottleneck. */
|
||||
/* Return the hit position, and negate the z component (making it positive) if not hit occured. */
|
||||
vec3 raycast(int index, vec3 ray_origin, vec3 ray_dir, float ray_jitter, float roughness)
|
||||
vec3 raycast(int index, vec3 ray_origin, vec3 ray_dir, float thickness, float ray_jitter, float roughness)
|
||||
{
|
||||
vec4 ss_step, ss_start;
|
||||
float max_time;
|
||||
prepare_raycast(ray_origin, ray_dir, ss_step, ss_start, max_time);
|
||||
prepare_raycast(ray_origin, ray_dir, thickness, ss_step, ss_start, max_time);
|
||||
|
||||
float max_trace_time = max(0.001, max_time - 0.01);
|
||||
|
||||
#ifdef GROUPED_FETCHES
|
||||
ray_jitter *= 0.25;
|
||||
#endif
|
||||
/* x : current_time, y: previous_time, z: previous_delta, w: current_delta */
|
||||
vec4 times_and_deltas = vec4(0.0, 0.0, 0.001, 0.001);
|
||||
|
||||
/* x : current_time, y: previous_time, z: current_delta, w: previous_delta */
|
||||
vec4 times_and_deltas = vec4(0.0);
|
||||
|
||||
float ray_time = 0.0;
|
||||
float depth_sample;
|
||||
float depth_sample = sample_depth(ss_start.xy, index, 0.0);
|
||||
curr_delta = depth_sample - ss_start.z;
|
||||
|
||||
float lod_fac = saturate(fast_sqrt(roughness) * 2.0 - 0.4);
|
||||
bool hit = false;
|
||||
float iter;
|
||||
for (iter = 1.0; !hit && (ray_time <= max_time) && (iter < MAX_STEP); iter++) {
|
||||
for (iter = 1.0; !hit && (ray_time < max_time) && (iter < MAX_STEP); iter++) {
|
||||
/* Minimum stride of 2 because we are using half res minmax zbuffer. */
|
||||
float stride = max(1.0, iter * ssrQuality) * 2.0;
|
||||
float lod = log2(stride * 0.5 * ssrQuality) * lod_fac;
|
||||
ray_time += stride;
|
||||
|
||||
/* Save previous values. */
|
||||
times_and_deltas.xyzw = times_and_deltas.yxwz;
|
||||
|
@ -152,7 +152,7 @@ vec3 raycast(int index, vec3 ray_origin, vec3 ray_dir, float ray_jitter, float r
|
|||
stride *= 4.0;
|
||||
vec4 jit_stride = mix(vec4(2.0), vec4(stride), vec4(0.0, 0.25, 0.5, 0.75) + ray_jitter);
|
||||
|
||||
vec4 times = vec4(ray_time) + jit_stride;
|
||||
vec4 times = min(vec4(ray_time) + jit_stride, vec4(max_trace_time));
|
||||
|
||||
vec4 uv1 = ss_start.xyxy + ss_step.xyxy * times.xxyy;
|
||||
vec4 uv2 = ss_start.xyxy + ss_step.xyxy * times.zzww;
|
||||
|
@ -160,11 +160,13 @@ vec3 raycast(int index, vec3 ray_origin, vec3 ray_dir, float ray_jitter, float r
|
|||
vec4 depth_samples = sample_depth_grouped(uv1, uv2, index, lod);
|
||||
|
||||
vec4 ray_z = ss_start.zzzz + ss_step.zzzz * times.xyzw;
|
||||
vec4 ray_w = ss_start.wwww + ss_step.wwww * vec4(prev_time, times.xyz);
|
||||
|
||||
vec4 deltas = depth_samples - ray_z;
|
||||
/* Same as component wise (depth_samples <= ray_z) && (ray_time <= max_time). */
|
||||
bvec4 test = equal(step(deltas, vec4(0.0)) * step(times, vec4(max_time)), vec4(1.0));
|
||||
/* Same as component wise (curr_delta <= 0.0) && (prev_w <= depth_sample). */
|
||||
bvec4 test = equal(step(deltas, vec4(0.0)) * step(ray_w, depth_samples), vec4(1.0));
|
||||
hit = any(test);
|
||||
|
||||
if (hit) {
|
||||
vec2 m = vec2(1.0, 0.0); /* Mask */
|
||||
|
||||
|
@ -177,54 +179,52 @@ vec3 raycast(int index, vec3 ray_origin, vec3 ray_dir, float ray_jitter, float r
|
|||
depth_sample = (test.z) ? depth_samples.z : depth_sample;
|
||||
depth_sample = (test.y) ? depth_samples.y : depth_sample;
|
||||
depth_sample = (test.x) ? depth_samples.x : depth_sample;
|
||||
break;
|
||||
}
|
||||
curr_time = times.w;
|
||||
curr_delta = deltas.w;
|
||||
ray_time += stride;
|
||||
else {
|
||||
curr_time = times.w;
|
||||
curr_delta = deltas.w;
|
||||
}
|
||||
#else
|
||||
float jit_stride = mix(2.0, stride, ray_jitter);
|
||||
|
||||
curr_time = ray_time + jit_stride;
|
||||
curr_time = min(ray_time + jit_stride, max_trace_time);
|
||||
vec4 ss_ray = ss_start + ss_step * curr_time;
|
||||
|
||||
depth_sample = sample_depth(ss_ray.xy, index, lod);
|
||||
|
||||
float prev_w = ss_start.w + ss_step.w * prev_time;
|
||||
curr_delta = depth_sample - ss_ray.z;
|
||||
hit = (curr_delta <= 0.0) && (curr_time <= max_time);
|
||||
|
||||
ray_time += stride;
|
||||
hit = (curr_delta <= 0.0) && (prev_w <= depth_sample);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Discard backface hits */
|
||||
hit = hit && (prev_delta > 0.0);
|
||||
|
||||
/* Reject hit if background. */
|
||||
hit = hit && (depth_sample != 1.0);
|
||||
|
||||
curr_time = (hit) ? mix(prev_time, curr_time, refine_isect(prev_delta, curr_delta)) : curr_time;
|
||||
ray_time = (hit) ? curr_time : ray_time;
|
||||
|
||||
#if 0 /* Not needed if using refine_isect() */
|
||||
/* Binary search */
|
||||
for (float time_step = (curr_time - prev_time) * 0.5; time_step > 1.0; time_step /= 2.0) {
|
||||
ray_time -= time_step;
|
||||
vec4 ss_ray = ss_start + ss_step * ray_time;
|
||||
float depth_sample = sample_maxz_depth(ss_ray.xy, index);
|
||||
bool is_hit = (depth_sample - ss_ray.z <= 0.0);
|
||||
ray_time = (is_hit) ? ray_time : ray_time + time_step;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Clip to frustum. */
|
||||
ray_time = min(ray_time, max_time - 0.5);
|
||||
ray_time = max(0.001, min(ray_time, max_time - 1.5));
|
||||
|
||||
vec4 ss_ray = ss_start + ss_step * ray_time;
|
||||
vec3 hit_pos = get_view_space_from_depth(ss_ray.xy, ss_ray.z);
|
||||
|
||||
/* Reject hit if not within threshold. */
|
||||
/* TODO do this check while tracing. Potentially higher quality */
|
||||
if (hit && (index == -1)) {
|
||||
float z = get_view_z_from_depth(depth_sample);
|
||||
hit = hit && ((z - hit_pos.z - ssrThickness) <= ssrThickness);
|
||||
}
|
||||
|
||||
/* Tag Z if ray failed. */
|
||||
hit_pos.z *= (hit) ? 1.0 : -1.0;
|
||||
return hit_pos;
|
||||
}
|
||||
|
||||
float screen_border_mask(vec2 hit_co)
|
||||
{
|
||||
const float margin = 0.003;
|
||||
float atten = borderFadeFactor + margin; /* Screen percentage */
|
||||
hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co));
|
||||
|
||||
float screenfade = hit_co.x * hit_co.y;
|
||||
|
||||
return screenfade;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue