diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-08-10 16:43:15 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-08-10 16:43:48 +0300 |
commit | 6e2f17ea02be5caa9eee8a68ccd558474030b29a (patch) | |
tree | 29584459e5306ede452923a4956b17ac85eacc3d /source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl | |
parent | 896154d15de716ef360d0187cb89f44102ac31ef (diff) |
Eevee: Refraction: Add "thickness" parameter.
This enables to fake a second refraction event. This is great to simulate thin planar objects such as glass panels.
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl')
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index b3559e3d366..4ee2e778c21 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -7,9 +7,7 @@ uniform int planar_count; uniform bool specToggle; uniform bool ssrToggle; -#ifdef USE_REFRACTION -uniform float refractionThickness; -#endif +uniform float refractionDepth; #ifndef UTIL_TEX #define UTIL_TEX @@ -551,7 +549,7 @@ vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ss /* ----------- Transmission ----------- */ -vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int ssr_id, out vec3 ssr_spec) +vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior) { /* Zero length vectors cause issues, see: T51979. */ #if 0 @@ -581,16 +579,26 @@ vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int s /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */ vec4 trans_accum = vec4(0.0); + /* Refract the view vector using the depth heuristic. + * Then later Refract a second time the already refracted + * ray using the inverse ior. */ + float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior; + vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V; + vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition; + #ifdef USE_REFRACTION /* Screen Space Refraction */ if (ssrToggle && roughness < maxRoughness + 0.2) { vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw; + /* Find approximated position of the 2nd refraction event. */ + vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition; + float ray_ofs = 1.0 / float(rayCount); - vec4 spec = screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand, 0.0); - if (rayCount > 1) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs); - if (rayCount > 2) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs); - if (rayCount > 3) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs); + vec4 spec = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand, 0.0); + if (rayCount > 1) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs); + if (rayCount > 2) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs); + if (rayCount > 3) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs); spec /= float(rayCount); spec.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness); accumulate_light(spec.rgb, spec.a, trans_accum); @@ -599,7 +607,7 @@ vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int s /* Specular probes */ /* NOTE: This bias the IOR */ - vec3 spec_dir = get_specular_refraction_dominant_dir(N, V, roughness, ior); + vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior); /* Starts at 1 because 0 is world probe */ for (int i = 1; i < MAX_PROBE && i < probe_count && trans_accum.a < 0.999; ++i) { @@ -608,14 +616,14 @@ vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int s float fade = probe_attenuation_cube(cd, worldPosition); if (fade > 0.0) { - vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughnessSquared); + vec3 spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared); accumulate_light(spec, fade, trans_accum); } } /* World Specular */ if (trans_accum.a < 0.999) { - vec3 spec = probe_evaluate_world_spec(spec_dir, roughnessSquared); + vec3 spec = probe_evaluate_world_spec(refr_dir, roughnessSquared); accumulate_light(spec, 1.0, trans_accum); } @@ -701,9 +709,13 @@ vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float i } } - /* Specular probes */ - vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); - vec3 refr_dir = get_specular_refraction_dominant_dir(N, V, roughness, ior); + /* Refract the view vector using the depth heuristic. + * Then later Refract a second time the already refracted + * ray using the inverse ior. */ + float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior; + vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V; + vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition; + vec4 trans_accum = vec4(0.0); #ifdef USE_REFRACTION @@ -711,17 +723,24 @@ vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float i if (ssrToggle && roughness < maxRoughness + 0.2) { vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw; + /* Find approximated position of the 2nd refraction event. */ + vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition; + float ray_ofs = 1.0 / float(rayCount); - vec4 spec = screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand, 0.0); - if (rayCount > 1) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs); - if (rayCount > 2) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs); - if (rayCount > 3) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs); + vec4 spec = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand, 0.0); + if (rayCount > 1) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs); + if (rayCount > 2) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs); + if (rayCount > 3) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs); spec /= float(rayCount); spec.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness); accumulate_light(spec.rgb, spec.a, trans_accum); } #endif + /* Specular probes */ + vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior); + vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); + /* Starts at 1 because 0 is world probe */ for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999 && trans_accum.a < 0.999; ++i) { CubeData cd = probes_data[i]; @@ -733,7 +752,7 @@ vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float i vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); accumulate_light(spec, fade, spec_accum); - spec = probe_evaluate_cube(float(i), cd, worldPosition, refr_dir, roughnessSquared); + spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared); accumulate_light(spec, fade, trans_accum); } } |