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:
committed by
Lukas Stockner
parent
32288bd200
commit
89218b66c2
@@ -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) {
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user