Blender V4.3
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
10#include "UI_interface.hh"
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 uiItemR(layout, ptr, "model", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
133 uiItemR(layout, 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{
139 NodeShaderHairPrincipled *data = MEM_cnew<NodeShaderHairPrincipled>(__func__);
140
141 data->model = SHD_PRINCIPLED_HAIR_CHIANG;
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{
150 NodeShaderHairPrincipled *data = static_cast<NodeShaderHairPrincipled *>(node->storage);
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*/,
198 GPUNodeStack *in,
199 GPUNodeStack *out)
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
216 &ntype, SH_NODE_BSDF_HAIR_PRINCIPLED, "Principled Hair BSDF", NODE_CLASS_SHADER);
217 ntype.declare = file_ns::node_declare;
219 ntype.draw_buttons = file_ns::node_shader_buts_principled_hair;
221 ntype.initfunc = file_ns::node_shader_init_hair_principled;
222 ntype.updatefunc = file_ns::node_shader_update_hair_principled;
223 ntype.gpu_fn = file_ns::node_shader_gpu_hair_principled;
225 &ntype, "NodeShaderHairPrincipled", node_free_standard_storage, node_copy_standard_storage);
226
228}
#define NODE_CLASS_SHADER
Definition BKE_node.hh:417
#define LISTBASE_FOREACH(type, var, list)
#define M_PI_2
#define M_PI
#define STR_ELEM(...)
Definition BLI_string.h:653
#define STREQ(a, b)
@ SHD_PRINCIPLED_HAIR_HUANG
@ SHD_PRINCIPLED_HAIR_CHIANG
@ SHD_PRINCIPLED_HAIR_REFLECTANCE
@ SHD_PRINCIPLED_HAIR_DIRECT_ABSORPTION
@ SHD_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
@ GPU_MATFLAG_GLOSSY
@ GPU_MATFLAG_DIFFUSE
void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag)
@ PROP_ANGLE
Definition RNA_types.hh:155
@ PROP_FACTOR
Definition RNA_types.hh:154
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
local_group_size(16, 16) .push_constant(Type b
void node_type_size_preset(bNodeType *ntype, eNodeSizePreset size)
Definition node.cc:4614
void node_set_socket_availability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
Definition node.cc:3911
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
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, int type, const char *name, short nclass)
bool object_cycles_shader_nodes_poll(const bContext *C)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
#define min(a, b)
Definition sort.c:32
Defines a node type.
Definition BKE_node.hh:218
bool(* add_ui_poll)(const bContext *C)
Definition BKE_node.hh:288
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:318
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:257
PointerRNA * ptr
Definition wm_files.cc:4126