Cycles: new Microfacet-based Hair BSDF with elliptical cross-section support #105600

Merged
Weizhen Huang merged 114 commits from weizhen/blender:microfacet_hair into main 2023-08-18 12:46:20 +02:00
24 changed files with 341 additions and 684 deletions
Showing only changes of commit cc9c70d9ef - Show all commits

View File

@ -624,22 +624,21 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
PrincipledHairBsdfNode *principled_hair = graph->create_node<PrincipledHairBsdfNode>();
principled_hair->set_parametrization((NodeHairParametrization)get_enum(
b_principled_hair_node.ptr, "parametrization", NODE_HAIR_NUM, NODE_HAIR_REFLECTANCE));
node = principled_hair;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfHairMicrofacet)) {
BL::ShaderNodeBsdfHairMicrofacet b_microfacet_hair_node(b_node);
MicrofacetHairBsdfNode *microfacet_hair = graph->create_node<MicrofacetHairBsdfNode>();
microfacet_hair->set_parametrization((NodeHairParametrization)get_enum(
b_microfacet_hair_node.ptr, "parametrization", NODE_HAIR_NUM, NODE_HAIR_REFLECTANCE));
microfacet_hair->set_distribution_type(
(NodeMicrofacetHairDistributionType)get_enum(b_microfacet_hair_node.ptr,
principled_hair->set_model((NodePrincipledHairModel)get_enum(b_principled_hair_node.ptr,
"model",
NODE_PRINCIPLED_HAIR_MODEL_NUM,
NODE_PRINCIPLED_HAIR_HUANG));
principled_hair->set_parametrization(
(NodePrincipledHairParametrization)get_enum(b_principled_hair_node.ptr,
"parametrization",
NODE_PRINCIPLED_HAIR_PARAMETRIZATION_NUM,
NODE_PRINCIPLED_HAIR_REFLECTANCE));
principled_hair->set_distribution_type(
(NodePrincipledHairDistributionType)get_enum(b_principled_hair_node.ptr,
"distribution_type",
NODE_MICROFACET_HAIR_DISTRIBUTION_TYPE_NUM,
NODE_MICROFACET_HAIR_GGX));
node = microfacet_hair;
NODE_PRINCIPLED_HAIR_DISTRIBUTION_TYPE_NUM,
NODE_PRINCIPLED_HAIR_GGX));
node = principled_hair;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);

View File

