Principled v2 combined changes for 4.0 #112848
|
@ -537,12 +537,12 @@ static ShaderNode *add_node(Scene *scene,
|
|||
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
|
||||
subsurface->set_method(CLOSURE_BSSRDF_BURLEY_ID);
|
||||
break;
|
||||
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK_FIXED_RADIUS:
|
||||
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
|
||||
break;
|
||||
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK:
|
||||
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_ID);
|
||||
break;
|
||||
case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK_SKIN:
|
||||
subsurface->set_method(CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
|
||||
break;
|
||||
}
|
||||
|
||||
node = subsurface;
|
||||
|
@ -651,12 +651,12 @@ static ShaderNode *add_node(Scene *scene,
|
|||
case BL::ShaderNodeBsdfPrincipled::subsurface_method_BURLEY:
|
||||
principled->set_subsurface_method(CLOSURE_BSSRDF_BURLEY_ID);
|
||||
break;
|
||||
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK_FIXED_RADIUS:
|
||||
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
|
||||
break;
|
||||
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK:
|
||||
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_ID);
|
||||
break;
|
||||
case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK_SKIN:
|
||||
principled->set_subsurface_method(CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
|
||||
break;
|
||||
}
|
||||
node = principled;
|
||||
}
|
||||
|
|
|
@ -359,7 +359,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
|
|||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
case CLOSURE_BSSRDF_BURLEY_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
#ifdef __SVM__
|
||||
|
|
|
@ -26,6 +26,7 @@ enum MicrofacetFresnel {
|
|||
DIELECTRIC_TINT, /* used by the OSL MaterialX closures */
|
||||
CONDUCTOR,
|
||||
GENERALIZED_SCHLICK,
|
||||
F82_TINT,
|
||||
};
|
||||
|
||||
typedef struct FresnelDielectricTint {
|
||||
|
@ -46,6 +47,13 @@ typedef struct FresnelGeneralizedSchlick {
|
|||
float exponent;
|
||||
} FresnelGeneralizedSchlick;
|
||||
|
||||
typedef struct FresnelF82Tint {
|
||||
/* Perpendicular reflectivity. */
|
||||
Spectrum f0;
|
||||
/* Precomputed (1-cos)^6 factor for edge tint. */
|
||||
Spectrum b;
|
||||
} FresnelF82Tint;
|
||||
|
||||
typedef struct MicrofacetBsdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
|
@ -236,6 +244,17 @@ ccl_device_forceinline void microfacet_fresnel(ccl_private const MicrofacetBsdf
|
|||
*r_reflectance = fresnel_conductor(cos_theta_i, fresnel->n, fresnel->k);
|
||||
*r_transmittance = zero_spectrum();
|
||||
}
|
||||
else if (bsdf->fresnel_type == MicrofacetFresnel::F82_TINT) {
|
||||
/* F82-Tint model, described in "Novel aspects of the Adobe Standard Material" by Kutz et al.
|
||||
* Essentially, this is the usual Schlick Fresnel with an additional cosI*(1-cosI)^6
|
||||
* term which modulates the reflectivity around acos(1/7) degrees (ca. 82°). */
|
||||
ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)bsdf->fresnel;
|
||||
const float mu = saturatef(1.0f - cos_theta_i);
|
||||
const float mu5 = sqr(sqr(mu)) * mu;
|
||||
const Spectrum F_schlick = mix(fresnel->f0, one_spectrum(), mu5);
|
||||
*r_reflectance = saturate(F_schlick - fresnel->b * cos_theta_i * mu5 * mu);
|
||||
*r_transmittance = zero_spectrum();
|
||||
}
|
||||
else if (bsdf->fresnel_type == MicrofacetFresnel::GENERALIZED_SCHLICK) {
|
||||
ccl_private FresnelGeneralizedSchlick *fresnel = (ccl_private FresnelGeneralizedSchlick *)
|
||||
bsdf->fresnel;
|
||||
|
@ -379,6 +398,14 @@ ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg,
|
|||
}
|
||||
reflectance = mix(fresnel->f0, fresnel->f90, s) * fresnel->reflection_tint;
|
||||
}
|
||||
else if (bsdf->fresnel_type == MicrofacetFresnel::F82_TINT) {
|
||||
ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)bsdf->fresnel;
|
||||
float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
|
||||
const float s = lookup_table_read_3D(
|
||||
kg, rough, cos_NI, 0.5f, kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
|
||||
/* TODO: Precompute B factor term and account for it here. */
|
||||
reflectance = mix(fresnel->f0, one_spectrum(), s);
|
||||
}
|
||||
|
||||
return reflectance + transmittance;
|
||||
}
|
||||
|
@ -738,6 +765,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(
|
|||
ccl_private FresnelGeneralizedSchlick *fresnel,
|
||||
const bool preserve_energy)
|
||||
{
|
||||
fresnel->f0 = saturate(fresnel->f0);
|
||||
bsdf->fresnel_type = MicrofacetFresnel::GENERALIZED_SCHLICK;
|
||||
bsdf->fresnel = fresnel;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
|
@ -780,6 +808,40 @@ ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(
|
|||
}
|
||||
}
|
||||
|
||||
ccl_device void bsdf_microfacet_setup_fresnel_f82_tint(KernelGlobals kg,
|
||||
ccl_private MicrofacetBsdf *bsdf,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private FresnelF82Tint *fresnel,
|
||||
const Spectrum f82_tint,
|
||||
const bool preserve_energy)
|
||||
{
|
||||
if (isequal(f82_tint, one_spectrum())) {
|
||||
fresnel->b = zero_spectrum();
|
||||
}
|
||||
else {
|
||||
/* Precompute the F82 term factor for the Fresnel model.
|
||||
* In the classic F82 model, the F82 input directly determines the value of the Fresnel
|
||||
* model at ~82°, similar to F0 and F90.
|
||||
* With F82-Tint, on the other hand, the value at 82° is the value of the classic Schlick
|
||||
* model multiplied by the tint input.
|
||||
* Therefore, the factor follows by setting F82Tint(cosI) = FSchlick(cosI) - b*cosI*(1-cosI)^6
|
||||
* and F82Tint(acos(1/7)) = FSchlick(acos(1/7)) * f82_tint and solving for b. */
|
||||
const float f = 6.0f / 7.0f;
|
||||
const float f5 = sqr(sqr(f)) * f;
|
||||
const Spectrum F_schlick = mix(fresnel->f0, one_spectrum(), f5);
|
||||
fresnel->b = F_schlick * (7.0f / (f5 * f)) * (one_spectrum() - f82_tint);
|
||||
}
|
||||
|
||||
bsdf->fresnel_type = MicrofacetFresnel::F82_TINT;
|
||||
bsdf->fresnel = fresnel;
|
||||
bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
|
||||
|
||||
if (preserve_energy) {
|
||||
Spectrum Fss = mix(fresnel->f0, one_spectrum(), 1.0f / 21.0f) - fresnel->b * (1.0f / 126.0f);
|
||||
microfacet_ggx_preserve_energy(kg, bsdf, sd, Fss);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device void bsdf_microfacet_setup_fresnel_constant(KernelGlobals kg,
|
||||
ccl_private MicrofacetBsdf *bsdf,
|
||||
ccl_private const ShaderData *sd,
|
||||
|
|
|
@ -59,7 +59,7 @@ ccl_device float bssrdf_dipole_compute_alpha_prime(float rd, float fourthirdA)
|
|||
|
||||
ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf, const ClosureType type)
|
||||
{
|
||||
if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) {
|
||||
if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
|
||||
/* Scale mean free path length so it gives similar looking result to older
|
||||
* Cubic, Gaussian and Burley models. */
|
||||
bssrdf->radius *= 0.25f * M_1_PI_F;
|
||||
|
@ -291,8 +291,8 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
|
|||
|
||||
int flag = 0;
|
||||
|
||||
if (type == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
|
||||
/* CLOSURE_BSSRDF_RANDOM_WALK_ID uses a fixed roughness. */
|
||||
if (type == CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID) {
|
||||
/* CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID uses a fixed roughness. */
|
||||
bssrdf->alpha = 1.0f;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ ccl_device_inline bool subsurface_entry_bounce(KernelGlobals kg,
|
|||
{
|
||||
float2 rand_bsdf = path_state_rng_2D(kg, rng_state, PRNG_SUBSURFACE_BSDF);
|
||||
|
||||
if (bssrdf->type == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
|
||||
/* CLOSURE_BSSRDF_RANDOM_WALK_ID has a 50% chance to sample a diffuse entry bounce.
|
||||
if (bssrdf->type == CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID) {
|
||||
/* CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID has a 50% chance to sample a diffuse entry bounce.
|
||||
* Also, for the refractive entry, it uses a fixed roughness of 1.0. */
|
||||
if (rand_bsdf.x < 0.5f) {
|
||||
rand_bsdf.x *= 2.0f;
|
||||
|
|
|
@ -474,6 +474,53 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
|
|||
|
||||
/* Special-purpose Microfacet closures */
|
||||
|
||||
ccl_device void osl_closure_microfacet_f82_tint_setup(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
uint32_t path_flag,
|
||||
float3 weight,
|
||||
ccl_private const MicrofacetF82TintClosure *closure,
|
||||
float3 *layer_albedo)
|
||||
{
|
||||
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
|
||||
if (!bsdf) {
|
||||
return;
|
||||
}
|
||||
|
||||
ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)closure_alloc_extra(
|
||||
sd, sizeof(FresnelF82Tint));
|
||||
if (!fresnel) {
|
||||
return;
|
||||
}
|
||||
|
||||
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
|
||||
bsdf->alpha_x = closure->alpha_x;
|
||||
bsdf->alpha_y = closure->alpha_y;
|
||||
bsdf->ior = 0.0f;
|
||||
bsdf->T = closure->T;
|
||||
|
||||
bool preserve_energy = false;
|
||||
|
||||
/* Beckmann */
|
||||
if (closure->distribution == make_string("beckmann", 14712237670914973463ull)) {
|
||||
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
|
||||
}
|
||||
/* GGX (either single- or multi-scattering) */
|
||||
else {
|
||||
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
||||
preserve_energy = (closure->distribution == make_string("multi_ggx", 16842698693386468366ull));
|
||||
}
|
||||
|
||||
fresnel->f0 = rgb_to_spectrum(closure->f0);
|
||||
bsdf_microfacet_setup_fresnel_f82_tint(
|
||||
kg, bsdf, sd, fresnel, rgb_to_spectrum(closure->f82), preserve_energy);
|
||||
}
|
||||
|
||||
ccl_device void osl_closure_microfacet_multi_ggx_glass_setup(
|
||||
KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
|
@ -760,12 +807,12 @@ ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg,
|
|||
if (closure->method == make_string("burley", 186330084368958868ull)) {
|
||||
type = CLOSURE_BSSRDF_BURLEY_ID;
|
||||
}
|
||||
else if (closure->method == make_string("random_walk_fixed_radius", 5695810351010063150ull)) {
|
||||
type = CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID;
|
||||
}
|
||||
else if (closure->method == make_string("random_walk", 11360609267673527222ull)) {
|
||||
else if (closure->method == make_string("random_walk", 5695810351010063150ull)) {
|
||||
type = CLOSURE_BSSRDF_RANDOM_WALK_ID;
|
||||
}
|
||||
else if (closure->method == make_string("random_walk_skin", 11360609267673527222ull)) {
|
||||
type = CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,16 @@ OSL_CLOSURE_STRUCT_BEGIN(Microfacet, microfacet)
|
|||
OSL_CLOSURE_STRUCT_MEMBER(Microfacet, INT, int, refract, NULL)
|
||||
OSL_CLOSURE_STRUCT_END(Microfacet, microfacet)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetF82Tint, microfacet_f82_tint)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, STRING, DeviceString, distribution, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, N, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, T, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, FLOAT, float, alpha_x, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, FLOAT, float, alpha_y, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, f0, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetF82Tint, VECTOR, packed_float3, f82, NULL)
|
||||
OSL_CLOSURE_STRUCT_END(MicrofacetF82Tint, microfacet)
|
||||
|
||||
OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXGlass, microfacet_multi_ggx_glass)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, VECTOR, packed_float3, N, NULL)
|
||||
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, FLOAT, float, alpha_x, NULL)
|
||||
|
|
|
@ -73,7 +73,7 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
|
|||
int layer_stack_level = -1;
|
||||
float3 layer_albedo = zero_float3();
|
||||
|
||||
while (closure) {
|
||||
while (true) {
|
||||
switch (closure->id) {
|
||||
case OSL_CLOSURE_MUL_ID: {
|
||||
ccl_private const OSLClosureMul *mul = static_cast<ccl_private const OSLClosureMul *>(
|
||||
|
@ -134,7 +134,12 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
|
|||
break;
|
||||
}
|
||||
|
||||
if (stack_size > 0) {
|
||||
/* Pop the next closure from the stack (or return if we're done). */
|
||||
do {
|
||||
if (stack_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
weight = weight_stack[--stack_size];
|
||||
closure = closure_stack[stack_size];
|
||||
if (stack_size == layer_stack_level) {
|
||||
|
@ -142,22 +147,13 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
|
|||
* account for the layering. */
|
||||
weight *= saturatef(1.0f - reduce_max(safe_divide_color(layer_albedo, weight)));
|
||||
layer_stack_level = -1;
|
||||
/* If it's fully occluded, skip the base layer we just popped from the stack and grab
|
||||
* the next entry instead. */
|
||||
if (is_zero(weight)) {
|
||||
/* If it's fully occluded, skip the base layer we just popped from the stack and grab
|
||||
* the next entry instead. */
|
||||
if (stack_size > 0) {
|
||||
weight = weight_stack[--stack_size];
|
||||
closure = closure_stack[stack_size];
|
||||
}
|
||||
else {
|
||||
closure = nullptr;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
closure = nullptr;
|
||||
}
|
||||
} while (closure == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,3 +42,9 @@ float F0_from_ior(float eta)
|
|||
float f0 = (eta - 1.0) / (eta + 1.0);
|
||||
return f0 * f0;
|
||||
}
|
||||
|
||||
float ior_from_F0(float f0)
|
||||
{
|
||||
float sqrt_f0 = sqrt(clamp(f0, 0.0, 0.99));
|
||||
return (1.0 + sqrt_f0) / (1.0 - sqrt_f0);
|
||||
}
|
||||
|
|
|
@ -8,27 +8,27 @@
|
|||
shader node_principled_bsdf(string distribution = "multi_ggx",
|
||||
string subsurface_method = "random_walk",
|
||||
color BaseColor = color(0.8, 0.8, 0.8),
|
||||
float Subsurface = 0.0,
|
||||
float SubsurfaceWeight = 0.0,
|
||||
float SubsurfaceScale = 0.1,
|
||||
vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
|
||||
float SubsurfaceIOR = 1.4,
|
||||
float SubsurfaceAnisotropy = 0.0,
|
||||
float Metallic = 0.0,
|
||||
float Specular = 0.5,
|
||||
float SpecularTint = 0.0,
|
||||
float SpecularIORLevel = 0.5,
|
||||
color SpecularTint = color(1.0),
|
||||
float Roughness = 0.5,
|
||||
float Anisotropic = 0.0,
|
||||
float AnisotropicRotation = 0.0,
|
||||
float Sheen = 0.0,
|
||||
float SheenWeight = 0.0,
|
||||
float SheenRoughness = 0.5,
|
||||
color SheenTint = 0.5,
|
||||
float Coat = 0.0,
|
||||
float CoatWeight = 0.0,
|
||||
float CoatRoughness = 0.03,
|
||||
float CoatIOR = 1.5,
|
||||
color CoatTint = color(1.0, 1.0, 1.0),
|
||||
float IOR = 1.45,
|
||||
float Transmission = 0.0,
|
||||
color Emission = 1.0,
|
||||
float TransmissionWeight = 0.0,
|
||||
color EmissionColor = 1.0,
|
||||
float EmissionStrength = 0.0,
|
||||
float Alpha = 1.0,
|
||||
normal Normal = N,
|
||||
|
@ -36,7 +36,11 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||
normal Tangent = normalize(dPdu),
|
||||
output closure color BSDF = 0)
|
||||
{
|
||||
float r2 = Roughness * Roughness;
|
||||
color specular_tint = max(SpecularTint, color(0.0));
|
||||
|
||||
float r2 = clamp(Roughness, 0.0, 1.0);
|
||||
r2 = r2 * r2;
|
||||
|
||||
float alpha_x = r2, alpha_y = r2;
|
||||
|
||||
/* Handle anisotropy. */
|
||||
|
@ -49,11 +53,22 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||
T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
|
||||
}
|
||||
|
||||
if (Metallic < 1.0 && Transmission < 1.0) {
|
||||
if (Metallic < 1.0 && TransmissionWeight < 1.0) {
|
||||
float eta = IOR;
|
||||
float f0 = F0_from_ior(eta);
|
||||
if (SpecularIORLevel != 0.5) {
|
||||
f0 *= 2.0 * max(SpecularIORLevel, 0.0);
|
||||
eta = ior_from_F0(f0);
|
||||
if (IOR < 1.0) {
|
||||
eta = 1.0 / eta;
|
||||
}
|
||||
}
|
||||
|
||||
BSDF = BaseColor * diffuse(Normal);
|
||||
if (Subsurface > 1e-5) {
|
||||
if (SubsurfaceWeight > 1e-5) {
|
||||
float subsurface_weight = min(SubsurfaceWeight, 1.0);
|
||||
vector radius = SubsurfaceScale * SubsurfaceRadius;
|
||||
float subsurface_ior = (subsurface_method == "random_walk") ? SubsurfaceIOR : IOR;
|
||||
float subsurface_ior = (subsurface_method == "random_walk_skin") ? SubsurfaceIOR : eta;
|
||||
closure color SubsurfBSDF = bssrdf(subsurface_method,
|
||||
Normal,
|
||||
SubsurfaceScale * SubsurfaceRadius,
|
||||
|
@ -64,66 +79,64 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||
subsurface_ior,
|
||||
"anisotropy",
|
||||
SubsurfaceAnisotropy);
|
||||
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, Subsurface);
|
||||
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, subsurface_weight);
|
||||
}
|
||||
|
||||
color f0 = color(F0_from_ior(IOR));
|
||||
color f90 = color(1.0);
|
||||
|
||||
/* Apply specular tint */
|
||||
float m_cdlum = luminance(BaseColor);
|
||||
color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum : color(1.0);
|
||||
color specTint = mix(color(1.0), m_ctint, SpecularTint);
|
||||
f0 *= (specTint * 2.0 * Specular);
|
||||
color F0 = f0 * specular_tint;
|
||||
color F90 = color(1.0);
|
||||
|
||||
BSDF = layer(
|
||||
generalized_schlick_bsdf(
|
||||
Normal, T, color(1.0), color(0.0), alpha_x, alpha_y, f0, f90, -IOR, distribution),
|
||||
Normal, T, color(1.0), color(0.0), alpha_x, alpha_y, F0, F90, -eta, distribution),
|
||||
BSDF);
|
||||
}
|
||||
|
||||
closure color TransmissionBSDF = 0;
|
||||
if (Metallic < 1.0 && Transmission > 0.0) {
|
||||
color reflectTint = mix(color(1.0), BaseColor, SpecularTint);
|
||||
if (Metallic < 1.0 && TransmissionWeight > 0.0) {
|
||||
float eta = max(IOR, 1e-5);
|
||||
eta = backfacing() ? 1.0 / eta : eta;
|
||||
|
||||
TransmissionBSDF = dielectric_bsdf(
|
||||
Normal, vector(0.0), reflectTint, sqrt(BaseColor), r2, r2, eta, distribution);
|
||||
BSDF = mix(BSDF, TransmissionBSDF, clamp(Transmission, 0.0, 1.0));
|
||||
color F0 = F0_from_ior(eta) * specular_tint;
|
||||
color F90 = color(1.0);
|
||||
|
||||
TransmissionBSDF = generalized_schlick_bsdf(
|
||||
Normal, vector(0.0), color(1.0), sqrt(BaseColor), r2, r2, F0, F90, -eta, distribution),
|
||||
BSDF = mix(BSDF, TransmissionBSDF, clamp(TransmissionWeight, 0.0, 1.0));
|
||||
}
|
||||
|
||||
closure color MetallicBSDF = 0;
|
||||
if (Metallic > 0.0) {
|
||||
color f0 = BaseColor;
|
||||
color f90 = color(1.0);
|
||||
MetallicBSDF = generalized_schlick_bsdf(
|
||||
Normal, T, color(1.0), color(0.0), alpha_x, alpha_y, f0, f90, 5.0, distribution);
|
||||
color F0 = BaseColor;
|
||||
color F82 = specular_tint;
|
||||
MetallicBSDF = microfacet_f82_tint(distribution, Normal, T, alpha_x, alpha_y, F0, F82);
|
||||
BSDF = mix(BSDF, MetallicBSDF, clamp(Metallic, 0.0, 1.0));
|
||||
}
|
||||
|
||||
if (EmissionStrength > 0.0 && Emission != color(0.0)) {
|
||||
BSDF += EmissionStrength * Emission * emission();
|
||||
if (EmissionStrength > 0.0 && EmissionColor != color(0.0)) {
|
||||
BSDF += EmissionStrength * EmissionColor * emission();
|
||||
}
|
||||
|
||||
if (Coat > 1e-5) {
|
||||
if (CoatWeight > 1e-5) {
|
||||
float coat_ior = max(CoatIOR, 1.0);
|
||||
if (CoatTint != color(1.0)) {
|
||||
float coat_neta = 1.0 / coat_ior;
|
||||
float cosNI = dot(I, CoatNormal);
|
||||
float cosNT = sqrt(1.0 - coat_neta * coat_neta * (1 - cosNI * cosNI));
|
||||
BSDF *= pow(CoatTint, Coat / cosNT);
|
||||
BSDF *= pow(CoatTint, CoatWeight / cosNT);
|
||||
}
|
||||
float coat_r2 = CoatRoughness * CoatRoughness;
|
||||
float coat_r2 = clamp(CoatRoughness, 0.0, 1.0);
|
||||
coat_r2 = coat_r2 * coat_r2;
|
||||
|
||||
closure color CoatBSDF = dielectric_bsdf(
|
||||
CoatNormal, vector(0.0), color(1.0), color(0.0), coat_r2, coat_r2, coat_ior, "ggx");
|
||||
BSDF = layer(Coat * CoatBSDF, BSDF);
|
||||
BSDF = layer(clamp(CoatWeight, 0.0, 1.0) * CoatBSDF, BSDF);
|
||||
}
|
||||
|
||||
if (Sheen > 1e-5) {
|
||||
closure color SheenBSDF = sheen(Normal, SheenRoughness);
|
||||
BSDF = layer(SheenTint * Sheen * SheenBSDF, BSDF);
|
||||
if (SheenWeight > 1e-5) {
|
||||
closure color SheenBSDF = sheen(Normal, clamp(SheenRoughness, 0.0, 1.0));
|
||||
BSDF = layer(clamp(SheenWeight, 0.0, 1.0) * SheenTint * SheenBSDF, BSDF);
|
||||
}
|
||||
|
||||
BSDF = mix(transparent(), BSDF, Alpha);
|
||||
BSDF = mix(transparent(), BSDF, clamp(Alpha, 0.0, 1.0));
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@ closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
|
|||
closure color sheen(normal N, float roughness) BUILTIN;
|
||||
closure color ambient_occlusion() BUILTIN;
|
||||
|
||||
closure color microfacet_f82_tint(
|
||||
string distribution, vector N, vector T, float ax, float ay, color f0, color f82) BUILTIN;
|
||||
|
||||
/* Needed to pass along the color for multi-scattering saturation adjustment,
|
||||
* otherwise could be replaced by microfacet() */
|
||||
closure color microfacet_multi_ggx_glass(normal N, float ag, float eta, color C) BUILTIN;
|
||||
|
|
|
@ -74,46 +74,50 @@ 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, sheen_roughness_offset, coat_offset,
|
||||
coat_roughness_offset, coat_ior_offset, eta_offset, transmission_offset,
|
||||
uint specular_ior_level_offset, roughness_offset, specular_tint_offset, anisotropic_offset,
|
||||
sheen_weight_offset, sheen_tint_offset, sheen_roughness_offset, coat_weight_offset,
|
||||
coat_roughness_offset, coat_ior_offset, eta_offset, transmission_weight_offset,
|
||||
anisotropic_rotation_offset, coat_tint_offset, coat_normal_offset, dummy, alpha_offset,
|
||||
emission_strength_offset, emission_offset;
|
||||
emission_strength_offset, emission_offset, unused;
|
||||
uint4 data_node2 = read_node(kg, &offset);
|
||||
|
||||
float3 T = stack_load_float3(stack, data_node.y);
|
||||
svm_unpack_node_uchar4(data_node.z,
|
||||
&specular_offset,
|
||||
&specular_ior_level_offset,
|
||||
&roughness_offset,
|
||||
&specular_tint_offset,
|
||||
&anisotropic_offset);
|
||||
svm_unpack_node_uchar4(
|
||||
data_node.w, &sheen_offset, &sheen_tint_offset, &sheen_roughness_offset, &dummy);
|
||||
data_node.w, &sheen_weight_offset, &sheen_tint_offset, &sheen_roughness_offset, &unused);
|
||||
svm_unpack_node_uchar4(data_node2.x,
|
||||
&eta_offset,
|
||||
&transmission_offset,
|
||||
&transmission_weight_offset,
|
||||
&anisotropic_rotation_offset,
|
||||
&coat_normal_offset);
|
||||
svm_unpack_node_uchar4(
|
||||
data_node2.w, &coat_offset, &coat_roughness_offset, &coat_ior_offset, &coat_tint_offset);
|
||||
svm_unpack_node_uchar4(data_node2.w,
|
||||
&coat_weight_offset,
|
||||
&coat_roughness_offset,
|
||||
&coat_ior_offset,
|
||||
&coat_tint_offset);
|
||||
|
||||
// get Disney principled parameters
|
||||
float metallic = saturatef(param1);
|
||||
float subsurface = param2;
|
||||
float specular = stack_load_float(stack, specular_offset);
|
||||
float roughness = stack_load_float(stack, roughness_offset);
|
||||
float specular_tint = stack_load_float(stack, specular_tint_offset);
|
||||
float anisotropic = stack_load_float(stack, anisotropic_offset);
|
||||
float sheen = stack_load_float(stack, sheen_offset);
|
||||
float subsurface_weight = saturatef(param2);
|
||||
brecht marked this conversation as resolved
Outdated
|
||||
float specular_ior_level = fmaxf(stack_load_float(stack, specular_ior_level_offset), 0.0f);
|
||||
float roughness = saturatef(stack_load_float(stack, roughness_offset));
|
||||
Spectrum specular_tint = rgb_to_spectrum(
|
||||
max(stack_load_float3(stack, specular_tint_offset), zero_float3()));
|
||||
brecht marked this conversation as resolved
Outdated
Lukas Stockner
commented
Same as in EEVEE, I don't think we want to hard-clamp >1.0 anymore. Same as in EEVEE, I don't think we want to hard-clamp >1.0 anymore.
|
||||
float anisotropic = saturatef(stack_load_float(stack, anisotropic_offset));
|
||||
float sheen_weight = saturatef(stack_load_float(stack, sheen_weight_offset));
|
||||
float3 sheen_tint = stack_load_float3(stack, sheen_tint_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 sheen_roughness = saturatef(stack_load_float(stack, sheen_roughness_offset));
|
||||
float coat_weight = saturatef(stack_load_float(stack, coat_weight_offset));
|
||||
float coat_roughness = saturatef(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 transmission_weight = saturatef(stack_load_float(stack, transmission_weight_offset));
|
||||
float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
|
||||
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
|
||||
float ior = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
|
||||
|
||||
ClosureType distribution = (ClosureType)data_node2.y;
|
||||
ClosureType subsurface_method = (ClosureType)data_node2.z;
|
||||
|
@ -139,17 +143,18 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
&dummy);
|
||||
float alpha = stack_valid(alpha_offset) ? stack_load_float(stack, alpha_offset) :
|
||||
__uint_as_float(data_alpha_emission.y);
|
||||
float3 emission = stack_load_float3(stack, emission_offset);
|
||||
/* Emission strength */
|
||||
emission *= stack_valid(emission_strength_offset) ?
|
||||
stack_load_float(stack, emission_strength_offset) :
|
||||
__uint_as_float(data_alpha_emission.z);
|
||||
alpha = saturatef(alpha);
|
||||
|
||||
float emission_strength = stack_valid(emission_strength_offset) ?
|
||||
stack_load_float(stack, emission_strength_offset) :
|
||||
__uint_as_float(data_alpha_emission.z);
|
||||
float3 emission = stack_load_float3(stack, emission_offset) * fmaxf(emission_strength, 0.0f);
|
||||
|
||||
Spectrum weight = closure_weight * mix_weight;
|
||||
|
||||
float alpha_x = sqr(roughness), alpha_y = sqr(roughness);
|
||||
if (anisotropic > 0.0f) {
|
||||
float aspect = sqrtf(1.0f - saturatef(anisotropic) * 0.9f);
|
||||
float aspect = sqrtf(1.0f - anisotropic * 0.9f);
|
||||
alpha_x /= aspect;
|
||||
alpha_y *= aspect;
|
||||
if (anisotropic_rotation != 0.0f)
|
||||
|
@ -174,9 +179,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* First layer: Sheen */
|
||||
if (sheen > CLOSURE_WEIGHT_CUTOFF) {
|
||||
if (sheen_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private SheenBsdf *bsdf = (ccl_private SheenBsdf *)bsdf_alloc(
|
||||
sd, sizeof(SheenBsdf), sheen * rgb_to_spectrum(sheen_tint) * weight);
|
||||
sd, sizeof(SheenBsdf), sheen_weight * rgb_to_spectrum(sheen_tint) * weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
|
@ -192,14 +197,14 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* Second layer: Coat */
|
||||
if (coat > CLOSURE_WEIGHT_CUTOFF) {
|
||||
if (coat_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 coat_normal = stack_valid(coat_normal_offset) ?
|
||||
stack_load_float3(stack, coat_normal_offset) :
|
||||
sd->N;
|
||||
coat_normal = maybe_ensure_valid_specular_reflection(sd, coat_normal);
|
||||
if (reflective_caustics) {
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), coat * weight);
|
||||
sd, sizeof(MicrofacetBsdf), coat_weight * weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = coat_normal;
|
||||
|
@ -242,7 +247,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
* 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);
|
||||
weight *= power(rgb_to_spectrum(coat_tint), coat_weight * optical_depth);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,10 +260,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
if (reflective_caustics && metallic > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), metallic * weight);
|
||||
ccl_private FresnelGeneralizedSchlick *fresnel =
|
||||
(bsdf != NULL) ? (ccl_private FresnelGeneralizedSchlick *)closure_alloc_extra(
|
||||
sd, sizeof(FresnelGeneralizedSchlick)) :
|
||||
NULL;
|
||||
ccl_private FresnelF82Tint *fresnel =
|
||||
(bsdf != NULL) ?
|
||||
(ccl_private FresnelF82Tint *)closure_alloc_extra(sd, sizeof(FresnelF82Tint)) :
|
||||
NULL;
|
||||
|
||||
if (bsdf && fresnel) {
|
||||
bsdf->N = valid_reflection_N;
|
||||
|
@ -268,15 +273,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
bsdf->alpha_y = alpha_y;
|
||||
|
||||
fresnel->f0 = rgb_to_spectrum(base_color);
|
||||
fresnel->f90 = one_spectrum();
|
||||
fresnel->exponent = 5.0f;
|
||||
fresnel->reflection_tint = one_spectrum();
|
||||
fresnel->transmission_tint = zero_spectrum();
|
||||
const Spectrum f82 = specular_tint;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
||||
const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
|
||||
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
|
||||
bsdf_microfacet_setup_fresnel_f82_tint(kg, bsdf, sd, fresnel, f82, is_multiggx);
|
||||
|
||||
/* Attenuate other components */
|
||||
weight *= (1.0f - metallic);
|
||||
|
@ -284,12 +286,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* Transmission component */
|
||||
if (glass_caustics && transmission > CLOSURE_WEIGHT_CUTOFF) {
|
||||
if (glass_caustics && transmission_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), transmission * weight);
|
||||
ccl_private FresnelDielectricTint *fresnel =
|
||||
(bsdf != NULL) ? (ccl_private FresnelDielectricTint *)closure_alloc_extra(
|
||||
sd, sizeof(FresnelDielectricTint)) :
|
||||
sd, sizeof(MicrofacetBsdf), transmission_weight * weight);
|
||||
ccl_private FresnelGeneralizedSchlick *fresnel =
|
||||
(bsdf != NULL) ? (ccl_private FresnelGeneralizedSchlick *)closure_alloc_extra(
|
||||
sd, sizeof(FresnelGeneralizedSchlick)) :
|
||||
NULL;
|
||||
|
||||
if (bsdf && fresnel) {
|
||||
|
@ -297,19 +299,21 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
bsdf->T = zero_float3();
|
||||
|
||||
bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
|
||||
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
||||
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / ior : ior;
|
||||
|
||||
fresnel->reflection_tint = mix(
|
||||
one_spectrum(), rgb_to_spectrum(base_color), specular_tint);
|
||||
fresnel->f0 = make_float3(F0_from_ior(ior));
|
||||
fresnel->f90 = one_spectrum();
|
||||
fresnel->exponent = -ior;
|
||||
fresnel->reflection_tint = one_spectrum();
|
||||
fresnel->transmission_tint = sqrt(rgb_to_spectrum(base_color));
|
||||
|
||||
/* 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);
|
||||
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
|
||||
|
||||
/* Attenuate other components */
|
||||
weight *= (1.0f - transmission);
|
||||
weight *= (1.0f - transmission_weight);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,17 +327,24 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
NULL;
|
||||
|
||||
if (bsdf && fresnel) {
|
||||
/* Apply IOR adjustment */
|
||||
float eta = ior;
|
||||
float f0 = F0_from_ior(eta);
|
||||
if (specular_ior_level != 0.5f) {
|
||||
f0 *= 2.0f * specular_ior_level;
|
||||
eta = ior_from_F0(f0);
|
||||
if (ior < 1.0f) {
|
||||
eta = 1.0f / eta;
|
||||
}
|
||||
}
|
||||
|
||||
bsdf->N = valid_reflection_N;
|
||||
bsdf->ior = eta;
|
||||
bsdf->T = T;
|
||||
bsdf->alpha_x = alpha_x;
|
||||
bsdf->alpha_y = alpha_y;
|
||||
|
||||
float m_cdlum = linear_rgb_to_gray(kg, base_color);
|
||||
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : one_float3();
|
||||
float3 specTint = mix(one_spectrum(), rgb_to_spectrum(m_ctint), specular_tint);
|
||||
|
||||
fresnel->f0 = F0_from_ior(eta) * 2.0f * specular * specTint;
|
||||
fresnel->f0 = f0 * specular_tint;
|
||||
fresnel->f90 = one_spectrum();
|
||||
fresnel->exponent = -eta;
|
||||
fresnel->reflection_tint = one_spectrum();
|
||||
|
@ -352,8 +363,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
|
||||
/* Diffuse/Subsurface component */
|
||||
#ifdef __SUBSURFACE__
|
||||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd,
|
||||
rgb_to_spectrum(base_color) * subsurface * weight);
|
||||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(
|
||||
sd, rgb_to_spectrum(base_color) * subsurface_weight * weight);
|
||||
if (bssrdf) {
|
||||
float3 subsurface_radius = stack_load_float3(stack, data_subsurf.y);
|
||||
float subsurface_scale = stack_load_float(stack, data_subsurf.z);
|
||||
|
@ -362,9 +373,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
bssrdf->albedo = rgb_to_spectrum(base_color);
|
||||
bssrdf->N = N;
|
||||
bssrdf->alpha = sqr(roughness);
|
||||
bssrdf->ior = eta;
|
||||
bssrdf->ior = ior;
|
||||
bssrdf->anisotropy = stack_load_float(stack, data_subsurf.w);
|
||||
if (subsurface_method == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
|
||||
if (subsurface_method == CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID) {
|
||||
bssrdf->ior = stack_load_float(stack, data_subsurf.x);
|
||||
}
|
||||
|
||||
|
@ -372,11 +383,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method);
|
||||
}
|
||||
#else
|
||||
subsurface = 0.0f;
|
||||
subsurface_weight = 0.0f;
|
||||
#endif
|
||||
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), rgb_to_spectrum(base_color) * (1.0f - subsurface) * weight);
|
||||
sd,
|
||||
sizeof(DiffuseBsdf),
|
||||
rgb_to_spectrum(base_color) * (1.0f - subsurface_weight) * weight);
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
|
||||
|
@ -804,7 +817,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
#ifdef __SUBSURFACE__
|
||||
case CLOSURE_BSSRDF_BURLEY_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID: {
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID: {
|
||||
Spectrum weight = closure_weight * mix_weight;
|
||||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
|
||||
|
||||
|
|
|
@ -453,7 +453,7 @@ typedef enum ClosureType {
|
|||
/* BSSRDF */
|
||||
CLOSURE_BSSRDF_BURLEY_ID,
|
||||
CLOSURE_BSSRDF_RANDOM_WALK_ID,
|
||||
CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID,
|
||||
CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID,
|
||||
|
||||
/* Other */
|
||||
CLOSURE_HOLDOUT_ID,
|
||||
|
@ -490,9 +490,9 @@ typedef enum ClosureType {
|
|||
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && \
|
||||
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID))
|
||||
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) \
|
||||
(type != CLOSURE_NONE_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
|
||||
(type != CLOSURE_NONE_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID)
|
||||
#define CLOSURE_IS_BSSRDF(type) \
|
||||
(type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
|
||||
(type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID)
|
||||
#define CLOSURE_IS_VOLUME(type) \
|
||||
(type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
|
||||
#define CLOSURE_IS_VOLUME_SCATTER(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
|
||||
|
|
|
@ -138,7 +138,7 @@ static float3 output_estimate_emission(ShaderOutput *output, bool &is_constant)
|
|||
{
|
||||
const bool is_principled = (node->type == PrincipledBsdfNode::get_node_type());
|
||||
/* Emission and Background node. */
|
||||
ShaderInput *color_in = node->input(is_principled ? "Emission" : "Color");
|
||||
ShaderInput *color_in = node->input(is_principled ? "Emission Color" : "Color");
|
||||
ShaderInput *strength_in = node->input(is_principled ? "Emission Strength" : "Strength");
|
||||
|
||||
if (is_principled) {
|
||||
|
|
|
@ -2690,9 +2690,8 @@ NODE_DEFINE(PrincipledBsdfNode)
|
|||
|
||||
static NodeEnum subsurface_method_enum;
|
||||
subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
|
||||
subsurface_method_enum.insert("random_walk_fixed_radius",
|
||||
CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
|
||||
subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
|
||||
subsurface_method_enum.insert("random_walk_skin", CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
|
||||
SOCKET_ENUM(subsurface_method,
|
||||
"Subsurface Method",
|
||||
subsurface_method_enum,
|
||||
|
@ -2700,31 +2699,38 @@ NODE_DEFINE(PrincipledBsdfNode)
|
|||
|
||||
SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f))
|
||||
SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
|
||||
SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
|
||||
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
|
||||
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
|
||||
SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
|
||||
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
|
||||
|
||||
SOCKET_IN_FLOAT(subsurface_weight, "Subsurface Weight", 0.0f);
|
||||
SOCKET_IN_FLOAT(subsurface_scale, "Subsurface Scale", 0.1f);
|
||||
SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
|
||||
SOCKET_IN_FLOAT(subsurface_ior, "Subsurface IOR", 1.4f);
|
||||
SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
|
||||
SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
|
||||
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
|
||||
SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
|
||||
|
||||
SOCKET_IN_FLOAT(specular_ior_level, "Specular IOR Level", 0.0f);
|
||||
SOCKET_IN_COLOR(specular_tint, "Specular Tint", one_float3());
|
||||
SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
|
||||
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
|
||||
SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
|
||||
SOCKET_IN_NORMAL(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
|
||||
|
||||
SOCKET_IN_FLOAT(transmission_weight, "Transmission Weight", 0.0f);
|
||||
|
||||
SOCKET_IN_FLOAT(sheen_weight, "Sheen Weight", 0.0f);
|
||||
SOCKET_IN_FLOAT(sheen_roughness, "Sheen Roughness", 0.5f);
|
||||
SOCKET_IN_COLOR(sheen_tint, "Sheen Tint", one_float3());
|
||||
SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
|
||||
|
||||
SOCKET_IN_FLOAT(coat_weight, "Coat Weight", 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);
|
||||
SOCKET_IN_COLOR(emission, "Emission", one_float3());
|
||||
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
|
||||
SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
|
||||
SOCKET_IN_NORMAL(normal, "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_COLOR(emission_color, "Emission Color", one_float3());
|
||||
SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
|
||||
|
||||
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
|
||||
|
||||
SOCKET_OUT_CLOSURE(BSDF, "BSDF");
|
||||
|
@ -2742,7 +2748,7 @@ void PrincipledBsdfNode::simplify_settings(Scene * /* scene */)
|
|||
{
|
||||
if (!has_surface_emission()) {
|
||||
/* Emission will be zero, so optimize away any connected emission input. */
|
||||
ShaderInput *emission_in = input("Emission");
|
||||
ShaderInput *emission_in = input("Emission Color");
|
||||
ShaderInput *strength_in = input("Emission Strength");
|
||||
if (emission_in->link) {
|
||||
emission_in->disconnect();
|
||||
|
@ -2761,16 +2767,18 @@ bool PrincipledBsdfNode::has_surface_transparent()
|
|||
|
||||
bool PrincipledBsdfNode::has_surface_emission()
|
||||
{
|
||||
ShaderInput *emission_in = input("Emission");
|
||||
ShaderInput *emission_color_in = input("Emission Color");
|
||||
ShaderInput *emission_strength_in = input("Emission Strength");
|
||||
return (emission_in->link != NULL || reduce_max(emission) > CLOSURE_WEIGHT_CUTOFF) &&
|
||||
return (emission_color_in->link != NULL || reduce_max(emission_color) > CLOSURE_WEIGHT_CUTOFF) &&
|
||||
(emission_strength_in->link != NULL || emission_strength > CLOSURE_WEIGHT_CUTOFF);
|
||||
}
|
||||
|
||||
bool PrincipledBsdfNode::has_surface_bssrdf()
|
||||
{
|
||||
ShaderInput *subsurface_in = input("Subsurface");
|
||||
return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
|
||||
ShaderInput *subsurface_weight_in = input("Subsurface Weight");
|
||||
ShaderInput *subsurface_scale_in = input("Subsurface Scale");
|
||||
return (subsurface_weight_in->link != NULL || subsurface_weight > CLOSURE_WEIGHT_CUTOFF) &&
|
||||
(subsurface_scale_in->link != NULL || subsurface_scale != 0.0f);
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
|
@ -2791,7 +2799,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
|||
ShaderInput *base_color_in = input("Base Color");
|
||||
|
||||
ShaderInput *p_metallic = input("Metallic");
|
||||
ShaderInput *p_subsurface = input("Subsurface");
|
||||
ShaderInput *p_subsurface_weight = input("Subsurface Weight");
|
||||
|
||||
ShaderInput *emission_strength_in = input("Emission Strength");
|
||||
ShaderInput *alpha_in = input("Alpha");
|
||||
|
@ -2803,19 +2811,19 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
|||
int normal_offset = compiler.stack_assign_if_linked(input("Normal"));
|
||||
int coat_normal_offset = compiler.stack_assign_if_linked(input("Coat Normal"));
|
||||
int tangent_offset = compiler.stack_assign_if_linked(input("Tangent"));
|
||||
int specular_offset = compiler.stack_assign(input("Specular"));
|
||||
int specular_ior_level_offset = compiler.stack_assign(input("Specular IOR Level"));
|
||||
int roughness_offset = compiler.stack_assign(input("Roughness"));
|
||||
int specular_tint_offset = compiler.stack_assign(input("Specular Tint"));
|
||||
int anisotropic_offset = compiler.stack_assign(input("Anisotropic"));
|
||||
int sheen_offset = compiler.stack_assign(input("Sheen"));
|
||||
int sheen_weight_offset = compiler.stack_assign(input("Sheen Weight"));
|
||||
int sheen_roughness_offset = compiler.stack_assign(input("Sheen Roughness"));
|
||||
int sheen_tint_offset = compiler.stack_assign(input("Sheen Tint"));
|
||||
int coat_offset = compiler.stack_assign(input("Coat"));
|
||||
int coat_weight_offset = compiler.stack_assign(input("Coat Weight"));
|
||||
int coat_roughness_offset = compiler.stack_assign(input("Coat Roughness"));
|
||||
int coat_ior_offset = compiler.stack_assign(input("Coat IOR"));
|
||||
int coat_tint_offset = compiler.stack_assign(input("Coat Tint"));
|
||||
int ior_offset = compiler.stack_assign(input("IOR"));
|
||||
int transmission_offset = compiler.stack_assign(input("Transmission"));
|
||||
int transmission_weight_offset = compiler.stack_assign(input("Transmission Weight"));
|
||||
int anisotropic_rotation_offset = compiler.stack_assign(input("Anisotropic Rotation"));
|
||||
int subsurface_radius_offset = compiler.stack_assign(input("Subsurface Radius"));
|
||||
int subsurface_scale_offset = compiler.stack_assign(input("Subsurface Scale"));
|
||||
|
@ -2823,31 +2831,31 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
|||
int subsurface_anisotropy_offset = compiler.stack_assign(input("Subsurface Anisotropy"));
|
||||
int alpha_offset = compiler.stack_assign_if_linked(alpha_in);
|
||||
int emission_strength_offset = compiler.stack_assign_if_linked(emission_strength_in);
|
||||
int emission_offset = compiler.stack_assign(input("Emission"));
|
||||
int emission_color_offset = compiler.stack_assign(input("Emission Color"));
|
||||
|
||||
compiler.add_node(NODE_CLOSURE_BSDF,
|
||||
compiler.encode_uchar4(closure,
|
||||
compiler.stack_assign(p_metallic),
|
||||
compiler.stack_assign(p_subsurface),
|
||||
compiler.closure_mix_weight_offset()),
|
||||
__float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
|
||||
__float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
|
||||
compiler.add_node(
|
||||
NODE_CLOSURE_BSDF,
|
||||
compiler.encode_uchar4(closure,
|
||||
compiler.stack_assign(p_metallic),
|
||||
compiler.stack_assign(p_subsurface_weight),
|
||||
compiler.closure_mix_weight_offset()),
|
||||
__float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
|
||||
__float_as_int((p_subsurface_weight) ? get_float(p_subsurface_weight->socket_type) : 0.0f));
|
||||
|
||||
compiler.add_node(
|
||||
normal_offset,
|
||||
tangent_offset,
|
||||
compiler.encode_uchar4(
|
||||
specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
|
||||
compiler.encode_uchar4(
|
||||
sheen_offset, sheen_tint_offset, sheen_roughness_offset, SVM_STACK_INVALID));
|
||||
specular_ior_level_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
|
||||
compiler.encode_uchar4(sheen_weight_offset, sheen_tint_offset, sheen_roughness_offset));
|
||||
|
||||
compiler.add_node(
|
||||
compiler.encode_uchar4(
|
||||
ior_offset, transmission_offset, anisotropic_rotation_offset, coat_normal_offset),
|
||||
ior_offset, transmission_weight_offset, anisotropic_rotation_offset, coat_normal_offset),
|
||||
distribution,
|
||||
subsurface_method,
|
||||
compiler.encode_uchar4(
|
||||
coat_offset, coat_roughness_offset, coat_ior_offset, coat_tint_offset));
|
||||
coat_weight_offset, coat_roughness_offset, coat_ior_offset, coat_tint_offset));
|
||||
|
||||
float3 bc_default = get_float3(base_color_in->socket_type);
|
||||
|
||||
|
@ -2864,7 +2872,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
|||
|
||||
compiler.add_node(
|
||||
compiler.encode_uchar4(
|
||||
alpha_offset, emission_strength_offset, emission_offset, SVM_STACK_INVALID),
|
||||
alpha_offset, emission_strength_offset, emission_color_offset, SVM_STACK_INVALID),
|
||||
__float_as_int(get_float(alpha_in->socket_type)),
|
||||
__float_as_int(get_float(emission_strength_in->socket_type)),
|
||||
SVM_STACK_INVALID);
|
||||
|
@ -2953,8 +2961,8 @@ NODE_DEFINE(SubsurfaceScatteringNode)
|
|||
|
||||
static NodeEnum method_enum;
|
||||
method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
|
||||
method_enum.insert("random_walk_fixed_radius", CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
|
||||
method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
|
||||
method_enum.insert("random_walk_skin", CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
|
||||
SOCKET_ENUM(method, "Method", method_enum, CLOSURE_BSSRDF_RANDOM_WALK_ID);
|
||||
|
||||
SOCKET_IN_FLOAT(scale, "Scale", 0.01f);
|
||||
|
|
|
@ -519,35 +519,35 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
|||
void simplify_settings(Scene *scene);
|
||||
|
||||
NODE_SOCKET_API(float3, base_color)
|
||||
NODE_SOCKET_API(float, metallic)
|
||||
NODE_SOCKET_API(float, roughness)
|
||||
NODE_SOCKET_API(float, ior)
|
||||
NODE_SOCKET_API(float3, normal)
|
||||
NODE_SOCKET_API(float, alpha)
|
||||
NODE_SOCKET_API(ClosureType, subsurface_method)
|
||||
NODE_SOCKET_API(float, subsurface_weight)
|
||||
NODE_SOCKET_API(float3, subsurface_radius)
|
||||
NODE_SOCKET_API(float, subsurface_scale)
|
||||
NODE_SOCKET_API(float, subsurface_ior)
|
||||
NODE_SOCKET_API(float, subsurface_anisotropy)
|
||||
NODE_SOCKET_API(float, metallic)
|
||||
NODE_SOCKET_API(float, subsurface)
|
||||
NODE_SOCKET_API(float, specular)
|
||||
NODE_SOCKET_API(float, roughness)
|
||||
NODE_SOCKET_API(float, specular_tint)
|
||||
NODE_SOCKET_API(ClosureType, distribution)
|
||||
NODE_SOCKET_API(float, specular_ior_level)
|
||||
NODE_SOCKET_API(float3, specular_tint)
|
||||
NODE_SOCKET_API(float, anisotropic)
|
||||
NODE_SOCKET_API(float, sheen)
|
||||
NODE_SOCKET_API(float, anisotropic_rotation)
|
||||
NODE_SOCKET_API(float3, tangent)
|
||||
NODE_SOCKET_API(float, transmission_weight)
|
||||
NODE_SOCKET_API(float, sheen_weight)
|
||||
NODE_SOCKET_API(float, sheen_roughness)
|
||||
NODE_SOCKET_API(float3, sheen_tint)
|
||||
NODE_SOCKET_API(float, coat)
|
||||
NODE_SOCKET_API(float, coat_weight)
|
||||
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, coat_normal)
|
||||
NODE_SOCKET_API(float3, tangent)
|
||||
NODE_SOCKET_API(float, surface_mix_weight)
|
||||
NODE_SOCKET_API(ClosureType, distribution)
|
||||
NODE_SOCKET_API(ClosureType, subsurface_method)
|
||||
NODE_SOCKET_API(float3, emission)
|
||||
NODE_SOCKET_API(float3, emission_color)
|
||||
NODE_SOCKET_API(float, emission_strength)
|
||||
NODE_SOCKET_API(float, alpha)
|
||||
NODE_SOCKET_API(float, surface_mix_weight)
|
||||
|
||||
public:
|
||||
void attributes(Shader *shader, AttributeRequestSet *attributes);
|
||||
|
|
|
@ -281,27 +281,28 @@ class PrincipledBSDFWrapper(ShaderWrapper):
|
|||
def specular_get(self):
|
||||
if not self.use_nodes or self.node_principled_bsdf is None:
|
||||
return self.material.specular_intensity
|
||||
return self.node_principled_bsdf.inputs["Specular"].default_value
|
||||
return self.node_principled_bsdf.inputs["Specular IOR Level"].default_value
|
||||
|
||||
@_set_check
|
||||
def specular_set(self, value):
|
||||
value = values_clamp(value, 0.0, 1.0)
|
||||
self.material.specular_intensity = value
|
||||
if self.use_nodes and self.node_principled_bsdf is not None:
|
||||
self.node_principled_bsdf.inputs["Specular"].default_value = value
|
||||
self.node_principled_bsdf.inputs["Specular IOR Level"].default_value = value
|
||||
|
||||
specular = property(specular_get, specular_set)
|
||||
|
||||
def specular_tint_get(self):
|
||||
if not self.use_nodes or self.node_principled_bsdf is None:
|
||||
return 0.0
|
||||
return self.node_principled_bsdf.inputs["Specular Tint"].default_value
|
||||
return Color((0.0, 0.0, 0.0))
|
||||
return rgba_to_rgb(self.node_principled_bsdf.inputs["Specular Tint"].default_value)
|
||||
|
||||
@_set_check
|
||||
def specular_tint_set(self, value):
|
||||
value = values_clamp(value, 0.0, 1.0)
|
||||
def specular_tint_set(self, color):
|
||||
color = values_clamp(color, 0.0, 1.0)
|
||||
color = rgb_to_rgba(color)
|
||||
if self.use_nodes and self.node_principled_bsdf is not None:
|
||||
self.node_principled_bsdf.inputs["Specular Tint"].default_value = value
|
||||
self.node_principled_bsdf.inputs["Specular Tint"].default_value = color
|
||||
|
||||
specular_tint = property(specular_tint_get, specular_tint_set)
|
||||
|
||||
|
@ -312,7 +313,7 @@ class PrincipledBSDFWrapper(ShaderWrapper):
|
|||
return None
|
||||
return ShaderImageTextureWrapper(
|
||||
self, self.node_principled_bsdf,
|
||||
self.node_principled_bsdf.inputs["Specular"],
|
||||
self.node_principled_bsdf.inputs["Specular IOR Level"],
|
||||
grid_row_diff=0,
|
||||
colorspace_name='Non-Color',
|
||||
)
|
||||
|
@ -411,13 +412,13 @@ class PrincipledBSDFWrapper(ShaderWrapper):
|
|||
def transmission_get(self):
|
||||
if not self.use_nodes or self.node_principled_bsdf is None:
|
||||
return 0.0
|
||||
return self.node_principled_bsdf.inputs["Transmission"].default_value
|
||||
return self.node_principled_bsdf.inputs["Transmission Weight"].default_value
|
||||
|
||||
@_set_check
|
||||
def transmission_set(self, value):
|
||||
value = values_clamp(value, 0.0, 1.0)
|
||||
if self.use_nodes and self.node_principled_bsdf is not None:
|
||||
self.node_principled_bsdf.inputs["Transmission"].default_value = value
|
||||
self.node_principled_bsdf.inputs["Transmission Weight"].default_value = value
|
||||
|
||||
transmission = property(transmission_get, transmission_set)
|
||||
|
||||
|
@ -427,7 +428,7 @@ class PrincipledBSDFWrapper(ShaderWrapper):
|
|||
return None
|
||||
return ShaderImageTextureWrapper(
|
||||
self, self.node_principled_bsdf,
|
||||
self.node_principled_bsdf.inputs["Transmission"],
|
||||
self.node_principled_bsdf.inputs["Transmission Weight"],
|
||||
grid_row_diff=-1,
|
||||
colorspace_name='Non-Color',
|
||||
)
|
||||
|
@ -467,14 +468,14 @@ class PrincipledBSDFWrapper(ShaderWrapper):
|
|||
def emission_color_get(self):
|
||||
if not self.use_nodes or self.node_principled_bsdf is None:
|
||||
return Color((0.0, 0.0, 0.0))
|
||||
return rgba_to_rgb(self.node_principled_bsdf.inputs["Emission"].default_value)
|
||||
return rgba_to_rgb(self.node_principled_bsdf.inputs["Emission Color"].default_value)
|
||||
|
||||
@_set_check
|
||||
def emission_color_set(self, color):
|
||||
if self.use_nodes and self.node_principled_bsdf is not None:
|
||||
color = values_clamp(color, 0.0, 1000000.0)
|
||||
color = rgb_to_rgba(color)
|
||||
self.node_principled_bsdf.inputs["Emission"].default_value = color
|
||||
self.node_principled_bsdf.inputs["Emission Color"].default_value = color
|
||||
|
||||
emission_color = property(emission_color_get, emission_color_set)
|
||||
|
||||
|
@ -483,7 +484,7 @@ class PrincipledBSDFWrapper(ShaderWrapper):
|
|||
return None
|
||||
return ShaderImageTextureWrapper(
|
||||
self, self.node_principled_bsdf,
|
||||
self.node_principled_bsdf.inputs["Emission"],
|
||||
self.node_principled_bsdf.inputs["Emission Color"],
|
||||
grid_row_diff=1,
|
||||
)
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 24
|
||||
#define BLENDER_FILE_SUBVERSION 25
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
|
|
@ -1070,7 +1070,7 @@ static void displacement_principled_nodes(bNode *node)
|
|||
}
|
||||
}
|
||||
else if (node->type == SH_NODE_BSDF_PRINCIPLED) {
|
||||
if (node->custom2 != SHD_SUBSURFACE_RANDOM_WALK) {
|
||||
if (node->custom2 != SHD_SUBSURFACE_RANDOM_WALK_SKIN) {
|
||||
node->custom2 = SHD_SUBSURFACE_BURLEY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1548,13 +1548,13 @@ static bool seq_meta_channels_ensure(Sequence *seq, void * /*user_data*/)
|
|||
static void do_version_subsurface_methods(bNode *node)
|
||||
{
|
||||
if (node->type == SH_NODE_SUBSURFACE_SCATTERING) {
|
||||
if (!ELEM(node->custom1, SHD_SUBSURFACE_BURLEY, SHD_SUBSURFACE_RANDOM_WALK)) {
|
||||
node->custom1 = SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS;
|
||||
if (!ELEM(node->custom1, SHD_SUBSURFACE_BURLEY, SHD_SUBSURFACE_RANDOM_WALK_SKIN)) {
|
||||
node->custom1 = SHD_SUBSURFACE_RANDOM_WALK;
|
||||
}
|
||||
}
|
||||
else if (node->type == SH_NODE_BSDF_PRINCIPLED) {
|
||||
if (!ELEM(node->custom2, SHD_SUBSURFACE_BURLEY, SHD_SUBSURFACE_RANDOM_WALK)) {
|
||||
node->custom2 = SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS;
|
||||
if (!ELEM(node->custom2, SHD_SUBSURFACE_BURLEY, SHD_SUBSURFACE_RANDOM_WALK_SKIN)) {
|
||||
node->custom2 = SHD_SUBSURFACE_RANDOM_WALK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -692,6 +692,19 @@ static void version_principled_bsdf_emission(bNodeTree *ntree)
|
|||
}
|
||||
}
|
||||
|
||||
/* Rename various Principled BSDF sockets. */
|
||||
brecht marked this conversation as resolved
Outdated
Weizhen Huang
commented
… and specular to specular ior level … and specular to specular ior level
|
||||
static void version_principled_bsdf_rename_sockets(bNodeTree *ntree)
|
||||
{
|
||||
version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Emission", "Emission Color");
|
||||
version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Specular", "Specular IOR Level");
|
||||
version_node_input_socket_name(
|
||||
ntree, SH_NODE_BSDF_PRINCIPLED, "Subsurface", "Subsurface Weight");
|
||||
version_node_input_socket_name(
|
||||
ntree, SH_NODE_BSDF_PRINCIPLED, "Transmission", "Transmission Weight");
|
||||
version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Coat", "Coat Weight");
|
||||
version_node_input_socket_name(ntree, SH_NODE_BSDF_PRINCIPLED, "Sheen", "Sheen Weight");
|
||||
}
|
||||
|
||||
/* Replace old Principled Hair BSDF as a variant in the new Principled Hair BSDF. */
|
||||
static void version_replace_principled_hair_model(bNodeTree *ntree)
|
||||
{
|
||||
|
@ -796,6 +809,65 @@ static void version_principled_bsdf_coat(bNodeTree *ntree)
|
|||
ntree, SH_NODE_BSDF_PRINCIPLED, "Clearcoat Normal", "Coat Normal");
|
||||
}
|
||||
|
||||
/* Convert specular tint in Principled BSDF. */
|
||||
static void version_principled_bsdf_specular_tint(bNodeTree *ntree)
|
||||
{
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != SH_NODE_BSDF_PRINCIPLED) {
|
||||
continue;
|
||||
}
|
||||
bNodeSocket *specular_tint_sock = nodeFindSocket(node, SOCK_IN, "Specular Tint");
|
||||
if (specular_tint_sock->type == SOCK_RGBA) {
|
||||
/* Node is already updated. */
|
||||
continue;
|
||||
}
|
||||
|
||||
bNodeSocket *base_color_sock = nodeFindSocket(node, SOCK_IN, "Base Color");
|
||||
float specular_tint_old = *version_cycles_node_socket_float_value(specular_tint_sock);
|
||||
float *base_color = version_cycles_node_socket_rgba_value(base_color_sock);
|
||||
|
||||
/* Change socket type to Color. */
|
||||
nodeModifySocketTypeStatic(ntree, node, specular_tint_sock, SOCK_RGBA, 0);
|
||||
|
||||
static float one[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
/* If any of the two inputs is dynamic, we add a Mix node. */
|
||||
if (base_color_sock->link || specular_tint_sock->link) {
|
||||
bNode *mix = nodeAddStaticNode(nullptr, ntree, SH_NODE_MIX);
|
||||
static_cast<NodeShaderMix *>(mix->storage)->data_type = SOCK_RGBA;
|
||||
mix->locx = node->locx - 170;
|
||||
mix->locy = node->locy - 120;
|
||||
|
||||
bNodeSocket *a_in = nodeFindSocket(mix, SOCK_IN, "A_Color");
|
||||
bNodeSocket *b_in = nodeFindSocket(mix, SOCK_IN, "B_Color");
|
||||
bNodeSocket *fac_in = nodeFindSocket(mix, SOCK_IN, "Factor_Float");
|
||||
bNodeSocket *result_out = nodeFindSocket(mix, SOCK_OUT, "Result_Color");
|
||||
|
||||
copy_v4_v4(version_cycles_node_socket_rgba_value(a_in), one);
|
||||
copy_v4_v4(version_cycles_node_socket_rgba_value(b_in), base_color);
|
||||
*version_cycles_node_socket_float_value(fac_in) = specular_tint_old;
|
||||
|
||||
if (base_color_sock->link) {
|
||||
nodeAddLink(
|
||||
ntree, base_color_sock->link->fromnode, base_color_sock->link->fromsock, mix, b_in);
|
||||
}
|
||||
if (specular_tint_sock->link) {
|
||||
nodeAddLink(ntree,
|
||||
specular_tint_sock->link->fromnode,
|
||||
specular_tint_sock->link->fromsock,
|
||||
mix,
|
||||
fac_in);
|
||||
nodeRemLink(ntree, specular_tint_sock->link);
|
||||
}
|
||||
nodeAddLink(ntree, mix, result_out, node, specular_tint_sock);
|
||||
}
|
||||
|
||||
float *specular_tint = version_cycles_node_socket_rgba_value(specular_tint_sock);
|
||||
/* Mix the fixed values. */
|
||||
interp_v4_v4v4(specular_tint, one, base_color, specular_tint_old);
|
||||
}
|
||||
}
|
||||
|
||||
static void version_copy_socket(bNodeTreeInterfaceSocket &dst,
|
||||
const bNodeTreeInterfaceSocket &src,
|
||||
char *identifier)
|
||||
|
@ -1359,6 +1431,18 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 25)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type == NTREE_SHADER) {
|
||||
/* Convert specular tint on the Principled BSDF. */
|
||||
version_principled_bsdf_specular_tint(ntree);
|
||||
/* Rename some sockets. */
|
||||
version_principled_bsdf_rename_sockets(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
|
|
@ -609,7 +609,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
|||
if (node->type == SH_NODE_BSDF_PRINCIPLED) {
|
||||
bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness");
|
||||
*version_cycles_node_socket_float_value(roughness_socket) = 0.5f;
|
||||
bNodeSocket *emission = nodeFindSocket(node, SOCK_IN, "Emission");
|
||||
bNodeSocket *emission = nodeFindSocket(node, SOCK_IN, "Emission Color");
|
||||
copy_v4_fl(version_cycles_node_socket_rgba_value(emission), 1.0f);
|
||||
bNodeSocket *emission_strength = nodeFindSocket(node, SOCK_IN, "Emission Strength");
|
||||
*version_cycles_node_socket_float_value(emission_strength) = 0.0f;
|
||||
|
|
|
@ -1138,7 +1138,7 @@ bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma)
|
|||
e_data.surface.roughness_socket = static_cast<bNodeSocketValueFloat *>(
|
||||
nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value);
|
||||
e_data.surface.specular_socket = static_cast<bNodeSocketValueFloat *>(
|
||||
nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value);
|
||||
nodeFindSocket(bsdf, SOCK_IN, "Specular IOR Level")->default_value);
|
||||
e_data.surface.ntree = ntree;
|
||||
}
|
||||
/* Update */
|
||||
|
|
|
@ -17,12 +17,6 @@ vec3 specular_dominant_dir(vec3 N, vec3 V, float roughness)
|
|||
return normalize(mix(N, R, fac));
|
||||
}
|
||||
|
||||
float ior_from_f0(float f0)
|
||||
{
|
||||
float f = sqrt(f0);
|
||||
return (-f - 1.0) / (f - 1.0);
|
||||
}
|
||||
|
||||
/* Simplified form of F_eta(eta, 1.0). */
|
||||
float F0_from_ior(float eta)
|
||||
{
|
||||
|
@ -67,29 +61,29 @@ float F_eta(float eta, float cos_theta)
|
|||
}
|
||||
|
||||
/* Fresnel color blend base on fresnel factor */
|
||||
vec3 F_color_blend(float eta, float fresnel, vec3 f0_color)
|
||||
vec3 F_color_blend(float eta, float fresnel, vec3 F0_color)
|
||||
{
|
||||
float f0 = F0_from_ior(eta);
|
||||
float fac = saturate((fresnel - f0) / (1.0 - f0));
|
||||
return mix(f0_color, vec3(1.0), fac);
|
||||
float F0 = F0_from_ior(eta);
|
||||
float fac = saturate((fresnel - F0) / (1.0 - F0));
|
||||
return mix(F0_color, vec3(1.0), fac);
|
||||
}
|
||||
|
||||
/* Fresnel split-sum approximation. */
|
||||
vec3 F_brdf_single_scatter(vec3 f0, vec3 f90, vec2 lut)
|
||||
vec3 F_brdf_single_scatter(vec3 F0, vec3 F90, vec2 lut)
|
||||
{
|
||||
return f0 * lut.x + f90 * lut.y;
|
||||
return F0 * lut.x + F90 * lut.y;
|
||||
}
|
||||
|
||||
/* Multi-scattering brdf approximation from
|
||||
* "A Multiple-Scattering Microfacet Model for Real-Time Image-based Lighting"
|
||||
* https://jcgt.org/published/0008/01/03/paper.pdf by Carmelo J. Fdez-Agüera. */
|
||||
vec3 F_brdf_multi_scatter(vec3 f0, vec3 f90, vec2 lut)
|
||||
vec3 F_brdf_multi_scatter(vec3 F0, vec3 F90, vec2 lut)
|
||||
{
|
||||
vec3 FssEss = F_brdf_single_scatter(f0, f90, lut);
|
||||
vec3 FssEss = F_brdf_single_scatter(F0, F90, lut);
|
||||
|
||||
float Ess = lut.x + lut.y;
|
||||
float Ems = 1.0 - Ess;
|
||||
vec3 Favg = f0 + (f90 - f0) / 21.0;
|
||||
vec3 Favg = F0 + (F90 - F0) / 21.0;
|
||||
|
||||
/* The original paper uses `FssEss * radiance + Fms*Ems * irradiance`, but
|
||||
* "A Journey Through Implementing Multiscattering BRDFs and Area Lights" by Steve McAuley
|
||||
|
|
|
@ -94,6 +94,15 @@ vec3 safe_normalize(vec3 N);
|
|||
float fast_sqrt(float a);
|
||||
vec3 cameraVec(vec3 P);
|
||||
vec2 bsdf_lut(float a, float b, float c, float d);
|
||||
void bsdf_lut(vec3 F0,
|
||||
vec3 F90,
|
||||
vec3 transmission_tint,
|
||||
float cos_theta,
|
||||
float roughness,
|
||||
float ior,
|
||||
float do_multiscatter,
|
||||
out vec3 reflectance,
|
||||
out vec3 transmittance);
|
||||
vec2 brdf_lut(float a, float b);
|
||||
vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c);
|
||||
vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c);
|
||||
|
|
|
@ -101,24 +101,35 @@ vec3 lut_coords_bsdf(float cos_theta, float roughness, float ior)
|
|||
return coords;
|
||||
}
|
||||
|
||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
/* Computes the reflectance and transmittance based on the tint (`f0`, `f90`, `transmission_tint`)
|
||||
* and the BSDF LUT. */
|
||||
void bsdf_lut(vec3 F0,
|
||||
vec3 F90,
|
||||
vec3 transmission_tint,
|
||||
float cos_theta,
|
||||
float roughness,
|
||||
float ior,
|
||||
float do_multiscatter,
|
||||
out vec3 reflectance,
|
||||
out vec3 transmittance)
|
||||
{
|
||||
if (ior == 1.0) {
|
||||
return vec2(0.0, 1.0);
|
||||
reflectance = vec3(0.0);
|
||||
transmittance = transmission_tint;
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 split_sum;
|
||||
float transmission_factor;
|
||||
float F0 = F0_from_ior(ior);
|
||||
float F90 = 1.0;
|
||||
|
||||
if (ior >= 1.0) {
|
||||
if (ior > 1.0) {
|
||||
split_sum = brdf_lut(cos_theta, roughness);
|
||||
transmission_factor = sample_3D_texture(utilTex, lut_coords_btdf(cos_theta, roughness, ior)).a;
|
||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||
* transition at `IOR == 1`. */
|
||||
F90 = saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0));
|
||||
if (all(equal(F90, vec3(1.0)))) {
|
||||
F90 = vec3(saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
vec3 bsdf = sample_3D_texture(utilTex, lut_coords_bsdf(cos_theta, roughness, ior)).rgb;
|
||||
|
@ -126,20 +137,41 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter
|
|||
transmission_factor = bsdf.b;
|
||||
}
|
||||
|
||||
float reflectance = F_brdf_single_scatter(vec3(F0), vec3(F90), split_sum).r;
|
||||
float transmittance = (1.0 - F0) * transmission_factor;
|
||||
reflectance = F_brdf_single_scatter(F0, F90, split_sum);
|
||||
transmittance = (vec3(1.0) - F0) * transmission_factor * transmission_tint;
|
||||
|
||||
if (do_multiscatter != 0.0) {
|
||||
float Ess = F0 * split_sum.x + split_sum.y + (1.0 - F0) * transmission_factor;
|
||||
/* TODO: maybe add saturation for higher roughness similar as in `F_brdf_multi_scatter()`.
|
||||
* However, it is not necessarily desirable that the users see a different color than they
|
||||
* picked. */
|
||||
float scale = 1.0 / Ess;
|
||||
float real_F0 = F0_from_ior(ior);
|
||||
float Ess = real_F0 * split_sum.x + split_sum.y + (1.0 - real_F0) * transmission_factor;
|
||||
float Ems = 1.0 - Ess;
|
||||
/* Assume that the transmissive tint makes up most of the overall color if it's not zero. */
|
||||
vec3 Favg = all(equal(transmission_tint, vec3(0.0))) ? F0 + (F90 - F0) / 21.0 :
|
||||
transmission_tint;
|
||||
|
||||
vec3 scale = 1.0 / (1.0 - Ems * Favg);
|
||||
reflectance *= scale;
|
||||
transmittance *= scale;
|
||||
}
|
||||
|
||||
return vec2(reflectance, transmittance);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
{
|
||||
float F0 = F0_from_ior(ior);
|
||||
vec3 color = vec3(1.0);
|
||||
vec3 reflectance, transmittance;
|
||||
bsdf_lut(vec3(F0),
|
||||
color,
|
||||
color,
|
||||
cos_theta,
|
||||
roughness,
|
||||
ior,
|
||||
do_multiscatter,
|
||||
reflectance,
|
||||
transmittance);
|
||||
return vec2(reflectance.r, transmittance.r);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -43,6 +43,21 @@ vec2 bsdf_lut(float a, float b, float c, float d)
|
|||
return vec2(0.0);
|
||||
}
|
||||
|
||||
void bsdf_lut(vec3 F0,
|
||||
vec3 F90,
|
||||
vec3 transmission_tint,
|
||||
float cos_theta,
|
||||
float roughness,
|
||||
float ior,
|
||||
float do_multiscatter,
|
||||
out vec3 reflectance,
|
||||
out vec3 transmittance)
|
||||
{
|
||||
reflectance = vec3(0.0);
|
||||
transmittance = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 brdf_lut(float a, float b)
|
||||
{
|
||||
return vec2(0.0);
|
||||
|
|
|
@ -41,7 +41,7 @@ DefaultSurfaceNodeTree::DefaultSurfaceNodeTree()
|
|||
roughness_socket_ =
|
||||
(bNodeSocketValueFloat *)nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value;
|
||||
specular_socket_ =
|
||||
(bNodeSocketValueFloat *)nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value;
|
||||
(bNodeSocketValueFloat *)nodeFindSocket(bsdf, SOCK_IN, "Specular IOR Level")->default_value;
|
||||
ntree_ = ntree;
|
||||
}
|
||||
|
||||
|
|
|
@ -320,26 +320,37 @@ vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
|
|||
return vec3(sqrt((ior - 1.0) / (ior + 1.0)), sqrt(1.0 - cos_theta), roughness);
|
||||
}
|
||||
|
||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
/* Computes the reflectance and transmittance based on the tint (`f0`, `f90`, `transmission_tint`)
|
||||
* and the BSDF LUT. */
|
||||
void bsdf_lut(vec3 F0,
|
||||
vec3 F90,
|
||||
vec3 transmission_tint,
|
||||
float cos_theta,
|
||||
float roughness,
|
||||
float ior,
|
||||
float do_multiscatter,
|
||||
out vec3 reflectance,
|
||||
out vec3 transmittance)
|
||||
{
|
||||
#ifdef EEVEE_UTILITY_TX
|
||||
if (ior == 1.0) {
|
||||
return vec2(0.0, 1.0);
|
||||
reflectance = vec3(0.0);
|
||||
transmittance = transmission_tint;
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 split_sum;
|
||||
float transmission_factor;
|
||||
float F0 = F0_from_ior(ior);
|
||||
float F90 = 1.0;
|
||||
|
||||
if (ior >= 1.0) {
|
||||
if (ior > 1.0) {
|
||||
split_sum = brdf_lut(cos_theta, roughness);
|
||||
vec3 coords = lut_coords_btdf(cos_theta, roughness, ior);
|
||||
transmission_factor = utility_tx_sample_bsdf_lut(utility_tx, coords.xy, coords.z).a;
|
||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||
* transition at `IOR == 1`. */
|
||||
F90 = saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0));
|
||||
if (all(equal(F90, vec3(1.0)))) {
|
||||
F90 = vec3(saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
vec3 coords = lut_coords_bsdf(cos_theta, roughness, ior);
|
||||
|
@ -348,23 +359,37 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter
|
|||
transmission_factor = bsdf.b;
|
||||
}
|
||||
|
||||
float reflectance = F_brdf_single_scatter(vec3(F0), vec3(F90), split_sum).r;
|
||||
float transmittance = (1.0 - F0) * transmission_factor;
|
||||
reflectance = F_brdf_single_scatter(F0, F90, split_sum);
|
||||
transmittance = (vec3(1.0) - F0) * transmission_factor * transmission_tint;
|
||||
|
||||
if (do_multiscatter != 0.0) {
|
||||
float Ess = F0 * split_sum.x + split_sum.y + (1.0 - F0) * transmission_factor;
|
||||
/* TODO: maybe add saturation for higher roughness similar as in `F_brdf_multi_scatter()`.
|
||||
* However, it is not necessarily desirable that the users see a different color than they
|
||||
* picked. */
|
||||
float scale = 1.0 / Ess;
|
||||
float real_F0 = F0_from_ior(ior);
|
||||
float Ess = real_F0 * split_sum.x + split_sum.y + (1.0 - real_F0) * transmission_factor;
|
||||
float Ems = 1.0 - Ess;
|
||||
/* Assume that the transmissive tint makes up most of the overall color if it's not zero. */
|
||||
vec3 Favg = all(equal(transmission_tint, vec3(0.0))) ? F0 + (F90 - F0) / 21.0 :
|
||||
transmission_tint;
|
||||
|
||||
vec3 scale = 1.0 / (1.0 - Ems * Favg);
|
||||
reflectance *= scale;
|
||||
transmittance *= scale;
|
||||
}
|
||||
|
||||
return vec2(reflectance, transmittance);
|
||||
#else
|
||||
return vec2(0.0);
|
||||
reflectance = vec3(0.0);
|
||||
transmittance = vec3(0.0);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
{
|
||||
float F0 = F0_from_ior(ior);
|
||||
vec3 color = vec3(1.0);
|
||||
vec3 reflectance, transmittance;
|
||||
bsdf_lut(
|
||||
F0, color, color, cos_theta, roughness, ior, do_multiscatter, reflectance, transmittance);
|
||||
return vec2(reflectance.r, transmittance.r);
|
||||
}
|
||||
|
||||
#ifdef EEVEE_MATERIAL_STUBS
|
||||
|
|
|
@ -10,7 +10,7 @@ vec3 tint_from_color(vec3 color)
|
|||
|
||||
float principled_sheen(float NV, float rough)
|
||||
{
|
||||
/* Empirical approximation (manual curve fitting) to the sheen albedo. Can be refined. */
|
||||
/* Empirical approximation (manual curve fitting) to the sheen_weight albedo. Can be refined. */
|
||||
float den = 35.6694f * rough * rough - 24.4269f * rough * NV - 0.1405f * NV * NV +
|
||||
6.1211f * rough + 0.28105f * NV - 0.1405f;
|
||||
float num = 58.5299f * rough * rough - 85.0941f * rough * NV + 9.8955f * NV * NV +
|
||||
|
@ -18,30 +18,36 @@ float principled_sheen(float NV, float rough)
|
|||
return saturate(den / num);
|
||||
}
|
||||
|
||||
float ior_from_F0(float F0)
|
||||
{
|
||||
float f = sqrt(clamp(F0, 0.0, 0.99));
|
||||
return (-f - 1.0) / (f - 1.0);
|
||||
}
|
||||
|
||||
void node_bsdf_principled(vec4 base_color,
|
||||
float metallic,
|
||||
float roughness,
|
||||
float ior,
|
||||
float transmission,
|
||||
float alpha,
|
||||
vec3 N,
|
||||
float weight,
|
||||
float subsurface,
|
||||
float subsurface_scale,
|
||||
float subsurface_weight,
|
||||
vec3 subsurface_radius,
|
||||
float subsurface_scale,
|
||||
float subsurface_ior,
|
||||
float subsurface_anisotropy,
|
||||
float specular,
|
||||
float specular_tint,
|
||||
float specular_ior_level,
|
||||
vec4 specular_tint,
|
||||
float anisotropic,
|
||||
float anisotropic_rotation,
|
||||
vec3 T,
|
||||
float coat,
|
||||
float transmission_weight,
|
||||
float coat_weight,
|
||||
float coat_roughness,
|
||||
float coat_ior,
|
||||
vec4 coat_tint,
|
||||
vec3 CN,
|
||||
float sheen,
|
||||
float sheen_weight,
|
||||
float sheen_roughness,
|
||||
vec4 sheen_tint,
|
||||
vec4 emission,
|
||||
|
@ -55,9 +61,21 @@ void node_bsdf_principled(vec4 base_color,
|
|||
{
|
||||
brecht marked this conversation as resolved
Outdated
Lukas Stockner
commented
This should also be clamped between 0.0 and 1.0, a mix factor >1 makes no sense. This should also be clamped between 0.0 and 1.0, a mix factor >1 makes no sense.
Lukas Stockner
commented
Sorry, the line number got messed up here. I meant Sorry, the line number got messed up here. I meant `subsurface_weight`.
|
||||
/* Match cycles. */
|
||||
metallic = clamp(metallic, 0.0, 1.0);
|
||||
brecht marked this conversation as resolved
Outdated
Lukas Stockner
commented
I think this is still left over from before the "Tint is now a color" change? I don't think we want a hard limit on 1.0 now. I think this is still left over from before the "Tint is now a color" change? I don't think we want a hard limit on 1.0 now.
Lukas Stockner
commented
Sorry, the line number got messed up here. I meant the Sorry, the line number got messed up here. I meant the `specular_tint`.
Weizhen Huang
commented
The F0 is clamped instead, following glTF ( The F0 is clamped instead, following glTF (706ba4aa38)
Not sure about the metallic tint.
|
||||
transmission = clamp(transmission, 0.0, 1.0);
|
||||
coat = max(coat, 0.0);
|
||||
roughness = clamp(roughness, 0.0, 1.0);
|
||||
ior = max(ior, 1e-5);
|
||||
transmission_weight = clamp(transmission_weight, 0.0, 1.0);
|
||||
subsurface_weight = clamp(subsurface_weight, 0.0, 1.0);
|
||||
specular_ior_level = max(specular_ior_level, 0.0);
|
||||
specular_tint = max(specular_tint, vec4(0.0));
|
||||
/* Not used by EEVEE */
|
||||
/* anisotropic = clamp(anisotropic, 0.0, 1.0) */
|
||||
coat_weight = clamp(coat_weight, 0.0, 1.0);
|
||||
coat_roughness = clamp(coat_roughness, 0.0, 1.0);
|
||||
coat_ior = max(coat_ior, 1.0);
|
||||
sheen_weight = clamp(sheen_weight, 0.0, 1.0);
|
||||
sheen_roughness = clamp(sheen_roughness, 0.0, 1.0);
|
||||
emission_strength = max(emission_strength, 0.0);
|
||||
alpha = clamp(alpha, 0.0, 1.0);
|
||||
|
||||
N = safe_normalize(N);
|
||||
CN = safe_normalize(CN);
|
||||
|
@ -71,33 +89,43 @@ void node_bsdf_principled(vec4 base_color,
|
|||
weight *= alpha;
|
||||
|
||||
/* First layer: Sheen */
|
||||
/* TODO: Maybe sheen should be specular. */
|
||||
vec3 sheen_color = sheen * sheen_tint.rgb * principled_sheen(NV, sheen_roughness);
|
||||
ClosureDiffuse diffuse_data;
|
||||
diffuse_data.color = weight * sheen_color;
|
||||
diffuse_data.N = N;
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - max_v3(sheen_color));
|
||||
|
||||
if (sheen_weight > 0.0) {
|
||||
/* TODO: Maybe sheen_weight should be specular. */
|
||||
vec3 sheen_color = sheen_weight * sheen_tint.rgb * principled_sheen(NV, sheen_roughness);
|
||||
diffuse_data.color = weight * sheen_color;
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - max_v3(sheen_color));
|
||||
}
|
||||
else {
|
||||
diffuse_data.color = vec3(0.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 = bsdf_lut(coat_NV, coat_data.roughness, coat_ior, 0.0).x;
|
||||
coat_data.weight = weight * coat * reflectance;
|
||||
coat_data.color = vec3(1.0);
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - reflectance * coat);
|
||||
|
||||
if (coat == 0) {
|
||||
coat_tint.rgb = vec3(1.0);
|
||||
if (coat_weight > 0.0) {
|
||||
float coat_NV = dot(coat_data.N, V);
|
||||
float reflectance = bsdf_lut(coat_NV, coat_data.roughness, coat_ior, 0.0).x;
|
||||
coat_data.weight = weight * coat_weight * reflectance;
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - reflectance * coat_weight);
|
||||
|
||||
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_weight / NT));
|
||||
}
|
||||
}
|
||||
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));
|
||||
else {
|
||||
coat_tint.rgb = vec3(1.0);
|
||||
coat_data.weight = 0.0;
|
||||
}
|
||||
|
||||
/* Attenuated by sheen and coat. */
|
||||
|
@ -109,48 +137,67 @@ void node_bsdf_principled(vec4 base_color,
|
|||
ClosureReflection reflection_data;
|
||||
reflection_data.N = N;
|
||||
reflection_data.roughness = roughness;
|
||||
vec2 split_sum = brdf_lut(NV, roughness);
|
||||
if (true) {
|
||||
vec3 f0 = base_color.rgb;
|
||||
vec3 f90 = vec3(1.0);
|
||||
vec3 metallic_brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
|
||||
F_brdf_single_scatter(f0, f90, split_sum);
|
||||
|
||||
if (metallic > 0.0) {
|
||||
vec3 F0 = base_color.rgb;
|
||||
vec3 F90 = vec3(1.0);
|
||||
vec2 split_sum = brdf_lut(NV, roughness);
|
||||
vec3 metallic_brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(F0, F90, split_sum) :
|
||||
F_brdf_single_scatter(F0, F90, split_sum);
|
||||
reflection_data.color = weight * metallic * metallic_brdf;
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - metallic);
|
||||
}
|
||||
else {
|
||||
reflection_data.color = vec3(0.0);
|
||||
}
|
||||
|
||||
/* Transmission component */
|
||||
ClosureRefraction refraction_data;
|
||||
/* TODO: change `specular_tint` to rgb. */
|
||||
vec3 reflection_tint = mix(vec3(1.0), base_color.rgb, specular_tint);
|
||||
if (true) {
|
||||
vec2 bsdf = bsdf_lut(NV, roughness, ior, do_multiscatter);
|
||||
refraction_data.N = N;
|
||||
refraction_data.roughness = roughness;
|
||||
refraction_data.ior = ior;
|
||||
vec3 reflection_tint = specular_tint.rgb;
|
||||
if (transmission_weight > 0.0) {
|
||||
vec3 F0 = vec3(F0_from_ior(ior)) * reflection_tint;
|
||||
vec3 F90 = vec3(1.0);
|
||||
vec3 reflectance, transmittance;
|
||||
bsdf_lut(
|
||||
F0, F90, base_color.rgb, NV, roughness, ior, do_multiscatter, reflectance, transmittance);
|
||||
|
||||
reflection_data.color += weight * transmission * bsdf.x * reflection_tint;
|
||||
reflection_data.color += weight * transmission_weight * reflectance;
|
||||
|
||||
refraction_data.weight = weight * transmission * bsdf.y;
|
||||
refraction_data.color = base_color.rgb * coat_tint.rgb;
|
||||
refraction_data.N = N;
|
||||
refraction_data.roughness = roughness;
|
||||
refraction_data.ior = ior;
|
||||
refraction_data.weight = weight * transmission_weight;
|
||||
refraction_data.color = transmittance * coat_tint.rgb;
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - transmission);
|
||||
weight *= (1.0 - transmission_weight);
|
||||
}
|
||||
else {
|
||||
refraction_data.weight = 0.0;
|
||||
refraction_data.color = vec3(0.0);
|
||||
}
|
||||
|
||||
/* Specular component */
|
||||
if (true) {
|
||||
vec3 f0 = vec3(F0_from_ior(ior));
|
||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||
* transition at `IOR == 1`. */
|
||||
vec3 f90 = sqrt(saturate(f0 / 0.02));
|
||||
f0 *= 2.0 * specular * reflection_tint;
|
||||
float eta = ior;
|
||||
float f0 = F0_from_ior(eta);
|
||||
if (specular_ior_level != 0.5) {
|
||||
f0 *= 2.0 * specular_ior_level;
|
||||
eta = ior_from_F0(f0);
|
||||
if (ior < 1.0) {
|
||||
eta = 1.0 / eta;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 specular_brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
|
||||
F_brdf_single_scatter(f0, f90, split_sum);
|
||||
reflection_data.color += weight * specular_brdf;
|
||||
vec3 F0 = vec3(f0) * reflection_tint;
|
||||
F0 = clamp(F0, vec3(0.0), vec3(1.0));
|
||||
vec3 F90 = vec3(1.0);
|
||||
vec3 reflectance, unused;
|
||||
bsdf_lut(F0, F90, vec3(0.0), NV, roughness, eta, do_multiscatter, reflectance, unused);
|
||||
|
||||
reflection_data.color += weight * reflectance;
|
||||
/* Attenuate lower layers */
|
||||
weight *= (1.0 - max_v3(specular_brdf));
|
||||
weight *= (1.0 - max_v3(reflectance));
|
||||
}
|
||||
|
||||
/* Diffuse component */
|
||||
|
|
|
@ -330,7 +330,7 @@ void MaterialNode::set_emission(COLLADAFW::ColorOrTexture &cot)
|
|||
int locy = -300 * (node_map.size() - 2);
|
||||
if (cot.isColor()) {
|
||||
COLLADAFW::Color col = cot.getColor();
|
||||
bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Emission");
|
||||
bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Emission Color");
|
||||
float *fcol = (float *)socket->default_value;
|
||||
|
||||
fcol[0] = col.getRed();
|
||||
|
@ -340,9 +340,9 @@ void MaterialNode::set_emission(COLLADAFW::ColorOrTexture &cot)
|
|||
}
|
||||
// texture
|
||||
else if (cot.isTexture()) {
|
||||
bNode *texture_node = add_texture_node(cot, -300, locy, "Emission");
|
||||
bNode *texture_node = add_texture_node(cot, -300, locy, "Emission Color");
|
||||
if (texture_node != nullptr) {
|
||||
add_link(texture_node, "Color", shader_node, "Emission");
|
||||
add_link(texture_node, "Color", shader_node, "Emission Color");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,13 +388,13 @@ void MaterialNode::set_specular(COLLADAFW::ColorOrTexture &cot)
|
|||
has_specularity = false;
|
||||
}
|
||||
else {
|
||||
bNode *node = add_node(SH_NODE_RGB, -300, locy, "Specular");
|
||||
bNode *node = add_node(SH_NODE_RGB, -300, locy, "Specular IOR Level");
|
||||
set_color(node, col);
|
||||
/* TODO: Connect node */
|
||||
}
|
||||
}
|
||||
else if (cot.isTexture()) {
|
||||
add_texture_node(cot, -300, locy, "Specular");
|
||||
add_texture_node(cot, -300, locy, "Specular IOR Level");
|
||||
/* TODO: Connect node */
|
||||
}
|
||||
else {
|
||||
|
@ -407,7 +407,7 @@ void MaterialNode::set_specular(COLLADAFW::ColorOrTexture &cot)
|
|||
* TODO: This is a solution only for a corner case. We must find a better
|
||||
* way to handle specularity in general. Also note that currently we
|
||||
* do not export specularity values, see EffectExporter::operator() */
|
||||
bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Specular");
|
||||
bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Specular IOR Level");
|
||||
((bNodeSocketValueFloat *)socket->default_value)->value = 0.0f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1188,7 +1188,7 @@ COLLADASW::ColorOrTexture bc_get_emission(Material *ma)
|
|||
return bc_get_cot(default_color);
|
||||
}
|
||||
|
||||
COLLADASW::ColorOrTexture cot = bc_get_cot_from_shader(shader, "Emission", default_color);
|
||||
COLLADASW::ColorOrTexture cot = bc_get_cot_from_shader(shader, "Emission Color", default_color);
|
||||
|
||||
/* If using texture, emission strength is not supported. */
|
||||
COLLADASW::Color col = cot.getColor();
|
||||
|
|
|
@ -465,11 +465,11 @@ void USDMaterialReader::set_principled_node_inputs(bNode *principled,
|
|||
}
|
||||
|
||||
if (pxr::UsdShadeInput emissive_input = usd_shader.GetInput(usdtokens::emissiveColor)) {
|
||||
set_node_input(emissive_input, principled, "Emission", ntree, column, &context);
|
||||
set_node_input(emissive_input, principled, "Emission Color", ntree, column, &context);
|
||||
}
|
||||
|
||||
if (pxr::UsdShadeInput specular_input = usd_shader.GetInput(usdtokens::specularColor)) {
|
||||
set_node_input(specular_input, principled, "Specular", ntree, column, &context);
|
||||
set_node_input(specular_input, principled, "Specular Tint", ntree, column, &context);
|
||||
}
|
||||
|
||||
if (pxr::UsdShadeInput metallic_input = usd_shader.GetInput(usdtokens::metallic)) {
|
||||
|
@ -482,7 +482,7 @@ void USDMaterialReader::set_principled_node_inputs(bNode *principled,
|
|||
}
|
||||
|
||||
if (pxr::UsdShadeInput coat_input = usd_shader.GetInput(usdtokens::clearcoat)) {
|
||||
set_node_input(coat_input, principled, "Coat", ntree, column, &context);
|
||||
set_node_input(coat_input, principled, "Coat Weight", ntree, column, &context);
|
||||
}
|
||||
|
||||
if (pxr::UsdShadeInput coat_roughness_input = usd_shader.GetInput(usdtokens::clearcoatRoughness))
|
||||
|
|
|
@ -292,16 +292,16 @@ static InputSpecMap &preview_surface_input_map()
|
|||
{
|
||||
static InputSpecMap input_map = {
|
||||
{"Base Color", {usdtokens::diffuse_color, pxr::SdfValueTypeNames->Float3, true}},
|
||||
{"Emission", {usdtokens::emissive_color, pxr::SdfValueTypeNames->Float3, true}},
|
||||
{"Emission Color", {usdtokens::emissive_color, pxr::SdfValueTypeNames->Float3, true}},
|
||||
{"Color", {usdtokens::diffuse_color, pxr::SdfValueTypeNames->Float3, true}},
|
||||
{"Roughness", {usdtokens::roughness, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Metallic", {usdtokens::metallic, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Specular", {usdtokens::specular, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Specular IOR Level", {usdtokens::specular, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Alpha", {usdtokens::opacity, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"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}},
|
||||
{"Coat", {usdtokens::clearcoat, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Coat Weight", {usdtokens::clearcoat, pxr::SdfValueTypeNames->Float, true}},
|
||||
{"Coat Roughness", {usdtokens::clearcoatRoughness, pxr::SdfValueTypeNames->Float, true}},
|
||||
};
|
||||
|
||||
|
|
|
@ -27,12 +27,12 @@ namespace blender::io::obj {
|
|||
const char *tex_map_type_to_socket_id[] = {
|
||||
"Base Color",
|
||||
"Metallic",
|
||||
"Specular",
|
||||
"Specular IOR Level",
|
||||
"Roughness", /* Map specular exponent to roughness. */
|
||||
"Roughness",
|
||||
"Sheen",
|
||||
"Sheen Weight",
|
||||
"Metallic", /* Map reflection to metallic. */
|
||||
"Emission",
|
||||
"Emission Color",
|
||||
"Alpha",
|
||||
"Normal",
|
||||
};
|
||||
|
@ -204,7 +204,7 @@ static void store_bsdf_properties(const bNode *bsdf_node,
|
|||
|
||||
float specular = material->spec;
|
||||
if (bsdf_node) {
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Specular", {&specular, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Specular IOR Level", {&specular, 1});
|
||||
}
|
||||
|
||||
float metallic = material->metallic;
|
||||
|
@ -232,7 +232,7 @@ static void store_bsdf_properties(const bNode *bsdf_node,
|
|||
float emission_strength = 0.0f;
|
||||
if (bsdf_node) {
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Emission Strength", {&emission_strength, 1});
|
||||
copy_property_from_node(SOCK_RGBA, bsdf_node, "Emission", {emission_col, 3});
|
||||
copy_property_from_node(SOCK_RGBA, bsdf_node, "Emission Color", {emission_col, 3});
|
||||
}
|
||||
mul_v3_fl(emission_col, emission_strength);
|
||||
|
||||
|
@ -243,12 +243,12 @@ static void store_bsdf_properties(const bNode *bsdf_node,
|
|||
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, "Coat", {&coat, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Sheen Weight", {&sheen, 1});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Coat Weight", {&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});
|
||||
copy_property_from_node(SOCK_FLOAT, bsdf_node, "Transmission Weight", {&transmission, 1});
|
||||
|
||||
/* Clearcoat used to include an implicit 0.25 factor, so stay compatible to old versions. */
|
||||
coat *= 4.0f;
|
||||
|
|
|
@ -302,12 +302,12 @@ static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const MTLMaterial
|
|||
|
||||
float3 emission_color = mtl_mat.emission_color;
|
||||
if (emission_color.x >= 0 && emission_color.y >= 0 && emission_color.z >= 0) {
|
||||
set_property_of_socket(SOCK_RGBA, "Emission", {emission_color, 3}, bsdf);
|
||||
set_property_of_socket(SOCK_RGBA, "Emission Color", {emission_color, 3}, bsdf);
|
||||
}
|
||||
if (mtl_mat.tex_map_of_type(MTLTexMapType::Emission).is_valid()) {
|
||||
set_property_of_socket(SOCK_FLOAT, "Emission Strength", {1.0f}, bsdf);
|
||||
}
|
||||
set_property_of_socket(SOCK_FLOAT, "Specular", {specular}, bsdf);
|
||||
set_property_of_socket(SOCK_FLOAT, "Specular IOR Level", {specular}, bsdf);
|
||||
set_property_of_socket(SOCK_FLOAT, "Roughness", {roughness}, bsdf);
|
||||
mat->roughness = roughness;
|
||||
set_property_of_socket(SOCK_FLOAT, "Metallic", {metallic}, bsdf);
|
||||
|
@ -324,11 +324,11 @@ static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const MTLMaterial
|
|||
}
|
||||
|
||||
if (mtl_mat.sheen >= 0) {
|
||||
set_property_of_socket(SOCK_FLOAT, "Sheen", {mtl_mat.sheen}, bsdf);
|
||||
set_property_of_socket(SOCK_FLOAT, "Sheen Weight", {mtl_mat.sheen}, bsdf);
|
||||
}
|
||||
if (mtl_mat.cc_thickness >= 0) {
|
||||
/* 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);
|
||||
set_property_of_socket(SOCK_FLOAT, "Coat Weight", {0.25f * mtl_mat.cc_thickness}, bsdf);
|
||||
}
|
||||
if (mtl_mat.cc_roughness >= 0) {
|
||||
set_property_of_socket(SOCK_FLOAT, "Coat Roughness", {mtl_mat.cc_roughness}, bsdf);
|
||||
|
@ -345,7 +345,7 @@ static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const MTLMaterial
|
|||
mtl_mat.transmit_color[2]) /
|
||||
3;
|
||||
if (transmission >= 0) {
|
||||
set_property_of_socket(SOCK_FLOAT, "Transmission", {transmission}, bsdf);
|
||||
set_property_of_socket(SOCK_FLOAT, "Transmission Weight", {transmission}, bsdf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2294,8 +2294,8 @@ enum {
|
|||
SHD_SUBSURFACE_GAUSSIAN = 2,
|
||||
#endif
|
||||
SHD_SUBSURFACE_BURLEY = 3,
|
||||
SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS = 4,
|
||||
SHD_SUBSURFACE_RANDOM_WALK = 5,
|
||||
SHD_SUBSURFACE_RANDOM_WALK = 4,
|
||||
SHD_SUBSURFACE_RANDOM_WALK_SKIN = 5,
|
||||
};
|
||||
|
||||
/* blur node */
|
||||
|
|
|
@ -4085,18 +4085,18 @@ static const EnumPropertyItem node_subsurface_method_items[] = {
|
|||
0,
|
||||
"Christensen-Burley",
|
||||
"Approximation to physically based volume scattering"},
|
||||
{SHD_SUBSURFACE_RANDOM_WALK_FIXED_RADIUS,
|
||||
"RANDOM_WALK_FIXED_RADIUS",
|
||||
0,
|
||||
"Random Walk (Fixed Radius)",
|
||||
"Volumetric approximation to physically based volume scattering, using the scattering radius "
|
||||
"as specified"},
|
||||
{SHD_SUBSURFACE_RANDOM_WALK,
|
||||
"RANDOM_WALK",
|
||||
0,
|
||||
"Random Walk",
|
||||
"Volumetric approximation to physically based volume scattering, using the scattering radius "
|
||||
"as specified"},
|
||||
{SHD_SUBSURFACE_RANDOM_WALK_SKIN,
|
||||
"RANDOM_WALK_SKIN",
|
||||
0,
|
||||
"Random Walk (Skin)",
|
||||
"Volumetric approximation to physically based volume scattering, with scattering radius "
|
||||
"automatically adjusted to match color textures"},
|
||||
"automatically adjusted to match color textures. Designed for skin shading"},
|
||||
{0, nullptr, 0, nullptr, nullptr}};
|
||||
|
||||
static const EnumPropertyItem prop_image_extension[] = {
|
||||
|
|
|
@ -40,18 +40,12 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
#define SOCK_ROUGHNESS_ID 2
|
||||
b.add_input<decl::Float>("IOR").default_value(1.45f).min(1.0f).max(1000.0f);
|
||||
#define SOCK_IOR_ID 3
|
||||
b.add_input<decl::Float>("Transmission")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_TRANSMISSION_ID 4
|
||||
b.add_input<decl::Float>("Alpha").default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
|
||||
#define SOCK_ALPHA_ID 5
|
||||
#define SOCK_ALPHA_ID 4
|
||||
b.add_input<decl::Vector>("Normal").hide_value();
|
||||
#define SOCK_NORMAL_ID 6
|
||||
#define SOCK_NORMAL_ID 5
|
||||
b.add_input<decl::Float>("Weight").unavailable();
|
||||
#define SOCK_WEIGHT_ID 7
|
||||
#define SOCK_WEIGHT_ID 6
|
||||
|
||||
/* Panel for Subsurface scattering settings. */
|
||||
PanelDeclarationBuilder &sss =
|
||||
|
@ -60,7 +54,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.draw_buttons([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) {
|
||||
uiItemR(layout, ptr, "subsurface_method", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
});
|
||||
sss.add_input<decl::Float>("Subsurface")
|
||||
sss.add_input<decl::Float>("Subsurface Weight")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
|
@ -68,7 +62,14 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.description(
|
||||
"Blend between diffuse surface and subsurface scattering. "
|
||||
"Typically should be zero or one (either fully diffuse or subsurface)");
|
||||
#define SOCK_SUBSURFACE_ID 8
|
||||
#define SOCK_SUBSURFACE_WEIGHT_ID 7
|
||||
sss.add_input<decl::Vector>("Subsurface Radius")
|
||||
.default_value({1.0f, 0.2f, 0.1f})
|
||||
.min(0.0f)
|
||||
.max(100.0f)
|
||||
.compact()
|
||||
.description("Scattering radius to use for subsurface component (multiplied with Scale)");
|
||||
#define SOCK_SUBSURFACE_RADIUS_ID 8
|
||||
sss.add_input<decl::Float>("Subsurface Scale")
|
||||
.default_value(0.05f)
|
||||
.min(0.0f)
|
||||
|
@ -76,26 +77,19 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.subtype(PROP_DISTANCE)
|
||||
.description("Scale of the subsurface scattering (multiplied with Radius)");
|
||||
#define SOCK_SUBSURFACE_SCALE_ID 9
|
||||
sss.add_input<decl::Vector>("Subsurface Radius")
|
||||
.default_value({1.0f, 0.2f, 0.1f})
|
||||
.min(0.0f)
|
||||
.max(100.0f)
|
||||
.compact()
|
||||
.description("Scattering radius to use for subsurface component (multiplied with Scale)");
|
||||
#define SOCK_SUBSURFACE_RADIUS_ID 10
|
||||
sss.add_input<decl::Float>("Subsurface IOR")
|
||||
.default_value(1.4f)
|
||||
.min(1.01f)
|
||||
.max(3.8f)
|
||||
.subtype(PROP_FACTOR)
|
||||
.description("Index of refraction used for rays that enter the subsurface component");
|
||||
#define SOCK_SUBSURFACE_IOR_ID 11
|
||||
#define SOCK_SUBSURFACE_IOR_ID 10
|
||||
sss.add_input<decl::Float>("Subsurface Anisotropy")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_SUBSURFACE_ANISOTROPY_ID 12
|
||||
#define SOCK_SUBSURFACE_ANISOTROPY_ID 11
|
||||
|
||||
/* Panel for Specular settings. */
|
||||
PanelDeclarationBuilder &spec =
|
||||
|
@ -104,36 +98,50 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.draw_buttons([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) {
|
||||
uiItemR(layout, ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
});
|
||||
spec.add_input<decl::Float>("Specular")
|
||||
spec.add_input<decl::Float>("Specular IOR Level")
|
||||
.default_value(0.5f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_SPECULAR_ID 13
|
||||
spec.add_input<decl::Float>("Specular Tint")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_SPECULAR_TINT_ID 14
|
||||
.subtype(PROP_FACTOR)
|
||||
.description(
|
||||
"Adjustment to the IOR to increase or decrease specular intensity "
|
||||
"(0.5 means no adjustment, 0 removes all reflections, 1 doubles them at normal "
|
||||
"incidence)");
|
||||
#define SOCK_SPECULAR_ID 12
|
||||
spec.add_input<decl::Color>("Specular Tint")
|
||||
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
|
||||
.description(
|
||||
"Tint dielectric reflection at normal incidence for artistic control, and metallic "
|
||||
brecht marked this conversation as resolved
Outdated
Weizhen Huang
commented
Should clarify that 1 doubles the reflectivity at normal incidence, as suggested in the pull request Should clarify that 1 doubles the reflectivity at normal incidence, as suggested in the pull request
|
||||
"reflection at near-grazing incidence to simulate complex index of refraction");
|
||||
#define SOCK_SPECULAR_TINT_ID 13
|
||||
spec.add_input<decl::Float>("Anisotropic")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
brecht marked this conversation as resolved
Outdated
Weizhen Huang
commented
Should be something like “Tint of dielectric reflection at normal incidence or metallic reflection at near-grazing incidence”. Should be something like “Tint of dielectric reflection at normal incidence or metallic reflection at near-grazing incidence”.
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_ANISOTROPIC_ID 15
|
||||
#define SOCK_ANISOTROPIC_ID 14
|
||||
spec.add_input<decl::Float>("Anisotropic Rotation")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_ANISOTROPIC_ROTATION_ID 16
|
||||
#define SOCK_ANISOTROPIC_ROTATION_ID 15
|
||||
spec.add_input<decl::Vector>("Tangent").hide_value();
|
||||
#define SOCK_TANGENT_ID 17
|
||||
#define SOCK_TANGENT_ID 16
|
||||
|
||||
/* Panel for Transmission settings. */
|
||||
PanelDeclarationBuilder &transmission = b.add_panel("Transmission").default_closed(true);
|
||||
transmission.add_input<decl::Float>("Transmission Weight")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR)
|
||||
.description("Blend between transmission and other base layer components");
|
||||
#define SOCK_TRANSMISSION_WEIGHT_ID 17
|
||||
|
||||
/* Panel for Coat settings. */
|
||||
PanelDeclarationBuilder &coat = b.add_panel("Coat").default_closed(true);
|
||||
coat.add_input<decl::Float>("Coat")
|
||||
coat.add_input<decl::Float>("Coat Weight")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
|
@ -141,7 +149,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.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 18
|
||||
#define SOCK_COAT_WEIGHT_ID 18
|
||||
coat.add_input<decl::Float>("Coat Roughness")
|
||||
.default_value(0.03f)
|
||||
.min(0.0f)
|
||||
|
@ -169,9 +177,12 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
|
||||
/* Panel for Sheen settings. */
|
||||
PanelDeclarationBuilder &sheen = b.add_panel("Sheen").default_closed(true);
|
||||
sheen.add_input<decl::Float>("Sheen").default_value(0.0f).min(0.0f).max(1.0f).subtype(
|
||||
PROP_FACTOR);
|
||||
#define SOCK_SHEEN_ID 23
|
||||
sheen.add_input<decl::Float>("Sheen Weight")
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
#define SOCK_SHEEN_WEIGHT_ID 23
|
||||
sheen.add_input<decl::Float>("Sheen Roughness")
|
||||
.default_value(0.5f)
|
||||
.min(0.0f)
|
||||
|
@ -183,7 +194,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
|
||||
/* Panel for Emission settings. */
|
||||
PanelDeclarationBuilder &emis = b.add_panel("Emission").default_closed(true);
|
||||
emis.add_input<decl::Color>("Emission").default_value({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
emis.add_input<decl::Color>("Emission Color").default_value({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
#define SOCK_EMISSION_ID 26
|
||||
emis.add_input<decl::Float>("Emission Strength").default_value(0.0).min(0.0f).max(1000000.0f);
|
||||
#define SOCK_EMISSION_STRENGTH_ID 27
|
||||
|
@ -224,12 +235,14 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
|
|||
}
|
||||
#endif
|
||||
|
||||
bool use_diffuse = socket_not_zero(SOCK_SHEEN_ID) ||
|
||||
(socket_not_one(SOCK_METALLIC_ID) && socket_not_one(SOCK_TRANSMISSION_ID));
|
||||
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_diffuse = socket_not_zero(SOCK_SHEEN_WEIGHT_ID) ||
|
||||
(socket_not_one(SOCK_METALLIC_ID) &&
|
||||
socket_not_one(SOCK_TRANSMISSION_WEIGHT_ID));
|
||||
bool use_subsurf = socket_not_zero(SOCK_SUBSURFACE_WEIGHT_ID) && use_diffuse;
|
||||
bool use_refract = socket_not_one(SOCK_METALLIC_ID) &&
|
||||
socket_not_zero(SOCK_TRANSMISSION_WEIGHT_ID);
|
||||
bool use_transparency = socket_not_one(SOCK_ALPHA_ID);
|
||||
bool use_coat = socket_not_zero(SOCK_COAT_ID);
|
||||
bool use_coat = socket_not_zero(SOCK_COAT_WEIGHT_ID);
|
||||
|
||||
eGPUMaterialFlag flag = GPU_MATFLAG_GLOSSY;
|
||||
if (use_diffuse) {
|
||||
|
@ -300,7 +313,7 @@ static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
|
|||
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
nodeFindSocket(node, SOCK_IN, "Subsurface IOR"),
|
||||
sss_method == SHD_SUBSURFACE_RANDOM_WALK);
|
||||
sss_method == SHD_SUBSURFACE_RANDOM_WALK_SKIN);
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
nodeFindSocket(node, SOCK_IN, "Subsurface Anisotropy"),
|
||||
sss_method != SHD_SUBSURFACE_BURLEY);
|
||||
|
|
Should be clamped to 0..1