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>2020-09-19 01:06:45 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-09-19 01:09:51 +0300
commit6f3c279d9e7082b963f3ca758f6ba0561c4bcc9c (patch)
tree1ea2b44e57e192dd9a23223d605d1244734bff9e /source/blender/draw/engines/eevee/shaders
parentaa2e978bd8b47dbc06826698b07d850cdd499568 (diff)
EEVEE: Add support for GGX Multi-scatter
Based on http://jcgt.org/published/0008/01/03/ This is a simple trick that does *not* have a huge performance impact but does work pretty well. It just modifies the Fresnel term to account for the multibounce energy loss (coloration). However this makes the shader variations count double. To avoid this we use a uniform and pass the multiscatter use flag inside the sign of f90. This is a bit hacky but avoids many code duplication. This uses the simplification proposed by McAuley in A Journey Through Implementing Multiscattering BRDFs and Area Lights This does not handle area light differently than the IBL case but that's already an issue in current implementation. This is related to T68460. Reviewed By: brecht Differential Revision: https://developer.blender.org/D8912
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders')
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl42
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_lit_lib.glsl8
2 files changed, 26 insertions, 24 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 deedde64194..3560ae62a84 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -74,34 +74,36 @@ vec3 F_color_blend(float eta, float fresnel, vec3 f0_color)
return mix(f0_color, vec3(1.0), fac);
}
-/* Fresnel */
-vec3 F_schlick(vec3 f0, float cos_theta)
-{
- float fac = 1.0 - cos_theta;
- float fac2 = fac * fac;
- fac = fac2 * fac2 * fac;
-
- /* Unreal specular matching : if specular color is below 2% intensity,
- * (using green channel for intensity) treat as shadowning */
- return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * fac + (1.0 - fac) * f0;
-}
-
-/* Fresnel approximation for LTC area lights (not MRP) */
-vec3 F_area(vec3 f0, vec3 f90, vec2 lut)
+/* Fresnel split-sum approximation. */
+vec3 F_brdf_single_scatter(vec3 f0, vec3 f90, vec2 lut)
{
/* Unreal specular matching : if specular color is below 2% intensity,
* treat as shadowning */
- return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y * f90 + lut.x * f0;
+ return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y * abs(f90) + lut.x * f0;
}
-/* Fresnel approximation for IBL */
-vec3 F_ibl(vec3 f0, vec3 f90, vec2 lut)
+/* Multi-scattering brdf approximation from :
+ * "A Multiple-Scattering Microfacet Model for Real-Time Image-based Lighting"
+ * by Carmelo J. Fdez-Agüera. */
+vec3 F_brdf_multi_scatter(vec3 f0, vec3 f90, vec2 lut)
{
- /* Unreal specular matching : if specular color is below 2% intensity,
- * treat as shadowning */
- return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y * f90 + lut.x * f0;
+ vec3 FssEss = F_brdf_single_scatter(f0, f90, lut);
+ /* Hack to avoid many more shader variations. */
+ if (f90.g < 0.0) {
+ return FssEss;
+ }
+
+ float Ess = lut.x + lut.y;
+ float Ems = 1.0 - Ess;
+ vec3 Favg = f0 + (1.0 - f0) / 21.0;
+ vec3 Fms = FssEss * Favg / (1.0 - (1.0 - Ess) * Favg);
+ /* We don't do anything special for diffuse surfaces because the principle bsdf
+ * does not care about energy conservation of the specular layer for dielectrics. */
+ return FssEss + Fms * Ems;
}
+#define F_brdf(f0, f90, lut) F_brdf_multi_scatter(f0, f90, lut)
+
/* GGX */
float D_ggx_opti(float NH, float a2)
{
diff --git a/source/blender/draw/engines/eevee/shaders/closure_lit_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_lit_lib.glsl
index bf33caf9854..613b48ff9b8 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_lit_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_lit_lib.glsl
@@ -250,12 +250,12 @@ void CLOSURE_NAME(vec3 N
# ifdef CLOSURE_GLOSSY
vec2 brdf_lut_lights = texture(utilTex, vec3(lut_uv, 1.0)).ba;
- out_spec *= F_area(f0, f90, brdf_lut_lights.xy);
+ out_spec *= F_brdf(f0, f90, brdf_lut_lights.xy);
# endif
# ifdef CLOSURE_CLEARCOAT
vec2 brdf_lut_lights_clear = texture(utilTex, vec3(lut_uv_clear, 1.0)).ba;
- out_spec_clear *= F_area(vec3(0.04), vec3(1.0), brdf_lut_lights_clear.xy);
+ out_spec_clear *= F_brdf(vec3(0.04), vec3(1.0), brdf_lut_lights_clear.xy);
out_spec += out_spec_clear * C_intensity;
# endif
@@ -449,7 +449,7 @@ void CLOSURE_NAME(vec3 N
/* This factor is outputted to be used by SSR in order
* to match the intensity of the regular reflections. */
- ssr_spec = F_ibl(f0, f90, brdf_lut);
+ ssr_spec = F_brdf(f0, f90, brdf_lut);
float spec_occlu = specular_occlusion(NV, final_ao, roughness);
/* The SSR pass recompute the occlusion to not apply it to the SSR */
@@ -470,7 +470,7 @@ void CLOSURE_NAME(vec3 N
NV = dot(C_N, V);
vec2 C_uv = lut_coords(NV, C_roughness);
vec2 C_brdf_lut = texture(utilTex, vec3(C_uv, 1.0)).rg;
- vec3 C_fresnel = F_ibl(vec3(0.04), vec3(1.0), C_brdf_lut) *
+ vec3 C_fresnel = F_brdf(vec3(0.04), vec3(1.0), C_brdf_lut) *
specular_occlusion(NV, final_ao, C_roughness);
out_spec += C_spec_accum.rgb * C_fresnel * C_intensity;