Files
test/intern/cycles/kernel/osl/shaders/node_principled_bsdf.osl

143 lines
5.4 KiB
Plaintext

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#include "node_fresnel.h"
#include "stdcycles.h"
shader node_principled_bsdf(string distribution = "multi_ggx",
string subsurface_method = "random_walk",
color BaseColor = color(0.8, 0.8, 0.8),
float SubsurfaceWeight = 0.0,
float SubsurfaceScale = 0.1,
vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
float SubsurfaceIOR = 1.4,
float SubsurfaceAnisotropy = 0.0,
float Metallic = 0.0,
float SpecularIORLevel = 0.5,
color SpecularTint = color(1.0),
float Roughness = 0.5,
float Anisotropic = 0.0,
float AnisotropicRotation = 0.0,
float SheenWeight = 0.0,
float SheenRoughness = 0.5,
color SheenTint = 0.5,
float CoatWeight = 0.0,
float CoatRoughness = 0.03,
float CoatIOR = 1.5,
color CoatTint = color(1.0, 1.0, 1.0),
float IOR = 1.45,
float TransmissionWeight = 0.0,
color EmissionColor = 1.0,
float EmissionStrength = 0.0,
float Alpha = 1.0,
normal Normal = N,
normal CoatNormal = N,
normal Tangent = normalize(dPdu),
output closure color BSDF = 0)
{
color specular_tint = max(SpecularTint, color(0.0));
float r2 = clamp(Roughness, 0.0, 1.0);
r2 = r2 * r2;
float alpha_x = r2, alpha_y = r2;
/* Handle anisotropy. */
vector T = Tangent;
if (Anisotropic > 0.0) {
float aspect = sqrt(1.0 - clamp(Anisotropic, 0.0, 1.0) * 0.9);
alpha_x /= aspect;
alpha_y *= aspect;
if (AnisotropicRotation != 0.0)
T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
}
if (Metallic < 1.0 && TransmissionWeight < 1.0) {
float eta = IOR;
float f0 = F0_from_ior(eta);
if (SpecularIORLevel != 0.5) {
f0 *= 2.0 * max(SpecularIORLevel, 0.0);
eta = ior_from_F0(f0);
if (IOR < 1.0) {
eta = 1.0 / eta;
}
}
BSDF = BaseColor * diffuse(Normal);
if (SubsurfaceWeight > 1e-5) {
float subsurface_weight = min(SubsurfaceWeight, 1.0);
vector radius = SubsurfaceScale * SubsurfaceRadius;
float subsurface_ior = (subsurface_method == "random_walk_skin") ? SubsurfaceIOR : eta;
closure color SubsurfBSDF = bssrdf(subsurface_method,
Normal,
SubsurfaceScale * SubsurfaceRadius,
BaseColor,
"roughness",
Roughness,
"ior",
subsurface_ior,
"anisotropy",
SubsurfaceAnisotropy);
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, subsurface_weight);
}
/* Apply specular tint */
color F0 = f0 * specular_tint;
color F90 = color(1.0);
BSDF = layer(
generalized_schlick_bsdf(
Normal, T, color(1.0), color(0.0), alpha_x, alpha_y, F0, F90, -eta, distribution),
BSDF);
}
closure color TransmissionBSDF = 0;
if (Metallic < 1.0 && TransmissionWeight > 0.0) {
float eta = max(IOR, 1e-5);
eta = backfacing() ? 1.0 / eta : eta;
color F0 = F0_from_ior(eta) * specular_tint;
color F90 = color(1.0);
TransmissionBSDF = generalized_schlick_bsdf(
Normal, vector(0.0), color(1.0), sqrt(BaseColor), r2, r2, F0, F90, -eta, distribution),
BSDF = mix(BSDF, TransmissionBSDF, clamp(TransmissionWeight, 0.0, 1.0));
}
closure color MetallicBSDF = 0;
if (Metallic > 0.0) {
color F0 = BaseColor;
color F82 = specular_tint;
MetallicBSDF = microfacet_f82_tint(distribution, Normal, T, alpha_x, alpha_y, F0, F82);
BSDF = mix(BSDF, MetallicBSDF, clamp(Metallic, 0.0, 1.0));
}
if (EmissionStrength > 0.0 && EmissionColor != color(0.0)) {
BSDF += EmissionStrength * EmissionColor * emission();
}
if (CoatWeight > 1e-5) {
float coat_ior = max(CoatIOR, 1.0);
if (CoatTint != color(1.0)) {
float coat_neta = 1.0 / coat_ior;
float cosNI = dot(I, CoatNormal);
float cosNT = sqrt(1.0 - coat_neta * coat_neta * (1 - cosNI * cosNI));
BSDF *= pow(CoatTint, CoatWeight / cosNT);
}
float coat_r2 = clamp(CoatRoughness, 0.0, 1.0);
coat_r2 = coat_r2 * coat_r2;
closure color CoatBSDF = dielectric_bsdf(
CoatNormal, vector(0.0), color(1.0), color(0.0), coat_r2, coat_r2, coat_ior, "ggx");
BSDF = layer(clamp(CoatWeight, 0.0, 1.0) * CoatBSDF, BSDF);
}
if (SheenWeight > 1e-5) {
closure color SheenBSDF = sheen(Normal, clamp(SheenRoughness, 0.0, 1.0));
BSDF = layer(clamp(SheenWeight, 0.0, 1.0) * SheenTint * SheenBSDF, BSDF);
}
BSDF = mix(transparent(), BSDF, clamp(Alpha, 0.0, 1.0));
}