Cycles: Remove Transmission Roughness from Principled BSDF

This was already unsupported in combination with Multiscattering GGX,
prevented the Principled BSDF from using microfaced-based Fresnel for
Glass materials, and would have made future improvements even trickier.

Pull Request: https://projects.blender.org/blender/blender/pulls/109950
This commit is contained in:
Lukas Stockner
2023-07-22 04:16:49 +02:00
committed by Lukas Stockner
parent 32288bd200
commit 89218b66c2
7 changed files with 56 additions and 162 deletions

View File

@@ -24,13 +24,11 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
float ClearcoatRoughness = 0.03,
float IOR = 1.45,
float Transmission = 0.0,
float TransmissionRoughness = 0.0,
normal Normal = N,
normal ClearcoatNormal = N,
normal Tangent = normalize(dPdu),
output closure color BSDF = 0)
{
float f = max(IOR, 1e-5);
float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(Transmission, 0.0, 1.0));
float final_transmission = clamp(Transmission, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0));
float specular_weight = (1.0 - final_transmission);
@@ -92,30 +90,11 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
if (final_transmission > 1e-5) {
color Cspec0 = mix(color(1.0), BaseColor, SpecularTint);
float eta = backfacing() ? 1.0 / f : f;
float eta = max(IOR, 1e-5);
eta = backfacing() ? 1.0 / eta : eta;
if (distribution == "ggx" || Roughness <= 5e-2) {
float cosNI = dot(Normal, I);
float Fr = fresnel_dielectric_cos(cosNI, eta);
float refl_roughness = Roughness;
if (Roughness <= 1e-2)
refl_roughness = 0.0;
float transmission_roughness = refl_roughness;
if (distribution == "ggx")
transmission_roughness = 1.0 - (1.0 - refl_roughness) * (1.0 - TransmissionRoughness);
closure color refraction = microfacet(
"ggx", Normal, transmission_roughness * transmission_roughness, eta, 1);
closure color reflection = microfacet_aniso_fresnel(
Normal, T, r2, r2, Cspec0, color(1.0), eta, "ggx");
BSDF += final_transmission * mix(BaseColor * refraction, reflection, Fr);
}
else {
BSDF += final_transmission *
dielectric_bsdf(Normal, vector(0.0), Cspec0, BaseColor, r2, r2, eta, "multi_ggx");
}
BSDF += final_transmission *
dielectric_bsdf(Normal, vector(0.0), Cspec0, BaseColor, r2, r2, eta, distribution);
}
if (Clearcoat > 1e-5) {

View File

@@ -69,8 +69,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,
transmission_roughness_offset;
eta_offset, transmission_offset, anisotropic_rotation_offset, pad1;
uint4 data_node2 = read_node(kg, &offset);
float3 T = stack_load_float3(stack, data_node.y);
@@ -84,11 +83,8 @@ 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,
&transmission_roughness_offset);
svm_unpack_node_uchar4(
data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &pad1);
// get Disney principled parameters
float metallic = param1;
@@ -103,7 +99,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset);
float transmission = stack_load_float(stack, transmission_offset);
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
float transmission_roughness = stack_load_float(stack, transmission_roughness_offset);
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
ClosureType distribution = (ClosureType)data_node2.y;
@@ -113,13 +108,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
if (anisotropic_rotation != 0.0f)
T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
/* calculate ior */
float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
/* Calculate fresnel for refraction. */
float3 valid_reflection_N = maybe_ensure_valid_specular_reflection(sd, N);
float cosNI = dot(valid_reflection_N, sd->wi);
float fresnel = fresnel_dielectric_cos(cosNI, ior);
// calculate weights of the diffuse and specular part
float diffuse_weight = (1.0f - saturatef(metallic)) * (1.0f - saturatef(transmission));
@@ -301,7 +290,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
}
#endif
/* BSDF */
/* Transmission */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_reflective ||
kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
@@ -311,100 +300,27 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
Spectrum glass_weight = weight * final_transmission;
Spectrum cspec0 = base_color * specular_tint + make_float3(1.0f - specular_tint);
/* Use single-scatter GGX. */
if (roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) {
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), glass_weight);
ccl_private FresnelDielectricTint *fresnel =
(bsdf != NULL) ? (ccl_private FresnelDielectricTint *)closure_alloc_extra(
sd, sizeof(FresnelDielectricTint)) :
NULL;
float refl_roughness = roughness;
if (bsdf && fresnel) {
bsdf->N = valid_reflection_N;
bsdf->T = zero_float3();
/* reflection */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), glass_weight * fresnel);
ccl_private FresnelGeneralizedSchlick *fresnel =
(bsdf != NULL) ? (ccl_private FresnelGeneralizedSchlick *)closure_alloc_extra(
sd, sizeof(FresnelGeneralizedSchlick)) :
NULL;
bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
if (bsdf && fresnel) {
bsdf->N = valid_reflection_N;
bsdf->T = zero_float3();
fresnel->reflection_tint = cspec0;
fresnel->transmission_tint = base_color;
bsdf->alpha_x = refl_roughness * refl_roughness;
bsdf->alpha_y = refl_roughness * refl_roughness;
bsdf->ior = ior;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
fresnel->f0 = cspec0;
fresnel->f90 = one_spectrum();
fresnel->exponent = -1.0f;
fresnel->reflection_tint = one_spectrum();
fresnel->transmission_tint = zero_spectrum();
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, false);
}
}
/* refraction */
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
/* This is to prevent MNEE from receiving a null BSDF. */
float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel);
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd,
sizeof(MicrofacetBsdf),
rgb_to_spectrum(base_color) * glass_weight * refraction_fresnel);
if (bsdf) {
bsdf->N = valid_reflection_N;
bsdf->T = zero_float3();
if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
transmission_roughness = 1.0f - (1.0f - refl_roughness) *
(1.0f - transmission_roughness);
else
transmission_roughness = refl_roughness;
bsdf->alpha_x = transmission_roughness * transmission_roughness;
bsdf->alpha_y = transmission_roughness * transmission_roughness;
bsdf->ior = ior;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
}
} /* Use multi-scatter GGX. */
else {
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), glass_weight);
ccl_private FresnelGeneralizedSchlick *fresnel =
(bsdf != NULL) ? (ccl_private FresnelGeneralizedSchlick *)closure_alloc_extra(
sd, sizeof(FresnelGeneralizedSchlick)) :
NULL;
if (bsdf && fresnel) {
bsdf->N = valid_reflection_N;
bsdf->T = zero_float3();
bsdf->alpha_x = roughness * roughness;
bsdf->alpha_y = roughness * roughness;
bsdf->ior = ior;
fresnel->f0 = make_spectrum(F0_from_ior(ior));
fresnel->f90 = one_spectrum();
fresnel->exponent = -1.0f;
fresnel->reflection_tint = cspec0;
fresnel->transmission_tint = base_color;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, true);
}
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
bsdf_microfacet_setup_fresnel_dielectric_tint(kg, bsdf, sd, fresnel, is_multiggx);
}
}
#ifdef __CAUSTICS_TRICKS__

