Cycles: Rework Principled BSDF Clearcoat
- Adds tint control, which simulates volumetric absorption inside the coating. This results in angle-dependent saturation and affects all underlying layers (diffuse, subsurface, metallic, transmission). It provides a physically-based alternative to ad-hoc effects such as tinted specular highlights. - Renames the component from "Clearcoat" to "Coat", since it's no longer necessarily clear now. This matches naming in e.g. other renderers or OpenPBR. - Adds an explicit Coat IOR input, in preparation for future smarter IOR logic around the interaction between Coat and main IOR. This used to be hardcoded to 1.5. - Removes hardcoded 0.25 weight multiplier, and adds versioning code to update existing files accordingly. OBJ import/export still applies the factor. - Replaces the GTR1 microfacet component with regular GGX. This removes a corner case in the Microfacet code, solves #53038, and makes us more consistent with other standard surface shaders. The original Disney BSDF used GTR1, but it doesn't appear that it caught on in the industry. Co-authored-by: Weizhen Huang <weizhen@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/110993
This commit is contained in:
committed by
Lukas Stockner
parent
b7ba7663a7
commit
158dbc1b10
@@ -139,7 +139,7 @@ class UsdToCycles {
|
||||
{TfToken("diffuseColor"), ustring("base_color")},
|
||||
{TfToken("emissiveColor"), ustring("emission")},
|
||||
{TfToken("specularColor"), ustring("specular")},
|
||||
{TfToken("clearcoatRoughness"), ustring("clearcoat_roughness")},
|
||||
{TfToken("clearcoatRoughness"), ustring("coat_roughness")},
|
||||
{TfToken("opacity"), ustring("alpha")},
|
||||
// opacityThreshold
|
||||
// occlusion
|
||||
|
||||
@@ -153,7 +153,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
||||
label = bsdf_microfacet_ggx_sample(
|
||||
@@ -284,7 +283,6 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
@@ -385,7 +383,6 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
|
||||
label = LABEL_TRANSMIT | LABEL_TRANSPARENT;
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
@@ -484,7 +481,6 @@ ccl_device_inline
|
||||
eval = bsdf_transparent_eval(sc, sd->wi, wo, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
||||
eval = bsdf_microfacet_ggx_eval(sc, Ng, sd->wi, wo, pdf);
|
||||
@@ -555,7 +551,6 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
|
||||
#if defined(__SVM__) || defined(__OSL__)
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
|
||||
@@ -377,17 +377,6 @@ ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg,
|
||||
return albedo;
|
||||
}
|
||||
|
||||
/* Generalized Trowbridge-Reitz for clearcoat. */
|
||||
ccl_device_forceinline float bsdf_clearcoat_D(float alpha2, float cos_NH)
|
||||
{
|
||||
if (alpha2 >= 1.0f) {
|
||||
return M_1_PI_F;
|
||||
}
|
||||
|
||||
const float t = 1.0f + (alpha2 - 1.0f) * cos_NH * cos_NH;
|
||||
return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
|
||||
}
|
||||
|
||||
/* Smith shadowing-masking term, here in the non-separable form.
|
||||
* For details, see:
|
||||
* Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs.
|
||||
@@ -529,18 +518,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
|
||||
* harder to compute. */
|
||||
if (alpha_x == alpha_y || is_transmission) { /* Isotropic. */
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
D = bsdf_clearcoat_D(alpha2, cos_NH);
|
||||
|
||||
/* The masking-shadowing term for clearcoat has a fixed alpha of 0.25
|
||||
* => alpha2 = 0.25 * 0.25 */
|
||||
alpha2 = 0.0625f;
|
||||
}
|
||||
else {
|
||||
D = bsdf_D<m_type>(alpha2, cos_NH);
|
||||
}
|
||||
|
||||
D = bsdf_D<m_type>(alpha2, cos_NH);
|
||||
lambdaI = bsdf_lambda<m_type>(alpha2, cos_NI);
|
||||
lambdaO = bsdf_lambda<m_type>(alpha2, cos_NO);
|
||||
}
|
||||
@@ -687,17 +665,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
|
||||
const float cos_NH = dot(N, H);
|
||||
const float cos_NO = dot(N, *wo);
|
||||
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
D = bsdf_clearcoat_D(alpha2, cos_NH);
|
||||
|
||||
/* The masking-shadowing term for clearcoat has a fixed alpha of 0.25
|
||||
* => alpha2 = 0.25 * 0.25 */
|
||||
alpha2 = 0.0625f;
|
||||
}
|
||||
else {
|
||||
D = bsdf_D<m_type>(alpha2, cos_NH);
|
||||
}
|
||||
|
||||
D = bsdf_D<m_type>(alpha2, cos_NH);
|
||||
lambdaO = bsdf_lambda<m_type>(alpha2, cos_NO);
|
||||
lambdaI = bsdf_lambda<m_type>(alpha2, cos_NI);
|
||||
}
|
||||
@@ -831,6 +799,14 @@ ccl_device void bsdf_microfacet_setup_fresnel_constant(KernelGlobals kg,
|
||||
microfacet_ggx_preserve_energy(kg, bsdf, sd, color);
|
||||
}
|
||||
|
||||
ccl_device void bsdf_microfacet_setup_fresnel_dielectric(KernelGlobals kg,
|
||||
ccl_private MicrofacetBsdf *bsdf,
|
||||
ccl_private const ShaderData *sd)
|
||||
{
|
||||
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
}
|
||||
|
||||
/* GGX microfacet with Smith shadow-masking from:
|
||||
*
|
||||
* Microfacet Models for Refraction through Rough Surfaces
|
||||
@@ -856,21 +832,6 @@ ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(KernelGlobals kg,
|
||||
ccl_private MicrofacetBsdf *bsdf,
|
||||
ccl_private const ShaderData *sd)
|
||||
{
|
||||
bsdf->alpha_x = saturatef(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
|
||||
bsdf->energy_scale = 1.0f;
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
|
||||
return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_x = saturatef(bsdf->alpha_x);
|
||||
|
||||
@@ -420,10 +420,6 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
|
||||
else if (closure->distribution == make_string("ashikhmin_shirley", 11318482998918370922ull)) {
|
||||
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
|
||||
}
|
||||
/* Clearcoat */
|
||||
else if (closure->distribution == make_string("clearcoat", 3490136178980547276ull)) {
|
||||
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(kg, bsdf, sd);
|
||||
}
|
||||
/* GGX (either single- or multi-scattering) */
|
||||
else {
|
||||
if (closure->refract == 1) {
|
||||
|
||||
@@ -140,7 +140,7 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
|
||||
if (stack_size == layer_stack_level) {
|
||||
/* We just finished processing the top layers of a Layer closure, so adjust the weight to
|
||||
* account for the layering. */
|
||||
weight *= saturatef(1.0f - reduce_max(layer_albedo / weight));
|
||||
weight *= saturatef(1.0f - reduce_max(safe_divide_color(layer_albedo, weight)));
|
||||
layer_stack_level = -1;
|
||||
if (is_zero(weight)) {
|
||||
/* If it's fully occluded, skip the base layer we just popped from the stack and grab
|
||||
|
||||
@@ -22,12 +22,14 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
||||
float Sheen = 0.0,
|
||||
float SheenRoughness = 0.5,
|
||||
color SheenTint = 0.5,
|
||||
float Clearcoat = 0.0,
|
||||
float ClearcoatRoughness = 0.03,
|
||||
float Coat = 0.0,
|
||||
float CoatRoughness = 0.03,
|
||||
float CoatIOR = 1.5,
|
||||
color CoatTint = color(1.0, 1.0, 1.0),
|
||||
float IOR = 1.45,
|
||||
float Transmission = 0.0,
|
||||
normal Normal = N,
|
||||
normal ClearcoatNormal = N,
|
||||
normal CoatNormal = N,
|
||||
normal Tangent = normalize(dPdu),
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
@@ -97,10 +99,18 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
||||
BSDF = mix(BSDF, MetallicBSDF, clamp(Metallic, 0.0, 1.0));
|
||||
}
|
||||
|
||||
if (Clearcoat > 1e-5) {
|
||||
float clearcoat_r2 = ClearcoatRoughness * ClearcoatRoughness;
|
||||
closure color ClearcoatBSDF = microfacet("clearcoat", ClearcoatNormal, clearcoat_r2, 1.5, 0);
|
||||
BSDF = layer(0.25 * Clearcoat * ClearcoatBSDF, BSDF);
|
||||
if (Coat > 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, Coat / cosNT);
|
||||
}
|
||||
float coat_r2 = CoatRoughness * CoatRoughness;
|
||||
closure color CoatBSDF = dielectric_bsdf(
|
||||
CoatNormal, vector(0.0), color(1.0), color(0.0), coat_r2, coat_r2, coat_ior, "ggx");
|
||||
BSDF = layer(Coat * CoatBSDF, BSDF);
|
||||
}
|
||||
|
||||
if (Sheen > 1e-5) {
|
||||
|
||||
@@ -69,8 +69,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
switch (type) {
|
||||
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;
|
||||
sheen_offset, sheen_tint_offset, sheen_roughness_offset, coat_offset,
|
||||
coat_roughness_offset, coat_ior_offset, eta_offset, transmission_offset,
|
||||
anisotropic_rotation_offset, coat_tint_offset, dummy;
|
||||
uint4 data_node2 = read_node(kg, &offset);
|
||||
|
||||
float3 T = stack_load_float3(stack, data_node.y);
|
||||
@@ -79,13 +80,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
&roughness_offset,
|
||||
&specular_tint_offset,
|
||||
&anisotropic_offset);
|
||||
svm_unpack_node_uchar4(data_node.w,
|
||||
&sheen_offset,
|
||||
&sheen_tint_offset,
|
||||
&clearcoat_offset,
|
||||
&clearcoat_roughness_offset);
|
||||
svm_unpack_node_uchar4(
|
||||
data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &pad1);
|
||||
data_node.w, &sheen_offset, &sheen_tint_offset, &sheen_roughness_offset, &dummy);
|
||||
svm_unpack_node_uchar4(
|
||||
data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &dummy);
|
||||
svm_unpack_node_uchar4(
|
||||
data_node2.w, &coat_offset, &coat_roughness_offset, &coat_ior_offset, &coat_tint_offset);
|
||||
|
||||
// get Disney principled parameters
|
||||
float metallic = saturatef(param1);
|
||||
@@ -96,9 +96,11 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
float anisotropic = stack_load_float(stack, anisotropic_offset);
|
||||
float sheen = stack_load_float(stack, sheen_offset);
|
||||
float3 sheen_tint = stack_load_float3(stack, sheen_tint_offset);
|
||||
float sheen_roughness = stack_load_float(stack, data_node2.w);
|
||||
float clearcoat = stack_load_float(stack, clearcoat_offset);
|
||||
float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset);
|
||||
float sheen_roughness = stack_load_float(stack, sheen_roughness_offset);
|
||||
float coat = stack_load_float(stack, coat_offset);
|
||||
float coat_roughness = stack_load_float(stack, coat_roughness_offset);
|
||||
float coat_ior = fmaxf(stack_load_float(stack, coat_ior_offset), 1.0f);
|
||||
float3 coat_tint = stack_load_float3(stack, coat_tint_offset);
|
||||
float transmission = saturatef(stack_load_float(stack, transmission_offset));
|
||||
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
|
||||
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
|
||||
@@ -116,12 +118,11 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
__uint_as_float(data_base_color.z),
|
||||
__uint_as_float(data_base_color.w));
|
||||
|
||||
// get the additional clearcoat normal and subsurface scattering radius
|
||||
// get the additional coat normal and subsurface scattering radius
|
||||
uint4 data_cn_ssr = read_node(kg, &offset);
|
||||
float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ?
|
||||
stack_load_float3(stack, data_cn_ssr.x) :
|
||||
sd->N;
|
||||
clearcoat_normal = maybe_ensure_valid_specular_reflection(sd, clearcoat_normal);
|
||||
float3 coat_normal = stack_valid(data_cn_ssr.x) ? stack_load_float3(stack, data_cn_ssr.x) :
|
||||
sd->N;
|
||||
coat_normal = maybe_ensure_valid_specular_reflection(sd, coat_normal);
|
||||
float3 subsurface_radius = stack_valid(data_cn_ssr.y) ?
|
||||
stack_load_float3(stack, data_cn_ssr.y) :
|
||||
one_float3();
|
||||
@@ -175,31 +176,58 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
/* Attenuate lower layers */
|
||||
Spectrum albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
|
||||
weight *= 1.0f - reduce_max(albedo / weight);
|
||||
weight *= 1.0f - reduce_max(safe_divide_color(albedo, weight));
|
||||
}
|
||||
}
|
||||
|
||||
/* Second layer: Clearcoat */
|
||||
if (reflective_caustics && clearcoat > CLOSURE_WEIGHT_CUTOFF) {
|
||||
/* Second layer: Coat */
|
||||
if (reflective_caustics && coat > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), 0.25f * clearcoat * weight);
|
||||
sd, sizeof(MicrofacetBsdf), coat * weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = clearcoat_normal;
|
||||
bsdf->N = coat_normal;
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->ior = 1.5f;
|
||||
bsdf->ior = coat_ior;
|
||||
|
||||
bsdf->alpha_x = bsdf->alpha_y = sqr(clearcoat_roughness);
|
||||
bsdf->alpha_x = bsdf->alpha_y = sqr(coat_roughness);
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(kg, bsdf, sd);
|
||||
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
||||
bsdf_microfacet_setup_fresnel_dielectric(kg, bsdf, sd);
|
||||
|
||||
/* Attenuate lower layers */
|
||||
Spectrum albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
|
||||
weight *= 1.0f - reduce_max(albedo / weight);
|
||||
weight *= 1.0f - reduce_max(safe_divide_color(albedo, weight));
|
||||
}
|
||||
}
|
||||
|
||||
if (coat > CLOSURE_WEIGHT_CUTOFF && !isequal(coat_tint, one_float3())) {
|
||||
/* Tint is normalized to perpendicular incidence.
|
||||
* Therefore, if we define the coat thickness as length 1, the length along the ray is
|
||||
* t = sqrt(1+tan^2(angle(N, I))) = sqrt(1+tan^2(acos(dotNI))) = 1 / dotNI.
|
||||
* From Beer's law, we have T = exp(-sigma_e * t).
|
||||
* Therefore, tint = exp(-sigma_e * 1) (per def.), so -sigma_e = log(tint).
|
||||
* From this, T = exp(log(tint) * t) = exp(log(tint)) ^ t = tint ^ t;
|
||||
*
|
||||
* Note that this is only an approximation - it assumes that the outgoing ray
|
||||
* follows the same angle, and that there aren't multiple internal bounces.
|
||||
* In particular, things that could be improved:
|
||||
* - For transmissive materials, there should not be an outgoing path at all if the path
|
||||
* is transmitted.
|
||||
* - For rough materials, we could blend towards a view-independent average path length
|
||||
* (e.g. 2 for diffuse reflection) for the outgoing direction.
|
||||
* However, there's also an argument to be made for keeping parameters independent of each
|
||||
* other for more intuitive control, in particular main roughness not affecting the coat.
|
||||
*/
|
||||
float cosNI = dot(sd->wi, coat_normal);
|
||||
/* Refract incoming direction into coat material.
|
||||
* TIR is no concern here since we're always coming from the outside. */
|
||||
float cosNT = sqrtf(1.0f - sqr(1.0f / coat_ior) * (1 - sqr(cosNI)));
|
||||
float optical_depth = 1.0f / cosNT;
|
||||
weight *= power(rgb_to_spectrum(coat_tint), coat * optical_depth);
|
||||
}
|
||||
|
||||
/* Metallic component */
|
||||
if (reflective_caustics && metallic > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
@@ -295,7 +323,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
/* Attenuate lower layers */
|
||||
Spectrum albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
|
||||
weight *= 1.0f - reduce_max(albedo / weight);
|
||||
weight *= 1.0f - reduce_max(safe_divide_color(albedo, weight));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -427,7 +427,6 @@ typedef enum ClosureType {
|
||||
|
||||
/* Glossy */
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID, /* virtual closure */
|
||||
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
|
||||
|
||||
@@ -2674,8 +2674,10 @@ NODE_DEFINE(PrincipledBsdfNode)
|
||||
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
|
||||
SOCKET_IN_FLOAT(sheen_roughness, "Sheen Roughness", 0.5f);
|
||||
SOCKET_IN_COLOR(sheen_tint, "Sheen Tint", one_float3());
|
||||
SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
|
||||
SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
|
||||
SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
|
||||
SOCKET_IN_FLOAT(coat_roughness, "Coat Roughness", 0.03f);
|
||||
SOCKET_IN_FLOAT(coat_ior, "Coat IOR", 1.5f);
|
||||
SOCKET_IN_COLOR(coat_tint, "Coat Tint", one_float3());
|
||||
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
|
||||
SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
|
||||
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
|
||||
@@ -2683,7 +2685,7 @@ NODE_DEFINE(PrincipledBsdfNode)
|
||||
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 1.0f);
|
||||
SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
|
||||
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
|
||||
SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", zero_float3(), SocketType::LINK_NORMAL);
|
||||
SOCKET_IN_NORMAL(coat_normal, "Coat Normal", zero_float3(), SocketType::LINK_NORMAL);
|
||||
SOCKET_IN_NORMAL(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
|
||||
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
|
||||
|
||||
@@ -2785,8 +2787,10 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
||||
ShaderInput *p_sheen,
|
||||
ShaderInput *p_sheen_roughness,
|
||||
ShaderInput *p_sheen_tint,
|
||||
ShaderInput *p_clearcoat,
|
||||
ShaderInput *p_clearcoat_roughness,
|
||||
ShaderInput *p_coat,
|
||||
ShaderInput *p_coat_roughness,
|
||||
ShaderInput *p_coat_ior,
|
||||
ShaderInput *p_coat_tint,
|
||||
ShaderInput *p_ior,
|
||||
ShaderInput *p_transmission,
|
||||
ShaderInput *p_anisotropic_rotation)
|
||||
@@ -2794,7 +2798,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
||||
ShaderInput *base_color_in = input("Base Color");
|
||||
ShaderInput *subsurface_color_in = input("Subsurface Color");
|
||||
ShaderInput *normal_in = input("Normal");
|
||||
ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
|
||||
ShaderInput *coat_normal_in = input("Coat Normal");
|
||||
ShaderInput *tangent_in = input("Tangent");
|
||||
|
||||
float3 weight = one_float3();
|
||||
@@ -2802,7 +2806,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
||||
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
|
||||
|
||||
int normal_offset = compiler.stack_assign_if_linked(normal_in);
|
||||
int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
|
||||
int coat_normal_offset = compiler.stack_assign_if_linked(coat_normal_in);
|
||||
int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
|
||||
int specular_offset = compiler.stack_assign(p_specular);
|
||||
int roughness_offset = compiler.stack_assign(p_roughness);
|
||||
@@ -2811,8 +2815,10 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
||||
int sheen_offset = compiler.stack_assign(p_sheen);
|
||||
int sheen_roughness_offset = compiler.stack_assign(p_sheen_roughness);
|
||||
int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
|
||||
int clearcoat_offset = compiler.stack_assign(p_clearcoat);
|
||||
int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
|
||||
int coat_offset = compiler.stack_assign(p_coat);
|
||||
int coat_roughness_offset = compiler.stack_assign(p_coat_roughness);
|
||||
int coat_ior_offset = compiler.stack_assign(p_coat_ior);
|
||||
int coat_tint_offset = compiler.stack_assign(p_coat_tint);
|
||||
int ior_offset = compiler.stack_assign(p_ior);
|
||||
int transmission_offset = compiler.stack_assign(p_transmission);
|
||||
int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
|
||||
@@ -2834,14 +2840,15 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
||||
compiler.encode_uchar4(
|
||||
specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
|
||||
compiler.encode_uchar4(
|
||||
sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
|
||||
sheen_offset, sheen_tint_offset, sheen_roughness_offset, SVM_STACK_INVALID));
|
||||
|
||||
compiler.add_node(
|
||||
compiler.encode_uchar4(
|
||||
ior_offset, transmission_offset, anisotropic_rotation_offset, SVM_STACK_INVALID),
|
||||
distribution,
|
||||
subsurface_method,
|
||||
sheen_roughness_offset);
|
||||
compiler.encode_uchar4(
|
||||
coat_offset, coat_roughness_offset, coat_ior_offset, coat_tint_offset));
|
||||
|
||||
float3 bc_default = get_float3(base_color_in->socket_type);
|
||||
|
||||
@@ -2851,7 +2858,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
||||
__float_as_int(bc_default.y),
|
||||
__float_as_int(bc_default.z));
|
||||
|
||||
compiler.add_node(clearcoat_normal_offset,
|
||||
compiler.add_node(coat_normal_offset,
|
||||
subsurface_radius_offset,
|
||||
subsurface_ior_offset,
|
||||
subsurface_anisotropy_offset);
|
||||
@@ -2880,8 +2887,10 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
||||
input("Sheen"),
|
||||
input("Sheen Roughness"),
|
||||
input("Sheen Tint"),
|
||||
input("Clearcoat"),
|
||||
input("Clearcoat Roughness"),
|
||||
input("Coat"),
|
||||
input("Coat Roughness"),
|
||||
input("Coat IOR"),
|
||||
input("Coat Tint"),
|
||||
input("IOR"),
|
||||
input("Transmission"),
|
||||
input("Anisotropic Rotation"));
|
||||
|
||||
@@ -530,8 +530,10 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
||||
ShaderInput *sheen,
|
||||
ShaderInput *sheen_roughness,
|
||||
ShaderInput *sheen_tint,
|
||||
ShaderInput *clearcoat,
|
||||
ShaderInput *clearcoat_roughness,
|
||||
ShaderInput *coat,
|
||||
ShaderInput *coat_roughness,
|
||||
ShaderInput *coat_ior,
|
||||
ShaderInput *coat_tint,
|
||||
ShaderInput *ior,
|
||||
ShaderInput *transmission,
|
||||
ShaderInput *anisotropic_rotation);
|
||||
@@ -550,13 +552,15 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
||||
NODE_SOCKET_API(float, sheen)
|
||||
NODE_SOCKET_API(float, sheen_roughness)
|
||||
NODE_SOCKET_API(float3, sheen_tint)
|
||||
NODE_SOCKET_API(float, clearcoat)
|
||||
NODE_SOCKET_API(float, clearcoat_roughness)
|
||||
NODE_SOCKET_API(float, coat)
|
||||
NODE_SOCKET_API(float, coat_roughness)
|
||||
NODE_SOCKET_API(float, coat_ior)
|
||||
NODE_SOCKET_API(float3, coat_tint)
|
||||
NODE_SOCKET_API(float, ior)
|
||||
NODE_SOCKET_API(float, transmission)
|
||||
NODE_SOCKET_API(float, anisotropic_rotation)
|
||||
NODE_SOCKET_API(float3, normal)
|
||||
NODE_SOCKET_API(float3, clearcoat_normal)
|
||||
NODE_SOCKET_API(float3, coat_normal)
|
||||
NODE_SOCKET_API(float3, tangent)
|
||||
NODE_SOCKET_API(float, surface_mix_weight)
|
||||
NODE_SOCKET_API(ClosureType, distribution)
|
||||
|
||||
@@ -655,6 +655,35 @@ static void versioning_convert_node_tree_socket_lists_to_interface(bNodeTree *nt
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert coat inputs on the Principled BSDF. */
|
||||
static void version_principled_bsdf_coat(bNodeTree *ntree)
|
||||
{
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != SH_NODE_BSDF_PRINCIPLED) {
|
||||
continue;
|
||||
}
|
||||
if (nodeFindSocket(node, SOCK_IN, "Coat IOR") != nullptr) {
|
||||
continue;
|
||||
}
|
||||
bNodeSocket *coat_ior_input = nodeAddStaticSocket(
|
||||
ntree, node, SOCK_IN, SOCK_FLOAT, PROP_NONE, "Coat IOR", "Coat IOR");
|
||||
|
||||
/* Adjust for 4x change in intensity. */
|
||||
bNodeSocket *coat_input = nodeFindSocket(node, SOCK_IN, "Clearcoat");
|
||||
*version_cycles_node_socket_float_value(coat_input) *= 0.25f;
|
||||
/* When the coat input is dynamic, instead of inserting a *0.25 math node, set the Coat IOR
|
||||
* to 1.2 instead - this also roughly quarters reflectivity compared to the 1.5 default. */
|
||||
*version_cycles_node_socket_float_value(coat_ior_input) = (coat_input->link) ? 1.2f : 1.5f;
|
||||
}
|
||||
|
||||
/* Rename sockets. */
|
||||
version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Clearcoat", "Coat");
|
||||
version_node_input_socket_name(
|
||||
ntree, SH_NODE_BSDF_PRINCIPLED, "Clearcoat Roughness", "Coat Roughness");
|
||||
version_node_input_socket_name(
|
||||
ntree, SH_NODE_BSDF_PRINCIPLED, "Clearcoat Normal", "Coat Normal");
|
||||
}
|
||||
|
||||
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
{
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
|
||||
@@ -1062,5 +1091,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type == NTREE_SHADER) {
|
||||
/* Convert coat inputs on the Principled BSDF. */
|
||||
version_principled_bsdf_coat(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,15 +230,13 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
|
||||
|
||||
/* Specular BSDF */
|
||||
CLOSURE_EVAL_FUNCTION_DECLARE_3(SpecularBSDF, Diffuse, Glossy, Glossy)
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat)
|
||||
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection, ClosureReflection coat)
|
||||
{
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(diffuse);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
Closure closure_clearcoat = closure_eval(clearcoat, false);
|
||||
closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance;
|
||||
Closure closure_coat = closure_eval(coat, false);
|
||||
closure.radiance += closure_reflection.radiance + closure_coat.radiance;
|
||||
return closure;
|
||||
#else
|
||||
/* Glue with the old system. */
|
||||
@@ -250,8 +248,8 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
||||
in_Diffuse_0.albedo = diffuse.color;
|
||||
in_Glossy_1.N = reflection.N;
|
||||
in_Glossy_1.roughness = reflection.roughness;
|
||||
in_Glossy_2.N = clearcoat.N;
|
||||
in_Glossy_2.roughness = clearcoat.roughness;
|
||||
in_Glossy_2.N = coat.N;
|
||||
in_Glossy_2.roughness = coat.roughness;
|
||||
|
||||
CLOSURE_EVAL_FUNCTION_3(SpecularBSDF, Diffuse, Glossy, Glossy);
|
||||
|
||||
@@ -259,7 +257,7 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
||||
if (!output_sss(diffuse, out_Diffuse_0)) {
|
||||
closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
|
||||
}
|
||||
closure.radiance += out_Glossy_2.radiance * clearcoat.color * clearcoat.weight;
|
||||
closure.radiance += out_Glossy_2.radiance * coat.color * coat.weight;
|
||||
if (!output_ssr(reflection)) {
|
||||
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
@@ -271,15 +269,15 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
||||
CLOSURE_EVAL_FUNCTION_DECLARE_4(PrincipledBSDF, Diffuse, Glossy, Glossy, Refraction)
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat,
|
||||
ClosureReflection coat,
|
||||
ClosureRefraction refraction)
|
||||
{
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(diffuse);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
Closure closure_clearcoat = closure_eval(clearcoat, false);
|
||||
Closure closure_coat = closure_eval(coat, false);
|
||||
Closure closure_refraction = closure_eval(refraction);
|
||||
closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance +
|
||||
closure.radiance += closure_reflection.radiance + closure_coat.radiance +
|
||||
closure_refraction.radiance;
|
||||
return closure;
|
||||
#else
|
||||
@@ -290,8 +288,8 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
||||
in_Diffuse_0.albedo = diffuse.color;
|
||||
in_Glossy_1.N = reflection.N;
|
||||
in_Glossy_1.roughness = reflection.roughness;
|
||||
in_Glossy_2.N = clearcoat.N;
|
||||
in_Glossy_2.roughness = clearcoat.roughness;
|
||||
in_Glossy_2.N = coat.N;
|
||||
in_Glossy_2.roughness = coat.roughness;
|
||||
in_Refraction_3.N = refraction.N;
|
||||
in_Refraction_3.roughness = refraction.roughness;
|
||||
in_Refraction_3.ior = refraction.ior;
|
||||
@@ -299,7 +297,7 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
||||
CLOSURE_EVAL_FUNCTION_4(PrincipledBSDF, Diffuse, Glossy, Glossy, Refraction);
|
||||
|
||||
Closure closure = CLOSURE_DEFAULT;
|
||||
closure.radiance += out_Glossy_2.radiance * clearcoat.color * clearcoat.weight;
|
||||
closure.radiance += out_Glossy_2.radiance * coat.color * coat.weight;
|
||||
closure.radiance += out_Refraction_3.radiance * refraction.color * refraction.weight;
|
||||
if (!output_sss(diffuse, out_Diffuse_0)) {
|
||||
closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
|
||||
@@ -312,10 +310,10 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
||||
}
|
||||
|
||||
CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy)
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection coat)
|
||||
{
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(clearcoat);
|
||||
Closure closure = closure_eval(coat);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
closure.radiance += closure_reflection.radiance;
|
||||
return closure;
|
||||
@@ -325,13 +323,13 @@ Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
|
||||
|
||||
in_Glossy_0.N = reflection.N;
|
||||
in_Glossy_0.roughness = reflection.roughness;
|
||||
in_Glossy_1.N = clearcoat.N;
|
||||
in_Glossy_1.roughness = clearcoat.roughness;
|
||||
in_Glossy_1.N = coat.N;
|
||||
in_Glossy_1.roughness = coat.roughness;
|
||||
|
||||
CLOSURE_EVAL_FUNCTION_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy);
|
||||
|
||||
Closure closure = CLOSURE_DEFAULT;
|
||||
closure.radiance += out_Glossy_1.radiance * clearcoat.color * clearcoat.weight;
|
||||
closure.radiance += out_Glossy_1.radiance * coat.color * coat.weight;
|
||||
if (!output_ssr(reflection)) {
|
||||
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
|
||||
@@ -42,20 +42,18 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
|
||||
{
|
||||
return CLOSURE_DEFAULT;
|
||||
}
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat)
|
||||
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection, ClosureReflection coat)
|
||||
{
|
||||
return CLOSURE_DEFAULT;
|
||||
}
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat,
|
||||
ClosureReflection coat,
|
||||
ClosureRefraction refraction)
|
||||
{
|
||||
return CLOSURE_DEFAULT;
|
||||
}
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection coat)
|
||||
{
|
||||
return CLOSURE_DEFAULT;
|
||||
}
|
||||
|
||||
@@ -67,20 +67,18 @@ Closure closure_eval(ClosureHair hair);
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction);
|
||||
/* Dielectric BSDF. */
|
||||
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection);
|
||||
/* ClearCoat BSDF. */
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat);
|
||||
/* Coat BSDF. */
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection coat);
|
||||
/* Volume BSDF. */
|
||||
Closure closure_eval(ClosureVolumeScatter volume_scatter,
|
||||
ClosureVolumeAbsorption volume_absorption,
|
||||
ClosureEmission emission);
|
||||
/* Specular BSDF. */
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat);
|
||||
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection, ClosureReflection coat);
|
||||
/* Principled BSDF. */
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat,
|
||||
ClosureReflection coat,
|
||||
ClosureRefraction refraction);
|
||||
|
||||
Closure closure_add(inout Closure cl1, inout Closure cl2);
|
||||
|
||||
@@ -166,11 +166,11 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
|
||||
return Closure(0);
|
||||
}
|
||||
|
||||
/* ClearCoat BSDF. */
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
|
||||
/* Coat BSDF. */
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection coat)
|
||||
{
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, reflection);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, clearcoat);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, coat);
|
||||
return Closure(0);
|
||||
}
|
||||
|
||||
@@ -186,25 +186,23 @@ Closure closure_eval(ClosureVolumeScatter volume_scatter,
|
||||
}
|
||||
|
||||
/* Specular BSDF. */
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat)
|
||||
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection, ClosureReflection coat)
|
||||
{
|
||||
SELECT_CLOSURE(g_diffuse_data, g_diffuse_rand, diffuse);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, reflection);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, clearcoat);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, coat);
|
||||
return Closure(0);
|
||||
}
|
||||
|
||||
/* Principled BSDF. */
|
||||
Closure closure_eval(ClosureDiffuse diffuse,
|
||||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat,
|
||||
ClosureReflection coat,
|
||||
ClosureRefraction refraction)
|
||||
{
|
||||
SELECT_CLOSURE(g_diffuse_data, g_diffuse_rand, diffuse);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, reflection);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, clearcoat);
|
||||
SELECT_CLOSURE(g_reflection_data, g_reflection_rand, coat);
|
||||
SELECT_CLOSURE(g_refraction_data, g_refraction_rand, refraction);
|
||||
return Closure(0);
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ void WM_OT_obj_export(wmOperatorType *ot)
|
||||
false,
|
||||
"Export Materials with PBR Extensions",
|
||||
"Export MTL library using PBR extensions (roughness, metallic, sheen, "
|
||||
"clearcoat, anisotropy, transmission)");
|
||||
"coat, anisotropy, transmission)");
|
||||
RNA_def_enum(ot->srna,
|
||||
"path_mode",
|
||||
io_obj_path_mode,
|
||||
|
||||
@@ -78,7 +78,7 @@ typedef enum eGPUMaterialFlag {
|
||||
GPU_MATFLAG_HOLDOUT = (1 << 6),
|
||||
GPU_MATFLAG_SHADER_TO_RGBA = (1 << 7),
|
||||
GPU_MATFLAG_AO = (1 << 8),
|
||||
GPU_MATFLAG_CLEARCOAT = (1 << 9),
|
||||
GPU_MATFLAG_COAT = (1 << 9),
|
||||
|
||||
GPU_MATFLAG_OBJECT_INFO = (1 << 10),
|
||||
GPU_MATFLAG_AOV = (1 << 11),
|
||||
@@ -86,7 +86,7 @@ typedef enum eGPUMaterialFlag {
|
||||
GPU_MATFLAG_BARYCENTRIC = (1 << 20),
|
||||
|
||||
/* Optimization to only add the branches of the principled shader that are necessary. */
|
||||
GPU_MATFLAG_PRINCIPLED_CLEARCOAT = (1 << 21),
|
||||
GPU_MATFLAG_PRINCIPLED_COAT = (1 << 21),
|
||||
GPU_MATFLAG_PRINCIPLED_METALLIC = (1 << 22),
|
||||
GPU_MATFLAG_PRINCIPLED_DIELECTRIC = (1 << 23),
|
||||
GPU_MATFLAG_PRINCIPLED_GLASS = (1 << 24),
|
||||
|
||||
@@ -404,8 +404,8 @@ void GPUCodegen::generate_resources()
|
||||
|
||||
/* Ref. #98190: Defines are optimizations for old compilers.
|
||||
* Might become unnecessary with EEVEE-Next. */
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_CLEARCOAT)) {
|
||||
info.define("PRINCIPLED_CLEARCOAT");
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_COAT)) {
|
||||
info.define("PRINCIPLED_COAT");
|
||||
}
|
||||
if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_METALLIC)) {
|
||||
info.define("PRINCIPLED_METALLIC");
|
||||
|
||||
@@ -33,8 +33,10 @@ void node_bsdf_principled(vec4 base_color,
|
||||
float sheen,
|
||||
float sheen_roughness,
|
||||
vec4 sheen_tint,
|
||||
float clearcoat,
|
||||
float clearcoat_roughness,
|
||||
float coat,
|
||||
float coat_roughness,
|
||||
float coat_ior,
|
||||
vec4 coat_tint,
|
||||
float ior,
|
||||
float transmission,
|
||||
vec4 emission,
|
||||
@@ -45,7 +47,7 @@ void node_bsdf_principled(vec4 base_color,
|
||||
vec3 T,
|
||||
float weight,
|
||||
const float do_diffuse,
|
||||
const float do_clearcoat,
|
||||
const float do_coat,
|
||||
const float do_refraction,
|
||||
const float do_multiscatter,
|
||||
float do_sss,
|
||||
@@ -54,7 +56,8 @@ void node_bsdf_principled(vec4 base_color,
|
||||
/* Match cycles. */
|
||||
metallic = clamp(metallic, 0.0, 1.0);
|
||||
transmission = clamp(transmission, 0.0, 1.0);
|
||||
clearcoat = max(clearcoat, 0.0) * 0.25;
|
||||
coat = max(coat, 0.0);
|
||||
coat_ior = max(coat_ior, 1.0);
|
||||
|
||||
N = safe_normalize(N);
|
||||
CN = safe_normalize(CN);
|
||||
@@ -76,22 +79,31 @@ void node_bsdf_principled(vec4 base_color,
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - max_v3(sheen_color));
|
||||
|
||||
/* Second layer: Clearcoat */
|
||||
ClosureReflection clearcoat_data;
|
||||
clearcoat_data.N = CN;
|
||||
clearcoat_data.roughness = clearcoat_roughness;
|
||||
float coat_ior = 1.5;
|
||||
float coat_NV = dot(clearcoat_data.N, V);
|
||||
float reflectance = btdf_lut(coat_NV, clearcoat_data.roughness, coat_ior, 0.0).y;
|
||||
clearcoat_data.weight = weight * clearcoat * reflectance;
|
||||
clearcoat_data.color = vec3(1.0);
|
||||
/* Second layer: Coat */
|
||||
ClosureReflection coat_data;
|
||||
coat_data.N = CN;
|
||||
coat_data.roughness = coat_roughness;
|
||||
float coat_NV = dot(coat_data.N, V);
|
||||
float reflectance = btdf_lut(coat_NV, coat_data.roughness, coat_ior, 0.0).y;
|
||||
coat_data.weight = weight * coat * reflectance;
|
||||
coat_data.color = vec3(1.0);
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - reflectance * clearcoat);
|
||||
weight *= (1.0 - reflectance * coat);
|
||||
|
||||
/* Attenuated by sheen and clearcoat. */
|
||||
if (coat == 0) {
|
||||
coat_tint.rgb = vec3(1.0);
|
||||
}
|
||||
else if (!all(equal(coat_tint.rgb, vec3(1.0)))) {
|
||||
float coat_neta = 1.0 / coat_ior;
|
||||
float NT = fast_sqrt(1.0 - coat_neta * coat_neta * (1 - NV * NV));
|
||||
/* Tint lower layers. */
|
||||
coat_tint.rgb = pow(coat_tint.rgb, vec3(coat / NT));
|
||||
}
|
||||
|
||||
/* Attenuated by sheen and coat. */
|
||||
ClosureEmission emission_data;
|
||||
emission_data.weight = weight;
|
||||
emission_data.emission = emission.rgb * emission_strength;
|
||||
emission_data.emission = coat_tint.rgb * emission.rgb * emission_strength;
|
||||
|
||||
/* Metallic component */
|
||||
ClosureReflection reflection_data;
|
||||
@@ -118,7 +130,7 @@ void node_bsdf_principled(vec4 base_color,
|
||||
reflection_data.color += weight * transmission * bsdf.y * reflection_tint;
|
||||
|
||||
refraction_data.weight = weight * transmission * bsdf.x;
|
||||
refraction_data.color = base_color.rgb;
|
||||
refraction_data.color = base_color.rgb * coat_tint.rgb;
|
||||
refraction_data.N = N;
|
||||
refraction_data.roughness = roughness;
|
||||
refraction_data.ior = ior;
|
||||
@@ -146,36 +158,38 @@ void node_bsdf_principled(vec4 base_color,
|
||||
vec3 diffuse_color = mix(base_color.rgb, subsurface_color.rgb, subsurface);
|
||||
diffuse_data.sss_radius = subsurface_radius * subsurface;
|
||||
diffuse_data.sss_id = uint(do_sss);
|
||||
diffuse_data.color += weight * diffuse_color;
|
||||
diffuse_data.color += weight * diffuse_color * coat_tint.rgb;
|
||||
}
|
||||
|
||||
/* Adjust the weight of picking the closure. */
|
||||
reflection_data.color *= coat_tint.rgb;
|
||||
reflection_data.weight = avg(reflection_data.color);
|
||||
reflection_data.color *= safe_rcp(reflection_data.weight);
|
||||
|
||||
diffuse_data.weight = avg(diffuse_data.color);
|
||||
diffuse_data.color *= safe_rcp(diffuse_data.weight);
|
||||
|
||||
/* Ref. #98190: Defines are optimizations for old compilers.
|
||||
* Might become unnecessary with EEVEE-Next. */
|
||||
if (do_diffuse == 0.0 && do_refraction == 0.0 && do_clearcoat != 0.0) {
|
||||
#ifdef PRINCIPLED_CLEARCOAT
|
||||
/* Metallic & Clearcoat case. */
|
||||
result = closure_eval(reflection_data, clearcoat_data);
|
||||
if (do_diffuse == 0.0 && do_refraction == 0.0 && do_coat != 0.0) {
|
||||
#ifdef PRINCIPLED_COAT
|
||||
/* Metallic & Coat case. */
|
||||
result = closure_eval(reflection_data, coat_data);
|
||||
#endif
|
||||
}
|
||||
else if (do_diffuse == 0.0 && do_refraction == 0.0 && do_clearcoat == 0.0) {
|
||||
else if (do_diffuse == 0.0 && do_refraction == 0.0 && do_coat == 0.0) {
|
||||
#ifdef PRINCIPLED_METALLIC
|
||||
/* Metallic case. */
|
||||
result = closure_eval(reflection_data);
|
||||
#endif
|
||||
}
|
||||
else if (do_diffuse != 0.0 && do_refraction == 0.0 && do_clearcoat == 0.0) {
|
||||
else if (do_diffuse != 0.0 && do_refraction == 0.0 && do_coat == 0.0) {
|
||||
#ifdef PRINCIPLED_DIELECTRIC
|
||||
/* Dielectric case. */
|
||||
result = closure_eval(diffuse_data, reflection_data);
|
||||
#endif
|
||||
}
|
||||
else if (do_diffuse == 0.0 && do_refraction != 0.0 && do_clearcoat == 0.0) {
|
||||
else if (do_diffuse == 0.0 && do_refraction != 0.0 && do_coat == 0.0) {
|
||||
#ifdef PRINCIPLED_GLASS
|
||||
/* Glass case. */
|
||||
result = closure_eval(reflection_data, refraction_data);
|
||||
@@ -184,7 +198,7 @@ void node_bsdf_principled(vec4 base_color,
|
||||
else {
|
||||
#ifdef PRINCIPLED_ANY
|
||||
/* Un-optimized case. */
|
||||
result = closure_eval(diffuse_data, reflection_data, clearcoat_data, refraction_data);
|
||||
result = closure_eval(diffuse_data, reflection_data, coat_data, refraction_data);
|
||||
#endif
|
||||
}
|
||||
Closure emission_cl = closure_eval(emission_data);
|
||||
|
||||
@@ -481,15 +481,12 @@ void USDMaterialReader::set_principled_node_inputs(bNode *principled,
|
||||
set_node_input(roughness_input, principled, "Roughness", ntree, column, &context);
|
||||
}
|
||||
|
||||
if (pxr::UsdShadeInput clearcoat_input = usd_shader.GetInput(usdtokens::clearcoat)) {
|
||||
set_node_input(clearcoat_input, principled, "Clearcoat", ntree, column, &context);
|
||||
if (pxr::UsdShadeInput coat_input = usd_shader.GetInput(usdtokens::clearcoat)) {
|
||||
set_node_input(coat_input, principled, "Coat", ntree, column, &context);
|
||||
}
|
||||
|
||||
if (pxr::UsdShadeInput clearcoat_roughness_input = usd_shader.GetInput(
|
||||
usdtokens::clearcoatRoughness))
|
||||
{
|
||||
set_node_input(
|
||||
clearcoat_roughness_input, principled, "Clearcoat Roughness", ntree, column, &context);
|
||||
if (pxr::UsdShadeInput coat_roughness_input = usd_shader.GetInput(usdtokens::clearcoatRoughness)) {
|
||||
set_node_input(coat_roughness_input, principled, "Coat Roughness", ntree, column, &context);
|
||||
}
|
||||
|
||||
if (pxr::UsdShadeInput opacity_input = usd_shader.GetInput(usdtokens::opacity)) {
|
||||
|
||||
@@ -298,9 +298,8 @@ static InputSpecMap &preview_surface_input_map()
|
||||
{"IOR", {usdtokens::ior, pxr::SdfValueTypeNames->Float, true}},
|
||||
/* Note that for the Normal input set_default_value is false. */
|
||||
{"Normal", {usdtokens::normal, pxr::SdfValueTypeNames->Float3, false}},
|
||||
{"Clearcoat", {usdtokens::clearcoat, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Clearcoat Roughness",
|
||||
{usdtokens::clearcoatRoughness, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Coat", {usdtokens::clearcoat, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Coat Roughness", {usdtokens::clearcoatRoughness, pxr::SdfValueTypeNames->Float, true}},
|
||||
};
|
||||
|
||||
return input_map;
|
||||
|
||||
@@ -237,19 +237,21 @@ static void store_bsdf_properties(const bNode *bsdf_node,
|
||||
mul_v3_fl(emission_col, emission_strength);
|
||||
|
||||
float sheen = -1.0f;
|
||||
float clearcoat = -1.0f;
|
||||
float clearcoat_roughness = -1.0f;
|
||||
float coat = -1.0f;
|
||||
float coat_roughness = -1.0f;
|
||||
float aniso = -1.0f;
|
||||
float aniso_rot = -1.0f;
|
||||
float transmission = -1.0f;
|
||||
if (bsdf_node) {
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Sheen", {&sheen, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Clearcoat", {&clearcoat, 1});
|
||||
copy_property_from_node(
|
||||
SOCK_FLOAT, bsdf_node, "Clearcoat Roughness", {&clearcoat_roughness, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Coat", {&coat, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Coat Roughness", {&coat_roughness, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Anisotropic", {&aniso, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Anisotropic Rotation", {&aniso_rot, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Transmission", {&transmission, 1});
|
||||
|
||||
/* Clearcoat used to include an implicit 0.25 factor, so stay compatible to old versions. */
|
||||
coat *= 4.0f;
|
||||
}
|
||||
|
||||
/* See https://wikipedia.org/wiki/Wavefront_.obj_file for all possible values of `illum`. */
|
||||
@@ -290,8 +292,8 @@ static void store_bsdf_properties(const bNode *bsdf_node,
|
||||
r_mtl_mat.roughness = roughness;
|
||||
r_mtl_mat.metallic = metallic;
|
||||
r_mtl_mat.sheen = sheen;
|
||||
r_mtl_mat.cc_thickness = clearcoat;
|
||||
r_mtl_mat.cc_roughness = clearcoat_roughness;
|
||||
r_mtl_mat.cc_thickness = coat;
|
||||
r_mtl_mat.cc_roughness = coat_roughness;
|
||||
r_mtl_mat.aniso = aniso;
|
||||
r_mtl_mat.aniso_rot = aniso_rot;
|
||||
r_mtl_mat.transmit_color = {transmission, transmission, transmission};
|
||||
|
||||
@@ -327,10 +327,11 @@ static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const MTLMaterial
|
||||
set_property_of_socket(SOCK_FLOAT, "Sheen", {mtl_mat.sheen}, bsdf);
|
||||
}
|
||||
if (mtl_mat.cc_thickness >= 0) {
|
||||
set_property_of_socket(SOCK_FLOAT, "Clearcoat", {mtl_mat.cc_thickness}, bsdf);
|
||||
/* Clearcoat used to include an implicit 0.25 factor, so stay compatible to old versions. */
|
||||
set_property_of_socket(SOCK_FLOAT, "Coat", {0.25f * mtl_mat.cc_thickness}, bsdf);
|
||||
}
|
||||
if (mtl_mat.cc_roughness >= 0) {
|
||||
set_property_of_socket(SOCK_FLOAT, "Clearcoat Roughness", {mtl_mat.cc_roughness}, bsdf);
|
||||
set_property_of_socket(SOCK_FLOAT, "Coat Roughness", {mtl_mat.cc_roughness}, bsdf);
|
||||
}
|
||||
if (mtl_mat.aniso >= 0) {
|
||||
set_property_of_socket(SOCK_FLOAT, "Anisotropic", {mtl_mat.aniso}, bsdf);
|
||||
|
||||
@@ -93,42 +93,62 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
#define SOCK_SHEEN_ROUGHNESS_ID 13
|
||||
b.add_input<decl::Color>("Sheen Tint").default_value({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
#define SOCK_SHEEN_TINT_ID 14
|
||||
b.add_input<decl::Float>("Clearcoat")
|
||||
b.add_input<decl::Float>("Coat")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_CLEARCOAT_ID 15
|
||||
b.add_input<decl::Float>("Clearcoat Roughness")
|
||||
.subtype(PROP_FACTOR)
|
||||
.description(
|
||||
"Controls the intensity of the coat layer, both the reflection and the tinting. "
|
||||
"Typically should be zero or one for physically-based materials");
|
||||
#define SOCK_COAT_ID 15
|
||||
b.add_input<decl::Float>("Coat Roughness")
|
||||
.default_value(0.03f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_CLEARCOAT_ROUGHNESS_ID 16
|
||||
.subtype(PROP_FACTOR)
|
||||
.description("The roughness of the coat layer");
|
||||
#define SOCK_COAT_ROUGHNESS_ID 16
|
||||
b.add_input<decl::Float>("Coat IOR")
|
||||
.default_value(1.5f)
|
||||
.min(1.0f)
|
||||
.max(4.0f)
|
||||
.description(
|
||||
"The index of refraction of the coat layer (affects its reflectivity as well "
|
||||
"as the falloff of coat tinting)");
|
||||
#define SOCK_COAT_IOR_ID 17
|
||||
b.add_input<decl::Color>("Coat Tint")
|
||||
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
|
||||
.description(
|
||||
"Adds a colored tint to the coat layer by modeling absorption in the layer. "
|
||||
"Saturation increases at shallower angles, as the light travels farther through the "
|
||||
"medium "
|
||||
"(depending on the Coat IOR)");
|
||||
#define SOCK_COAT_TINT_ID 18
|
||||
b.add_input<decl::Float>("IOR").default_value(1.45f).min(1.0f).max(1000.0f);
|
||||
#define SOCK_IOR_ID 17
|
||||
#define SOCK_IOR_ID 19
|
||||
b.add_input<decl::Float>("Transmission")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_TRANSMISSION_ID 18
|
||||
#define SOCK_TRANSMISSION_ID 20
|
||||
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 21
|
||||
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 22
|
||||
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 23
|
||||
b.add_input<decl::Vector>("Normal").hide_value();
|
||||
#define SOCK_NORMAL_ID 22
|
||||
b.add_input<decl::Vector>("Clearcoat Normal").hide_value();
|
||||
#define SOCK_CLEARCOAT_NORMAL_ID 23
|
||||
#define SOCK_NORMAL_ID 24
|
||||
b.add_input<decl::Vector>("Coat Normal").hide_value();
|
||||
#define SOCK_COAT_NORMAL_ID 25
|
||||
b.add_input<decl::Vector>("Tangent").hide_value();
|
||||
#define SOCK_TANGENT_ID 24
|
||||
#define SOCK_TANGENT_ID 26
|
||||
b.add_input<decl::Float>("Weight").unavailable();
|
||||
#define SOCK_WEIGHT_ID 25
|
||||
#define SOCK_WEIGHT_ID 27
|
||||
b.add_output<decl::Shader>("BSDF");
|
||||
#define SOCK_BSDF_ID 26
|
||||
#define SOCK_BSDF_ID 28
|
||||
}
|
||||
|
||||
static void node_shader_buts_principled(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
@@ -158,9 +178,9 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
||||
GPU_link(mat, "world_normals_get", &in[SOCK_NORMAL_ID].link);
|
||||
}
|
||||
|
||||
/* Clearcoat Normals */
|
||||
if (!in[SOCK_CLEARCOAT_NORMAL_ID].link) {
|
||||
GPU_link(mat, "world_normals_get", &in[SOCK_CLEARCOAT_NORMAL_ID].link);
|
||||
/* Coat Normals */
|
||||
if (!in[SOCK_COAT_NORMAL_ID].link) {
|
||||
GPU_link(mat, "world_normals_get", &in[SOCK_COAT_NORMAL_ID].link);
|
||||
}
|
||||
|
||||
#if 0 /* Not used at the moment. */
|
||||
@@ -177,7 +197,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
||||
bool use_subsurf = socket_not_zero(SOCK_SUBSURFACE_ID) && use_diffuse;
|
||||
bool use_refract = socket_not_one(SOCK_METALLIC_ID) && socket_not_zero(SOCK_TRANSMISSION_ID);
|
||||
bool use_transparency = socket_not_one(SOCK_ALPHA_ID);
|
||||
bool use_clear = socket_not_zero(SOCK_CLEARCOAT_ID);
|
||||
bool use_coat = socket_not_zero(SOCK_COAT_ID);
|
||||
|
||||
eGPUMaterialFlag flag = GPU_MATFLAG_GLOSSY;
|
||||
if (use_diffuse) {
|
||||
@@ -192,22 +212,22 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
||||
if (use_transparency) {
|
||||
flag |= GPU_MATFLAG_TRANSPARENT;
|
||||
}
|
||||
if (use_clear) {
|
||||
flag |= GPU_MATFLAG_CLEARCOAT;
|
||||
if (use_coat) {
|
||||
flag |= GPU_MATFLAG_COAT;
|
||||
}
|
||||
|
||||
/* Ref. #98190: Defines are optimizations for old compilers.
|
||||
* Might become unnecessary with EEVEE-Next. */
|
||||
if (use_diffuse == false && use_refract == false && use_clear == true) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_CLEARCOAT;
|
||||
if (use_diffuse == false && use_refract == false && use_coat == true) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_COAT;
|
||||
}
|
||||
else if (use_diffuse == false && use_refract == false && use_clear == false) {
|
||||
else if (use_diffuse == false && use_refract == false && use_coat == false) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_METALLIC;
|
||||
}
|
||||
else if (use_diffuse == true && use_refract == false && use_clear == false) {
|
||||
else if (use_diffuse == true && use_refract == false && use_coat == false) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_DIELECTRIC;
|
||||
}
|
||||
else if (use_diffuse == false && use_refract == true && use_clear == false) {
|
||||
else if (use_diffuse == false && use_refract == true && use_coat == false) {
|
||||
flag |= GPU_MATFLAG_PRINCIPLED_GLASS;
|
||||
}
|
||||
else {
|
||||
@@ -225,7 +245,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
||||
float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f;
|
||||
float use_sss = (use_subsurf) ? 1.0f : 0.0f;
|
||||
float use_diffuse_f = (use_diffuse) ? 1.0f : 0.0f;
|
||||
float use_clear_f = (use_clear) ? 1.0f : 0.0f;
|
||||
float use_coat_f = (use_coat) ? 1.0f : 0.0f;
|
||||
float use_refract_f = (use_refract) ? 1.0f : 0.0f;
|
||||
|
||||
GPU_material_flag_set(mat, flag);
|
||||
@@ -236,7 +256,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
||||
in,
|
||||
out,
|
||||
GPU_constant(&use_diffuse_f),
|
||||
GPU_constant(&use_clear_f),
|
||||
GPU_constant(&use_coat_f),
|
||||
GPU_constant(&use_refract_f),
|
||||
GPU_constant(&use_multi_scatter),
|
||||
GPU_uniform(&use_sss));
|
||||
|
||||
@@ -53,7 +53,7 @@ static int node_shader_gpu_eevee_specular(GPUMaterial *mat,
|
||||
GPU_link(mat, "world_normals_get", &in[5].link);
|
||||
}
|
||||
|
||||
/* Clearcoat Normals */
|
||||
/* Coat Normals */
|
||||
if (!in[8].link) {
|
||||
GPU_link(mat, "world_normals_get", &in[8].link);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user