Cycles: Tweak Principled BSDF Subsurface parameters #110989
|
@ -11,8 +11,11 @@ typedef struct Bssrdf {
|
|||
|
||||
Spectrum radius;
|
||||
Spectrum albedo;
|
||||
float roughness;
|
||||
float anisotropy;
|
||||
|
||||
/* Parameters for refractive entry bounce. */
|
||||
float ior;
|
||||
float alpha;
|
||||
} Bssrdf;
|
||||
|
||||
static_assert(sizeof(ShaderClosure) >= sizeof(Bssrdf), "Bssrdf is too large!");
|
||||
|
@ -54,9 +57,7 @@ ccl_device float bssrdf_dipole_compute_alpha_prime(float rd, float fourthirdA)
|
|||
return xmid;
|
||||
}
|
||||
|
||||
ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf,
|
||||
const ClosureType type,
|
||||
const float eta)
|
||||
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) {
|
||||
/* Scale mean free path length so it gives similar looking result to older
|
||||
|
@ -65,8 +66,8 @@ ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf,
|
|||
}
|
||||
else {
|
||||
/* Adjust radius based on IOR and albedo. */
|
||||
const float inv_eta = 1.0f / eta;
|
||||
const float F_dr = inv_eta * (-1.440f * inv_eta + 0.710f) + 0.668f + 0.0636f * eta;
|
||||
const float inv_eta = 1.0f / bssrdf->ior;
|
||||
const float F_dr = inv_eta * (-1.440f * inv_eta + 0.710f) + 0.668f + 0.0636f * bssrdf->ior;
|
||||
const float fourthirdA = (4.0f / 3.0f) * (1.0f + F_dr) /
|
||||
(1.0f - F_dr); /* From Jensen's `Fdr` ratio formula. */
|
||||
|
||||
|
@ -281,17 +282,34 @@ ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, S
|
|||
|
||||
ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
|
||||
ccl_private Bssrdf *bssrdf,
|
||||
ClosureType type,
|
||||
const float ior)
|
||||
int path_flag,
|
||||
ClosureType type)
|
||||
{
|
||||
/* Clamps protecting against bad/extreme and non physical values. */
|
||||
bssrdf->anisotropy = clamp(bssrdf->anisotropy, 0.0f, 0.9f);
|
||||
bssrdf->ior = clamp(bssrdf->ior, 1.01f, 3.8f);
|
||||
|
||||
int flag = 0;
|
||||
|
||||
if (type == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
|
||||
/* CLOSURE_BSSRDF_RANDOM_WALK_ID uses a fixed roughness. */
|
||||
bssrdf->alpha = 1.0f;
|
||||
}
|
||||
|
||||
/* Verify if the radii are large enough to sample without precision issues. */
|
||||
int bssrdf_channels = SPECTRUM_CHANNELS;
|
||||
Spectrum diffuse_weight = zero_spectrum();
|
||||
|
||||
/* Fall back to diffuse if the radius is smaller than a quarter pixel. */
|
||||
float min_radius = max(0.25f * sd->dP, BSSRDF_MIN_RADIUS);
|
||||
if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
|
||||
/* Always fall back to diffuse after a diffuse ancestor. Can't see it well then and adds
|
||||
* considerable noise due to probabilities of continuing the path getting lower and lower. */
|
||||
min_radius = FLT_MAX;
|
||||
}
|
||||
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
if (GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < BSSRDF_MIN_RADIUS) {
|
||||
if (GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < min_radius) {
|
||||
GET_SPECTRUM_CHANNEL(diffuse_weight, i) = GET_SPECTRUM_CHANNEL(bssrdf->weight, i);
|
||||
GET_SPECTRUM_CHANNEL(bssrdf->weight, i) = 0.0f;
|
||||
GET_SPECTRUM_CHANNEL(bssrdf->radius, i) = 0.0f;
|
||||
|
@ -315,12 +333,12 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
|
|||
bssrdf->type = type;
|
||||
bssrdf->sample_weight = fabsf(average(bssrdf->weight)) * bssrdf_channels;
|
||||
|
||||
bssrdf_setup_radius(bssrdf, type, ior);
|
||||
bssrdf_setup_radius(bssrdf, type);
|
||||
|
||||
flag |= SD_BSSRDF;
|
||||
}
|
||||
else {
|
||||
bssrdf->type = type;
|
||||
bssrdf->type = CLOSURE_NONE_ID;
|
||||
bssrdf->sample_weight = 0.0f;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ KERNEL_STRUCT_BEGIN(subsurface)
|
|||
KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, albedo, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, radius, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, float, anisotropy, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, packed_float3, Ng, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, packed_float3, N, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_END(subsurface)
|
||||
|
||||
/********************************** Volume Stack ******************************/
|
||||
|
|
|
@ -23,6 +23,60 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
#ifdef __SUBSURFACE__
|
||||
|
||||
ccl_device_inline bool subsurface_entry_bounce(KernelGlobals kg,
|
||||
ccl_private const Bssrdf *bssrdf,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private RNGState *rng_state,
|
||||
ccl_private float3 *wo)
|
||||
{
|
||||
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.
|
||||
* Also, for the refractive entry, it uses a fixed roughness of 1.0. */
|
||||
if (rand_bsdf.x < 0.5f) {
|
||||
rand_bsdf.x *= 2.0f;
|
||||
float pdf;
|
||||
sample_cos_hemisphere(-bssrdf->N, rand_bsdf, wo, &pdf);
|
||||
return true;
|
||||
}
|
||||
rand_bsdf.x = 2.0f * (rand_bsdf.x - 0.5f);
|
||||
}
|
||||
|
||||
const float cos_NI = dot(bssrdf->N, sd->wi);
|
||||
if (cos_NI <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float3 X, Y, Z = bssrdf->N;
|
||||
make_orthonormals(Z, &X, &Y);
|
||||
|
||||
const float alpha = bssrdf->alpha;
|
||||
const float neta = 1.0f / bssrdf->ior;
|
||||
LukasStockner marked this conversation as resolved
Outdated
|
||||
|
||||
/* Sample microfacet normal by transforming to/from local coordinates. */
|
||||
const float3 local_I = make_float3(dot(X, sd->wi), dot(Y, sd->wi), cos_NI);
|
||||
const float3 local_H = microfacet_ggx_sample_vndf(local_I, alpha, alpha, rand_bsdf);
|
||||
const float3 H = X * local_H.x + Y * local_H.y + Z * local_H.z;
|
||||
|
||||
const float cos_HI = dot(H, sd->wi);
|
||||
const float arg = 1.0f - (sqr(neta) * (1.0f - sqr(cos_HI)));
|
||||
/* We clamp subsurface IOR to be above 1, so there should never be TIR. */
|
||||
kernel_assert(arg >= 0.0f);
|
||||
|
||||
const float dnp = max(sqrtf(arg), 1e-7f);
|
||||
const float nK = (neta * cos_HI) - dnp;
|
||||
*wo = -(neta * sd->wi) + (nK * H);
|
||||
return true;
|
||||
/* Note: For a proper refractive GGX interface, we should be computing lambdaI and lambdaO
|
||||
* and multiplying the throughput by BSDF/pdf, which for VNDF sampling works out to
|
||||
* (1 + lambdaI) / (1 + lambdaI + lambdaO).
|
||||
* However, this causes darkening due to the single-scattering approximation, which we'd
|
||||
* then have to correct with a lookup table.
|
||||
* Since we only really care about the directional distribution here, it's much easier to
|
||||
* just skip all that instead. */
|
||||
}
|
||||
|
||||
ccl_device int subsurface_bounce(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
|
@ -37,32 +91,44 @@ ccl_device int subsurface_bounce(KernelGlobals kg,
|
|||
|
||||
/* Setup ray into surface. */
|
||||
INTEGRATOR_STATE_WRITE(state, ray, P) = sd->P;
|
||||
INTEGRATOR_STATE_WRITE(state, ray, D) = bssrdf->N;
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmin) = 0.0f;
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmax) = FLT_MAX;
|
||||
INTEGRATOR_STATE_WRITE(state, ray, dP) = differential_make_compact(sd->dP);
|
||||
INTEGRATOR_STATE_WRITE(state, ray, dD) = differential_zero_compact();
|
||||
|
||||
/* Pass along object info, reusing isect to save memory. */
|
||||
INTEGRATOR_STATE_WRITE(state, subsurface, Ng) = sd->Ng;
|
||||
|
||||
uint32_t path_flag = (INTEGRATOR_STATE(state, path, flag) & ~PATH_RAY_CAMERA) |
|
||||
((sc->type == CLOSURE_BSSRDF_BURLEY_ID) ? PATH_RAY_SUBSURFACE_DISK :
|
||||
PATH_RAY_SUBSURFACE_RANDOM_WALK);
|
||||
/* Advance random number offset for bounce. */
|
||||
INTEGRATOR_STATE_WRITE(state, path, rng_offset) += PRNG_BOUNCE_NUM;
|
||||
|
||||
/* Compute weight, optionally including Fresnel from entry point. */
|
||||
Spectrum weight = surface_shader_bssrdf_sample_weight(sd, sc);
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) *= weight;
|
||||
|
||||
uint32_t path_flag = (INTEGRATOR_STATE(state, path, flag) & ~PATH_RAY_CAMERA);
|
||||
if (sc->type == CLOSURE_BSSRDF_BURLEY_ID) {
|
||||
path_flag |= PATH_RAY_SUBSURFACE_DISK;
|
||||
INTEGRATOR_STATE_WRITE(state, subsurface, N) = sd->Ng;
|
||||
}
|
||||
else {
|
||||
path_flag |= PATH_RAY_SUBSURFACE_RANDOM_WALK;
|
||||
|
||||
/* Sample entry bounce into the material. */
|
||||
RNGState rng_state;
|
||||
path_state_rng_load(state, &rng_state);
|
||||
float3 wo;
|
||||
if (!subsurface_entry_bounce(kg, bssrdf, sd, &rng_state, &wo) || dot(sd->Ng, wo) >= 0.0f) {
|
||||
/* Sampling failed, give up on this bounce. */
|
||||
return LABEL_NONE;
|
||||
}
|
||||
INTEGRATOR_STATE_WRITE(state, ray, D) = wo;
|
||||
INTEGRATOR_STATE_WRITE(state, subsurface, N) = sd->N;
|
||||
}
|
||||
|
||||
if (sd->flag & SD_BACKFACING) {
|
||||
path_flag |= PATH_RAY_SUBSURFACE_BACKFACING;
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) *= weight;
|
||||
INTEGRATOR_STATE_WRITE(state, path, flag) = path_flag;
|
||||
|
||||
/* Advance random number offset for bounce. */
|
||||
INTEGRATOR_STATE_WRITE(state, path, rng_offset) += PRNG_BOUNCE_NUM;
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
|
||||
|
|
|
@ -34,7 +34,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg,
|
|||
const float3 P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float ray_dP = INTEGRATOR_STATE(state, ray, dP);
|
||||
const float time = INTEGRATOR_STATE(state, ray, time);
|
||||
const float3 Ng = INTEGRATOR_STATE(state, subsurface, Ng);
|
||||
const float3 Ng = INTEGRATOR_STATE(state, subsurface, N);
|
||||
const int object = INTEGRATOR_STATE(state, isect, object);
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
|
||||
|
|
|
@ -168,24 +168,14 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
|||
ccl_private Ray &ray,
|
||||
ccl_private LocalIntersection &ss_isect)
|
||||
{
|
||||
const float2 rand_bsdf = path_state_rng_2D(kg, &rng_state, PRNG_SUBSURFACE_BSDF);
|
||||
|
||||
const float3 P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float3 N = INTEGRATOR_STATE(state, ray, D);
|
||||
const float3 D = INTEGRATOR_STATE(state, ray, D);
|
||||
const float ray_dP = INTEGRATOR_STATE(state, ray, dP);
|
||||
const float time = INTEGRATOR_STATE(state, ray, time);
|
||||
const float3 Ng = INTEGRATOR_STATE(state, subsurface, Ng);
|
||||
const float3 N = INTEGRATOR_STATE(state, subsurface, N);
|
||||
const int object = INTEGRATOR_STATE(state, isect, object);
|
||||
const int prim = INTEGRATOR_STATE(state, isect, prim);
|
||||
|
||||
/* Sample diffuse surface scatter into the object. */
|
||||
float3 D;
|
||||
float pdf;
|
||||
sample_cos_hemisphere(-N, rand_bsdf, &D, &pdf);
|
||||
if (dot(-Ng, D) <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Setup ray. */
|
||||
ray.P = P;
|
||||
ray.D = D;
|
||||
|
@ -436,10 +426,11 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
|||
if (hit) {
|
||||
kernel_assert(isfinite_safe(throughput));
|
||||
|
||||
/* TODO(lukas): Which PDF should we report here? Entry bounce? The random walk? Just 1.0? */
|
||||
guiding_record_bssrdf_bounce(
|
||||
kg,
|
||||
state,
|
||||
pdf,
|
||||
1.0f,
|
||||
N,
|
||||
D,
|
||||
safe_divide_color(throughput, INTEGRATOR_STATE(state, path, throughput)),
|
||||
|
|
|
@ -740,23 +740,16 @@ ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg,
|
|||
return;
|
||||
}
|
||||
|
||||
/* disable in case of diffuse ancestor, can't see it well then and
|
||||
* adds considerably noise due to probabilities of continuing path
|
||||
* getting lower and lower */
|
||||
if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
|
||||
bssrdf->radius = zero_spectrum();
|
||||
}
|
||||
else {
|
||||
bssrdf->radius = closure->radius;
|
||||
}
|
||||
bssrdf->radius = closure->radius;
|
||||
|
||||
/* create one closure per color channel */
|
||||
bssrdf->albedo = closure->albedo;
|
||||
bssrdf->N = closure->N;
|
||||
bssrdf->roughness = closure->roughness;
|
||||
bssrdf->anisotropy = clamp(closure->anisotropy, 0.0f, 0.9f);
|
||||
bssrdf->alpha = sqr(closure->roughness);
|
||||
bssrdf->ior = closure->ior;
|
||||
bssrdf->anisotropy = closure->anisotropy;
|
||||
|
||||
sd->flag |= bssrdf_setup(sd, bssrdf, type, clamp(closure->ior, 1.01f, 3.8f));
|
||||
sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, type);
|
||||
}
|
||||
|
||||
/* Hair */
|
||||
|
|
|
@ -9,8 +9,8 @@ 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 SubsurfaceScale = 0.1,
|
||||
vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
|
||||
color SubsurfaceColor = color(0.7, 0.1, 0.1),
|
||||
float SubsurfaceIOR = 1.4,
|
||||
float SubsurfaceAnisotropy = 0.0,
|
||||
float Metallic = 0.0,
|
||||
|
@ -47,21 +47,21 @@ shader node_principled_bsdf(string distribution = "multi_ggx",
|
|||
}
|
||||
|
||||
if (Metallic < 1.0 && Transmission < 1.0) {
|
||||
color diffuse_color = mix(BaseColor, SubsurfaceColor, Subsurface);
|
||||
BSDF = BaseColor * diffuse(Normal);
|
||||
if (Subsurface > 1e-5) {
|
||||
BSDF = diffuse_color * bssrdf(subsurface_method,
|
||||
Normal,
|
||||
Subsurface * SubsurfaceRadius,
|
||||
diffuse_color,
|
||||
"roughness",
|
||||
Roughness,
|
||||
"ior",
|
||||
SubsurfaceIOR,
|
||||
"anisotropy",
|
||||
SubsurfaceAnisotropy);
|
||||
}
|
||||
else {
|
||||
BSDF = diffuse_color * diffuse(Normal);
|
||||
vector radius = SubsurfaceScale * SubsurfaceRadius;
|
||||
float subsurface_ior = (subsurface_method == "random_walk") ? SubsurfaceIOR : IOR;
|
||||
closure color SubsurfBSDF = bssrdf(subsurface_method,
|
||||
Normal,
|
||||
SubsurfaceScale * SubsurfaceRadius,
|
||||
BaseColor,
|
||||
"roughness",
|
||||
Roughness,
|
||||
"ior",
|
||||
subsurface_ior,
|
||||
"anisotropy",
|
||||
SubsurfaceAnisotropy);
|
||||
BSDF = mix(BSDF, BaseColor * SubsurfBSDF, Subsurface);
|
||||
}
|
||||
|
||||
color f0 = color(F0_from_ior(IOR));
|
||||
|
|
|
@ -22,7 +22,6 @@ ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, u
|
|||
read_node(kg, &offset);
|
||||
read_node(kg, &offset);
|
||||
read_node(kg, &offset);
|
||||
read_node(kg, &offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
|
@ -71,7 +70,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
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,
|
||||
anisotropic_rotation_offset, coat_tint_offset, dummy;
|
||||
anisotropic_rotation_offset, coat_tint_offset, coat_normal_offset, dummy;
|
||||
uint4 data_node2 = read_node(kg, &offset);
|
||||
|
||||
float3 T = stack_load_float3(stack, data_node.y);
|
||||
|
@ -82,8 +81,11 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
&anisotropic_offset);
|
||||
svm_unpack_node_uchar4(
|
||||
data_node.w, &sheen_offset, &sheen_tint_offset, &sheen_roughness_offset, &dummy);
|
||||
svm_unpack_node_uchar4(
|
||||
data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &dummy);
|
||||
svm_unpack_node_uchar4(data_node2.x,
|
||||
&eta_offset,
|
||||
&transmission_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);
|
||||
|
||||
|
@ -118,27 +120,14 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
__uint_as_float(data_base_color.z),
|
||||
__uint_as_float(data_base_color.w));
|
||||
|
||||
// get the additional coat normal and subsurface scattering radius
|
||||
uint4 data_cn_ssr = read_node(kg, &offset);
|
||||
float3 coat_normal = stack_valid(data_cn_ssr.x) ? stack_load_float3(stack, data_cn_ssr.x) :
|
||||
sd->N;
|
||||
coat_normal = maybe_ensure_valid_specular_reflection(sd, coat_normal);
|
||||
float3 subsurface_radius = stack_valid(data_cn_ssr.y) ?
|
||||
stack_load_float3(stack, data_cn_ssr.y) :
|
||||
one_float3();
|
||||
float subsurface_ior = stack_valid(data_cn_ssr.z) ? stack_load_float(stack, data_cn_ssr.z) :
|
||||
1.4f;
|
||||
float subsurface_anisotropy = stack_valid(data_cn_ssr.w) ?
|
||||
stack_load_float(stack, data_cn_ssr.w) :
|
||||
0.0f;
|
||||
// get the subsurface scattering data
|
||||
uint4 data_subsurf = read_node(kg, &offset);
|
||||
|
||||
// get the subsurface color
|
||||
uint4 data_subsurface_color = read_node(kg, &offset);
|
||||
float3 subsurface_color = stack_valid(data_subsurface_color.x) ?
|
||||
stack_load_float3(stack, data_subsurface_color.x) :
|
||||
make_float3(__uint_as_float(data_subsurface_color.y),
|
||||
__uint_as_float(data_subsurface_color.z),
|
||||
__uint_as_float(data_subsurface_color.w));
|
||||
// get the additional coat normal
|
||||
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);
|
||||
|
||||
Spectrum weight = closure_weight * mix_weight;
|
||||
|
||||
|
@ -327,44 +316,38 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
/* Diffuse component */
|
||||
float3 diffuse_color = mix(base_color, subsurface_color, subsurface);
|
||||
/* Diffuse/Subsurface component */
|
||||
#ifdef __SUBSURFACE__
|
||||
/* disable in case of diffuse ancestor, can't see it well then and
|
||||
* adds considerably noise due to probabilities of continuing path
|
||||
* getting lower and lower */
|
||||
if ((subsurface > CLOSURE_WEIGHT_CUTOFF) && !(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)) {
|
||||
/* Skip in case of extremely low albedo. */
|
||||
if (fabsf(average(diffuse_color)) > CLOSURE_WEIGHT_CUTOFF) {
|
||||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, rgb_to_spectrum(diffuse_color) * weight);
|
||||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd,
|
||||
rgb_to_spectrum(base_color) * subsurface * weight);
|
||||
if (bssrdf) {
|
||||
float3 subsurface_radius = stack_load_float3(stack, data_subsurf.y);
|
||||
float subsurface_scale = stack_load_float(stack, data_subsurf.z);
|
||||
|
||||
if (bssrdf) {
|
||||
bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface);
|
||||
bssrdf->albedo = rgb_to_spectrum(diffuse_color);
|
||||
bssrdf->N = N;
|
||||
bssrdf->roughness = roughness;
|
||||
|
||||
/* Clamps protecting against bad/extreme and non physical values. */
|
||||
subsurface_ior = clamp(subsurface_ior, 1.01f, 3.8f);
|
||||
bssrdf->anisotropy = clamp(subsurface_anisotropy, 0.0f, 0.9f);
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bssrdf_setup(sd, bssrdf, subsurface_method, subsurface_ior);
|
||||
}
|
||||
bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface_scale);
|
||||
bssrdf->albedo = rgb_to_spectrum(base_color);
|
||||
bssrdf->N = N;
|
||||
bssrdf->alpha = sqr(roughness);
|
||||
bssrdf->ior = eta;
|
||||
bssrdf->anisotropy = stack_load_float(stack, data_subsurf.w);
|
||||
if (subsurface_method == CLOSURE_BSSRDF_RANDOM_WALK_ID) {
|
||||
bssrdf->ior = stack_load_float(stack, data_subsurf.x);
|
||||
}
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method);
|
||||
}
|
||||
else
|
||||
#else
|
||||
subsurface = 0.0f;
|
||||
#endif
|
||||
{
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), rgb_to_spectrum(diffuse_color) * weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), rgb_to_spectrum(base_color) * (1.0f - subsurface) * weight);
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
|
||||
/* setup bsdf */
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
}
|
||||
/* setup bsdf */
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -797,22 +780,14 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
|
||||
|
||||
if (bssrdf) {
|
||||
/* disable in case of diffuse ancestor, can't see it well then and
|
||||
* adds considerably noise due to probabilities of continuing path
|
||||
* getting lower and lower */
|
||||
if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
|
||||
param1 = 0.0f;
|
||||
|
||||
bssrdf->radius = rgb_to_spectrum(stack_load_float3(stack, data_node.z) * param1);
|
||||
bssrdf->albedo = closure_weight;
|
||||
bssrdf->N = N;
|
||||
bssrdf->roughness = FLT_MAX;
|
||||
bssrdf->ior = param2;
|
||||
bssrdf->alpha = 1.0f;
|
||||
bssrdf->anisotropy = stack_load_float(stack, data_node.w);
|
||||
|
||||
const float subsurface_ior = clamp(param2, 1.01f, 3.8f);
|
||||
const float subsurface_anisotropy = stack_load_float(stack, data_node.w);
|
||||
bssrdf->anisotropy = clamp(subsurface_anisotropy, 0.0f, 0.9f);
|
||||
|
||||
sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)type, subsurface_ior);
|
||||
sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, (ClosureType)type);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -2660,10 +2660,10 @@ NODE_DEFINE(PrincipledBsdfNode)
|
|||
subsurface_method_enum,
|
||||
CLOSURE_BSSRDF_RANDOM_WALK_ID);
|
||||
|
||||
SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
|
||||
SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
|
||||
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(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);
|
||||
|
@ -2774,57 +2774,38 @@ void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attribu
|
|||
ShaderNode::attributes(shader, attributes);
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
||||
ShaderInput *p_metallic,
|
||||
ShaderInput *p_subsurface,
|
||||
ShaderInput *p_subsurface_radius,
|
||||
ShaderInput *p_subsurface_ior,
|
||||
ShaderInput *p_subsurface_anisotropy,
|
||||
ShaderInput *p_specular,
|
||||
ShaderInput *p_roughness,
|
||||
ShaderInput *p_specular_tint,
|
||||
ShaderInput *p_anisotropic,
|
||||
ShaderInput *p_sheen,
|
||||
ShaderInput *p_sheen_roughness,
|
||||
ShaderInput *p_sheen_tint,
|
||||
ShaderInput *p_coat,
|
||||
ShaderInput *p_coat_roughness,
|
||||
ShaderInput *p_coat_ior,
|
||||
ShaderInput *p_coat_tint,
|
||||
ShaderInput *p_ior,
|
||||
ShaderInput *p_transmission,
|
||||
ShaderInput *p_anisotropic_rotation)
|
||||
void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
ShaderInput *base_color_in = input("Base Color");
|
||||
ShaderInput *subsurface_color_in = input("Subsurface Color");
|
||||
ShaderInput *normal_in = input("Normal");
|
||||
ShaderInput *coat_normal_in = input("Coat Normal");
|
||||
ShaderInput *tangent_in = input("Tangent");
|
||||
|
||||
ShaderInput *p_metallic = input("Metallic");
|
||||
ShaderInput *p_subsurface = input("Subsurface");
|
||||
|
||||
float3 weight = one_float3();
|
||||
|
||||
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
|
||||
|
||||
int normal_offset = compiler.stack_assign_if_linked(normal_in);
|
||||
int coat_normal_offset = compiler.stack_assign_if_linked(coat_normal_in);
|
||||
int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
|
||||
int specular_offset = compiler.stack_assign(p_specular);
|
||||
int roughness_offset = compiler.stack_assign(p_roughness);
|
||||
int specular_tint_offset = compiler.stack_assign(p_specular_tint);
|
||||
int anisotropic_offset = compiler.stack_assign(p_anisotropic);
|
||||
int sheen_offset = compiler.stack_assign(p_sheen);
|
||||
int sheen_roughness_offset = compiler.stack_assign(p_sheen_roughness);
|
||||
int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
|
||||
int coat_offset = compiler.stack_assign(p_coat);
|
||||
int coat_roughness_offset = compiler.stack_assign(p_coat_roughness);
|
||||
int coat_ior_offset = compiler.stack_assign(p_coat_ior);
|
||||
int coat_tint_offset = compiler.stack_assign(p_coat_tint);
|
||||
int ior_offset = compiler.stack_assign(p_ior);
|
||||
int transmission_offset = compiler.stack_assign(p_transmission);
|
||||
int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
|
||||
int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
|
||||
int subsurface_ior_offset = compiler.stack_assign(p_subsurface_ior);
|
||||
int subsurface_anisotropy_offset = compiler.stack_assign(p_subsurface_anisotropy);
|
||||
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 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_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_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 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"));
|
||||
int subsurface_ior_offset = compiler.stack_assign(input("Subsurface IOR"));
|
||||
int subsurface_anisotropy_offset = compiler.stack_assign(input("Subsurface Anisotropy"));
|
||||
|
||||
compiler.add_node(NODE_CLOSURE_BSDF,
|
||||
compiler.encode_uchar4(closure,
|
||||
|
@ -2844,7 +2825,7 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
|||
|
||||
compiler.add_node(
|
||||
compiler.encode_uchar4(
|
||||
ior_offset, transmission_offset, anisotropic_rotation_offset, SVM_STACK_INVALID),
|
||||
ior_offset, transmission_offset, anisotropic_rotation_offset, coat_normal_offset),
|
||||
distribution,
|
||||
subsurface_method,
|
||||
compiler.encode_uchar4(
|
||||
|
@ -2858,42 +2839,10 @@ void PrincipledBsdfNode::compile(SVMCompiler &compiler,
|
|||
__float_as_int(bc_default.y),
|
||||
__float_as_int(bc_default.z));
|
||||
|
||||
compiler.add_node(coat_normal_offset,
|
||||
compiler.add_node(subsurface_ior_offset,
|
||||
subsurface_radius_offset,
|
||||
subsurface_ior_offset,
|
||||
subsurface_scale_offset,
|
||||
subsurface_anisotropy_offset);
|
||||
|
||||
float3 ss_default = get_float3(subsurface_color_in->socket_type);
|
||||
|
||||
compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) :
|
||||
SVM_STACK_INVALID),
|
||||
__float_as_int(ss_default.x),
|
||||
__float_as_int(ss_default.y),
|
||||
__float_as_int(ss_default.z));
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
compile(compiler,
|
||||
input("Metallic"),
|
||||
input("Subsurface"),
|
||||
input("Subsurface Radius"),
|
||||
input("Subsurface IOR"),
|
||||
input("Subsurface Anisotropy"),
|
||||
input("Specular"),
|
||||
input("Roughness"),
|
||||
input("Specular Tint"),
|
||||
input("Anisotropic"),
|
||||
input("Sheen"),
|
||||
input("Sheen Roughness"),
|
||||
input("Sheen Tint"),
|
||||
input("Coat"),
|
||||
input("Coat Roughness"),
|
||||
input("Coat IOR"),
|
||||
input("Coat Tint"),
|
||||
input("IOR"),
|
||||
input("Transmission"),
|
||||
input("Anisotropic Rotation"));
|
||||
}
|
||||
|
||||
void PrincipledBsdfNode::compile(OSLCompiler &compiler)
|
||||
|
|
|
@ -517,30 +517,10 @@ class PrincipledBsdfNode : public BsdfBaseNode {
|
|||
void expand(ShaderGraph *graph);
|
||||
bool has_surface_bssrdf();
|
||||
bool has_bssrdf_bump();
|
||||
void compile(SVMCompiler &compiler,
|
||||
ShaderInput *metallic,
|
||||
ShaderInput *subsurface,
|
||||
ShaderInput *subsurface_radius,
|
||||
ShaderInput *subsurface_ior,
|
||||
ShaderInput *subsurface_anisotropy,
|
||||
ShaderInput *specular,
|
||||
ShaderInput *roughness,
|
||||
ShaderInput *specular_tint,
|
||||
ShaderInput *anisotropic,
|
||||
ShaderInput *sheen,
|
||||
ShaderInput *sheen_roughness,
|
||||
ShaderInput *sheen_tint,
|
||||
ShaderInput *coat,
|
||||
ShaderInput *coat_roughness,
|
||||
ShaderInput *coat_ior,
|
||||
ShaderInput *coat_tint,
|
||||
ShaderInput *ior,
|
||||
ShaderInput *transmission,
|
||||
ShaderInput *anisotropic_rotation);
|
||||
|
||||
NODE_SOCKET_API(float3, base_color)
|
||||
NODE_SOCKET_API(float3, subsurface_color)
|
||||
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)
|
||||
|
|
|
@ -580,6 +580,86 @@ static void version_principled_bsdf_sheen(bNodeTree *ntree)
|
|||
}
|
||||
}
|
||||
|
||||
/* Convert subsurface inputs on the Principled BSDF. */
|
||||
static void version_principled_bsdf_subsurface(bNodeTree *ntree)
|
||||
{
|
||||
/* - Create Subsurface Scale input
|
||||
* - If a node's Subsurface input was connected or nonzero:
|
||||
* - Make the Base Color a mix of old Base Color and Subsurface Color,
|
||||
* using Subsurface as the mix factor
|
||||
* - Move Subsurface link and default value to the new Subsurface Scale input
|
||||
* - Set the Subsurface input to 1.0
|
||||
* - Remove Subsurface Color input
|
||||
*/
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != SH_NODE_BSDF_PRINCIPLED) {
|
||||
continue;
|
||||
}
|
||||
if (nodeFindSocket(node, SOCK_IN, "Subsurface Scale")) {
|
||||
/* Node is already updated. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add Scale input */
|
||||
bNodeSocket *scale_in = nodeAddStaticSocket(
|
||||
ntree, node, SOCK_IN, SOCK_FLOAT, PROP_DISTANCE, "Subsurface Scale", "Subsurface Scale");
|
||||
|
||||
bNodeSocket *subsurf = nodeFindSocket(node, SOCK_IN, "Subsurface");
|
||||
float *subsurf_val = version_cycles_node_socket_float_value(subsurf);
|
||||
*version_cycles_node_socket_float_value(scale_in) = *subsurf_val;
|
||||
|
||||
if (subsurf->link == nullptr && *subsurf_val == 0.0f) {
|
||||
/* Node doesn't use Subsurf, we're done here. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fix up Subsurface Color input */
|
||||
bNodeSocket *base_col = nodeFindSocket(node, SOCK_IN, "Base Color");
|
||||
bNodeSocket *subsurf_col = nodeFindSocket(node, SOCK_IN, "Subsurface Color");
|
||||
float *base_col_val = version_cycles_node_socket_rgba_value(base_col);
|
||||
float *subsurf_col_val = version_cycles_node_socket_rgba_value(subsurf_col);
|
||||
/* If any of the three inputs is dynamic, we need a Mix node. */
|
||||
if (subsurf->link || subsurf_col->link || base_col->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), base_col_val);
|
||||
copy_v4_v4(version_cycles_node_socket_rgba_value(b_in), subsurf_col_val);
|
||||
*version_cycles_node_socket_float_value(fac_in) = *subsurf_val;
|
||||
|
||||
if (base_col->link) {
|
||||
nodeAddLink(ntree, base_col->link->fromnode, base_col->link->fromsock, mix, a_in);
|
||||
nodeRemLink(ntree, base_col->link);
|
||||
}
|
||||
if (subsurf_col->link) {
|
||||
nodeAddLink(ntree, subsurf_col->link->fromnode, subsurf_col->link->fromsock, mix, b_in);
|
||||
nodeRemLink(ntree, subsurf_col->link);
|
||||
}
|
||||
if (subsurf->link) {
|
||||
nodeAddLink(ntree, subsurf->link->fromnode, subsurf->link->fromsock, mix, fac_in);
|
||||
nodeAddLink(ntree, subsurf->link->fromnode, subsurf->link->fromsock, node, scale_in);
|
||||
nodeRemLink(ntree, subsurf->link);
|
||||
}
|
||||
nodeAddLink(ntree, mix, result_out, node, base_col);
|
||||
}
|
||||
/* Mix the fixed values. */
|
||||
interp_v4_v4v4(base_col_val, base_col_val, subsurf_col_val, *subsurf_val);
|
||||
|
||||
/* Set node to 100% subsurface, 0% diffuse. */
|
||||
*subsurf_val = 1.0f;
|
||||
|
||||
/* Delete Subsurface Color input */
|
||||
nodeRemoveSocket(ntree, node, subsurf_col);
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace old Principled Hair BSDF as a variant in the new Principled Hair BSDF. */
|
||||
static void version_replace_principled_hair_model(bNodeTree *ntree)
|
||||
{
|
||||
|
@ -1096,6 +1176,8 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
if (ntree->type == NTREE_SHADER) {
|
||||
/* Convert coat inputs on the Principled BSDF. */
|
||||
version_principled_bsdf_coat(ntree);
|
||||
/* Convert subsurface inputs on the Principled BSDF. */
|
||||
version_principled_bsdf_subsurface(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
|
|
|
@ -20,8 +20,8 @@ float principled_sheen(float NV, float rough)
|
|||
|
||||
void node_bsdf_principled(vec4 base_color,
|
||||
float subsurface,
|
||||
float subsurface_scale,
|
||||
vec3 subsurface_radius,
|
||||
vec4 subsurface_color,
|
||||
float subsurface_ior,
|
||||
float subsurface_anisotropy,
|
||||
float metallic,
|
||||
|
@ -155,10 +155,9 @@ void node_bsdf_principled(vec4 base_color,
|
|||
|
||||
/* Diffuse component */
|
||||
if (true) {
|
||||
vec3 diffuse_color = mix(base_color.rgb, subsurface_color.rgb, subsurface);
|
||||
diffuse_data.sss_radius = subsurface_radius * subsurface;
|
||||
diffuse_data.sss_radius = subsurface_radius * subsurface_scale;
|
||||
diffuse_data.sss_id = uint(do_sss);
|
||||
diffuse_data.color += weight * diffuse_color * coat_tint.rgb;
|
||||
diffuse_data.color += weight * base_color.rgb * coat_tint.rgb;
|
||||
}
|
||||
|
||||
/* Adjust the weight of picking the closure. */
|
||||
|
|
|
@ -25,21 +25,31 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
.subtype(PROP_FACTOR)
|
||||
.description(
|
||||
"Blend between diffuse surface and subsurface scattering. "
|
||||
"Typically should be zero or one (either fully diffuse or subsurface)");
|
||||
#define SOCK_SUBSURFACE_ID 1
|
||||
b.add_input<decl::Float>("Subsurface Scale")
|
||||
.default_value(0.05f)
|
||||
.min(0.0f)
|
||||
.max(10.0f)
|
||||
.subtype(PROP_DISTANCE)
|
||||
.description("Scale of the subsurface scattering (multiplied with Radius)");
|
||||
#define SOCK_SUBSURFACE_SCALE_ID 2
|
||||
b.add_input<decl::Vector>("Subsurface Radius")
|
||||
.default_value({1.0f, 0.2f, 0.1f})
|
||||
.min(0.0f)
|
||||
.max(100.0f)
|
||||
.compact();
|
||||
#define SOCK_SUBSURFACE_RADIUS_ID 2
|
||||
b.add_input<decl::Color>("Subsurface Color").default_value({0.8f, 0.8f, 0.8f, 1.0f});
|
||||
#define SOCK_SUBSURFACE_COLOR_ID 3
|
||||
.compact()
|
||||
.description("Scattering radius to use for subsurface component (multiplied with Scale)");
|
||||
#define SOCK_SUBSURFACE_RADIUS_ID 3
|
||||
b.add_input<decl::Float>("Subsurface IOR")
|
||||
.default_value(1.4f)
|
||||
.min(1.01f)
|
||||
.max(3.8f)
|
||||
.subtype(PROP_FACTOR);
|
||||
.subtype(PROP_FACTOR)
|
||||
.description("Index of refraction used for rays that enter the subsurface component");
|
||||
#define SOCK_SUBSURFACE_IOR_ID 4
|
||||
b.add_input<decl::Float>("Subsurface Anisotropy")
|
||||
.default_value(0.0f)
|
||||
|
@ -266,11 +276,12 @@ static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
|
|||
{
|
||||
const int sss_method = node->custom2;
|
||||
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
||||
if (STR_ELEM(sock->name, "Subsurface IOR", "Subsurface Anisotropy")) {
|
||||
bke::nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY);
|
||||
}
|
||||
}
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
nodeFindSocket(node, SOCK_IN, "Subsurface IOR"),
|
||||
sss_method == SHD_SUBSURFACE_RANDOM_WALK);
|
||||
bke::nodeSetSocketAvailability(ntree,
|
||||
nodeFindSocket(node, SOCK_IN, "Subsurface Anisotropy"),
|
||||
sss_method != SHD_SUBSURFACE_BURLEY);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_shader_bsdf_principled_cc
|
||||
|
|
Loading…
Reference in New Issue
Unused variable.