diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-09-19 01:06:45 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-09-19 01:09:51 +0300 |
commit | 6f3c279d9e7082b963f3ca758f6ba0561c4bcc9c (patch) | |
tree | 1ea2b44e57e192dd9a23223d605d1244734bff9e /source/blender/gpu/shaders/material | |
parent | aa2e978bd8b47dbc06826698b07d850cdd499568 (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/gpu/shaders/material')
3 files changed, 60 insertions, 19 deletions
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl index e1137d9d0e7..8131958313b 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl @@ -5,11 +5,12 @@ void node_bsdf_anisotropic(vec4 color, float rotation, vec3 N, vec3 T, + float use_multiscatter, out Closure result) { - node_bsdf_glossy(color, roughness, N, -1, result); + node_bsdf_glossy(color, roughness, N, -1, use_multiscatter, result); } #else /* Stub anisotropic because it is not compatible with volumetrics. */ -# define node_bsdf_anisotropic(a, b, c, d, e, f, g) (g = CLOSURE_DEFAULT) +# define node_bsdf_anisotropic(a, b, c, d, e, f, g, result) (result = CLOSURE_DEFAULT) #endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl index 5ea22f3e0b4..36675cf720d 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl @@ -1,10 +1,18 @@ #ifndef VOLUMETRICS -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) +void node_bsdf_glossy( + vec4 color, float roughness, vec3 N, float use_multiscatter, float ssr_id, out Closure result) { N = normalize(N); vec3 out_spec, ssr_spec; - eevee_closure_glossy( - N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec); + eevee_closure_glossy(N, + vec3(1.0), + use_multiscatter != 0.0 ? vec3(1.0) : vec3(-1.0), /* HACK */ + int(ssr_id), + roughness, + 1.0, + true, + out_spec, + ssr_spec); vec3 vN = mat3(ViewMatrix) * N; result = CLOSURE_DEFAULT; result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) * color.rgb; @@ -12,5 +20,5 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo } #else /* Stub glossy because it is not compatible with volumetrics. */ -# define node_bsdf_glossy(a, b, c, d, e) (e = CLOSURE_DEFAULT) +# define node_bsdf_glossy(a, b, c, d, e, result) (result = CLOSURE_DEFAULT) #endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index f7803155934..3fc40fd88e5 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -60,6 +60,7 @@ void node_bsdf_principled(vec4 base_color, vec3 CN, vec3 T, vec3 I, + float use_multiscatter, float ssr_id, float sss_id, vec3 sss_scale, @@ -107,7 +108,9 @@ void node_bsdf_principled(vec4 base_color, eevee_closure_principled(N, mixed_ss_base_color, f0, - f90, + /* HACK: Pass the multiscatter flag as the sign to not add closure + * variations or increase register usage. */ + (use_multiscatter != 0.0) ? f90 : -f90, int(ssr_id), roughness, CN, @@ -168,6 +171,7 @@ void node_bsdf_principled_dielectric(vec4 base_color, vec3 CN, vec3 T, vec3 I, + float use_multiscatter, float ssr_id, float sss_id, vec3 sss_scale, @@ -188,8 +192,19 @@ void node_bsdf_principled_dielectric(vec4 base_color, float NV = dot(N, cameraVec); principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color); - eevee_closure_default( - N, diffuse, f0, f90, int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec); + eevee_closure_default(N, + diffuse, + f0, + /* HACK: Pass the multiscatter flag as the sign to not add closure + * variations or increase register usage. */ + (use_multiscatter != 0.0) ? f90 : -f90, + int(ssr_id), + roughness, + 1.0, + true, + out_diff, + out_spec, + ssr_spec); result = CLOSURE_DEFAULT; result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); @@ -226,6 +241,7 @@ void node_bsdf_principled_metallic(vec4 base_color, vec3 CN, vec3 T, vec3 I, + float use_multiscatter, float ssr_id, float sss_id, vec3 sss_scale, @@ -236,8 +252,17 @@ void node_bsdf_principled_metallic(vec4 base_color, vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); - eevee_closure_glossy( - N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec); + eevee_closure_glossy(N, + base_color.rgb, + /* HACK: Pass the multiscatter flag as the sign to not add closure + * variations or increase register usage. */ + (use_multiscatter != 0.0) ? f90 : -f90, + int(ssr_id), + roughness, + 1.0, + true, + out_spec, + ssr_spec); result = CLOSURE_DEFAULT; result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); @@ -272,6 +297,7 @@ void node_bsdf_principled_clearcoat(vec4 base_color, vec3 CN, vec3 T, vec3 I, + float use_multiscatter, float ssr_id, float sss_id, vec3 sss_scale, @@ -284,7 +310,9 @@ void node_bsdf_principled_clearcoat(vec4 base_color, eevee_closure_clearcoat(N, base_color.rgb, - f90, + /* HACK: Pass the multiscatter flag as the sign to not add closure + * variations or increase register usage. */ + (use_multiscatter != 0.0) ? f90 : -f90, int(ssr_id), roughness, CN, @@ -331,6 +359,7 @@ void node_bsdf_principled_subsurface(vec4 base_color, vec3 CN, vec3 T, vec3 I, + float use_multiscatter, float ssr_id, float sss_id, vec3 sss_scale, @@ -357,7 +386,9 @@ void node_bsdf_principled_subsurface(vec4 base_color, eevee_closure_skin(N, mixed_ss_base_color, f0, - f90, + /* HACK: Pass the multiscatter flag as the sign to not add closure variations + or increase register usage. */ + (use_multiscatter != 0.0) ? f90 : -f90, int(ssr_id), roughness, 1.0, @@ -405,6 +436,7 @@ void node_bsdf_principled_glass(vec4 base_color, vec3 CN, vec3 T, vec3 I, + float use_multiscatter, float ssr_id, float sss_id, vec3 sss_scale, @@ -450,11 +482,11 @@ void node_bsdf_principled_glass(vec4 base_color, #else /* clang-format off */ /* Stub principled because it is not compatible with volumetrics. */ -# define node_bsdf_principled(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, result) (result = CLOSURE_DEFAULT) -# define node_bsdf_principled_dielectric(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, result) (result = CLOSURE_DEFAULT) -# define node_bsdf_principled_metallic(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, result) (result = CLOSURE_DEFAULT) -# define node_bsdf_principled_clearcoat(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, result) (result = CLOSURE_DEFAULT) -# define node_bsdf_principled_subsurface(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, result) (result = CLOSURE_DEFAULT) -# define node_bsdf_principled_glass(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, result) (result = CLOSURE_DEFAULT) +# define node_bsdf_principled(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT) +# define node_bsdf_principled_dielectric(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT) +# define node_bsdf_principled_metallic(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT) +# define node_bsdf_principled_clearcoat(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT) +# define node_bsdf_principled_subsurface(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT) +# define node_bsdf_principled_glass(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT) /* clang-format on */ #endif |