Cycles: add distance-dependent transmission color in Principled BSDF #111806

Open
Weizhen Huang wants to merge 1 commits from weizhen/blender:principled-transmission-tint into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
6 changed files with 61 additions and 14 deletions

View File

@ -26,6 +26,7 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
float ClearcoatRoughness = 0.03,
float IOR = 1.45,
float Transmission = 0.0,
float TransmissionDepth = 0.0,
normal Normal = N,
normal ClearcoatNormal = N,
normal Tangent = normalize(dPdu),
@ -83,8 +84,21 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
float eta = max(IOR, 1e-5);
eta = backfacing() ? 1.0 / eta : eta;
color refractTint = BaseColor;
if (TransmissionDepth > 0) {
if (backfacing()) {
float RayLength;
getattribute("path:ray_length", RayLength);
reflectTint = pow(max(BaseColor, color(1e-5)), RayLength / TransmissionDepth);
refractTint = reflectTint;
}
else {
refractTint = color(1.0);
}
}
TransmissionBSDF = dielectric_bsdf(
Normal, vector(0.0), reflectTint, BaseColor, r2, r2, eta, distribution);
Normal, vector(0.0), reflectTint, refractTint, r2, r2, eta, distribution);
BSDF = mix(BSDF, TransmissionBSDF, clamp(Transmission, 0.0, 1.0));
}

View File

@ -70,7 +70,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
case CLOSURE_BSDF_PRINCIPLED_ID: {
uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset,
sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset,
eta_offset, transmission_offset, anisotropic_rotation_offset, pad1;
eta_offset, transmission_offset, transmission_depth_offset, anisotropic_rotation_offset;
uint4 data_node2 = read_node(kg, &offset);
float3 T = stack_load_float3(stack, data_node.y);
@ -84,8 +84,11 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
&sheen_tint_offset,
&clearcoat_offset,
&clearcoat_roughness_offset);
svm_unpack_node_uchar4(
data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &pad1);
svm_unpack_node_uchar4(data_node2.x,
&eta_offset,
&transmission_offset,
&transmission_depth_offset,
&anisotropic_rotation_offset);
// get Disney principled parameters
float metallic = saturatef(param1);
@ -100,6 +103,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
float clearcoat = stack_load_float(stack, clearcoat_offset);
float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset);
float transmission = saturatef(stack_load_float(stack, transmission_offset));
float transmission_depth = stack_load_float(stack, transmission_depth_offset);
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
@ -250,7 +254,20 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
fresnel->reflection_tint = mix(
one_spectrum(), rgb_to_spectrum(base_color), specular_tint);
fresnel->transmission_tint = rgb_to_spectrum(base_color);
if (transmission_depth == 0.0f) {
fresnel->transmission_tint = rgb_to_spectrum(base_color);
}
else if (sd->flag & SD_BACKFACING) {
/* Use Beer-Lambert opsorption law. Clamp to avoid singularity when some color channel
* is zero. */
fresnel->reflection_tint = power(
max(rgb_to_spectrum(base_color), make_spectrum(1e-5f)),
sd->ray_length / transmission_depth);
fresnel->transmission_tint = fresnel->reflection_tint;
}
else {
fresnel->transmission_tint = one_spectrum();
}
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);

View File

