diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2021-05-27 18:15:39 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2021-05-27 18:15:39 +0300 |
commit | 8590cb26a979c7eee6af5fba09b5edaf47cb4e8e (patch) | |
tree | 0a222c3fab3b21fb0f0ee630c9997cd5eb27a6d8 /source | |
parent | 3025c348253a66f9c316259aa03f8884bf56d779 (diff) | |
parent | ba4228bcf77e50368a7c84affd5e380bd45789a7 (diff) |
Merge branch 'blender-v2.93-release'
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index fdbb70e917d..c8eaa06094e 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -138,30 +138,55 @@ void accumulate_light(vec3 light, float fac, inout vec4 accum) /* Same thing as Cycles without the comments to make it shorter. */ vec3 ensure_valid_reflection(vec3 Ng, vec3 I, vec3 N) { - vec3 R; - float NI = dot(N, I); - float NgR, threshold; - /* Check if the incident ray is coming from behind normal N. */ - if (NI > 0.0) { - /* Normal reflection. */ - R = (2.0 * NI) * N - I; - NgR = dot(Ng, R); - /* Reflection rays may always be at least as shallow as the incoming ray. */ - threshold = min(0.9 * dot(Ng, I), 0.01); - if (NgR >= threshold) { - return N; + vec3 R = -reflect(I, N); + + /* Reflection rays may always be at least as shallow as the incoming ray. */ + float threshold = min(0.9 * dot(Ng, I), 0.025); + if (dot(Ng, R) >= threshold) { + return N; + } + + float NdotNg = dot(N, Ng); + vec3 X = normalize(N - NdotNg * Ng); + + float Ix = dot(I, X), Iz = dot(I, Ng); + float Ix2 = sqr(Ix), Iz2 = sqr(Iz); + float a = Ix2 + Iz2; + + float b = sqrt(Ix2 * (a - sqr(threshold))); + float c = Iz * threshold + a; + + float fac = 0.5 / a; + float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c); + bool valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5)); + bool valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5)); + + vec2 N_new; + if (valid1 && valid2) { + /* If both are possible, do the expensive reflection-based check. */ + vec2 N1 = vec2(sqrt(1.0 - N1_z2), sqrt(N1_z2)); + vec2 N2 = vec2(sqrt(1.0 - N2_z2), sqrt(N2_z2)); + + float R1 = 2.0 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz; + float R2 = 2.0 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz; + + valid1 = (R1 >= 1e-5); + valid2 = (R2 >= 1e-5); + if (valid1 && valid2) { + N_new = (R1 < R2) ? N1 : N2; } + else { + N_new = (R1 > R2) ? N1 : N2; + } + } + else if (valid1 || valid2) { + float Nz2 = valid1 ? N1_z2 : N2_z2; + N_new = vec2(sqrt(1.0 - Nz2), sqrt(Nz2)); } else { - /* Bad incident. */ - R = -I; - NgR = dot(Ng, R); - threshold = 0.01; + return Ng; } - /* Lift the reflection above the threshold. */ - R = R + Ng * (threshold - NgR); - /* Find a bisector. */ - return safe_normalize(I * length(R) + R * length(I)); + return N_new.x * X + N_new.y * Ng; } /* ----------- Cone angle Approximation --------- */ |