View File

@@ -2659,7 +2659,6 @@ 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_roughness, "Transmission Roughness", 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);
@@ -2770,8 +2769,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
ShaderInput *p_clearcoat_roughness,
ShaderInput *p_ior,
ShaderInput *p_transmission,
ShaderInput *p_anisotropic_rotation,
ShaderInput *p_transmission_roughness)
ShaderInput *p_anisotropic_rotation)
{
ShaderInput *base_color_in = input("Base Color");
ShaderInput *subsurface_color_in = input("Subsurface Color");
@@ -2796,7 +2794,6 @@ 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_roughness_offset = compiler.stack_assign(p_transmission_roughness);
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);
@@ -2818,13 +2815,12 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
compiler.encode_uchar4(
sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
compiler.add_node(compiler.encode_uchar4(ior_offset,
transmission_offset,
anisotropic_rotation_offset,
transmission_roughness_offset),
distribution,
subsurface_method,
SVM_STACK_INVALID);
compiler.add_node(
compiler.encode_uchar4(
ior_offset, transmission_offset, anisotropic_rotation_offset, SVM_STACK_INVALID),
distribution,
subsurface_method,
SVM_STACK_INVALID);
float3 bc_default = get_float3(base_color_in->socket_type);
@@ -2866,8 +2862,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
input("Clearcoat Roughness"),
input("IOR"),
input("Transmission"),
input("Anisotropic Rotation"),
input("Transmission Roughness"));
input("Anisotropic Rotation"));
}
void PrincipledBsdfNode::compile(OSLCompiler &compiler)

