diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-08-09 16:29:44 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-08-10 16:43:48 +0300 |
commit | 99f37bf2a2ad452ee995cd8ce9ce60d010b1f7f9 (patch) | |
tree | 7b8c88a5032b26931245fc9ac1b36a049ada4524 /source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl | |
parent | 292f5ab7584d6e9ba54893eaafd70d9ee8d1c3ce (diff) |
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.
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl')
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl | 127 |
1 files changed, 52 insertions, 75 deletions
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 fb59c522deb..b1286fd15f0 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -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); - pdf *= -1.0; /* Tag as planar ray. */ - /* If ray is bad (i.e. going below the plane) do not trace. */ + /* If ray is bad (i.e. going below the plane) regenerate. */ if (dot(R, planeNormal) > 0.0) { - vec3 R = generate_ray(V, N, a2, rand * vec3(1.0, -1.0, -1.0), pdf); - } + 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); - 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; + R = reflect(-V, H); + R = reflect(R, planeNormal); } + pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */ + pdf *= -1.0; /* Tag as planar ray. */ + + /* 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); + + /* 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, fract(rand.x + (ray_nbr / float(rayCount))), a2); + 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. */ |