@ -2678,6 +2678,7 @@ NODE_DEFINE(PrincipledBsdfNode)
SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
SOCKET_IN_FLOAT(transmission_depth, "Transmission Depth", 0.0f);
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
SOCKET_IN_COLOR(emission, "Emission", zero_float3());
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 1.0f);
@ -2789,6 +2790,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
ShaderInput *p_clearcoat_roughness,
ShaderInput *p_ior,
ShaderInput *p_transmission,
ShaderInput *p_transmission_depth,
ShaderInput *p_anisotropic_rotation)
{
ShaderInput *base_color_in = input("Base Color");
@ -2815,6 +2817,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
int ior_offset = compiler.stack_assign(p_ior);
int transmission_offset = compiler.stack_assign(p_transmission);
int transmission_depth_offset = compiler.stack_assign(p_transmission_depth);
int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
int subsurface_ior_offset = compiler.stack_assign(p_subsurface_ior);
@ -2838,7 +2841,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
compiler.add_node(
compiler.encode_uchar4(
ior_offset, transmission_offset, anisotropic_rotation_offset, SVM_STACK_INVALID),
ior_offset, transmission_offset, transmission_depth_offset, anisotropic_rotation_offset),
distribution,
subsurface_method,
sheen_roughness_offset);
@ -2884,6 +2887,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
input("Clearcoat Roughness"),
input("IOR"),
input("Transmission"),
input("Transmission Depth"),
input("Anisotropic Rotation"));
}

View File

@ -534,6 +534,7 @@ class PrincipledBsdfNode : public BsdfBaseNode {
ShaderInput *clearcoat_roughness,
ShaderInput *ior,
ShaderInput *transmission,
ShaderInput *transmission_depth,
ShaderInput *anisotropic_rotation);
NODE_SOCKET_API(float3, base_color)
@ -554,6 +555,7 @@ class PrincipledBsdfNode : public BsdfBaseNode {
NODE_SOCKET_API(float, clearcoat_roughness)
NODE_SOCKET_API(float, ior)
NODE_SOCKET_API(float, transmission)
NODE_SOCKET_API(float, transmission_depth)
NODE_SOCKET_API(float, anisotropic_rotation)
NODE_SOCKET_API(float3, normal)
NODE_SOCKET_API(float3, clearcoat_normal)

View File

@ -37,6 +37,7 @@ void node_bsdf_principled(vec4 base_color,
float clearcoat_roughness,
float ior,
float transmission,
float transmission_depth,
vec4 emission,
float emission_strength,
float alpha,

View File

@ -111,22 +111,31 @@ static void node_declare(NodeDeclarationBuilder &b)
.max(1.0f)
.subtype(PROP_FACTOR);
#define SOCK_TRANSMISSION_ID 18
b.add_input<decl::Float>("Transmission Depth")
.default_value(0.0f)
.min(0.0f)
.max(1000000.0f)
.description(
"Distance traveled inside the medium by white light before its color becomes exactly "
"base color, determining the extinction coefficient of the interior medium based on "
"Beer-Lambert law; if zero, base color acts as a constant transmission tint");
#define SOCK_TRANSMISSION_DEPTH_ID 19
b.add_input<decl::Color>("Emission").default_value({0.0f, 0.0f, 0.0f, 1.0f});
#define SOCK_EMISSION_ID 19
#define SOCK_EMISSION_ID 20
b.add_input<decl::Float>("Emission Strength").default_value(1.0).min(0.0f).max(1000000.0f);
#define SOCK_EMISSION_STRENGTH_ID 20
#define SOCK_EMISSION_STRENGTH_ID 21
b.add_input<decl::Float>("Alpha").default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
#define SOCK_ALPHA_ID 21
#define SOCK_ALPHA_ID 22
b.add_input<decl::Vector>("Normal").hide_value();
#define SOCK_NORMAL_ID 22
#define SOCK_NORMAL_ID 23
b.add_input<decl::Vector>("Clearcoat Normal").hide_value();
#define SOCK_CLEARCOAT_NORMAL_ID 23
#define SOCK_CLEARCOAT_NORMAL_ID 24
b.add_input<decl::Vector>("Tangent").hide_value();
#define SOCK_TANGENT_ID 24
#define SOCK_TANGENT_ID 25
b.add_input<decl::Float>("Weight").unavailable();
#define SOCK_WEIGHT_ID 25
#define SOCK_WEIGHT_ID 26
b.add_output<decl::Shader>("BSDF");
#define SOCK_BSDF_ID 26
#define SOCK_BSDF_ID 27
}
static void node_shader_buts_principled(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)