Split `model_type` into `cross_section_type` and `distribution_type`
Also disable analytical GGX R because it seems confusing
This commit is contained in:
parent
08684b2601
commit
f88b91fe61
|
@ -668,11 +668,16 @@ static ShaderNode *add_node(Scene *scene,
|
|||
"parametrization",
|
||||
NODE_MICROFACET_HAIR_NUM,
|
||||
NODE_MICROFACET_HAIR_REFLECTANCE));
|
||||
microfacet_hair->set_model_type(
|
||||
(NodeMicrofacetHairModelType)get_enum(b_microfacet_hair_node.ptr,
|
||||
"model_type",
|
||||
NODE_MICROFACET_HAIR_MODEL_TYPE_NUM,
|
||||
NODE_MICROFACET_HAIR_CIRCULAR_GGX));
|
||||
microfacet_hair->set_cross_section_type(
|
||||
(NodeMicrofacetHairCrossSectionType)get_enum(b_microfacet_hair_node.ptr,
|
||||
"cross_section_type",
|
||||
NODE_MICROFACET_HAIR_CROSS_SECTION_TYPE_NUM,
|
||||
NODE_MICROFACET_HAIR_CIRCULAR));
|
||||
microfacet_hair->set_distribution_type(
|
||||
(NodeMicrofacetHairDistributionType)get_enum(b_microfacet_hair_node.ptr,
|
||||
"distribution_type",
|
||||
NODE_MICROFACET_HAIR_DISTRIBUTION_TYPE_NUM,
|
||||
NODE_MICROFACET_HAIR_GGX));
|
||||
node = microfacet_hair;
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
|
||||
|
|
|
@ -37,8 +37,11 @@ typedef struct MicrofacetHairBSDF {
|
|||
/* Blur. */
|
||||
float blur;
|
||||
|
||||
/* Circular/Ellipitic and GGX/Beckmann. */
|
||||
int model_type;
|
||||
/* GGX/Beckmann. */
|
||||
int distribution_type;
|
||||
|
||||
/* Circular/Elliptical */
|
||||
int cross_section_type;
|
||||
|
||||
/* Extra closure. */
|
||||
ccl_private MicrofacetHairExtra *extra;
|
||||
|
@ -72,8 +75,7 @@ ccl_device int bsdf_microfacet_hair_setup(ccl_private ShaderData *sd,
|
|||
kernel_assert(isfinite_safe(X));
|
||||
kernel_assert(isfinite_safe(h));
|
||||
|
||||
if (bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_GGX ||
|
||||
bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN) {
|
||||
if (bsdf->cross_section_type == NODE_MICROFACET_HAIR_ELLIPTIC) {
|
||||
/* Local frame is independent of the ray direction for elliptical hairs. */
|
||||
bsdf->extra->geom.w = h;
|
||||
}
|
||||
|
@ -329,8 +331,7 @@ ccl_device float3 bsdf_microfacet_hair_eval_r_circular(ccl_private const ShaderC
|
|||
const float tilt = -bsdf->alpha;
|
||||
const float roughness = bsdf->roughness;
|
||||
const float eta = bsdf->eta;
|
||||
const bool beckmann = (bsdf->model_type == NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN);
|
||||
const bool analytical_ggx = (bsdf->model_type == NODE_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC);
|
||||
const bool beckmann = (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN);
|
||||
|
||||
float3 R = zero_float3();
|
||||
if (bsdf->extra->R <= 0.0f)
|
||||
|
@ -359,68 +360,26 @@ ccl_device float3 bsdf_microfacet_hair_eval_r_circular(ccl_private const ShaderC
|
|||
|
||||
float integral = 0.0f;
|
||||
|
||||
/* analytical for ggx (no masking term) */
|
||||
if (analytical_ggx) {
|
||||
const float phi_h = dir_phi(wh);
|
||||
const float d_max = phi_h - phi_m_max;
|
||||
const float d_min = phi_h - phi_m_min;
|
||||
/* Maximal sample resolution. */
|
||||
float res = roughness * 0.7f;
|
||||
/* Number of intervals should be even. */
|
||||
const size_t intervals = 2 * (size_t)ceilf((phi_m_max - phi_m_min) / res * 0.5f);
|
||||
|
||||
const float roughness_squared = roughness * roughness;
|
||||
/* Modified resolution based on numbers of intervals. */
|
||||
res = (phi_m_max - phi_m_min) / float(intervals);
|
||||
|
||||
float sm, cm;
|
||||
fast_sincosf(tilt, &sm, &cm);
|
||||
/* Integrate using Simpson's rule. */
|
||||
for (size_t i = 0; i <= intervals; i++) {
|
||||
|
||||
const float C = sqrtf(1.0f - roughness_squared);
|
||||
const float A = cm * cos_theta(wh) * C;
|
||||
const float B = sm * sin_theta(wh) * C;
|
||||
const float A2 = sqr(A);
|
||||
const float B2 = sqr(B);
|
||||
const float tmp1 = 1.0f / sqrtf(sqr(B - 1.0f) - A2);
|
||||
const float tmp2 = 1.0f / sqrtf(sqr(B + 1.0f) - A2);
|
||||
const float phi_m = phi_m_min + i * res;
|
||||
const float3 wm = sph_dir(tilt, phi_m);
|
||||
|
||||
float smax, cmax, smin, cmin;
|
||||
fast_sincosf(d_max, &smax, &cmax);
|
||||
fast_sincosf(d_min, &smin, &cmin);
|
||||
|
||||
const float tmax = smax / (1.0f + cmax);
|
||||
const float tmin = smin / (1.0f + cmin);
|
||||
|
||||
const float temp1 = 2.0f * (A2 - B2 + 3.0f * B - 2) * sqr(tmp1) * tmp1 *
|
||||
(atanf((A - B + 1.0f) * tmp1 * tmax) -
|
||||
atanf((A - B + 1.0f) * tmp1 * tmin));
|
||||
const float temp2 = 2.0f * (A2 - B2 - 3.0f * B - 2) * sqr(tmp2) * tmp2 *
|
||||
(atanf((B - A + 1.0f) * tmp2 * tmax) -
|
||||
atanf((B - A + 1.0f) * tmp2 * tmin));
|
||||
const float temp3 = A * sqr(tmp1) *
|
||||
(smax / (A * cmax + B - 1.0f) - smin / (A * cmin + B - 1.0f));
|
||||
const float temp4 = A * sqr(tmp2) *
|
||||
(smax / (A * cmax + B + 1.0f) - smin / (A * cmin + B + 1.0f));
|
||||
|
||||
integral = roughness_squared * M_1_PI_F * 0.5f * (temp1 + temp2 + temp3 + temp4);
|
||||
}
|
||||
else { /* Falls back to numerical integration. */
|
||||
/* Maximal sample resolution. */
|
||||
float res = roughness * 0.7f;
|
||||
/* Number of intervals should be even. */
|
||||
const size_t intervals = 2 * (size_t)ceilf((phi_m_max - phi_m_min) / res * 0.5f);
|
||||
|
||||
/* Modified resolution based on numbers of intervals. */
|
||||
res = (phi_m_max - phi_m_min) / float(intervals);
|
||||
|
||||
/* Integrate using Simpson's rule. */
|
||||
for (size_t i = 0; i <= intervals; i++) {
|
||||
|
||||
const float phi_m = phi_m_min + i * res;
|
||||
const float3 wm = sph_dir(tilt, phi_m);
|
||||
|
||||
if (microfacet_visible(wi, wo, make_float3(wm.x, 0.0f, wm.z), wh)) {
|
||||
const float weight = (i == 0 || i == intervals) ? 0.5f : (i % 2 + 1);
|
||||
integral += weight * D(beckmann, roughness, wm, wh) *
|
||||
G(beckmann, roughness, wi, wo, wm, wh);
|
||||
}
|
||||
if (microfacet_visible(wi, wo, make_float3(wm.x, 0.0f, wm.z), wh)) {
|
||||
const float weight = (i == 0 || i == intervals) ? 0.5f : (i % 2 + 1);
|
||||
integral += weight * D(beckmann, roughness, wm, wh) * G(beckmann, roughness, wi, wo, wm, wh);
|
||||
}
|
||||
integral *= (2.0f / 3.0f * res);
|
||||
}
|
||||
integral *= (2.0f / 3.0f * res);
|
||||
|
||||
const float F = fresnel_dielectric_cos(dot(wi, wh), eta);
|
||||
|
||||
|
@ -438,7 +397,7 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt_circular(KernelGlobals kg,
|
|||
const float tilt = -bsdf->alpha;
|
||||
const float roughness = bsdf->roughness;
|
||||
const float eta = bsdf->eta;
|
||||
const bool beckmann = (bsdf->model_type == NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN);
|
||||
const bool beckmann = (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN);
|
||||
|
||||
if (bsdf->extra->TT <= 0.0f && bsdf->extra->TRT <= 0.0f)
|
||||
return zero_float3();
|
||||
|
@ -652,7 +611,7 @@ ccl_device int bsdf_microfacet_hair_sample_circular(const KernelGlobals kg,
|
|||
|
||||
const float tilt = -bsdf->alpha;
|
||||
const float roughness = bsdf->roughness;
|
||||
const bool beckmann = (bsdf->model_type == NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN);
|
||||
const bool beckmann = (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN);
|
||||
|
||||
/* generate sample */
|
||||
float sample_lobe = randu;
|
||||
|
@ -833,7 +792,7 @@ ccl_device float3 bsdf_microfacet_hair_eval_r_elliptic(ccl_private const ShaderC
|
|||
const float tilt = -bsdf->alpha;
|
||||
const float roughness = bsdf->roughness;
|
||||
const float eta = bsdf->eta;
|
||||
const bool beckmann = (bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN);
|
||||
const bool beckmann = (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN);
|
||||
|
||||
float3 R = zero_float3();
|
||||
if (bsdf->extra->R <= 0.0f) {
|
||||
|
@ -933,7 +892,7 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt_elliptic(KernelGlobals kg,
|
|||
const float tilt = -bsdf->alpha;
|
||||
const float roughness = bsdf->roughness;
|
||||
const float eta = bsdf->eta;
|
||||
const bool beckmann = (bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN);
|
||||
const bool beckmann = (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN);
|
||||
|
||||
if (bsdf->extra->TT <= 0.0f && bsdf->extra->TRT <= 0.0f) {
|
||||
return zero_float3();
|
||||
|
@ -1203,7 +1162,7 @@ ccl_device int bsdf_microfacet_hair_sample_elliptic(const KernelGlobals kg,
|
|||
|
||||
const float tilt = -bsdf->alpha;
|
||||
const float roughness = bsdf->roughness;
|
||||
const bool beckmann = (bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN);
|
||||
const bool beckmann = (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN);
|
||||
|
||||
/* generate sample */
|
||||
float sample_lobe = randu;
|
||||
|
@ -1387,17 +1346,12 @@ ccl_device Spectrum bsdf_microfacet_hair_eval(KernelGlobals kg,
|
|||
{
|
||||
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)sc;
|
||||
|
||||
switch (bsdf->model_type) {
|
||||
case NODE_MICROFACET_HAIR_CIRCULAR_GGX:
|
||||
case NODE_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC:
|
||||
case NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN:
|
||||
return bsdf_microfacet_hair_eval_circular(kg, sd, sc, omega_in, pdf);
|
||||
case NODE_MICROFACET_HAIR_ELLIPTIC_GGX:
|
||||
case NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN:
|
||||
return bsdf_microfacet_hair_eval_elliptic(kg, sd, sc, omega_in, pdf);
|
||||
default:
|
||||
return bsdf_microfacet_hair_eval_circular(kg, sd, sc, omega_in, pdf);
|
||||
if (bsdf->cross_section_type == NODE_MICROFACET_HAIR_CIRCULAR ||
|
||||
bsdf->extra->aspect_ratio == 1.0f) {
|
||||
return bsdf_microfacet_hair_eval_circular(kg, sd, sc, omega_in, pdf);
|
||||
}
|
||||
|
||||
return bsdf_microfacet_hair_eval_elliptic(kg, sd, sc, omega_in, pdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_hair_sample(KernelGlobals kg,
|
||||
|
@ -1413,20 +1367,14 @@ ccl_device int bsdf_microfacet_hair_sample(KernelGlobals kg,
|
|||
{
|
||||
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)sc;
|
||||
|
||||
switch (bsdf->model_type) {
|
||||
case NODE_MICROFACET_HAIR_CIRCULAR_GGX:
|
||||
case NODE_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC:
|
||||
case NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN:
|
||||
return bsdf_microfacet_hair_sample_circular(
|
||||
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
case NODE_MICROFACET_HAIR_ELLIPTIC_GGX:
|
||||
case NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN:
|
||||
return bsdf_microfacet_hair_sample_elliptic(
|
||||
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
default:
|
||||
return bsdf_microfacet_hair_sample_circular(
|
||||
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
if (bsdf->cross_section_type == NODE_MICROFACET_HAIR_CIRCULAR ||
|
||||
bsdf->extra->aspect_ratio == 1.0f) {
|
||||
return bsdf_microfacet_hair_sample_circular(
|
||||
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
}
|
||||
|
||||
return bsdf_microfacet_hair_sample_elliptic(
|
||||
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
}
|
||||
|
||||
/* Implements Filter Glossy by capping the effective roughness. */
|
||||
|
|
|
@ -43,7 +43,8 @@ shader node_microfacet_hair_bsdf(color Color = color(0.017513, 0.005763, 0.00205
|
|||
color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
|
||||
normal Normal = Ng,
|
||||
string parametrization = "Direct Coloring",
|
||||
string model_type = "Microfacet Circular GGX",
|
||||
string cross_section_type = "Circular",
|
||||
string distribution_type = "GGX",
|
||||
float Offset = radians(2),
|
||||
float Roughness = 0.3,
|
||||
float RandomRoughness = 0.0,
|
||||
|
|
|
@ -899,9 +899,9 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
&melanin_redness_ofs,
|
||||
&absorption_coefficient_ofs);
|
||||
|
||||
uint tint_ofs, random_ofs, random_color_ofs, random_roughness_ofs;
|
||||
uint tint_ofs, random_ofs, random_color_ofs, cross_section_type;
|
||||
svm_unpack_node_uchar4(
|
||||
data_node3.x, &tint_ofs, &random_ofs, &random_color_ofs, &random_roughness_ofs);
|
||||
data_node3.x, &tint_ofs, &random_ofs, &random_color_ofs, &cross_section_type);
|
||||
|
||||
const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, data_node3.w);
|
||||
float random = 0.0f;
|
||||
|
@ -912,9 +912,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
random = stack_load_float_default(stack, random_ofs, data_node3.y);
|
||||
}
|
||||
|
||||
uint R_ofs, TT_ofs, TRT_ofs, model_type;
|
||||
|
||||
svm_unpack_node_uchar4(data_node4.x, &R_ofs, &TT_ofs, &TRT_ofs, &model_type);
|
||||
uint R_ofs, TT_ofs, TRT_ofs, distribution_type;
|
||||
svm_unpack_node_uchar4(data_node4.x, &R_ofs, &TT_ofs, &TRT_ofs, &distribution_type);
|
||||
float R = stack_load_float_default(stack, R_ofs, data_node4.y);
|
||||
float TT = stack_load_float_default(stack, TT_ofs, data_node4.z);
|
||||
float TRT = stack_load_float_default(stack, TRT_ofs, data_node4.w);
|
||||
|
@ -940,24 +939,17 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
float factor_random_roughness = 1.0f + 2.0f * (random - 0.5f) * random_roughness;
|
||||
float roughness = param1 * factor_random_roughness;
|
||||
|
||||
/* if (model_type >= NODE_MICROFACET_HAIR_HYBRID_NEAR_FIELD && model_type <
|
||||
* NODE_MICROFACET_HAIR_MODEL_TYPE_NUM) */
|
||||
/* model_type is a uint, so no need to compare to 0
|
||||
* (NODE_MICROFACET_HAIR_HYBRID_NEAR_FIELD), which generates a warning */
|
||||
if (model_type < NODE_MICROFACET_HAIR_MODEL_TYPE_NUM)
|
||||
bsdf->model_type = model_type;
|
||||
else
|
||||
bsdf->model_type = NODE_MICROFACET_HAIR_CIRCULAR_GGX; // default
|
||||
bsdf->cross_section_type = clamp(
|
||||
cross_section_type, NODE_MICROFACET_HAIR_CIRCULAR, NODE_MICROFACET_HAIR_ELLIPTIC);
|
||||
|
||||
if (bsdf->model_type == NODE_MICROFACET_HAIR_CIRCULAR_GGX ||
|
||||
bsdf->model_type == NODE_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC ||
|
||||
bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_GGX) {
|
||||
// empirical equivalences
|
||||
bsdf->distribution_type = clamp(
|
||||
distribution_type, NODE_MICROFACET_HAIR_GGX, NODE_MICROFACET_HAIR_BECKMANN);
|
||||
|
||||
/* Empirical equivalences compared with principled hair BSDF. */
|
||||
if (bsdf->distribution_type == NODE_MICROFACET_HAIR_GGX) {
|
||||
roughness *= 0.5f;
|
||||
}
|
||||
else if (bsdf->model_type == NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN ||
|
||||
bsdf->model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN) {
|
||||
// empirical equivalences
|
||||
else { /* bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN*/
|
||||
roughness *= 2.f / 3.f;
|
||||
}
|
||||
|
||||
|
@ -1014,8 +1006,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
if (model_type == NODE_MICROFACET_HAIR_ELLIPTIC_GGX ||
|
||||
model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN) {
|
||||
if (cross_section_type == NODE_MICROFACET_HAIR_ELLIPTIC) {
|
||||
|
||||
uint aspect_ratio_ofs, temp;
|
||||
svm_unpack_node_uchar4(data_node5.x, &aspect_ratio_ofs, &temp, &temp, &temp);
|
||||
|
|
|
@ -402,14 +402,17 @@ typedef enum NodeMicrofacetHairParametrization {
|
|||
NODE_MICROFACET_HAIR_NUM,
|
||||
} NodeMicrofacetHairParametrization;
|
||||
|
||||
typedef enum NodeMicrofacetHairModelType {
|
||||
NODE_MICROFACET_HAIR_CIRCULAR_GGX = 0,
|
||||
NODE_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC = 1,
|
||||
NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN = 2,
|
||||
NODE_MICROFACET_HAIR_ELLIPTIC_GGX = 3,
|
||||
NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN = 4,
|
||||
NODE_MICROFACET_HAIR_MODEL_TYPE_NUM,
|
||||
} NodeMicrofacetHairModelType;
|
||||
typedef enum NodeMicrofacetHairDistributionType {
|
||||
NODE_MICROFACET_HAIR_GGX = 0,
|
||||
NODE_MICROFACET_HAIR_BECKMANN = 1,
|
||||
NODE_MICROFACET_HAIR_DISTRIBUTION_TYPE_NUM,
|
||||
} NodeMicrofacetHairDistributionType;
|
||||
|
||||
typedef enum NodeMicrofacetHairCrossSectionType {
|
||||
NODE_MICROFACET_HAIR_CIRCULAR = 0,
|
||||
NODE_MICROFACET_HAIR_ELLIPTIC = 1,
|
||||
NODE_MICROFACET_HAIR_CROSS_SECTION_TYPE_NUM,
|
||||
} NodeMicrofacetHairCrossSectionType;
|
||||
|
||||
typedef enum NodeCombSepColorType {
|
||||
NODE_COMBSEP_COLOR_RGB,
|
||||
|
|
|
@ -3644,16 +3644,21 @@ NODE_DEFINE(MicrofacetHairBsdfNode)
|
|||
SOCKET_ENUM(
|
||||
parametrization, "Parametrization", parametrization_enum, NODE_MICROFACET_HAIR_REFLECTANCE);
|
||||
|
||||
/* Hair integration mode specified as enum. */
|
||||
static NodeEnum model_type_enum;
|
||||
model_type_enum.insert("Microfacet Circular GGX", NODE_MICROFACET_HAIR_CIRCULAR_GGX);
|
||||
model_type_enum.insert("Microfacet Circular GGX Analytical",
|
||||
NODE_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC);
|
||||
model_type_enum.insert("Microfacet Circular Beckmann", NODE_MICROFACET_HAIR_CIRCULAR_BECKMANN);
|
||||
model_type_enum.insert("Microfacet Elliptical GGX", NODE_MICROFACET_HAIR_ELLIPTIC_GGX);
|
||||
model_type_enum.insert("Microfacet Elliptical Beckmann", NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN);
|
||||
/* Hair microfacet normal distribution mode specified as enum. */
|
||||
static NodeEnum distribution_type_enum;
|
||||
distribution_type_enum.insert("GGX", NODE_MICROFACET_HAIR_GGX);
|
||||
distribution_type_enum.insert("Beckmann", NODE_MICROFACET_HAIR_BECKMANN);
|
||||
SOCKET_ENUM(
|
||||
distribution_type, "Distribution Type", distribution_type_enum, NODE_MICROFACET_HAIR_GGX);
|
||||
|
||||
SOCKET_ENUM(model_type, "model_type", model_type_enum, NODE_MICROFACET_HAIR_CIRCULAR_GGX);
|
||||
/* Hair cross-section type specified as enum. */
|
||||
static NodeEnum cross_section_type_enum;
|
||||
distribution_type_enum.insert("Circular", NODE_MICROFACET_HAIR_CIRCULAR);
|
||||
distribution_type_enum.insert("Elliptical", NODE_MICROFACET_HAIR_ELLIPTIC);
|
||||
SOCKET_ENUM(cross_section_type,
|
||||
"Cross Section Type",
|
||||
cross_section_type_enum,
|
||||
NODE_MICROFACET_HAIR_CIRCULAR);
|
||||
|
||||
/* Initialize sockets to their default values. */
|
||||
SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
|
||||
|
@ -3698,8 +3703,7 @@ MicrofacetHairBsdfNode::MicrofacetHairBsdfNode() : BsdfBaseNode(get_node_type())
|
|||
void MicrofacetHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
{
|
||||
/* Make sure we have the normal for elliptical cross section tracking */
|
||||
if (model_type == NODE_MICROFACET_HAIR_ELLIPTIC_BECKMANN ||
|
||||
model_type == NODE_MICROFACET_HAIR_ELLIPTIC_GGX) {
|
||||
if (cross_section_type == NODE_MICROFACET_HAIR_ELLIPTIC) {
|
||||
attributes->add(ATTR_STD_VERTEX_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -3777,16 +3781,17 @@ void MicrofacetHairBsdfNode::compile(SVMCompiler &compiler)
|
|||
__float_as_uint(melanin_redness));
|
||||
|
||||
/* data node 3 */
|
||||
compiler.add_node(compiler.encode_uchar4(tint_ofs, random_in_ofs, random_color_ofs, 0),
|
||||
__float_as_uint(random),
|
||||
__float_as_uint(random_color),
|
||||
attr_random);
|
||||
compiler.add_node(
|
||||
compiler.encode_uchar4(tint_ofs, random_in_ofs, random_color_ofs, cross_section_type),
|
||||
__float_as_uint(random),
|
||||
__float_as_uint(random_color),
|
||||
attr_random);
|
||||
|
||||
/* data node 4 */
|
||||
compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(R_in),
|
||||
compiler.stack_assign_if_linked(TT_in),
|
||||
compiler.stack_assign_if_linked(TRT_in),
|
||||
model_type),
|
||||
distribution_type),
|
||||
__float_as_uint(R),
|
||||
__float_as_uint(TT),
|
||||
__float_as_uint(TRT));
|
||||
|
@ -3805,7 +3810,8 @@ void MicrofacetHairBsdfNode::compile(SVMCompiler &compiler)
|
|||
void MicrofacetHairBsdfNode::compile(OSLCompiler &compiler)
|
||||
{
|
||||
compiler.parameter(this, "parametrization");
|
||||
compiler.parameter(this, "model_type");
|
||||
compiler.parameter(this, "cross_section_type");
|
||||
compiler.parameter(this, "distribution_type");
|
||||
compiler.add(this, "node_microfacet_hair_bsdf");
|
||||
}
|
||||
|
||||
|
|
|
@ -922,8 +922,10 @@ class MicrofacetHairBsdfNode : public BsdfBaseNode {
|
|||
NODE_SOCKET_API(float, random)
|
||||
/* Selected coloring parametrization. */
|
||||
NODE_SOCKET_API(NodeMicrofacetHairParametrization, parametrization)
|
||||
/* Selected model type. */
|
||||
NODE_SOCKET_API(NodeMicrofacetHairModelType, model_type)
|
||||
/* Selected cross-section type. */
|
||||
NODE_SOCKET_API(NodeMicrofacetHairCrossSectionType, cross_section_type)
|
||||
/* Selected microfacet distribution type. */
|
||||
NODE_SOCKET_API(NodeMicrofacetHairDistributionType, distribution_type)
|
||||
};
|
||||
|
||||
class HairBsdfNode : public BsdfNode {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7be7aff5a18c550465b3f7634539ed4168af7c51
|
||||
Subproject commit 4f6dbb69893bd6bdf73467effe77ae46c8e4ee37
|
|
@ -1 +1 @@
|
|||
Subproject commit c226f867affd12881533a54c8c90ac6eebfaca6c
|
||||
Subproject commit 5a774a6dad4378f173ec7fdcdcd406048fcc9a29
|
|
@ -1 +1 @@
|
|||
Subproject commit bdcfdd47ec3451822b21d1cff2ea2db751093c9a
|
||||
Subproject commit 0f72f6c85c3743a9072273acb6a8a34b1cf1064b
|
|
@ -322,10 +322,8 @@ typedef struct bNode {
|
|||
*/
|
||||
int16_t type;
|
||||
|
||||
char _pad1[2];
|
||||
|
||||
/** Used for some builtin nodes that store properties but don't have a storage struct . */
|
||||
int16_t custom1, custom2;
|
||||
int16_t custom0, custom1, custom2;
|
||||
float custom3, custom4;
|
||||
|
||||
/** Optional link to libdata. */
|
||||
|
@ -1687,12 +1685,13 @@ enum {
|
|||
#define SHD_MICROFACET_HAIR_PIGMENT_CONCENTRATION 1
|
||||
#define SHD_MICROFACET_HAIR_DIRECT_ABSORPTION 2
|
||||
|
||||
/* microfacet hair modes */
|
||||
#define SHD_MICROFACET_HAIR_CIRCULAR_GGX 0
|
||||
#define SHD_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC 1
|
||||
#define SHD_MICROFACET_HAIR_CIRCULAR_BECKMANN 2
|
||||
#define SHD_MICROFACET_HAIR_ELLIPTIC_GGX 3
|
||||
#define SHD_MICROFACET_HAIR_ELLIPTIC_BECKMANN 4
|
||||
/* microfacet hair cross-section */
|
||||
#define SHD_MICROFACET_HAIR_CIRCULAR 0
|
||||
#define SHD_MICROFACET_HAIR_ELLIPTIC 1
|
||||
|
||||
/* microfacet hair distribution */
|
||||
#define SHD_MICROFACET_HAIR_GGX 0
|
||||
#define SHD_MICROFACET_HAIR_BECKMANN 1
|
||||
|
||||
/* blend texture */
|
||||
#define SHD_BLEND_LINEAR 0
|
||||
|
|
|
@ -4671,37 +4671,31 @@ static const EnumPropertyItem node_microfacet_hair_parametrization_items[] = {
|
|||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem node_microfacet_hair_mode_items[] = {
|
||||
{SHD_MICROFACET_HAIR_CIRCULAR_GGX,
|
||||
"HAIR_MICROFACET_CIRCULAR_GGX",
|
||||
static const EnumPropertyItem node_microfacet_hair_cross_section_items[] = {
|
||||
{SHD_MICROFACET_HAIR_CIRCULAR,
|
||||
"HAIR_MICROFACET_CIRCULAR",
|
||||
0,
|
||||
"Microfacet Circular GGX",
|
||||
"GGX microfacet-based hair scattering model with circular cross section fiber, numerically "
|
||||
"integrated across the width"},
|
||||
{SHD_MICROFACET_HAIR_CIRCULAR_GGX_ANALYTIC,
|
||||
"HAIR_MICROFACET_CIRCULAR_GGX_ANALYTIC",
|
||||
"Circular",
|
||||
"Microfacet-based hair scattering model with circular cross section"},
|
||||
{SHD_MICROFACET_HAIR_ELLIPTIC,
|
||||
"HAIR_MICROFACET_CIRCULAR_ELLIPTIC",
|
||||
0,
|
||||
"Microfacet Circular GGX Analytic",
|
||||
"GGX microfacet-based hair scattering model with circular cross section fiber, analytically "
|
||||
"integrated across the width with no masking term"},
|
||||
{SHD_MICROFACET_HAIR_CIRCULAR_BECKMANN,
|
||||
"HAIR_MICROFACET_CIRCULAR_BECKMANN",
|
||||
"Elliptical",
|
||||
"Microfacet-based hair scattering model with elliptical cross section fiber"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem node_microfacet_hair_distribution_items[] = {
|
||||
{SHD_MICROFACET_HAIR_GGX,
|
||||
"HAIR_MICROFACET_GGX",
|
||||
0,
|
||||
"Microfacet Circular Beckmann",
|
||||
"Beckmann microfacet-based hair scattering model with circular cross section fiber, "
|
||||
"numerically integrated across the width"},
|
||||
{SHD_MICROFACET_HAIR_ELLIPTIC_GGX,
|
||||
"HAIR_MICROFACET_ELLIPTIC_GGX",
|
||||
0,
|
||||
"Microfacet Elliptical GGX",
|
||||
"GGX microfacet-based hair scattering model with elliptical cross section fiber, numerically "
|
||||
"integrated across the width"},
|
||||
{SHD_MICROFACET_HAIR_ELLIPTIC_BECKMANN,
|
||||
"GGX",
|
||||
"Microfacet-based hair scattering model with GGX distribution"},
|
||||
{SHD_MICROFACET_HAIR_BECKMANN,
|
||||
"HAIR_MICROFACET_ELLIPTIC_BECKMANN",
|
||||
0,
|
||||
"Microfacet Elliptical Beckmann",
|
||||
"Beckmann microfacet-based hair scattering model with elliptical cross section fiber, "
|
||||
"numerically integrated across the width"},
|
||||
"Beckmann",
|
||||
"Microfacet-based hair scattering model with Beckmann distribution"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
@ -6231,20 +6225,31 @@ static void def_hair_microfacet(StructRNA *srna)
|
|||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "parametrization", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom0");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Color parametrization", "Select the shader's color parametrization");
|
||||
prop, "Color Parametrization", "Select the shader's color parametrization");
|
||||
RNA_def_property_enum_items(prop, node_microfacet_hair_parametrization_items);
|
||||
RNA_def_property_enum_default(prop, SHD_MICROFACET_HAIR_REFLECTANCE);
|
||||
/* Upon editing, update both the node data AND the UI representation */
|
||||
/* (This effectively shows/hides the relevant sockets) */
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "model_type", PROP_ENUM, PROP_NONE);
|
||||
prop = RNA_def_property(srna, "cross_section_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Hair Cross Section Shape", "Select the hair's cross section shape");
|
||||
RNA_def_property_enum_items(prop, node_microfacet_hair_cross_section_items);
|
||||
RNA_def_property_enum_default(prop, SHD_MICROFACET_HAIR_CIRCULAR);
|
||||
/* Upon editing, update both the node data AND the UI representation */
|
||||
/* (This effectively shows/hides the relevant sockets) */
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "distribution_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom2");
|
||||
RNA_def_property_ui_text(prop, "Mode", "Select the shader's mode");
|
||||
RNA_def_property_enum_items(prop, node_microfacet_hair_mode_items);
|
||||
RNA_def_property_enum_default(prop, SHD_MICROFACET_HAIR_CIRCULAR_GGX);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Microfacet Distribution", "Select the microfacet distribution of the hair surface");
|
||||
RNA_def_property_enum_items(prop, node_microfacet_hair_distribution_items);
|
||||
RNA_def_property_enum_default(prop, SHD_MICROFACET_HAIR_GGX);
|
||||
/* Upon editing, update both the node data AND the UI representation */
|
||||
/* (This effectively shows/hides the relevant sockets) */
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
|
||||
|
|
|
@ -81,24 +81,25 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
static void node_shader_buts_microfacet_hair(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "parametrization", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
uiItemR(layout, ptr, "model_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
uiItemR(layout, ptr, "cross_section_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
uiItemR(layout, ptr, "distribution_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
}
|
||||
|
||||
/* Initialize the custom Parametrization property to Color. */
|
||||
static void node_shader_init_hair_microfacet(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node->custom1 = SHD_MICROFACET_HAIR_REFLECTANCE;
|
||||
node->custom2 = SHD_MICROFACET_HAIR_CIRCULAR_GGX;
|
||||
node->custom0 = SHD_MICROFACET_HAIR_REFLECTANCE;
|
||||
node->custom1 = SHD_MICROFACET_HAIR_CIRCULAR;
|
||||
node->custom2 = SHD_MICROFACET_HAIR_GGX;
|
||||
}
|
||||
|
||||
/* Triggers (in)visibility of some sockets when changing Parametrization. */
|
||||
static void node_shader_update_hair_microfacet(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
int parametrization = node->custom1;
|
||||
int model_type = node->custom2;
|
||||
int parametrization = node->custom0;
|
||||
int cross_section_type = node->custom1;
|
||||
|
||||
bool elliptical = (model_type == SHD_MICROFACET_HAIR_ELLIPTIC_GGX ||
|
||||
model_type == SHD_MICROFACET_HAIR_ELLIPTIC_BECKMANN);
|
||||
bool elliptical = (cross_section_type == SHD_MICROFACET_HAIR_ELLIPTIC);
|
||||
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
||||
if (STREQ(sock->name, "Color")) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f542f4d21a077d85ffb3e43aa7f170976dee20b6
|
||||
Subproject commit e1744b9bd82527cf7e8af63362b61bd309b5711b
|
Loading…
Reference in New Issue