23 b.use_custom_socket_order();
28 .default_value({0.8f, 0.8f, 0.8f, 1.0f})
30 "Color of the material used for diffuse, subsurface, metallic and transmission");
31#define SOCK_BASE_COLOR_ID 0
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
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
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");
62 .description(
"Controls the transparency of the surface, with 1.0 fully opaque");
63#define SOCK_ALPHA_ID 4
65#define SOCK_NORMAL_ID 5
67#define SOCK_WEIGHT_ID 6
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
91 .short_label(
"Weight")
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
97 .default_value({1.0f, 0.2f, 0.1f})
101 .description(
"Scattering radius per color channel (RGB), multiplied with Scale");
102#define SOCK_SUBSURFACE_RADIUS_ID 9
104 .default_value(0.05f)
108 .short_label(
"Scale")
109 .description(
"Scale factor of the subsurface scattering radius");
110#define SOCK_SUBSURFACE_SCALE_ID 10
117 .description(
"Index of Refraction (IOR) used for rays that enter the subsurface component");
118#define SOCK_SUBSURFACE_IOR_ID 11
124 .short_label(
"Anisotropy")
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
142 .short_label(
"IOR Level")
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 "
147#define SOCK_SPECULAR_ID 13
149 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
152 "Tint dielectric reflection at normal incidence for artistic control, and metallic "
153 "reflection at near-grazing incidence to simulate complex index of refraction")
155#define SOCK_SPECULAR_TINT_ID 14
162 "Amount of anisotropy for specular reflection. "
163 "Higher values give elongated highlights along the tangent direction");
164#define SOCK_ANISOTROPIC_ID 15
170 .description(
"Rotates the direction of anisotropy, with 1.0 going full circle");
171#define SOCK_ANISOTROPIC_ROTATION_ID 16
173 "Controls the tangent direction for anisotropy");
174#define SOCK_TANGENT_ID 17
183 .short_label(
"Weight")
184 .description(
"Blend between transmission and other base layer components");
185#define SOCK_TRANSMISSION_WEIGHT_ID 18
194 .short_label(
"Weight")
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
200 .default_value(0.03f)
204 .short_label(
"Roughness")
205 .description(
"The roughness of the coat layer");
206#define SOCK_COAT_ROUGHNESS_ID 20
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
217 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
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)")
224#define SOCK_COAT_TINT_ID 22
226#define SOCK_COAT_NORMAL_ID 23
235 .short_label(
"Weight")
237 "Intensity of the sheen layer, which simulates very small fibers on the surface");
238#define SOCK_SHEEN_WEIGHT_ID 24
244 .short_label(
"Roughness")
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
250 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
253 .description(
"Color of the sheen reflection");
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")
272#define SOCK_EMISSION_STRENGTH_ID 28
281 .description(
"Thickness of the film in nanometers");
282#define SOCK_THIN_FILM_THICKNESS_ID 29
284 .default_value(1.33f)
287 .
description(
"Index of refraction (IOR) of the thin film");
288#define SOCK_THIN_FILM_IOR_ID 30
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))
345 if (use_transparency) {
362 const int sss_method = node->
custom2;
376 using InputsType = std::map<std::string, NodeItem>;
379 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# if MATERIALX_MAJOR_VERSION <= 1 && MATERIALX_MINOR_VERSION <= 38
387 {
"subsurface_radius", get_input_value(
"Subsurface Radius", NodeItem::Type::Vector3)},
389 {
"subsurface_radius", get_input_value(
"Subsurface Radius", NodeItem::Type::Color3)},
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)},
418 auto edf_inputs = [&]() -> InputsType {
420 {
"emission", get_input_value(
"Emission Strength", NodeItem::Type::Float)},
421 {
"emission_color", get_input_value(
"Emission Color", NodeItem::Type::Color3)},
425 NodeItem res = empty();
428 case NodeItem::Type::BSDF: {
429 auto in = bsdf_inputs();
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"];
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);
450 NodeItem n_coat_roughness_vector = create_node(
451 "roughness_anisotropy",
452 NodeItem::Type::Vector2,
453 {{
"roughness",
in[
"coat_roughness"]}, {
"anisotropy", anisotropy}});
455 NodeItem n_coat_bsdf = create_node(
"dielectric_bsdf",
456 NodeItem::Type::BSDF,
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}});
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);
470 n_coat_bsdf.set_input(
"tangent", n_coat_tangent);
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(
477 NodeItem::Type::BSDF,
478 {{
"thickness", thin_film_thickness}, {
"ior", thin_film_ior}});
480 NodeItem n_artistic_ior = create_node(
482 NodeItem::Type::Multioutput,
483 {{
"reflectivity", base_color * val(1.0f)}, {
"edge_color", base_color * specular}});
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);
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,
492 NodeItem n_main_roughness = create_node(
493 "roughness_anisotropy",
494 NodeItem::Type::Vector2,
495 {{
"roughness", n_coat_affected_roughness}, {
"anisotropy", anisotropy}});
497 NodeItem n_metal_bsdf = create_node(
"conductor_bsdf",
498 NodeItem::Type::BSDF,
500 {
"extinction", n_extinction_out},
501 {
"roughness", n_main_roughness},
503 {
"tangent", n_main_tangent}});
505 NodeItem n_specular_bsdf = create_node(
"dielectric_bsdf",
506 NodeItem::Type::BSDF,
507 {{
"weight", specular},
508 {
"tint",
in[
"specular_tint"]},
510 {
"scatter_mode", val(std::string(
"R"))},
511 {
"roughness", n_main_roughness},
513 {
"tangent", n_main_tangent}});
515 NodeItem n_coat_affected_transmission_roughness = n_coat_affect_roughness_multiply2.mix(
516 (roughness + roughness).
clamp(), val(1.0f));
518 NodeItem n_transmission_roughness = create_node(
519 "roughness_anisotropy",
520 NodeItem::Type::Vector2,
521 {{
"roughness", n_coat_affected_transmission_roughness}, {
"anisotropy", anisotropy}});
523 NodeItem n_transmission_bsdf = create_node(
"dielectric_bsdf",
524 NodeItem::Type::BSDF,
525 {{
"tint", base_color},
527 {
"roughness", n_transmission_roughness},
529 {
"tangent", n_main_tangent}});
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(
535 NodeItem::Type::BSDF,
536 {{
"color", n_coat_affected_subsurface_color}, {
"normal", normal}});
538 NodeItem n_subsurface_bsdf = create_node(
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}});
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}});
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}});
560 NodeItem n_subsurface_mix =
in[
"subsurface"].mix(n_diffuse_bsdf, n_subsurface_bsdf);
562 NodeItem n_sheen_layer = create_node(
563 "layer", NodeItem::Type::BSDF, {{
"top", n_sheen_bsdf}, {
"base", n_subsurface_mix}});
565 NodeItem n_transmission_mix =
in[
"transmission"].mix(n_sheen_layer, n_transmission_bsdf);
567 NodeItem n_specular_layer = create_node(
568 "layer", NodeItem::Type::BSDF, {{
"top", n_specular_bsdf}, {
"base", n_transmission_mix}});
570 NodeItem n_metalness_mix =
in[
"metallic"].mix(n_specular_layer, n_metal_bsdf);
572 NodeItem n_thin_film_layer = create_node(
573 "layer", NodeItem::Type::BSDF, {{
"top", n_thin_film_bsdf}, {
"base", n_metalness_mix}});
575 NodeItem n_coat_attenuation = coat.mix(val(MaterialX::Color3(1.0f, 1.0f, 1.0f)),
578 res = create_node(
"layer",
579 NodeItem::Type::BSDF,
580 {{
"top", n_coat_bsdf}, {
"base", n_thin_film_layer * n_coat_attenuation}});
584 case NodeItem::Type::EDF: {
585 auto in = edf_inputs();
587 "uniform_edf", NodeItem::Type::EDF, {{
"color",
in[
"emission_color"] *
in[
"emission"]}});
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());
596 NodeItem base_color =
in[
"base_color"];
598 NodeItem anisotropy =
in[
"anisotropic"];
599 NodeItem tangent =
in[
"tangent"];
602 anisotropy = anisotropy * val(0.7f);
606 NodeItem rotation = -((
in[
"anisotropic_rotation"] * val(360.0f)) + val(90.0f));
610 NodeItem normal =
in[
"normal"];
612 const std::string world =
"world";
614 create_node(
"normal", NodeItem::Type::Vector3, {{
"space", val(world)}}).
normalize();
618 const std::string world =
"world";
620 create_node(
"tangent", NodeItem::Type::Vector3, {{
"space", val(world)}}).
normalize();
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);
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));
637 NodeItem specular_weight =
in[
"specular"] * val(2.0f);
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"]},
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"]}});
679 case NodeItem::Type::SurfaceOpacity: {
680 res = get_input_value(
"Alpha", NodeItem::Type::Float);