@ -914,12 +914,13 @@ ccl_device Spectrum bsdf_microfacet_hair_eval(KernelGlobals kg,
/* Evaluate. */
Spectrum eval;
if (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN) {
if (bsdf->distribution_type == NODE_PRINCIPLED_HAIR_BECKMANN) {
eval = bsdf_microfacet_hair_eval_r<MicrofacetType::BECKMANN>(kg, sc, local_I, local_O) +
bsdf_microfacet_hair_eval_residual<MicrofacetType::BECKMANN>(
kg, sc, local_I, local_O, sd->lcg_state);
}
else {
kernel_assert(bsdf->distribution_type == NODE_PRINCIPLED_HAIR_GGX);
eval = bsdf_microfacet_hair_eval_r<MicrofacetType::GGX>(kg, sc, local_I, local_O) +
bsdf_microfacet_hair_eval_residual<MicrofacetType::GGX>(
kg, sc, local_I, local_O, sd->lcg_state);
@ -943,10 +944,11 @@ ccl_device int bsdf_microfacet_hair_sample(KernelGlobals kg,
{
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)sc;
if (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN) {
if (bsdf->distribution_type == NODE_PRINCIPLED_HAIR_BECKMANN) {
return bsdf_microfacet_hair_sample<MicrofacetType::BECKMANN>(
kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
}
kernel_assert(bsdf->distribution_type == NODE_PRINCIPLED_HAIR_GGX);
return bsdf_microfacet_hair_sample<MicrofacetType::GGX>(
kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
}

View File

@ -913,9 +913,9 @@ ccl_device void osl_closure_microfacet_hair_setup(KernelGlobals kg,
bsdf->aspect_ratio = closure->aspect_ratio;
bsdf->extra = extra;
bsdf->extra->R = closure->reflection;
bsdf->extra->TT = closure->transmission;
bsdf->extra->TRT = closure->secondary_reflection;
bsdf->extra->R = closure->r_lobe;
bsdf->extra->TT = closure->tt_lobe;
bsdf->extra->TRT = closure->trt_lobe;
sd->flag |= bsdf_microfacet_hair_setup(sd, bsdf);
#endif

View File

@ -201,9 +201,9 @@ OSL_CLOSURE_STRUCT_BEGIN(MicrofacetHair, microfacet_hair)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, eta, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, INT, int, distribution_type, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, aspect_ratio, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, reflection, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, transmission, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, secondary_reflection, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, r_lobe, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, tt_lobe, NULL)
OSL_CLOSURE_STRUCT_MEMBER(MicrofacetHair, FLOAT, float, trt_lobe, NULL)
OSL_CLOSURE_STRUCT_END(MicrofacetHair, microfacet_hair)
OSL_CLOSURE_STRUCT_BEGIN(VolumeAbsorption, absorption)

View File

@ -102,7 +102,6 @@ set(SRC_OSL
node_wireframe.osl
node_hair_bsdf.osl
node_principled_hair_bsdf.osl
node_microfacet_hair_bsdf.osl
node_uv_map.osl
node_principled_bsdf.osl
node_rgb_to_bw.osl

View File

@ -1,121 +0,0 @@
/*
* Copyright 2018 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "stdcycles.h"
color m_log3(color a)
{
return color(log(a[0]), log(a[1]), log(a[2]));
}
color m_sigma_from_concentration(float eumelanin, float pheomelanin)
{
return eumelanin * color(0.506, 0.841, 1.653) + pheomelanin * color(0.343, 0.733, 1.924);
}
color m_sigma_from_reflectance(color c, float azimuthal_roughness)
{
float x = azimuthal_roughness;
float roughness_fac = (((((0.245 * x) + 5.574) * x - 10.73) * x + 2.532) * x - 0.215) * x +
5.969;
color sigma = m_log3(c) / roughness_fac;
return sigma * sigma;
}
shader node_microfacet_hair_bsdf(color Color = color(0.017513, 0.005763, 0.002059),
float Melanin = 0.8,
float MelaninRedness = 1.0,
float RandomColor = 0.0,
color Tint = 1.0,
color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
string parametrization = "Direct Coloring",
string distribution_type = "GGX",
float Offset = radians(2),
float Roughness = 0.3,
float RandomRoughness = 0.0,
float IOR = 1.55,
string AttrRandom = "geom:curve_random",
float Random = 0.0,
float AspectRatio = 0.85,
float Reflection = 1.0,
float Transmission = 1.0,
float SecondaryReflection = 1.0,
output closure color BSDF = 0)
{
/* Get random value from curve in none is specified. */
float random_value = 0.0;
if (isconnected(Random)) {
random_value = Random;
}
else {
getattribute(AttrRandom, random_value);
}
/* Compute roughness. */
float factor_random_roughness = 1.0 + 2.0 * (random_value - 0.5) * RandomRoughness;
float roughness = Roughness * factor_random_roughness;
/* Compute absorption. */
color sigma;
if (parametrization == "Absorption coefficient") {
sigma = AbsorptionCoefficient;
}
else if (parametrization == "Melanin concentration") {
/* Randomize melanin. */
float factor_random_color = 1.0 + 2.0 * (random_value - 0.5) * RandomColor;
float melanin = Melanin * factor_random_color;
/* Map melanin 0..inf from more perceptually linear 0..1. */
melanin = -log(max(1.0 - melanin, 0.0001));
/* Benedikt Bitterli's melanin ratio remapping. */
float eumelanin = melanin * (1.0 - MelaninRedness);
float pheomelanin = melanin * MelaninRedness;
color melanin_sigma = m_sigma_from_concentration(eumelanin, pheomelanin);
/* Optional tint. */
color tint_sigma = m_sigma_from_reflectance(Tint, roughness);
sigma = melanin_sigma + tint_sigma;
}
else if (parametrization == "Direct coloring") {
sigma = m_sigma_from_reflectance(Color, roughness);
}
else {
/* Fallback to brownish hair, same as defaults for melanin. */
sigma = m_sigma_from_concentration(0.0, 0.8054375);
}
int distribution_type_enum = (distribution_type == "GGX") ? 0 : 1;
normal major_axis = 0.0;
if (AspectRatio != 1.0) {
getattribute("geom:N", major_axis);
}
BSDF = microfacet_hair(major_axis,
sigma,
roughness,
Offset,
IOR,
distribution_type_enum,
AspectRatio,
Reflection,
Transmission,
SecondaryReflection);
}

View File

@ -29,7 +29,9 @@ shader node_principled_hair_bsdf(color Color = color(0.017513, 0.005763, 0.00205
color Tint = 1.0,
color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
normal Normal = Ng,
string parametrization = "Absorption coefficient",
string model = "Far-field Model",
string parametrization = "Direct Coloring",
string distribution_type = "GGX",
float Offset = radians(2),
float Roughness = 0.3,
float RadialRoughness = 0.3,
@ -38,6 +40,10 @@ shader node_principled_hair_bsdf(color Color = color(0.017513, 0.005763, 0.00205
float IOR = 1.55,
string AttrRandom = "geom:curve_random",
float Random = 0.0,
float AspectRatio = 0.85,
float Rlobe = 1.0,
float TTlobe = 1.0,
float TRTlobe = 1.0,
output closure color BSDF = 0)
{
@ -88,5 +94,27 @@ shader node_principled_hair_bsdf(color Color = color(0.017513, 0.005763, 0.00205
sigma = sigma_from_concentration(0.0, 0.8054375);
}
BSDF = principled_hair(Normal, sigma, roughness, radial_roughness, m0_roughness, Offset, IOR);
int distribution_type_enum = (distribution_type == "GGX") ? 0 : 1;
weizhen marked this conversation as resolved Outdated

I think we can move this into the main if below?

I think we can move this into the main `if` below?
normal major_axis = Normal;
if (model == "Far-field Model" && AspectRatio != 1.0) {
getattribute("geom:N", major_axis);
}
if (model == "Far-field Model") {
BSDF = microfacet_hair(major_axis,
sigma,
roughness,
Offset,
IOR,
distribution_type_enum,
AspectRatio,
Rlobe,
TTlobe,
TRTlobe);
}
else {
BSDF = principled_hair(Normal, sigma, roughness, radial_roughness, m0_roughness, Offset, IOR);
}
}

View File

@ -617,12 +617,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
Spectrum sigma;
switch (parametrization) {
case NODE_HAIR_DIRECT_ABSORPTION: {
case NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION: {
float3 absorption_coefficient = stack_load_float3(stack, absorption_coefficient_ofs);
sigma = rgb_to_spectrum(absorption_coefficient);
break;
}
case NODE_HAIR_PIGMENT_CONCENTRATION: {
case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION: {
float melanin = stack_load_float_default(stack, melanin_ofs, data_node2.z);
float melanin_redness = stack_load_float_default(
stack, melanin_redness_ofs, data_node2.w);
@ -649,7 +649,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
sigma = melanin_sigma + tint_sigma;
break;
}
case NODE_HAIR_REFLECTANCE: {
case NODE_PRINCIPLED_HAIR_REFLECTANCE: {
float3 color = stack_load_float3(stack, color_ofs);
sigma = bsdf_hair_sigma_from_reflectance(rgb_to_spectrum(color), radial_roughness);
break;
@ -690,6 +690,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
}
}
else {
kernel_assert(type == CLOSURE_BSDF_HAIR_MICROFACET_ID);
ccl_private MicrofacetHairBSDF *bsdf = (ccl_private MicrofacetHairBSDF *)bsdf_alloc(
sd, sizeof(MicrofacetHairBSDF), weight);
if (bsdf) {

View File

@ -389,18 +389,24 @@ typedef enum ShaderType {
SHADER_TYPE_BUMP,
} ShaderType;
typedef enum NodeHairParametrization {
NODE_HAIR_REFLECTANCE = 0,
NODE_HAIR_PIGMENT_CONCENTRATION = 1,
NODE_HAIR_DIRECT_ABSORPTION = 2,
NODE_HAIR_NUM,
} NodeHairParametrization;
typedef enum NodePrincipledHairModel {
NODE_PRINCIPLED_HAIR_CHIANG = 0,
NODE_PRINCIPLED_HAIR_HUANG = 1,
NODE_PRINCIPLED_HAIR_MODEL_NUM,
} NodePrincipledHairModel;
typedef enum NodeMicrofacetHairDistributionType {
NODE_MICROFACET_HAIR_GGX = 0,
NODE_MICROFACET_HAIR_BECKMANN = 1,
NODE_MICROFACET_HAIR_DISTRIBUTION_TYPE_NUM,
} NodeMicrofacetHairDistributionType;
typedef enum NodePrincipledHairParametrization {
NODE_PRINCIPLED_HAIR_REFLECTANCE = 0,
NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION = 1,
NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION = 2,
NODE_PRINCIPLED_HAIR_PARAMETRIZATION_NUM,
} NodePrincipledHairParametrization;
typedef enum NodePrincipledHairDistributionType {
NODE_PRINCIPLED_HAIR_GGX = 0,
NODE_PRINCIPLED_HAIR_BECKMANN = 1,
NODE_PRINCIPLED_HAIR_DISTRIBUTION_TYPE_NUM,
} NodePrincipledHairDistributionType;
typedef enum NodeCombSepColorType {
NODE_COMBSEP_COLOR_RGB,

View File

@ -3391,12 +3391,26 @@ NODE_DEFINE(PrincipledHairBsdfNode)
{
NodeType *type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
/* Scattering models. */
static NodeEnum model_enum;
model_enum.insert("Near-field Model", NODE_PRINCIPLED_HAIR_CHIANG);
model_enum.insert("Far-field Model", NODE_PRINCIPLED_HAIR_HUANG);
SOCKET_ENUM(model, "Model", model_enum, NODE_PRINCIPLED_HAIR_HUANG);
/* Color parametrization specified as enum. */
static NodeEnum parametrization_enum;
parametrization_enum.insert("Direct coloring", NODE_HAIR_REFLECTANCE);
parametrization_enum.insert("Melanin concentration", NODE_HAIR_PIGMENT_CONCENTRATION);
parametrization_enum.insert("Absorption coefficient", NODE_HAIR_DIRECT_ABSORPTION);
SOCKET_ENUM(parametrization, "Parametrization", parametrization_enum, NODE_HAIR_REFLECTANCE);
parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
SOCKET_ENUM(
parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
/* Hair microfacet normal distribution mode. */
static NodeEnum distribution_type_enum;
distribution_type_enum.insert("GGX", NODE_PRINCIPLED_HAIR_GGX);
distribution_type_enum.insert("Beckmann", NODE_PRINCIPLED_HAIR_BECKMANN);
SOCKET_ENUM(
distribution_type, "Distribution Type", distribution_type_enum, NODE_PRINCIPLED_HAIR_GGX);
/* Initialize sockets to their default values. */
SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
@ -3406,6 +3420,8 @@ NODE_DEFINE(PrincipledHairBsdfNode)
SOCKET_IN_VECTOR(
absorption_coefficient, "Absorption Coefficient", make_float3(0.245531f, 0.52f, 1.365f));
SOCKET_IN_FLOAT(aspect_ratio, "Aspect Ratio", 0.85f);
SOCKET_IN_FLOAT(offset, "Offset", 2.f * M_PI_F / 180.f);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
@ -3416,7 +3432,10 @@ NODE_DEFINE(PrincipledHairBsdfNode)
SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
SOCKET_IN_FLOAT(random, "Random", 0.0f);
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
SOCKET_IN_FLOAT(R, "R lobe", 1.0f);
SOCKET_IN_FLOAT(TT, "TT lobe", 1.0f);
SOCKET_IN_FLOAT(TRT, "TRT lobe", 1.0f);
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
SOCKET_OUT_CLOSURE(BSDF, "BSDF");
@ -3426,12 +3445,17 @@ NODE_DEFINE(PrincipledHairBsdfNode)
PrincipledHairBsdfNode::PrincipledHairBsdfNode() : BsdfBaseNode(get_node_type())
{
closure = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
closure = CLOSURE_BSDF_HAIR_MICROFACET_ID;
weizhen marked this conversation as resolved Outdated

I think you also need to check whether the socket is connected here?

I think you also need to check whether the socket is connected here?
}
/* Enable retrieving Hair Info -> Random if Random isn't linked. */
void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
/* Make sure we have the normal for elliptical cross section tracking. */
if (model == NODE_PRINCIPLED_HAIR_HUANG && aspect_ratio != 1.0f) {
attributes->add(ATTR_STD_VERTEX_NORMAL);
}
if (!input("Random")->link) {
attributes->add(ATTR_STD_CURVE_RANDOM);
}
@ -3441,6 +3465,9 @@ void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *att
/* Prepares the input data for the SVM shader. */
void PrincipledHairBsdfNode::compile(SVMCompiler &compiler)
{
closure = (model == NODE_PRINCIPLED_HAIR_HUANG) ? CLOSURE_BSDF_HAIR_MICROFACET_ID :
CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, one_float3());
ShaderInput *roughness_in = input("Roughness");
@ -3449,10 +3476,17 @@ void PrincipledHairBsdfNode::compile(SVMCompiler &compiler)
ShaderInput *offset_in = input("Offset");
ShaderInput *coat_in = input("Coat");
ShaderInput *ior_in = input("IOR");
ShaderInput *melanin_in = input("Melanin");
ShaderInput *melanin_redness_in = input("Melanin Redness");
ShaderInput *random_color_in = input("Random Color");
ShaderInput *R_in = input("R lobe");
ShaderInput *TT_in = input("TT lobe");
ShaderInput *TRT_in = input("TRT lobe");
ShaderInput *aspect_ratio_in = input("Aspect Ratio");
int color_ofs = compiler.stack_assign(input("Color"));
int tint_ofs = compiler.stack_assign(input("Tint"));
int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
@ -3460,7 +3494,6 @@ void PrincipledHairBsdfNode::compile(SVMCompiler &compiler)
int roughness_ofs = compiler.stack_assign_if_linked(roughness_in);
int radial_roughness_ofs = compiler.stack_assign_if_linked(radial_roughness_in);
int normal_ofs = compiler.stack_assign_if_linked(input("Normal"));
int offset_ofs = compiler.stack_assign_if_linked(offset_in);
int ior_ofs = compiler.stack_assign_if_linked(ior_in);
@ -3487,196 +3520,50 @@ void PrincipledHairBsdfNode::compile(SVMCompiler &compiler)
__float_as_uint(random_roughness));
/* data node */
compiler.add_node(normal_ofs,
compiler.add_node(model,
compiler.encode_uchar4(offset_ofs, ior_ofs, color_ofs, parametrization),
__float_as_uint(offset),
__float_as_uint(ior));
/* data node 2 */
compiler.add_node(compiler.encode_uchar4(
coat_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs),
__float_as_uint(coat),
__float_as_uint(melanin),
__float_as_uint(melanin_redness));
/* data node 3 */
compiler.add_node(
compiler.encode_uchar4(tint_ofs, random_in_ofs, random_color_ofs, radial_roughness_ofs),
__float_as_uint(random),
__float_as_uint(random_color),
attr_random);
/* data node 4 */
compiler.add_node(
compiler.encode_uchar4(
SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID),
__float_as_uint(radial_roughness),
SVM_STACK_INVALID,
SVM_STACK_INVALID);
}
/* Prepares the input data for the OSL shader. */
void PrincipledHairBsdfNode::compile(OSLCompiler &compiler)
{
compiler.parameter(this, "parametrization");
compiler.add(this, "node_principled_hair_bsdf");
}
/* Microfacet Hair BSDF Closure */
NODE_DEFINE(MicrofacetHairBsdfNode)
{
NodeType *type = NodeType::add("microfacet_hair_bsdf", create, NodeType::SHADER);
/* Color parametrization specified as enum. */
static NodeEnum parametrization_enum;
parametrization_enum.insert("Direct coloring", NODE_HAIR_REFLECTANCE);
parametrization_enum.insert("Melanin concentration", NODE_HAIR_PIGMENT_CONCENTRATION);
parametrization_enum.insert("Absorption coefficient", NODE_HAIR_DIRECT_ABSORPTION);
SOCKET_ENUM(parametrization, "Parametrization", parametrization_enum, NODE_HAIR_REFLECTANCE);
/* 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);
/* Initialize sockets to their default values. */
SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
SOCKET_IN_VECTOR(absorption_coefficient,
"Absorption Coefficient",
make_float3(0.245531f, 0.52f, 1.365f),
SocketType::VECTOR);
SOCKET_IN_FLOAT(aspect_ratio, "Aspect Ratio", 0.85f);
SOCKET_IN_FLOAT(offset, "Offset", 2.f * M_PI_F / 180.f);
SOCKET_IN_FLOAT(roughness, "Hair Roughness", 0.3f);
SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
SOCKET_IN_FLOAT(random, "Random", 0.0f);
SOCKET_IN_FLOAT(R, "R lobe", 1.0f);
SOCKET_IN_FLOAT(TT, "TT lobe", 1.0f);
SOCKET_IN_FLOAT(TRT, "TRT lobe", 1.0f);
SOCKET_OUT_CLOSURE(BSDF, "BSDF");
return type;
}
MicrofacetHairBsdfNode::MicrofacetHairBsdfNode() : BsdfBaseNode(get_node_type())
{
closure = CLOSURE_BSDF_HAIR_MICROFACET_ID;
}
void MicrofacetHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
/* Make sure we have the normal for elliptical cross section tracking. */
if (aspect_ratio != 1.0f) {
attributes->add(ATTR_STD_VERTEX_NORMAL);
}
/* Enable retrieving Hair Info -> Random if Random isn't linked. */
if (!input("Random")->link) {
attributes->add(ATTR_STD_CURVE_RANDOM);
}
ShaderNode::attributes(shader, attributes);
}
void MicrofacetHairBsdfNode::compile(SVMCompiler &compiler)
{
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, one_float3());
ShaderInput *roughness_in = input("Hair Roughness");
ShaderInput *random_roughness_in = input("Random Roughness");
ShaderInput *offset_in = input("Offset");
ShaderInput *ior_in = input("IOR");
ShaderInput *melanin_in = input("Melanin");
ShaderInput *melanin_redness_in = input("Melanin Redness");
ShaderInput *random_color_in = input("Random Color");
ShaderInput *R_in = input("R lobe");
ShaderInput *TT_in = input("TT lobe");
ShaderInput *TRT_in = input("TRT lobe");
ShaderInput *aspect_ratio_in = input("Aspect Ratio");
int color_ofs = compiler.stack_assign(input("Color"));
int tint_ofs = compiler.stack_assign(input("Tint"));
int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
int roughness_ofs = compiler.stack_assign_if_linked(roughness_in);
int offset_ofs = compiler.stack_assign_if_linked(offset_in);
int ior_ofs = compiler.stack_assign_if_linked(ior_in);
int melanin_ofs = compiler.stack_assign_if_linked(melanin_in);
int melanin_redness_ofs = compiler.stack_assign_if_linked(melanin_redness_in);
ShaderInput *random_in = input("Random");
int attr_random = random_in->link ? SVM_STACK_INVALID :
compiler.attribute(ATTR_STD_CURVE_RANDOM);
int random_in_ofs = compiler.stack_assign_if_linked(random_in);
int random_color_ofs = compiler.stack_assign_if_linked(random_color_in);
int random_roughness_ofs = compiler.stack_assign_if_linked(random_roughness_in);
/* Encode all parameters into data nodes. */
/* node */
compiler.add_node(
NODE_CLOSURE_BSDF,
/* Socket IDs can be packed 4 at a time into a single data packet */
compiler.encode_uchar4(
closure, roughness_ofs, random_roughness_ofs, compiler.closure_mix_weight_offset()),
/* The rest are stored as unsigned integers */
__float_as_uint(roughness),
__float_as_uint(random_roughness));
/* data node */
compiler.add_node(SVM_STACK_INVALID,
compiler.encode_uchar4(offset_ofs, ior_ofs, color_ofs, parametrization),
__float_as_uint(offset),
__float_as_uint(ior));
/* data node 2 */
compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(aspect_ratio_in),
compiler.add_node(compiler.encode_uchar4(model == NODE_PRINCIPLED_HAIR_HUANG ?
compiler.stack_assign_if_linked(aspect_ratio_in) :
coat_ofs,
melanin_ofs,
melanin_redness_ofs,
absorption_coefficient_ofs),
__float_as_uint(aspect_ratio),
__float_as_uint(model == NODE_PRINCIPLED_HAIR_HUANG ? aspect_ratio : coat),
__float_as_uint(melanin),
__float_as_uint(melanin_redness));
/* data node 3 */
compiler.add_node(
compiler.encode_uchar4(
tint_ofs, random_in_ofs, random_color_ofs, compiler.attribute(ATTR_STD_VERTEX_NORMAL)),
__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,
model == NODE_PRINCIPLED_HAIR_HUANG ?
compiler.attribute(ATTR_STD_VERTEX_NORMAL) :
radial_roughness_ofs),
__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),
distribution_type),
__float_as_uint(R),
__float_as_uint(model == NODE_PRINCIPLED_HAIR_HUANG ? R : radial_roughness),
__float_as_uint(TT),
__float_as_uint(TRT));
}
void MicrofacetHairBsdfNode::compile(OSLCompiler &compiler)
/* Prepares the input data for the OSL shader. */
void PrincipledHairBsdfNode::compile(OSLCompiler &compiler)
{
compiler.parameter(this, "model");
compiler.parameter(this, "parametrization");
compiler.parameter(this, "distribution_type");
compiler.add(this, "node_microfacet_hair_bsdf");
compiler.add(this, "node_principled_hair_bsdf");
}
/* Hair BSDF Closure */

View File

@ -855,40 +855,6 @@ class PrincipledHairBsdfNode : public BsdfBaseNode {
/* Absorption coefficient (unfiltered). */
NODE_SOCKET_API(float3, absorption_coefficient)
NODE_SOCKET_API(float3, normal)
NODE_SOCKET_API(float, surface_mix_weight)
/* If linked, here will be the given random number. */
NODE_SOCKET_API(float, random)
/* Selected coloring parametrization. */
NODE_SOCKET_API(NodeHairParametrization, parametrization)
};
/* Interface between the I/O sockets and the SVM/OSL backend. */
class MicrofacetHairBsdfNode : public BsdfBaseNode {
public:
SHADER_NODE_CLASS(MicrofacetHairBsdfNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
/* Roughness. */
NODE_SOCKET_API(float, roughness)
/* Randomization factor for roughnesses. */
NODE_SOCKET_API(float, random_roughness)
/* Index of reflection. */
NODE_SOCKET_API(float, ior)
/* Cuticle tilt angle. */
NODE_SOCKET_API(float, offset)
/* Direct coloring's color. */
NODE_SOCKET_API(float3, color)
/* Melanin concentration. */
NODE_SOCKET_API(float, melanin)
/* Melanin redness ratio. */
NODE_SOCKET_API(float, melanin_redness)
/* Dye color. */
NODE_SOCKET_API(float3, tint)
/* Randomization factor for melanin quantities. */
NODE_SOCKET_API(float, random_color)
/* Absorption coefficient (unfiltered). */
NODE_SOCKET_API(float3, absorption_coefficient)
/* Aspect Ratio. */
NODE_SOCKET_API(float, aspect_ratio)
@ -897,12 +863,16 @@ class MicrofacetHairBsdfNode : public BsdfBaseNode {
NODE_SOCKET_API(float, TT)
NODE_SOCKET_API(float, TRT)
/* Weight for mix shader. */
NODE_SOCKET_API(float, surface_mix_weight)
/* If linked, here will be the given random number. */
NODE_SOCKET_API(float, random)
/* Selected coloring parametrization. */
NODE_SOCKET_API(NodeHairParametrization, parametrization)
NODE_SOCKET_API(NodePrincipledHairParametrization, parametrization)
/* Selected microfacet distribution type. */
NODE_SOCKET_API(NodeMicrofacetHairDistributionType, distribution_type)
NODE_SOCKET_API(NodePrincipledHairDistributionType, distribution_type)
/* Selected scattering model (near-/far-field). */
NODE_SOCKET_API(NodePrincipledHairModel, model)
};
class HairBsdfNode : public BsdfNode {

View File

@ -1023,7 +1023,6 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define SH_NODE_COMBINE_COLOR 711
#define SH_NODE_SEPARATE_COLOR 712
#define SH_NODE_MIX 713
#define SH_NODE_BSDF_HAIR_MICROFACET 714
/** \} */

View File

@ -568,6 +568,14 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
}
for (bNode *node : ntree->all_nodes()) {
if (ntree->type == NTREE_SHADER && node->type == SH_NODE_BSDF_HAIR_PRINCIPLED) {
/* For Principeld Hair BSDF, also write to `node->custom1` for forward compatibility, because
* prior to 4.0 `node->custom1` was used for color parametrization instead of
* `node->storage->parametrization`. */
NodeShaderHairPrincipled *data = static_cast<NodeShaderHairPrincipled *>(node->storage);
node->custom1 = data->parametrization;
}
BLO_write_struct(writer, bNode, node);
if (node->prop) {

View File

@ -340,6 +340,22 @@ static void version_principled_bsdf_sheen(bNodeTree *ntree)
}
}
/* Replace old Principled Hair BSDF as a variant in the new Principled Hair BSDF. */
static void version_replace_principled_hair_model(bNodeTree *ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type != SH_NODE_BSDF_HAIR_PRINCIPLED) {
continue;
}
NodeShaderHairPrincipled *data = MEM_cnew<NodeShaderHairPrincipled>(__func__);
data->model = SHD_PRINCIPLED_HAIR_CHIANG;
data->parametrization = node->custom1;
data->distribution = SHD_PRINCIPLED_HAIR_GGX;
node->storage = data;
}
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@ -532,6 +548,14 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
* \note Keep this message at the bottom of the function.
*/
{
if (!DNA_struct_find(fd->filesdna, "NodeShaderHairPrincipled")) {
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_SHADER) {
version_replace_principled_hair_model(ntree);
}
}
FOREACH_NODETREE_END;
}
/* Keep this block, even when empty. */
}
}

View File

@ -38,6 +38,10 @@ void node_bsdf_hair_principled(vec4 color,
float coat,
float ior,
float offset,
float aspect_ratio,
float R,
float TT,
float TRT,
float random_color,
float random_roughness,
float random,
@ -64,41 +68,3 @@ void node_bsdf_hair_principled(vec4 color,
#endif
result = closure_eval(hair_data);
}
void node_bsdf_hair_microfacet(vec4 color,
float melanin,
float melanin_redness,
vec4 tint,
vec3 absorption_coefficient,
float roughness,
float R,
float TT,
float TRT,
float ior,
float offset,
float aspect_ratio,
float random_color,
float random_roughness,
float random,
float weight,
out Closure result)
{
/* Placeholder closure.
* TODO: Some computation will have to happen here just like the Principled BSDF. */
#if 0
ClosureHair hair_data;
hair_data.weight = weight;
hair_data.color = color.rgb;
hair_data.offset = offset;
hair_data.roughness = vec2(0.0);
hair_data.T = g_data.curve_B;
#else
ClosureDiffuse hair_data;
hair_data.weight = weight;
hair_data.color = color.rgb;
hair_data.N = g_data.N;
hair_data.sss_radius = vec3(0.0);
hair_data.sss_id = 0u;
#endif
result = closure_eval(hair_data);
}

View File

@ -1279,12 +1279,12 @@ typedef struct NodeShaderPrincipled {
char _pad[3];
} NodeShaderPrincipled;
typedef struct NodeShaderHairMicrofacet {
typedef struct NodeShaderHairPrincipled {
short model;
short parametrization;
short cross_section;
weizhen marked this conversation as resolved Outdated

Doesn't appear to be used?

Doesn't appear to be used?
short distribution;
char _pad[2];
} NodeShaderHairMicrofacet;
} NodeShaderHairPrincipled;
weizhen marked this conversation as resolved Outdated

Not sure if we need this yet, custom1 and custom2 should be enough?

Not sure if we need this yet, `custom1` and `custom2` should be enough?

For the current two enums yes, but named struct seems easier understandable. On the other hand, it introduces additional storage and is seen as a compromise for not having enum-typed sockets. I'm actually not sure what the current recommendation is.

For the current two enums yes, but named struct seems easier understandable. On the other hand, it introduces additional storage and is seen as a compromise for not having enum-typed sockets. I'm actually not sure what the current recommendation is.

I think it's fine to have better names for storage, custom1 / custom2 are not that great.

I think it's fine to have better names for storage, custom1 / custom2 are not that great.
/** TEX_output. */
typedef struct TexNodeOutput {
@ -1917,21 +1917,24 @@ enum {
SHD_HAIR_TRANSMISSION = 1,
};
/* principled hair parametrization */
/* principled hair models */
enum {
SHD_PRINCIPLED_HAIR_CHIANG = 0,
SHD_PRINCIPLED_HAIR_HUANG = 1,
};
/* principled hair color parametrization */
enum {
SHD_PRINCIPLED_HAIR_REFLECTANCE = 0,
SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION = 1,
SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION = 2,
};
/* microfacet hair parametrization */
#define SHD_MICROFACET_HAIR_REFLECTANCE 0
#define SHD_MICROFACET_HAIR_PIGMENT_CONCENTRATION 1
#define SHD_MICROFACET_HAIR_DIRECT_ABSORPTION 2
/* microfacet hair distribution */
#define SHD_MICROFACET_HAIR_GGX 0
#define SHD_MICROFACET_HAIR_BECKMANN 1
/* principled hair microfacet distribution */
enum {
SHD_PRINCIPLED_HAIR_GGX = 0,
SHD_PRINCIPLED_HAIR_BECKMANN = 1,
};
/* blend texture */
enum {

View File

@ -4542,7 +4542,24 @@ static const EnumPropertyItem node_hair_items[] = {
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem node_principled_hair_items[] = {
static const EnumPropertyItem node_principled_hair_model_items[] = {
{SHD_PRINCIPLED_HAIR_CHIANG,
"HAIR_PRINCIPLED_CHIANG",
0,
"Near-field Model",
"Hair scattering model by Chiang et. al 2016, suitable for close-up looks, but is in general "
"more noisy."},
{SHD_PRINCIPLED_HAIR_HUANG,
"HAIR_PRINCIPLED_HUANG",
0,
"Far-field Model",
"Microfacet-based hair scattering model by Huang et. al 2022, suitable for viewing from a "
"distance, supports elliptical cross-sections and has preciser highlight in forward "
weizhen marked this conversation as resolved Outdated

"preciser"->"more precise"

"preciser"->"more precise"
"scattering direction."},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem node_principled_hair_parametrization_items[] = {
{SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION,
"ABSORPTION",
0,
@ -4553,8 +4570,8 @@ static const EnumPropertyItem node_principled_hair_items[] = {
"MELANIN",
0,
"Melanin Concentration",
"Define the melanin concentrations below to get the most realistic-looking hair "
"(you can get the concentrations for different types of hair online)"},
"Define the melanin concentrations below to get the most realistic-looking hair (you can get "
"the concentrations for different types of hair online)"},
{SHD_PRINCIPLED_HAIR_REFLECTANCE,
"COLOR",
0,
@ -4564,40 +4581,18 @@ static const EnumPropertyItem node_principled_hair_items[] = {
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem node_microfacet_hair_parametrization_items[] = {
{SHD_MICROFACET_HAIR_DIRECT_ABSORPTION,
"ABSORPTION",
0,
"Absorption Coefficient",
"Directly set the absorption coefficient \"sigma_a\" (this is not the most intuitive way to "
"color hair)"},
{SHD_MICROFACET_HAIR_PIGMENT_CONCENTRATION,
"MELANIN",
0,
"Melanin Concentration",
"Define the melanin concentrations below to get the most realistic-looking hair "
"(you can get the concentrations for different types of hair online)"},
{SHD_MICROFACET_HAIR_REFLECTANCE,
"COLOR",
0,
"Direct Coloring",
"Choose the color of your preference, and the shader will approximate the absorption "
"coefficient to render lookalike hair"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem node_microfacet_hair_distribution_items[] = {
{SHD_MICROFACET_HAIR_GGX,
"HAIR_MICROFACET_GGX",
static const EnumPropertyItem node_principled_hair_distribution_items[] = {
{SHD_PRINCIPLED_HAIR_GGX,
"HAIR_PRINCIPLED_GGX",
0,
"GGX",
"Microfacet-based hair scattering model with GGX distribution"},
{SHD_MICROFACET_HAIR_BECKMANN,
"HAIR_MICROFACET_BECKMANN",
{SHD_PRINCIPLED_HAIR_BECKMANN,
"HAIR_PRINCIPLED_BECKMANN",
0,
"Beckmann",
"Microfacet-based hair scattering model with Beckmann distribution"},
{0, NULL, 0, NULL, NULL},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem node_script_mode_items[] = {
@ -6104,41 +6099,36 @@ static void def_hair(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
/* RNA initialization for the custom property. */
/* RNA initialization for the custom properties. */
static void def_hair_principled(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "parametrization", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "custom1");
RNA_def_property_ui_text(
prop, "Color Parametrization", "Select the shader's color parametrization");
RNA_def_property_enum_items(prop, node_principled_hair_items);
RNA_def_property_enum_default(prop, SHD_PRINCIPLED_HAIR_REFLECTANCE);
RNA_def_struct_sdna_from(srna, "NodeShaderHairPrincipled", "storage");
prop = RNA_def_property(srna, "model", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "model");
RNA_def_property_ui_text(prop, "Scattering model", "Select from near- or far-field model");
RNA_def_property_enum_items(prop, node_principled_hair_model_items);
RNA_def_property_enum_default(prop, SHD_PRINCIPLED_HAIR_HUANG);
/* 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");
}
/* RNA initialization for the custom property. */
static void def_hair_microfacet(StructRNA *srna)
{
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeShaderHairMicrofacet", "storage");
prop = RNA_def_property(srna, "parametrization", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "parametrization");
RNA_def_property_enum_sdna(prop, nullptr, "parametrization");
RNA_def_property_ui_text(
prop, "Color Parametrization", "Select the shader's color parametrization");
RNA_def_property_enum_items(prop, node_microfacet_hair_parametrization_items);
RNA_def_property_enum_items(prop, node_principled_hair_parametrization_items);
RNA_def_property_enum_default(prop, SHD_PRINCIPLED_HAIR_REFLECTANCE);
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, "distribution");
RNA_def_property_enum_sdna(prop, nullptr, "distribution");
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_items(prop, node_principled_hair_distribution_items);
RNA_def_property_enum_default(prop, SHD_PRINCIPLED_HAIR_GGX);
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
}

View File

@ -125,8 +125,6 @@ DefNode(ShaderNode, SH_NODE_COMBINE_COLOR, def_sh_combsep_color, "COM
DefNode(ShaderNode, SH_NODE_SEPARATE_COLOR, def_sh_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "Split a color into its individual components using multiple models")
DefNode(ShaderNode, SH_NODE_MIX, def_sh_mix, "MIX", Mix, "Mix", "Mix values by a factor")
DefNode(ShaderNode, SH_NODE_BSDF_HAIR_MICROFACET, def_hair_microfacet, "BSDF_HAIR_MICROFACET", BsdfHairMicrofacet, "Microfacet Hair BSDF", "Microfect Hair Scattering Model (EGSR 2022)")
DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
DefNode(CompositorNode, CMP_NODE_VALUE, 0, "VALUE", Value, "Value", "" )

View File

@ -35,7 +35,6 @@ set(SRC
nodes/node_shader_bsdf_glossy.cc
nodes/node_shader_bsdf_hair.cc
nodes/node_shader_bsdf_hair_principled.cc
nodes/node_shader_bsdf_hair_microfacet.cc
nodes/node_shader_bsdf_principled.cc
nodes/node_shader_bsdf_refraction.cc
nodes/node_shader_bsdf_sheen.cc

View File

@ -23,7 +23,6 @@ void register_shader_nodes()
register_node_type_sh_bsdf_glass();
register_node_type_sh_bsdf_glossy();
register_node_type_sh_bsdf_hair_principled();
register_node_type_sh_bsdf_hair_microfacet();
register_node_type_sh_bsdf_hair();
register_node_type_sh_bsdf_principled();
register_node_type_sh_bsdf_refraction();

View File

@ -19,7 +19,6 @@ void register_node_type_sh_bsdf_diffuse();
void register_node_type_sh_bsdf_glass();
void register_node_type_sh_bsdf_glossy();
void register_node_type_sh_bsdf_hair_principled();
void register_node_type_sh_bsdf_hair_microfacet();
void register_node_type_sh_bsdf_hair();
void register_node_type_sh_bsdf_principled();
void register_node_type_sh_bsdf_refraction();

View File

@ -887,7 +887,6 @@ static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_HAIR_PRINCIPLED:
case SH_NODE_BSDF_HAIR_MICROFACET:
case SH_NODE_BSDF_HAIR:
case SH_NODE_BSDF_PRINCIPLED:
case SH_NODE_BSDF_REFRACTION:
@ -945,7 +944,6 @@ static bool closure_node_filter(const bNode *node)
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_HAIR_PRINCIPLED:
case SH_NODE_BSDF_HAIR_MICROFACET:
case SH_NODE_BSDF_HAIR:
case SH_NODE_BSDF_PRINCIPLED:
case SH_NODE_BSDF_REFRACTION:

View File

@ -1,192 +0,0 @@
/* SPDX-FileCopyrightText: 2018 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_shader_util.hh"
#include "UI_interface.h"
#include "UI_resources.h"
namespace blender::nodes::node_shader_bsdf_hair_microfacet_cc {
/* Color, melanin and absorption coefficient default to approximately same brownish hair. */
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Color>("Color")
.default_value({0.017513f, 0.005763f, 0.002059f, 1.0f})
.description("The RGB color of the strand. Only used in Direct Coloring");
b.add_input<decl::Float>("Melanin")
.default_value(0.8f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR)
.description("Hair pigment. Specify its absolute quantity between 0 and 1");
b.add_input<decl::Float>("Melanin Redness")
.default_value(1.0f)
.min(0.0f)