This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
Brecht Van Lommel 0803119725 Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.

Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.

Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles

Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)

For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.

Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
2021-09-21 14:55:54 +02:00

209 lines
8.1 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.0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
}
float principled_sheen(float NV)
{
float f = 1.0 - NV;
/* Empirical approximation (manual curve fitting). Can be refined. */
float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026;
return sheen;
}
CLOSURE_EVAL_FUNCTION_DECLARE_4(node_bsdf_principled, Diffuse, Glossy, Glossy, Refraction)
void node_bsdf_principled(vec4 base_color,
float subsurface,
vec3 subsurface_radius,
vec4 subsurface_color,
float subsurface_ior,
float subsurface_anisotropy,
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 emission_strength,
float alpha,
vec3 N,
vec3 CN,
vec3 T,
const float do_diffuse,
const float do_clearcoat,
const float do_refraction,
const float do_multiscatter,
float ssr_id,
float sss_id,
vec3 sss_scale,
out Closure result)
{
/* Match cycles. */
metallic = saturate(metallic);
transmission = saturate(transmission);
float diffuse_weight = (1.0 - transmission) * (1.0 - metallic);
transmission *= (1.0 - metallic);
float specular_weight = (1.0 - transmission);
clearcoat = max(clearcoat, 0.0);
transmission_roughness = 1.0 - (1.0 - roughness) * (1.0 - transmission_roughness);
specular = max(0.0, specular);
CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction);
in_Diffuse_0.N = N; /* Normalized during eval. */
in_Diffuse_0.albedo = mix(base_color.rgb, subsurface_color.rgb, subsurface);
in_Glossy_1.N = N; /* Normalized during eval. */
in_Glossy_1.roughness = roughness;
in_Glossy_2.N = CN; /* Normalized during eval. */
in_Glossy_2.roughness = clearcoat_roughness;
in_Refraction_3.N = N; /* Normalized during eval. */
in_Refraction_3.roughness = do_multiscatter != 0.0 ? roughness : transmission_roughness;
in_Refraction_3.ior = ior;
CLOSURE_EVAL_FUNCTION_4(node_bsdf_principled, Diffuse, Glossy, Glossy, Refraction);
result = CLOSURE_DEFAULT;
/* This will tag the whole eval for optimisation. */
if (do_diffuse == 0.0) {
out_Diffuse_0.radiance = vec3(0);
}
if (do_clearcoat == 0.0) {
out_Glossy_2.radiance = vec3(0);
}
if (do_refraction == 0.0) {
out_Refraction_3.radiance = vec3(0);
}
vec3 V = cameraVec(worldPosition);
/* Glossy_1 will always be evaluated. */
float NV = dot(in_Glossy_1.N, V);
vec3 base_color_tint = tint_from_color(base_color.rgb);
float fresnel = (do_multiscatter != 0.0) ?
btdf_lut(NV, in_Glossy_1.roughness, in_Refraction_3.ior).y :
F_eta(in_Refraction_3.ior, NV);
{
/* Glossy reflections.
* Separate Glass reflections and main specular reflections to match Cycles renderpasses. */
out_Glossy_1.radiance = closure_mask_ssr_radiance(out_Glossy_1.radiance, ssr_id);
vec2 split_sum = brdf_lut(NV, roughness);
vec3 glossy_radiance_final = vec3(0.0);
if (transmission > 1e-5) {
/* Glass Reflection: Reuse radiance from Glossy1. */
vec3 out_glass_refl_radiance = out_Glossy_1.radiance;
/* Poor approximation since we baked the LUT using a fixed IOR. */
vec3 f0 = mix(vec3(1.0), base_color.rgb, specular_tint);
vec3 f90 = vec3(1);
vec3 brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
F_brdf_single_scatter(f0, f90, split_sum);
out_glass_refl_radiance *= brdf;
out_glass_refl_radiance = render_pass_glossy_mask(vec3(1), out_glass_refl_radiance);
out_glass_refl_radiance *= fresnel * transmission;
glossy_radiance_final += out_glass_refl_radiance;
}
if (specular_weight > 1e-5) {
vec3 dielectric_f0_color = mix(vec3(1.0), base_color_tint, specular_tint);
vec3 metallic_f0_color = base_color.rgb;
vec3 f0 = mix((0.08 * specular) * dielectric_f0_color, metallic_f0_color, metallic);
/* Cycles does this blending using the microfacet fresnel factor. However, our fresnel
* is already baked inside the split sum LUT. We approximate using by modifying the
* changing the f90 color directly in a non linear fashion. */
vec3 f90 = mix(f0, vec3(1), fast_sqrt(specular));
vec3 brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
F_brdf_single_scatter(f0, f90, split_sum);
out_Glossy_1.radiance *= brdf;
out_Glossy_1.radiance = render_pass_glossy_mask(vec3(1), out_Glossy_1.radiance);
out_Glossy_1.radiance *= specular_weight;
glossy_radiance_final += out_Glossy_1.radiance;
}
closure_load_ssr_data(
glossy_radiance_final, in_Glossy_1.roughness, in_Glossy_1.N, ssr_id, result);
}
if (diffuse_weight > 1e-5) {
/* Mask over all diffuse radiance. */
out_Diffuse_0.radiance *= diffuse_weight;
/* Sheen Coarse approximation: We reuse the diffuse radiance and just scale it. */
vec3 sheen_color = mix(vec3(1), base_color_tint, sheen_tint);
vec3 out_sheen_radiance = out_Diffuse_0.radiance * principled_sheen(NV);
out_sheen_radiance = render_pass_diffuse_mask(vec3(1), out_sheen_radiance);
out_sheen_radiance *= sheen * sheen_color;
result.radiance += out_sheen_radiance;
/* Diffuse / Subsurface. */
float scale = avg(sss_scale) * subsurface;
closure_load_sss_data(scale, out_Diffuse_0.radiance, in_Diffuse_0.albedo, int(sss_id), result);
}
if (transmission > 1e-5) {
float btdf = (do_multiscatter != 0.0) ?
1.0 :
btdf_lut(NV, in_Refraction_3.roughness, in_Refraction_3.ior).x;
/* TODO(fclem) This could be going to a transmission render pass instead. */
out_Refraction_3.radiance *= btdf;
out_Refraction_3.radiance = render_pass_glossy_mask(vec3(1), out_Refraction_3.radiance);
out_Refraction_3.radiance *= base_color.rgb;
/* Simulate 2nd transmission event. */
out_Refraction_3.radiance *= (refractionDepth > 0.0) ? base_color.rgb : vec3(1);
out_Refraction_3.radiance *= (1.0 - fresnel) * transmission;
result.radiance += out_Refraction_3.radiance;
}
if (clearcoat > 1e-5) {
float NV = dot(in_Glossy_2.N, V);
vec2 split_sum = brdf_lut(NV, in_Glossy_2.roughness);
vec3 brdf = F_brdf_single_scatter(vec3(0.04), vec3(1.0), split_sum);
out_Glossy_2.radiance *= brdf * clearcoat * 0.25;
out_Glossy_2.radiance = render_pass_glossy_mask(vec3(1), out_Glossy_2.radiance);
result.radiance += out_Glossy_2.radiance;
}
{
vec3 out_emission_radiance = render_pass_emission_mask(emission.rgb);
out_emission_radiance *= emission_strength;
result.radiance += out_emission_radiance;
}
result.transmittance = vec3(1.0 - alpha);
result.radiance *= alpha;
result.ssr_data.rgb *= alpha;
# ifdef USE_SSS
result.sss_albedo *= alpha;
# endif
}
#else
/* clang-format off */
/* Stub principled because it is not compatible with volumetrics. */
# define node_bsdf_principled(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, cc, dd, ee, ff, result) (result = CLOSURE_DEFAULT)
/* clang-format on */
#endif