25 b.use_custom_socket_order();
30 .default_value({0.8f, 0.8f, 0.8f, 1.0f})
32 "Color of the material used for diffuse, subsurface, metallic and transmission");
33#define SOCK_BASE_COLOR_ID 0
40 "Blends between a dielectric and metallic material model. "
41 "At 0.0 the material consists of a diffuse or transmissive base layer, "
42 "with a specular reflection layer on top. A value of 1.0 gives a fully specular "
43 "reflection tinted with the base color, without diffuse reflection or transmission");
44#define SOCK_METALLIC_ID 1
51 "Specifies microfacet roughness of the surface for specular reflection and transmission"
52 " (0.0 is a perfect mirror reflection, 1.0 is completely rough)");
53#define SOCK_ROUGHNESS_ID 2
55 "Index of Refraction (IOR) for specular reflection and transmission. "
56 "For most materials, the IOR is between 1.0 (vacuum and air) and 4.0 (germanium). "
57 "The default value of 1.5 is a good approximation for glass");
64 .description(
"Controls the transparency of the surface, with 1.0 fully opaque");
65#define SOCK_ALPHA_ID 4
67#define SOCK_NORMAL_ID 5
69#define SOCK_WEIGHT_ID 6
79 "Specifies microfacet roughness of the diffuse base"
80 " (0.0 is perfect lambertian reflection, 1.0 is completely rough)");
81#define SOCK_DIFFUSE_ROUGHNESS_ID 7
85 b.add_panel(
"Subsurface")
95 .short_label(
"Weight")
97 "Blend between diffuse surface and subsurface scattering. "
98 "Typically should be zero or one (either fully diffuse or subsurface)");
99#define SOCK_SUBSURFACE_WEIGHT_ID 8
101 .default_value({1.0f, 0.2f, 0.1f})
105 .description(
"Scattering radius to use for subsurface component (multiplied with Scale)");
106#define SOCK_SUBSURFACE_RADIUS_ID 9
108 .default_value(0.05f)
112 .short_label(
"Scale")
113 .description(
"Scale of the subsurface scattering (multiplied with Radius)");
114#define SOCK_SUBSURFACE_SCALE_ID 10
121 .description(
"Index of Refraction (IOR) used for rays that enter the subsurface component");
122#define SOCK_SUBSURFACE_IOR_ID 11
128 .short_label(
"Anisotropy")
130 "Directionality of volume scattering within the subsurface medium. "
131 "Zero scatters uniformly in all directions, with higher values "
132 "scattering more strongly forward. For example, skin has been measured "
133 "to have an anisotropy of 0.8");
134#define SOCK_SUBSURFACE_ANISOTROPY_ID 12
138 b.add_panel(
"Specular")
139 .default_closed(
true)
148 .short_label(
"IOR Level")
150 "Adjustment to the Index of Refraction (IOR) to increase or decrease specular intensity "
151 "(0.5 means no adjustment, 0 removes all reflections, 1 doubles them at normal "
153#define SOCK_SPECULAR_ID 13
155 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
158 "Tint dielectric reflection at normal incidence for artistic control, and metallic "
159 "reflection at near-grazing incidence to simulate complex index of refraction")
161#define SOCK_SPECULAR_TINT_ID 14
168 "Amount of anisotropy for specular reflection. "
169 "Higher values give elongated highlights along the tangent direction");
170#define SOCK_ANISOTROPIC_ID 15
176 .description(
"Rotates the direction of anisotropy, with 1.0 going full circle");
177#define SOCK_ANISOTROPIC_ROTATION_ID 16
179 "Controls the tangent direction for anisotropy");
180#define SOCK_TANGENT_ID 17
184 transmission.add_input<
decl::Float>(
"Transmission Weight")
189 .short_label(
"Weight")
190 .description(
"Blend between transmission and other base layer components");
191#define SOCK_TRANSMISSION_WEIGHT_ID 18
200 .short_label(
"Weight")
202 "Controls the intensity of the coat layer, both the reflection and the tinting. "
203 "Typically should be zero or one for physically-based materials");
204#define SOCK_COAT_WEIGHT_ID 19
206 .default_value(0.03f)
210 .short_label(
"Roughness")
211 .description(
"The roughness of the coat layer");
212#define SOCK_COAT_ROUGHNESS_ID 20
219 "The Index of Refraction (IOR) of the coat layer "
220 "(affects its reflectivity as well as the falloff of coat tinting)");
221#define SOCK_COAT_IOR_ID 21
223 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
226 "Adds a colored tint to the coat layer by modeling absorption in the layer. "
227 "Saturation increases at shallower angles, as the light travels farther "
228 "through the medium (depending on the Coat IOR)")
230#define SOCK_COAT_TINT_ID 22
232#define SOCK_COAT_NORMAL_ID 23
241 .short_label(
"Weight");
242#define SOCK_SHEEN_WEIGHT_ID 24
248 .short_label(
"Roughness");
249#define SOCK_SHEEN_ROUGHNESS_ID 25
251 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
254#define SOCK_SHEEN_TINT_ID 26
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
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#define SOCK_EMISSION_STRENGTH_ID 28
280#define SOCK_THIN_FILM_THICKNESS_ID 29
281 film.add_input<
decl::Float>(
"Thin Film IOR").default_value(1.33f).min(1.0f).max(1000.0f);
282#define SOCK_THIN_FILM_IOR_ID 30
291#define socket_not_zero(sock) (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) > 1e-5f))
292#define socket_not_one(sock) \
293 (in[sock].link || (clamp_f(in[sock].vec[0], 0.0f, 1.0f) < 1.0f - 1e-5f))
339 if (use_transparency) {
359 mat, node,
"node_bsdf_principled", in, out,
GPU_constant(&use_multi_scatter));
364 const int sss_method = node->custom2;
377 using InputsType = std::map<std::string, NodeItem>;
380 auto bsdf_inputs = [&]() -> InputsType {
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 {
"subsurface_radius", get_input_value(
"Subsurface Radius", NodeItem::Type::Vector3)},
388 {
"subsurface_anisotropy", get_input_value(
"Subsurface Anisotropy", NodeItem::Type::Float)},
389 {
"metallic", get_input_value(
"Metallic", NodeItem::Type::Float)},
390 {
"specular", get_input_value(
"Specular IOR Level", NodeItem::Type::Float)},
391 {
"specular_tint", get_input_value(
"Specular Tint", NodeItem::Type::Color3)},
392 {
"roughness", get_input_value(
"Roughness", NodeItem::Type::Float)},
393 {
"anisotropic", get_input_value(
"Anisotropic", NodeItem::Type::Float)},
394 {
"anisotropic_rotation", get_input_value(
"Anisotropic Rotation", NodeItem::Type::Float)},
395 {
"sheen", get_input_value(
"Sheen Weight", NodeItem::Type::Float)},
396 {
"sheen_roughness", get_input_value(
"Sheen Roughness", NodeItem::Type::Float)},
397 {
"sheen_tint", get_input_value(
"Sheen Tint", NodeItem::Type::Color3)},
398 {
"coat", get_input_value(
"Coat Weight", NodeItem::Type::Float)},
399 {
"coat_roughness", get_input_value(
"Coat Roughness", NodeItem::Type::Float)},
400 {
"coat_ior", get_input_value(
"Coat IOR", NodeItem::Type::Float)},
401 {
"coat_tint", get_input_value(
"Coat Tint", NodeItem::Type::Color3)},
402 {
"ior", get_input_value(
"IOR", NodeItem::Type::Float)},
403 {
"transmission", get_input_value(
"Transmission Weight", NodeItem::Type::Float)},
404 {
"thin_film_thickness", get_input_value(
"Thin Film Thickness", NodeItem::Type::Float)},
405 {
"thin_film_IOR", get_input_value(
"Thin Film IOR", NodeItem::Type::Float)},
406 {
"alpha", get_input_value(
"Alpha", NodeItem::Type::Float)},
407 {
"normal", get_input_link(
"Normal", NodeItem::Type::Vector3)},
408 {
"coat_normal", get_input_link(
"Coat Normal", NodeItem::Type::Vector3)},
409 {
"tangent", get_input_link(
"Tangent", NodeItem::Type::Vector3)},
413 auto edf_inputs = [&]() -> InputsType {
415 {
"emission", get_input_value(
"Emission Strength", NodeItem::Type::Float)},
416 {
"emission_color", get_input_value(
"Emission Color", NodeItem::Type::Color3)},
420 NodeItem res = empty();
423 case NodeItem::Type::BSDF: {
424 auto in = bsdf_inputs();
426 NodeItem roughness = in[
"roughness"];
427 NodeItem diffuse_roughness = in[
"diffuse_roughness"];
428 NodeItem anisotropy = in[
"anisotropic"];
429 NodeItem rotation = in[
"anisotropic_rotation"] * val(360.0f);
430 NodeItem base_color = in[
"base_color"];
431 NodeItem specular = in[
"specular"];
432 NodeItem coat = in[
"coat"];
433 NodeItem ior = in[
"ior"];
434 NodeItem normal = in[
"normal"];
435 NodeItem tangent = in[
"tangent"];
436 NodeItem coat_normal = in[
"coat_normal"];
438 NodeItem n_main_tangent = empty();
439 if (tangent && normal) {
440 NodeItem n_tangent_rotate_normalize = tangent.rotate(rotation, normal).normalize();
441 n_main_tangent = anisotropy.if_else(
442 NodeItem::CompareOp::Greater, val(0.0f), n_tangent_rotate_normalize, tangent);
445 NodeItem n_coat_roughness_vector = create_node(
446 "roughness_anisotropy",
447 NodeItem::Type::Vector2,
448 {{
"roughness", in[
"coat_roughness"]}, {
"anisotropy", anisotropy}});
450 NodeItem n_coat_bsdf = create_node(
"dielectric_bsdf",
451 NodeItem::Type::BSDF,
453 {
"tint", in[
"coat_tint"]},
454 {
"ior", in[
"coat_ior"]},
455 {
"scatter_mode", val(std::string(
"R"))},
456 {
"roughness", n_coat_roughness_vector},
457 {
"normal", coat_normal}});
459 if (tangent && coat_normal) {
460 NodeItem n_coat_tangent_rotate_normalize =
461 tangent.rotate(rotation, coat_normal).normalize();
462 NodeItem n_coat_tangent = anisotropy.if_else(
463 NodeItem::CompareOp::Greater, val(0.0f), n_coat_tangent_rotate_normalize, tangent);
465 n_coat_bsdf.set_input(
"tangent", n_coat_tangent);
468 NodeItem thin_film_thickness = in[
"thin_film_thickness"];
469 NodeItem thin_film_ior = in[
"thin_film_IOR"];
470 NodeItem n_thin_film_bsdf = create_node(
472 NodeItem::Type::BSDF,
473 {{
"thickness", thin_film_thickness}, {
"ior", thin_film_ior}});
475 NodeItem n_artistic_ior = create_node(
477 NodeItem::Type::Multioutput,
478 {{
"reflectivity", base_color * val(1.0f)}, {
"edge_color", base_color * specular}});
480 NodeItem n_ior_out = n_artistic_ior.add_output(
"ior", NodeItem::Type::Color3);
481 NodeItem n_extinction_out = n_artistic_ior.add_output(
"extinction", NodeItem::Type::Color3);
483 NodeItem n_coat_affect_roughness_multiply2 = coat * val(0.0f) * in[
"coat_roughness"];
484 NodeItem n_coat_affected_roughness = n_coat_affect_roughness_multiply2.mix(roughness,
487 NodeItem n_main_roughness = create_node(
488 "roughness_anisotropy",
489 NodeItem::Type::Vector2,
490 {{
"roughness", n_coat_affected_roughness}, {
"anisotropy", anisotropy}});
492 NodeItem n_metal_bsdf = create_node(
"conductor_bsdf",
493 NodeItem::Type::BSDF,
495 {
"extinction", n_extinction_out},
496 {
"roughness", n_main_roughness},
498 {
"tangent", n_main_tangent}});
500 NodeItem n_specular_bsdf = create_node(
"dielectric_bsdf",
501 NodeItem::Type::BSDF,
502 {{
"weight", specular},
503 {
"tint", in[
"specular_tint"]},
505 {
"scatter_mode", val(std::string(
"R"))},
506 {
"roughness", n_main_roughness},
508 {
"tangent", n_main_tangent}});
510 NodeItem n_coat_affected_transmission_roughness = n_coat_affect_roughness_multiply2.mix(
511 (roughness + roughness).clamp(), val(1.0f));
513 NodeItem n_transmission_roughness = create_node(
514 "roughness_anisotropy",
515 NodeItem::Type::Vector2,
516 {{
"roughness", n_coat_affected_transmission_roughness}, {
"anisotropy", anisotropy}});
518 NodeItem n_transmission_bsdf = create_node(
"dielectric_bsdf",
519 NodeItem::Type::BSDF,
520 {{
"tint", base_color},
522 {
"roughness", n_transmission_roughness},
524 {
"tangent", n_main_tangent}});
526 NodeItem n_coat_gamma = coat.clamp(0.0f, 1.0f) * val(0.0f) + val(1.0f);
527 NodeItem n_coat_affected_subsurface_color = base_color.max(val(0.0f)) ^ n_coat_gamma;
528 NodeItem n_translucent_bsdf = create_node(
530 NodeItem::Type::BSDF,
531 {{
"color", n_coat_affected_subsurface_color}, {
"normal", normal}});
533 NodeItem n_subsurface_bsdf = create_node(
535 NodeItem::Type::BSDF,
536 {{
"color", n_coat_affected_subsurface_color},
537 {
"radius", in[
"subsurface_radius"] * in[
"subsurface_scale"]},
538 {
"anisotropy", in[
"subsurface_anisotropy"]},
539 {
"normal", normal}});
541 NodeItem n_sheen_bsdf = create_node(
"sheen_bsdf",
542 NodeItem::Type::BSDF,
543 {{
"weight", in[
"sheen"]},
544 {
"color", in[
"sheen_tint"]},
545 {
"roughness", in[
"sheen_roughness"]},
546 {
"normal", normal}});
548 NodeItem n_diffuse_bsdf = create_node(
"oren_nayar_diffuse_bsdf",
549 NodeItem::Type::BSDF,
550 {{
"color", base_color.max(val(0.0f)) ^ n_coat_gamma},
551 {
"roughness", diffuse_roughness},
552 {
"weight", val(1.0f)},
553 {
"normal", normal}});
555 NodeItem n_subsurface_mix = in[
"subsurface"].mix(n_diffuse_bsdf, n_subsurface_bsdf);
557 NodeItem n_sheen_layer = create_node(
558 "layer", NodeItem::Type::BSDF, {{
"top", n_sheen_bsdf}, {
"base", n_subsurface_mix}});
560 NodeItem n_transmission_mix = in[
"transmission"].mix(n_sheen_layer, n_transmission_bsdf);
562 NodeItem n_specular_layer = create_node(
563 "layer", NodeItem::Type::BSDF, {{
"top", n_specular_bsdf}, {
"base", n_transmission_mix}});
565 NodeItem n_metalness_mix = in[
"metallic"].mix(n_specular_layer, n_metal_bsdf);
567 NodeItem n_thin_film_layer = create_node(
568 "layer", NodeItem::Type::BSDF, {{
"top", n_thin_film_bsdf}, {
"base", n_metalness_mix}});
570 NodeItem n_coat_attenuation = coat.mix(val(MaterialX::Color3(1.0f, 1.0f, 1.0f)),
573 res = create_node(
"layer",
574 NodeItem::Type::BSDF,
575 {{
"top", n_coat_bsdf}, {
"base", n_thin_film_layer * n_coat_attenuation}});
579 case NodeItem::Type::EDF: {
580 auto in = edf_inputs();
582 "uniform_edf", NodeItem::Type::EDF, {{
"color", in[
"emission_color"] * in[
"emission"]}});
586 case NodeItem::Type::SurfaceShader: {
587 auto in = bsdf_inputs();
588 auto e_in = edf_inputs();
589 in.insert(e_in.begin(), e_in.end());
591 NodeItem roughness = in[
"roughness"];
592 NodeItem base_color = in[
"base_color"];
593 NodeItem anisotropic = in[
"anisotropic"];
594 NodeItem rotation = in[
"anisotropic_rotation"];
598 NodeItem::Type::SurfaceShader,
599 {{
"base", val(1.0f)},
600 {
"base_color", base_color},
601 {
"diffuse_roughness", in[
"diffuse_roughness"]},
602 {
"metalness", in[
"metallic"]},
603 {
"specular", in[
"specular"]},
604 {
"specular_color", in[
"specular_tint"]},
605 {
"specular_roughness", roughness},
606 {
"specular_IOR", in[
"ior"]},
607 {
"specular_anisotropy", anisotropic},
608 {
"specular_rotation", rotation},
609 {
"transmission", in[
"transmission"]},
610 {
"transmission_color", base_color},
611 {
"transmission_extra_roughness", roughness},
612 {
"subsurface", in[
"subsurface"]},
613 {
"subsurface_color", base_color},
614 {
"subsurface_radius",
615 (in[
"subsurface_radius"] * in[
"subsurface_scale"]).
convert(NodeItem::Type::Color3)},
616 {
"subsurface_anisotropy", in[
"subsurface_anisotropy"]},
617 {
"sheen", in[
"sheen"]},
618 {
"sheen_color", in[
"sheen_tint"]},
619 {
"sheen_roughness", in[
"sheen_roughness"]},
620 {
"coat", in[
"coat"]},
621 {
"coat_color", in[
"coat_tint"]},
622 {
"coat_roughness", in[
"coat_roughness"]},
623 {
"coat_IOR", in[
"coat_ior"]},
624 {
"coat_anisotropy", anisotropic},
625 {
"coat_rotation", rotation},
626 {
"coat_normal", in[
"coat_normal"]},
627 {
"emission", in[
"emission"]},
628 {
"emission_color", in[
"emission_color"]},
629 {
"thin_film_thickness", in[
"thin_film_thickness"]},
630 {
"thin_film_IOR", in[
"thin_film_IOR"]},
631 {
"normal", in[
"normal"]},
632 {
"tangent", in[
"tangent"]},
633 {
"opacity", in[
"alpha"].convert(NodeItem::Type::Color3)}});
637 case NodeItem::Type::SurfaceOpacity: {
638 res = get_input_value(
"Alpha", NodeItem::Type::Float);