View File

@@ -531,8 +531,7 @@ class PrincipledBsdfNode : public BsdfBaseNode {
ShaderInput *clearcoat_roughness,
ShaderInput *ior,
ShaderInput *transmission,
ShaderInput *anisotropic_rotation,
ShaderInput *transmission_roughness);
ShaderInput *anisotropic_rotation);
NODE_SOCKET_API(float3, base_color)
NODE_SOCKET_API(float3, subsurface_color)
@@ -552,7 +551,6 @@ class PrincipledBsdfNode : public BsdfBaseNode {
NODE_SOCKET_API(float, ior)
NODE_SOCKET_API(float, transmission)
NODE_SOCKET_API(float, anisotropic_rotation)
NODE_SOCKET_API(float, transmission_roughness)
NODE_SOCKET_API(float3, normal)
NODE_SOCKET_API(float3, clearcoat_normal)
NODE_SOCKET_API(float3, tangent)

View File

@@ -266,6 +266,19 @@ static void version_replace_texcoord_normal_socket(bNodeTree *ntree)
}
}
static void version_principled_transmission_roughness(bNodeTree *ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type != SH_NODE_BSDF_PRINCIPLED) {
continue;
}
bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, "Transmission Roughness");
if (sock != nullptr) {
nodeRemoveSocket(ntree, node, sock);
}
}
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@@ -374,8 +387,6 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
* \note Keep this message at the bottom of the function.
*/
{
/* Convert anisotropic BSDF node to glossy BSDF. */
/* Keep this block, even when empty. */
if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "int", "grid_bake_samples")) {
@@ -415,5 +426,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
layer->opacity = 1.0f;
}
}
/* Remove Transmission Roughness from Principled BSDF. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_SHADER) {
version_principled_transmission_roughness(ntree);
}
}
FOREACH_NODETREE_END;
}
}

View File

@@ -31,7 +31,6 @@ void node_bsdf_principled(vec4 base_color,
float clearcoat_roughness,
float ior,
float transmission,
float transmission_roughness,
vec4 emission,
float emission_strength,
float alpha,
@@ -52,7 +51,6 @@ void node_bsdf_principled(vec4 base_color,
float diffuse_weight = (1.0 - transmission) * (1.0 - metallic);
float specular_weight = (1.0 - transmission);
float clearcoat_weight = max(clearcoat, 0.0) * 0.25;
transmission_roughness = 1.0 - (1.0 - roughness) * (1.0 - transmission_roughness);
specular = max(0.0, specular);
N = safe_normalize(N);
@@ -145,8 +143,7 @@ void node_bsdf_principled(vec4 base_color,
refraction_data.color = base_color.rgb * btdf;
refraction_data.N = N;
refraction_data.roughness = do_multiscatter != 0.0 ? roughness :
max(roughness, transmission_roughness);
refraction_data.roughness = roughness;
refraction_data.ior = ior;
/* Ref. #98190: Defines are optimizations for old compilers.

View File

@@ -87,11 +87,6 @@ static void node_declare(NodeDeclarationBuilder &b)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>("Transmission Roughness")
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Color>("Emission").default_value({0.0f, 0.0f, 0.0f, 1.0f});
b.add_input<decl::Float>("Emission Strength").default_value(1.0).min(0.0f).max(1000000.0f);
b.add_input<decl::Float>("Alpha").default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
@@ -213,14 +208,9 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
{
const int distribution = node->custom1;
const int sss_method = node->custom2;
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (STREQ(sock->name, "Transmission Roughness")) {
bke::nodeSetSocketAvailability(ntree, sock, distribution == SHD_GLOSSY_GGX);
}
if (STR_ELEM(sock->name, "Subsurface IOR", "Subsurface Anisotropy")) {
bke::nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY);
}