Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2021-05-05 19:13:24 +0300
committerClément Foucault <foucault.clem@gmail.com>2021-05-05 19:40:20 +0300
commita1a9f8e6c3f341061777bc2d985b35e9d7a20ad1 (patch)
tree36f2a3f8cc329c45d8c7e2872cfbd40134ff13f7 /source/blender/draw/engines/eevee
parent95889fe071e179a9a7d7e6a27aaf7a4a42fc49b8 (diff)
Fix T87068 EEVEE: Moire effect with particle hair and subsurface
This artifact was already present in previous version but was hidden by the faulty SSS scale. The issue comes from the translucence using the geometric normal (computed using fragment shader derivative) leading to poor precision at depth discontinuity. Replacing using the same geometric normal reconstruction as the ambient occlusion pass removes most of the issue.
Diffstat (limited to 'source/blender/draw/engines/eevee')
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl60
1 files changed, 57 insertions, 3 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
index 737ef7dc509..356ed102928 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -183,16 +183,70 @@ vec3 light_translucent(LightData ld, vec3 P, vec3 N, vec4 l_vector, vec2 rand, f
#undef scube
#undef scsmd
+/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/.
+ * This samples the depth buffer 4 time for each direction to get the most correct
+ * implicit normal reconstruction out of the depth buffer. */
+vec3 view_position_derivative_from_depth(vec2 uvs, vec2 ofs, vec3 vP, float depth_center)
+{
+ vec2 uv1 = uvs - ofs * 2.0;
+ vec2 uv2 = uvs - ofs;
+ vec2 uv3 = uvs + ofs;
+ vec2 uv4 = uvs + ofs * 2.0;
+ vec4 H;
+ H.x = textureLod(depthBuffer, uv1, 0.0).r;
+ H.y = textureLod(depthBuffer, uv2, 0.0).r;
+ H.z = textureLod(depthBuffer, uv3, 0.0).r;
+ H.w = textureLod(depthBuffer, uv4, 0.0).r;
+ /* Fix issue with depth precision. Take even larger diff. */
+ vec4 diff = abs(vec4(depth_center, H.yzw) - H.x);
+ if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) {
+ return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x));
+ }
+ /* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */
+ vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center);
+ if (deltas.x < deltas.y) {
+ return vP - get_view_space_from_depth(uv2, H.y);
+ }
+ else {
+ return get_view_space_from_depth(uv3, H.z) - vP;
+ }
+}
+
+/* TODO(fclem) port to a common place for other effects to use. */
+bool reconstruct_view_position_and_normal_from_depth(vec2 uvs, out vec3 vP, out vec3 vNg)
+{
+ vec2 texel_size = vec2(abs(dFdx(uvs.x)), abs(dFdy(uvs.y)));
+ float depth_center = textureLod(depthBuffer, uvs, 0.0).r;
+
+ vP = get_view_space_from_depth(uvs, depth_center);
+
+ vec3 dPdx = view_position_derivative_from_depth(uvs, texel_size * vec2(1, 0), vP, depth_center);
+ vec3 dPdy = view_position_derivative_from_depth(uvs, texel_size * vec2(0, 1), vP, depth_center);
+
+ vNg = safe_normalize(cross(dPdx, dPdy));
+
+ /* Background case. */
+ if (depth_center == 1.0) {
+ return false;
+ }
+
+ return true;
+}
+
void main(void)
{
vec2 uvs = uvcoordsvar.xy;
float sss_scale = texture(sssRadius, uvs).r;
- vec3 P = get_world_space_from_depth(uvs, texture(depthBuffer, uvs).r);
- vec3 N = normalize(cross(dFdx(P), dFdy(P)));
vec3 rand = texelfetch_noise_tex(gl_FragCoord.xy).zwy;
rand.xy *= fast_sqrt(rand.z);
+ vec3 vP, vNg;
+ reconstruct_view_position_and_normal_from_depth(uvs, vP, vNg);
+
+ vec3 P = point_view_to_world(vP);
+ vec3 Ng = normal_view_to_world(vNg);
+
vec3 accum = vec3(0.0);
for (int i = 0; i < MAX_LIGHT && i < laNumLight; i++) {
LightData ld = lights_data[i];
@@ -211,7 +265,7 @@ void main(void)
continue;
}
- accum += att * ld.l_color * light_translucent(ld, P, -N, l_vector, rand.xy, sss_scale);
+ accum += att * ld.l_color * light_translucent(ld, P, -Ng, l_vector, rand.xy, sss_scale);
}
FragColor = vec4(accum, 1.0);