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.
This commit is contained in:
Clément Foucault
2017-11-24 06:15:42 +01:00
parent 16a2802149
commit 2302ba2245
5 changed files with 425 additions and 832 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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,195 +31,162 @@ in vec3 viewNormal;
uniform float maxRoughness;
uniform int rayCount;
/* ----------- default ----------- */
#endif /* LIT_SURFACE_UNIFORM */
vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec)
/** 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
#ifdef CLOSURE_GLOSSY
, vec3 f0, int ssr_id
#endif
#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
, float roughness
#endif
#ifdef CLOSURE_CLEARCOAT
, vec3 C_N, float C_intensity, float C_roughness
#endif
#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
, float ao
#endif
#ifdef CLOSURE_SUBSURFACE
, float sss_scale
#endif
#ifdef CLOSURE_REFRACTION
, float ior
#endif
#ifdef CLOSURE_DIFFUSE
, out vec3 out_diff
#endif
#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
)
{
/* 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
#ifdef CLOSURE_SUBSURFACE
out_trans = vec3(0.0);
#endif
#ifdef CLOSURE_GLOSSY
out_spec = vec3(0.0);
#endif
#ifdef CLOSURE_REFRACTION
out_refr = vec3(0.0);
#endif
/* Zero length vectors cause issues, see: T51979. */
float len = length(N);
if (isnan(len)) {
return;
}
N /= len;
#ifdef CLOSURE_CLEARCOAT
len = length(C_N);
if (isnan(len)) {
return;
}
C_N /= len;
#endif
#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;
/* ---------------- SCENE LAMPS LIGHTING ----------------- */
#ifdef HAIR_SHADER
vec3 norm_view = cross(V, N);
norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
#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);
#endif
}
/* Accumulate outgoing radiance */
vec3 out_light = diff * albedo + 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);
/* 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;
}
#endif
vec3 V = cameraVec;
/* ---------------- 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 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];
@@ -231,30 +201,71 @@ vec3 eevee_surface_clearcoat_lit(
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;
#endif
}
#ifdef CLOSURE_DIFFUSE
out_diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
#endif
/* Accumulate outgoing radiance */
vec3 out_light = diff * albedo + spec * float(specToggle);
#ifdef CLOSURE_SUBSURFACE
out_trans += ld.l_color * light_translucent(ld, worldPosition, -norm_lamp, l_vector, sss_scale) * occlu_trans;
#endif
#ifdef CLOSURE_GLOSSY
out_spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
#endif
#ifdef CLOSURE_CLEARCOAT
out_spec += l_color_vis * light_specular(ld, C_N, view_vec, l_vector, C_roughnessSquared, f0) * C_intensity * occlu;
#endif
#else /* HAIR_SHADER */
#ifdef CLOSURE_DIFFUSE
out_diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
#endif
#ifdef CLOSURE_SUBSURFACE
out_trans += ld.l_color * light_translucent(ld, worldPosition, -N, l_vector, sss_scale);
#endif
#ifdef CLOSURE_GLOSSY
out_spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
#endif
#ifdef CLOSURE_CLEARCOAT
out_spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity;
#endif
#endif /* HAIR_SHADER */
}
#ifdef HAIR_SHADER
N = -norm_view;
#endif
/* ---------------------------------------------------------------- */
/* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
/* ---------------------------------------------------------------- */
/* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
/* Accumulate incomming light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
#ifdef CLOSURE_GLOSSY
vec4 spec_accum = vec4(0.0);
vec4 C_spec_accum = vec4(0.0);
#endif
#ifdef CLOSURE_CLEARCOAT
vec4 C_spec_accum = vec4(0.0);
#endif
#ifdef CLOSURE_REFRACTION
vec4 refr_accum = vec4(0.0);
#endif
#ifdef CLOSURE_GLOSSY
/* ---------------------------- */
/* Planar Reflections */
/* ---------------------------- */
/* Planar Reflections */
for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
PlanarData pd = planars_data[i];
@@ -267,604 +278,223 @@ vec3 eevee_surface_clearcoat_lit(
accumulate_light(spec, fade, spec_accum);
}
#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
}
}
#endif
/* Specular probes */
#ifdef CLOSURE_GLOSSY
vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
#endif
#ifdef CLOSURE_CLEARCOAT
vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared);
#endif
#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
#ifdef CLOSURE_REFRACTION
/* ---------------------------- */
/* Screen Space Refraction */
/* ---------------------------- */
#ifdef USE_REFRACTION
if (ssrToggle && roughness < maxRoughness + 0.2) {
/* 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 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 */
/* ---------------------------- */
#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; ++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
#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
vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
#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 */
/* ---------------------------- */
/* Ambient Occlusion */
/* ---------------------------- */
#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
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)
{
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
/* ---------------- SCENE LAMPS LIGHTING ----------------- */
#ifdef HAIR_SHADER
vec3 norm_view = cross(V, N);
norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
#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);
#endif
}
/* Accumulate outgoing radiance */
vec3 out_light = diff * albedo;
#ifdef HAIR_SHADER
N = -norm_view;
#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);
}
}
/* 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;
}
/* ----------- Glossy ----------- */
vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec)
{
roughness = clamp(roughness, 1e-8, 0.9999);
float roughnessSquared = roughness * roughness;
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
/* ---------------- 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, 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);
}
}
/* 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));
/* 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)) {
/* Ambient Occlusion */
vec3 bent_normal;
float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
}
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;
}
#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;
/* 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);
}
#endif
/* Specular probes */
/* NOTE: This bias the 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) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, worldPosition);
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);
return trans_accum.rgb * btdf;
}
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));
#endif
}
/* Accumulate outgoing radiance */
vec3 out_light = spec;
#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);
/* 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);
}
}
}
/* 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
/* 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(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];
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);
}
spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
accumulate_light(spec, fade, trans_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);
}
}
if (trans_accum.a < 0.999) {
spec = probe_evaluate_world_spec(refr_dir, roughnessSquared);
accumulate_light(spec, 1.0, trans_accum);
}
/* 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;
}
/* ----------- Translucency ----------- */
vec3 eevee_surface_translucent_lit(vec3 N, vec3 albedo, float sss_scale)
{
#ifndef USE_TRANSLUCENCY
return vec3(0.0);
out_refr += refr_accum.rgb * btdf;
#endif
vec3 V = cameraVec;
#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);
/* Zero length vectors cause issues, see: T51979. */
#if 0
N = normalize(N);
#else
{
float len = length(N);
if (isnan(len)) {
return vec3(0.0);
out_spec += C_spec_accum.rgb * C_fresnel * float(specToggle) * C_intensity;
#endif
/* ---------------------------------------------------------------- */
/* ---------------- DIFFUSE ENVIRONMENT LIGHTING ------------------ */
/* ---------------------------------------------------------------- */
/* 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 ----------------- */
#ifdef HAIR_SHADER
vec3 norm_view = cross(V, N);
norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
#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);
#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 += 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);
#endif
}
/* Accumulate outgoing radiance */
vec3 out_light = diff * albedo;
/* ---------------------------- */
/* 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);
}
return out_light;
out_diff += diff_accum.rgb * gtao_multibounce(final_ao, albedo);
#endif
}
/* Cleanup for next configuration */
#undef CLOSURE_NAME
#ifdef CLOSURE_DIFFUSE
#undef CLOSURE_DIFFUSE
#endif
#ifdef CLOSURE_GLOSSY
#undef CLOSURE_GLOSSY
#endif
#ifdef CLOSURE_CLEARCOAT
#undef CLOSURE_CLEARCOAT
#endif
#ifdef CLOSURE_REFRACTION
#undef CLOSURE_REFRACTION
#endif
#ifdef CLOSURE_SUBSURFACE
#undef CLOSURE_SUBSURFACE
#endif

View File

@@ -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);
transmission *= 1.0 - metallic;
subsurface *= 1.0 - metallic;
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);
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 *= 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);