426 lines
17 KiB
GLSL
426 lines
17 KiB
GLSL
#ifndef VOLUMETRICS
|
|
vec3 tint_from_color(vec3 color)
|
|
{
|
|
float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
|
|
return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
|
|
}
|
|
|
|
void convert_metallic_to_specular_tinted(vec3 basecol,
|
|
vec3 basecol_tint,
|
|
float metallic,
|
|
float specular_fac,
|
|
float specular_tint,
|
|
out vec3 diffuse,
|
|
out vec3 f0)
|
|
{
|
|
vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint);
|
|
f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic);
|
|
diffuse = basecol * (1.0 - metallic);
|
|
}
|
|
|
|
vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint)
|
|
{
|
|
float f = 1.0 - NV;
|
|
/* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps,
|
|
* therefore we need to clamp value. */
|
|
f = clamp(f, 0.0, 1.0);
|
|
/* Empirical approximation (manual curve fitting). Can be refined. */
|
|
float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026;
|
|
return sheen * mix(vec3(1.0), basecol_tint, sheen_tint);
|
|
}
|
|
|
|
void node_bsdf_principled(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,
|
|
vec4 emission,
|
|
float alpha,
|
|
vec3 N,
|
|
vec3 CN,
|
|
vec3 T,
|
|
vec3 I,
|
|
float ssr_id,
|
|
float sss_id,
|
|
vec3 sss_scale,
|
|
out Closure result)
|
|
{
|
|
N = normalize(N);
|
|
ior = max(ior, 1e-5);
|
|
metallic = saturate(metallic);
|
|
transmission = saturate(transmission);
|
|
float dielectric = 1.0 - metallic;
|
|
transmission *= dielectric;
|
|
sheen *= dielectric;
|
|
subsurface_color *= dielectric;
|
|
|
|
vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec;
|
|
vec3 ctint = tint_from_color(base_color.rgb);
|
|
convert_metallic_to_specular_tinted(
|
|
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
|
|
|
|
float NV = dot(N, cameraVec);
|
|
vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
|
|
|
|
/* Far from being accurate, but 2 glossy evaluation is too expensive.
|
|
* Most noticeable difference is at grazing angles since the bsdf lut
|
|
* f0 color interpolation is done on top of this interpolation. */
|
|
vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint);
|
|
float fresnel = F_eta(ior, NV);
|
|
vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel;
|
|
f0 = mix(f0, spec_col, transmission);
|
|
|
|
vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
|
|
|
|
vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
|
|
|
|
float sss_scalef = avg(sss_scale) * subsurface;
|
|
eevee_closure_principled(N,
|
|
mixed_ss_base_color,
|
|
f0,
|
|
f90,
|
|
int(ssr_id),
|
|
roughness,
|
|
CN,
|
|
clearcoat * 0.25,
|
|
clearcoat_roughness,
|
|
1.0,
|
|
sss_scalef,
|
|
ior,
|
|
true,
|
|
out_diff,
|
|
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 */
|
|
out_refr *= refr_color * (1.0 - fresnel) * transmission;
|
|
|
|
result = CLOSURE_DEFAULT;
|
|
result.radiance = out_spec + out_refr;
|
|
result.radiance += out_diff * out_sheen; /* Coarse approx. */
|
|
result.radiance += emission.rgb;
|
|
result.radiance *= alpha;
|
|
|
|
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
|
|
|
|
mixed_ss_base_color *= alpha * (1.0 - transmission);
|
|
closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
|
|
|
|
result.transmittance = vec3(1.0 - alpha);
|
|
}
|
|
|
|
void node_bsdf_principled_dielectric(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,
|
|
vec4 emission,
|
|
float alpha,
|
|
vec3 N,
|
|
vec3 CN,
|
|
vec3 T,
|
|
vec3 I,
|
|
float ssr_id,
|
|
float sss_id,
|
|
vec3 sss_scale,
|
|
out Closure result)
|
|
{
|
|
N = normalize(N);
|
|
metallic = saturate(metallic);
|
|
float dielectric = 1.0 - metallic;
|
|
|
|
vec3 diffuse, f0, out_diff, out_spec, ssr_spec;
|
|
vec3 ctint = tint_from_color(base_color.rgb);
|
|
convert_metallic_to_specular_tinted(
|
|
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
|
|
|
|
float NV = dot(N, cameraVec);
|
|
vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
|
|
|
|
eevee_closure_default(
|
|
N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec);
|
|
|
|
result = CLOSURE_DEFAULT;
|
|
result.radiance = out_spec + out_diff * (diffuse + out_sheen);
|
|
result.radiance += emission.rgb;
|
|
result.radiance *= alpha;
|
|
|
|
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
|
|
|
|
result.transmittance = vec3(1.0 - alpha);
|
|
}
|
|
|
|
void node_bsdf_principled_metallic(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,
|
|
vec4 emission,
|
|
float alpha,
|
|
vec3 N,
|
|
vec3 CN,
|
|
vec3 T,
|
|
vec3 I,
|
|
float ssr_id,
|
|
float sss_id,
|
|
vec3 sss_scale,
|
|
out Closure result)
|
|
{
|
|
N = normalize(N);
|
|
vec3 out_spec, ssr_spec;
|
|
|
|
vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
|
|
|
|
eevee_closure_glossy(
|
|
N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec);
|
|
|
|
result = CLOSURE_DEFAULT;
|
|
result.radiance = out_spec;
|
|
result.radiance += emission.rgb;
|
|
result.radiance *= alpha;
|
|
|
|
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
|
|
|
|
result.transmittance = vec3(1.0 - alpha);
|
|
}
|
|
|
|
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,
|
|
vec4 emission,
|
|
float alpha,
|
|
vec3 N,
|
|
vec3 CN,
|
|
vec3 T,
|
|
vec3 I,
|
|
float ssr_id,
|
|
float sss_id,
|
|
vec3 sss_scale,
|
|
out Closure result)
|
|
{
|
|
vec3 out_spec, ssr_spec;
|
|
N = normalize(N);
|
|
|
|
vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
|
|
|
|
eevee_closure_clearcoat(N,
|
|
base_color.rgb,
|
|
f90,
|
|
int(ssr_id),
|
|
roughness,
|
|
CN,
|
|
clearcoat * 0.25,
|
|
clearcoat_roughness,
|
|
1.0,
|
|
true,
|
|
out_spec,
|
|
ssr_spec);
|
|
|
|
result = CLOSURE_DEFAULT;
|
|
result.radiance = out_spec;
|
|
result.radiance += emission.rgb;
|
|
result.radiance *= alpha;
|
|
|
|
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
|
|
|
|
result.transmittance = vec3(1.0 - alpha);
|
|
}
|
|
|
|
void node_bsdf_principled_subsurface(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,
|
|
vec4 emission,
|
|
float alpha,
|
|
vec3 N,
|
|
vec3 CN,
|
|
vec3 T,
|
|
vec3 I,
|
|
float ssr_id,
|
|
float sss_id,
|
|
vec3 sss_scale,
|
|
out Closure result)
|
|
{
|
|
metallic = saturate(metallic);
|
|
N = normalize(N);
|
|
|
|
vec3 diffuse, f0, out_diff, out_spec, ssr_spec;
|
|
vec3 ctint = tint_from_color(base_color.rgb);
|
|
convert_metallic_to_specular_tinted(
|
|
base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
|
|
|
|
subsurface_color = subsurface_color * (1.0 - metallic);
|
|
vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
|
|
float sss_scalef = avg(sss_scale) * subsurface;
|
|
|
|
float NV = dot(N, cameraVec);
|
|
vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
|
|
|
|
vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
|
|
|
|
eevee_closure_skin(N,
|
|
mixed_ss_base_color,
|
|
f0,
|
|
f90,
|
|
int(ssr_id),
|
|
roughness,
|
|
1.0,
|
|
sss_scalef,
|
|
true,
|
|
out_diff,
|
|
out_spec,
|
|
ssr_spec);
|
|
|
|
result = CLOSURE_DEFAULT;
|
|
result.radiance = out_spec;
|
|
result.radiance += out_diff * out_sheen;
|
|
result.radiance += emission.rgb;
|
|
result.radiance *= alpha;
|
|
|
|
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
|
|
|
|
mixed_ss_base_color *= alpha * (1.0 - transmission);
|
|
closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
|
|
|
|
result.transmittance = vec3(1.0 - alpha);
|
|
}
|
|
|
|
void node_bsdf_principled_glass(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,
|
|
vec4 emission,
|
|
float alpha,
|
|
vec3 N,
|
|
vec3 CN,
|
|
vec3 T,
|
|
vec3 I,
|
|
float ssr_id,
|
|
float sss_id,
|
|
vec3 sss_scale,
|
|
out Closure result)
|
|
{
|
|
ior = max(ior, 1e-5);
|
|
N = normalize(N);
|
|
|
|
vec3 f0, out_spec, out_refr, ssr_spec;
|
|
f0 = mix(vec3(1.0), base_color.rgb, specular_tint);
|
|
|
|
eevee_closure_glass(N,
|
|
vec3(1.0),
|
|
vec3(1.0),
|
|
int(ssr_id),
|
|
roughness,
|
|
1.0,
|
|
ior,
|
|
true,
|
|
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 events */
|
|
out_refr *= refr_color;
|
|
|
|
float fresnel = F_eta(ior, dot(N, cameraVec));
|
|
vec3 spec_col = F_color_blend(ior, fresnel, f0);
|
|
out_spec *= spec_col;
|
|
ssr_spec *= spec_col * fresnel;
|
|
|
|
result = CLOSURE_DEFAULT;
|
|
result.radiance = mix(out_refr, out_spec, fresnel);
|
|
result.radiance += emission.rgb;
|
|
result.radiance *= alpha;
|
|
closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
|
|
result.transmittance = vec3(1.0 - alpha);
|
|
}
|
|
#else
|
|
/* Stub principled because it is not compatible with volumetrics. */
|
|
# define node_bsdf_principled
|
|
# define node_bsdf_principled_dielectric
|
|
# define node_bsdf_principled_metallic
|
|
# define node_bsdf_principled_clearcoat
|
|
# define node_bsdf_principled_subsurface
|
|
# define node_bsdf_principled_glass
|
|
#endif
|