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
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-11-24 08:15:42 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-11-24 08:37:37 +0300
commit2302ba2245f1e65dde7870cc9ab610ded5abc364 (patch)
treef504f772ab4a6e5dee5bbada56b5b421e8a2b842 /source
parent16a28021493d5a54efff5e6aade39f7b015366cd (diff)
Eevee: Refactor of lit_surface_frag.glsl
This cleanup removes the need of gigantic code duplication for each closure. This also make some preformance improvement since it removes some branches and duplicated loops. It also fix some mismatch (between cycles and eevee) with the principled shader.
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c5
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl1008
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl147
5 files changed, 385 insertions, 792 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 62e2cd3805c..e216dc7e60e 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -499,7 +499,10 @@ void EEVEE_materials_init(EEVEE_StorageList *stl)
BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
+ for (int i = 0; i < 7; ++i) {
+ /* Add one for each Closure */
+ BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
+ }
BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
e_data.frag_shader_lib = BLI_dynstr_get_cstring(ds_frag);
BLI_dynstr_free(ds_frag);
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
index 4ba4192abbd..91746a6f082 100644
--- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -7,12 +7,13 @@ uniform float roughness;
Closure nodetree_exec(void)
{
vec3 dielectric = vec3(0.034) * specular * 2.0;
- vec3 diffuse = mix(basecol, vec3(0.0), metallic);
+ vec3 albedo = mix(basecol, vec3(0.0), metallic);
vec3 f0 = mix(dielectric, basecol, metallic);
- vec3 ssr_spec;
- vec3 radiance = eevee_surface_lit((gl_FrontFacing) ? worldNormal : -worldNormal, diffuse, f0, roughness, 1.0, 0, ssr_spec);
+ vec3 N = (gl_FrontFacing) ? worldNormal : -worldNormal;
+ vec3 out_diff, out_spec, ssr_spec;
+ eevee_closure_default(N, albedo, f0, 0, roughness, 1.0, out_diff, out_spec, ssr_spec);
- Closure result = Closure(radiance, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0);
+ Closure result = Closure(out_spec + out_diff, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0);
return result;
}
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
index 1b4addaa4ed..933f056c401 100644
--- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -296,9 +296,13 @@ vec3 sss_profile(float s) {
vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
{
- vec3 vis = vec3(1.0);
+#if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS)
+ return vec3(0.0);
+#endif
#ifndef VOLUMETRICS
+ vec3 vis = vec3(1.0);
+
/* Only shadowed light can produce translucency */
if (ld.l_shadowid >= 0.0) {
ShadowData data = shadows_data[int(ld.l_shadowid)];
@@ -410,9 +414,9 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
else {
vis = vec3(0.0);
}
-#endif
return vis;
+#endif
}
#ifdef HAIR_SHADER
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 44410be700b..6ecaf0a627b 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -1,4 +1,7 @@
+#ifndef LIT_SURFACE_UNIFORM
+#define LIT_SURFACE_UNIFORM
+
uniform int light_count;
uniform int probe_count;
uniform int grid_count;
@@ -28,451 +31,162 @@ in vec3 viewNormal;
uniform float maxRoughness;
uniform int rayCount;
-/* ----------- default ----------- */
-
-vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec)
-{
- /* Zero length vectors cause issues, see: T51979. */
-#if 0
- N = normalize(N);
-#else
- {
- float len = length(N);
- if (isnan(len)) {
- return vec3(0.0);
- }
- N /= len;
- }
+#endif /* LIT_SURFACE_UNIFORM */
+
+/** AUTO CONFIG
+ * We include the file multiple times each time with a different configuration.
+ * This leads to a lot of deadcode. Better idea would be to only generate the one needed.
+ */
+#if !defined(SURFACE_DEFAULT)
+ #define SURFACE_DEFAULT
+ #define CLOSURE_NAME eevee_closure_default
+ #define CLOSURE_DIFFUSE
+ #define CLOSURE_GLOSSY
+#endif /* SURFACE_DEFAULT */
+
+#if !defined(SURFACE_PRINCIPLED) && !defined(CLOSURE_NAME)
+ #define SURFACE_PRINCIPLED
+ #define CLOSURE_NAME eevee_closure_principled
+ #define CLOSURE_DIFFUSE
+ #define CLOSURE_GLOSSY
+ #define CLOSURE_CLEARCOAT
+ #define CLOSURE_REFRACTION
+ #define CLOSURE_SUBSURFACE
+#endif /* SURFACE_PRINCIPLED */
+
+#if !defined(SURFACE_DIFFUSE) && !defined(CLOSURE_NAME)
+ #define SURFACE_DIFFUSE
+ #define CLOSURE_NAME eevee_closure_diffuse
+ #define CLOSURE_DIFFUSE
+#endif /* SURFACE_DIFFUSE */
+
+#if !defined(SURFACE_SUBSURFACE) && !defined(CLOSURE_NAME)
+ #define SURFACE_SUBSURFACE
+ #define CLOSURE_NAME eevee_closure_subsurface
+ #define CLOSURE_DIFFUSE
+ #define CLOSURE_SUBSURFACE
+#endif /* SURFACE_SUBSURFACE */
+
+#if !defined(SURFACE_GLOSSY) && !defined(CLOSURE_NAME)
+ #define SURFACE_GLOSSY
+ #define CLOSURE_NAME eevee_closure_glossy
+ #define CLOSURE_GLOSSY
+#endif /* SURFACE_GLOSSY */
+
+#if !defined(SURFACE_REFRACT) && !defined(CLOSURE_NAME)
+ #define SURFACE_REFRACT
+ #define CLOSURE_NAME eevee_closure_refraction
+ #define CLOSURE_REFRACTION
+#endif /* SURFACE_REFRACT */
+
+#if !defined(SURFACE_GLASS) && !defined(CLOSURE_NAME)
+ #define SURFACE_GLASS
+ #define CLOSURE_NAME eevee_closure_glass
+ #define CLOSURE_GLOSSY
+ #define CLOSURE_REFRACTION
+#endif /* SURFACE_GLASS */
+
+/* Safety : CLOSURE_CLEARCOAT implies CLOSURE_GLOSSY */
+#ifdef CLOSURE_CLEARCOAT
+ #ifndef CLOSURE_GLOSSY
+ #define CLOSURE_GLOSSY
+ #endif
+#endif /* CLOSURE_CLEARCOAT */
+
+void CLOSURE_NAME(
+ vec3 N
+#ifdef CLOSURE_DIFFUSE
+ , vec3 albedo
#endif
-
- roughness = clamp(roughness, 1e-8, 0.9999);
- float roughnessSquared = roughness * roughness;
-
- vec3 V = cameraVec;
-
- /* ---------------- SCENE LAMPS LIGHTING ----------------- */
-
-#ifdef HAIR_SHADER
- vec3 norm_view = cross(V, N);
- norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
+#ifdef CLOSURE_GLOSSY
+ , vec3 f0, int ssr_id
#endif
-
- vec3 diff = vec3(0.0);
- vec3 spec = vec3(0.0);
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
- LightData ld = lights_data[i];
-
- vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
- l_vector.xyz = ld.l_position - worldPosition;
- l_vector.w = length(l_vector.xyz);
-
- vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector);
-
-#ifdef HAIR_SHADER
- vec3 norm_lamp, view_vec;
- float occlu_trans, occlu;
- light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
-
- diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
- spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
-#else
- diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
- spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
+ , float roughness
#endif
- }
-
- /* Accumulate outgoing radiance */
- vec3 out_light = diff * albedo + spec * float(specToggle);
-
-#ifdef HAIR_SHADER
- N = -norm_view;
+#ifdef CLOSURE_CLEARCOAT
+ , vec3 C_N, float C_intensity, float C_roughness
#endif
-
- /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
-
- /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
- vec4 spec_accum = vec4(0.0);
-
- /* SSR lobe is applied later in a defered style */
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- /* Planar Reflections */
- for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
- PlanarData pd = planars_data[i];
-
- float fade = probe_attenuation_planar(pd, worldPosition, N, roughness);
-
- if (fade > 0.0) {
- vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
- accumulate_light(spec, fade, spec_accum);
- }
- }
-
- /* Specular probes */
- 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; ++i) {
- CubeData cd = probes_data[i];
-
- float fade = probe_attenuation_cube(cd, worldPosition);
-
- if (fade > 0.0) {
- vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
- accumulate_light(spec, fade, spec_accum);
- }
- }
-
- /* World Specular */
- if (spec_accum.a < 0.999) {
- vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
- accumulate_light(spec, 1.0, spec_accum);
- }
- }
-
- vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
-
- /* Ambient Occlusion */
- vec3 bent_normal;
- float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
-
- /* Get Brdf intensity */
- vec2 uv = lut_coords(dot(N, V), roughness);
- vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
-
- ssr_spec = F_ibl(f0, brdf_lut);
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
- }
- out_light += spec_accum.rgb * ssr_spec * float(specToggle);
-
- /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ----------------- */
-
- /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
- vec4 diff_accum = vec4(0.0);
-
- /* Start at 1 because 0 is world irradiance */
- for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
- GridData gd = grids_data[i];
-
- vec3 localpos;
- float fade = probe_attenuation_grid(gd, worldPosition, localpos);
-
- if (fade > 0.0) {
- vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
- accumulate_light(diff, fade, diff_accum);
- }
- }
-
- /* World Diffuse */
- if (diff_accum.a < 0.999 && grid_count > 0) {
- vec3 diff = probe_evaluate_world_diff(bent_normal);
- accumulate_light(diff, 1.0, diff_accum);
- }
-
- out_light += diff_accum.rgb * albedo * gtao_multibounce(final_ao, albedo);
-
- return out_light;
-}
-
-/* ----------- CLEAR COAT ----------- */
-
-vec3 eevee_surface_clearcoat_lit(
- vec3 N, vec3 albedo, vec3 f0, float roughness,
- vec3 C_N, float C_intensity, float C_roughness, /* Clearcoat params */
- float ao, int ssr_id, out vec3 ssr_spec)
-{
- roughness = clamp(roughness, 1e-8, 0.9999);
- float roughnessSquared = roughness * roughness;
- C_roughness = clamp(C_roughness, 1e-8, 0.9999);
- float C_roughnessSquared = C_roughness * C_roughness;
-
- /* Zero length vectors cause issues, see: T51979. */
-#if 0
- N = normalize(N);
- C_N = normalize(C_N);
-#else
- {
- float len = length(N);
- if (isnan(len)) {
- return vec3(0.0);
- }
- N /= len;
-
- len = length(C_N);
- if (isnan(len)) {
- return vec3(0.0);
- }
- C_N /= len;
- }
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
+ , float ao
#endif
-
- vec3 V = cameraVec;
-
- /* ---------------- SCENE LAMPS LIGHTING ----------------- */
-
-#ifdef HAIR_SHADER
- vec3 norm_view = cross(V, N);
- norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
+#ifdef CLOSURE_SUBSURFACE
+ , float sss_scale
#endif
-
- vec3 diff = vec3(0.0);
- vec3 spec = vec3(0.0);
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
- LightData ld = lights_data[i];
-
- vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
- l_vector.xyz = ld.l_position - worldPosition;
- l_vector.w = length(l_vector.xyz);
-
- vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector);
-
-#ifdef HAIR_SHADER
- vec3 norm_lamp, view_vec;
- float occlu_trans, occlu;
- light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
-
- diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
- spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
- spec += l_color_vis * light_specular(ld, C_N, view_vec, l_vector, C_roughnessSquared, f0) * C_intensity * occlu;
-#else
- diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
- spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
- spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity;
+#ifdef CLOSURE_REFRACTION
+ , float ior
#endif
- }
-
- /* Accumulate outgoing radiance */
- vec3 out_light = diff * albedo + spec * float(specToggle);
-
-#ifdef HAIR_SHADER
- N = -norm_view;
+#ifdef CLOSURE_DIFFUSE
+ , out vec3 out_diff
#endif
-
- /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
-
- /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
- vec4 spec_accum = vec4(0.0);
- vec4 C_spec_accum = vec4(0.0);
-
- /* Planar Reflections */
- for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
- PlanarData pd = planars_data[i];
-
- /* Fade on geometric normal. */
- float fade = probe_attenuation_planar(pd, worldPosition, worldNormal, roughness);
-
- if (fade > 0.0) {
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
- accumulate_light(spec, fade, spec_accum);
- }
-
- vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, C_roughness, fade);
- accumulate_light(C_spec, fade, C_spec_accum);
- }
- }
-
- /* Specular probes */
- vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
- vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared);
-
- /* Starts at 1 because 0 is world probe */
- for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
- CubeData cd = probes_data[i];
-
- float fade = probe_attenuation_cube(cd, worldPosition);
-
- if (fade > 0.0) {
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
- accumulate_light(spec, fade, spec_accum);
- }
-
- vec3 C_spec = probe_evaluate_cube(float(i), cd, worldPosition, C_spec_dir, C_roughness);
- accumulate_light(C_spec, fade, C_spec_accum);
- }
- }
-
- /* World Specular */
- if (spec_accum.a < 0.999) {
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
- accumulate_light(spec, 1.0, spec_accum);
- }
-
- vec3 C_spec = probe_evaluate_world_spec(C_spec_dir, C_roughness);
- accumulate_light(C_spec, 1.0, C_spec_accum);
- }
-
- vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
-
- /* Ambient Occlusion */
- vec3 bent_normal;
- float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
-
- /* Get Brdf intensity */
- vec2 uv = lut_coords(dot(N, V), roughness);
- vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
-
- ssr_spec = F_ibl(f0, brdf_lut);
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
- }
- out_light += spec_accum.rgb * ssr_spec * float(specToggle);
-
- uv = lut_coords(dot(C_N, V), C_roughness);
- brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
-
- out_light += C_spec_accum.rgb * F_ibl(vec3(0.04), brdf_lut) * specular_occlusion(dot(C_N, V), final_ao, C_roughness) * float(specToggle) * C_intensity;
-
- /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ----------------- */
-
- /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
- vec4 diff_accum = vec4(0.0);
-
- /* Start at 1 because 0 is world irradiance */
- for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
- GridData gd = grids_data[i];
-
- vec3 localpos;
- float fade = probe_attenuation_grid(gd, worldPosition, localpos);
-
- if (fade > 0.0) {
- vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
- accumulate_light(diff, fade, diff_accum);
- }
- }
-
- /* World Diffuse */
- if (diff_accum.a < 0.999 && grid_count > 0) {
- vec3 diff = probe_evaluate_world_diff(bent_normal);
- accumulate_light(diff, 1.0, diff_accum);
- }
-
- out_light += diff_accum.rgb * albedo * gtao_multibounce(final_ao, albedo);
-
- return out_light;
-}
-
-/* ----------- Diffuse ----------- */
-
-vec3 eevee_surface_diffuse_lit(vec3 N, vec3 albedo, float ao)
+#ifdef CLOSURE_SUBSURFACE
+ , out vec3 out_trans
+#endif
+#ifdef CLOSURE_GLOSSY
+ , out vec3 out_spec
+#endif
+#ifdef CLOSURE_REFRACTION
+ , out vec3 out_refr
+#endif
+#ifdef CLOSURE_GLOSSY
+ , out vec3 ssr_spec
+#endif
+ )
{
- vec3 V = cameraVec;
-
- /* Zero length vectors cause issues, see: T51979. */
-#if 0
- N = normalize(N);
-#else
- {
- float len = length(N);
- if (isnan(len)) {
- return vec3(0.0);
- }
- N /= len;
- }
+#ifdef CLOSURE_DIFFUSE
+ out_diff = vec3(0.0);
#endif
- /* ---------------- SCENE LAMPS LIGHTING ----------------- */
-
-#ifdef HAIR_SHADER
- vec3 norm_view = cross(V, N);
- norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
+#ifdef CLOSURE_SUBSURFACE
+ out_trans = vec3(0.0);
#endif
- vec3 diff = vec3(0.0);
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
- LightData ld = lights_data[i];
-
- vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
- l_vector.xyz = ld.l_position - worldPosition;
- l_vector.w = length(l_vector.xyz);
-
- vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector);
-
-#ifdef HAIR_SHADER
- vec3 norm_lamp, view_vec;
- float occlu_trans, occlu;
- light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
-
- diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
-#else
- diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
+#ifdef CLOSURE_GLOSSY
+ out_spec = vec3(0.0);
#endif
- }
-
- /* Accumulate outgoing radiance */
- vec3 out_light = diff * albedo;
-#ifdef HAIR_SHADER
- N = -norm_view;
+#ifdef CLOSURE_REFRACTION
+ out_refr = vec3(0.0);
#endif
- /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ----------------- */
-
- vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
-
- /* Ambient Occlusion */
- vec3 bent_normal;
- float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
-
- /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
- vec4 diff_accum = vec4(0.0);
-
- /* Start at 1 because 0 is world irradiance */
- for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
- GridData gd = grids_data[i];
-
- vec3 localpos;
- float fade = probe_attenuation_grid(gd, worldPosition, localpos);
-
- if (fade > 0.0) {
- vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
- accumulate_light(diff, fade, diff_accum);
- }
+ /* Zero length vectors cause issues, see: T51979. */
+ float len = length(N);
+ if (isnan(len)) {
+ return;
}
+ N /= len;
- /* World Diffuse */
- if (diff_accum.a < 0.999 && grid_count > 0) {
- vec3 diff = probe_evaluate_world_diff(bent_normal);
- accumulate_light(diff, 1.0, diff_accum);
+#ifdef CLOSURE_CLEARCOAT
+ len = length(C_N);
+ if (isnan(len)) {
+ return;
}
+ C_N /= len;
+#endif
- out_light += diff_accum.rgb * albedo * gtao_multibounce(final_ao, albedo);
-
- return out_light;
-}
-
-/* ----------- Glossy ----------- */
-
-vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec)
-{
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
roughness = clamp(roughness, 1e-8, 0.9999);
float roughnessSquared = roughness * roughness;
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+ C_roughness = clamp(C_roughness, 1e-8, 0.9999);
+ float C_roughnessSquared = C_roughness * C_roughness;
+#endif
vec3 V = cameraVec;
- /* Zero length vectors cause issues, see: T51979. */
-#if 0
- N = normalize(N);
-#else
- {
- float len = length(N);
- if (isnan(len)) {
- return vec3(0.0);
- }
- N /= len;
- }
-#endif
+ vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
- /* ---------------- SCENE LAMPS LIGHTING ----------------- */
+ /* ---------------------------------------------------------------- */
+ /* -------------------- SCENE LAMPS LIGHTING ---------------------- */
+ /* ---------------------------------------------------------------- */
#ifdef HAIR_SHADER
vec3 norm_view = cross(V, N);
norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
#endif
- vec3 spec = vec3(0.0);
for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
LightData ld = lights_data[i];
@@ -487,384 +201,300 @@ vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ss
float occlu_trans, occlu;
light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
- spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
-#else
- spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
-#endif
- }
-
- /* Accumulate outgoing radiance */
- vec3 out_light = spec * float(specToggle);
-
-#ifdef HAIR_SHADER
- N = -norm_view;
-#endif
-
- /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
-
- /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
- vec4 spec_accum = vec4(0.0);
-
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- /* Planar Reflections */
- for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
- PlanarData pd = planars_data[i];
-
- float fade = probe_attenuation_planar(pd, worldPosition, N, roughness);
-
- if (fade > 0.0) {
- vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
- accumulate_light(spec, fade, spec_accum);
- }
- }
+ #ifdef CLOSURE_DIFFUSE
+ out_diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
+ #endif
- /* Specular probes */
- vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
+ #ifdef CLOSURE_SUBSURFACE
+ out_trans += ld.l_color * light_translucent(ld, worldPosition, -norm_lamp, l_vector, sss_scale) * occlu_trans;
+ #endif
- /* Starts at 1 because 0 is world probe */
- for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
- CubeData cd = probes_data[i];
+ #ifdef CLOSURE_GLOSSY
+ out_spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
+ #endif
- float fade = probe_attenuation_cube(cd, worldPosition);
+ #ifdef CLOSURE_CLEARCOAT
+ out_spec += l_color_vis * light_specular(ld, C_N, view_vec, l_vector, C_roughnessSquared, f0) * C_intensity * occlu;
+ #endif
- if (fade > 0.0) {
- vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
- accumulate_light(spec, fade, spec_accum);
- }
- }
+#else /* HAIR_SHADER */
- /* World Specular */
- if (spec_accum.a < 0.999) {
- vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
- accumulate_light(spec, 1.0, spec_accum);
- }
- }
+ #ifdef CLOSURE_DIFFUSE
+ out_diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
+ #endif
- vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
+ #ifdef CLOSURE_SUBSURFACE
+ out_trans += ld.l_color * light_translucent(ld, worldPosition, -N, l_vector, sss_scale);
+ #endif
- /* Get Brdf intensity */
- vec2 uv = lut_coords(dot(N, V), roughness);
- vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
+ #ifdef CLOSURE_GLOSSY
+ out_spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
+ #endif
- ssr_spec = F_ibl(f0, brdf_lut);
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- /* Ambient Occlusion */
- vec3 bent_normal;
- float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
+ #ifdef CLOSURE_CLEARCOAT
+ out_spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity;
+ #endif
- ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
+#endif /* HAIR_SHADER */
}
- out_light += spec_accum.rgb * ssr_spec * float(specToggle);
- return out_light;
-}
-
-/* ----------- Transmission ----------- */
-
-vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior)
-{
- /* Zero length vectors cause issues, see: T51979. */
-#if 0
- N = normalize(N);
-#else
- {
- float len = length(N);
- if (isnan(len)) {
- return vec3(0.0);
- }
- N /= len;
- }
+#ifdef HAIR_SHADER
+ N = -norm_view;
#endif
- vec3 V = cameraVec;
- ior = (gl_FrontFacing) ? ior : 1.0 / ior;
-
- roughness = clamp(roughness, 1e-8, 0.9999);
- float roughnessSquared = roughness * roughness;
- /* ---------------- SCENE LAMPS LIGHTING ----------------- */
- /* No support for now. Supporting LTCs mean having a 3D LUT.
- * We could support point lights easily though. */
+ /* ---------------------------------------------------------------- */
/* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
+ /* ---------------------------------------------------------------- */
- /* 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;
+ /* Accumulate incomming light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
+#ifdef CLOSURE_GLOSSY
+ vec4 spec_accum = vec4(0.0);
+#endif
- /* Find approximated position of the 2nd refraction event. */
- vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition;
+#ifdef CLOSURE_CLEARCOAT
+ vec4 C_spec_accum = vec4(0.0);
+#endif
- float ray_ofs = 1.0 / float(rayCount);
- 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);
- }
+#ifdef CLOSURE_REFRACTION
+ vec4 refr_accum = vec4(0.0);
#endif
- /* Specular probes */
- /* NOTE: This bias the IOR */
- vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
+#ifdef CLOSURE_GLOSSY
+ /* ---------------------------- */
+ /* Planar Reflections */
+ /* ---------------------------- */
- /* Starts at 1 because 0 is world probe */
- for (int i = 1; i < MAX_PROBE && i < probe_count && trans_accum.a < 0.999; ++i) {
- CubeData cd = probes_data[i];
+ for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
+ PlanarData pd = planars_data[i];
- float fade = probe_attenuation_cube(cd, worldPosition);
+ /* Fade on geometric normal. */
+ float fade = probe_attenuation_planar(pd, worldPosition, worldNormal, roughness);
if (fade > 0.0) {
- 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(refr_dir, roughnessSquared);
- accumulate_light(spec, 1.0, trans_accum);
- }
-
- float btdf = get_btdf_lut(utilTex, dot(N, V), roughness, ior);
+ if (!(ssrToggle && ssr_id == outputSsrId)) {
+ vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
+ accumulate_light(spec, fade, spec_accum);
+ }
- return trans_accum.rgb * btdf;
-}
+ #ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, C_roughness, fade);
+ accumulate_light(C_spec, fade, C_spec_accum);
+ #endif
-vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float ior, int ssr_id, out vec3 ssr_spec)
-{
- /* Zero length vectors cause issues, see: T51979. */
-#if 0
- N = normalize(N);
-#else
- {
- float len = length(N);
- if (isnan(len)) {
- return vec3(0.0);
}
- N /= len;
}
#endif
- vec3 V = cameraVec;
- ior = (gl_FrontFacing) ? ior : 1.0 / ior;
-
- if (!specToggle) return vec3(0.0);
-
- roughness = clamp(roughness, 1e-8, 0.9999);
- float roughnessSquared = roughness * roughness;
-
- /* ---------------- SCENE LAMPS LIGHTING ----------------- */
-
-#ifdef HAIR_SHADER
- vec3 norm_view = cross(V, N);
- norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
-#endif
-
- vec3 spec = vec3(0.0);
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
- LightData ld = lights_data[i];
-
- vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
- l_vector.xyz = ld.l_position - worldPosition;
- l_vector.w = length(l_vector.xyz);
-
- vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector);
-#ifdef HAIR_SHADER
- vec3 norm_lamp, view_vec;
- float occlu_trans, occlu;
- light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
- spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, vec3(1.0)) * occlu;
-#else
- spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, vec3(1.0));
+#ifdef CLOSURE_GLOSSY
+ vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
#endif
- }
- /* Accumulate outgoing radiance */
- vec3 out_light = spec;
-
-#ifdef HAIR_SHADER
- N = -norm_view;
+#ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared);
#endif
-
- /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
-
- /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
- vec4 spec_accum = vec4(0.0);
-
- /* Planar Reflections */
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999 && roughness < 0.1; ++i) {
- PlanarData pd = planars_data[i];
-
- float fade = probe_attenuation_planar(pd, worldPosition, N, roughness);
-
- if (fade > 0.0) {
- vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
- accumulate_light(spec, fade, spec_accum);
- }
- }
- }
-
+#ifdef CLOSURE_REFRACTION
/* 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;
+ vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
+#endif
- vec4 trans_accum = vec4(0.0);
-#ifdef USE_REFRACTION
- /* Screen Space Refraction */
+#ifdef CLOSURE_REFRACTION
+ /* ---------------------------- */
+ /* Screen Space Refraction */
+ /* ---------------------------- */
+ #ifdef USE_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(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);
+ vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw, 0.0);
+ if (rayCount > 1) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
+ if (rayCount > 2) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
+ if (rayCount > 3) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
+ trans /= float(rayCount);
+ trans.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
+ accumulate_light(trans.rgb, trans.a, refr_accum);
}
+ #endif
+
#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);
+
+ /* ---------------------------- */
+ /* Specular probes */
+ /* ---------------------------- */
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
+
+ #ifdef CLOSURE_REFRACTION
+ #define ACCUM refr_accum
+ #else
+ #define ACCUM spec_accum
+ #endif
/* 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) {
+ for (int i = 1; ACCUM.a < 0.999 && i < probe_count && i < MAX_PROBE; ++i) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, worldPosition);
if (fade > 0.0) {
+
+ #ifdef CLOSURE_GLOSSY
if (!(ssrToggle && ssr_id == outputSsrId)) {
vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
accumulate_light(spec, fade, spec_accum);
}
+ #endif
+
+ #ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec = probe_evaluate_cube(float(i), cd, worldPosition, C_spec_dir, C_roughness);
+ accumulate_light(C_spec, fade, C_spec_accum);
+ #endif
- spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
- accumulate_light(spec, fade, trans_accum);
+ #ifdef CLOSURE_REFRACTION
+ vec3 trans = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
+ accumulate_light(trans, fade, refr_accum);
+ #endif
}
}
- /* World Specular */
+ #undef ACCUM
+
+ /* ---------------------------- */
+ /* World Probe */
+ /* ---------------------------- */
+ #ifdef CLOSURE_GLOSSY
if (spec_accum.a < 0.999) {
if (!(ssrToggle && ssr_id == outputSsrId)) {
vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
accumulate_light(spec, 1.0, spec_accum);
}
+
+ #ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec = probe_evaluate_world_spec(C_spec_dir, C_roughness);
+ accumulate_light(C_spec, 1.0, C_spec_accum);
+ #endif
+
}
+ #endif
- if (trans_accum.a < 0.999) {
- spec = probe_evaluate_world_spec(refr_dir, roughnessSquared);
- accumulate_light(spec, 1.0, trans_accum);
+ #ifdef CLOSURE_REFRACTION
+ if (refr_accum.a < 0.999) {
+ vec3 trans = probe_evaluate_world_spec(refr_dir, roughnessSquared);
+ accumulate_light(trans, 1.0, refr_accum);
}
+ #endif
+#endif /* Specular probes */
+
+
+ /* ---------------------------- */
+ /* Ambient Occlusion */
+ /* ---------------------------- */
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
+ vec3 bent_normal;
+ float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
+#endif
- /* Ambient Occlusion */
- /* TODO : when AO will be cheaper */
- float final_ao = 1.0;
+ /* ---------------------------- */
+ /* Specular Output */
+ /* ---------------------------- */
float NV = dot(N, V);
- /* Get Brdf intensity */
+#ifdef CLOSURE_GLOSSY
vec2 uv = lut_coords(NV, roughness);
vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
- float fresnel = F_eta(ior, NV);
-
- /* Apply fresnel on lamps. */
- out_light *= vec3(fresnel);
-
- ssr_spec = vec3(fresnel) * F_ibl(vec3(1.0), brdf_lut);
+ /* This factor is outputed to be used by SSR in order
+ * to match the intensity of the regular reflections. */
+ ssr_spec = F_ibl(f0, brdf_lut);
if (!(ssrToggle && ssr_id == outputSsrId)) {
- ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
+ /* The SSR pass recompute the occlusion to not apply it to the SSR */
+ ssr_spec *= specular_occlusion(NV, final_ao, roughness);
}
- out_light += spec_accum.rgb * ssr_spec;
+ out_spec += spec_accum.rgb * ssr_spec * float(specToggle);
+#endif
+#ifdef CLOSURE_REFRACTION
float btdf = get_btdf_lut(utilTex, NV, roughness, ior);
- out_light += vec3(1.0 - fresnel) * transmission_col * trans_accum.rgb * btdf;
-
- return out_light;
-}
+ out_refr += refr_accum.rgb * btdf;
+#endif
-/* ----------- Translucency ----------- */
+#ifdef CLOSURE_CLEARCOAT
+ 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), brdf_lut) * specular_occlusion(NV, final_ao, C_roughness);
-vec3 eevee_surface_translucent_lit(vec3 N, vec3 albedo, float sss_scale)
-{
-#ifndef USE_TRANSLUCENCY
- return vec3(0.0);
+ out_spec += C_spec_accum.rgb * C_fresnel * float(specToggle) * C_intensity;
#endif
- vec3 V = cameraVec;
+ /* ---------------------------------------------------------------- */
+ /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ------------------ */
+ /* ---------------------------------------------------------------- */
- /* Zero length vectors cause issues, see: T51979. */
-#if 0
- N = normalize(N);
-#else
- {
- float len = length(N);
- if (isnan(len)) {
- return vec3(0.0);
+ /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
+#ifdef CLOSURE_DIFFUSE
+ vec4 diff_accum = vec4(0.0);
+
+ /* ---------------------------- */
+ /* Irradiance Grids */
+ /* ---------------------------- */
+ /* Start at 1 because 0 is world irradiance */
+ for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
+ GridData gd = grids_data[i];
+
+ vec3 localpos;
+ float fade = probe_attenuation_grid(gd, worldPosition, localpos);
+
+ if (fade > 0.0) {
+ vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
+ accumulate_light(diff, fade, diff_accum);
}
- N /= len;
}
-#endif
- /* We only enlit the backfaces */
- N = -N;
-
- /* ---------------- SCENE LAMPS LIGHTING ----------------- */
+ /* ---------------------------- */
+ /* World Diffuse */
+ /* ---------------------------- */
+ if (diff_accum.a < 0.999 && grid_count > 0) {
+ vec3 diff = probe_evaluate_world_diff(bent_normal);
+ accumulate_light(diff, 1.0, diff_accum);
+ }
-#ifdef HAIR_SHADER
- vec3 norm_view = cross(V, N);
- norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
+ out_diff += diff_accum.rgb * gtao_multibounce(final_ao, albedo);
#endif
+}
- vec3 diff = vec3(0.0);
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
- LightData ld = lights_data[i];
+/* Cleanup for next configuration */
+#undef CLOSURE_NAME
- vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
- l_vector.xyz = ld.l_position - worldPosition;
- l_vector.w = length(l_vector.xyz);
+#ifdef CLOSURE_DIFFUSE
+ #undef CLOSURE_DIFFUSE
+#endif
-#ifdef HAIR_SHADER
- vec3 norm_lamp, view_vec;
- float occlu_trans, occlu;
- light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
+#ifdef CLOSURE_GLOSSY
+ #undef CLOSURE_GLOSSY
+#endif
- diff += ld.l_color * light_translucent(ld, worldPosition, norm_lamp, l_vector, sss_scale) * occlu_trans;
-#else
- diff += ld.l_color * light_translucent(ld, worldPosition, N, l_vector, sss_scale);
+#ifdef CLOSURE_CLEARCOAT
+ #undef CLOSURE_CLEARCOAT
#endif
- }
- /* Accumulate outgoing radiance */
- vec3 out_light = diff * albedo;
+#ifdef CLOSURE_REFRACTION
+ #undef CLOSURE_REFRACTION
+#endif
- return out_light;
-}
+#ifdef CLOSURE_SUBSURFACE
+ #undef CLOSURE_SUBSURFACE
+#endif \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index c3345f51b4c..b23c1708ee1 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2670,11 +2670,11 @@ layout(std140) uniform lightSource {
void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
{
#ifdef EEVEE_ENGINE
- vec3 L = eevee_surface_diffuse_lit(N, vec3(1.0), 1.0);
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
- result.radiance = L * color.rgb;
result.ssr_normal = normal_encode(vN, viewCameraVec);
+ eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance);
+ result.radiance *= color.rgb;
#else
/* ambient light */
vec3 L = vec3(0.2);
@@ -2695,12 +2695,12 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result)
{
#ifdef EEVEE_ENGINE
- vec3 ssr_spec;
+ vec3 out_spec, ssr_spec;
roughness = sqrt(roughness);
- vec3 L = eevee_surface_glossy_lit(N, vec3(1.0), roughness, 1.0, int(ssr_id), ssr_spec);
+ eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
- result.radiance = L * color.rgb;
+ result.radiance = out_spec * color.rgb;
result.ssr_data = vec4(ssr_spec * color.rgb, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
@@ -2737,13 +2737,17 @@ void node_bsdf_anisotropic(
void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result)
{
#ifdef EEVEE_ENGINE
- vec3 ssr_spec;
+ vec3 out_spec, out_refr, ssr_spec;
roughness = sqrt(roughness);
- vec3 L = eevee_surface_glass(N, (refractionDepth > 0.0) ? color.rgb : vec3(1.0), roughness, ior, int(ssr_id), ssr_spec);
+ vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : color.rgb; /* Simulate 2 transmission event */
+ eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+ out_refr *= refr_color;
+ out_spec *= color.rgb;
+ float fresnel = F_eta(ior, dot(N, cameraVec));
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
- result.radiance = L * color.rgb;
- result.ssr_data = vec4(ssr_spec * color.rgb, roughness);
+ result.radiance = mix(out_refr, out_spec, fresnel);
+ result.ssr_data = vec4(ssr_spec * color.rgb * fresnel, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
#else
@@ -2856,109 +2860,57 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
}
#endif
-void node_bsdf_principled_simple(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
- float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, out Closure result)
-{
-#ifdef EEVEE_ENGINE
- vec3 diffuse, f0, ssr_spec;
- convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
-
-#ifdef USE_SSS
- diffuse = mix(diffuse, vec3(0.0), subsurface);
-#else
- diffuse = mix(diffuse, subsurface_color.rgb, subsurface);
-#endif
-
- vec3 L = eevee_surface_lit(N, diffuse, f0, roughness, 1.0, int(ssr_id), ssr_spec);
- vec3 vN = normalize(mat3(ViewMatrix) * N);
- result = CLOSURE_DEFAULT;
- result.radiance = L;
- result.ssr_data = vec4(ssr_spec, roughness);
- result.ssr_normal = normal_encode(vN, viewCameraVec);
- result.ssr_id = int(ssr_id);
-
-#ifdef USE_SSS
- /* OPTI : Make irradiance computation shared with the diffuse. */
- result.sss_data.rgb = eevee_surface_diffuse_lit(N, vec3(1.0), 1.0);
- result.sss_data.rgb += eevee_surface_translucent_lit(N, vec3(1.0), 1.0);
- result.sss_data.rgb *= mix(vec3(0.0), subsurface_color.rgb, subsurface);
- result.sss_data.a = 1.0; /* TODO Find a parametrization */
-#endif
-#else
- node_bsdf_principled(base_color, subsurface, subsurface_radius, subsurface_color, metallic, specular,
- specular_tint, roughness, anisotropic, anisotropic_rotation, sheen, sheen_tint, clearcoat,
- clearcoat_roughness, ior, transmission, transmission_roughness, N, CN, T, I, result);
-#endif
-}
-
void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
float sss_id, vec3 sss_scale, out Closure result)
{
#ifdef EEVEE_ENGINE
- if (clearcoat == 0.0) {
- node_bsdf_principled_simple(
- base_color, subsurface, subsurface_radius, subsurface_color, metallic, specular,
- specular_tint, roughness, anisotropic, anisotropic_rotation, sheen, sheen_tint, clearcoat,
- clearcoat_roughness, ior, transmission, transmission_roughness, N, CN, T, I, ssr_id, result);
- return;
- }
+ metallic = saturate(metallic);
+ transmission = saturate(transmission);
- vec3 diffuse, f0, ssr_spec;
+ vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec;
convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
- clearcoat *= 0.25;
-#if 0 /* Wait until temporal AA (aka. denoising) */
-
- vec3 X, Y;
- float ax, ay;
- prepare_tangent(anisotropic, anisotropic_rotation, roughness, N, T, X, Y, ax, ay);
-
- /* Distribute N in anisotropy direction. */
- vec4 surface_color = vec4(0.0);
- for (float i = 0.0; i < 5.0; ++i) {
- vec4 rand = texture(utilTex, vec3((gl_FragCoord.xy + i) / LUT_SIZE, 2.0));
-
- float tmp = sqrt( rand.x / (1.0 - rand.x) );
- float x = (ax > ay ? ax : 0.0) * tmp * rand.z;
- float y = (ay > ax ? ay : 0.0) * tmp * rand.w;
- vec3 Ht = normalize(vec3(x, y, 1.0));
- N = tangent_to_world(Ht, N, Y, X);
+ transmission *= 1.0 - metallic;
+ subsurface *= 1.0 - metallic;
- if (dot(N, cameraVec) > 0) {
- surface_color.rgb += eevee_surface_clearcoat_lit(N, diffuse, f0, sqrt(min(ax, ay)), CN, clearcoat, clearcoat_roughness, 1.0, ssr_id);
- surface_color.a += 1.0;
- }
- }
- result = Closure(surface_color.rgb / surface_color.a, 1.0);
-#else
+ clearcoat *= 0.25;
+ clearcoat *= 1.0 - transmission;
#ifdef USE_SSS
diffuse = mix(diffuse, vec3(0.0), subsurface);
#else
diffuse = mix(diffuse, subsurface_color.rgb, subsurface);
#endif
+ f0 = mix(f0, vec3(1.0), transmission);
+
+ float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0));
+ eevee_closure_principled(N, diffuse, f0, int(ssr_id), roughness,
+ CN, clearcoat, clearcoat_roughness, 1.0, sss_scalef, ior,
+ out_diff, out_trans, out_spec, out_refr, ssr_spec);
+
+ vec3 refr_color = base_color.rgb;
+ refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */
+
+ float fresnel = F_eta(ior, dot(N, cameraVec));
+ vec3 refr_spec_color = base_color.rgb * fresnel;
+ /* This bit maybe innacurate. */
+ out_refr = out_refr * refr_color * (1.0 - fresnel) + out_spec * refr_spec_color;
+
+ ssr_spec = mix(ssr_spec, refr_spec_color, transmission);
- vec3 L_trans = (transmission <= 0.0) ? vec3(0.0) : eevee_surface_glass(N, base_color.rgb * ((refractionDepth > 0.0) ? base_color.rgb : vec3(1.0)), roughness, ior, REFRACT_CLOSURE_FLAG, ssr_spec);
- vec3 L = eevee_surface_clearcoat_lit(N, diffuse, f0, roughness, CN, clearcoat, clearcoat_roughness, 1.0, int(ssr_id), ssr_spec);
- L = mix(L, L_trans, transmission);
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
- result.radiance = L;
+ result.radiance = out_spec + out_diff * diffuse;
+ result.radiance = mix(result.radiance, out_refr, transmission);
result.ssr_data = vec4(ssr_spec, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
-
#ifdef USE_SSS
- /* OPTI : Make irradiance computation shared with the diffuse. */
- result.sss_data.a = dot(sss_scale, vec3(1.0 / 3.0));
- result.sss_data.rgb = eevee_surface_translucent_lit(N, subsurface_color.rgb, result.sss_data.a);
- result.sss_data.rgb += eevee_surface_diffuse_lit(N, vec3(1.0), 1.0);
- result.sss_data.rgb *= mix(vec3(0.0), subsurface_color.rgb, subsurface);
-#endif
-
+ result.sss_data.a = sss_scalef;
+ result.sss_data.rgb = (out_diff + out_trans) * mix(vec3(0.0), subsurface_color.rgb, subsurface);
+ result.sss_data.rgb *= (1.0 - transmission);
#endif
#else
@@ -2994,14 +2946,15 @@ void node_subsurface_scattering(
out Closure result)
{
#if defined(EEVEE_ENGINE) && defined(USE_SSS)
+ vec3 out_diff, out_trans;
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
result.ssr_data = vec4(0.0);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = -1;
- result.sss_data.rgb = eevee_surface_translucent_lit(N, color.rgb, scale);
- result.sss_data.rgb += eevee_surface_diffuse_lit(N, color.rgb, 1.0);
result.sss_data.a = scale;
+ eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans);
+ result.sss_data.rgb = (out_diff + out_trans) * color.rgb;
#else
node_bsdf_diffuse(color, 0.0, N, result);
#endif
@@ -3010,11 +2963,12 @@ void node_subsurface_scattering(
void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result)
{
#ifdef EEVEE_ENGINE
+ vec3 out_refr;
color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
roughness = sqrt(roughness);
- vec3 L = eevee_surface_refraction(N, vec3(1.0), roughness, ior);
+ eevee_closure_refraction(N, roughness, ior, out_refr);
result = CLOSURE_DEFAULT;
- result.radiance = L * color.rgb;
+ result.radiance = out_refr * color.rgb;
result.ssr_id = REFRACT_CLOSURE_FLAG;
#else
node_bsdf_diffuse(color, 0.0, N, result);
@@ -4210,12 +4164,13 @@ void node_eevee_specular(
float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal,
float occlusion, float ssr_id, out Closure result)
{
- vec3 ssr_spec;
+ vec3 out_diff, out_spec, ssr_spec;
+ eevee_closure_default(normal, diffuse.rgb, specular.rgb, int(ssr_id), roughness, occlusion,
+ out_diff, out_spec, ssr_spec);
- vec3 L = eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion, int(ssr_id), ssr_spec);
vec3 vN = normalize(mat3(ViewMatrix) * normal);
result = CLOSURE_DEFAULT;
- result.radiance = L + emissive.rgb;
+ result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb;
result.opacity = 1.0 - transp;
result.ssr_data = vec4(ssr_spec, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);