Blender V5.0
node_shader_bsdf_hair_principled.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_string.h"
6
7#include "node_shader_util.hh"
8#include "node_util.hh"
9
11#include "UI_resources.hh"
12
14
15/* Color, melanin and absorption coefficient default to approximately same brownish hair. */
17{
18 b.add_input<decl::Color>("Color")
19 .default_value({0.017513f, 0.005763f, 0.002059f, 1.0f})
20 .description("The RGB color of the strand. Only used in Direct Coloring");
21 b.add_input<decl::Float>("Melanin")
22 .default_value(0.8f)
23 .min(0.0f)
24 .max(1.0f)
26 .description("Hair pigment. Specify its absolute quantity between 0 and 1");
27 b.add_input<decl::Float>("Melanin Redness")
28 .default_value(1.0f)
29 .min(0.0f)
30 .max(1.0f)
32 .description(
33 "Fraction of pheomelanin in melanin, gives yellowish to reddish color, as opposed to "
34 "the brownish to black color of eumelanin");
35 b.add_input<decl::Color>("Tint")
36 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
37 .description("Additional color used for dyeing the hair");
38 b.add_input<decl::Vector>("Absorption Coefficient")
39 .default_value({0.245531f, 0.52f, 1.365f})
40 .min(0.0f)
41 .max(1000.0f)
43 "Specifies energy absorption per unit length as light passes through the hair. A higher "
44 "value leads to a darker color");
45 b.add_input<decl::Float>("Aspect Ratio")
46 .default_value(0.85f)
47 .min(0.0f)
48 .max(1.0f)
50 .description(
51 "The ratio of the minor axis to the major axis of an elliptical cross-section. "
52 "Recommended values are 0.8~1 for Asian hair, 0.65~0.9 for Caucasian hair, 0.5~0.65 for "
53 "African hair. The major axis is aligned with the curve normal, which is not supported "
54 "in particle hair");
55 b.add_input<decl::Float>("Roughness")
56 .default_value(0.3f)
57 .min(0.0f)
58 .max(1.0f)
60 .description("Hair roughness. A low value leads to a metallic look");
61 b.add_input<decl::Float>("Radial Roughness")
62 .default_value(0.3f)
63 .min(0.0f)
64 .max(1.0f)
66 b.add_input<decl::Float>("Coat")
67 .default_value(0.0f)
68 .min(0.0f)
69 .max(1.0f)
71 .description(
72 "Simulate a shiny coat by reducing the roughness to the given factor only for the first "
73 "light bounce (diffuse). Range [0, 1] is equivalent to a reduction of [0%, 100%] of the "
74 "original roughness");
75 b.add_input<decl::Float>("IOR").default_value(1.55f).min(0.0f).max(1000.0f).description(
76 "Index of refraction determines how much the ray is bent. At 1.0 rays pass straight through "
77 "like in a transparent material; higher values cause larger deflection in angle. Default "
78 "value is 1.55 (the IOR of keratin)");
79 b.add_input<decl::Float>("Offset")
80 .default_value(2.0f * float(M_PI) / 180.0f)
81 .min(-M_PI_2)
82 .max(M_PI_2)
84 .description(
85 "The tilt angle of the cuticle scales (the outermost part of the hair). They are always "
86 "tilted towards the hair root. The value is usually between 2 and 4 for human hair");
87 b.add_input<decl::Float>("Random Color")
88 .default_value(0.0f)
89 .min(0.0f)
90 .max(1.0f)
92 .description("Vary the melanin concentration for each strand");
93 b.add_input<decl::Float>("Random Roughness")
94 .default_value(0.0f)
95 .min(0.0f)
96 .max(1.0f)
98 .description("Vary roughness values for each strand");
99 b.add_input<decl::Float>("Random").hide_value();
100 b.add_input<decl::Float>("Weight").available(false);
101 b.add_input<decl::Float>("Reflection", "R lobe")
102 .default_value(1.0f)
103 .min(0.0f)
104 .max(1.0f)
106 .description(
107 "Optional factor for modulating the first light bounce off the hair surface. The color "
108 "of this component is always white. Keep this 1.0 for physical correctness");
109 b.add_input<decl::Float>("Transmission", "TT lobe")
110 .default_value(1.0f)
111 .min(0.0f)
112 .max(1.0f)
114 .description(
115 "Optional factor for modulating the transmission component. Picks up the color of the "
116 "pigment inside the hair. Keep this 1.0 for physical correctness");
117 b.add_input<decl::Float>("Secondary Reflection", "TRT lobe")
118 .default_value(1.0f)
119 .min(0.0f)
120 .max(1.0f)
122 .description(
123 "Optional factor for modulating the component which is transmitted into the hair, "
124 "reflected off the backside of the hair and then transmitted out of the hair. This "
125 "component is oriented approximately around the incoming direction, and picks up the "
126 "color of the pigment inside the hair. Keep this 1.0 for physical correctness");
127 b.add_output<decl::Shader>("BSDF");
128}
129
131{
132 layout->prop(ptr, "model", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
133 layout->prop(ptr, "parametrization", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
134}
135
136/* Initialize custom properties. */
137static void node_shader_init_hair_principled(bNodeTree * /*ntree*/, bNode *node)
138{
140
142 data->parametrization = SHD_PRINCIPLED_HAIR_REFLECTANCE;
143
144 node->storage = data;
145}
146
147/* Triggers (in)visibility of some sockets when changing the parametrization or the model. */
149{
151
152 int parametrization = data->parametrization;
153 int model = data->model;
154
155 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
156 if (STREQ(sock->name, "Color")) {
158 *ntree, *sock, parametrization == SHD_PRINCIPLED_HAIR_REFLECTANCE);
159 }
160 else if (STREQ(sock->name, "Melanin")) {
162 *ntree, *sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
163 }
164 else if (STREQ(sock->name, "Melanin Redness")) {
166 *ntree, *sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
167 }
168 else if (STREQ(sock->name, "Tint")) {
170 *ntree, *sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
171 }
172 else if (STREQ(sock->name, "Absorption Coefficient")) {
174 *ntree, *sock, parametrization == SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
175 }
176 else if (STREQ(sock->name, "Random Color")) {
178 *ntree, *sock, parametrization == SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
179 }
180 else if (STREQ(sock->name, "Radial Roughness")) {
182 }
183 else if (STREQ(sock->name, "Coat")) {
185 }
186 else if (STREQ(sock->name, "Aspect Ratio")) {
188 }
189 else if (STR_ELEM(sock->name, "Reflection", "Transmission", "Secondary Reflection")) {
191 }
192 }
193}
194
196 bNode *node,
197 bNodeExecData * /*execdata*/,
200{
202
203 return GPU_stack_link(mat, node, "node_bsdf_hair_principled", in, out);
204}
205
206} // namespace blender::nodes::node_shader_bsdf_hair_principled_cc
207
208/* node type definition */
210{
212
213 static blender::bke::bNodeType ntype;
214
215 sh_node_type_base(&ntype, "ShaderNodeBsdfHairPrincipled", SH_NODE_BSDF_HAIR_PRINCIPLED);
216 ntype.ui_name = "Principled Hair BSDF";
217 ntype.ui_description = "Physically-based, easy-to-use shader for rendering hair and fur";
218 ntype.enum_name_legacy = "BSDF_HAIR_PRINCIPLED";
220 ntype.declare = file_ns::node_declare;
222 ntype.draw_buttons = file_ns::node_shader_buts_principled_hair;
224 ntype.initfunc = file_ns::node_shader_init_hair_principled;
225 ntype.updatefunc = file_ns::node_shader_update_hair_principled;
226 ntype.gpu_fn = file_ns::node_shader_gpu_hair_principled;
228 ntype, "NodeShaderHairPrincipled", node_free_standard_storage, node_copy_standard_storage);
229
231}
#define NODE_CLASS_SHADER
Definition BKE_node.hh:460
#define SH_NODE_BSDF_HAIR_PRINCIPLED
#define LISTBASE_FOREACH(type, var, list)
#define M_PI_2
#define M_PI
#define STR_ELEM(...)
Definition BLI_string.h:661
#define STREQ(a, b)
@ SHD_PRINCIPLED_HAIR_REFLECTANCE
@ SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION
@ SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION
@ SHD_PRINCIPLED_HAIR_HUANG
@ SHD_PRINCIPLED_HAIR_CHIANG
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
@ GPU_MATFLAG_DIFFUSE
void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag)
@ PROP_ANGLE
Definition RNA_types.hh:252
@ PROP_FACTOR
Definition RNA_types.hh:251
@ UI_ITEM_R_SPLIT_EMPTY_NAME
BMesh const char void * data
#define in
#define out
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
Definition node.cc:4739
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5414
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
Definition node.cc:5396
static int node_shader_gpu_hair_principled(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void node_shader_update_hair_principled(bNodeTree *ntree, bNode *node)
static void node_shader_buts_principled_hair(uiLayout *layout, bContext *, PointerRNA *ptr)
void register_node_type_sh_bsdf_hair_principled()
void sh_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
bool object_cycles_shader_nodes_poll(const bContext *C)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
#define min(a, b)
Definition sort.cc:36
ListBase inputs
void * storage
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
bool(* add_ui_poll)(const bContext *C)
Definition BKE_node.hh:310
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:289
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:342
const char * enum_name_legacy
Definition BKE_node.hh:247
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:259
NodeDeclareFunction declare
Definition BKE_node.hh:362
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:281
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
PointerRNA * ptr
Definition wm_files.cc:4238