Blender V4.5
node_shader_bsdf_principled.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <map>
6
7#include "node_shader_util.hh"
8
9#include "UI_interface.hh"
10#include "UI_resources.hh"
11
12#include "BKE_node_runtime.hh"
13
15
17{
22
23 b.use_custom_socket_order();
24
25 b.add_output<decl::Shader>("BSDF");
26
27 b.add_input<decl::Color>("Base Color")
28 .default_value({0.8f, 0.8f, 0.8f, 1.0f})
29 .description(
30 "Color of the material used for diffuse, subsurface, metallic and transmission");
31#define SOCK_BASE_COLOR_ID 0
32 b.add_input<decl::Float>("Metallic")
33 .default_value(0.0f)
34 .min(0.0f)
35 .max(1.0f)
37 .description(
38 "Blends between a dielectric and metallic material model. "
39 "At 0.0 the material consists of a diffuse or transmissive base layer, "
40 "with a specular reflection layer on top. A value of 1.0 gives a fully specular "
41 "reflection tinted with the base color, without diffuse reflection or transmission");
42#define SOCK_METALLIC_ID 1
43 b.add_input<decl::Float>("Roughness")
44 .default_value(0.5f)
45 .min(0.0f)
46 .max(1.0f)
48 .description(
49 "Specifies microfacet roughness of the surface for specular reflection and transmission"
50 " (0.0 is a perfect mirror reflection, 1.0 is completely rough)");
51#define SOCK_ROUGHNESS_ID 2
52 b.add_input<decl::Float>("IOR").default_value(1.5f).min(1.0f).max(1000.0f).description(
53 "Index of Refraction (IOR) for specular reflection and transmission. "
54 "For most materials, the IOR is between 1.0 (vacuum and air) and 4.0 (germanium). "
55 "The default value of 1.5 is a good approximation for glass");
56#define SOCK_IOR_ID 3
57 b.add_input<decl::Float>("Alpha")
58 .default_value(1.0f)
59 .min(0.0f)
60 .max(1.0f)
62 .description("Controls the transparency of the surface, with 1.0 fully opaque");
63#define SOCK_ALPHA_ID 4
64 b.add_input<decl::Vector>("Normal").hide_value();
65#define SOCK_NORMAL_ID 5
66 b.add_input<decl::Float>("Weight").available(false);
67#define SOCK_WEIGHT_ID 6
68
69 /* Panel for Diffuse settings. */
70 PanelDeclarationBuilder &diffuse = b.add_panel("Diffuse").default_closed(true);
71 diffuse.add_input<decl::Float>("Diffuse Roughness")
72 .default_value(0.0f)
73 .min(0.0f)
74 .max(1.0f)
76 .description(
77 "Specifies microfacet roughness of the diffuse base"
78 " (0.0 is perfect lambertian reflection, 1.0 is completely rough)");
79#define SOCK_DIFFUSE_ROUGHNESS_ID 7
80
81 /* Panel for Subsurface scattering settings. */
82 PanelDeclarationBuilder &sss = b.add_panel("Subsurface").default_closed(true);
83 sss.add_layout([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) {
84 layout->prop(ptr, "subsurface_method", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
85 });
86 sss.add_input<decl::Float>("Subsurface Weight")
87 .default_value(0.0f)
88 .min(0.0f)
89 .max(1.0f)
91 .short_label("Weight")
92 .description(
93 "Blend between diffuse surface and subsurface scattering. "
94 "Typically should be zero or one (either fully diffuse or subsurface)");
95#define SOCK_SUBSURFACE_WEIGHT_ID 8
96 sss.add_input<decl::Vector>("Subsurface Radius")
97 .default_value({1.0f, 0.2f, 0.1f})
98 .min(0.0f)
99 .max(100.0f)
100 .short_label("Radius")
101 .description("Scattering radius per color channel (RGB), multiplied with Scale");
102#define SOCK_SUBSURFACE_RADIUS_ID 9
103 sss.add_input<decl::Float>("Subsurface Scale")
104 .default_value(0.05f)
105 .min(0.0f)
106 .max(10.0f)
108 .short_label("Scale")
109 .description("Scale factor of the subsurface scattering radius");
110#define SOCK_SUBSURFACE_SCALE_ID 10
111 sss.add_input<decl::Float>("Subsurface IOR")
112 .default_value(1.4f)
113 .min(1.01f)
114 .max(3.8f)
116 .short_label("IOR")
117 .description("Index of Refraction (IOR) used for rays that enter the subsurface component");
118#define SOCK_SUBSURFACE_IOR_ID 11
119 sss.add_input<decl::Float>("Subsurface Anisotropy")
120 .default_value(0.0f)
121 .min(0.0f)
122 .max(1.0f)
124 .short_label("Anisotropy")
125 .description(
126 "Directionality of volume scattering within the subsurface medium. "
127 "Zero scatters uniformly in all directions, with higher values "
128 "scattering more strongly forward. For example, skin has been measured "
129 "to have an anisotropy of 0.8");
130#define SOCK_SUBSURFACE_ANISOTROPY_ID 12
131
132 /* Panel for Specular settings. */
133 PanelDeclarationBuilder &spec = b.add_panel("Specular").default_closed(true);
134 spec.add_layout([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) {
135 layout->prop(ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
136 });
137 spec.add_input<decl::Float>("Specular IOR Level")
138 .default_value(0.5f)
139 .min(0.0f)
140 .max(1.0f)
142 .short_label("IOR Level")
143 .description(
144 "Adjustment to the Index of Refraction (IOR) to increase or decrease specular intensity "
145 "(0.5 means no adjustment, 0 removes all reflections, 1 doubles them at normal "
146 "incidence)");
147#define SOCK_SPECULAR_ID 13
148 spec.add_input<decl::Color>("Specular Tint")
149 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
150 .short_label("Tint")
152 "Tint dielectric reflection at normal incidence for artistic control, and metallic "
153 "reflection at near-grazing incidence to simulate complex index of refraction")
154 .translation_context(BLT_I18NCONTEXT_ID_NODETREE);
155#define SOCK_SPECULAR_TINT_ID 14
156 spec.add_input<decl::Float>("Anisotropic")
157 .default_value(0.0f)
158 .min(0.0f)
159 .max(1.0f)
161 .description(
162 "Amount of anisotropy for specular reflection. "
163 "Higher values give elongated highlights along the tangent direction");
164#define SOCK_ANISOTROPIC_ID 15
165 spec.add_input<decl::Float>("Anisotropic Rotation")
166 .default_value(0.0f)
167 .min(0.0f)
168 .max(1.0f)
170 .description("Rotates the direction of anisotropy, with 1.0 going full circle");
171#define SOCK_ANISOTROPIC_ROTATION_ID 16
172 spec.add_input<decl::Vector>("Tangent").hide_value().description(
173 "Controls the tangent direction for anisotropy");
174#define SOCK_TANGENT_ID 17
175
176 /* Panel for Transmission settings. */
177 PanelDeclarationBuilder &transmission = b.add_panel("Transmission").default_closed(true);
178 transmission.add_input<decl::Float>("Transmission Weight")
179 .default_value(0.0f)
180 .min(0.0f)
181 .max(1.0f)
183 .short_label("Weight")
184 .description("Blend between transmission and other base layer components");
185#define SOCK_TRANSMISSION_WEIGHT_ID 18
186
187 /* Panel for Coat settings. */
188 PanelDeclarationBuilder &coat = b.add_panel("Coat").default_closed(true);
189 coat.add_input<decl::Float>("Coat Weight")
190 .default_value(0.0f)
191 .min(0.0f)
192 .max(1.0f)
194 .short_label("Weight")
195 .description(
196 "Controls the intensity of the coat layer, both the reflection and the tinting. "
197 "Typically should be zero or one for physically-based materials");
198#define SOCK_COAT_WEIGHT_ID 19
199 coat.add_input<decl::Float>("Coat Roughness")
200 .default_value(0.03f)
201 .min(0.0f)
202 .max(1.0f)
204 .short_label("Roughness")
205 .description("The roughness of the coat layer");
206#define SOCK_COAT_ROUGHNESS_ID 20
207 coat.add_input<decl::Float>("Coat IOR")
208 .default_value(1.5f)
209 .min(1.0f)
210 .max(4.0f)
211 .short_label("IOR")
212 .description(
213 "The Index of Refraction (IOR) of the coat layer "
214 "(affects its reflectivity as well as the falloff of coat tinting)");
215#define SOCK_COAT_IOR_ID 21
216 coat.add_input<decl::Color>("Coat Tint")
217 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
218 .short_label("Tint")
220 "Adds a colored tint to the coat layer by modeling absorption in the layer. "
221 "Saturation increases at shallower angles, as the light travels farther "
222 "through the medium (depending on the Coat IOR)")
223 .translation_context(BLT_I18NCONTEXT_ID_NODETREE);
224#define SOCK_COAT_TINT_ID 22
225 coat.add_input<decl::Vector>("Coat Normal").short_label("Normal").hide_value();
226#define SOCK_COAT_NORMAL_ID 23
227
228 /* Panel for Sheen settings. */
229 PanelDeclarationBuilder &sheen = b.add_panel("Sheen").default_closed(true);
230 sheen.add_input<decl::Float>("Sheen Weight")
231 .default_value(0.0f)
232 .min(0.0f)
233 .max(1.0f)
235 .short_label("Weight")
236 .description(
237 "Intensity of the sheen layer, which simulates very small fibers on the surface");
238#define SOCK_SHEEN_WEIGHT_ID 24
239 sheen.add_input<decl::Float>("Sheen Roughness")
240 .default_value(0.5f)
241 .min(0.0f)
242 .max(1.0f)
244 .short_label("Roughness")
245 .description(
246 "Roughness of the sheen layer. Low and high roughness values produce fuzzy or dusty "
247 "appearance, respectively");
248#define SOCK_SHEEN_ROUGHNESS_ID 25
249 sheen.add_input<decl::Color>("Sheen Tint")
250 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
251 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
252 .short_label("Tint")
253 .description("Color of the sheen reflection");
254#define SOCK_SHEEN_TINT_ID 26
255
256 /* Panel for Emission settings. */
257 PanelDeclarationBuilder &emis = b.add_panel("Emission").default_closed(true);
258 emis.add_input<decl::Color>("Emission Color")
259 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
260 .short_label("Color")
261 .description("Color of light emission from the surface");
262#define SOCK_EMISSION_ID 27
263 emis.add_input<decl::Float>("Emission Strength")
264 .default_value(0.0)
265 .min(0.0f)
266 .max(1000000.0f)
267 .short_label("Strength")
268 .description(
269 "Strength of the emitted light. A value of 1.0 ensures "
270 "that the object in the image has the exact same color as the Emission Color")
271 .translation_context(BLT_I18NCONTEXT_AMOUNT);
272#define SOCK_EMISSION_STRENGTH_ID 28
273
274 /* Panel for Thin Film settings. */
275 PanelDeclarationBuilder &film = b.add_panel("Thin Film").default_closed(true);
276 film.add_input<decl::Float>("Thin Film Thickness")
277 .default_value(0.0)
278 .min(0.0f)
279 .max(100000.0f)
281 .description("Thickness of the film in nanometers");
282#define SOCK_THIN_FILM_THICKNESS_ID 29
283 film.add_input<decl::Float>("Thin Film IOR")
284 .default_value(1.33f)
285 .min(1.0f)
286 .max(1000.0f)
287 .description("Index of refraction (IOR) of the thin film");
288#define SOCK_THIN_FILM_IOR_ID 30
289}
290
291static void node_shader_init_principled(bNodeTree * /*ntree*/, bNode *node)
292{
295}
296
297#define socket_not_zero(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) > 1e-5f))
298#define socket_not_one(sock) \
299 (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) < 1.0f - 1e-5f))
300
302 bNode *node,
303 bNodeExecData * /*execdata*/,
306{
307 /* Normals */
308 if (!in[SOCK_NORMAL_ID].link) {
309 GPU_link(mat, "world_normals_get", &in[SOCK_NORMAL_ID].link);
310 }
311
312 /* Coat Normals */
313 if (!in[SOCK_COAT_NORMAL_ID].link) {
314 GPU_link(mat, "world_normals_get", &in[SOCK_COAT_NORMAL_ID].link);
315 }
316
317#if 0 /* Not used at the moment. */
318 /* Tangents */
319 if (!in[SOCK_TANGENT_ID].link) {
320 GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
321 GPU_link(mat, "tangent_orco_z", orco, &in[SOCK_TANGENT_ID].link);
322 GPU_link(mat, "node_tangent", in[SOCK_TANGENT_ID].link, &in[SOCK_TANGENT_ID].link);
323 }
324#endif
325
326 bool use_diffuse = socket_not_zero(SOCK_SHEEN_WEIGHT_ID) ||
329 bool use_subsurf = socket_not_zero(SOCK_SUBSURFACE_WEIGHT_ID) && use_diffuse;
330 bool use_refract = socket_not_one(SOCK_METALLIC_ID) &&
332 bool use_transparency = socket_not_one(SOCK_ALPHA_ID);
333 bool use_coat = socket_not_zero(SOCK_COAT_WEIGHT_ID);
334
336 if (use_diffuse) {
338 }
339 if (use_refract) {
341 }
342 if (use_subsurf) {
344 }
345 if (use_transparency) {
347 }
348 if (use_coat) {
350 }
351
352 float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f;
353
355
356 return GPU_stack_link(
357 mat, node, "node_bsdf_principled", in, out, GPU_constant(&use_multi_scatter));
358}
359
361{
362 const int sss_method = node->custom2;
363
365 *bke::node_find_socket(*node, SOCK_IN, "Subsurface IOR"),
366 sss_method == SHD_SUBSURFACE_RANDOM_WALK_SKIN);
368 *ntree,
369 *bke::node_find_socket(*node, SOCK_IN, "Subsurface Anisotropy"),
370 sss_method != SHD_SUBSURFACE_BURLEY);
371}
372
374#ifdef WITH_MATERIALX
375{
376 using InputsType = std::map<std::string, NodeItem>;
377
378 /* NOTE: commented inputs aren't used for node creation. */
379 auto bsdf_inputs = [&]() -> InputsType {
380 return
381 {
382 {"base_color", get_input_value("Base Color", NodeItem::Type::Color3)},
383 {"diffuse_roughness", get_input_value("Diffuse Roughness", NodeItem::Type::Float)},
384 {"subsurface", get_input_value("Subsurface Weight", NodeItem::Type::Float)},
385 {"subsurface_scale", get_input_value("Subsurface Scale", NodeItem::Type::Float)},
386# if MATERIALX_MAJOR_VERSION <= 1 && MATERIALX_MINOR_VERSION <= 38
387 {"subsurface_radius", get_input_value("Subsurface Radius", NodeItem::Type::Vector3)},
388# else
389 {"subsurface_radius", get_input_value("Subsurface Radius", NodeItem::Type::Color3)},
390# endif
391 //{"subsurface_ior", get_input_value("Subsurface IOR", NodeItem::Type::Vector3)},
392 {"subsurface_anisotropy",
393 get_input_value("Subsurface Anisotropy", NodeItem::Type::Float)},
394 {"metallic", get_input_value("Metallic", NodeItem::Type::Float)},
395 {"specular", get_input_value("Specular IOR Level", NodeItem::Type::Float)},
396 {"specular_tint", get_input_value("Specular Tint", NodeItem::Type::Color3)},
397 {"roughness", get_input_value("Roughness", NodeItem::Type::Float)},
398 {"anisotropic", get_input_value("Anisotropic", NodeItem::Type::Float)},
399 {"anisotropic_rotation", get_input_value("Anisotropic Rotation", NodeItem::Type::Float)},
400 {"sheen", get_input_value("Sheen Weight", NodeItem::Type::Float)},
401 {"sheen_roughness", get_input_value("Sheen Roughness", NodeItem::Type::Float)},
402 {"sheen_tint", get_input_value("Sheen Tint", NodeItem::Type::Color3)},
403 {"coat", get_input_value("Coat Weight", NodeItem::Type::Float)},
404 {"coat_roughness", get_input_value("Coat Roughness", NodeItem::Type::Float)},
405 {"coat_ior", get_input_value("Coat IOR", NodeItem::Type::Float)},
406 {"coat_tint", get_input_value("Coat Tint", NodeItem::Type::Color3)},
407 {"ior", get_input_value("IOR", NodeItem::Type::Float)},
408 {"transmission", get_input_value("Transmission Weight", NodeItem::Type::Float)},
409 {"thin_film_thickness", get_input_value("Thin Film Thickness", NodeItem::Type::Float)},
410 {"thin_film_IOR", get_input_value("Thin Film IOR", NodeItem::Type::Float)},
411 {"alpha", get_input_value("Alpha", NodeItem::Type::Float)},
412 {"normal", get_input_link("Normal", NodeItem::Type::Vector3)},
413 {"coat_normal", get_input_link("Coat Normal", NodeItem::Type::Vector3)},
414 {"tangent", get_input_link("Tangent", NodeItem::Type::Vector3)},
415 };
416 };
417
418 auto edf_inputs = [&]() -> InputsType {
419 return {
420 {"emission", get_input_value("Emission Strength", NodeItem::Type::Float)},
421 {"emission_color", get_input_value("Emission Color", NodeItem::Type::Color3)},
422 };
423 };
424
425 NodeItem res = empty();
426
427 switch (to_type_) {
428 case NodeItem::Type::BSDF: {
429 auto in = bsdf_inputs();
430
431 NodeItem roughness = in["roughness"];
432 NodeItem diffuse_roughness = in["diffuse_roughness"];
433 NodeItem anisotropy = in["anisotropic"];
434 NodeItem rotation = in["anisotropic_rotation"] * val(360.0f);
435 NodeItem base_color = in["base_color"];
436 NodeItem specular = in["specular"];
437 NodeItem coat = in["coat"];
438 NodeItem ior = in["ior"];
439 NodeItem normal = in["normal"];
440 NodeItem tangent = in["tangent"];
441 NodeItem coat_normal = in["coat_normal"];
442
443 NodeItem n_main_tangent = empty();
444 if (tangent && normal) {
445 NodeItem n_tangent_rotate_normalize = tangent.rotate(rotation, normal).normalize();
446 n_main_tangent = anisotropy.if_else(
447 NodeItem::CompareOp::Greater, val(0.0f), n_tangent_rotate_normalize, tangent);
448 }
449
450 NodeItem n_coat_roughness_vector = create_node(
451 "roughness_anisotropy",
452 NodeItem::Type::Vector2,
453 {{"roughness", in["coat_roughness"]}, {"anisotropy", anisotropy}});
454
455 NodeItem n_coat_bsdf = create_node("dielectric_bsdf",
456 NodeItem::Type::BSDF,
457 {{"weight", coat},
458 {"tint", in["coat_tint"]},
459 {"ior", in["coat_ior"]},
460 {"scatter_mode", val(std::string("R"))},
461 {"roughness", n_coat_roughness_vector},
462 {"normal", coat_normal}});
463
464 if (tangent && coat_normal) {
465 NodeItem n_coat_tangent_rotate_normalize =
466 tangent.rotate(rotation, coat_normal).normalize();
467 NodeItem n_coat_tangent = anisotropy.if_else(
468 NodeItem::CompareOp::Greater, val(0.0f), n_coat_tangent_rotate_normalize, tangent);
469
470 n_coat_bsdf.set_input("tangent", n_coat_tangent);
471 }
472
473 NodeItem thin_film_thickness = in["thin_film_thickness"];
474 NodeItem thin_film_ior = in["thin_film_IOR"];
475 NodeItem n_thin_film_bsdf = create_node(
476 "thin_film_bsdf",
477 NodeItem::Type::BSDF,
478 {{"thickness", thin_film_thickness}, {"ior", thin_film_ior}});
479
480 NodeItem n_artistic_ior = create_node(
481 "artistic_ior",
482 NodeItem::Type::Multioutput,
483 {{"reflectivity", base_color * val(1.0f)}, {"edge_color", base_color * specular}});
484
485 NodeItem n_ior_out = n_artistic_ior.add_output("ior", NodeItem::Type::Color3);
486 NodeItem n_extinction_out = n_artistic_ior.add_output("extinction", NodeItem::Type::Color3);
487
488 NodeItem n_coat_affect_roughness_multiply2 = coat * val(0.0f) * in["coat_roughness"];
489 NodeItem n_coat_affected_roughness = n_coat_affect_roughness_multiply2.mix(roughness,
490 val(1.0f));
491
492 NodeItem n_main_roughness = create_node(
493 "roughness_anisotropy",
494 NodeItem::Type::Vector2,
495 {{"roughness", n_coat_affected_roughness}, {"anisotropy", anisotropy}});
496
497 NodeItem n_metal_bsdf = create_node("conductor_bsdf",
498 NodeItem::Type::BSDF,
499 {{"ior", n_ior_out},
500 {"extinction", n_extinction_out},
501 {"roughness", n_main_roughness},
502 {"normal", normal},
503 {"tangent", n_main_tangent}});
504
505 NodeItem n_specular_bsdf = create_node("dielectric_bsdf",
506 NodeItem::Type::BSDF,
507 {{"weight", specular},
508 {"tint", in["specular_tint"]},
509 {"ior", ior},
510 {"scatter_mode", val(std::string("R"))},
511 {"roughness", n_main_roughness},
512 {"normal", normal},
513 {"tangent", n_main_tangent}});
514
515 NodeItem n_coat_affected_transmission_roughness = n_coat_affect_roughness_multiply2.mix(
516 (roughness + roughness).clamp(), val(1.0f));
517
518 NodeItem n_transmission_roughness = create_node(
519 "roughness_anisotropy",
520 NodeItem::Type::Vector2,
521 {{"roughness", n_coat_affected_transmission_roughness}, {"anisotropy", anisotropy}});
522
523 NodeItem n_transmission_bsdf = create_node("dielectric_bsdf",
524 NodeItem::Type::BSDF,
525 {{"tint", base_color},
526 {"ior", ior},
527 {"roughness", n_transmission_roughness},
528 {"normal", normal},
529 {"tangent", n_main_tangent}});
530
531 NodeItem n_coat_gamma = coat.clamp(0.0f, 1.0f) * val(0.0f) + val(1.0f);
532 NodeItem n_coat_affected_subsurface_color = base_color.max(val(0.0f)) ^ n_coat_gamma;
533 NodeItem n_translucent_bsdf = create_node(
534 "translucent_bsdf",
535 NodeItem::Type::BSDF,
536 {{"color", n_coat_affected_subsurface_color}, {"normal", normal}});
537
538 NodeItem n_subsurface_bsdf = create_node(
539 "subsurface_bsdf",
540 NodeItem::Type::BSDF,
541 {{"color", n_coat_affected_subsurface_color},
542 {"radius", in["subsurface_radius"] * in["subsurface_scale"]},
543 {"anisotropy", in["subsurface_anisotropy"]},
544 {"normal", normal}});
545
546 NodeItem n_sheen_bsdf = create_node("sheen_bsdf",
547 NodeItem::Type::BSDF,
548 {{"weight", in["sheen"]},
549 {"color", in["sheen_tint"]},
550 {"roughness", in["sheen_roughness"]},
551 {"normal", normal}});
552
553 NodeItem n_diffuse_bsdf = create_node("oren_nayar_diffuse_bsdf",
554 NodeItem::Type::BSDF,
555 {{"color", base_color.max(val(0.0f)) ^ n_coat_gamma},
556 {"roughness", diffuse_roughness},
557 {"weight", val(1.0f)},
558 {"normal", normal}});
559
560 NodeItem n_subsurface_mix = in["subsurface"].mix(n_diffuse_bsdf, n_subsurface_bsdf);
561
562 NodeItem n_sheen_layer = create_node(
563 "layer", NodeItem::Type::BSDF, {{"top", n_sheen_bsdf}, {"base", n_subsurface_mix}});
564
565 NodeItem n_transmission_mix = in["transmission"].mix(n_sheen_layer, n_transmission_bsdf);
566
567 NodeItem n_specular_layer = create_node(
568 "layer", NodeItem::Type::BSDF, {{"top", n_specular_bsdf}, {"base", n_transmission_mix}});
569
570 NodeItem n_metalness_mix = in["metallic"].mix(n_specular_layer, n_metal_bsdf);
571
572 NodeItem n_thin_film_layer = create_node(
573 "layer", NodeItem::Type::BSDF, {{"top", n_thin_film_bsdf}, {"base", n_metalness_mix}});
574
575 NodeItem n_coat_attenuation = coat.mix(val(MaterialX::Color3(1.0f, 1.0f, 1.0f)),
576 in["coat_tint"]);
577
578 res = create_node("layer",
579 NodeItem::Type::BSDF,
580 {{"top", n_coat_bsdf}, {"base", n_thin_film_layer * n_coat_attenuation}});
581 break;
582 }
583
584 case NodeItem::Type::EDF: {
585 auto in = edf_inputs();
586 res = create_node(
587 "uniform_edf", NodeItem::Type::EDF, {{"color", in["emission_color"] * in["emission"]}});
588 break;
589 }
590
591 case NodeItem::Type::SurfaceShader: {
592 auto in = bsdf_inputs();
593 auto e_in = edf_inputs();
594 in.insert(e_in.begin(), e_in.end());
595
596 NodeItem base_color = in["base_color"];
597
598 NodeItem anisotropy = in["anisotropic"];
599 NodeItem tangent = in["tangent"];
600 if (anisotropy) {
601 /* Anisotropy scaled down to approximately match the principled BSDF. */
602 anisotropy = anisotropy * val(0.7f);
603
604 /* Rotation is offset by 90 degrees and inverted to approximately align visually with
605 * principled BSDF direction. */
606 NodeItem rotation = -((in["anisotropic_rotation"] * val(360.0f)) + val(90.0f));
607
608 /* Only create a normal node locally if we need to use it to rotate the tangent vector.
609 * we don't actually pass this to the exported material. */
610 NodeItem normal = in["normal"];
611 if (!normal) {
612 const std::string world = "world";
613 normal =
614 create_node("normal", NodeItem::Type::Vector3, {{"space", val(world)}}).normalize();
615 }
616
617 if (!tangent) {
618 const std::string world = "world";
619 tangent =
620 create_node("tangent", NodeItem::Type::Vector3, {{"space", val(world)}}).normalize();
621 }
622
623 NodeItem n_tangent_rotate_normalize = tangent.rotate(rotation, normal).normalize();
624 tangent = anisotropy.if_else(
625 NodeItem::CompareOp::Greater, val(0.0f), n_tangent_rotate_normalize, tangent);
626 }
627
628 /* Enable OpenPBR thin film only if thickness > 0. */
629 NodeItem thin_film_thickness = in["thin_film_thickness"] * val(0.001f);
630 NodeItem thin_film_weight = thin_film_thickness.if_else(
631 NodeItem::CompareOp::Greater, val(0.0f), val(1.0f), val(0.0f));
632
633 /* "specular" here is "Specular IOR Level" in principled BSDF
634 * 0 = no specular
635 * 0.5 = full weight specular
636 * 1 = double specular weight */
637 NodeItem specular_weight = in["specular"] * val(2.0f);
638
639 res = create_node("open_pbr_surface",
640 NodeItem::Type::SurfaceShader,
641 {{"base_weight", val(1.0f)},
642 {"base_color", base_color},
643 {"base_diffuse_roughness", in["diffuse_roughness"]},
644 {"base_metalness", in["metallic"]},
645 {"specular_weight", specular_weight},
646 {"specular_color", in["specular_tint"]},
647 {"specular_roughness", in["roughness"]},
648 {"specular_ior", in["ior"]},
649 {"specular_roughness_anisotropy", anisotropy},
650 {"transmission_weight", in["transmission"]},
651 {"transmission_color", base_color},
652 {"subsurface_weight", in["subsurface"]},
653 {"subsurface_color", base_color},
654 {"subsurface_radius_scale", in["subsurface_radius"]},
655 {"subsurface_radius", in["subsurface_scale"]},
656 {"subsurface_scatter_anisotropy", in["subsurface_anisotropy"]},
657 {"fuzz_weight", in["sheen"]},
658 {"fuzz_color", in["sheen_tint"]},
659 {"fuzz_roughness", in["sheen_roughness"]},
660 {"coat_weight", in["coat"]},
661 {"coat_color", in["coat_tint"]},
662 {"coat_roughness", in["coat_roughness"]},
663 {"coat_ior", in["coat_ior"]},
664 /* Principled BSDF does not support anisotropy for the coat
665 * {"coat_roughness_anisotropy", anisotropic},
666 * {"geometry_coat_tangent", tangent}, */
667 {"emission_luminance", in["emission"]},
668 {"emission_color", in["emission_color"]},
669 {"thin_film_weight", thin_film_weight},
670 {"thin_film_thickness", thin_film_thickness},
671 {"thin_film_ior", in["thin_film_IOR"]},
672 {"geometry_normal", in["normal"]},
673 {"geometry_coat_normal", in["coat_normal"]},
674 {"geometry_tangent", tangent},
675 {"geometry_opacity", in["alpha"]}});
676 break;
677 }
678
679 case NodeItem::Type::SurfaceOpacity: {
680 res = get_input_value("Alpha", NodeItem::Type::Float);
681 break;
682 }
683
684 default:
686 }
687 return res;
688}
689#endif
691
692} // namespace blender::nodes::node_shader_bsdf_principled_cc
693
694/* node type definition */
696{
698
699 static blender::bke::bNodeType ntype;
700
701 sh_node_type_base(&ntype, "ShaderNodeBsdfPrincipled", SH_NODE_BSDF_PRINCIPLED);
702 ntype.ui_name = "Principled BSDF";
703 ntype.ui_description =
704 "Physically-based, easy-to-use shader for rendering surface materials, based on the OpenPBR "
705 "model";
706 ntype.enum_name_legacy = "BSDF_PRINCIPLED";
708 ntype.declare = file_ns::node_declare;
711 ntype.initfunc = file_ns::node_shader_init_principled;
712 ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_principled;
713 ntype.updatefunc = file_ns::node_shader_update_principled;
714 ntype.materialx_fn = file_ns::node_shader_materialx;
715
717}
#define NODE_CLASS_SHADER
Definition BKE_node.hh:446
#define SH_NODE_BSDF_PRINCIPLED
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLT_I18NCONTEXT_AMOUNT
#define BLT_I18NCONTEXT_ID_NODETREE
@ SOCK_IN
@ SHD_SUBSURFACE_BURLEY
@ SHD_SUBSURFACE_RANDOM_WALK_SKIN
@ SHD_SUBSURFACE_RANDOM_WALK
@ SHD_GLOSSY_MULTI_GGX
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
eGPUMaterialFlag
@ GPU_MATFLAG_GLOSSY
@ GPU_MATFLAG_COAT
@ GPU_MATFLAG_REFRACT
@ GPU_MATFLAG_DIFFUSE
@ GPU_MATFLAG_TRANSPARENT
@ GPU_MATFLAG_SUBSURFACE
void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag)
GPUNodeLink * GPU_attribute(GPUMaterial *mat, eCustomDataType type, const char *name)
bool GPU_link(GPUMaterial *mat, const char *name,...)
@ PROP_DISTANCE
Definition RNA_types.hh:244
@ PROP_FACTOR
Definition RNA_types.hh:239
@ PROP_WAVELENGTH
Definition RNA_types.hh:275
@ UI_ITEM_R_SPLIT_EMPTY_NAME
void add_layout(std::function< void(uiLayout *, bContext *, PointerRNA *)> draw)
DeclType::Builder & add_input(StringRef name, StringRef identifier="")
VecBase< float, D > normalize(VecOp< float, D >) RET
#define in
#define out
constexpr T clamp(T, U, U) RET
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2864
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
Definition node.cc:5011
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
Definition node.cc:5585
static void node_shader_init_principled(bNodeTree *, bNode *node)
static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void node_declare(NodeDeclarationBuilder &b)
static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
#define socket_not_one(sock)
#define SOCK_TRANSMISSION_WEIGHT_ID
#define socket_not_zero(sock)
#define SOCK_SUBSURFACE_WEIGHT_ID
#define SOCK_COAT_WEIGHT_ID
#define SOCK_METALLIC_ID
void register_node_type_sh_bsdf_principled()
#define SOCK_COAT_NORMAL_ID
#define SOCK_TANGENT_ID
#define SOCK_NORMAL_ID
#define SOCK_SHEEN_WEIGHT_ID
#define SOCK_ALPHA_ID
void sh_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
bool object_shader_nodes_poll(const bContext *C)
#define min(a, b)
Definition sort.cc:36
closure color sheen(normal N, float roughness) BUILTIN
int16_t custom1
int16_t custom2
Defines a node type.
Definition BKE_node.hh:226
NodeMaterialXFunction materialx_fn
Definition BKE_node.hh:332
std::string ui_description
Definition BKE_node.hh:232
bool(* add_ui_poll)(const bContext *C)
Definition BKE_node.hh:298
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:277
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:330
const char * enum_name_legacy
Definition BKE_node.hh:235
NodeDeclareFunction declare
Definition BKE_node.hh:355
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:269
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:4226
uint8_t flag
Definition wm_window.cc:139