Blender V5.0
shader_nodes.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
6#include "kernel/svm/types.h"
7#include "kernel/types.h"
8#include "scene/colorspace.h"
10#include "scene/film.h"
11#include "scene/image.h"
12#include "scene/image_sky.h"
13#include "scene/integrator.h"
14#include "scene/light.h"
15#include "scene/mesh.h"
16#include "scene/osl.h"
17#include "scene/scene.h"
18#include "scene/svm.h"
19
20#include "sky_hosek.h"
21#include "sky_nishita.h"
22
23#include "util/color.h"
24
25#include "util/log.h"
26#include "util/math_base.h"
27#include "util/string.h"
28#include "util/transform.h"
29
34
36
37/* Texture Mapping */
38
39#define TEXTURE_MAPPING_DEFINE(TextureNode) \
40 SOCKET_POINT(tex_mapping.translation, "Translation", zero_float3()); \
41 SOCKET_VECTOR(tex_mapping.rotation, "Rotation", zero_float3()); \
42 SOCKET_VECTOR(tex_mapping.scale, "Scale", one_float3()); \
43\
44 SOCKET_VECTOR(tex_mapping.min, "Min", make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); \
45 SOCKET_VECTOR(tex_mapping.max, "Max", make_float3(FLT_MAX, FLT_MAX, FLT_MAX)); \
46 SOCKET_BOOLEAN(tex_mapping.use_minmax, "Use Min Max", false); \
47\
48 static NodeEnum mapping_axis_enum; \
49 mapping_axis_enum.insert("none", TextureMapping::NONE); \
50 mapping_axis_enum.insert("x", TextureMapping::X); \
51 mapping_axis_enum.insert("y", TextureMapping::Y); \
52 mapping_axis_enum.insert("z", TextureMapping::Z); \
53 SOCKET_ENUM(tex_mapping.x_mapping, "x_mapping", mapping_axis_enum, TextureMapping::X); \
54 SOCKET_ENUM(tex_mapping.y_mapping, "y_mapping", mapping_axis_enum, TextureMapping::Y); \
55 SOCKET_ENUM(tex_mapping.z_mapping, "z_mapping", mapping_axis_enum, TextureMapping::Z); \
56\
57 static NodeEnum mapping_type_enum; \
58 mapping_type_enum.insert("point", TextureMapping::POINT); \
59 mapping_type_enum.insert("texture", TextureMapping::TEXTURE); \
60 mapping_type_enum.insert("vector", TextureMapping::VECTOR); \
61 mapping_type_enum.insert("normal", TextureMapping::NORMAL); \
62 SOCKET_ENUM(tex_mapping.type, "Type", mapping_type_enum, TextureMapping::TEXTURE); \
63\
64 static NodeEnum mapping_projection_enum; \
65 mapping_projection_enum.insert("flat", TextureMapping::FLAT); \
66 mapping_projection_enum.insert("cube", TextureMapping::CUBE); \
67 mapping_projection_enum.insert("tube", TextureMapping::TUBE); \
68 mapping_projection_enum.insert("sphere", TextureMapping::SPHERE); \
69 SOCKET_ENUM(tex_mapping.projection, "Projection", mapping_projection_enum, TextureMapping::FLAT);
70
72
74{
76
77 if (x_mapping != NONE) {
78 mmat[0][x_mapping - 1] = 1.0f;
79 }
80 if (y_mapping != NONE) {
81 mmat[1][y_mapping - 1] = 1.0f;
82 }
83 if (z_mapping != NONE) {
84 mmat[2][z_mapping - 1] = 1.0f;
85 }
86
87 float3 scale_clamped = scale;
88
89 if (type == TEXTURE || type == NORMAL) {
90 /* keep matrix invertible */
91 if (fabsf(scale.x) < 1e-5f) {
92 scale_clamped.x = signf(scale.x) * 1e-5f;
93 }
94 if (fabsf(scale.y) < 1e-5f) {
95 scale_clamped.y = signf(scale.y) * 1e-5f;
96 }
97 if (fabsf(scale.z) < 1e-5f) {
98 scale_clamped.z = signf(scale.z) * 1e-5f;
99 }
100 }
101
102 const Transform smat = transform_scale(scale_clamped);
103 const Transform rmat = transform_euler(rotation);
105
106 Transform mat;
107
108 switch (type) {
109 case TEXTURE:
110 /* inverse transform on texture coordinate gives
111 * forward transform on texture */
112 mat = tmat * rmat * smat;
113 mat = transform_inverse(mat);
114 break;
115 case POINT:
116 /* full transform */
117 mat = tmat * rmat * smat;
118 break;
119 case VECTOR:
120 /* no translation for vectors */
121 mat = rmat * smat;
122 break;
123 case NORMAL:
124 /* no translation for normals, and inverse transpose */
125 mat = rmat * smat;
127 break;
128 }
129
130 /* projection last */
131 mat = mat * mmat;
132
133 return mat;
134}
135
137{
138 if (translation != zero_float3()) {
139 return false;
140 }
141 if (rotation != zero_float3()) {
142 return false;
143 }
144 if (scale != one_float3()) {
145 return false;
146 }
147
148 if (x_mapping != X || y_mapping != Y || z_mapping != Z) {
149 return false;
150 }
151 if (use_minmax) {
152 return false;
153 }
154
155 return true;
156}
157
158void TextureMapping::compile(SVMCompiler &compiler, const int offset_in, const int offset_out)
159{
160 compiler.add_node(NODE_TEXTURE_MAPPING, offset_in, offset_out);
161
162 const Transform tfm = compute_transform();
163 compiler.add_node(tfm.x);
164 compiler.add_node(tfm.y);
165 compiler.add_node(tfm.z);
166
167 if (use_minmax) {
168 compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
169 compiler.add_node(make_float4(min));
170 compiler.add_node(make_float4(max));
171 }
172
173 if (type == NORMAL) {
174 compiler.add_node(NODE_VECTOR_MATH,
176 compiler.encode_uchar4(offset_out, offset_out, offset_out),
177 compiler.encode_uchar4(SVM_STACK_INVALID, offset_out));
178 }
179}
180
181/* Convenience function for texture nodes, allocating stack space to output
182 * a modified vector and returning its offset */
184{
185 if (!skip()) {
186 const int offset_in = compiler.stack_assign(vector_in);
187 const int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
188
189 compile(compiler, offset_in, offset_out);
190
191 return offset_out;
192 }
193
194 return compiler.stack_assign(vector_in);
195}
196
198 ShaderInput *vector_in,
199 const int vector_offset)
200{
201 if (!skip()) {
202 compiler.stack_clear_offset(vector_in->type(), vector_offset);
203 }
204}
205
207{
208 if (!skip()) {
209 compiler.parameter("mapping", compute_transform());
210 compiler.parameter("use_mapping", 1);
211 }
212}
213
214/* Image Texture */
215
217{
218 NodeType *type = NodeType::add("image_texture", create, NodeType::SHADER);
219
221
222 SOCKET_STRING(filename, "Filename", ustring());
223 SOCKET_STRING(colorspace, "Colorspace", u_colorspace_auto);
224
225 static NodeEnum alpha_type_enum;
226 alpha_type_enum.insert("auto", IMAGE_ALPHA_AUTO);
227 alpha_type_enum.insert("unassociated", IMAGE_ALPHA_UNASSOCIATED);
228 alpha_type_enum.insert("associated", IMAGE_ALPHA_ASSOCIATED);
229 alpha_type_enum.insert("channel_packed", IMAGE_ALPHA_CHANNEL_PACKED);
230 alpha_type_enum.insert("ignore", IMAGE_ALPHA_IGNORE);
231 SOCKET_ENUM(alpha_type, "Alpha Type", alpha_type_enum, IMAGE_ALPHA_AUTO);
232
233 static NodeEnum interpolation_enum;
234 interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
235 interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
236 interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
237 interpolation_enum.insert("smart", INTERPOLATION_SMART);
238 SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
239
240 static NodeEnum extension_enum;
241 extension_enum.insert("periodic", EXTENSION_REPEAT);
242 extension_enum.insert("clamp", EXTENSION_EXTEND);
243 extension_enum.insert("black", EXTENSION_CLIP);
244 extension_enum.insert("mirror", EXTENSION_MIRROR);
245 SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT);
246
247 static NodeEnum projection_enum;
248 projection_enum.insert("flat", NODE_IMAGE_PROJ_FLAT);
249 projection_enum.insert("box", NODE_IMAGE_PROJ_BOX);
250 projection_enum.insert("sphere", NODE_IMAGE_PROJ_SPHERE);
251 projection_enum.insert("tube", NODE_IMAGE_PROJ_TUBE);
252 SOCKET_ENUM(projection, "Projection", projection_enum, NODE_IMAGE_PROJ_FLAT);
253
254 SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f);
255
256 SOCKET_INT_ARRAY(tiles, "Tiles", array<int>());
257 SOCKET_BOOLEAN(animated, "Animated", false);
258
260
261 SOCKET_OUT_COLOR(color, "Color");
262 SOCKET_OUT_FLOAT(alpha, "Alpha");
263
264 return type;
265}
266
267ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(get_node_type())
268{
269 colorspace = u_colorspace_raw;
270 animated = false;
271}
272
274{
275 ImageTextureNode *node = graph->create_node<ImageTextureNode>(*this);
276 node->handle = handle;
277 return node;
278}
279
281{
283 params.animated = animated;
284 params.interpolation = interpolation;
285 params.extension = extension;
286 params.alpha_type = alpha_type;
287 params.colorspace = colorspace;
288 return params;
289}
290
292{
293 /* Box projection computes its own UVs that always lie in the
294 * 1001 tile, so there's no point in loading any others. */
295 if (projection == NODE_IMAGE_PROJ_BOX) {
296 if (tiles.size()) {
297 tiles.clear();
298 tiles.push_back_slow(1001);
299 }
300 return;
301 }
302
303 if (!scene->params.background) {
304 /* During interactive renders, all tiles are loaded.
305 * While we could support updating this when UVs change, that could lead
306 * to annoying interruptions when loading images while editing UVs. */
307 return;
308 }
309
310 /* Only check UVs for tile culling when using tiles. */
311 if (tiles.size() == 0) {
312 return;
313 }
314
315 ShaderInput *vector_in = input("Vector");
316 ustring attribute;
317 if (vector_in->link) {
318 ShaderNode *node = vector_in->link->parent;
319 if (node->type == UVMapNode::get_node_type()) {
320 UVMapNode *uvmap = (UVMapNode *)node;
321 attribute = uvmap->get_attribute();
322 }
323 else if (node->type == TextureCoordinateNode::get_node_type()) {
324 if (vector_in->link != node->output("UV")) {
325 return;
326 }
327 }
328 else {
329 return;
330 }
331 }
332
333 unordered_set<int> used_tiles;
334 /* TODO(lukas): This is quite inefficient. A fairly simple improvement would
335 * be to have a cache in each mesh that is indexed by attribute.
336 * Additionally, building a graph-to-meshes list once could help. */
337 for (Geometry *geom : scene->geometry) {
338 for (Node *node : geom->get_used_shaders()) {
339 Shader *shader = static_cast<Shader *>(node);
340 if (shader->graph.get() == graph) {
341 geom->get_uv_tiles(attribute, used_tiles);
342 }
343 }
344 }
345
346 array<int> new_tiles;
347 for (const int tile : tiles) {
348 if (used_tiles.count(tile)) {
349 new_tiles.push_back_slow(tile);
350 }
351 }
352 tiles.steal_data(new_tiles);
353}
354
356{
357#ifdef WITH_PTEX
358 /* todo: avoid loading other texture coordinates when using ptex,
359 * and hide texture coordinate socket in the UI */
360 if (shader->has_surface_link() && string_endswith(filename, ".ptx")) {
361 /* ptex */
364 }
365#endif
366
368}
369
371{
372 ShaderInput *vector_in = input("Vector");
373 ShaderOutput *color_out = output("Color");
374 ShaderOutput *alpha_out = output("Alpha");
375
376 if (handle.empty()) {
377 cull_tiles(compiler.scene, compiler.current_graph);
378 ImageManager *image_manager = compiler.scene->image_manager.get();
379 handle = image_manager->add_image(filename.string(), image_params(), tiles);
380 }
381
382 /* All tiles have the same metadata. */
383 const ImageMetaData metadata = handle.metadata();
384 const bool compress_as_srgb = metadata.compress_as_srgb;
385
386 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
387 uint flags = 0;
388
389 if (compress_as_srgb) {
391 }
392 if (!alpha_out->links.empty()) {
393 const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
394 alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
395 alpha_type == IMAGE_ALPHA_IGNORE);
396
397 if (unassociate_alpha) {
399 }
400 }
401
402 if (projection != NODE_IMAGE_PROJ_BOX) {
403 /* If there only is one image (a very common case), we encode it as a negative value. */
404 int num_nodes;
405 if (handle.num_tiles() == 0) {
406 num_nodes = -handle.svm_slot();
407 }
408 else {
409 num_nodes = divide_up(handle.num_tiles(), 2);
410 }
411
412 compiler.add_node(NODE_TEX_IMAGE,
413 num_nodes,
414 compiler.encode_uchar4(vector_offset,
415 compiler.stack_assign_if_linked(color_out),
416 compiler.stack_assign_if_linked(alpha_out),
417 flags),
418 projection);
419
420 if (num_nodes > 0) {
421 for (int i = 0; i < num_nodes; i++) {
422 int4 node;
423 node.x = tiles[2 * i];
424 node.y = handle.svm_slot(2 * i);
425 if (2 * i + 1 < tiles.size()) {
426 node.z = tiles[2 * i + 1];
427 node.w = handle.svm_slot(2 * i + 1);
428 }
429 else {
430 node.z = -1;
431 node.w = -1;
432 }
433 compiler.add_node(node.x, node.y, node.z, node.w);
434 }
435 }
436 }
437 else {
438 assert(handle.num_svm_slots() == 1);
439 compiler.add_node(NODE_TEX_IMAGE_BOX,
440 handle.svm_slot(),
441 compiler.encode_uchar4(vector_offset,
442 compiler.stack_assign_if_linked(color_out),
443 compiler.stack_assign_if_linked(alpha_out),
444 flags),
445 __float_as_int(projection_blend));
446 }
447
448 tex_mapping.compile_end(compiler, vector_in, vector_offset);
449}
450
452{
453 ShaderOutput *alpha_out = output("Alpha");
454
455 tex_mapping.compile(compiler);
456
457 if (handle.empty()) {
458 ImageManager *image_manager = compiler.scene->image_manager.get();
459 handle = image_manager->add_image(filename.string(), image_params());
460 }
461
462 const ImageMetaData metadata = handle.metadata();
463 const bool is_float = metadata.is_float();
464 const bool compress_as_srgb = metadata.compress_as_srgb;
465 const ustring known_colorspace = metadata.colorspace;
466
467 if (handle.svm_slot() == -1) {
468 compiler.parameter_texture(
469 "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace);
470 }
471 else {
472 compiler.parameter_texture("filename", handle);
473 }
474
475 const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
476 alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
477 alpha_type == IMAGE_ALPHA_IGNORE);
478 const bool is_tiled = (filename.find("<UDIM>") != string::npos ||
479 filename.find("<UVTILE>") != string::npos) ||
480 handle.num_tiles() > 0;
481
482 compiler.parameter(this, "projection");
483 compiler.parameter(this, "projection_blend");
484 compiler.parameter("compress_as_srgb", compress_as_srgb);
485 compiler.parameter("ignore_alpha", alpha_type == IMAGE_ALPHA_IGNORE);
486 compiler.parameter("unassociate_alpha", !alpha_out->links.empty() && unassociate_alpha);
487 compiler.parameter("is_float", is_float);
488 compiler.parameter("is_tiled", is_tiled);
489 compiler.parameter(this, "interpolation");
490 compiler.parameter(this, "extension");
491
492 compiler.add(this, "node_image_texture");
493}
494
495/* Environment Texture */
496
498{
499 NodeType *type = NodeType::add("environment_texture", create, NodeType::SHADER);
500
502
503 SOCKET_STRING(filename, "Filename", ustring());
504 SOCKET_STRING(colorspace, "Colorspace", u_colorspace_auto);
505
506 static NodeEnum alpha_type_enum;
507 alpha_type_enum.insert("auto", IMAGE_ALPHA_AUTO);
508 alpha_type_enum.insert("unassociated", IMAGE_ALPHA_UNASSOCIATED);
509 alpha_type_enum.insert("associated", IMAGE_ALPHA_ASSOCIATED);
510 alpha_type_enum.insert("channel_packed", IMAGE_ALPHA_CHANNEL_PACKED);
511 alpha_type_enum.insert("ignore", IMAGE_ALPHA_IGNORE);
512 SOCKET_ENUM(alpha_type, "Alpha Type", alpha_type_enum, IMAGE_ALPHA_AUTO);
513
514 static NodeEnum interpolation_enum;
515 interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
516 interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
517 interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
518 interpolation_enum.insert("smart", INTERPOLATION_SMART);
519 SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
520
521 static NodeEnum projection_enum;
522 projection_enum.insert("equirectangular", NODE_ENVIRONMENT_EQUIRECTANGULAR);
523 projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL);
524 SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR);
525
526 SOCKET_BOOLEAN(animated, "Animated", false);
527
529
530 SOCKET_OUT_COLOR(color, "Color");
531 SOCKET_OUT_FLOAT(alpha, "Alpha");
532
533 return type;
534}
535
536EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(get_node_type())
537{
538 colorspace = u_colorspace_raw;
539 animated = false;
540}
541
543{
545 node->handle = handle;
546 return node;
547}
548
550{
552 params.animated = animated;
553 params.interpolation = interpolation;
554 params.extension = EXTENSION_REPEAT;
555 params.alpha_type = alpha_type;
556 params.colorspace = colorspace;
557 return params;
558}
559
561{
562#ifdef WITH_PTEX
563 if (shader->has_surface_link() && string_endswith(filename, ".ptx")) {
564 /* ptex */
567 }
568#endif
569
571}
572
574{
575 ShaderInput *vector_in = input("Vector");
576 ShaderOutput *color_out = output("Color");
577 ShaderOutput *alpha_out = output("Alpha");
578
579 if (handle.empty()) {
580 ImageManager *image_manager = compiler.scene->image_manager.get();
581 handle = image_manager->add_image(filename.string(), image_params());
582 }
583
584 const ImageMetaData metadata = handle.metadata();
585 const bool compress_as_srgb = metadata.compress_as_srgb;
586
587 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
588 uint flags = 0;
589
590 if (compress_as_srgb) {
592 }
593
594 compiler.add_node(NODE_TEX_ENVIRONMENT,
595 handle.svm_slot(),
596 compiler.encode_uchar4(vector_offset,
597 compiler.stack_assign_if_linked(color_out),
598 compiler.stack_assign_if_linked(alpha_out),
599 flags),
600 projection);
601
602 tex_mapping.compile_end(compiler, vector_in, vector_offset);
603}
604
606{
607 if (handle.empty()) {
608 ImageManager *image_manager = compiler.scene->image_manager.get();
609 handle = image_manager->add_image(filename.string(), image_params());
610 }
611
612 tex_mapping.compile(compiler);
613
614 const ImageMetaData metadata = handle.metadata();
615 const bool is_float = metadata.is_float();
616 const bool compress_as_srgb = metadata.compress_as_srgb;
617 const ustring known_colorspace = metadata.colorspace;
618
619 if (handle.svm_slot() == -1) {
620 compiler.parameter_texture(
621 "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace);
622 }
623 else {
624 compiler.parameter_texture("filename", handle);
625 }
626
627 compiler.parameter(this, "projection");
628 compiler.parameter(this, "interpolation");
629 compiler.parameter("compress_as_srgb", compress_as_srgb);
630 compiler.parameter("ignore_alpha", alpha_type == IMAGE_ALPHA_IGNORE);
631 compiler.parameter("is_float", is_float);
632 compiler.add(this, "node_environment_texture");
633}
634
635/* Sky Texture */
636
638{
639 return make_float2(acosf(dir.z), atan2f(dir.x, dir.y));
640}
641
642struct SunSky {
643 /* sun direction in spherical and cartesian */
644 float theta, phi;
645
646 /* Parameter */
648 float config_x[9], config_y[9], config_z[9], nishita_data[11];
649};
650
651/* Preetham model */
652static float sky_perez_function(const float lam[6], float theta, const float gamma)
653{
654 return (1.0f + lam[0] * expf(lam[1] / cosf(theta))) *
655 (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cosf(gamma) * cosf(gamma));
656}
657
659 const float3 dir,
660 const float turbidity)
661{
662 /*
663 * We re-use the SunSky struct of the new model, to avoid extra variables
664 * zenith_Y/x/y is now radiance_x/y/z
665 * perez_Y/x/y is now config_x/y/z
666 */
667
668 const float2 spherical = sky_spherical_coordinates(dir);
669 const float theta = spherical.x;
670 const float phi = spherical.y;
671
672 sunsky->theta = theta;
673 sunsky->phi = phi;
674
675 const float theta2 = theta * theta;
676 const float theta3 = theta2 * theta;
677 const float T = turbidity;
678 const float T2 = T * T;
679
680 const float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta);
681 sunsky->radiance_x = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
682 sunsky->radiance_x *= 0.06f;
683
684 sunsky->radiance_y = (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 +
685 (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) * T +
686 (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f);
687
688 sunsky->radiance_z = (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 +
689 (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) * T +
690 (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f);
691
692 sunsky->config_x[0] = (0.1787f * T - 1.4630f);
693 sunsky->config_x[1] = (-0.3554f * T + 0.4275f);
694 sunsky->config_x[2] = (-0.0227f * T + 5.3251f);
695 sunsky->config_x[3] = (0.1206f * T - 2.5771f);
696 sunsky->config_x[4] = (-0.0670f * T + 0.3703f);
697
698 sunsky->config_y[0] = (-0.0193f * T - 0.2592f);
699 sunsky->config_y[1] = (-0.0665f * T + 0.0008f);
700 sunsky->config_y[2] = (-0.0004f * T + 0.2125f);
701 sunsky->config_y[3] = (-0.0641f * T - 0.8989f);
702 sunsky->config_y[4] = (-0.0033f * T + 0.0452f);
703
704 sunsky->config_z[0] = (-0.0167f * T - 0.2608f);
705 sunsky->config_z[1] = (-0.0950f * T + 0.0092f);
706 sunsky->config_z[2] = (-0.0079f * T + 0.2102f);
707 sunsky->config_z[3] = (-0.0441f * T - 1.6537f);
708 sunsky->config_z[4] = (-0.0109f * T + 0.0529f);
709
710 /* unused for old sky model */
711 for (int i = 5; i < 9; i++) {
712 sunsky->config_x[i] = 0.0f;
713 sunsky->config_y[i] = 0.0f;
714 sunsky->config_z[i] = 0.0f;
715 }
716
717 sunsky->radiance_x /= sky_perez_function(sunsky->config_x, 0, theta);
718 sunsky->radiance_y /= sky_perez_function(sunsky->config_y, 0, theta);
719 sunsky->radiance_z /= sky_perez_function(sunsky->config_z, 0, theta);
720}
721
722/* Hosek / Wilkie */
724 const float3 dir,
725 float turbidity,
726 const float ground_albedo)
727{
728 /* Calculate Sun Direction and save coordinates */
729 const float2 spherical = sky_spherical_coordinates(dir);
730 float theta = spherical.x;
731 const float phi = spherical.y;
732
733 /* Clamp Turbidity */
734 turbidity = clamp(turbidity, 0.0f, 10.0f);
735
736 /* Clamp to Horizon */
737 theta = clamp(theta, 0.0f, M_PI_2_F);
738
739 sunsky->theta = theta;
740 sunsky->phi = phi;
741
742 const float solarElevation = M_PI_2_F - theta;
743
744 /* Initialize Sky Model */
745 SKY_ArHosekSkyModelState *sky_state;
747 (double)turbidity, (double)ground_albedo, (double)solarElevation);
748
749 /* Copy values from sky_state to SunSky */
750 for (int i = 0; i < 9; ++i) {
751 sunsky->config_x[i] = (float)sky_state->configs[0][i];
752 sunsky->config_y[i] = (float)sky_state->configs[1][i];
753 sunsky->config_z[i] = (float)sky_state->configs[2][i];
754 }
755 sunsky->radiance_x = (float)sky_state->radiances[0];
756 sunsky->radiance_y = (float)sky_state->radiances[1];
757 sunsky->radiance_z = (float)sky_state->radiances[2];
758
759 /* Free sky_state */
761}
762
763/* Nishita improved */
765 bool multiple_scattering,
766 bool sun_disc,
767 const float sun_size,
768 const float sun_intensity,
769 const float sun_elevation,
770 const float sun_rotation,
771 const float altitude,
772 const float air_density,
773 const float aerosol_density,
774 const float ozone_density)
775{
776 /* Sample 2 Sun pixels */
777 float pixel_bottom[3];
778 float pixel_top[3];
779
780 if (multiple_scattering) {
782 sun_size,
783 altitude,
784 air_density,
785 aerosol_density,
786 ozone_density,
787 pixel_bottom,
788 pixel_top);
789 }
790 else {
792 sun_elevation, sun_size, altitude, air_density, aerosol_density, pixel_bottom, pixel_top);
793 }
794
795 float earth_intersection_angle = SKY_earth_intersection_angle(altitude);
796
797 /* Send data to sky.h */
798 sunsky->nishita_data[0] = pixel_bottom[0];
799 sunsky->nishita_data[1] = pixel_bottom[1];
800 sunsky->nishita_data[2] = pixel_bottom[2];
801 sunsky->nishita_data[3] = pixel_top[0];
802 sunsky->nishita_data[4] = pixel_top[1];
803 sunsky->nishita_data[5] = pixel_top[2];
804 sunsky->nishita_data[6] = sun_elevation;
805 sunsky->nishita_data[7] = sun_rotation;
806 sunsky->nishita_data[8] = sun_disc ? sun_size : -1.0f;
807 sunsky->nishita_data[9] = sun_intensity;
808 sunsky->nishita_data[10] = -earth_intersection_angle;
809}
810
812{
813 const float angular_diameter = get_sun_size();
814 float pix_bottom[3];
815 float pix_top[3];
816
817 if (sky_type == NODE_SKY_SINGLE_SCATTERING) {
819 angular_diameter,
820 altitude,
821 air_density,
822 aerosol_density,
823 pix_bottom,
824 pix_top);
825 }
826 else {
828 angular_diameter,
829 altitude,
830 air_density,
831 aerosol_density,
832 ozone_density,
833 pix_bottom,
834 pix_top);
835 }
836
837 /* Sample center of Sun. */
838 const float3 pixel_bottom = make_float3(pix_bottom[0], pix_bottom[1], pix_bottom[2]);
839 const float3 pixel_top = make_float3(pix_top[0], pix_top[1], pix_top[2]);
840 float3 xyz = interp(pixel_bottom, pixel_top, 0.5f) * sun_intensity;
841
842 /* We first approximate the Sun's contribution by
843 * multiplying the evaluated point by the square of the angular diameter.
844 * Then we scale the approximation using a piecewise function (determined empirically). */
845 float sun_contribution = average(xyz) * sqr(angular_diameter);
846
847 const float first_point = 0.8f / 180.0f * M_PI_F;
848 const float second_point = 1.0f / 180.0f * M_PI_F;
849 const float third_point = M_PI_2_F;
850 if (angular_diameter < first_point) {
851 sun_contribution *= 1.0f;
852 }
853 else if (angular_diameter < second_point) {
854 const float diff = angular_diameter - first_point;
855 const float slope = (0.8f - 1.0f) / (second_point - first_point);
856 sun_contribution *= 1.0f + slope * diff;
857 }
858 else {
859 const float diff = angular_diameter - 1.0f / 180.0f * M_PI_F;
860 const float slope = (0.45f - 0.8f) / (third_point - second_point);
861 sun_contribution *= 0.8f + slope * diff;
862 }
863
864 return sun_contribution;
865}
866
868{
869 NodeType *type = NodeType::add("sky_texture", create, NodeType::SHADER);
871 static NodeEnum type_enum;
872 type_enum.insert("preetham", NODE_SKY_PREETHAM);
873 type_enum.insert("hosek_wilkie", NODE_SKY_HOSEK);
874 type_enum.insert("single_scattering", NODE_SKY_SINGLE_SCATTERING);
875 type_enum.insert("multiple_scattering", NODE_SKY_MULTIPLE_SCATTERING);
876 SOCKET_ENUM(sky_type, "Type", type_enum, NODE_SKY_MULTIPLE_SCATTERING);
877
878 /* Nishita parameters. */
879 SOCKET_BOOLEAN(sun_disc, "Sun Disc", true);
880 SOCKET_FLOAT(sun_size, "Sun Size", 0.009512f);
881 SOCKET_FLOAT(sun_intensity, "Sun Intensity", 1.0f);
882 SOCKET_FLOAT(sun_elevation, "Sun Elevation", 15.0f * M_PI_F / 180.0f);
883 SOCKET_FLOAT(sun_rotation, "Sun Rotation", 0.0f);
884 SOCKET_FLOAT(altitude, "Altitude", 100.0f);
885 SOCKET_FLOAT(air_density, "Air", 1.0f);
886 SOCKET_FLOAT(aerosol_density, "Aerosol", 1.0f);
887 SOCKET_FLOAT(ozone_density, "Ozone", 1.0f);
889 SOCKET_OUT_COLOR(color, "Color");
890
891 /* Legacy parameters. */
892 SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f));
893 SOCKET_FLOAT(turbidity, "Turbidity", 2.2f);
894 SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f);
895
896 return type;
897}
898
899SkyTextureNode::SkyTextureNode() : TextureNode(get_node_type()) {}
900
902{
903 /* Patch Sun position so users are able to animate the daylight cycle while keeping the shading
904 * code simple. */
905 float new_sun_elevation = sun_elevation;
906 float new_sun_rotation = sun_rotation;
907
908 /* Wrap `new_sun_elevation` into [-2PI..2PI] range. */
909 new_sun_elevation = fmodf(new_sun_elevation, M_2PI_F);
910 /* Wrap `new_sun_elevation` into [-PI..PI] range. */
911 if (fabsf(new_sun_elevation) >= M_PI_F) {
912 new_sun_elevation -= copysignf(2.0f, new_sun_elevation) * M_PI_F;
913 }
914 /* Wrap `new_sun_elevation` into [-PI/2..PI/2] range while keeping the same absolute position. */
915 if (new_sun_elevation >= M_PI_2_F || new_sun_elevation <= -M_PI_2_F) {
916 new_sun_elevation = copysignf(M_PI_F, new_sun_elevation) - new_sun_elevation;
917 new_sun_rotation += M_PI_F;
918 }
919
920 /* Wrap `new_sun_rotation` into [-2PI..2PI] range. */
921 new_sun_rotation = fmodf(new_sun_rotation, M_2PI_F);
922 /* Wrap `new_sun_rotation` into [0..2PI] range. */
923 if (new_sun_rotation < 0.0f) {
924 new_sun_rotation += M_2PI_F;
925 }
926 new_sun_rotation = M_2PI_F - new_sun_rotation;
927
928 sun_elevation = new_sun_elevation;
929 sun_rotation = new_sun_rotation;
930}
931
933{
934 ShaderInput *vector_in = input("Vector");
935 ShaderOutput *color_out = output("Color");
936 SunSky sunsky = {};
937
938 if (sky_type == NODE_SKY_PREETHAM) {
940 }
941 else if (sky_type == NODE_SKY_HOSEK) {
942 sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
943 }
944 else {
947 sun_disc,
948 get_sun_size(),
949 sun_intensity,
950 sun_elevation,
951 sun_rotation,
952 altitude,
953 air_density,
954 aerosol_density,
955 ozone_density);
956 /* Sky texture image parameters */
957 ImageManager *image_manager = compiler.scene->image_manager.get();
958 ImageParams impar;
961
962 /* Precompute sky texture */
963 if (handle.empty()) {
964 unique_ptr<SkyLoader> loader = make_unique<SkyLoader>(sky_type ==
966 sun_elevation,
967 altitude,
968 air_density,
969 aerosol_density,
970 ozone_density);
971 handle = image_manager->add_image(std::move(loader), impar);
972 }
973 }
974
975 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
976
977 compiler.stack_assign(color_out);
978 compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), sky_type);
979 if (sky_type == NODE_SKY_PREETHAM || sky_type == NODE_SKY_HOSEK) {
980 compiler.add_node(__float_as_uint(sunsky.phi),
981 __float_as_uint(sunsky.theta),
984 compiler.add_node(__float_as_uint(sunsky.radiance_z),
985 __float_as_uint(sunsky.config_x[0]),
986 __float_as_uint(sunsky.config_x[1]),
987 __float_as_uint(sunsky.config_x[2]));
988 compiler.add_node(__float_as_uint(sunsky.config_x[3]),
989 __float_as_uint(sunsky.config_x[4]),
990 __float_as_uint(sunsky.config_x[5]),
991 __float_as_uint(sunsky.config_x[6]));
992 compiler.add_node(__float_as_uint(sunsky.config_x[7]),
993 __float_as_uint(sunsky.config_x[8]),
994 __float_as_uint(sunsky.config_y[0]),
995 __float_as_uint(sunsky.config_y[1]));
996 compiler.add_node(__float_as_uint(sunsky.config_y[2]),
997 __float_as_uint(sunsky.config_y[3]),
998 __float_as_uint(sunsky.config_y[4]),
999 __float_as_uint(sunsky.config_y[5]));
1000 compiler.add_node(__float_as_uint(sunsky.config_y[6]),
1001 __float_as_uint(sunsky.config_y[7]),
1002 __float_as_uint(sunsky.config_y[8]),
1003 __float_as_uint(sunsky.config_z[0]));
1004 compiler.add_node(__float_as_uint(sunsky.config_z[1]),
1005 __float_as_uint(sunsky.config_z[2]),
1006 __float_as_uint(sunsky.config_z[3]),
1007 __float_as_uint(sunsky.config_z[4]));
1008 compiler.add_node(__float_as_uint(sunsky.config_z[5]),
1009 __float_as_uint(sunsky.config_z[6]),
1010 __float_as_uint(sunsky.config_z[7]),
1011 __float_as_uint(sunsky.config_z[8]));
1012 }
1013 else {
1014 compiler.add_node(__float_as_uint(sunsky.nishita_data[0]),
1015 __float_as_uint(sunsky.nishita_data[1]),
1016 __float_as_uint(sunsky.nishita_data[2]),
1017 __float_as_uint(sunsky.nishita_data[3]));
1018 compiler.add_node(__float_as_uint(sunsky.nishita_data[4]),
1019 __float_as_uint(sunsky.nishita_data[5]),
1020 __float_as_uint(sunsky.nishita_data[6]),
1021 __float_as_uint(sunsky.nishita_data[7]));
1022 compiler.add_node(__float_as_uint(sunsky.nishita_data[8]),
1023 __float_as_uint(sunsky.nishita_data[9]),
1024 __float_as_uint(sunsky.nishita_data[10]),
1025 handle.svm_slot());
1026 }
1027
1028 tex_mapping.compile_end(compiler, vector_in, vector_offset);
1029}
1030
1032{
1033 tex_mapping.compile(compiler);
1034 SunSky sunsky = {};
1035
1036 if (sky_type == NODE_SKY_PREETHAM) {
1038 }
1039 else if (sky_type == NODE_SKY_HOSEK) {
1040 sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
1041 }
1042 else {
1044 sky_type == NODE_SKY_MULTIPLE_SCATTERING,
1045 sun_disc,
1046 get_sun_size(),
1047 sun_intensity,
1048 sun_elevation,
1049 sun_rotation,
1050 altitude,
1051 air_density,
1052 aerosol_density,
1053 ozone_density);
1054 /* Sky texture image parameters */
1055 ImageManager *image_manager = compiler.scene->image_manager.get();
1056 ImageParams impar;
1059
1060 /* Precompute sky texture */
1061 {
1062 unique_ptr<SkyLoader> loader = make_unique<SkyLoader>(sky_type ==
1064 sun_elevation,
1065 altitude,
1066 air_density,
1067 aerosol_density,
1068 ozone_density);
1069 handle = image_manager->add_image(std::move(loader), impar);
1070 }
1071
1072 compiler.parameter_texture("filename", handle);
1073 }
1074
1075 compiler.parameter(this, "sky_type");
1076 compiler.parameter("theta", sunsky.theta);
1077 compiler.parameter("phi", sunsky.phi);
1078 compiler.parameter_color("radiance",
1079 make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z));
1080 compiler.parameter_array("config_x", sunsky.config_x, 9);
1081 compiler.parameter_array("config_y", sunsky.config_y, 9);
1082 compiler.parameter_array("config_z", sunsky.config_z, 9);
1083 compiler.parameter_array("nishita_data", sunsky.nishita_data, 11);
1084 compiler.add(this, "node_sky_texture");
1085}
1086
1087/* Gradient Texture */
1088
1090{
1091 NodeType *type = NodeType::add("gradient_texture", create, NodeType::SHADER);
1092
1094
1095 static NodeEnum type_enum;
1096 type_enum.insert("linear", NODE_BLEND_LINEAR);
1097 type_enum.insert("quadratic", NODE_BLEND_QUADRATIC);
1098 type_enum.insert("easing", NODE_BLEND_EASING);
1099 type_enum.insert("diagonal", NODE_BLEND_DIAGONAL);
1100 type_enum.insert("radial", NODE_BLEND_RADIAL);
1101 type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE);
1102 type_enum.insert("spherical", NODE_BLEND_SPHERICAL);
1103 SOCKET_ENUM(gradient_type, "Type", type_enum, NODE_BLEND_LINEAR);
1104
1106
1107 SOCKET_OUT_COLOR(color, "Color");
1108 SOCKET_OUT_FLOAT(fac, "Fac");
1109
1110 return type;
1111}
1112
1113GradientTextureNode::GradientTextureNode() : TextureNode(get_node_type()) {}
1114
1116{
1117 ShaderInput *vector_in = input("Vector");
1118 ShaderOutput *color_out = output("Color");
1119 ShaderOutput *fac_out = output("Fac");
1120
1121 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1122
1123 compiler.add_node(NODE_TEX_GRADIENT,
1124 compiler.encode_uchar4(gradient_type,
1125 vector_offset,
1126 compiler.stack_assign_if_linked(fac_out),
1127 compiler.stack_assign_if_linked(color_out)));
1128
1129 tex_mapping.compile_end(compiler, vector_in, vector_offset);
1130}
1131
1133{
1134 tex_mapping.compile(compiler);
1135
1136 compiler.parameter(this, "gradient_type");
1137 compiler.add(this, "node_gradient_texture");
1138}
1139
1140/* Noise Texture */
1141
1143{
1144 NodeType *type = NodeType::add("noise_texture", create, NodeType::SHADER);
1145
1147
1148 static NodeEnum dimensions_enum;
1149 dimensions_enum.insert("1D", 1);
1150 dimensions_enum.insert("2D", 2);
1151 dimensions_enum.insert("3D", 3);
1152 dimensions_enum.insert("4D", 4);
1153 SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
1154
1155 static NodeEnum type_enum;
1156 type_enum.insert("multifractal", NODE_NOISE_MULTIFRACTAL);
1157 type_enum.insert("fBM", NODE_NOISE_FBM);
1158 type_enum.insert("hybrid_multifractal", NODE_NOISE_HYBRID_MULTIFRACTAL);
1159 type_enum.insert("ridged_multifractal", NODE_NOISE_RIDGED_MULTIFRACTAL);
1160 type_enum.insert("hetero_terrain", NODE_NOISE_HETERO_TERRAIN);
1161 SOCKET_ENUM(type, "Type", type_enum, NODE_NOISE_FBM);
1162
1163 SOCKET_BOOLEAN(use_normalize, "Normalize", true);
1164
1166 SOCKET_IN_FLOAT(w, "W", 0.0f);
1167 SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
1168 SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
1169 SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
1170 SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f);
1171 SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
1172 SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
1173 SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
1174
1175 SOCKET_OUT_FLOAT(fac, "Fac");
1176 SOCKET_OUT_COLOR(color, "Color");
1177
1178 return type;
1179}
1180
1181NoiseTextureNode::NoiseTextureNode() : TextureNode(get_node_type()) {}
1182
1184{
1185 ShaderInput *vector_in = input("Vector");
1186 ShaderInput *w_in = input("W");
1187 ShaderInput *scale_in = input("Scale");
1188 ShaderInput *detail_in = input("Detail");
1189 ShaderInput *roughness_in = input("Roughness");
1190 ShaderInput *lacunarity_in = input("Lacunarity");
1191 ShaderInput *offset_in = input("Offset");
1192 ShaderInput *gain_in = input("Gain");
1193 ShaderInput *distortion_in = input("Distortion");
1194 ShaderOutput *fac_out = output("Fac");
1195 ShaderOutput *color_out = output("Color");
1196
1197 const int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
1198 const int w_stack_offset = compiler.stack_assign_if_linked(w_in);
1199 const int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
1200 const int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
1201 const int roughness_stack_offset = compiler.stack_assign_if_linked(roughness_in);
1202 const int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
1203 const int offset_stack_offset = compiler.stack_assign_if_linked(offset_in);
1204 const int gain_stack_offset = compiler.stack_assign_if_linked(gain_in);
1205 const int distortion_stack_offset = compiler.stack_assign_if_linked(distortion_in);
1206 const int fac_stack_offset = compiler.stack_assign_if_linked(fac_out);
1207 const int color_stack_offset = compiler.stack_assign_if_linked(color_out);
1208
1209 compiler.add_node(
1210 NODE_TEX_NOISE,
1211 compiler.encode_uchar4(
1212 vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset),
1213 compiler.encode_uchar4(
1214 roughness_stack_offset, lacunarity_stack_offset, offset_stack_offset, gain_stack_offset),
1215 compiler.encode_uchar4(distortion_stack_offset, fac_stack_offset, color_stack_offset));
1216
1217 compiler.add_node(
1218 __float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(roughness));
1219
1220 compiler.add_node(__float_as_int(lacunarity),
1221 __float_as_int(offset),
1222 __float_as_int(gain),
1223 __float_as_int(distortion));
1224 compiler.add_node(dimensions, type, use_normalize, SVM_STACK_INVALID);
1225
1226 tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
1227}
1228
1230{
1231 tex_mapping.compile(compiler);
1232 compiler.parameter(this, "dimensions");
1233 compiler.parameter(this, "type");
1234 compiler.parameter(this, "use_normalize");
1235 compiler.add(this, "node_noise_texture");
1236}
1237
1238/* Gabor Texture */
1239
1241{
1242 NodeType *type = NodeType::add("gabor_texture", create, NodeType::SHADER);
1243
1245
1246 static NodeEnum type_enum;
1247 type_enum.insert("2D", NODE_GABOR_TYPE_2D);
1248 type_enum.insert("3D", NODE_GABOR_TYPE_3D);
1249 SOCKET_ENUM(type, "Type", type_enum, NODE_GABOR_TYPE_2D);
1250
1252 SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
1253 SOCKET_IN_FLOAT(frequency, "Frequency", 2.0f);
1254 SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 1.0f);
1255 SOCKET_IN_FLOAT(orientation_2d, "Orientation 2D", M_PI_F / 4.0f);
1256 SOCKET_IN_VECTOR(orientation_3d, "Orientation 3D", make_float3(M_SQRT2_F, M_SQRT2_F, 0.0f));
1257
1258 SOCKET_OUT_FLOAT(value, "Value");
1259 SOCKET_OUT_FLOAT(phase, "Phase");
1260 SOCKET_OUT_FLOAT(intensity, "Intensity");
1261
1262 return type;
1263}
1264
1265GaborTextureNode::GaborTextureNode() : TextureNode(get_node_type()) {}
1266
1268{
1269 ShaderInput *vector_in = input("Vector");
1270 ShaderInput *scale_in = input("Scale");
1271 ShaderInput *frequency_in = input("Frequency");
1272 ShaderInput *anisotropy_in = input("Anisotropy");
1273 ShaderInput *orientation_2d_in = input("Orientation 2D");
1274 ShaderInput *orientation_3d_in = input("Orientation 3D");
1275
1276 ShaderOutput *value_out = output("Value");
1277 ShaderOutput *phase_out = output("Phase");
1278 ShaderOutput *intensity_out = output("Intensity");
1279
1280 const int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
1281 const int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
1282 const int frequency_stack_offset = compiler.stack_assign_if_linked(frequency_in);
1283 const int anisotropy_stack_offset = compiler.stack_assign_if_linked(anisotropy_in);
1284 const int orientation_2d_stack_offset = compiler.stack_assign_if_linked(orientation_2d_in);
1285 const int orientation_3d_stack_offset = compiler.stack_assign(orientation_3d_in);
1286
1287 const int value_stack_offset = compiler.stack_assign_if_linked(value_out);
1288 const int phase_stack_offset = compiler.stack_assign_if_linked(phase_out);
1289 const int intensity_stack_offset = compiler.stack_assign_if_linked(intensity_out);
1290
1291 compiler.add_node(
1292 NODE_TEX_GABOR,
1293 type,
1294 compiler.encode_uchar4(vector_stack_offset,
1295 scale_stack_offset,
1296 frequency_stack_offset,
1297 anisotropy_stack_offset),
1298 compiler.encode_uchar4(orientation_2d_stack_offset, orientation_3d_stack_offset));
1299
1300 compiler.add_node(
1301 compiler.encode_uchar4(value_stack_offset, phase_stack_offset, intensity_stack_offset),
1302 __float_as_int(scale),
1303 __float_as_int(frequency),
1304 __float_as_int(anisotropy));
1305 compiler.add_node(__float_as_int(orientation_2d));
1306
1307 tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
1308}
1309
1311{
1312 tex_mapping.compile(compiler);
1313 compiler.parameter(this, "type");
1314 compiler.add(this, "node_gabor_texture");
1315}
1316
1317/* Voronoi Texture */
1318
1320{
1321 NodeType *type = NodeType::add("voronoi_texture", create, NodeType::SHADER);
1322
1324
1325 static NodeEnum dimensions_enum;
1326 dimensions_enum.insert("1D", 1);
1327 dimensions_enum.insert("2D", 2);
1328 dimensions_enum.insert("3D", 3);
1329 dimensions_enum.insert("4D", 4);
1330 SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
1331
1332 static NodeEnum metric_enum;
1333 metric_enum.insert("euclidean", NODE_VORONOI_EUCLIDEAN);
1334 metric_enum.insert("manhattan", NODE_VORONOI_MANHATTAN);
1335 metric_enum.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
1336 metric_enum.insert("minkowski", NODE_VORONOI_MINKOWSKI);
1337 SOCKET_ENUM(metric, "Distance Metric", metric_enum, NODE_VORONOI_EUCLIDEAN);
1338
1339 static NodeEnum feature_enum;
1340 feature_enum.insert("f1", NODE_VORONOI_F1);
1341 feature_enum.insert("f2", NODE_VORONOI_F2);
1342 feature_enum.insert("smooth_f1", NODE_VORONOI_SMOOTH_F1);
1343 feature_enum.insert("distance_to_edge", NODE_VORONOI_DISTANCE_TO_EDGE);
1344 feature_enum.insert("n_sphere_radius", NODE_VORONOI_N_SPHERE_RADIUS);
1345 SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_F1);
1346
1347 SOCKET_BOOLEAN(use_normalize, "Normalize", false);
1348
1350 SOCKET_IN_FLOAT(w, "W", 0.0f);
1351 SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
1352 SOCKET_IN_FLOAT(detail, "Detail", 0.0f);
1353 SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
1354 SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f);
1355 SOCKET_IN_FLOAT(smoothness, "Smoothness", 5.0f);
1356 SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
1357 SOCKET_IN_FLOAT(randomness, "Randomness", 1.0f);
1358
1359 SOCKET_OUT_FLOAT(distance, "Distance");
1360 SOCKET_OUT_COLOR(color, "Color");
1361 SOCKET_OUT_POINT(position, "Position");
1362 SOCKET_OUT_FLOAT(w, "W");
1363 SOCKET_OUT_FLOAT(radius, "Radius");
1364
1365 return type;
1366}
1367
1368VoronoiTextureNode::VoronoiTextureNode() : TextureNode(get_node_type()) {}
1369
1371{
1372 ShaderInput *vector_in = input("Vector");
1373 ShaderInput *w_in = input("W");
1374 ShaderInput *scale_in = input("Scale");
1375 ShaderInput *detail_in = input("Detail");
1376 ShaderInput *roughness_in = input("Roughness");
1377 ShaderInput *lacunarity_in = input("Lacunarity");
1378 ShaderInput *smoothness_in = input("Smoothness");
1379 ShaderInput *exponent_in = input("Exponent");
1380 ShaderInput *randomness_in = input("Randomness");
1381
1382 ShaderOutput *distance_out = output("Distance");
1383 ShaderOutput *color_out = output("Color");
1384 ShaderOutput *position_out = output("Position");
1385 ShaderOutput *w_out = output("W");
1386 ShaderOutput *radius_out = output("Radius");
1387
1388 const int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
1389 const int w_in_stack_offset = compiler.stack_assign_if_linked(w_in);
1390 const int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
1391 const int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
1392 const int roughness_stack_offset = compiler.stack_assign_if_linked(roughness_in);
1393 const int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
1394 const int smoothness_stack_offset = compiler.stack_assign_if_linked(smoothness_in);
1395 const int exponent_stack_offset = compiler.stack_assign_if_linked(exponent_in);
1396 const int randomness_stack_offset = compiler.stack_assign_if_linked(randomness_in);
1397 const int distance_stack_offset = compiler.stack_assign_if_linked(distance_out);
1398 const int color_stack_offset = compiler.stack_assign_if_linked(color_out);
1399 const int position_stack_offset = compiler.stack_assign_if_linked(position_out);
1400 const int w_out_stack_offset = compiler.stack_assign_if_linked(w_out);
1401 const int radius_stack_offset = compiler.stack_assign_if_linked(radius_out);
1402
1403 compiler.add_node(NODE_TEX_VORONOI, dimensions, feature, metric);
1404 compiler.add_node(
1405 compiler.encode_uchar4(
1406 vector_stack_offset, w_in_stack_offset, scale_stack_offset, detail_stack_offset),
1407 compiler.encode_uchar4(roughness_stack_offset,
1408 lacunarity_stack_offset,
1409 smoothness_stack_offset,
1410 exponent_stack_offset),
1411 compiler.encode_uchar4(
1412 randomness_stack_offset, use_normalize, distance_stack_offset, color_stack_offset),
1413 compiler.encode_uchar4(position_stack_offset, w_out_stack_offset, radius_stack_offset));
1414
1415 compiler.add_node(
1416 __float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(roughness));
1417 compiler.add_node(__float_as_int(lacunarity),
1418 __float_as_int(smoothness),
1419 __float_as_int(exponent),
1420 __float_as_int(randomness));
1421 tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
1422}
1423
1425{
1426 tex_mapping.compile(compiler);
1427
1428 compiler.parameter(this, "dimensions");
1429 compiler.parameter(this, "feature");
1430 compiler.parameter(this, "metric");
1431 compiler.parameter(this, "use_normalize");
1432 compiler.add(this, "node_voronoi_texture");
1433}
1434
1435/* IES Light */
1436
1438{
1439 NodeType *type = NodeType::add("ies_light", create, NodeType::SHADER);
1440
1442
1443 SOCKET_STRING(ies, "IES", ustring());
1444 SOCKET_STRING(filename, "File Name", ustring());
1445
1446 SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
1448
1449 SOCKET_OUT_FLOAT(fac, "Fac");
1450
1451 return type;
1452}
1453
1454IESLightNode::IESLightNode() : TextureNode(get_node_type())
1455{
1456 light_manager = nullptr;
1457 slot = -1;
1458}
1459
1461{
1462 IESLightNode *node = graph->create_node<IESLightNode>(*this);
1463
1464 node->light_manager = nullptr;
1465 node->slot = -1;
1466
1467 return node;
1468}
1469
1471{
1472 if (light_manager) {
1473 light_manager->remove_ies(slot);
1474 }
1475}
1476
1477void IESLightNode::get_slot()
1478{
1479 assert(light_manager);
1480
1481 if (slot == -1) {
1482 if (ies.empty()) {
1483 slot = light_manager->add_ies_from_file(filename.string());
1484 }
1485 else {
1486 slot = light_manager->add_ies(ies.string());
1487 }
1488 }
1489}
1490
1491void IESLightNode::compile(SVMCompiler &compiler)
1492{
1493 light_manager = compiler.scene->light_manager.get();
1494 get_slot();
1495
1496 ShaderInput *strength_in = input("Strength");
1497 ShaderInput *vector_in = input("Vector");
1498 ShaderOutput *fac_out = output("Fac");
1499
1500 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1501
1502 compiler.add_node(NODE_IES,
1503 compiler.encode_uchar4(compiler.stack_assign_if_linked(strength_in),
1504 vector_offset,
1505 compiler.stack_assign(fac_out),
1506 0),
1507 slot,
1508 __float_as_int(strength));
1509
1510 tex_mapping.compile_end(compiler, vector_in, vector_offset);
1511}
1512
1513void IESLightNode::compile(OSLCompiler &compiler)
1514{
1515 light_manager = compiler.scene->light_manager.get();
1516 get_slot();
1517
1518 tex_mapping.compile(compiler);
1519
1520 compiler.parameter_texture_ies("filename", slot);
1521 compiler.add(this, "node_ies_light");
1522}
1523
1524/* White Noise Texture */
1525
1527{
1528 NodeType *type = NodeType::add("white_noise_texture", create, NodeType::SHADER);
1529
1530 static NodeEnum dimensions_enum;
1531 dimensions_enum.insert("1D", 1);
1532 dimensions_enum.insert("2D", 2);
1533 dimensions_enum.insert("3D", 3);
1534 dimensions_enum.insert("4D", 4);
1535 SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
1536
1537 SOCKET_IN_POINT(vector, "Vector", zero_float3());
1538 SOCKET_IN_FLOAT(w, "W", 0.0f);
1539
1540 SOCKET_OUT_FLOAT(value, "Value");
1541 SOCKET_OUT_COLOR(color, "Color");
1542
1543 return type;
1544}
1545
1546WhiteNoiseTextureNode::WhiteNoiseTextureNode() : ShaderNode(get_node_type()) {}
1547
1549{
1550 ShaderInput *vector_in = input("Vector");
1551 ShaderInput *w_in = input("W");
1552 ShaderOutput *value_out = output("Value");
1553 ShaderOutput *color_out = output("Color");
1554
1555 const int vector_stack_offset = compiler.stack_assign(vector_in);
1556 const int w_stack_offset = compiler.stack_assign(w_in);
1557 const int value_stack_offset = compiler.stack_assign(value_out);
1558 const int color_stack_offset = compiler.stack_assign(color_out);
1559
1560 compiler.add_node(NODE_TEX_WHITE_NOISE,
1561 dimensions,
1562 compiler.encode_uchar4(vector_stack_offset, w_stack_offset),
1563 compiler.encode_uchar4(value_stack_offset, color_stack_offset));
1564}
1565
1567{
1568 compiler.parameter(this, "dimensions");
1569 compiler.add(this, "node_white_noise_texture");
1570}
1571
1572/* Wave Texture */
1573
1575{
1576 NodeType *type = NodeType::add("wave_texture", create, NodeType::SHADER);
1577
1579
1580 static NodeEnum type_enum;
1581 type_enum.insert("bands", NODE_WAVE_BANDS);
1582 type_enum.insert("rings", NODE_WAVE_RINGS);
1583 SOCKET_ENUM(wave_type, "Type", type_enum, NODE_WAVE_BANDS);
1584
1585 static NodeEnum bands_direction_enum;
1586 bands_direction_enum.insert("x", NODE_WAVE_BANDS_DIRECTION_X);
1587 bands_direction_enum.insert("y", NODE_WAVE_BANDS_DIRECTION_Y);
1588 bands_direction_enum.insert("z", NODE_WAVE_BANDS_DIRECTION_Z);
1589 bands_direction_enum.insert("diagonal", NODE_WAVE_BANDS_DIRECTION_DIAGONAL);
1591 bands_direction, "Bands Direction", bands_direction_enum, NODE_WAVE_BANDS_DIRECTION_X);
1592
1593 static NodeEnum rings_direction_enum;
1594 rings_direction_enum.insert("x", NODE_WAVE_RINGS_DIRECTION_X);
1595 rings_direction_enum.insert("y", NODE_WAVE_RINGS_DIRECTION_Y);
1596 rings_direction_enum.insert("z", NODE_WAVE_RINGS_DIRECTION_Z);
1597 rings_direction_enum.insert("spherical", NODE_WAVE_RINGS_DIRECTION_SPHERICAL);
1599 rings_direction, "Rings Direction", rings_direction_enum, NODE_WAVE_BANDS_DIRECTION_X);
1600
1601 static NodeEnum profile_enum;
1602 profile_enum.insert("sine", NODE_WAVE_PROFILE_SIN);
1603 profile_enum.insert("saw", NODE_WAVE_PROFILE_SAW);
1604 profile_enum.insert("tri", NODE_WAVE_PROFILE_TRI);
1605 SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN);
1606
1608 SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
1609 SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
1610 SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
1611 SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f);
1612 SOCKET_IN_FLOAT(detail_roughness, "Detail Roughness", 0.5f);
1613 SOCKET_IN_FLOAT(phase, "Phase Offset", 0.0f);
1614 SOCKET_OUT_COLOR(color, "Color");
1615 SOCKET_OUT_FLOAT(fac, "Fac");
1616
1617 return type;
1618}
1619
1620WaveTextureNode::WaveTextureNode() : TextureNode(get_node_type()) {}
1621
1623{
1624 ShaderInput *vector_in = input("Vector");
1625 ShaderInput *scale_in = input("Scale");
1626 ShaderInput *distortion_in = input("Distortion");
1627 ShaderInput *detail_in = input("Detail");
1628 ShaderInput *dscale_in = input("Detail Scale");
1629 ShaderInput *droughness_in = input("Detail Roughness");
1630 ShaderInput *phase_in = input("Phase Offset");
1631 ShaderOutput *color_out = output("Color");
1632 ShaderOutput *fac_out = output("Fac");
1633
1634 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1635
1636 const int scale_ofs = compiler.stack_assign_if_linked(scale_in);
1637 const int distortion_ofs = compiler.stack_assign_if_linked(distortion_in);
1638 const int detail_ofs = compiler.stack_assign_if_linked(detail_in);
1639 const int dscale_ofs = compiler.stack_assign_if_linked(dscale_in);
1640 const int droughness_ofs = compiler.stack_assign_if_linked(droughness_in);
1641 const int phase_ofs = compiler.stack_assign_if_linked(phase_in);
1642 const int color_ofs = compiler.stack_assign_if_linked(color_out);
1643 const int fac_ofs = compiler.stack_assign_if_linked(fac_out);
1644
1645 compiler.add_node(NODE_TEX_WAVE,
1646 compiler.encode_uchar4(wave_type, bands_direction, rings_direction, profile),
1647 compiler.encode_uchar4(vector_offset, scale_ofs, distortion_ofs),
1648 compiler.encode_uchar4(detail_ofs, dscale_ofs, droughness_ofs, phase_ofs));
1649
1650 compiler.add_node(compiler.encode_uchar4(color_ofs, fac_ofs),
1651 __float_as_int(scale),
1652 __float_as_int(distortion),
1653 __float_as_int(detail));
1654
1655 compiler.add_node(__float_as_int(detail_scale),
1656 __float_as_int(detail_roughness),
1657 __float_as_int(phase),
1659
1660 tex_mapping.compile_end(compiler, vector_in, vector_offset);
1661}
1662
1664{
1665 tex_mapping.compile(compiler);
1666
1667 compiler.parameter(this, "wave_type");
1668 compiler.parameter(this, "bands_direction");
1669 compiler.parameter(this, "rings_direction");
1670 compiler.parameter(this, "profile");
1671
1672 compiler.add(this, "node_wave_texture");
1673}
1674
1675/* Magic Texture */
1676
1678{
1679 NodeType *type = NodeType::add("magic_texture", create, NodeType::SHADER);
1680
1682
1683 SOCKET_INT(depth, "Depth", 2);
1684
1686 SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
1687 SOCKET_IN_FLOAT(distortion, "Distortion", 1.0f);
1688
1689 SOCKET_OUT_COLOR(color, "Color");
1690 SOCKET_OUT_FLOAT(fac, "Fac");
1691
1692 return type;
1693}
1694
1695MagicTextureNode::MagicTextureNode() : TextureNode(get_node_type()) {}
1696
1698{
1699 ShaderInput *vector_in = input("Vector");
1700 ShaderInput *scale_in = input("Scale");
1701 ShaderInput *distortion_in = input("Distortion");
1702 ShaderOutput *color_out = output("Color");
1703 ShaderOutput *fac_out = output("Fac");
1704
1705 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1706
1707 compiler.add_node(NODE_TEX_MAGIC,
1708 compiler.encode_uchar4(depth,
1709 compiler.stack_assign_if_linked(color_out),
1710 compiler.stack_assign_if_linked(fac_out)),
1711 compiler.encode_uchar4(vector_offset,
1712 compiler.stack_assign_if_linked(scale_in),
1713 compiler.stack_assign_if_linked(distortion_in)));
1714 compiler.add_node(__float_as_int(scale), __float_as_int(distortion));
1715
1716 tex_mapping.compile_end(compiler, vector_in, vector_offset);
1717}
1718
1720{
1721 tex_mapping.compile(compiler);
1722
1723 compiler.parameter(this, "depth");
1724 compiler.add(this, "node_magic_texture");
1725}
1726
1727/* Checker Texture */
1728
1730{
1731 NodeType *type = NodeType::add("checker_texture", create, NodeType::SHADER);
1732
1734
1736 SOCKET_IN_COLOR(color1, "Color1", zero_float3());
1737 SOCKET_IN_COLOR(color2, "Color2", zero_float3());
1738 SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
1739
1740 SOCKET_OUT_COLOR(color, "Color");
1741 SOCKET_OUT_FLOAT(fac, "Fac");
1742
1743 return type;
1744}
1745
1746CheckerTextureNode::CheckerTextureNode() : TextureNode(get_node_type()) {}
1747
1749{
1750 ShaderInput *vector_in = input("Vector");
1751 ShaderInput *color1_in = input("Color1");
1752 ShaderInput *color2_in = input("Color2");
1753 ShaderInput *scale_in = input("Scale");
1754
1755 ShaderOutput *color_out = output("Color");
1756 ShaderOutput *fac_out = output("Fac");
1757
1758 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1759
1760 compiler.add_node(NODE_TEX_CHECKER,
1761 compiler.encode_uchar4(vector_offset,
1762 compiler.stack_assign(color1_in),
1763 compiler.stack_assign(color2_in),
1764 compiler.stack_assign_if_linked(scale_in)),
1765 compiler.encode_uchar4(compiler.stack_assign_if_linked(color_out),
1766 compiler.stack_assign_if_linked(fac_out)),
1767 __float_as_int(scale));
1768
1769 tex_mapping.compile_end(compiler, vector_in, vector_offset);
1770}
1771
1773{
1774 tex_mapping.compile(compiler);
1775
1776 compiler.add(this, "node_checker_texture");
1777}
1778
1779/* Brick Texture */
1780
1782{
1783 NodeType *type = NodeType::add("brick_texture", create, NodeType::SHADER);
1784
1786
1787 SOCKET_FLOAT(offset, "Offset", 0.5f);
1788 SOCKET_INT(offset_frequency, "Offset Frequency", 2);
1789 SOCKET_FLOAT(squash, "Squash", 1.0f);
1790 SOCKET_INT(squash_frequency, "Squash Frequency", 2);
1791
1793
1794 SOCKET_IN_COLOR(color1, "Color1", zero_float3());
1795 SOCKET_IN_COLOR(color2, "Color2", zero_float3());
1796 SOCKET_IN_COLOR(mortar, "Mortar", zero_float3());
1797 SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
1798 SOCKET_IN_FLOAT(mortar_size, "Mortar Size", 0.02f);
1799 SOCKET_IN_FLOAT(mortar_smooth, "Mortar Smooth", 0.0f);
1800 SOCKET_IN_FLOAT(bias, "Bias", 0.0f);
1801 SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f);
1802 SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f);
1803
1804 SOCKET_OUT_COLOR(color, "Color");
1805 SOCKET_OUT_FLOAT(fac, "Fac");
1806
1807 return type;
1808}
1809
1810BrickTextureNode::BrickTextureNode() : TextureNode(get_node_type()) {}
1811
1813{
1814 ShaderInput *vector_in = input("Vector");
1815 ShaderInput *color1_in = input("Color1");
1816 ShaderInput *color2_in = input("Color2");
1817 ShaderInput *mortar_in = input("Mortar");
1818 ShaderInput *scale_in = input("Scale");
1819 ShaderInput *mortar_size_in = input("Mortar Size");
1820 ShaderInput *mortar_smooth_in = input("Mortar Smooth");
1821 ShaderInput *bias_in = input("Bias");
1822 ShaderInput *brick_width_in = input("Brick Width");
1823 ShaderInput *row_height_in = input("Row Height");
1824
1825 ShaderOutput *color_out = output("Color");
1826 ShaderOutput *fac_out = output("Fac");
1827
1828 const int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1829
1830 compiler.add_node(NODE_TEX_BRICK,
1831 compiler.encode_uchar4(vector_offset,
1832 compiler.stack_assign(color1_in),
1833 compiler.stack_assign(color2_in),
1834 compiler.stack_assign(mortar_in)),
1835 compiler.encode_uchar4(compiler.stack_assign_if_linked(scale_in),
1836 compiler.stack_assign_if_linked(mortar_size_in),
1837 compiler.stack_assign_if_linked(bias_in),
1838 compiler.stack_assign_if_linked(brick_width_in)),
1839 compiler.encode_uchar4(compiler.stack_assign_if_linked(row_height_in),
1840 compiler.stack_assign_if_linked(color_out),
1841 compiler.stack_assign_if_linked(fac_out),
1842 compiler.stack_assign_if_linked(mortar_smooth_in)));
1843
1844 compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
1845 __float_as_int(scale),
1846 __float_as_int(mortar_size),
1847 __float_as_int(bias));
1848
1849 compiler.add_node(__float_as_int(brick_width),
1850 __float_as_int(row_height),
1851 __float_as_int(offset),
1852 __float_as_int(squash));
1853
1854 compiler.add_node(
1856
1857 tex_mapping.compile_end(compiler, vector_in, vector_offset);
1858}
1859
1861{
1862 tex_mapping.compile(compiler);
1863
1864 compiler.parameter(this, "offset");
1865 compiler.parameter(this, "offset_frequency");
1866 compiler.parameter(this, "squash");
1867 compiler.parameter(this, "squash_frequency");
1868 compiler.add(this, "node_brick_texture");
1869}
1870
1871/* Normal */
1872
1874{
1875 NodeType *type = NodeType::add("normal", create, NodeType::SHADER);
1876
1877 SOCKET_VECTOR(direction, "direction", zero_float3());
1878
1879 SOCKET_IN_NORMAL(normal, "Normal", zero_float3());
1880
1881 SOCKET_OUT_NORMAL(normal, "Normal");
1882 SOCKET_OUT_FLOAT(dot, "Dot");
1883
1884 return type;
1885}
1886
1887NormalNode::NormalNode() : ShaderNode(get_node_type()) {}
1888
1889void NormalNode::compile(SVMCompiler &compiler)
1890{
1891 ShaderInput *normal_in = input("Normal");
1892 ShaderOutput *normal_out = output("Normal");
1893 ShaderOutput *dot_out = output("Dot");
1894
1895 compiler.add_node(NODE_NORMAL,
1896 compiler.stack_assign(normal_in),
1897 compiler.stack_assign(normal_out),
1898 compiler.stack_assign(dot_out));
1899 compiler.add_node(
1900 __float_as_int(direction.x), __float_as_int(direction.y), __float_as_int(direction.z));
1901}
1902
1903void NormalNode::compile(OSLCompiler &compiler)
1904{
1905 compiler.parameter(this, "direction");
1906 compiler.add(this, "node_normal");
1907}
1908
1909/* Mapping */
1910
1912{
1913 NodeType *type = NodeType::add("mapping", create, NodeType::SHADER);
1914
1915 static NodeEnum type_enum;
1916 type_enum.insert("point", NODE_MAPPING_TYPE_POINT);
1917 type_enum.insert("texture", NODE_MAPPING_TYPE_TEXTURE);
1918 type_enum.insert("vector", NODE_MAPPING_TYPE_VECTOR);
1919 type_enum.insert("normal", NODE_MAPPING_TYPE_NORMAL);
1920 SOCKET_ENUM(mapping_type, "Type", type_enum, NODE_MAPPING_TYPE_POINT);
1921
1922 SOCKET_IN_POINT(vector, "Vector", zero_float3());
1923 SOCKET_IN_POINT(location, "Location", zero_float3());
1924 SOCKET_IN_POINT(rotation, "Rotation", zero_float3());
1925 SOCKET_IN_POINT(scale, "Scale", one_float3());
1926
1927 SOCKET_OUT_POINT(vector, "Vector");
1928
1929 return type;
1930}
1931
1932MappingNode::MappingNode() : ShaderNode(get_node_type()) {}
1933
1935{
1936 if (folder.all_inputs_constant()) {
1937 const float3 result = svm_mapping(mapping_type, vector, location, rotation, scale);
1938 folder.make_constant(result);
1939 }
1940 else {
1941 folder.fold_mapping(mapping_type);
1942 }
1943}
1944
1945void MappingNode::compile(SVMCompiler &compiler)
1946{
1947 ShaderInput *vector_in = input("Vector");
1948 ShaderInput *location_in = input("Location");
1949 ShaderInput *rotation_in = input("Rotation");
1950 ShaderInput *scale_in = input("Scale");
1951 ShaderOutput *vector_out = output("Vector");
1952
1953 const int vector_stack_offset = compiler.stack_assign(vector_in);
1954 const int location_stack_offset = compiler.stack_assign(location_in);
1955 const int rotation_stack_offset = compiler.stack_assign(rotation_in);
1956 const int scale_stack_offset = compiler.stack_assign(scale_in);
1957 const int result_stack_offset = compiler.stack_assign(vector_out);
1958
1959 compiler.add_node(
1960 NODE_MAPPING,
1961 mapping_type,
1962 compiler.encode_uchar4(
1963 vector_stack_offset, location_stack_offset, rotation_stack_offset, scale_stack_offset),
1964 result_stack_offset);
1965}
1966
1967void MappingNode::compile(OSLCompiler &compiler)
1968{
1969 compiler.parameter(this, "mapping_type");
1970 compiler.add(this, "node_mapping");
1971}
1972
1973/* RGBToBW */
1974
1976{
1977 NodeType *type = NodeType::add("rgb_to_bw", create, NodeType::SHADER);
1978
1979 SOCKET_IN_COLOR(color, "Color", zero_float3());
1980 SOCKET_OUT_FLOAT(val, "Val");
1981
1982 return type;
1983}
1984
1985RGBToBWNode::RGBToBWNode() : ShaderNode(get_node_type()) {}
1986
1988{
1989 if (folder.all_inputs_constant()) {
1990 const float val = folder.scene->shader_manager->linear_rgb_to_gray(color);
1991 folder.make_constant(val);
1992 }
1993}
1994
1995void RGBToBWNode::compile(SVMCompiler &compiler)
1996{
1997 compiler.add_node(NODE_CONVERT,
1999 compiler.stack_assign(inputs[0]),
2000 compiler.stack_assign(outputs[0]));
2001}
2002
2003void RGBToBWNode::compile(OSLCompiler &compiler)
2004{
2005 compiler.add(this, "node_rgb_to_bw");
2006}
2007
2008/* Convert */
2009
2010const NodeType *ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
2011bool ConvertNode::initialized = ConvertNode::register_types();
2012
2013unique_ptr<Node> ConvertNode::create(const NodeType *type)
2014{
2015 return make_unique<ConvertNode>(type->inputs[0].type, type->outputs[0].type);
2016}
2017
2018bool ConvertNode::register_types()
2019{
2020 const int num_types = 8;
2021 const SocketType::Type types[num_types] = {SocketType::FLOAT,
2029
2030 for (size_t i = 0; i < num_types; i++) {
2031 const SocketType::Type from = types[i];
2032 const ustring from_name(SocketType::type_name(from));
2033 const ustring from_value_name("value_" + from_name.string());
2034
2035 for (size_t j = 0; j < num_types; j++) {
2036 const SocketType::Type to = types[j];
2037 const ustring to_name(SocketType::type_name(to));
2038 const ustring to_value_name("value_" + to_name.string());
2039
2040 const string node_name = "convert_" + from_name.string() + "_to_" + to_name.string();
2041 NodeType *type = NodeType::add(node_name.c_str(), create, NodeType::SHADER);
2042
2043 type->register_input(from_value_name,
2044 from_value_name,
2045 from,
2048 nullptr,
2049 nullptr,
2051 type->register_output(to_value_name, to_value_name, to);
2052
2053 assert(from < MAX_TYPE);
2054 assert(to < MAX_TYPE);
2055
2056 node_types[from][to] = type;
2057 }
2058 }
2059
2060 return true;
2061}
2062
2064 : ShaderNode(node_types[from_][to_])
2065{
2066 from = from_;
2067 to = to_;
2068
2069 if (from == to) {
2071 }
2072 else if (autoconvert) {
2074 }
2075}
2076
2077/* Union usage requires a manual copy constructor. */
2079 : ShaderNode(other),
2080 from(other.from),
2081 to(other.to),
2082 value_color(other.value_color),
2083 value_string(other.value_string)
2084{
2085}
2086
2088{
2089 /* proxy nodes should have been removed at this point */
2091
2092 if (folder.all_inputs_constant()) {
2093 if (from == SocketType::FLOAT || from == SocketType::INT) {
2094 float val = value_float;
2095 if (from == SocketType::INT) {
2096 val = value_int;
2097 }
2098 if (SocketType::is_float3(to)) {
2099 folder.make_constant(make_float3(val, val, val));
2100 }
2101 else if (to == SocketType::INT) {
2102 folder.make_constant((int)val);
2103 }
2104 else if (to == SocketType::FLOAT) {
2105 folder.make_constant(val);
2106 }
2107 }
2108 else if (SocketType::is_float3(from)) {
2109 if (to == SocketType::FLOAT || to == SocketType::INT) {
2110 float val;
2111 if (from == SocketType::COLOR) {
2112 /* color to scalar */
2113 val = folder.scene->shader_manager->linear_rgb_to_gray(value_color);
2114 }
2115 else {
2116 /* vector/point/normal to scalar */
2117 val = average(value_vector);
2118 }
2119 if (to == SocketType::INT) {
2120 folder.make_constant((int)val);
2121 }
2122 else if (to == SocketType::FLOAT) {
2123 folder.make_constant(val);
2124 }
2125 }
2126 else if (SocketType::is_float3(to)) {
2127 folder.make_constant(value_color);
2128 }
2129 }
2130 }
2131 else {
2132 ShaderInput *in = inputs[0];
2133 ShaderNode *prev = in->link->parent;
2134
2135 /* no-op conversion of A to B to A */
2136 if (prev->type == node_types[to][from]) {
2137 ShaderInput *prev_in = prev->inputs[0];
2138
2140 prev_in->link)
2141 {
2142 folder.bypass(prev_in->link);
2143 }
2144 }
2145 }
2146}
2147
2148void ConvertNode::compile(SVMCompiler &compiler)
2149{
2150 /* proxy nodes should have been removed at this point */
2152
2153 ShaderInput *in = inputs[0];
2154 ShaderOutput *out = outputs[0];
2155
2156 if (from == SocketType::FLOAT) {
2157 if (to == SocketType::INT) {
2158 /* float to int */
2159 compiler.add_node(
2160 NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
2161 }
2162 else {
2163 /* float to float3 */
2164 compiler.add_node(
2165 NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
2166 }
2167 }
2168 else if (from == SocketType::INT) {
2169 if (to == SocketType::FLOAT) {
2170 /* int to float */
2171 compiler.add_node(
2172 NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
2173 }
2174 else {
2175 /* int to vector/point/normal */
2176 compiler.add_node(
2177 NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
2178 }
2179 }
2180 else if (to == SocketType::FLOAT) {
2181 if (from == SocketType::COLOR) {
2182 /* color to float */
2183 compiler.add_node(
2184 NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
2185 }
2186 else {
2187 /* vector/point/normal to float */
2188 compiler.add_node(
2189 NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
2190 }
2191 }
2192 else if (to == SocketType::INT) {
2193 if (from == SocketType::COLOR) {
2194 /* color to int */
2195 compiler.add_node(
2196 NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
2197 }
2198 else {
2199 /* vector/point/normal to int */
2200 compiler.add_node(
2201 NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out));
2202 }
2203 }
2204 else {
2205 /* float3 to float3 */
2206 if (in->link) {
2207 /* no op in SVM */
2208 compiler.stack_link(in, out);
2209 }
2210 else {
2211 /* set 0,0,0 value */
2212 compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
2213 compiler.add_node(NODE_VALUE_V, value_color);
2214 }
2215 }
2216}
2217
2218void ConvertNode::compile(OSLCompiler &compiler)
2219{
2220 /* proxy nodes should have been removed at this point */
2222
2223 if (from == SocketType::FLOAT) {
2224 compiler.add(this, "node_convert_from_float");
2225 }
2226 else if (from == SocketType::INT) {
2227 compiler.add(this, "node_convert_from_int");
2228 }
2229 else if (from == SocketType::COLOR) {
2230 compiler.add(this, "node_convert_from_color");
2231 }
2232 else if (from == SocketType::VECTOR) {
2233 compiler.add(this, "node_convert_from_vector");
2234 }
2235 else if (from == SocketType::POINT) {
2236 compiler.add(this, "node_convert_from_point");
2237 }
2238 else if (from == SocketType::NORMAL) {
2239 compiler.add(this, "node_convert_from_normal");
2240 }
2241 else {
2242 assert(0);
2243 }
2244}
2245
2246/* Base type for all closure-type nodes */
2247
2252
2254{
2255 /* detect if anything is plugged into the normal input besides the default */
2256 ShaderInput *normal_in = input("Normal");
2257 return (normal_in && normal_in->link &&
2259}
2260
2261/* BSDF Closure */
2262
2263BsdfNode::BsdfNode(const NodeType *node_type) : BsdfBaseNode(node_type) {}
2264
2266 ShaderInput *bsdf_y,
2267 ShaderInput *bsdf_z,
2268 ShaderInput *data_y,
2269 ShaderInput *data_z,
2270 ShaderInput *data_w)
2271{
2272 ShaderInput *color_in = input("Color");
2273 ShaderInput *normal_in = input("Normal");
2274
2275 if (color_in->link) {
2276 compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
2277 }
2278 else {
2279 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
2280 }
2281
2282 const int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) :
2284 const int data_y_offset = (data_y) ? compiler.stack_assign(data_y) : SVM_STACK_INVALID;
2285 const int data_z_offset = (data_z) ? compiler.stack_assign(data_z) : SVM_STACK_INVALID;
2286 const int data_w_offset = (data_w) ? compiler.stack_assign(data_w) : SVM_STACK_INVALID;
2287
2288 compiler.add_node(NODE_CLOSURE_BSDF,
2289 compiler.encode_uchar4(
2290 closure,
2291 (bsdf_y) ? compiler.stack_assign_if_linked(bsdf_y) : SVM_STACK_INVALID,
2292 (bsdf_z) ? compiler.stack_assign_if_linked(bsdf_z) : SVM_STACK_INVALID,
2293 compiler.closure_mix_weight_offset()),
2294 __float_as_int((bsdf_y) ? get_float(bsdf_y->socket_type) : 0.0f),
2295 __float_as_int((bsdf_z) ? get_float(bsdf_z->socket_type) : 0.0f));
2296
2297 compiler.add_node(normal_offset, data_y_offset, data_z_offset, data_w_offset);
2298}
2299
2300void BsdfNode::compile(SVMCompiler &compiler)
2301{
2302 compile(compiler, nullptr, nullptr);
2303}
2304
2305void BsdfNode::compile(OSLCompiler & /*compiler*/)
2306{
2307 assert(0);
2308}
2309
2310/* Metallic BSDF Closure */
2311
2313{
2314 NodeType *type = NodeType::add("metallic_bsdf", create, NodeType::SHADER);
2315
2316 SOCKET_IN_COLOR(color, "Base Color", make_float3(0.617f, 0.577f, 0.540f));
2318 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2319
2320 static NodeEnum distribution_enum;
2321 distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
2322 distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_ID);
2323 distribution_enum.insert("multi_ggx", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
2325 distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
2326
2327 static NodeEnum fresnel_type_enum;
2328 fresnel_type_enum.insert("f82", CLOSURE_BSDF_F82_CONDUCTOR);
2329 fresnel_type_enum.insert("physical_conductor", CLOSURE_BSDF_PHYSICAL_CONDUCTOR);
2330 SOCKET_ENUM(fresnel_type, "fresnel_type", fresnel_type_enum, CLOSURE_BSDF_F82_CONDUCTOR);
2331
2332 SOCKET_IN_COLOR(edge_tint, "Edge Tint", make_float3(0.695f, 0.726f, 0.770f));
2333
2334 SOCKET_IN_VECTOR(ior, "IOR", make_float3(2.757f, 2.513f, 2.231f));
2335 SOCKET_IN_VECTOR(k, "Extinction", make_float3(3.867f, 3.404f, 3.009f));
2336
2338
2339 SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
2340 SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
2341 SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
2342
2343 SOCKET_IN_FLOAT(thin_film_thickness, "Thin Film Thickness", 0.0f);
2344 SOCKET_IN_FLOAT(thin_film_ior, "Thin Film IOR", 1.33f);
2345
2346 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2347
2348 return type;
2349}
2350
2351MetallicBsdfNode::MetallicBsdfNode() : BsdfNode(get_node_type())
2352{
2354}
2355
2357{
2358 ShaderInput *anisotropy_input = input("Anisotropy");
2359 /* Keep in sync with the thresholds in OSL's node_conductor_bsdf and SVM's
2360 * svm_node_metallic_bsdf. */
2361 return (!anisotropy_input->link && fabsf(anisotropy) <= 1e-4f);
2362}
2363
2365{
2366 if (shader->has_surface_link()) {
2367 ShaderInput *tangent_in = input("Tangent");
2368 if (!tangent_in->link && !is_isotropic()) {
2370 }
2371 }
2372
2374}
2375
2377{
2378 /* If the anisotropy is close enough to zero, fall back to the isotropic case. */
2379 if (is_isotropic()) {
2380 disconnect_unused_input("Tangent");
2381 }
2382}
2383
2385{
2386 const int base_color_ior_offset = fresnel_type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR ?
2387 compiler.stack_assign(input("IOR")) :
2388 compiler.stack_assign(input("Base Color"));
2389 const int edge_tint_k_offset = fresnel_type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR ?
2390 compiler.stack_assign(input("Extinction")) :
2391 compiler.stack_assign(input("Edge Tint"));
2392
2393 const int thin_film_thickness_offset = compiler.stack_assign(input("Thin Film Thickness"));
2394 const int thin_film_ior_offset = compiler.stack_assign(input("Thin Film IOR"));
2395
2396 ShaderInput *roughness_in = input("Roughness");
2397 ShaderInput *anisotropy_in = input("Anisotropy");
2398
2399 const int normal_offset = compiler.stack_assign_if_linked(input("Normal"));
2400 const int tangent_offset = compiler.stack_assign_if_linked(input("Tangent"));
2401 const int rotation_offset = compiler.stack_assign(input("Rotation"));
2402
2403 compiler.add_node(NODE_CLOSURE_BSDF,
2404 compiler.encode_uchar4(fresnel_type,
2405 compiler.stack_assign_if_linked(roughness_in),
2406 compiler.stack_assign_if_linked(anisotropy_in),
2407 compiler.closure_mix_weight_offset()),
2408 __float_as_int(get_float(roughness_in->socket_type)),
2409 __float_as_int(get_float(anisotropy_in->socket_type)));
2410 compiler.add_node(
2411 normal_offset,
2412 compiler.encode_uchar4(
2413 base_color_ior_offset, edge_tint_k_offset, rotation_offset, tangent_offset),
2414 compiler.encode_uchar4(distribution, thin_film_thickness_offset, thin_film_ior_offset));
2415}
2416
2418{
2419 compiler.parameter(this, "distribution");
2420 compiler.parameter(this, "fresnel_type");
2421 compiler.add(this, "node_metallic_bsdf");
2422}
2423
2424/* Glossy BSDF Closure */
2425
2427{
2428 NodeType *type = NodeType::add("glossy_bsdf", create, NodeType::SHADER);
2429
2430 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2432 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2433
2434 static NodeEnum distribution_enum;
2435 distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
2436 distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_ID);
2437 distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
2438 distribution_enum.insert("multi_ggx", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
2439 SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
2440
2442
2443 SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
2444 SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
2445 SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
2446
2447 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2448
2449 return type;
2450}
2451
2452GlossyBsdfNode::GlossyBsdfNode() : BsdfNode(get_node_type())
2453{
2455}
2456
2458{
2459 ShaderInput *anisotropy_input = input("Anisotropy");
2460 /* Keep in sync with the thresholds in OSL's node_glossy_bsdf and SVM's svm_node_closure_bsdf.
2461 */
2462 return (!anisotropy_input->link && fabsf(anisotropy) <= 1e-4f);
2463}
2464
2466{
2467 if (shader->has_surface_link()) {
2468 ShaderInput *tangent_in = input("Tangent");
2469 if (!tangent_in->link && !is_isotropic()) {
2471 }
2472 }
2473
2475}
2476
2478{
2479 /* If the anisotropy is close enough to zero, fall back to the isotropic case. */
2480 if (is_isotropic()) {
2481 disconnect_unused_input("Tangent");
2482 }
2483}
2484
2486{
2487 closure = distribution;
2488
2489 ShaderInput *tangent = input("Tangent");
2490 tangent = compiler.is_linked(tangent) ? tangent : nullptr;
2491
2492 /* TODO: Just use weight for legacy MultiGGX? Would also simplify OSL. */
2494 BsdfNode::compile(compiler,
2495 input("Roughness"),
2496 input("Anisotropy"),
2497 input("Rotation"),
2498 input("Color"),
2499 tangent);
2500 }
2501 else {
2503 compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), nullptr, tangent);
2504 }
2505}
2506
2508{
2509 compiler.parameter(this, "distribution");
2510 compiler.add(this, "node_glossy_bsdf");
2511}
2512
2513/* Glass BSDF Closure */
2514
2516{
2517 NodeType *type = NodeType::add("glass_bsdf", create, NodeType::SHADER);
2518
2519 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2521 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2522
2523 static NodeEnum distribution_enum;
2524 distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
2525 distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
2526 distribution_enum.insert("multi_ggx", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
2528 distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
2529 SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
2530 SOCKET_IN_FLOAT(IOR, "IOR", 1.5f);
2531
2532 SOCKET_IN_FLOAT(thin_film_thickness, "Thin Film Thickness", 0.0f);
2533 SOCKET_IN_FLOAT(thin_film_ior, "Thin Film IOR", 1.3f);
2534
2535 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2536
2537 return type;
2538}
2539
2540GlassBsdfNode::GlassBsdfNode() : BsdfNode(get_node_type())
2541{
2543}
2544
2545void GlassBsdfNode::compile(SVMCompiler &compiler)
2546{
2547 closure = distribution;
2548 BsdfNode::compile(compiler,
2549 input("Roughness"),
2550 input("IOR"),
2551 input("Color"),
2552 input("Thin Film Thickness"),
2553 input("Thin Film IOR"));
2554}
2555
2556void GlassBsdfNode::compile(OSLCompiler &compiler)
2557{
2558 compiler.parameter(this, "distribution");
2559 compiler.add(this, "node_glass_bsdf");
2560}
2561
2562/* Refraction BSDF Closure */
2563
2565{
2566 NodeType *type = NodeType::add("refraction_bsdf", create, NodeType::SHADER);
2567
2568 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2570 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2571
2572 static NodeEnum distribution_enum;
2573 distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
2574 distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
2576 distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
2577
2578 SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
2579 SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
2580
2581 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2582
2583 return type;
2584}
2585
2586RefractionBsdfNode::RefractionBsdfNode() : BsdfNode(get_node_type())
2587{
2589}
2590
2592{
2593 closure = distribution;
2594
2595 BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
2596}
2597
2599{
2600 compiler.parameter(this, "distribution");
2601 compiler.add(this, "node_refraction_bsdf");
2602}
2603
2604/* Toon BSDF Closure */
2605
2607{
2608 NodeType *type = NodeType::add("toon_bsdf", create, NodeType::SHADER);
2609
2610 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2612 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2613
2614 static NodeEnum component_enum;
2615 component_enum.insert("diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
2616 component_enum.insert("glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
2617 SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_DIFFUSE_TOON_ID);
2618 SOCKET_IN_FLOAT(size, "Size", 0.5f);
2619 SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
2620
2621 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2622
2623 return type;
2624}
2625
2626ToonBsdfNode::ToonBsdfNode() : BsdfNode(get_node_type())
2627{
2629}
2630
2631void ToonBsdfNode::compile(SVMCompiler &compiler)
2632{
2633 closure = component;
2634
2635 BsdfNode::compile(compiler, input("Size"), input("Smooth"));
2636}
2637
2638void ToonBsdfNode::compile(OSLCompiler &compiler)
2639{
2640 compiler.parameter(this, "component");
2641 compiler.add(this, "node_toon_bsdf");
2642}
2643
2644/* Sheen BSDF Closure */
2645
2647{
2648 NodeType *type = NodeType::add("sheen_bsdf", create, NodeType::SHADER);
2649
2650 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2652 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2653 SOCKET_IN_FLOAT(roughness, "Roughness", 1.0f);
2654
2655 static NodeEnum distribution_enum;
2656 distribution_enum.insert("ashikhmin", CLOSURE_BSDF_ASHIKHMIN_VELVET_ID);
2657 distribution_enum.insert("microfiber", CLOSURE_BSDF_SHEEN_ID);
2658 SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_SHEEN_ID);
2659
2660 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2661
2662 return type;
2663}
2664
2665SheenBsdfNode::SheenBsdfNode() : BsdfNode(get_node_type())
2666{
2667 closure = CLOSURE_BSDF_SHEEN_ID;
2668}
2669
2670void SheenBsdfNode::compile(SVMCompiler &compiler)
2671{
2672 closure = distribution;
2673 BsdfNode::compile(compiler, input("Roughness"), nullptr);
2674}
2675
2676void SheenBsdfNode::compile(OSLCompiler &compiler)
2677{
2678 compiler.parameter(this, "distribution");
2679 compiler.add(this, "node_sheen_bsdf");
2680}
2681
2682/* Diffuse BSDF Closure */
2683
2685{
2686 NodeType *type = NodeType::add("diffuse_bsdf", create, NodeType::SHADER);
2687
2688 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2690 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2691 SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
2692
2693 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2694
2695 return type;
2696}
2697
2698DiffuseBsdfNode::DiffuseBsdfNode() : BsdfNode(get_node_type())
2699{
2700 closure = CLOSURE_BSDF_DIFFUSE_ID;
2701}
2702
2704{
2705 BsdfNode::compile(compiler, input("Roughness"), nullptr, input("Color"));
2706}
2707
2709{
2710 compiler.add(this, "node_diffuse_bsdf");
2711}
2712
2713/* Disney principled BSDF Closure */
2715{
2716 NodeType *type = NodeType::add("principled_bsdf", create, NodeType::SHADER);
2717
2718 static NodeEnum distribution_enum;
2719 distribution_enum.insert("ggx", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
2720 distribution_enum.insert("multi_ggx", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
2722 distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
2723
2724 static NodeEnum subsurface_method_enum;
2725 subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
2726 subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
2727 subsurface_method_enum.insert("random_walk_skin", CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
2728 SOCKET_ENUM(subsurface_method,
2729 "Subsurface Method",
2730 subsurface_method_enum,
2732
2733 SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f))
2734 SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
2735 SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
2736 SOCKET_IN_FLOAT(ior, "IOR", 1.5f);
2737 SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
2739
2740 SOCKET_IN_FLOAT(diffuse_roughness, "Diffuse Roughness", 0.0f);
2741
2742 SOCKET_IN_FLOAT(subsurface_weight, "Subsurface Weight", 0.0f);
2743 SOCKET_IN_FLOAT(subsurface_scale, "Subsurface Scale", 0.1f);
2744 SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
2745 SOCKET_IN_FLOAT(subsurface_ior, "Subsurface IOR", 1.4f);
2746 SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
2747
2748 SOCKET_IN_FLOAT(specular_ior_level, "Specular IOR Level", 0.5f);
2749 SOCKET_IN_COLOR(specular_tint, "Specular Tint", one_float3());
2750 SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
2751 SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
2753
2754 SOCKET_IN_FLOAT(transmission_weight, "Transmission Weight", 0.0f);
2755
2756 SOCKET_IN_FLOAT(sheen_weight, "Sheen Weight", 0.0f);
2757 SOCKET_IN_FLOAT(sheen_roughness, "Sheen Roughness", 0.5f);
2758 SOCKET_IN_COLOR(sheen_tint, "Sheen Tint", one_float3());
2759
2760 SOCKET_IN_FLOAT(coat_weight, "Coat Weight", 0.0f);
2761 SOCKET_IN_FLOAT(coat_roughness, "Coat Roughness", 0.03f);
2762 SOCKET_IN_FLOAT(coat_ior, "Coat IOR", 1.5f);
2763 SOCKET_IN_COLOR(coat_tint, "Coat Tint", one_float3());
2764 SOCKET_IN_NORMAL(coat_normal, "Coat Normal", zero_float3(), SocketType::LINK_NORMAL);
2765
2766 SOCKET_IN_COLOR(emission_color, "Emission Color", one_float3());
2767 SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
2768
2769 SOCKET_IN_FLOAT(thin_film_thickness, "Thin Film Thickness", 0.0f);
2770 SOCKET_IN_FLOAT(thin_film_ior, "Thin Film IOR", 1.3f);
2771
2772 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2773
2774 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2775
2776 return type;
2777}
2778
2779PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(get_node_type())
2780{
2783}
2784
2786{
2787 if (!has_surface_emission()) {
2788 /* Emission will be zero, so optimize away any connected emission input. */
2789 disconnect_unused_input("Emission Color");
2790 disconnect_unused_input("Emission Strength");
2791 }
2792
2793 if (!has_surface_bssrdf()) {
2794 disconnect_unused_input("Subsurface Weight");
2795 disconnect_unused_input("Subsurface Radius");
2796 disconnect_unused_input("Subsurface Scale");
2797 disconnect_unused_input("Subsurface IOR");
2798 disconnect_unused_input("Subsurface Anisotropy");
2799 }
2800
2801 if (!has_nonzero_weight("Coat Weight")) {
2802 disconnect_unused_input("Coat Weight");
2803 disconnect_unused_input("Coat IOR");
2804 disconnect_unused_input("Coat Roughness");
2805 disconnect_unused_input("Coat Tint");
2806 }
2807
2808 if (!has_nonzero_weight("Sheen Weight")) {
2809 disconnect_unused_input("Sheen Weight");
2810 disconnect_unused_input("Sheen Roughness");
2811 disconnect_unused_input("Sheen Tint");
2812 }
2813
2814 if (!has_nonzero_weight("Anisotropic")) {
2815 disconnect_unused_input("Anisotropic");
2816 disconnect_unused_input("Anisotropic Rotation");
2817 disconnect_unused_input("Tangent");
2818 }
2819
2820 if (!has_nonzero_weight("Thin Film Thickness")) {
2821 disconnect_unused_input("Thin Film Thickness");
2822 disconnect_unused_input("Thin Film IOR");
2823 }
2824}
2825
2827{
2828 ShaderInput *alpha_in = input("Alpha");
2829 return (alpha_in->link != nullptr || alpha < (1.0f - CLOSURE_WEIGHT_CUTOFF));
2830}
2831
2833{
2834 ShaderInput *emission_color_in = input("Emission Color");
2835 ShaderInput *emission_strength_in = input("Emission Strength");
2836 return (emission_color_in->link != nullptr ||
2837 reduce_max(emission_color) > CLOSURE_WEIGHT_CUTOFF) &&
2838 (emission_strength_in->link != nullptr || emission_strength > CLOSURE_WEIGHT_CUTOFF);
2839}
2840
2842{
2843 ShaderInput *subsurface_weight_in = input("Subsurface Weight");
2844 ShaderInput *subsurface_scale_in = input("Subsurface Scale");
2845 return (subsurface_weight_in->link != nullptr || subsurface_weight > CLOSURE_WEIGHT_CUTOFF) &&
2846 (subsurface_scale_in->link != nullptr || subsurface_scale != 0.0f);
2847}
2848
2850{
2851 ShaderInput *weight_in = input(name);
2852 if (weight_in == nullptr) {
2853 return true;
2854 }
2855 if (weight_in->link != nullptr) {
2856 return true;
2857 }
2858 return (get_float(weight_in->socket_type) >= CLOSURE_WEIGHT_CUTOFF);
2859}
2860
2862{
2863 if (shader->has_surface_link()) {
2864 ShaderInput *tangent_in = input("Tangent");
2865
2866 if (!tangent_in->link) {
2868 }
2869 }
2870
2872}
2873
2875{
2876 /* Allocate basic material inputs. */
2877 const int base_color_offset = compiler.stack_assign_if_linked(input("Base Color"));
2878 const int ior_offset = compiler.stack_assign_if_linked(input("IOR"));
2879 const int roughness_offset = compiler.stack_assign_if_linked(input("Roughness"));
2880 const int metallic_offset = compiler.stack_assign_if_not_equal(input("Metallic"), 0.0f);
2881
2882 /* Allocate miscellaneous inputs. */
2883 const int alpha_offset = compiler.stack_assign_if_not_equal(input("Alpha"), 1.0f);
2884 const int normal_offset = compiler.stack_assign_if_linked(input("Normal"));
2885 const int coat_normal_offset = compiler.stack_assign_if_linked(input("Coat Normal"));
2886 const int transmission_weight_offset = compiler.stack_assign_if_not_equal(
2887 input("Transmission Weight"), 0.0f);
2888 const int diffuse_roughness_offset = compiler.stack_assign_if_not_equal(
2889 input("Diffuse Roughness"), 0.0f);
2890 const int specular_ior_level_offset = compiler.stack_assign_if_not_equal(
2891 input("Specular IOR Level"), 0.5f);
2892 const int specular_tint_offset = compiler.stack_assign_if_not_equal(input("Specular Tint"),
2893 one_float3());
2894
2895 /* Allocate emission inputs, if enabled. */
2896 int emission_strength_offset = SVM_STACK_INVALID;
2897 int emission_color_offset = SVM_STACK_INVALID;
2898 if (has_surface_emission()) {
2899 emission_strength_offset = compiler.stack_assign(input("Emission Strength"));
2900 emission_color_offset = compiler.stack_assign(input("Emission Color"));
2901 }
2902
2903 /* Allocate subsurface inputs, if enabled. */
2904 int subsurface_weight_offset = SVM_STACK_INVALID;
2905 int subsurface_radius_offset = SVM_STACK_INVALID;
2906 int subsurface_scale_offset = SVM_STACK_INVALID;
2907 int subsurface_ior_offset = SVM_STACK_INVALID;
2908 int subsurface_anisotropy_offset = SVM_STACK_INVALID;
2909 if (has_surface_bssrdf()) {
2910 subsurface_weight_offset = compiler.stack_assign(input("Subsurface Weight"));
2911 subsurface_radius_offset = compiler.stack_assign(input("Subsurface Radius"));
2912 subsurface_scale_offset = compiler.stack_assign(input("Subsurface Scale"));
2913 subsurface_ior_offset = compiler.stack_assign_if_not_equal(input("Subsurface IOR"), 1.4f);
2914 subsurface_anisotropy_offset = compiler.stack_assign_if_not_equal(
2915 input("Subsurface Anisotropy"), 0.0f);
2916 }
2917
2918 /* Allocate coat inputs, if enabled. */
2919 int coat_weight_offset = SVM_STACK_INVALID;
2920 int coat_roughness_offset = SVM_STACK_INVALID;
2921 int coat_ior_offset = SVM_STACK_INVALID;
2922 int coat_tint_offset = SVM_STACK_INVALID;
2923 if (has_nonzero_weight("Coat Weight")) {
2924 coat_weight_offset = compiler.stack_assign(input("Coat Weight"));
2925 coat_roughness_offset = compiler.stack_assign(input("Coat Roughness"));
2926 coat_ior_offset = compiler.stack_assign(input("Coat IOR"));
2927 coat_tint_offset = compiler.stack_assign_if_not_equal(input("Coat Tint"), one_float3());
2928 }
2929
2930 /* Allocate sheen inputs, if enabled. */
2931 int sheen_weight_offset = SVM_STACK_INVALID;
2932 int sheen_roughness_offset = SVM_STACK_INVALID;
2933 int sheen_tint_offset = SVM_STACK_INVALID;
2934 if (has_nonzero_weight("Sheen Weight")) {
2935 sheen_weight_offset = compiler.stack_assign(input("Sheen Weight"));
2936 sheen_roughness_offset = compiler.stack_assign(input("Sheen Roughness"));
2937 sheen_tint_offset = compiler.stack_assign_if_not_equal(input("Sheen Tint"), one_float3());
2938 }
2939
2940 /* Allocate anisotropy inputs, if enabled. */
2941 int anisotropic_offset = SVM_STACK_INVALID;
2942 int anisotropic_rotation_offset = SVM_STACK_INVALID;
2943 int tangent_offset = SVM_STACK_INVALID;
2944 if (has_nonzero_weight("Anisotropic")) {
2945 anisotropic_offset = compiler.stack_assign(input("Anisotropic"));
2946 anisotropic_rotation_offset = compiler.stack_assign_if_not_equal(input("Anisotropic Rotation"),
2947 0.0f);
2948 tangent_offset = compiler.stack_assign_if_linked(input("Tangent"));
2949 }
2950
2951 /* Allocate thin film inputs, if enabled. */
2952 int thin_film_thickness_offset = SVM_STACK_INVALID;
2953 int thin_film_ior_offset = SVM_STACK_INVALID;
2954 if (has_nonzero_weight("Thin Film Thickness")) {
2955 thin_film_thickness_offset = compiler.stack_assign(input("Thin Film Thickness"));
2956 thin_film_ior_offset = compiler.stack_assign(input("Thin Film IOR"));
2957 }
2958
2959 compiler.add_node(
2960 NODE_CLOSURE_BSDF,
2961 compiler.encode_uchar4(
2962 closure, ior_offset, roughness_offset, compiler.closure_mix_weight_offset()),
2963 __float_as_int(get_float(input("IOR")->socket_type)),
2964 __float_as_int(get_float(input("Roughness")->socket_type)));
2965
2966 compiler.add_node(
2967 normal_offset,
2968 compiler.encode_uchar4(base_color_offset, metallic_offset, alpha_offset, coat_normal_offset),
2969 compiler.encode_uchar4(
2970 distribution, diffuse_roughness_offset, specular_ior_level_offset, specular_tint_offset),
2971 compiler.encode_uchar4(emission_strength_offset,
2972 emission_color_offset,
2973 anisotropic_offset,
2974 thin_film_thickness_offset));
2975
2976 compiler.add_node(
2977 compiler.encode_uchar4(subsurface_weight_offset,
2978 coat_weight_offset,
2979 sheen_weight_offset,
2980 transmission_weight_offset),
2981 compiler.encode_uchar4(
2982 coat_roughness_offset, coat_ior_offset, coat_tint_offset, subsurface_method),
2983 compiler.encode_uchar4(subsurface_radius_offset,
2984 subsurface_scale_offset,
2985 subsurface_ior_offset,
2986 subsurface_anisotropy_offset),
2987 compiler.encode_uchar4(
2988 sheen_roughness_offset, sheen_tint_offset, anisotropic_rotation_offset, tangent_offset));
2989
2990 const float3 base_color = get_float3(input("Base Color")->socket_type);
2991 compiler.add_node(thin_film_ior_offset,
2992 __float_as_int(base_color.x),
2993 __float_as_int(base_color.y),
2994 __float_as_int(base_color.z));
2995}
2996
2998{
2999 compiler.parameter(this, "distribution");
3000 compiler.parameter(this, "subsurface_method");
3001 compiler.add(this, "node_principled_bsdf");
3002}
3003
3008
3009/* Translucent BSDF Closure */
3010
3012{
3013 NodeType *type = NodeType::add("translucent_bsdf", create, NodeType::SHADER);
3014
3015 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3017 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3018
3019 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3020
3021 return type;
3022}
3023
3024TranslucentBsdfNode::TranslucentBsdfNode() : BsdfNode(get_node_type())
3025{
3027}
3028
3030{
3031 BsdfNode::compile(compiler, nullptr, nullptr);
3032}
3033
3035{
3036 compiler.add(this, "node_translucent_bsdf");
3037}
3038
3039/* Transparent BSDF Closure */
3040
3042{
3043 NodeType *type = NodeType::add("transparent_bsdf", create, NodeType::SHADER);
3044
3045 SOCKET_IN_COLOR(color, "Color", one_float3());
3046 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3047
3048 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3049
3050 return type;
3051}
3052
3053TransparentBsdfNode::TransparentBsdfNode() : BsdfNode(get_node_type())
3054{
3056}
3057
3059{
3060 BsdfNode::compile(compiler, nullptr, nullptr);
3061}
3062
3064{
3065 compiler.add(this, "node_transparent_bsdf");
3066}
3067
3068/* Ray Portal BSDF Closure */
3069
3071{
3072 NodeType *type = NodeType::add("ray_portal_bsdf", create, NodeType::SHADER);
3073
3074 SOCKET_IN_COLOR(color, "Color", one_float3());
3075 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3076
3077 SOCKET_IN_VECTOR(position, "Position", zero_float3(), SocketType::LINK_POSITION);
3078 SOCKET_IN_VECTOR(direction, "Direction", zero_float3());
3079
3080 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3081
3082 return type;
3083}
3084
3085RayPortalBsdfNode::RayPortalBsdfNode() : BsdfNode(get_node_type())
3086{
3088}
3089
3091{
3092 BsdfNode::compile(compiler, nullptr, nullptr, input("Position"), input("Direction"));
3093}
3094
3096{
3097 compiler.add(this, "node_ray_portal_bsdf");
3098}
3099
3100/* Subsurface Scattering Closure */
3101
3103{
3104 NodeType *type = NodeType::add("subsurface_scattering", create, NodeType::SHADER);
3105
3106 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3108 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3109
3110 static NodeEnum method_enum;
3111 method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
3112 method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
3113 method_enum.insert("random_walk_skin", CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID);
3114 SOCKET_ENUM(method, "Method", method_enum, CLOSURE_BSSRDF_RANDOM_WALK_ID);
3115
3116 SOCKET_IN_FLOAT(scale, "Scale", 0.01f);
3117 SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f));
3118
3119 SOCKET_IN_FLOAT(subsurface_ior, "IOR", 1.4f);
3120 SOCKET_IN_FLOAT(subsurface_roughness, "Roughness", 1.0f);
3121 SOCKET_IN_FLOAT(subsurface_anisotropy, "Anisotropy", 0.0f);
3122
3123 SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF");
3124
3125 return type;
3126}
3127
3128SubsurfaceScatteringNode::SubsurfaceScatteringNode() : BsdfNode(get_node_type())
3129{
3130 closure = method;
3131}
3132
3134{
3135 closure = method;
3136 BsdfNode::compile(compiler,
3137 input("Scale"),
3138 input("IOR"),
3139 input("Radius"),
3140 input("Anisotropy"),
3141 input("Roughness"));
3142}
3143
3145{
3146 closure = method;
3147 compiler.parameter(this, "method");
3148 compiler.add(this, "node_subsurface_scattering");
3149}
3150
3152{
3153 /* detect if anything is plugged into the normal input besides the default */
3154 ShaderInput *normal_in = input("Normal");
3155 return (normal_in->link &&
3157}
3158
3159/* Emissive Closure */
3160
3162{
3163 NodeType *type = NodeType::add("emission", create, NodeType::SHADER);
3164
3165 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3166 SOCKET_IN_FLOAT(strength, "Strength", 10.0f);
3167 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3168 SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3169
3170 SOCKET_OUT_CLOSURE(emission, "Emission");
3171
3172 return type;
3173}
3174
3175EmissionNode::EmissionNode() : ShaderNode(get_node_type()) {}
3176
3177void EmissionNode::compile(SVMCompiler &compiler)
3178{
3179 ShaderInput *color_in = input("Color");
3180 ShaderInput *strength_in = input("Strength");
3181
3182 const int strength_offset = compiler.stack_assign_if_linked(strength_in);
3183
3184 if (color_in->link || strength_in->link) {
3185 compiler.add_node(NODE_EMISSION_WEIGHT,
3186 compiler.stack_assign(color_in),
3187 strength_offset,
3188 __float_as_int(get_float(strength_in->socket_type)));
3189 }
3190 else {
3191 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
3192 }
3193
3194 compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
3195}
3196
3197void EmissionNode::compile(OSLCompiler &compiler)
3198{
3199 compiler.add(this, "node_emission");
3200}
3201
3203{
3204 ShaderInput *color_in = input("Color");
3205 ShaderInput *strength_in = input("Strength");
3206
3207 if ((!color_in->link && color == zero_float3()) || (!strength_in->link && strength == 0.0f)) {
3208 folder.discard();
3209 }
3210}
3211
3212/* Background Closure */
3213
3215{
3216 NodeType *type = NodeType::add("background_shader", create, NodeType::SHADER);
3217
3218 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3219 SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
3220 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3221
3222 SOCKET_OUT_CLOSURE(background, "Background");
3223
3224 return type;
3225}
3226
3227BackgroundNode::BackgroundNode() : ShaderNode(get_node_type()) {}
3228
3230{
3231 ShaderInput *color_in = input("Color");
3232 ShaderInput *strength_in = input("Strength");
3233
3234 const int strength_offset = compiler.stack_assign_if_linked(strength_in);
3235
3236 if (color_in->link || strength_in->link) {
3237 compiler.add_node(NODE_EMISSION_WEIGHT,
3238 compiler.stack_assign(color_in),
3239 strength_offset,
3240 __float_as_int(get_float(strength_in->socket_type)));
3241 }
3242 else {
3243 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
3244 }
3245
3246 compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
3247}
3248
3250{
3251 compiler.add(this, "node_background");
3252}
3253
3255{
3256 ShaderInput *color_in = input("Color");
3257 ShaderInput *strength_in = input("Strength");
3258
3259 if ((!color_in->link && color == zero_float3()) || (!strength_in->link && strength == 0.0f)) {
3260 folder.discard();
3261 }
3262}
3263
3264/* Holdout Closure */
3265
3267{
3268 NodeType *type = NodeType::add("holdout", create, NodeType::SHADER);
3269
3270 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3271 SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3272
3273 SOCKET_OUT_CLOSURE(holdout, "Holdout");
3274
3275 return type;
3276}
3277
3278HoldoutNode::HoldoutNode() : ShaderNode(get_node_type()) {}
3279
3280void HoldoutNode::compile(SVMCompiler &compiler)
3281{
3282 const float3 value = one_float3();
3283
3284 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value);
3285 compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
3286}
3287
3288void HoldoutNode::compile(OSLCompiler &compiler)
3289{
3290 compiler.add(this, "node_holdout");
3291}
3292
3293/* Ambient Occlusion */
3294
3296{
3297 NodeType *type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
3298
3299 SOCKET_INT(samples, "Samples", 16);
3300
3301 SOCKET_IN_COLOR(color, "Color", one_float3());
3302 SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
3304
3305 SOCKET_BOOLEAN(inside, "Inside", false);
3306 SOCKET_BOOLEAN(only_local, "Only Local", false);
3307
3308 SOCKET_OUT_COLOR(color, "Color");
3309 SOCKET_OUT_FLOAT(ao, "AO");
3310
3311 return type;
3312}
3313
3314AmbientOcclusionNode::AmbientOcclusionNode() : ShaderNode(get_node_type()) {}
3315
3317{
3318 ShaderInput *color_in = input("Color");
3319 ShaderInput *distance_in = input("Distance");
3320 ShaderInput *normal_in = input("Normal");
3321 ShaderOutput *color_out = output("Color");
3322 ShaderOutput *ao_out = output("AO");
3323
3324 int flags = (inside ? NODE_AO_INSIDE : 0) | (only_local ? NODE_AO_ONLY_LOCAL : 0);
3325
3326 if (!distance_in->link && distance == 0.0f) {
3327 flags |= NODE_AO_GLOBAL_RADIUS;
3328 }
3329
3330 compiler.add_node(NODE_AMBIENT_OCCLUSION,
3331 compiler.encode_uchar4(flags,
3332 compiler.stack_assign_if_linked(distance_in),
3333 compiler.stack_assign_if_linked(normal_in),
3334 compiler.stack_assign(ao_out)),
3335 compiler.encode_uchar4(compiler.stack_assign(color_in),
3336 compiler.stack_assign(color_out),
3337 samples),
3339}
3340
3342{
3343 compiler.parameter(this, "samples");
3344 compiler.parameter(this, "inside");
3345 compiler.parameter(this, "only_local");
3346 compiler.add(this, "node_ambient_occlusion");
3347}
3348
3349/* Volume Closure */
3350
3355
3357 ShaderInput *density,
3358 ShaderInput *param1,
3359 ShaderInput *param2)
3360{
3361 ShaderInput *color_in = input("Color");
3362
3363 if (color_in->link) {
3364 compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
3365 }
3366 else {
3367 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
3368 }
3369
3370 /* Density and mix weight need to be stored the same way for all volume closures since there's
3371 * a shortcut code path if we only need the extinction value. */
3372 const uint density_ofs = (density) ? compiler.stack_assign_if_linked(density) :
3374 const uint mix_weight_ofs = compiler.closure_mix_weight_offset();
3375
3376 if (param2 == nullptr) {
3377 /* More efficient packing if we don't need the second parameter. */
3378 const uint param1_ofs = (param1) ? compiler.stack_assign_if_linked(param1) : SVM_STACK_INVALID;
3379 compiler.add_node(NODE_CLOSURE_VOLUME,
3380 compiler.encode_uchar4(closure, density_ofs, param1_ofs, mix_weight_ofs),
3381 __float_as_int((density) ? get_float(density->socket_type) : 0.0f),
3382 __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f));
3383 }
3384 else {
3385 const uint param1_ofs = (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID;
3386 const uint param2_ofs = (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID;
3387 compiler.add_node(NODE_CLOSURE_VOLUME,
3388 compiler.encode_uchar4(closure, density_ofs, param1_ofs, mix_weight_ofs),
3389 __float_as_int((density) ? get_float(density->socket_type) : 0.0f),
3390 param2_ofs);
3391 }
3392}
3393
3394void VolumeNode::compile(SVMCompiler &compiler)
3395{
3396 compile(compiler, nullptr, nullptr, nullptr);
3397}
3398
3399void VolumeNode::compile(OSLCompiler & /*compiler*/)
3400{
3401 assert(0);
3402}
3403
3404/* Absorption Volume Closure */
3405
3407{
3408 NodeType *type = NodeType::add("absorption_volume", create, NodeType::SHADER);
3409
3410 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3411 SOCKET_IN_FLOAT(density, "Density", 1.0f);
3412 SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3413
3414 SOCKET_OUT_CLOSURE(volume, "Volume");
3415
3416 return type;
3417}
3418
3419AbsorptionVolumeNode::AbsorptionVolumeNode() : VolumeNode(get_node_type())
3420{
3422}
3423
3425{
3426 VolumeNode::compile(compiler, input("Density"));
3427}
3428
3430{
3431 compiler.add(this, "node_absorption_volume");
3432}
3433
3434/* Scatter Volume Closure */
3435
3437{
3438 NodeType *type = NodeType::add("scatter_volume", create, NodeType::SHADER);
3439
3440 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3441 SOCKET_IN_FLOAT(density, "Density", 1.0f);
3442 SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
3443 SOCKET_IN_FLOAT(IOR, "IOR", 1.33f);
3444 SOCKET_IN_FLOAT(backscatter, "Backscatter", 0.1f);
3445 SOCKET_IN_FLOAT(alpha, "Alpha", 0.5f);
3446 SOCKET_IN_FLOAT(diameter, "Diameter", 20.0f);
3447
3448 static NodeEnum phase_enum;
3449 phase_enum.insert("Henyey-Greenstein", CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
3450 phase_enum.insert("Fournier-Forand", CLOSURE_VOLUME_FOURNIER_FORAND_ID);
3451 phase_enum.insert("Draine", CLOSURE_VOLUME_DRAINE_ID);
3452 phase_enum.insert("Rayleigh", CLOSURE_VOLUME_RAYLEIGH_ID);
3453 phase_enum.insert("Mie", CLOSURE_VOLUME_MIE_ID);
3454 SOCKET_ENUM(phase, "Phase", phase_enum, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
3455
3456 SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3457
3458 SOCKET_OUT_CLOSURE(volume, "Volume");
3459
3460 return type;
3461}
3462
3467
3469{
3471}
3472
3474{
3475 closure = phase;
3476
3477 switch (phase) {
3479 VolumeNode::compile(compiler, input("Density"), input("Anisotropy"));
3480 break;
3482 VolumeNode::compile(compiler, input("Density"), input("IOR"), input("Backscatter"));
3483 break;
3485 VolumeNode::compile(compiler, input("Density"));
3486 break;
3488 VolumeNode::compile(compiler, input("Density"), input("Anisotropy"), input("Alpha"));
3489 break;
3491 VolumeNode::compile(compiler, input("Density"), input("Diameter"));
3492 break;
3493 default:
3494 assert(false);
3495 break;
3496 }
3497}
3498
3500{
3501 compiler.parameter(this, "phase");
3502 compiler.add(this, "node_scatter_volume");
3503}
3504
3505/* Volume Coefficients Closure */
3506
3508{
3509 NodeType *type = NodeType::add("volume_coefficients", create, NodeType::SHADER);
3510
3511 SOCKET_IN_VECTOR(scatter_coeffs, "Scatter Coefficients", make_float3(1.0f, 1.0f, 1.0f));
3512 SOCKET_IN_VECTOR(absorption_coeffs, "Absorption Coefficients", make_float3(1.0f, 1.0f, 1.0f));
3513 SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
3514 SOCKET_IN_FLOAT(IOR, "IOR", 1.33f);
3515 SOCKET_IN_FLOAT(backscatter, "Backscatter", 0.1f);
3516 SOCKET_IN_FLOAT(alpha, "Alpha", 0.5f);
3517 SOCKET_IN_FLOAT(diameter, "Diameter", 20.0f);
3518 SOCKET_IN_VECTOR(emission_coeffs, "Emission Coefficients", make_float3(0.0f, 0.0f, 0.0f));
3519
3520 static NodeEnum phase_enum;
3521 phase_enum.insert("Henyey-Greenstein", CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
3522 phase_enum.insert("Fournier-Forand", CLOSURE_VOLUME_FOURNIER_FORAND_ID);
3523 phase_enum.insert("Draine", CLOSURE_VOLUME_DRAINE_ID);
3524 phase_enum.insert("Rayleigh", CLOSURE_VOLUME_RAYLEIGH_ID);
3525 phase_enum.insert("Mie", CLOSURE_VOLUME_MIE_ID);
3526 SOCKET_ENUM(phase, "Phase", phase_enum, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
3527
3528 SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3529
3530 SOCKET_OUT_CLOSURE(volume, "Volume");
3531
3532 return type;
3533}
3534
3535VolumeCoefficientsNode::VolumeCoefficientsNode() : ScatterVolumeNode(get_node_type())
3536{
3538}
3539
3541{
3542 closure = phase;
3543 ShaderInput *param1 = nullptr;
3544 ShaderInput *param2 = nullptr;
3545
3546 switch (phase) {
3548 param1 = input("Anisotropy");
3549 break;
3551 param1 = input("IOR");
3552 param2 = input("Backscatter");
3553 break;
3555 break;
3557 param1 = input("Anisotropy");
3558 param2 = input("Alpha");
3559 break;
3561 param1 = input("Diameter");
3562 break;
3563 default:
3564 assert(false);
3565 break;
3566 }
3567 ShaderInput *coeffs_in = input("Scatter Coefficients");
3568 ShaderInput *absorption_coeffs_in = input("Absorption Coefficients");
3569 ShaderInput *emission_coeffs_in = input("Emission Coefficients");
3570
3571 if (coeffs_in->link) {
3572 compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(coeffs_in));
3573 }
3574 else {
3575 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, scatter_coeffs);
3576 }
3577
3578 const uint mix_weight_ofs = compiler.closure_mix_weight_offset();
3579
3580 if (param2 == nullptr) {
3581 /* More efficient packing if we don't need the second parameter. */
3582 const uint param1_ofs = (param1) ? compiler.stack_assign_if_linked(param1) : SVM_STACK_INVALID;
3583 compiler.add_node(NODE_VOLUME_COEFFICIENTS,
3584 compiler.encode_uchar4(closure, 0, param1_ofs, mix_weight_ofs),
3585 __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f),
3586 compiler.encode_uchar4(compiler.stack_assign(absorption_coeffs_in),
3587 compiler.stack_assign(emission_coeffs_in),
3588 0,
3589 0));
3590 }
3591 else {
3592 const uint param1_ofs = (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID;
3593 const uint param2_ofs = (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID;
3594 compiler.add_node(NODE_VOLUME_COEFFICIENTS,
3595 compiler.encode_uchar4(closure, 0, param1_ofs, mix_weight_ofs),
3596 param2_ofs,
3597 compiler.encode_uchar4(compiler.stack_assign(absorption_coeffs_in),
3598 compiler.stack_assign(emission_coeffs_in),
3599 0,
3600 0));
3601 }
3602}
3603
3605{
3606 compiler.parameter(this, "phase");
3607 compiler.add(this, "node_volume_coefficients");
3608}
3609
3610/* Principled Volume Closure */
3611
3613{
3614 NodeType *type = NodeType::add("principled_volume", create, NodeType::SHADER);
3615
3616 SOCKET_IN_STRING(density_attribute, "Density Attribute", ustring());
3617 SOCKET_IN_STRING(color_attribute, "Color Attribute", ustring());
3618 SOCKET_IN_STRING(temperature_attribute, "Temperature Attribute", ustring());
3619
3620 SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 0.5f));
3621 SOCKET_IN_FLOAT(density, "Density", 1.0f);
3622 SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
3623 SOCKET_IN_COLOR(absorption_color, "Absorption Color", zero_float3());
3624 SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
3625 SOCKET_IN_COLOR(emission_color, "Emission Color", one_float3());
3626 SOCKET_IN_FLOAT(blackbody_intensity, "Blackbody Intensity", 0.0f);
3627 SOCKET_IN_COLOR(blackbody_tint, "Blackbody Tint", one_float3());
3628 SOCKET_IN_FLOAT(temperature, "Temperature", 1000.0f);
3629 SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3630
3631 SOCKET_OUT_CLOSURE(volume, "Volume");
3632
3633 return type;
3634}
3635
3636PrincipledVolumeNode::PrincipledVolumeNode() : VolumeNode(get_node_type())
3637{
3639 density_attribute = ustring("density");
3640 temperature_attribute = ustring("temperature");
3641}
3642
3644{
3645 if (shader->has_volume) {
3646 ShaderInput *density_in = input("Density");
3647 ShaderInput *blackbody_in = input("Blackbody Intensity");
3648
3649 if (density_in->link || density > 0.0f) {
3650 attributes->add_standard(density_attribute);
3651 attributes->add_standard(color_attribute);
3652 }
3653
3654 if (blackbody_in->link || blackbody_intensity > 0.0f) {
3655 attributes->add_standard(temperature_attribute);
3656 }
3657
3659 }
3660
3662}
3663
3665{
3666 ShaderInput *color_in = input("Color");
3667 ShaderInput *density_in = input("Density");
3668 ShaderInput *anisotropy_in = input("Anisotropy");
3669 ShaderInput *absorption_color_in = input("Absorption Color");
3670 ShaderInput *emission_in = input("Emission Strength");
3671 ShaderInput *emission_color_in = input("Emission Color");
3672 ShaderInput *blackbody_in = input("Blackbody Intensity");
3673 ShaderInput *blackbody_tint_in = input("Blackbody Tint");
3674 ShaderInput *temperature_in = input("Temperature");
3675
3676 if (color_in->link) {
3677 compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
3678 }
3679 else {
3680 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
3681 }
3682
3683 compiler.add_node(NODE_PRINCIPLED_VOLUME,
3684 compiler.encode_uchar4(compiler.stack_assign_if_linked(density_in),
3685 compiler.stack_assign_if_linked(anisotropy_in),
3686 compiler.stack_assign(absorption_color_in),
3687 compiler.closure_mix_weight_offset()),
3688 compiler.encode_uchar4(compiler.stack_assign_if_linked(emission_in),
3689 compiler.stack_assign(emission_color_in),
3690 compiler.stack_assign_if_linked(blackbody_in),
3691 compiler.stack_assign(temperature_in)),
3692 compiler.stack_assign(blackbody_tint_in));
3693
3694 const int attr_density = compiler.attribute_standard(density_attribute);
3695 const int attr_color = compiler.attribute_standard(color_attribute);
3696 const int attr_temperature = compiler.attribute_standard(temperature_attribute);
3697
3698 compiler.add_node(__float_as_int(density),
3699 __float_as_int(anisotropy),
3700 __float_as_int(emission_strength),
3701 __float_as_int(blackbody_intensity));
3702
3703 compiler.add_node(attr_density, attr_color, attr_temperature);
3704}
3705
3707{
3708 if (Attribute::name_standard(density_attribute.c_str())) {
3709 density_attribute = ustring("geom:" + density_attribute.string());
3710 }
3711 if (Attribute::name_standard(color_attribute.c_str())) {
3712 color_attribute = ustring("geom:" + color_attribute.string());
3713 }
3714 if (Attribute::name_standard(temperature_attribute.c_str())) {
3715 temperature_attribute = ustring("geom:" + temperature_attribute.string());
3716 }
3717
3718 compiler.add(this, "node_principled_volume");
3719}
3720
3721/* Principled Hair BSDF Closure */
3722
3724{
3725 NodeType *type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
3726
3727 /* Scattering models. */
3728 static NodeEnum model_enum;
3729 model_enum.insert("Chiang", NODE_PRINCIPLED_HAIR_CHIANG);
3730 model_enum.insert("Huang", NODE_PRINCIPLED_HAIR_HUANG);
3731 SOCKET_ENUM(model, "Model", model_enum, NODE_PRINCIPLED_HAIR_HUANG);
3732
3733 /* Color parametrization specified as enum. */
3734 static NodeEnum parametrization_enum;
3735 parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
3736 parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
3737 parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
3739 parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
3740
3741 /* Initialize sockets to their default values. */
3742 SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
3743 SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
3744 SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
3745 SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
3747 absorption_coefficient, "Absorption Coefficient", make_float3(0.245531f, 0.52f, 1.365f));
3748
3749 SOCKET_IN_FLOAT(aspect_ratio, "Aspect Ratio", 0.85f);
3750
3751 SOCKET_IN_FLOAT(offset, "Offset", 2.f * M_PI_F / 180.f);
3752 SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
3753 SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
3754 SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
3755 SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
3756
3757 SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
3758 SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
3759 SOCKET_IN_FLOAT(random, "Random", 0.0f);
3760
3761 SOCKET_IN_FLOAT(R, "R lobe", 1.0f);
3762 SOCKET_IN_FLOAT(TT, "TT lobe", 1.0f);
3763 SOCKET_IN_FLOAT(TRT, "TRT lobe", 1.0f);
3764
3765 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3766
3767 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3768
3769 return type;
3770}
3771
3772PrincipledHairBsdfNode::PrincipledHairBsdfNode() : BsdfBaseNode(get_node_type())
3773{
3775}
3776
3777/* Treat hair as transparent if the hit is outside of the projected width. */
3779{
3780 if (model == NODE_PRINCIPLED_HAIR_HUANG) {
3781 if (aspect_ratio != 1.0f || input("Aspect Ratio")->link) {
3782 return true;
3783 }
3784 }
3785 return false;
3786}
3787
3789{
3791 /* Make sure we have the normal for elliptical cross section tracking. */
3793 }
3794
3795 if (!input("Random")->link) {
3796 /* Enable retrieving Hair Info -> Random if Random isn't linked. */
3798 }
3800}
3801
3802/* Prepares the input data for the SVM shader. */
3804{
3807
3808 compiler.add_node(NODE_CLOSURE_SET_WEIGHT, one_float3());
3809
3810 ShaderInput *roughness_in = input("Roughness");
3811 ShaderInput *radial_roughness_in = input("Radial Roughness");
3812 ShaderInput *random_roughness_in = input("Random Roughness");
3813 ShaderInput *offset_in = input("Offset");
3814 ShaderInput *coat_in = input("Coat");
3815 ShaderInput *ior_in = input("IOR");
3816
3817 ShaderInput *melanin_in = input("Melanin");
3818 ShaderInput *melanin_redness_in = input("Melanin Redness");
3819 ShaderInput *random_color_in = input("Random Color");
3820
3821 ShaderInput *R_in = input("R lobe");
3822 ShaderInput *TT_in = input("TT lobe");
3823 ShaderInput *TRT_in = input("TRT lobe");
3824
3825 ShaderInput *aspect_ratio_in = input("Aspect Ratio");
3826
3827 const int color_ofs = compiler.stack_assign(input("Color"));
3828 const int tint_ofs = compiler.stack_assign(input("Tint"));
3829 const int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
3830
3831 const int roughness_ofs = compiler.stack_assign_if_linked(roughness_in);
3832 const int radial_roughness_ofs = compiler.stack_assign_if_linked(radial_roughness_in);
3833
3834 const int offset_ofs = compiler.stack_assign_if_linked(offset_in);
3835 const int ior_ofs = compiler.stack_assign_if_linked(ior_in);
3836
3837 const int coat_ofs = compiler.stack_assign_if_linked(coat_in);
3838 const int melanin_ofs = compiler.stack_assign_if_linked(melanin_in);
3839 const int melanin_redness_ofs = compiler.stack_assign_if_linked(melanin_redness_in);
3840
3841 ShaderInput *random_in = input("Random");
3842 const int attr_random = random_in->link ? SVM_STACK_INVALID :
3844 const int random_in_ofs = compiler.stack_assign_if_linked(random_in);
3845 const int random_color_ofs = compiler.stack_assign_if_linked(random_color_in);
3846 const int random_roughness_ofs = compiler.stack_assign_if_linked(random_roughness_in);
3847
3848 /* Encode all parameters into data nodes. */
3849 /* node */
3850 compiler.add_node(
3851 NODE_CLOSURE_BSDF,
3852 /* Socket IDs can be packed 4 at a time into a single data packet */
3853 compiler.encode_uchar4(
3854 closure, roughness_ofs, random_roughness_ofs, compiler.closure_mix_weight_offset()),
3855 /* The rest are stored as unsigned integers */
3856 __float_as_uint(roughness),
3857 __float_as_uint(random_roughness));
3858
3859 /* data node */
3860 compiler.add_node(SVM_STACK_INVALID,
3861 compiler.encode_uchar4(offset_ofs, ior_ofs, color_ofs, parametrization),
3862 __float_as_uint(offset),
3863 __float_as_uint(ior));
3864
3865 /* data node 2 */
3866 compiler.add_node(compiler.encode_uchar4(
3867 tint_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs),
3868 attr_random,
3869 __float_as_uint(melanin),
3870 __float_as_uint(melanin_redness));
3871
3872 /* data node 3 */
3873 if (model == NODE_PRINCIPLED_HAIR_HUANG) {
3874 compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(aspect_ratio_in),
3875 random_in_ofs,
3876 random_color_ofs,
3879 __float_as_uint(random_color),
3880 __float_as_uint(aspect_ratio));
3881 }
3882 else {
3883 compiler.add_node(
3884 compiler.encode_uchar4(coat_ofs, random_in_ofs, random_color_ofs, radial_roughness_ofs),
3886 __float_as_uint(random_color),
3887 __float_as_uint(coat));
3888 }
3889
3890 /* data node 4 */
3891 compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(R_in),
3892 compiler.stack_assign_if_linked(TT_in),
3893 compiler.stack_assign_if_linked(TRT_in),
3895 __float_as_uint(model == NODE_PRINCIPLED_HAIR_HUANG ? R : radial_roughness),
3896 __float_as_uint(TT),
3897 __float_as_uint(TRT));
3898}
3899
3900/* Prepares the input data for the OSL shader. */
3902{
3903 compiler.parameter(this, "model");
3904 compiler.parameter(this, "parametrization");
3905 compiler.add(this, "node_principled_hair_bsdf");
3906}
3907
3908/* Hair BSDF Closure */
3909
3911{
3912 NodeType *type = NodeType::add("hair_bsdf", create, NodeType::SHADER);
3913
3914 SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3915 SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3916
3917 static NodeEnum component_enum;
3918 component_enum.insert("reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
3919 component_enum.insert("transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
3920 SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_HAIR_REFLECTION_ID);
3921 SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
3922 SOCKET_IN_FLOAT(roughness_u, "RoughnessU", 0.2f);
3923 SOCKET_IN_FLOAT(roughness_v, "RoughnessV", 0.2f);
3924 SOCKET_IN_VECTOR(tangent, "Tangent", zero_float3());
3925
3926 SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3927
3928 return type;
3929}
3930
3931HairBsdfNode::HairBsdfNode() : BsdfNode(get_node_type())
3932{
3934}
3935
3936void HairBsdfNode::compile(SVMCompiler &compiler)
3937{
3938 closure = component;
3939
3940 ShaderInput *tangent = input("Tangent");
3941 tangent = compiler.is_linked(tangent) ? tangent : nullptr;
3942
3944 compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"), nullptr, tangent);
3945}
3946
3947void HairBsdfNode::compile(OSLCompiler &compiler)
3948{
3949 compiler.parameter(this, "component");
3950 compiler.add(this, "node_hair_bsdf");
3951}
3952
3953/* Geometry */
3954
3956{
3957 NodeType *type = NodeType::add("geometry", create, NodeType::SHADER);
3958
3959 SOCKET_OUT_POINT(position, "Position");
3960 SOCKET_OUT_NORMAL(normal, "Normal");
3961 SOCKET_OUT_NORMAL(tangent, "Tangent");
3962 SOCKET_OUT_NORMAL(true_normal, "True Normal");
3963 SOCKET_OUT_VECTOR(incoming, "Incoming");
3964 SOCKET_OUT_POINT(parametric, "Parametric");
3965 SOCKET_OUT_FLOAT(backfacing, "Backfacing");
3966 SOCKET_OUT_FLOAT(pointiness, "Pointiness");
3967 SOCKET_OUT_FLOAT(random_per_island, "Random Per Island");
3968
3969 return type;
3970}
3971
3972GeometryNode::GeometryNode() : ShaderNode(get_node_type())
3973{
3974 special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
3975}
3976
3978{
3979 if (shader->has_surface_link()) {
3980 if (!output("Tangent")->links.empty()) {
3982 }
3983 if (!output("Pointiness")->links.empty()) {
3985 }
3986 if (!output("Random Per Island")->links.empty()) {
3988 }
3989 }
3990
3992}
3993
3994void GeometryNode::compile(SVMCompiler &compiler)
3995{
3997 ShaderNodeType geom_node = NODE_GEOMETRY;
3998 ShaderNodeType attr_node = NODE_ATTR;
3999
4000 if (bump == SHADER_BUMP_DX) {
4001 geom_node = NODE_GEOMETRY_BUMP_DX;
4002 attr_node = NODE_ATTR_BUMP_DX;
4003 }
4004 else if (bump == SHADER_BUMP_DY) {
4005 geom_node = NODE_GEOMETRY_BUMP_DY;
4006 attr_node = NODE_ATTR_BUMP_DY;
4007 }
4008
4009 out = output("Position");
4010 if (!out->links.empty()) {
4011 compiler.add_node(
4013 }
4014
4015 out = output("Normal");
4016 if (!out->links.empty()) {
4017 compiler.add_node(
4019 }
4020
4021 out = output("Tangent");
4022 if (!out->links.empty()) {
4023 compiler.add_node(
4025 }
4026
4027 out = output("True Normal");
4028 if (!out->links.empty()) {
4029 compiler.add_node(
4031 }
4032
4033 out = output("Incoming");
4034 if (!out->links.empty()) {
4035 compiler.add_node(
4037 }
4038
4039 out = output("Parametric");
4040 if (!out->links.empty()) {
4041 compiler.add_node(
4043 }
4044
4045 out = output("Backfacing");
4046 if (!out->links.empty()) {
4047 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_backfacing, compiler.stack_assign(out));
4048 }
4049
4050 out = output("Pointiness");
4051 if (!out->links.empty()) {
4052 if (compiler.output_type() != SHADER_TYPE_VOLUME) {
4053 compiler.add_node(attr_node,
4057 }
4058 else {
4059 compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
4060 }
4061 }
4062
4063 out = output("Random Per Island");
4064 if (!out->links.empty()) {
4065 if (compiler.output_type() != SHADER_TYPE_VOLUME) {
4066 compiler.add_node(attr_node,
4070 }
4071 else {
4072 compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
4073 }
4074 }
4075}
4076
4077void GeometryNode::compile(OSLCompiler &compiler)
4078{
4079 if (bump == SHADER_BUMP_DX) {
4080 compiler.parameter("bump_offset", "dx");
4081 }
4082 else if (bump == SHADER_BUMP_DY) {
4083 compiler.parameter("bump_offset", "dy");
4084 }
4085 else {
4086 compiler.parameter("bump_offset", "center");
4087 }
4088 compiler.parameter("bump_filter_width", bump_filter_width);
4089
4090 compiler.add(this, "node_geometry");
4091}
4092
4093/* TextureCoordinate */
4094
4096{
4097 NodeType *type = NodeType::add("texture_coordinate", create, NodeType::SHADER);
4098
4099 SOCKET_BOOLEAN(from_dupli, "From Dupli", false);
4100 SOCKET_BOOLEAN(use_transform, "Use Transform", false);
4101 SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity());
4102
4103 SOCKET_OUT_POINT(generated, "Generated");
4104 SOCKET_OUT_NORMAL(normal, "Normal");
4105 SOCKET_OUT_POINT(UV, "UV");
4106 SOCKET_OUT_POINT(object, "Object");
4107 SOCKET_OUT_POINT(camera, "Camera");
4108 SOCKET_OUT_POINT(window, "Window");
4109 SOCKET_OUT_NORMAL(reflection, "Reflection");
4110
4111 return type;
4112}
4113
4114TextureCoordinateNode::TextureCoordinateNode() : ShaderNode(get_node_type()) {}
4115
4117{
4118 if (shader->has_surface_link()) {
4119 if (!from_dupli) {
4120 if (!output("Generated")->links.empty()) {
4122 }
4123 if (!output("UV")->links.empty()) {
4124 attributes->add(ATTR_STD_UV);
4125 }
4126 }
4127 }
4128
4129 if (shader->has_volume) {
4130 if (!from_dupli) {
4131 if (!output("Generated")->links.empty()) {
4133 }
4134 }
4135 }
4136
4138}
4139
4141{
4143 ShaderNodeType texco_node = NODE_TEX_COORD;
4144 ShaderNodeType attr_node = NODE_ATTR;
4145 ShaderNodeType geom_node = NODE_GEOMETRY;
4146
4147 if (bump == SHADER_BUMP_DX) {
4148 texco_node = NODE_TEX_COORD_BUMP_DX;
4149 attr_node = NODE_ATTR_BUMP_DX;
4150 geom_node = NODE_GEOMETRY_BUMP_DX;
4151 }
4152 else if (bump == SHADER_BUMP_DY) {
4153 texco_node = NODE_TEX_COORD_BUMP_DY;
4154 attr_node = NODE_ATTR_BUMP_DY;
4155 geom_node = NODE_GEOMETRY_BUMP_DY;
4156 }
4157
4158 out = output("Generated");
4159 if (!out->links.empty()) {
4160 if (compiler.background) {
4161 compiler.add_node(
4163 }
4164 else {
4165 if (from_dupli) {
4166 compiler.add_node(texco_node,
4168 compiler.stack_assign(out),
4170 }
4171 else if (compiler.output_type() == SHADER_TYPE_VOLUME) {
4172 compiler.add_node(texco_node,
4174 compiler.stack_assign(out),
4176 }
4177 else {
4178 const int attr = compiler.attribute(ATTR_STD_GENERATED);
4179 compiler.add_node(
4180 attr_node,
4181 attr,
4184 }
4185 }
4186 }
4187
4188 out = output("Normal");
4189 if (!out->links.empty()) {
4190 compiler.add_node(texco_node,
4192 compiler.stack_assign(out),
4194 }
4195
4196 out = output("UV");
4197 if (!out->links.empty()) {
4198 if (from_dupli) {
4199 compiler.add_node(texco_node,
4201 compiler.stack_assign(out),
4203 }
4204 else {
4205 const int attr = compiler.attribute(ATTR_STD_UV);
4206 compiler.add_node(
4207 attr_node,
4208 attr,
4211 }
4212 }
4213
4214 out = output("Object");
4215 if (!out->links.empty()) {
4216 compiler.add_node(texco_node,
4218 compiler.stack_assign(out),
4220 if (use_transform) {
4221 const Transform ob_itfm = transform_inverse(ob_tfm);
4222 compiler.add_node(ob_itfm.x);
4223 compiler.add_node(ob_itfm.y);
4224 compiler.add_node(ob_itfm.z);
4225 }
4226 }
4227
4228 out = output("Camera");
4229 if (!out->links.empty()) {
4230 compiler.add_node(texco_node,
4232 compiler.stack_assign(out),
4234 }
4235
4236 out = output("Window");
4237 if (!out->links.empty()) {
4238 compiler.add_node(texco_node,
4240 compiler.stack_assign(out),
4242 }
4243
4244 out = output("Reflection");
4245 if (!out->links.empty()) {
4246 if (compiler.background) {
4247 compiler.add_node(
4249 }
4250 else {
4251 compiler.add_node(texco_node,
4253 compiler.stack_assign(out),
4255 }
4256 }
4257}
4258
4260{
4261 if (bump == SHADER_BUMP_DX) {
4262 compiler.parameter("bump_offset", "dx");
4263 }
4264 else if (bump == SHADER_BUMP_DY) {
4265 compiler.parameter("bump_offset", "dy");
4266 }
4267 else {
4268 compiler.parameter("bump_offset", "center");
4269 }
4270 compiler.parameter("bump_filter_width", bump_filter_width);
4271
4272 if (compiler.background) {
4273 compiler.parameter("is_background", true);
4274 }
4275 if (compiler.output_type() == SHADER_TYPE_VOLUME) {
4276 compiler.parameter("is_volume", true);
4277 }
4278 compiler.parameter(this, "use_transform");
4279 const Transform ob_itfm = transform_inverse(ob_tfm);
4280 compiler.parameter("object_itfm", ob_itfm);
4281
4282 compiler.parameter(this, "from_dupli");
4283
4284 compiler.add(this, "node_texture_coordinate");
4285}
4286
4287/* UV Map */
4288
4290{
4291 NodeType *type = NodeType::add("uvmap", create, NodeType::SHADER);
4292
4293 SOCKET_STRING(attribute, "attribute", ustring());
4294 SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
4295
4296 SOCKET_OUT_POINT(UV, "UV");
4297
4298 return type;
4299}
4300
4301UVMapNode::UVMapNode() : ShaderNode(get_node_type()) {}
4302
4304{
4305 if (shader->has_surface) {
4306 if (!from_dupli) {
4307 if (!output("UV")->links.empty()) {
4308 if (!attribute.empty()) {
4309 attributes->add(attribute);
4310 }
4311 else {
4312 attributes->add(ATTR_STD_UV);
4313 }
4314 }
4315 }
4316 }
4317
4319}
4320
4321void UVMapNode::compile(SVMCompiler &compiler)
4322{
4323 ShaderOutput *out = output("UV");
4324 ShaderNodeType texco_node = NODE_TEX_COORD;
4325 ShaderNodeType attr_node = NODE_ATTR;
4326 int attr;
4327
4328 if (bump == SHADER_BUMP_DX) {
4329 texco_node = NODE_TEX_COORD_BUMP_DX;
4330 attr_node = NODE_ATTR_BUMP_DX;
4331 }
4332 else if (bump == SHADER_BUMP_DY) {
4333 texco_node = NODE_TEX_COORD_BUMP_DY;
4334 attr_node = NODE_ATTR_BUMP_DY;
4335 }
4336
4337 if (!out->links.empty()) {
4338 if (from_dupli) {
4339 compiler.add_node(texco_node,
4341 compiler.stack_assign(out),
4343 }
4344 else {
4345 if (!attribute.empty()) {
4346 attr = compiler.attribute(attribute);
4347 }
4348 else {
4349 attr = compiler.attribute(ATTR_STD_UV);
4350 }
4351
4352 compiler.add_node(
4353 attr_node,
4354 attr,
4357 }
4358 }
4359}
4360
4361void UVMapNode::compile(OSLCompiler &compiler)
4362{
4363 if (bump == SHADER_BUMP_DX) {
4364 compiler.parameter("bump_offset", "dx");
4365 }
4366 else if (bump == SHADER_BUMP_DY) {
4367 compiler.parameter("bump_offset", "dy");
4368 }
4369 else {
4370 compiler.parameter("bump_offset", "center");
4371 }
4372 compiler.parameter("bump_filter_width", bump_filter_width);
4373
4374 compiler.parameter(this, "from_dupli");
4375 compiler.parameter(this, "attribute");
4376 compiler.add(this, "node_uv_map");
4377}
4378
4379/* Light Path */
4380
4382{
4383 NodeType *type = NodeType::add("light_path", create, NodeType::SHADER);
4384
4385 SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray");
4386 SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray");
4387 SOCKET_OUT_FLOAT(is_diffuse_ray, "Is Diffuse Ray");
4388 SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray");
4389 SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray");
4390 SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray");
4391 SOCKET_OUT_FLOAT(is_transmission_ray, "Is Transmission Ray");
4392 SOCKET_OUT_FLOAT(is_volume_scatter_ray, "Is Volume Scatter Ray");
4393 SOCKET_OUT_FLOAT(ray_length, "Ray Length");
4394 SOCKET_OUT_FLOAT(ray_depth, "Ray Depth");
4395 SOCKET_OUT_FLOAT(diffuse_depth, "Diffuse Depth");
4396 SOCKET_OUT_FLOAT(glossy_depth, "Glossy Depth");
4397 SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth");
4398 SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth");
4399 SOCKET_OUT_FLOAT(portal_depth, "Portal Depth");
4400
4401 return type;
4402}
4403
4404LightPathNode::LightPathNode() : ShaderNode(get_node_type())
4405{
4406 special_type = SHADER_SPECIAL_TYPE_LIGHT_PATH;
4407}
4408
4409void LightPathNode::compile(SVMCompiler &compiler)
4410{
4411 ShaderOutput *out;
4412
4413 out = output("Is Camera Ray");
4414 if (!out->links.empty()) {
4415 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_camera, compiler.stack_assign(out));
4416 }
4417
4418 out = output("Is Shadow Ray");
4419 if (!out->links.empty()) {
4420 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_shadow, compiler.stack_assign(out));
4421 }
4422
4423 out = output("Is Diffuse Ray");
4424 if (!out->links.empty()) {
4425 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_diffuse, compiler.stack_assign(out));
4426 }
4427
4428 out = output("Is Glossy Ray");
4429 if (!out->links.empty()) {
4430 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_glossy, compiler.stack_assign(out));
4431 }
4432
4433 out = output("Is Singular Ray");
4434 if (!out->links.empty()) {
4435 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_singular, compiler.stack_assign(out));
4436 }
4437
4438 out = output("Is Reflection Ray");
4439 if (!out->links.empty()) {
4440 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, compiler.stack_assign(out));
4441 }
4442
4443 out = output("Is Transmission Ray");
4444 if (!out->links.empty()) {
4445 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, compiler.stack_assign(out));
4446 }
4447
4448 out = output("Is Volume Scatter Ray");
4449 if (!out->links.empty()) {
4450 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_volume_scatter, compiler.stack_assign(out));
4451 }
4452
4453 out = output("Ray Length");
4454 if (!out->links.empty()) {
4455 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, compiler.stack_assign(out));
4456 }
4457
4458 out = output("Ray Depth");
4459 if (!out->links.empty()) {
4460 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, compiler.stack_assign(out));
4461 }
4462
4463 out = output("Diffuse Depth");
4464 if (!out->links.empty()) {
4465 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_diffuse, compiler.stack_assign(out));
4466 }
4467
4468 out = output("Glossy Depth");
4469 if (!out->links.empty()) {
4470 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_glossy, compiler.stack_assign(out));
4471 }
4472
4473 out = output("Transparent Depth");
4474 if (!out->links.empty()) {
4475 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transparent, compiler.stack_assign(out));
4476 }
4477
4478 out = output("Transmission Depth");
4479 if (!out->links.empty()) {
4480 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transmission, compiler.stack_assign(out));
4481 }
4482
4483 out = output("Portal Depth");
4484 if (!out->links.empty()) {
4485 compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_portal, compiler.stack_assign(out));
4486 }
4487}
4488
4489void LightPathNode::compile(OSLCompiler &compiler)
4490{
4491 compiler.add(this, "node_light_path");
4492}
4493
4494/* Light Falloff */
4495
4497{
4498 NodeType *type = NodeType::add("light_falloff", create, NodeType::SHADER);
4499
4500 SOCKET_IN_FLOAT(strength, "Strength", 100.0f);
4501 SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
4502
4503 SOCKET_OUT_FLOAT(quadratic, "Quadratic");
4504 SOCKET_OUT_FLOAT(linear, "Linear");
4505 SOCKET_OUT_FLOAT(constant, "Constant");
4506
4507 return type;
4508}
4509
4510LightFalloffNode::LightFalloffNode() : ShaderNode(get_node_type()) {}
4511
4513{
4514 ShaderInput *strength_in = input("Strength");
4515 ShaderInput *smooth_in = input("Smooth");
4516
4517 ShaderOutput *out = output("Quadratic");
4518 if (!out->links.empty()) {
4519 compiler.add_node(NODE_LIGHT_FALLOFF,
4521 compiler.encode_uchar4(compiler.stack_assign(strength_in),
4522 compiler.stack_assign(smooth_in),
4523 compiler.stack_assign(out)));
4524 }
4525
4526 out = output("Linear");
4527 if (!out->links.empty()) {
4528 compiler.add_node(NODE_LIGHT_FALLOFF,
4530 compiler.encode_uchar4(compiler.stack_assign(strength_in),
4531 compiler.stack_assign(smooth_in),
4532 compiler.stack_assign(out)));
4533 }
4534
4535 out = output("Constant");
4536 if (!out->links.empty()) {
4537 compiler.add_node(NODE_LIGHT_FALLOFF,
4539 compiler.encode_uchar4(compiler.stack_assign(strength_in),
4540 compiler.stack_assign(smooth_in),
4541 compiler.stack_assign(out)));
4542 }
4543}
4544
4546{
4547 compiler.add(this, "node_light_falloff");
4548}
4549
4550/* Object Info */
4551
4553{
4554 NodeType *type = NodeType::add("object_info", create, NodeType::SHADER);
4555
4556 SOCKET_OUT_VECTOR(location, "Location");
4557 SOCKET_OUT_COLOR(color, "Color");
4558 SOCKET_OUT_FLOAT(alpha, "Alpha");
4559 SOCKET_OUT_FLOAT(object_index, "Object Index");
4560 SOCKET_OUT_FLOAT(material_index, "Material Index");
4561 SOCKET_OUT_FLOAT(random, "Random");
4562
4563 return type;
4564}
4565
4566ObjectInfoNode::ObjectInfoNode() : ShaderNode(get_node_type()) {}
4567
4569{
4570 ShaderOutput *out = output("Location");
4571 if (!out->links.empty()) {
4572 compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_LOCATION, compiler.stack_assign(out));
4573 }
4574
4575 out = output("Color");
4576 if (!out->links.empty()) {
4577 compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_COLOR, compiler.stack_assign(out));
4578 }
4579
4580 out = output("Alpha");
4581 if (!out->links.empty()) {
4582 compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_ALPHA, compiler.stack_assign(out));
4583 }
4584
4585 out = output("Object Index");
4586 if (!out->links.empty()) {
4587 compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out));
4588 }
4589
4590 out = output("Material Index");
4591 if (!out->links.empty()) {
4592 compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_MAT_INDEX, compiler.stack_assign(out));
4593 }
4594
4595 out = output("Random");
4596 if (!out->links.empty()) {
4597 compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_RANDOM, compiler.stack_assign(out));
4598 }
4599}
4600
4602{
4603 compiler.add(this, "node_object_info");
4604}
4605
4606/* Particle Info */
4607
4609{
4610 NodeType *type = NodeType::add("particle_info", create, NodeType::SHADER);
4611
4612 SOCKET_OUT_FLOAT(index, "Index");
4613 SOCKET_OUT_FLOAT(random, "Random");
4614 SOCKET_OUT_FLOAT(age, "Age");
4615 SOCKET_OUT_FLOAT(lifetime, "Lifetime");
4616 SOCKET_OUT_POINT(location, "Location");
4617#if 0 /* not yet supported */
4618 SOCKET_OUT_QUATERNION(rotation, "Rotation");
4619#endif
4620 SOCKET_OUT_FLOAT(size, "Size");
4621 SOCKET_OUT_VECTOR(velocity, "Velocity");
4622 SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity");
4623
4624 return type;
4625}
4626
4627ParticleInfoNode::ParticleInfoNode() : ShaderNode(get_node_type()) {}
4628
4630{
4631 if (!output("Index")->links.empty()) {
4633 }
4634 if (!output("Random")->links.empty()) {
4636 }
4637 if (!output("Age")->links.empty()) {
4639 }
4640 if (!output("Lifetime")->links.empty()) {
4642 }
4643 if (!output("Location")->links.empty()) {
4645 }
4646#if 0 /* not yet supported */
4647 if (!output("Rotation")->links.empty()) {
4649 }
4650#endif
4651 if (!output("Size")->links.empty()) {
4653 }
4654 if (!output("Velocity")->links.empty()) {
4656 }
4657 if (!output("Angular Velocity")->links.empty()) {
4659 }
4660
4662}
4663
4665{
4667
4668 out = output("Index");
4669 if (!out->links.empty()) {
4670 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
4671 }
4672
4673 out = output("Random");
4674 if (!out->links.empty()) {
4675 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
4676 }
4677
4678 out = output("Age");
4679 if (!out->links.empty()) {
4680 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, compiler.stack_assign(out));
4681 }
4682
4683 out = output("Lifetime");
4684 if (!out->links.empty()) {
4685 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, compiler.stack_assign(out));
4686 }
4687
4688 out = output("Location");
4689 if (!out->links.empty()) {
4690 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, compiler.stack_assign(out));
4691 }
4692
4693 /* quaternion data is not yet supported by Cycles */
4694#if 0
4695 out = output("Rotation");
4696 if (!out->links.empty()) {
4697 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, compiler.stack_assign(out));
4698 }
4699#endif
4700
4701 out = output("Size");
4702 if (!out->links.empty()) {
4703 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, compiler.stack_assign(out));
4704 }
4705
4706 out = output("Velocity");
4707 if (!out->links.empty()) {
4708 compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, compiler.stack_assign(out));
4709 }
4710
4711 out = output("Angular Velocity");
4712 if (!out->links.empty()) {
4713 compiler.add_node(
4714 NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, compiler.stack_assign(out));
4715 }
4716}
4717
4719{
4720 compiler.add(this, "node_particle_info");
4721}
4722
4723/* Hair Info */
4724
4726{
4727 NodeType *type = NodeType::add("hair_info", create, NodeType::SHADER);
4728
4729 SOCKET_OUT_FLOAT(is_strand, "Is Strand");
4730 SOCKET_OUT_FLOAT(intercept, "Intercept");
4731 SOCKET_OUT_FLOAT(size, "Length");
4732 SOCKET_OUT_FLOAT(thickness, "Thickness");
4733 SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal");
4734 SOCKET_OUT_FLOAT(index, "Random");
4735
4736 return type;
4737}
4738
4739HairInfoNode::HairInfoNode() : ShaderNode(get_node_type()) {}
4740
4742{
4743 if (shader->has_surface_link()) {
4744 ShaderOutput *intercept_out = output("Intercept");
4745
4746 if (!intercept_out->links.empty()) {
4748 }
4749
4750 if (!output("Length")->links.empty()) {
4752 }
4753
4754 if (!output("Random")->links.empty()) {
4756 }
4757 }
4758
4760}
4761
4762void HairInfoNode::compile(SVMCompiler &compiler)
4763{
4765
4766 out = output("Is Strand");
4767 if (!out->links.empty()) {
4768 compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, compiler.stack_assign(out));
4769 }
4770
4771 out = output("Intercept");
4772 if (!out->links.empty()) {
4773 const int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
4774 compiler.add_node(NODE_ATTR,
4775 attr,
4777 __float_as_uint(0.0f));
4778 }
4779
4780 out = output("Length");
4781 if (!out->links.empty()) {
4782 const int attr = compiler.attribute(ATTR_STD_CURVE_LENGTH);
4783 compiler.add_node(NODE_ATTR,
4784 attr,
4786 __float_as_uint(0.0f));
4787 }
4788
4789 out = output("Thickness");
4790 if (!out->links.empty()) {
4791 compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, compiler.stack_assign(out));
4792 }
4793
4794 out = output("Tangent Normal");
4795 if (!out->links.empty()) {
4796 compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
4797 }
4798
4799 out = output("Random");
4800 if (!out->links.empty()) {
4801 const int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
4802 compiler.add_node(NODE_ATTR,
4803 attr,
4805 __float_as_uint(0.0f));
4806 }
4807}
4808
4809void HairInfoNode::compile(OSLCompiler &compiler)
4810{
4811 compiler.add(this, "node_hair_info");
4812}
4813
4814/* Point Info */
4815
4817{
4818 NodeType *type = NodeType::add("point_info", create, NodeType::SHADER);
4819
4820 SOCKET_OUT_POINT(position, "Position");
4821 SOCKET_OUT_FLOAT(radius, "Radius");
4822 SOCKET_OUT_FLOAT(random, "Random");
4823
4824 return type;
4825}
4826
4827PointInfoNode::PointInfoNode() : ShaderNode(get_node_type()) {}
4828
4830{
4831 if (shader->has_surface_link()) {
4832 if (!output("Random")->links.empty()) {
4834 }
4835 }
4836
4838}
4839
4840void PointInfoNode::compile(SVMCompiler &compiler)
4841{
4843
4844 out = output("Position");
4845 if (!out->links.empty()) {
4846 compiler.add_node(NODE_POINT_INFO, NODE_INFO_POINT_POSITION, compiler.stack_assign(out));
4847 }
4848
4849 out = output("Radius");
4850 if (!out->links.empty()) {
4851 compiler.add_node(NODE_POINT_INFO, NODE_INFO_POINT_RADIUS, compiler.stack_assign(out));
4852 }
4853
4854 out = output("Random");
4855 if (!out->links.empty()) {
4856 const int attr = compiler.attribute(ATTR_STD_POINT_RANDOM);
4857 compiler.add_node(NODE_ATTR,
4858 attr,
4860 __float_as_uint(0.0f));
4861 }
4862}
4863
4864void PointInfoNode::compile(OSLCompiler &compiler)
4865{
4866 compiler.add(this, "node_point_info");
4867}
4868
4869/* Volume Info */
4870
4872{
4873 NodeType *type = NodeType::add("volume_info", create, NodeType::SHADER);
4874
4875 SOCKET_OUT_COLOR(color, "Color");
4876 SOCKET_OUT_FLOAT(density, "Density");
4877 SOCKET_OUT_FLOAT(flame, "Flame");
4878 SOCKET_OUT_FLOAT(temperature, "Temperature");
4879
4880 return type;
4881}
4882
4883VolumeInfoNode::VolumeInfoNode() : ShaderNode(get_node_type()) {}
4884
4885/* The requested attributes are not updated after node expansion.
4886 * So we explicitly request the required attributes.
4887 */
4889{
4890 if (shader->has_volume) {
4891 if (!output("Color")->links.empty()) {
4893 }
4894 if (!output("Density")->links.empty()) {
4896 }
4897 if (!output("Flame")->links.empty()) {
4899 }
4900 if (!output("Temperature")->links.empty()) {
4902 }
4904 }
4906}
4907
4909{
4910 ShaderOutput *color_out = output("Color");
4911 if (!color_out->links.empty()) {
4912 AttributeNode *attr = graph->create_node<AttributeNode>();
4913 attr->set_attribute(ustring("color"));
4914 graph->relink(color_out, attr->output("Color"));
4915 }
4916
4917 ShaderOutput *density_out = output("Density");
4918 if (!density_out->links.empty()) {
4919 AttributeNode *attr = graph->create_node<AttributeNode>();
4920 attr->set_attribute(ustring("density"));
4921 graph->relink(density_out, attr->output("Fac"));
4922 }
4923
4924 ShaderOutput *flame_out = output("Flame");
4925 if (!flame_out->links.empty()) {
4926 AttributeNode *attr = graph->create_node<AttributeNode>();
4927 attr->set_attribute(ustring("flame"));
4928 graph->relink(flame_out, attr->output("Fac"));
4929 }
4930
4931 ShaderOutput *temperature_out = output("Temperature");
4932 if (!temperature_out->links.empty()) {
4933 AttributeNode *attr = graph->create_node<AttributeNode>();
4934 attr->set_attribute(ustring("temperature"));
4935 graph->relink(temperature_out, attr->output("Fac"));
4936 }
4937}
4938
4939void VolumeInfoNode::compile(SVMCompiler & /*compiler*/) {}
4940
4941void VolumeInfoNode::compile(OSLCompiler & /*compiler*/) {}
4942
4944{
4945 NodeType *type = NodeType::add("vertex_color", create, NodeType::SHADER);
4946
4947 SOCKET_STRING(layer_name, "Layer Name", ustring());
4948 SOCKET_OUT_COLOR(color, "Color");
4949 SOCKET_OUT_FLOAT(alpha, "Alpha");
4950
4951 return type;
4952}
4953
4954VertexColorNode::VertexColorNode() : ShaderNode(get_node_type()) {}
4955
4957{
4958 if (!(output("Color")->links.empty() && output("Alpha")->links.empty())) {
4959 if (!layer_name.empty()) {
4960 attributes->add_standard(layer_name);
4961 }
4962 else {
4964 }
4965 }
4967}
4968
4970{
4971 ShaderOutput *color_out = output("Color");
4972 ShaderOutput *alpha_out = output("Alpha");
4973 int layer_id = 0;
4974
4975 if (!layer_name.empty()) {
4976 layer_id = compiler.attribute(layer_name);
4977 }
4978 else {
4979 layer_id = compiler.attribute(ATTR_STD_VERTEX_COLOR);
4980 }
4981
4982 ShaderNodeType node;
4983
4984 if (bump == SHADER_BUMP_DX) {
4985 node = NODE_VERTEX_COLOR_BUMP_DX;
4986 }
4987 else if (bump == SHADER_BUMP_DY) {
4988 node = NODE_VERTEX_COLOR_BUMP_DY;
4989 }
4990 else {
4991 node = NODE_VERTEX_COLOR;
4992 }
4993
4994 compiler.add_node(node,
4995 compiler.encode_uchar4(layer_id,
4996 compiler.stack_assign(color_out),
4997 compiler.stack_assign(alpha_out)),
4999}
5000
5002{
5003 if (bump == SHADER_BUMP_DX) {
5004 compiler.parameter("bump_offset", "dx");
5005 }
5006 else if (bump == SHADER_BUMP_DY) {
5007 compiler.parameter("bump_offset", "dy");
5008 }
5009 else {
5010 compiler.parameter("bump_offset", "center");
5011 }
5012 compiler.parameter("bump_filter_width", bump_filter_width);
5013
5014 if (layer_name.empty()) {
5015 compiler.parameter("layer_name", ustring("geom:vertex_color"));
5016 }
5017 else {
5018 if (Attribute::name_standard(layer_name.c_str()) != ATTR_STD_NONE) {
5019 compiler.parameter("name", (string("geom:") + layer_name.c_str()).c_str());
5020 }
5021 else {
5022 compiler.parameter("layer_name", layer_name.c_str());
5023 }
5024 }
5025
5026 compiler.add(this, "node_vertex_color");
5027}
5028
5029/* Value */
5030
5032{
5033 NodeType *type = NodeType::add("value", create, NodeType::SHADER);
5034
5035 SOCKET_FLOAT(value, "Value", 0.0f);
5036 SOCKET_OUT_FLOAT(value, "Value");
5037
5038 return type;
5039}
5040
5041ValueNode::ValueNode() : ShaderNode(get_node_type()) {}
5042
5044{
5045 folder.make_constant(value);
5046}
5047
5048void ValueNode::compile(SVMCompiler &compiler)
5049{
5050 ShaderOutput *val_out = output("Value");
5051
5052 compiler.add_node(NODE_VALUE_F, __float_as_int(value), compiler.stack_assign(val_out));
5053}
5054
5055void ValueNode::compile(OSLCompiler &compiler)
5056{
5057 compiler.parameter("value_value", value);
5058 compiler.add(this, "node_value");
5059}
5060
5061/* Color */
5062
5064{
5065 NodeType *type = NodeType::add("color", create, NodeType::SHADER);
5066
5067 SOCKET_COLOR(value, "Value", zero_float3());
5068 SOCKET_OUT_COLOR(color, "Color");
5069
5070 return type;
5071}
5072
5073ColorNode::ColorNode() : ShaderNode(get_node_type()) {}
5074
5076{
5077 folder.make_constant(value);
5078}
5079
5080void ColorNode::compile(SVMCompiler &compiler)
5081{
5082 ShaderOutput *color_out = output("Color");
5083
5084 if (!color_out->links.empty()) {
5085 compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
5086 compiler.add_node(NODE_VALUE_V, value);
5087 }
5088}
5089
5090void ColorNode::compile(OSLCompiler &compiler)
5091{
5092 compiler.parameter_color("color_value", value);
5093
5094 compiler.add(this, "node_value");
5095}
5096
5097/* Add Closure */
5098
5100{
5101 NodeType *type = NodeType::add("add_closure", create, NodeType::SHADER);
5102
5103 SOCKET_IN_CLOSURE(closure1, "Closure1");
5104 SOCKET_IN_CLOSURE(closure2, "Closure2");
5105 SOCKET_OUT_CLOSURE(closure, "Closure");
5106
5107 return type;
5108}
5109
5110AddClosureNode::AddClosureNode() : ShaderNode(get_node_type())
5111{
5113}
5114
5115void AddClosureNode::compile(SVMCompiler & /*compiler*/)
5116{
5117 /* handled in the SVM compiler */
5118}
5119
5121{
5122 compiler.add(this, "node_add_closure");
5123}
5124
5126{
5127 ShaderInput *closure1_in = input("Closure1");
5128 ShaderInput *closure2_in = input("Closure2");
5129
5130 /* remove useless add closures nodes */
5131 if (!closure1_in->link) {
5132 folder.bypass_or_discard(closure2_in);
5133 }
5134 else if (!closure2_in->link) {
5135 folder.bypass_or_discard(closure1_in);
5136 }
5137}
5138
5139/* Mix Closure */
5140
5142{
5143 NodeType *type = NodeType::add("mix_closure", create, NodeType::SHADER);
5144
5145 SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
5146 SOCKET_IN_CLOSURE(closure1, "Closure1");
5147 SOCKET_IN_CLOSURE(closure2, "Closure2");
5148
5149 SOCKET_OUT_CLOSURE(closure, "Closure");
5150
5151 return type;
5152}
5153
5154MixClosureNode::MixClosureNode() : ShaderNode(get_node_type())
5155{
5157}
5158
5159void MixClosureNode::compile(SVMCompiler & /*compiler*/)
5160{
5161 /* handled in the SVM compiler */
5162}
5163
5165{
5166 compiler.add(this, "node_mix_closure");
5167}
5168
5170{
5171 ShaderInput *fac_in = input("Fac");
5172 ShaderInput *closure1_in = input("Closure1");
5173 ShaderInput *closure2_in = input("Closure2");
5174
5175 /* remove useless mix closures nodes */
5176 if (closure1_in->link == closure2_in->link) {
5177 folder.bypass_or_discard(closure1_in);
5178 }
5179 /* remove unused mix closure input when factor is 0.0 or 1.0
5180 * check for closure links and make sure factor link is disconnected */
5181 else if (!fac_in->link) {
5182 /* factor 0.0 */
5183 if (fac <= 0.0f) {
5184 folder.bypass_or_discard(closure1_in);
5185 }
5186 /* factor 1.0 */
5187 else if (fac >= 1.0f) {
5188 folder.bypass_or_discard(closure2_in);
5189 }
5190 }
5191}
5192
5193/* Mix Closure */
5194
5196{
5197 NodeType *type = NodeType::add("mix_closure_weight", create, NodeType::SHADER);
5198
5199 SOCKET_IN_FLOAT(weight, "Weight", 1.0f);
5200 SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
5201
5202 SOCKET_OUT_FLOAT(weight1, "Weight1");
5203 SOCKET_OUT_FLOAT(weight2, "Weight2");
5204
5205 return type;
5206}
5207
5208MixClosureWeightNode::MixClosureWeightNode() : ShaderNode(get_node_type()) {}
5209
5211{
5212 ShaderInput *weight_in = input("Weight");
5213 ShaderInput *fac_in = input("Fac");
5214 ShaderOutput *weight1_out = output("Weight1");
5215 ShaderOutput *weight2_out = output("Weight2");
5216
5217 compiler.add_node(NODE_MIX_CLOSURE,
5218 compiler.encode_uchar4(compiler.stack_assign(fac_in),
5219 compiler.stack_assign(weight_in),
5220 compiler.stack_assign(weight1_out),
5221 compiler.stack_assign(weight2_out)));
5222}
5223
5224void MixClosureWeightNode::compile(OSLCompiler & /*compiler*/)
5225{
5226 assert(0);
5227}
5228
5229/* Invert */
5230
5232{
5233 NodeType *type = NodeType::add("invert", create, NodeType::SHADER);
5234
5235 SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
5236 SOCKET_IN_COLOR(color, "Color", zero_float3());
5237
5238 SOCKET_OUT_COLOR(color, "Color");
5239
5240 return type;
5241}
5242
5243InvertNode::InvertNode() : ShaderNode(get_node_type()) {}
5244
5246{
5247 ShaderInput *fac_in = input("Fac");
5248 ShaderInput *color_in = input("Color");
5249
5250 if (!fac_in->link) {
5251 /* evaluate fully constant node */
5252 if (!color_in->link) {
5253 folder.make_constant(interp(color, one_float3() - color, fac));
5254 }
5255 /* remove no-op node */
5256 else if (fac == 0.0f) {
5257 folder.bypass(color_in->link);
5258 }
5259 }
5260}
5261
5262void InvertNode::compile(SVMCompiler &compiler)
5263{
5264 ShaderInput *fac_in = input("Fac");
5265 ShaderInput *color_in = input("Color");
5266 ShaderOutput *color_out = output("Color");
5267
5268 compiler.add_node(NODE_INVERT,
5269 compiler.stack_assign(fac_in),
5270 compiler.stack_assign(color_in),
5271 compiler.stack_assign(color_out));
5272}
5273
5274void InvertNode::compile(OSLCompiler &compiler)
5275{
5276 compiler.add(this, "node_invert");
5277}
5278
5279/* Mix */
5280
5282{
5283 NodeType *type = NodeType::add("mix", create, NodeType::SHADER);
5284
5285 static NodeEnum type_enum;
5286 type_enum.insert("mix", NODE_MIX_BLEND);
5287 type_enum.insert("add", NODE_MIX_ADD);
5288 type_enum.insert("multiply", NODE_MIX_MUL);
5289 type_enum.insert("screen", NODE_MIX_SCREEN);
5290 type_enum.insert("overlay", NODE_MIX_OVERLAY);
5291 type_enum.insert("subtract", NODE_MIX_SUB);
5292 type_enum.insert("divide", NODE_MIX_DIV);
5293 type_enum.insert("difference", NODE_MIX_DIFF);
5294 type_enum.insert("darken", NODE_MIX_DARK);
5295 type_enum.insert("lighten", NODE_MIX_LIGHT);
5296 type_enum.insert("dodge", NODE_MIX_DODGE);
5297 type_enum.insert("burn", NODE_MIX_BURN);
5298 type_enum.insert("hue", NODE_MIX_HUE);
5299 type_enum.insert("saturation", NODE_MIX_SAT);
5300 type_enum.insert("value", NODE_MIX_VAL);
5301 type_enum.insert("color", NODE_MIX_COL);
5302 type_enum.insert("soft_light", NODE_MIX_SOFT);
5303 type_enum.insert("linear_light", NODE_MIX_LINEAR);
5304 type_enum.insert("exclusion", NODE_MIX_EXCLUSION);
5305 SOCKET_ENUM(mix_type, "Type", type_enum, NODE_MIX_BLEND);
5306
5307 SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
5308
5309 SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
5310 SOCKET_IN_COLOR(color1, "Color1", zero_float3());
5311 SOCKET_IN_COLOR(color2, "Color2", zero_float3());
5312
5313 SOCKET_OUT_COLOR(color, "Color");
5314
5315 return type;
5316}
5317
5318MixNode::MixNode() : ShaderNode(get_node_type()) {}
5319
5320void MixNode::compile(SVMCompiler &compiler)
5321{
5322 ShaderInput *fac_in = input("Fac");
5323 ShaderInput *color1_in = input("Color1");
5324 ShaderInput *color2_in = input("Color2");
5325 ShaderOutput *color_out = output("Color");
5326
5327 compiler.add_node(NODE_MIX,
5328 compiler.stack_assign(fac_in),
5329 compiler.stack_assign(color1_in),
5330 compiler.stack_assign(color2_in));
5331 compiler.add_node(NODE_MIX, mix_type, compiler.stack_assign(color_out));
5332
5333 if (use_clamp) {
5334 compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
5335 compiler.add_node(NODE_MIX, NODE_MIX_CLAMP, compiler.stack_assign(color_out));
5336 }
5337}
5338
5339void MixNode::compile(OSLCompiler &compiler)
5340{
5341 compiler.parameter(this, "mix_type");
5342 compiler.parameter(this, "use_clamp");
5343 compiler.add(this, "node_mix");
5344}
5345
5347{
5348 if (folder.all_inputs_constant()) {
5349 folder.make_constant_clamp(svm_mix_clamped_factor(mix_type, fac, color1, color2), use_clamp);
5350 }
5351 else {
5352 folder.fold_mix(mix_type, use_clamp);
5353 }
5354}
5355
5357{
5358 switch (mix_type) {
5359 case NODE_MIX_BLEND:
5360 case NODE_MIX_ADD:
5361 case NODE_MIX_MUL:
5362 case NODE_MIX_SUB:
5363 break;
5364 default:
5365 return false;
5366 }
5367 return use_clamp == false && input("Factor")->link == nullptr;
5368}
5369
5370/* Mix Color */
5371
5373{
5374 NodeType *type = NodeType::add("mix_color", create, NodeType::SHADER);
5375
5376 static NodeEnum type_enum;
5377 type_enum.insert("mix", NODE_MIX_BLEND);
5378 type_enum.insert("add", NODE_MIX_ADD);
5379 type_enum.insert("multiply", NODE_MIX_MUL);
5380 type_enum.insert("screen", NODE_MIX_SCREEN);
5381 type_enum.insert("overlay", NODE_MIX_OVERLAY);
5382 type_enum.insert("subtract", NODE_MIX_SUB);
5383 type_enum.insert("divide", NODE_MIX_DIV);
5384 type_enum.insert("difference", NODE_MIX_DIFF);
5385 type_enum.insert("darken", NODE_MIX_DARK);
5386 type_enum.insert("lighten", NODE_MIX_LIGHT);
5387 type_enum.insert("dodge", NODE_MIX_DODGE);
5388 type_enum.insert("burn", NODE_MIX_BURN);
5389 type_enum.insert("hue", NODE_MIX_HUE);
5390 type_enum.insert("saturation", NODE_MIX_SAT);
5391 type_enum.insert("value", NODE_MIX_VAL);
5392 type_enum.insert("color", NODE_MIX_COL);
5393 type_enum.insert("soft_light", NODE_MIX_SOFT);
5394 type_enum.insert("linear_light", NODE_MIX_LINEAR);
5395 type_enum.insert("exclusion", NODE_MIX_EXCLUSION);
5396 SOCKET_ENUM(blend_type, "Type", type_enum, NODE_MIX_BLEND);
5397
5398 SOCKET_IN_FLOAT(fac, "Factor", 0.5f);
5399 SOCKET_IN_COLOR(a, "A", zero_float3());
5400 SOCKET_IN_COLOR(b, "B", zero_float3());
5401 SOCKET_BOOLEAN(use_clamp_result, "Use Clamp Result", false);
5402 SOCKET_BOOLEAN(use_clamp, "Use Clamp", true);
5403
5404 SOCKET_OUT_COLOR(result, "Result");
5405
5406 return type;
5407}
5408
5409MixColorNode::MixColorNode() : ShaderNode(get_node_type()) {}
5410
5411void MixColorNode::compile(SVMCompiler &compiler)
5412{
5413 ShaderInput *fac_in = input("Factor");
5414 ShaderInput *a_in = input("A");
5415 ShaderInput *b_in = input("B");
5416 ShaderOutput *result_out = output("Result");
5417
5418 const int fac_in_stack_offset = compiler.stack_assign(fac_in);
5419 const int a_in_stack_offset = compiler.stack_assign(a_in);
5420 const int b_in_stack_offset = compiler.stack_assign(b_in);
5421
5422 compiler.add_node(
5423 NODE_MIX_COLOR,
5424 compiler.encode_uchar4(use_clamp, blend_type, use_clamp_result),
5425 compiler.encode_uchar4(fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset),
5426 compiler.stack_assign(result_out));
5427}
5428
5429void MixColorNode::compile(OSLCompiler &compiler)
5430{
5431 compiler.parameter(this, "blend_type");
5432 compiler.parameter(this, "use_clamp");
5433 compiler.parameter(this, "use_clamp_result");
5434 compiler.add(this, "node_mix_color");
5435}
5436
5438{
5439 if (folder.all_inputs_constant()) {
5440 if (use_clamp) {
5441 fac = clamp(fac, 0.0f, 1.0f);
5442 }
5443 folder.make_constant_clamp(svm_mix(blend_type, fac, a, b), use_clamp_result);
5444 }
5445 else {
5446 folder.fold_mix_color(blend_type, use_clamp, use_clamp_result);
5447 }
5448}
5449
5451{
5452 switch (blend_type) {
5453 case NODE_MIX_BLEND:
5454 case NODE_MIX_ADD:
5455 case NODE_MIX_MUL:
5456 case NODE_MIX_SUB:
5457 break;
5458 default:
5459 return false;
5460 }
5461 return use_clamp == false && use_clamp_result == false && input("Factor")->link == nullptr;
5462}
5463
5464/* Mix Float */
5465
5467{
5468 NodeType *type = NodeType::add("mix_float", create, NodeType::SHADER);
5469
5470 SOCKET_IN_FLOAT(fac, "Factor", 0.5f);
5471 SOCKET_IN_FLOAT(a, "A", 0.0f);
5472 SOCKET_IN_FLOAT(b, "B", 0.0f);
5473 SOCKET_BOOLEAN(use_clamp, "Use Clamp", true);
5474 SOCKET_OUT_FLOAT(result, "Result");
5475
5476 return type;
5477}
5478
5479MixFloatNode::MixFloatNode() : ShaderNode(get_node_type()) {}
5480
5481void MixFloatNode::compile(SVMCompiler &compiler)
5482{
5483 ShaderInput *fac_in = input("Factor");
5484 ShaderInput *a_in = input("A");
5485 ShaderInput *b_in = input("B");
5486 ShaderOutput *result_out = output("Result");
5487
5488 const int fac_in_stack_offset = compiler.stack_assign(fac_in);
5489 const int a_in_stack_offset = compiler.stack_assign(a_in);
5490 const int b_in_stack_offset = compiler.stack_assign(b_in);
5491
5492 compiler.add_node(
5493 NODE_MIX_FLOAT,
5494 use_clamp,
5495 compiler.encode_uchar4(fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset),
5496 compiler.stack_assign(result_out));
5497}
5498
5499void MixFloatNode::compile(OSLCompiler &compiler)
5500{
5501 compiler.parameter(this, "use_clamp");
5502 compiler.add(this, "node_mix_float");
5503}
5504
5506{
5507 if (folder.all_inputs_constant()) {
5508 if (use_clamp) {
5509 fac = clamp(fac, 0.0f, 1.0f);
5510 }
5511 folder.make_constant(a * (1 - fac) + b * fac);
5512 }
5513 else {
5514 folder.fold_mix_float(use_clamp, false);
5515 }
5516}
5517
5519{
5520 return use_clamp == false && input("Factor")->link == nullptr;
5521}
5522
5523/* Mix Vector */
5524
5526{
5527 NodeType *type = NodeType::add("mix_vector", create, NodeType::SHADER);
5528
5529 SOCKET_IN_FLOAT(fac, "Factor", 0.5f);
5530 SOCKET_IN_VECTOR(a, "A", zero_float3());
5532 SOCKET_BOOLEAN(use_clamp, "Use Clamp", true);
5533
5534 SOCKET_OUT_VECTOR(result, "Result");
5535
5536 return type;
5537}
5538
5539MixVectorNode::MixVectorNode() : ShaderNode(get_node_type()) {}
5540
5541void MixVectorNode::compile(SVMCompiler &compiler)
5542{
5543 ShaderInput *fac_in = input("Factor");
5544 ShaderInput *a_in = input("A");
5545 ShaderInput *b_in = input("B");
5546 ShaderOutput *result_out = output("Result");
5547
5548 const int fac_in_stack_offset = compiler.stack_assign(fac_in);
5549 const int a_in_stack_offset = compiler.stack_assign(a_in);
5550 const int b_in_stack_offset = compiler.stack_assign(b_in);
5551
5552 compiler.add_node(
5553 NODE_MIX_VECTOR,
5554 compiler.encode_uchar4(use_clamp, fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset),
5555 compiler.stack_assign(result_out));
5556}
5557
5558void MixVectorNode::compile(OSLCompiler &compiler)
5559{
5560 compiler.parameter(this, "use_clamp");
5561 compiler.add(this, "node_mix_vector");
5562}
5563
5565{
5566 if (folder.all_inputs_constant()) {
5567 if (use_clamp) {
5568 fac = clamp(fac, 0.0f, 1.0f);
5569 }
5570 folder.make_constant(a * (one_float3() - fac) + b * fac);
5571 }
5572 else {
5573 folder.fold_mix_color(NODE_MIX_BLEND, use_clamp, false);
5574 }
5575}
5576
5578{
5579 return use_clamp == false && input("Factor")->link == nullptr;
5580}
5581
5582/* Mix Vector Non Uniform */
5583
5585{
5586 NodeType *type = NodeType::add("mix_vector_non_uniform", create, NodeType::SHADER);
5587
5588 SOCKET_IN_VECTOR(fac, "Factor", make_float3(0.5f, 0.5f, 0.5f));
5589 SOCKET_IN_VECTOR(a, "A", zero_float3());
5591 SOCKET_BOOLEAN(use_clamp, "Use Clamp", true);
5592
5593 SOCKET_OUT_VECTOR(result, "Result");
5594
5595 return type;
5596}
5597
5598MixVectorNonUniformNode::MixVectorNonUniformNode() : ShaderNode(get_node_type()) {}
5599
5601{
5602 ShaderInput *fac_in = input("Factor");
5603 ShaderInput *a_in = input("A");
5604 ShaderInput *b_in = input("B");
5605 ShaderOutput *result_out = output("Result");
5606
5607 const int fac_in_stack_offset = compiler.stack_assign(fac_in);
5608 const int a_in_stack_offset = compiler.stack_assign(a_in);
5609 const int b_in_stack_offset = compiler.stack_assign(b_in);
5610
5611 compiler.add_node(
5612 NODE_MIX_VECTOR_NON_UNIFORM,
5613 compiler.encode_uchar4(use_clamp, fac_in_stack_offset, a_in_stack_offset, b_in_stack_offset),
5614 compiler.stack_assign(result_out));
5615}
5616
5618{
5619 compiler.parameter(this, "use_clamp");
5620 compiler.add(this, "node_mix_vector_non_uniform");
5621}
5622
5624{
5625 if (folder.all_inputs_constant()) {
5626 if (use_clamp) {
5627 fac = saturate(fac);
5628 }
5629 folder.make_constant(a * (one_float3() - fac) + b * fac);
5630 }
5631}
5632
5634{
5635 return use_clamp == false && input("Factor")->link == nullptr;
5636}
5637
5638/* Combine Color */
5639
5641{
5642 NodeType *type = NodeType::add("combine_color", create, NodeType::SHADER);
5643
5644 static NodeEnum type_enum;
5645 type_enum.insert("rgb", NODE_COMBSEP_COLOR_RGB);
5646 type_enum.insert("hsv", NODE_COMBSEP_COLOR_HSV);
5647 type_enum.insert("hsl", NODE_COMBSEP_COLOR_HSL);
5648 SOCKET_ENUM(color_type, "Type", type_enum, NODE_COMBSEP_COLOR_RGB);
5649
5650 SOCKET_IN_FLOAT(r, "Red", 0.0f);
5651 SOCKET_IN_FLOAT(g, "Green", 0.0f);
5652 SOCKET_IN_FLOAT(b, "Blue", 0.0f);
5653
5654 SOCKET_OUT_COLOR(color, "Color");
5655
5656 return type;
5657}
5658
5659CombineColorNode::CombineColorNode() : ShaderNode(get_node_type()) {}
5660
5662{
5663 if (folder.all_inputs_constant()) {
5664 folder.make_constant(svm_combine_color(color_type, make_float3(r, g, b)));
5665 }
5666}
5667
5669{
5670 ShaderInput *red_in = input("Red");
5671 ShaderInput *green_in = input("Green");
5672 ShaderInput *blue_in = input("Blue");
5673 ShaderOutput *color_out = output("Color");
5674
5675 const int red_stack_offset = compiler.stack_assign(red_in);
5676 const int green_stack_offset = compiler.stack_assign(green_in);
5677 const int blue_stack_offset = compiler.stack_assign(blue_in);
5678 const int color_stack_offset = compiler.stack_assign(color_out);
5679
5680 compiler.add_node(
5681 NODE_COMBINE_COLOR,
5682 color_type,
5683 compiler.encode_uchar4(red_stack_offset, green_stack_offset, blue_stack_offset),
5684 color_stack_offset);
5685}
5686
5688{
5689 compiler.parameter(this, "color_type");
5690 compiler.add(this, "node_combine_color");
5691}
5692
5693/* Combine XYZ */
5694
5696{
5697 NodeType *type = NodeType::add("combine_xyz", create, NodeType::SHADER);
5698
5699 SOCKET_IN_FLOAT(x, "X", 0.0f);
5700 SOCKET_IN_FLOAT(y, "Y", 0.0f);
5701 SOCKET_IN_FLOAT(z, "Z", 0.0f);
5702
5703 SOCKET_OUT_VECTOR(vector, "Vector");
5704
5705 return type;
5706}
5707
5708CombineXYZNode::CombineXYZNode() : ShaderNode(get_node_type()) {}
5709
5711{
5712 if (folder.all_inputs_constant()) {
5713 folder.make_constant(make_float3(x, y, z));
5714 }
5715}
5716
5718{
5719 ShaderInput *x_in = input("X");
5720 ShaderInput *y_in = input("Y");
5721 ShaderInput *z_in = input("Z");
5722 ShaderOutput *vector_out = output("Vector");
5723
5724 compiler.add_node(
5725 NODE_COMBINE_VECTOR, compiler.stack_assign(x_in), 0, compiler.stack_assign(vector_out));
5726
5727 compiler.add_node(
5728 NODE_COMBINE_VECTOR, compiler.stack_assign(y_in), 1, compiler.stack_assign(vector_out));
5729
5730 compiler.add_node(
5731 NODE_COMBINE_VECTOR, compiler.stack_assign(z_in), 2, compiler.stack_assign(vector_out));
5732}
5733
5735{
5736 compiler.add(this, "node_combine_xyz");
5737}
5738
5739/* Gamma */
5740
5742{
5743 NodeType *type = NodeType::add("gamma", create, NodeType::SHADER);
5744
5745 SOCKET_IN_COLOR(color, "Color", zero_float3());
5746 SOCKET_IN_FLOAT(gamma, "Gamma", 1.0f);
5747 SOCKET_OUT_COLOR(color, "Color");
5748
5749 return type;
5750}
5751
5752GammaNode::GammaNode() : ShaderNode(get_node_type()) {}
5753
5755{
5756 if (folder.all_inputs_constant()) {
5757 folder.make_constant(svm_math_gamma_color(color, gamma));
5758 }
5759 else {
5760 ShaderInput *color_in = input("Color");
5761 ShaderInput *gamma_in = input("Gamma");
5762
5763 /* 1 ^ X == X ^ 0 == 1 */
5764 if (folder.is_one(color_in) || folder.is_zero(gamma_in)) {
5765 folder.make_one();
5766 }
5767 /* X ^ 1 == X */
5768 else if (folder.is_one(gamma_in)) {
5769 folder.try_bypass_or_make_constant(color_in, false);
5770 }
5771 }
5772}
5773
5774void GammaNode::compile(SVMCompiler &compiler)
5775{
5776 ShaderInput *color_in = input("Color");
5777 ShaderInput *gamma_in = input("Gamma");
5778 ShaderOutput *color_out = output("Color");
5779
5780 compiler.add_node(NODE_GAMMA,
5781 compiler.stack_assign(gamma_in),
5782 compiler.stack_assign(color_in),
5783 compiler.stack_assign(color_out));
5784}
5785
5786void GammaNode::compile(OSLCompiler &compiler)
5787{
5788 compiler.add(this, "node_gamma");
5789}
5790
5791/* Bright Contrast */
5792
5794{
5795 NodeType *type = NodeType::add("brightness_contrast", create, NodeType::SHADER);
5796
5797 SOCKET_IN_COLOR(color, "Color", zero_float3());
5798 SOCKET_IN_FLOAT(bright, "Bright", 0.0f);
5799 SOCKET_IN_FLOAT(contrast, "Contrast", 0.0f);
5800
5801 SOCKET_OUT_COLOR(color, "Color");
5802
5803 return type;
5804}
5805
5806BrightContrastNode::BrightContrastNode() : ShaderNode(get_node_type()) {}
5807
5809{
5810 if (folder.all_inputs_constant()) {
5811 folder.make_constant(svm_brightness_contrast(color, bright, contrast));
5812 }
5813}
5814
5816{
5817 ShaderInput *color_in = input("Color");
5818 ShaderInput *bright_in = input("Bright");
5819 ShaderInput *contrast_in = input("Contrast");
5820 ShaderOutput *color_out = output("Color");
5821
5822 compiler.add_node(NODE_BRIGHTCONTRAST,
5823 compiler.stack_assign(color_in),
5824 compiler.stack_assign(color_out),
5825 compiler.encode_uchar4(compiler.stack_assign(bright_in),
5826 compiler.stack_assign(contrast_in)));
5827}
5828
5830{
5831 compiler.add(this, "node_brightness");
5832}
5833
5834/* Separate Color */
5835
5837{
5838 NodeType *type = NodeType::add("separate_color", create, NodeType::SHADER);
5839
5840 static NodeEnum type_enum;
5841 type_enum.insert("rgb", NODE_COMBSEP_COLOR_RGB);
5842 type_enum.insert("hsv", NODE_COMBSEP_COLOR_HSV);
5843 type_enum.insert("hsl", NODE_COMBSEP_COLOR_HSL);
5844 SOCKET_ENUM(color_type, "Type", type_enum, NODE_COMBSEP_COLOR_RGB);
5845
5846 SOCKET_IN_COLOR(color, "Color", zero_float3());
5847
5848 SOCKET_OUT_FLOAT(r, "Red");
5849 SOCKET_OUT_FLOAT(g, "Green");
5850 SOCKET_OUT_FLOAT(b, "Blue");
5851
5852 return type;
5853}
5854
5855SeparateColorNode::SeparateColorNode() : ShaderNode(get_node_type()) {}
5856
5858{
5859 if (folder.all_inputs_constant()) {
5860 float3 col = svm_separate_color(color_type, color);
5861
5862 for (int channel = 0; channel < 3; channel++) {
5863 if (outputs[channel] == folder.output) {
5864 folder.make_constant(col[channel]);
5865 return;
5866 }
5867 }
5868 }
5869}
5870
5872{
5873 ShaderInput *color_in = input("Color");
5874 ShaderOutput *red_out = output("Red");
5875 ShaderOutput *green_out = output("Green");
5876 ShaderOutput *blue_out = output("Blue");
5877
5878 const int color_stack_offset = compiler.stack_assign(color_in);
5879 const int red_stack_offset = compiler.stack_assign(red_out);
5880 const int green_stack_offset = compiler.stack_assign(green_out);
5881 const int blue_stack_offset = compiler.stack_assign(blue_out);
5882
5883 compiler.add_node(
5884 NODE_SEPARATE_COLOR,
5885 color_type,
5886 color_stack_offset,
5887 compiler.encode_uchar4(red_stack_offset, green_stack_offset, blue_stack_offset));
5888}
5889
5891{
5892 compiler.parameter(this, "color_type");
5893 compiler.add(this, "node_separate_color");
5894}
5895
5896/* Separate XYZ */
5897
5899{
5900 NodeType *type = NodeType::add("separate_xyz", create, NodeType::SHADER);
5901
5902 SOCKET_IN_COLOR(vector, "Vector", zero_float3());
5903
5904 SOCKET_OUT_FLOAT(x, "X");
5905 SOCKET_OUT_FLOAT(y, "Y");
5906 SOCKET_OUT_FLOAT(z, "Z");
5907
5908 return type;
5909}
5910
5911SeparateXYZNode::SeparateXYZNode() : ShaderNode(get_node_type()) {}
5912
5914{
5915 if (folder.all_inputs_constant()) {
5916 for (int channel = 0; channel < 3; channel++) {
5917 if (outputs[channel] == folder.output) {
5918 folder.make_constant(vector[channel]);
5919 return;
5920 }
5921 }
5922 }
5923}
5924
5926{
5927 ShaderInput *vector_in = input("Vector");
5928 ShaderOutput *x_out = output("X");
5929 ShaderOutput *y_out = output("Y");
5930 ShaderOutput *z_out = output("Z");
5931
5932 compiler.add_node(
5933 NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 0, compiler.stack_assign(x_out));
5934
5935 compiler.add_node(
5936 NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 1, compiler.stack_assign(y_out));
5937
5938 compiler.add_node(
5939 NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 2, compiler.stack_assign(z_out));
5940}
5941
5943{
5944 compiler.add(this, "node_separate_xyz");
5945}
5946
5947/* Hue/Saturation/Value */
5948
5950{
5951 NodeType *type = NodeType::add("hsv", create, NodeType::SHADER);
5952
5953 SOCKET_IN_FLOAT(hue, "Hue", 0.5f);
5954 SOCKET_IN_FLOAT(saturation, "Saturation", 1.0f);
5955 SOCKET_IN_FLOAT(value, "Value", 1.0f);
5956 SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
5957 SOCKET_IN_COLOR(color, "Color", zero_float3());
5958
5959 SOCKET_OUT_COLOR(color, "Color");
5960
5961 return type;
5962}
5963
5964HSVNode::HSVNode() : ShaderNode(get_node_type()) {}
5965
5966void HSVNode::compile(SVMCompiler &compiler)
5967{
5968 ShaderInput *hue_in = input("Hue");
5969 ShaderInput *saturation_in = input("Saturation");
5970 ShaderInput *value_in = input("Value");
5971 ShaderInput *fac_in = input("Fac");
5972 ShaderInput *color_in = input("Color");
5973 ShaderOutput *color_out = output("Color");
5974
5975 compiler.add_node(NODE_HSV,
5976 compiler.encode_uchar4(compiler.stack_assign(color_in),
5977 compiler.stack_assign(fac_in),
5978 compiler.stack_assign(color_out)),
5979 compiler.encode_uchar4(compiler.stack_assign(hue_in),
5980 compiler.stack_assign(saturation_in),
5981 compiler.stack_assign(value_in)));
5982}
5983
5984void HSVNode::compile(OSLCompiler &compiler)
5985{
5986 compiler.add(this, "node_hsv");
5987}
5988
5989/* Attribute */
5990
5992{
5993 NodeType *type = NodeType::add("attribute", create, NodeType::SHADER);
5994
5995 SOCKET_STRING(attribute, "Attribute", ustring());
5996
5997 SOCKET_OUT_COLOR(color, "Color");
5998 SOCKET_OUT_VECTOR(vector, "Vector");
5999 SOCKET_OUT_FLOAT(fac, "Fac");
6000 SOCKET_OUT_FLOAT(alpha, "Alpha");
6001
6002 return type;
6003}
6004
6005AttributeNode::AttributeNode() : ShaderNode(get_node_type()) {}
6006
6008{
6009 ShaderOutput *color_out = output("Color");
6010 ShaderOutput *vector_out = output("Vector");
6011 ShaderOutput *fac_out = output("Fac");
6012 ShaderOutput *alpha_out = output("Alpha");
6013
6014 if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty() ||
6015 !alpha_out->links.empty())
6016 {
6017 attributes->add_standard(attribute);
6018
6019 /* Request UV if we asked for one of the attributes computed from it.
6020 * Ideally this would be handled at a more generic level. */
6021 const AttributeStandard std = Attribute::name_standard(attribute.c_str());
6022 if (std == ATTR_STD_UV_TANGENT || std == ATTR_STD_UV_TANGENT_SIGN ||
6024 {
6025 attributes->add(ATTR_STD_UV);
6026 }
6027 else {
6028 const char *suffixes[] = {
6029 ".tangent_sign", ".tangent", ".undisplaced_tangent", ".undisplaced_tangent_sign"};
6030 for (const char *suffix : suffixes) {
6031 if (string_endswith(attribute, suffix)) {
6032 attributes->add(attribute.substr(0, attribute.size() - strlen(suffix)));
6033 }
6034 }
6035 }
6036 }
6037
6038 if (shader->has_volume) {
6040 }
6041
6043}
6044
6045void AttributeNode::compile(SVMCompiler &compiler)
6046{
6047 ShaderOutput *color_out = output("Color");
6048 ShaderOutput *vector_out = output("Vector");
6049 ShaderOutput *fac_out = output("Fac");
6050 ShaderOutput *alpha_out = output("Alpha");
6051 ShaderNodeType attr_node = NODE_ATTR;
6052 const int attr = compiler.attribute_standard(attribute);
6053 const uint bump_filter_or_stochastic = (compiler.output_type() == SHADER_TYPE_VOLUME) ?
6056
6057 if (bump == SHADER_BUMP_DX) {
6058 attr_node = NODE_ATTR_BUMP_DX;
6059 }
6060 else if (bump == SHADER_BUMP_DY) {
6061 attr_node = NODE_ATTR_BUMP_DY;
6062 }
6063
6064 if (!color_out->links.empty() || !vector_out->links.empty()) {
6065 if (!color_out->links.empty()) {
6066 compiler.add_node(
6067 attr_node,
6068 attr,
6069 compiler.encode_uchar4(compiler.stack_assign(color_out), NODE_ATTR_OUTPUT_FLOAT3),
6070 bump_filter_or_stochastic);
6071 }
6072 if (!vector_out->links.empty()) {
6073 compiler.add_node(
6074 attr_node,
6075 attr,
6076 compiler.encode_uchar4(compiler.stack_assign(vector_out), NODE_ATTR_OUTPUT_FLOAT3),
6077 bump_filter_or_stochastic);
6078 }
6079 }
6080
6081 if (!fac_out->links.empty()) {
6082 compiler.add_node(
6083 attr_node,
6084 attr,
6085 compiler.encode_uchar4(compiler.stack_assign(fac_out), NODE_ATTR_OUTPUT_FLOAT),
6086 bump_filter_or_stochastic);
6087 }
6088
6089 if (!alpha_out->links.empty()) {
6090 compiler.add_node(
6091 attr_node,
6092 attr,
6093 compiler.encode_uchar4(compiler.stack_assign(alpha_out), NODE_ATTR_OUTPUT_FLOAT_ALPHA),
6094 bump_filter_or_stochastic);
6095 }
6096}
6097
6098void AttributeNode::compile(OSLCompiler &compiler)
6099{
6100 if (bump == SHADER_BUMP_DX) {
6101 compiler.parameter("bump_offset", "dx");
6102 }
6103 else if (bump == SHADER_BUMP_DY) {
6104 compiler.parameter("bump_offset", "dy");
6105 }
6106 else {
6107 compiler.parameter("bump_offset", "center");
6108 }
6109 compiler.parameter("bump_filter_width", bump_filter_width);
6110
6111 if (Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE) {
6112 compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
6113 }
6114 else {
6115 compiler.parameter("name", attribute.c_str());
6116 }
6117
6118 compiler.add(this, "node_attribute");
6119}
6120
6121/* Camera */
6122
6124{
6125 NodeType *type = NodeType::add("camera_info", create, NodeType::SHADER);
6126
6127 SOCKET_OUT_VECTOR(view_vector, "View Vector");
6128 SOCKET_OUT_FLOAT(view_z_depth, "View Z Depth");
6129 SOCKET_OUT_FLOAT(view_distance, "View Distance");
6130
6131 return type;
6132}
6133
6134CameraNode::CameraNode() : ShaderNode(get_node_type()) {}
6135
6136void CameraNode::compile(SVMCompiler &compiler)
6137{
6138 ShaderOutput *vector_out = output("View Vector");
6139 ShaderOutput *z_depth_out = output("View Z Depth");
6140 ShaderOutput *distance_out = output("View Distance");
6141
6142 compiler.add_node(NODE_CAMERA,
6143 compiler.stack_assign(vector_out),
6144 compiler.stack_assign(z_depth_out),
6145 compiler.stack_assign(distance_out));
6146}
6147
6148void CameraNode::compile(OSLCompiler &compiler)
6149{
6150 compiler.add(this, "node_camera");
6151}
6152
6153/* Fresnel */
6154
6156{
6157 NodeType *type = NodeType::add("fresnel", create, NodeType::SHADER);
6158
6161 SOCKET_IN_FLOAT(IOR, "IOR", 1.5f);
6162
6163 SOCKET_OUT_FLOAT(fac, "Fac");
6164
6165 return type;
6166}
6167
6168FresnelNode::FresnelNode() : ShaderNode(get_node_type()) {}
6169
6170void FresnelNode::compile(SVMCompiler &compiler)
6171{
6172 ShaderInput *normal_in = input("Normal");
6173 ShaderInput *IOR_in = input("IOR");
6174 ShaderOutput *fac_out = output("Fac");
6175
6176 compiler.add_node(NODE_FRESNEL,
6177 compiler.stack_assign(IOR_in),
6178 __float_as_int(IOR),
6179 compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
6180 compiler.stack_assign(fac_out)));
6181}
6182
6183void FresnelNode::compile(OSLCompiler &compiler)
6184{
6185 compiler.add(this, "node_fresnel");
6186}
6187
6188/* Layer Weight */
6189
6191{
6192 NodeType *type = NodeType::add("layer_weight", create, NodeType::SHADER);
6193
6196 SOCKET_IN_FLOAT(blend, "Blend", 0.5f);
6197
6198 SOCKET_OUT_FLOAT(fresnel, "Fresnel");
6199 SOCKET_OUT_FLOAT(facing, "Facing");
6200
6201 return type;
6202}
6203
6204LayerWeightNode::LayerWeightNode() : ShaderNode(get_node_type()) {}
6205
6207{
6208 ShaderInput *normal_in = input("Normal");
6209 ShaderInput *blend_in = input("Blend");
6210 ShaderOutput *fresnel_out = output("Fresnel");
6211 ShaderOutput *facing_out = output("Facing");
6212
6213 if (!fresnel_out->links.empty()) {
6214 compiler.add_node(NODE_LAYER_WEIGHT,
6215 compiler.stack_assign_if_linked(blend_in),
6218 compiler.stack_assign_if_linked(normal_in),
6219 compiler.stack_assign(fresnel_out)));
6220 }
6221
6222 if (!facing_out->links.empty()) {
6223 compiler.add_node(NODE_LAYER_WEIGHT,
6224 compiler.stack_assign_if_linked(blend_in),
6227 compiler.stack_assign_if_linked(normal_in),
6228 compiler.stack_assign(facing_out)));
6229 }
6230}
6231
6233{
6234 compiler.add(this, "node_layer_weight");
6235}
6236
6237/* Wireframe */
6238
6240{
6241 NodeType *type = NodeType::add("wireframe", create, NodeType::SHADER);
6242
6243 SOCKET_BOOLEAN(use_pixel_size, "Use Pixel Size", false);
6244 SOCKET_IN_FLOAT(size, "Size", 0.01f);
6245 SOCKET_OUT_FLOAT(fac, "Fac");
6246
6247 return type;
6248}
6249
6250WireframeNode::WireframeNode() : ShaderNode(get_node_type()) {}
6251
6252void WireframeNode::compile(SVMCompiler &compiler)
6253{
6254 ShaderInput *size_in = input("Size");
6255 ShaderOutput *fac_out = output("Fac");
6257 if (bump == SHADER_BUMP_DX) {
6258 bump_offset = NODE_BUMP_OFFSET_DX;
6259 }
6260 else if (bump == SHADER_BUMP_DY) {
6261 bump_offset = NODE_BUMP_OFFSET_DY;
6262 }
6263 compiler.add_node(
6264 NODE_WIREFRAME,
6265 compiler.stack_assign(size_in),
6267 compiler.encode_uchar4(use_pixel_size, bump_offset, compiler.stack_assign(fac_out), 0));
6268}
6269
6270void WireframeNode::compile(OSLCompiler &compiler)
6271{
6272 if (bump == SHADER_BUMP_DX) {
6273 compiler.parameter("bump_offset", "dx");
6274 }
6275 else if (bump == SHADER_BUMP_DY) {
6276 compiler.parameter("bump_offset", "dy");
6277 }
6278 else {
6279 compiler.parameter("bump_offset", "center");
6280 }
6281 compiler.parameter("bump_filter_width", bump_filter_width);
6282
6283 compiler.parameter(this, "use_pixel_size");
6284 compiler.add(this, "node_wireframe");
6285}
6286
6287/* Wavelength */
6288
6290{
6291 NodeType *type = NodeType::add("wavelength", create, NodeType::SHADER);
6292
6293 SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f);
6294 SOCKET_OUT_COLOR(color, "Color");
6295
6296 return type;
6297}
6298
6299WavelengthNode::WavelengthNode() : ShaderNode(get_node_type()) {}
6300
6302{
6303 ShaderInput *wavelength_in = input("Wavelength");
6304 ShaderOutput *color_out = output("Color");
6305
6306 compiler.add_node(
6307 NODE_WAVELENGTH, compiler.stack_assign(wavelength_in), compiler.stack_assign(color_out));
6308}
6309
6311{
6312 compiler.add(this, "node_wavelength");
6313}
6314
6315/* Blackbody */
6316
6318{
6319 NodeType *type = NodeType::add("blackbody", create, NodeType::SHADER);
6320
6321 SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f);
6322 SOCKET_OUT_COLOR(color, "Color");
6323
6324 return type;
6325}
6326
6327BlackbodyNode::BlackbodyNode() : ShaderNode(get_node_type()) {}
6328
6330{
6331 if (folder.all_inputs_constant()) {
6332 const float3 rgb_rec709 = svm_math_blackbody_color_rec709(temperature);
6333 const float3 rgb = folder.scene->shader_manager->rec709_to_scene_linear(rgb_rec709);
6334 folder.make_constant(max(rgb, zero_float3()));
6335 }
6336}
6337
6338void BlackbodyNode::compile(SVMCompiler &compiler)
6339{
6340 ShaderInput *temperature_in = input("Temperature");
6341 ShaderOutput *color_out = output("Color");
6342
6343 compiler.add_node(
6344 NODE_BLACKBODY, compiler.stack_assign(temperature_in), compiler.stack_assign(color_out));
6345}
6346
6347void BlackbodyNode::compile(OSLCompiler &compiler)
6348{
6349 compiler.add(this, "node_blackbody");
6350}
6351
6352/* Output */
6353
6355{
6356 NodeType *type = NodeType::add("output", create, NodeType::SHADER);
6357
6358 SOCKET_IN_CLOSURE(surface, "Surface");
6359 SOCKET_IN_CLOSURE(volume, "Volume");
6360 SOCKET_IN_VECTOR(displacement, "Displacement", zero_float3());
6361 SOCKET_IN_NORMAL(normal, "Normal", zero_float3());
6362
6363 return type;
6364}
6365
6366OutputNode::OutputNode() : ShaderNode(get_node_type())
6367{
6368 special_type = SHADER_SPECIAL_TYPE_OUTPUT;
6369}
6370
6371void OutputNode::compile(SVMCompiler &compiler)
6372{
6373 if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
6374 ShaderInput *displacement_in = input("Displacement");
6375
6376 if (displacement_in->link) {
6377 compiler.add_node(NODE_SET_DISPLACEMENT, compiler.stack_assign(displacement_in));
6378 }
6379 }
6380}
6381
6382void OutputNode::compile(OSLCompiler &compiler)
6383{
6384 if (compiler.output_type() == SHADER_TYPE_SURFACE) {
6385 compiler.add(this, "node_output_surface");
6386 }
6387 else if (compiler.output_type() == SHADER_TYPE_VOLUME) {
6388 compiler.add(this, "node_output_volume");
6389 }
6390 else if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
6391 compiler.add(this, "node_output_displacement");
6392 }
6393}
6394
6395/* Map Range Node */
6396
6398{
6399 NodeType *type = NodeType::add("map_range", create, NodeType::SHADER);
6400
6401 static NodeEnum type_enum;
6402 type_enum.insert("linear", NODE_MAP_RANGE_LINEAR);
6403 type_enum.insert("stepped", NODE_MAP_RANGE_STEPPED);
6404 type_enum.insert("smoothstep", NODE_MAP_RANGE_SMOOTHSTEP);
6405 type_enum.insert("smootherstep", NODE_MAP_RANGE_SMOOTHERSTEP);
6406 SOCKET_ENUM(range_type, "Type", type_enum, NODE_MAP_RANGE_LINEAR);
6407
6408 SOCKET_IN_FLOAT(value, "Value", 1.0f);
6409 SOCKET_IN_FLOAT(from_min, "From Min", 0.0f);
6410 SOCKET_IN_FLOAT(from_max, "From Max", 1.0f);
6411 SOCKET_IN_FLOAT(to_min, "To Min", 0.0f);
6412 SOCKET_IN_FLOAT(to_max, "To Max", 1.0f);
6413 SOCKET_IN_FLOAT(steps, "Steps", 4.0f);
6414 SOCKET_IN_BOOLEAN(clamp, "Clamp", false);
6415
6416 SOCKET_OUT_FLOAT(result, "Result");
6417
6418 return type;
6419}
6420
6421MapRangeNode::MapRangeNode() : ShaderNode(get_node_type()) {}
6422
6424{
6425 if (clamp) {
6426 ShaderOutput *result_out = output("Result");
6427 if (!result_out->links.empty()) {
6428 ClampNode *clamp_node = graph->create_node<ClampNode>();
6429 clamp_node->set_clamp_type(NODE_CLAMP_RANGE);
6430 graph->relink(result_out, clamp_node->output("Result"));
6431 graph->connect(result_out, clamp_node->input("Value"));
6432 if (input("To Min")->link) {
6433 graph->connect(input("To Min")->link, clamp_node->input("Min"));
6434 }
6435 else {
6436 clamp_node->set_min(to_min);
6437 }
6438 if (input("To Max")->link) {
6439 graph->connect(input("To Max")->link, clamp_node->input("Max"));
6440 }
6441 else {
6442 clamp_node->set_max(to_max);
6443 }
6444 }
6445 }
6446}
6447
6449{
6450 if (range_type != NODE_MAP_RANGE_LINEAR) {
6451 return false;
6452 }
6453
6454 ShaderInput *from_min_in = input("To Min");
6455 ShaderInput *from_max_in = input("To Max");
6456 ShaderInput *to_min_in = input("To Min");
6457 ShaderInput *to_max_in = input("To Max");
6458 return from_min_in->link == nullptr && from_max_in->link == nullptr &&
6459 to_min_in->link == nullptr && to_max_in->link == nullptr;
6460}
6461
6462void MapRangeNode::compile(SVMCompiler &compiler)
6463{
6464 ShaderInput *value_in = input("Value");
6465 ShaderInput *from_min_in = input("From Min");
6466 ShaderInput *from_max_in = input("From Max");
6467 ShaderInput *to_min_in = input("To Min");
6468 ShaderInput *to_max_in = input("To Max");
6469 ShaderInput *steps_in = input("Steps");
6470 ShaderOutput *result_out = output("Result");
6471
6472 const int value_stack_offset = compiler.stack_assign(value_in);
6473 const int from_min_stack_offset = compiler.stack_assign_if_linked(from_min_in);
6474 const int from_max_stack_offset = compiler.stack_assign_if_linked(from_max_in);
6475 const int to_min_stack_offset = compiler.stack_assign_if_linked(to_min_in);
6476 const int to_max_stack_offset = compiler.stack_assign_if_linked(to_max_in);
6477 const int steps_stack_offset = compiler.stack_assign(steps_in);
6478 const int result_stack_offset = compiler.stack_assign(result_out);
6479
6480 compiler.add_node(
6481 NODE_MAP_RANGE,
6482 value_stack_offset,
6483 compiler.encode_uchar4(
6484 from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset),
6485 compiler.encode_uchar4(range_type, steps_stack_offset, result_stack_offset));
6486
6487 compiler.add_node(__float_as_int(from_min),
6488 __float_as_int(from_max),
6489 __float_as_int(to_min),
6490 __float_as_int(to_max));
6491 compiler.add_node(__float_as_int(steps));
6492}
6493
6494void MapRangeNode::compile(OSLCompiler &compiler)
6495{
6496 compiler.parameter(this, "range_type");
6497 compiler.add(this, "node_map_range");
6498}
6499
6500/* Vector Map Range Node */
6501
6503{
6504 NodeType *type = NodeType::add("vector_map_range", create, NodeType::SHADER);
6505
6506 static NodeEnum type_enum;
6507 type_enum.insert("linear", NODE_MAP_RANGE_LINEAR);
6508 type_enum.insert("stepped", NODE_MAP_RANGE_STEPPED);
6509 type_enum.insert("smoothstep", NODE_MAP_RANGE_SMOOTHSTEP);
6510 type_enum.insert("smootherstep", NODE_MAP_RANGE_SMOOTHERSTEP);
6511 SOCKET_ENUM(range_type, "Type", type_enum, NODE_MAP_RANGE_LINEAR);
6512
6513 SOCKET_IN_VECTOR(vector, "Vector", zero_float3());
6514 SOCKET_IN_VECTOR(from_min, "From_Min_FLOAT3", zero_float3());
6515 SOCKET_IN_VECTOR(from_max, "From_Max_FLOAT3", one_float3());
6516 SOCKET_IN_VECTOR(to_min, "To_Min_FLOAT3", zero_float3());
6517 SOCKET_IN_VECTOR(to_max, "To_Max_FLOAT3", one_float3());
6518 SOCKET_IN_VECTOR(steps, "Steps_FLOAT3", make_float3(4.0f));
6519 SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
6520
6521 SOCKET_OUT_VECTOR(vector, "Vector");
6522
6523 return type;
6524}
6525
6526VectorMapRangeNode::VectorMapRangeNode() : ShaderNode(get_node_type()) {}
6527
6529
6531{
6532 if (range_type != NODE_MAP_RANGE_LINEAR) {
6533 return false;
6534 }
6535
6536 ShaderInput *from_min_in = input("From_Min_FLOAT3");
6537 ShaderInput *from_max_in = input("From_Max_FLOAT3");
6538 ShaderInput *to_min_in = input("To_Min_FLOAT3");
6539 ShaderInput *to_max_in = input("To_Max_FLOAT3");
6540 return from_min_in->link == nullptr && from_max_in->link == nullptr &&
6541 to_min_in->link == nullptr && to_max_in->link == nullptr;
6542}
6543
6545{
6546 ShaderInput *vector_in = input("Vector");
6547 ShaderInput *from_min_in = input("From_Min_FLOAT3");
6548 ShaderInput *from_max_in = input("From_Max_FLOAT3");
6549 ShaderInput *to_min_in = input("To_Min_FLOAT3");
6550 ShaderInput *to_max_in = input("To_Max_FLOAT3");
6551 ShaderInput *steps_in = input("Steps_FLOAT3");
6552 ShaderOutput *vector_out = output("Vector");
6553
6554 const int value_stack_offset = compiler.stack_assign(vector_in);
6555 const int from_min_stack_offset = compiler.stack_assign(from_min_in);
6556 const int from_max_stack_offset = compiler.stack_assign(from_max_in);
6557 const int to_min_stack_offset = compiler.stack_assign(to_min_in);
6558 const int to_max_stack_offset = compiler.stack_assign(to_max_in);
6559 const int steps_stack_offset = compiler.stack_assign(steps_in);
6560 const int result_stack_offset = compiler.stack_assign(vector_out);
6561
6562 compiler.add_node(
6563 NODE_VECTOR_MAP_RANGE,
6564 value_stack_offset,
6565 compiler.encode_uchar4(
6566 from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset),
6567 compiler.encode_uchar4(steps_stack_offset, use_clamp, range_type, result_stack_offset));
6568}
6569
6571{
6572 compiler.parameter(this, "range_type");
6573 compiler.parameter(this, "use_clamp");
6574 compiler.add(this, "node_vector_map_range");
6575}
6576
6577/* Clamp Node */
6578
6580{
6581 NodeType *type = NodeType::add("clamp", create, NodeType::SHADER);
6582
6583 static NodeEnum type_enum;
6584 type_enum.insert("minmax", NODE_CLAMP_MINMAX);
6585 type_enum.insert("range", NODE_CLAMP_RANGE);
6586 SOCKET_ENUM(clamp_type, "Type", type_enum, NODE_CLAMP_MINMAX);
6587
6588 SOCKET_IN_FLOAT(value, "Value", 1.0f);
6589 SOCKET_IN_FLOAT(min, "Min", 0.0f);
6590 SOCKET_IN_FLOAT(max, "Max", 1.0f);
6591
6592 SOCKET_OUT_FLOAT(result, "Result");
6593
6594 return type;
6595}
6596
6597ClampNode::ClampNode() : ShaderNode(get_node_type()) {}
6598
6600{
6601 if (folder.all_inputs_constant()) {
6602 if (clamp_type == NODE_CLAMP_RANGE && (min > max)) {
6603 folder.make_constant(clamp(value, max, min));
6604 }
6605 else {
6606 folder.make_constant(clamp(value, min, max));
6607 }
6608 }
6609}
6610
6611void ClampNode::compile(SVMCompiler &compiler)
6612{
6613 ShaderInput *value_in = input("Value");
6614 ShaderInput *min_in = input("Min");
6615 ShaderInput *max_in = input("Max");
6616 ShaderOutput *result_out = output("Result");
6617
6618 const int value_stack_offset = compiler.stack_assign(value_in);
6619 const int min_stack_offset = compiler.stack_assign(min_in);
6620 const int max_stack_offset = compiler.stack_assign(max_in);
6621 const int result_stack_offset = compiler.stack_assign(result_out);
6622
6623 compiler.add_node(NODE_CLAMP,
6624 value_stack_offset,
6625 compiler.encode_uchar4(min_stack_offset, max_stack_offset, clamp_type),
6626 result_stack_offset);
6628}
6629
6630void ClampNode::compile(OSLCompiler &compiler)
6631{
6632 compiler.parameter(this, "clamp_type");
6633 compiler.add(this, "node_clamp");
6634}
6635
6636/* AOV Output */
6637
6639{
6640 NodeType *type = NodeType::add("aov_output", create, NodeType::SHADER);
6641
6642 SOCKET_IN_COLOR(color, "Color", zero_float3());
6643 SOCKET_IN_FLOAT(value, "Value", 0.0f);
6644
6645 SOCKET_STRING(name, "AOV Name", ustring(""));
6646
6647 return type;
6648}
6649
6650OutputAOVNode::OutputAOVNode() : ShaderNode(get_node_type())
6651{
6652 special_type = SHADER_SPECIAL_TYPE_OUTPUT_AOV;
6653 offset = -1;
6654}
6655
6657{
6658 offset = scene->film->get_aov_offset(scene, name.string(), is_color);
6659 if (offset == -1) {
6660 offset = scene->film->get_aov_offset(scene, name.string(), is_color);
6661 }
6662
6663 if (offset == -1 || is_color) {
6664 input("Value")->disconnect();
6665 }
6666 if (offset == -1 || !is_color) {
6667 input("Color")->disconnect();
6668 }
6669}
6670
6671void OutputAOVNode::compile(SVMCompiler &compiler)
6672{
6673 assert(offset >= 0);
6674
6675 if (is_color) {
6676 compiler.add_node(NODE_AOV_COLOR, compiler.stack_assign(input("Color")), offset);
6677 }
6678 else {
6679 compiler.add_node(NODE_AOV_VALUE, compiler.stack_assign(input("Value")), offset);
6680 }
6681}
6682
6683void OutputAOVNode::compile(OSLCompiler & /*compiler*/)
6684{
6685 /* TODO */
6686}
6687
6688/* Math */
6689
6691{
6692 NodeType *type = NodeType::add("math", create, NodeType::SHADER);
6693
6694 static NodeEnum type_enum;
6695 type_enum.insert("add", NODE_MATH_ADD);
6696 type_enum.insert("subtract", NODE_MATH_SUBTRACT);
6697 type_enum.insert("multiply", NODE_MATH_MULTIPLY);
6698 type_enum.insert("divide", NODE_MATH_DIVIDE);
6699 type_enum.insert("multiply_add", NODE_MATH_MULTIPLY_ADD);
6700 type_enum.insert("sine", NODE_MATH_SINE);
6701 type_enum.insert("cosine", NODE_MATH_COSINE);
6702 type_enum.insert("tangent", NODE_MATH_TANGENT);
6703 type_enum.insert("sinh", NODE_MATH_SINH);
6704 type_enum.insert("cosh", NODE_MATH_COSH);
6705 type_enum.insert("tanh", NODE_MATH_TANH);
6706 type_enum.insert("arcsine", NODE_MATH_ARCSINE);
6707 type_enum.insert("arccosine", NODE_MATH_ARCCOSINE);
6708 type_enum.insert("arctangent", NODE_MATH_ARCTANGENT);
6709 type_enum.insert("power", NODE_MATH_POWER);
6710 type_enum.insert("logarithm", NODE_MATH_LOGARITHM);
6711 type_enum.insert("minimum", NODE_MATH_MINIMUM);
6712 type_enum.insert("maximum", NODE_MATH_MAXIMUM);
6713 type_enum.insert("round", NODE_MATH_ROUND);
6714 type_enum.insert("less_than", NODE_MATH_LESS_THAN);
6715 type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
6716 type_enum.insert("modulo", NODE_MATH_MODULO);
6717 type_enum.insert("floored_modulo", NODE_MATH_FLOORED_MODULO);
6718 type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
6719 type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
6720 type_enum.insert("floor", NODE_MATH_FLOOR);
6721 type_enum.insert("ceil", NODE_MATH_CEIL);
6722 type_enum.insert("fraction", NODE_MATH_FRACTION);
6723 type_enum.insert("trunc", NODE_MATH_TRUNC);
6724 type_enum.insert("snap", NODE_MATH_SNAP);
6725 type_enum.insert("wrap", NODE_MATH_WRAP);
6726 type_enum.insert("pingpong", NODE_MATH_PINGPONG);
6727 type_enum.insert("sqrt", NODE_MATH_SQRT);
6728 type_enum.insert("inversesqrt", NODE_MATH_INV_SQRT);
6729 type_enum.insert("sign", NODE_MATH_SIGN);
6730 type_enum.insert("exponent", NODE_MATH_EXPONENT);
6731 type_enum.insert("radians", NODE_MATH_RADIANS);
6732 type_enum.insert("degrees", NODE_MATH_DEGREES);
6733 type_enum.insert("smoothmin", NODE_MATH_SMOOTH_MIN);
6734 type_enum.insert("smoothmax", NODE_MATH_SMOOTH_MAX);
6735 type_enum.insert("compare", NODE_MATH_COMPARE);
6736 SOCKET_ENUM(math_type, "Type", type_enum, NODE_MATH_ADD);
6737
6738 SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
6739
6740 SOCKET_IN_FLOAT(value1, "Value1", 0.5f);
6741 SOCKET_IN_FLOAT(value2, "Value2", 0.5f);
6742 SOCKET_IN_FLOAT(value3, "Value3", 0.0f);
6743
6744 SOCKET_OUT_FLOAT(value, "Value");
6745
6746 return type;
6747}
6748
6749MathNode::MathNode() : ShaderNode(get_node_type()) {}
6750
6752{
6753 if (use_clamp) {
6754 ShaderOutput *result_out = output("Value");
6755 if (!result_out->links.empty()) {
6756 ClampNode *clamp_node = graph->create_node<ClampNode>();
6757 clamp_node->set_clamp_type(NODE_CLAMP_MINMAX);
6758 clamp_node->set_min(0.0f);
6759 clamp_node->set_max(1.0f);
6760 graph->relink(result_out, clamp_node->output("Result"));
6761 graph->connect(result_out, clamp_node->input("Value"));
6762 }
6763 }
6764}
6765
6767{
6768 if (folder.all_inputs_constant()) {
6769 folder.make_constant(svm_math(math_type, value1, value2, value3));
6770 }
6771 else {
6772 folder.fold_math(math_type);
6773 }
6774}
6775
6777{
6778 switch (math_type) {
6779 case NODE_MATH_ADD:
6780 case NODE_MATH_SUBTRACT:
6781 case NODE_MATH_MULTIPLY:
6783 break;
6784 case NODE_MATH_DIVIDE:
6785 return input("Value2")->link == nullptr;
6786 default:
6787 return false;
6788 }
6789
6790 int num_variable_inputs = 0;
6791 for (ShaderInput *input : inputs) {
6792 num_variable_inputs += (input->link) ? 1 : 0;
6793 }
6794 return num_variable_inputs <= 1;
6795}
6796
6797void MathNode::compile(SVMCompiler &compiler)
6798{
6799 ShaderInput *value1_in = input("Value1");
6800 ShaderInput *value2_in = input("Value2");
6801 ShaderInput *value3_in = input("Value3");
6802 ShaderOutput *value_out = output("Value");
6803
6804 const int value1_stack_offset = compiler.stack_assign(value1_in);
6805 const int value2_stack_offset = compiler.stack_assign(value2_in);
6806 const int value3_stack_offset = compiler.stack_assign(value3_in);
6807 const int value_stack_offset = compiler.stack_assign(value_out);
6808
6809 compiler.add_node(
6810 NODE_MATH,
6811 math_type,
6812 compiler.encode_uchar4(value1_stack_offset, value2_stack_offset, value3_stack_offset),
6813 value_stack_offset);
6814}
6815
6816void MathNode::compile(OSLCompiler &compiler)
6817{
6818 compiler.parameter(this, "math_type");
6819 compiler.add(this, "node_math");
6820}
6821
6822/* VectorMath */
6823
6825{
6826 NodeType *type = NodeType::add("vector_math", create, NodeType::SHADER);
6827
6828 static NodeEnum type_enum;
6829 type_enum.insert("add", NODE_VECTOR_MATH_ADD);
6830 type_enum.insert("subtract", NODE_VECTOR_MATH_SUBTRACT);
6831 type_enum.insert("multiply", NODE_VECTOR_MATH_MULTIPLY);
6832 type_enum.insert("divide", NODE_VECTOR_MATH_DIVIDE);
6833
6834 type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
6835 type_enum.insert("project", NODE_VECTOR_MATH_PROJECT);
6836 type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT);
6837 type_enum.insert("refract", NODE_VECTOR_MATH_REFRACT);
6838 type_enum.insert("faceforward", NODE_VECTOR_MATH_FACEFORWARD);
6839 type_enum.insert("multiply_add", NODE_VECTOR_MATH_MULTIPLY_ADD);
6840
6841 type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
6842
6843 type_enum.insert("distance", NODE_VECTOR_MATH_DISTANCE);
6844 type_enum.insert("length", NODE_VECTOR_MATH_LENGTH);
6845 type_enum.insert("scale", NODE_VECTOR_MATH_SCALE);
6846 type_enum.insert("normalize", NODE_VECTOR_MATH_NORMALIZE);
6847
6848 type_enum.insert("snap", NODE_VECTOR_MATH_SNAP);
6849 type_enum.insert("floor", NODE_VECTOR_MATH_FLOOR);
6850 type_enum.insert("ceil", NODE_VECTOR_MATH_CEIL);
6851 type_enum.insert("modulo", NODE_VECTOR_MATH_MODULO);
6852 type_enum.insert("wrap", NODE_VECTOR_MATH_WRAP);
6853 type_enum.insert("fraction", NODE_VECTOR_MATH_FRACTION);
6854 type_enum.insert("absolute", NODE_VECTOR_MATH_ABSOLUTE);
6855 type_enum.insert("power", NODE_VECTOR_MATH_POWER);
6856 type_enum.insert("sign", NODE_VECTOR_MATH_SIGN);
6857 type_enum.insert("minimum", NODE_VECTOR_MATH_MINIMUM);
6858 type_enum.insert("maximum", NODE_VECTOR_MATH_MAXIMUM);
6859
6860 type_enum.insert("sine", NODE_VECTOR_MATH_SINE);
6861 type_enum.insert("cosine", NODE_VECTOR_MATH_COSINE);
6862 type_enum.insert("tangent", NODE_VECTOR_MATH_TANGENT);
6863 SOCKET_ENUM(math_type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
6864
6865 SOCKET_IN_VECTOR(vector1, "Vector1", zero_float3());
6866 SOCKET_IN_VECTOR(vector2, "Vector2", zero_float3());
6867 SOCKET_IN_VECTOR(vector3, "Vector3", zero_float3());
6868 SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
6869
6870 SOCKET_OUT_FLOAT(value, "Value");
6871 SOCKET_OUT_VECTOR(vector, "Vector");
6872
6873 return type;
6874}
6875
6876VectorMathNode::VectorMathNode() : ShaderNode(get_node_type()) {}
6877
6879{
6880 float value = 0.0f;
6882
6883 if (folder.all_inputs_constant()) {
6884 svm_vector_math(&value, &vector, math_type, vector1, vector2, vector3, scale);
6885 if (folder.output == output("Value")) {
6886 folder.make_constant(value);
6887 }
6888 else if (folder.output == output("Vector")) {
6889 folder.make_constant(vector);
6890 }
6891 }
6892 else {
6893 folder.fold_vector_math(math_type);
6894 }
6895}
6896
6898{
6899 switch (math_type) {
6904 break;
6906 return input("Vector2")->link == nullptr;
6907 default:
6908 return false;
6909 }
6910
6911 int num_variable_inputs = 0;
6912 for (ShaderInput *input : inputs) {
6913 num_variable_inputs += (input->link) ? 1 : 0;
6914 }
6915 return num_variable_inputs <= 1;
6916}
6917
6919{
6920 ShaderInput *vector1_in = input("Vector1");
6921 ShaderInput *vector2_in = input("Vector2");
6922 ShaderInput *param1_in = input("Scale");
6923 ShaderOutput *value_out = output("Value");
6924 ShaderOutput *vector_out = output("Vector");
6925
6926 const int vector1_stack_offset = compiler.stack_assign(vector1_in);
6927 const int vector2_stack_offset = compiler.stack_assign(vector2_in);
6928 const int param1_stack_offset = compiler.stack_assign(param1_in);
6929 const int value_stack_offset = compiler.stack_assign_if_linked(value_out);
6930 const int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
6931
6932 /* 3 Vector Operators */
6933 if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD ||
6934 math_type == NODE_VECTOR_MATH_MULTIPLY_ADD)
6935 {
6936 ShaderInput *vector3_in = input("Vector3");
6937 const int vector3_stack_offset = compiler.stack_assign(vector3_in);
6938 compiler.add_node(
6939 NODE_VECTOR_MATH,
6940 math_type,
6941 compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset),
6942 compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
6943 compiler.add_node(vector3_stack_offset);
6944 }
6945 else {
6946 compiler.add_node(
6947 NODE_VECTOR_MATH,
6948 math_type,
6949 compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset),
6950 compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
6951 }
6952}
6953
6955{
6956 compiler.parameter(this, "math_type");
6957 compiler.add(this, "node_vector_math");
6958}
6959
6960/* Vector Rotate */
6961
6963{
6964 NodeType *type = NodeType::add("vector_rotate", create, NodeType::SHADER);
6965
6966 static NodeEnum type_enum;
6967 type_enum.insert("axis", NODE_VECTOR_ROTATE_TYPE_AXIS);
6968 type_enum.insert("x_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_X);
6969 type_enum.insert("y_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Y);
6970 type_enum.insert("z_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Z);
6971 type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ);
6972 SOCKET_ENUM(rotate_type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS);
6973
6974 SOCKET_BOOLEAN(invert, "Invert", false);
6975
6976 SOCKET_IN_VECTOR(vector, "Vector", zero_float3());
6977 SOCKET_IN_POINT(rotation, "Rotation", zero_float3());
6978 SOCKET_IN_POINT(center, "Center", zero_float3());
6979 SOCKET_IN_VECTOR(axis, "Axis", make_float3(0.0f, 0.0f, 1.0f));
6980 SOCKET_IN_FLOAT(angle, "Angle", 0.0f);
6981 SOCKET_OUT_VECTOR(vector, "Vector");
6982
6983 return type;
6984}
6985
6986VectorRotateNode::VectorRotateNode() : ShaderNode(get_node_type()) {}
6987
6989{
6990 ShaderInput *vector_in = input("Vector");
6991 ShaderInput *rotation_in = input("Rotation");
6992 ShaderInput *center_in = input("Center");
6993 ShaderInput *axis_in = input("Axis");
6994 ShaderInput *angle_in = input("Angle");
6995 ShaderOutput *vector_out = output("Vector");
6996
6997 compiler.add_node(NODE_VECTOR_ROTATE,
6998 compiler.encode_uchar4(rotate_type,
6999 compiler.stack_assign(vector_in),
7000 compiler.stack_assign(rotation_in),
7001 invert),
7002 compiler.encode_uchar4(compiler.stack_assign(center_in),
7003 compiler.stack_assign(axis_in),
7004 compiler.stack_assign(angle_in)),
7005 compiler.stack_assign(vector_out));
7006}
7007
7009{
7010 compiler.parameter(this, "rotate_type");
7011 compiler.parameter(this, "invert");
7012 compiler.add(this, "node_vector_rotate");
7013}
7014
7015/* VectorTransform */
7016
7018{
7019 NodeType *type = NodeType::add("vector_transform", create, NodeType::SHADER);
7020
7021 static NodeEnum type_enum;
7022 type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
7023 type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
7024 type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
7025 SOCKET_ENUM(transform_type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
7026
7027 static NodeEnum space_enum;
7031 SOCKET_ENUM(convert_from, "Convert From", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
7032 SOCKET_ENUM(convert_to, "Convert To", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
7033
7034 SOCKET_IN_VECTOR(vector, "Vector", zero_float3());
7035 SOCKET_OUT_VECTOR(vector, "Vector");
7036
7037 return type;
7038}
7039
7040VectorTransformNode::VectorTransformNode() : ShaderNode(get_node_type()) {}
7041
7043{
7044 ShaderInput *vector_in = input("Vector");
7045 ShaderOutput *vector_out = output("Vector");
7046
7047 compiler.add_node(
7048 NODE_VECTOR_TRANSFORM,
7049 compiler.encode_uchar4(transform_type, convert_from, convert_to),
7050 compiler.encode_uchar4(compiler.stack_assign(vector_in), compiler.stack_assign(vector_out)));
7051}
7052
7054{
7055 compiler.parameter(this, "transform_type");
7056 compiler.parameter(this, "convert_from");
7057 compiler.parameter(this, "convert_to");
7058 compiler.add(this, "node_vector_transform");
7059}
7060
7061/* BumpNode */
7062
7064{
7065 NodeType *type = NodeType::add("bump", create, NodeType::SHADER);
7066
7067 SOCKET_BOOLEAN(invert, "Invert", false);
7068 SOCKET_BOOLEAN(use_object_space, "UseObjectSpace", false);
7069
7070 /* this input is used by the user, but after graph transform it is no longer
7071 * used and moved to sampler center/x/y instead */
7072 SOCKET_IN_FLOAT(height, "Height", 1.0f);
7073
7074 SOCKET_IN_FLOAT(sample_center, "SampleCenter", 0.0f);
7075 SOCKET_IN_FLOAT(sample_x, "SampleX", 0.0f);
7076 SOCKET_IN_FLOAT(sample_y, "SampleY", 0.0f);
7078 SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
7079 SOCKET_IN_FLOAT(distance, "Distance", 0.1f);
7080 SOCKET_IN_FLOAT(filter_width, "Filter Width", 0.1f);
7081
7082 SOCKET_OUT_NORMAL(normal, "Normal");
7083
7084 return type;
7085}
7086
7087BumpNode::BumpNode() : ShaderNode(get_node_type())
7088{
7089 special_type = SHADER_SPECIAL_TYPE_BUMP;
7090}
7091
7092void BumpNode::compile(SVMCompiler &compiler)
7093{
7094 ShaderInput *center_in = input("SampleCenter");
7095 ShaderInput *dx_in = input("SampleX");
7096 ShaderInput *dy_in = input("SampleY");
7097 ShaderInput *normal_in = input("Normal");
7098 ShaderInput *strength_in = input("Strength");
7099 ShaderInput *distance_in = input("Distance");
7100 ShaderOutput *normal_out = output("Normal");
7101
7102 /* pack all parameters in the node */
7103 compiler.add_node(
7104 NODE_SET_BUMP,
7105 compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
7106 compiler.stack_assign(distance_in),
7107 invert,
7108 use_object_space),
7109 compiler.encode_uchar4(compiler.stack_assign(center_in),
7110 compiler.stack_assign(dx_in),
7111 compiler.stack_assign(dy_in),
7112 compiler.stack_assign(strength_in)),
7113 compiler.encode_uchar4(compiler.stack_assign(normal_out), compiler.get_bump_state_offset()));
7114 compiler.add_node(__float_as_uint(filter_width));
7115}
7116
7117void BumpNode::compile(OSLCompiler &compiler)
7118{
7119 compiler.parameter(this, "invert");
7120 compiler.parameter(this, "use_object_space");
7121 compiler.add(this, "node_bump");
7122}
7123
7125{
7126 ShaderInput *height_in = input("Height");
7127 ShaderInput *normal_in = input("Normal");
7128
7129 if (height_in->link == nullptr) {
7130 if (normal_in->link == nullptr) {
7131 GeometryNode *geom = folder.graph->create_node<GeometryNode>();
7132 folder.bypass(geom->output("Normal"));
7133 }
7134 else {
7135 folder.bypass(normal_in->link);
7136 }
7137 }
7138
7139 /* TODO(sergey): Ignore bump with zero strength. */
7140}
7141
7142/* Curves node */
7143
7144CurvesNode::CurvesNode(const NodeType *node_type) : ShaderNode(node_type) {}
7145
7147{
7148 ShaderInput *fac_in = input("Fac");
7149
7150 /* evaluate fully constant node */
7151 if (folder.all_inputs_constant()) {
7152 if (curves.size() == 0) {
7153 return;
7154 }
7155
7156 float3 pos = (value - make_float3(min_x, min_x, min_x)) / (max_x - min_x);
7157 float3 result;
7158
7159 result[0] = rgb_ramp_lookup(curves.data(), pos[0], true, extrapolate, curves.size()).x;
7160 result[1] = rgb_ramp_lookup(curves.data(), pos[1], true, extrapolate, curves.size()).y;
7161 result[2] = rgb_ramp_lookup(curves.data(), pos[2], true, extrapolate, curves.size()).z;
7162
7163 folder.make_constant(interp(value, result, fac));
7164 }
7165 /* remove no-op node */
7166 else if (!fac_in->link && fac == 0.0f) {
7167 /* link is not null because otherwise all inputs are constant */
7168 folder.bypass(value_in->link);
7169 }
7170}
7171
7173 const int type,
7174 ShaderInput *value_in,
7175 ShaderOutput *value_out)
7176{
7177 if (curves.size() == 0) {
7178 return;
7179 }
7180
7181 ShaderInput *fac_in = input("Fac");
7182
7183 compiler.add_node(ShaderNodeType(type),
7184 compiler.encode_uchar4(compiler.stack_assign(fac_in),
7185 compiler.stack_assign(value_in),
7186 compiler.stack_assign(value_out),
7187 extrapolate),
7188 __float_as_int(min_x),
7189 __float_as_int(max_x));
7190
7191 compiler.add_node(curves.size());
7192 for (int i = 0; i < curves.size(); i++) {
7193 compiler.add_node(make_float4(curves[i]));
7194 }
7195}
7196
7197void CurvesNode::compile(OSLCompiler &compiler, const char *name)
7198{
7199 if (curves.size() == 0) {
7200 return;
7201 }
7202
7203 compiler.parameter_color_array("ramp", curves);
7204 compiler.parameter(this, "min_x");
7205 compiler.parameter(this, "max_x");
7206 compiler.parameter(this, "extrapolate");
7207 compiler.add(this, name);
7208}
7209
7210void CurvesNode::compile(SVMCompiler & /*compiler*/)
7211{
7212 assert(0);
7213}
7214
7215void CurvesNode::compile(OSLCompiler & /*compiler*/)
7216{
7217 assert(0);
7218}
7219
7220/* RGBCurvesNode */
7221
7223{
7224 NodeType *type = NodeType::add("rgb_curves", create, NodeType::SHADER);
7225
7226 SOCKET_COLOR_ARRAY(curves, "Curves", array<float3>());
7227 SOCKET_FLOAT(min_x, "Min X", 0.0f);
7228 SOCKET_FLOAT(max_x, "Max X", 1.0f);
7229 SOCKET_BOOLEAN(extrapolate, "Extrapolate", true);
7230
7231 SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
7232 SOCKET_IN_COLOR(value, "Color", zero_float3());
7233
7234 SOCKET_OUT_COLOR(value, "Color");
7235
7236 return type;
7237}
7238
7239RGBCurvesNode::RGBCurvesNode() : CurvesNode(get_node_type()) {}
7240
7242{
7243 CurvesNode::constant_fold(folder, input("Color"));
7244}
7245
7246void RGBCurvesNode::compile(SVMCompiler &compiler)
7247{
7248 CurvesNode::compile(compiler, NODE_CURVES, input("Color"), output("Color"));
7249}
7250
7251void RGBCurvesNode::compile(OSLCompiler &compiler)
7252{
7253 CurvesNode::compile(compiler, "node_rgb_curves");
7254}
7255
7256/* VectorCurvesNode */
7257
7259{
7260 NodeType *type = NodeType::add("vector_curves", create, NodeType::SHADER);
7261
7262 SOCKET_VECTOR_ARRAY(curves, "Curves", array<float3>());
7263 SOCKET_FLOAT(min_x, "Min X", 0.0f);
7264 SOCKET_FLOAT(max_x, "Max X", 1.0f);
7265 SOCKET_BOOLEAN(extrapolate, "Extrapolate", true);
7266
7267 SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
7268 SOCKET_IN_VECTOR(value, "Vector", zero_float3());
7269
7270 SOCKET_OUT_VECTOR(value, "Vector");
7271
7272 return type;
7273}
7274
7275VectorCurvesNode::VectorCurvesNode() : CurvesNode(get_node_type()) {}
7276
7278{
7279 CurvesNode::constant_fold(folder, input("Vector"));
7280}
7281
7283{
7284 CurvesNode::compile(compiler, NODE_CURVES, input("Vector"), output("Vector"));
7285}
7286
7288{
7289 CurvesNode::compile(compiler, "node_vector_curves");
7290}
7291
7292/* FloatCurveNode */
7293
7295{
7296 NodeType *type = NodeType::add("float_curve", create, NodeType::SHADER);
7297
7298 SOCKET_FLOAT_ARRAY(curve, "Curve", array<float>());
7299 SOCKET_FLOAT(min_x, "Min X", 0.0f);
7300 SOCKET_FLOAT(max_x, "Max X", 1.0f);
7301 SOCKET_BOOLEAN(extrapolate, "Extrapolate", true);
7302
7303 SOCKET_IN_FLOAT(fac, "Factor", 0.0f);
7304 SOCKET_IN_FLOAT(value, "Value", 0.0f);
7305
7306 SOCKET_OUT_FLOAT(value, "Value");
7307
7308 return type;
7309}
7310
7311FloatCurveNode::FloatCurveNode() : ShaderNode(get_node_type()) {}
7312
7314{
7315 ShaderInput *value_in = input("Value");
7316 ShaderInput *fac_in = input("Factor");
7317
7318 /* evaluate fully constant node */
7319 if (folder.all_inputs_constant()) {
7320 if (curve.size() == 0) {
7321 return;
7322 }
7323
7324 const float pos = (value - min_x) / (max_x - min_x);
7325 const float result = float_ramp_lookup(curve.data(), pos, true, extrapolate, curve.size());
7326
7327 folder.make_constant(value + fac * (result - value));
7328 }
7329 /* remove no-op node */
7330 else if (!fac_in->link && fac == 0.0f) {
7331 /* link is not null because otherwise all inputs are constant */
7332 folder.bypass(value_in->link);
7333 }
7334}
7335
7337{
7338 if (curve.size() == 0) {
7339 return;
7340 }
7341
7342 ShaderInput *value_in = input("Value");
7343 ShaderInput *fac_in = input("Factor");
7344 ShaderOutput *value_out = output("Value");
7345
7346 compiler.add_node(NODE_FLOAT_CURVE,
7347 compiler.encode_uchar4(compiler.stack_assign(fac_in),
7348 compiler.stack_assign(value_in),
7349 compiler.stack_assign(value_out),
7350 extrapolate),
7351 __float_as_int(min_x),
7352 __float_as_int(max_x));
7353
7354 compiler.add_node(curve.size());
7355 for (int i = 0; i < curve.size(); i++) {
7356 compiler.add_node(make_float4(curve[i]));
7357 }
7358}
7359
7361{
7362 if (curve.size() == 0) {
7363 return;
7364 }
7365
7366 compiler.parameter_array("ramp", curve.data(), curve.size());
7367 compiler.parameter(this, "min_x");
7368 compiler.parameter(this, "max_x");
7369 compiler.parameter(this, "extrapolate");
7370 compiler.add(this, "node_float_curve");
7371}
7372
7373/* RGBRampNode */
7374
7376{
7377 NodeType *type = NodeType::add("rgb_ramp", create, NodeType::SHADER);
7378
7379 SOCKET_COLOR_ARRAY(ramp, "Ramp", array<float3>());
7380 SOCKET_FLOAT_ARRAY(ramp_alpha, "Ramp Alpha", array<float>());
7381 SOCKET_BOOLEAN(interpolate, "Interpolate", true);
7382
7383 SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
7384
7385 SOCKET_OUT_COLOR(color, "Color");
7386 SOCKET_OUT_FLOAT(alpha, "Alpha");
7387
7388 return type;
7389}
7390
7391RGBRampNode::RGBRampNode() : ShaderNode(get_node_type()) {}
7392
7394{
7395 if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) {
7396 return;
7397 }
7398
7399 if (folder.all_inputs_constant()) {
7400 const float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
7401
7402 /* clamp int as well in case of NaN */
7403 const int i = clamp((int)f, 0, ramp.size() - 1);
7404 const float t = f - (float)i;
7405
7406 const bool use_lerp = interpolate && t > 0.0f;
7407
7408 if (folder.output == output("Color")) {
7409 const float3 color = rgb_ramp_lookup(ramp.data(), fac, use_lerp, false, ramp.size());
7410 folder.make_constant(color);
7411 }
7412 else if (folder.output == output("Alpha")) {
7413 const float alpha = float_ramp_lookup(
7414 ramp_alpha.data(), fac, use_lerp, false, ramp_alpha.size());
7415 folder.make_constant(alpha);
7416 }
7417 }
7418}
7419
7420void RGBRampNode::compile(SVMCompiler &compiler)
7421{
7422 if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) {
7423 return;
7424 }
7425
7426 ShaderInput *fac_in = input("Fac");
7427 ShaderOutput *color_out = output("Color");
7428 ShaderOutput *alpha_out = output("Alpha");
7429
7430 compiler.add_node(NODE_RGB_RAMP,
7431 compiler.encode_uchar4(compiler.stack_assign(fac_in),
7432 compiler.stack_assign_if_linked(color_out),
7433 compiler.stack_assign_if_linked(alpha_out)),
7434 interpolate);
7435
7436 compiler.add_node(ramp.size());
7437 for (int i = 0; i < ramp.size(); i++) {
7438 compiler.add_node(make_float4(ramp[i], ramp_alpha[i]));
7439 }
7440}
7441
7442void RGBRampNode::compile(OSLCompiler &compiler)
7443{
7444 if (ramp.size() == 0 || ramp.size() != ramp_alpha.size()) {
7445 return;
7446 }
7447
7448 compiler.parameter_color_array("ramp_color", ramp);
7449 compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
7450 compiler.parameter(this, "interpolate");
7451
7452 compiler.add(this, "node_rgb_ramp");
7453}
7454
7455/* Set Normal Node */
7456
7458{
7459 NodeType *type = NodeType::add("set_normal", create, NodeType::SHADER);
7460
7461 SOCKET_IN_VECTOR(direction, "Direction", zero_float3());
7462 SOCKET_OUT_NORMAL(normal, "Normal");
7463
7464 return type;
7465}
7466
7467SetNormalNode::SetNormalNode() : ShaderNode(get_node_type()) {}
7468
7469void SetNormalNode::compile(SVMCompiler &compiler)
7470{
7471 ShaderInput *direction_in = input("Direction");
7472 ShaderOutput *normal_out = output("Normal");
7473
7474 compiler.add_node(NODE_CLOSURE_SET_NORMAL,
7475 compiler.stack_assign(direction_in),
7476 compiler.stack_assign(normal_out));
7477}
7478
7479void SetNormalNode::compile(OSLCompiler &compiler)
7480{
7481 compiler.add(this, "node_set_normal");
7482}
7483
7484/* OSLNode */
7485
7486OSLNode::OSLNode() : ShaderNode(new NodeType(NodeType::SHADER))
7487{
7488 special_type = SHADER_SPECIAL_TYPE_OSL;
7489 has_emission = false;
7490}
7491
7493{
7494 delete type;
7495}
7496
7498{
7499 return OSLNode::create(graph, this->inputs.size(), this);
7500}
7501
7503{
7504 /* the added geometry node's attributes function unfortunately doesn't
7505 * request the need for ATTR_STD_GENERATED in-time somehow, so we request it
7506 * here if there are any sockets that have LINK_TANGENT or
7507 * LINK_TEXTURE_GENERATED flags */
7508 if (shader->has_surface_link()) {
7509 for (const ShaderInput *in : inputs) {
7510 if (!in->link && (in->flags() & SocketType::LINK_TANGENT ||
7512 {
7514 break;
7515 }
7516 }
7517 }
7518
7520}
7521
7522OSLNode *OSLNode::create(ShaderGraph *graph, const size_t num_inputs, const OSLNode *from)
7523{
7524 /* allocate space for the node itself and parameters, aligned to 16 bytes
7525 * assuming that's the most parameter types need */
7526 const size_t node_size = align_up(sizeof(OSLNode), 16);
7527 const size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
7528
7529 char *node_memory = (char *)operator new(node_size + inputs_size);
7530 memset(node_memory, 0, node_size + inputs_size);
7531
7532 if (!from) {
7533 return graph->create_osl_node<OSLNode>(node_memory);
7534 }
7535 /* copy input default values and node type for cloning */
7536 memcpy(node_memory + node_size, (char *)from + node_size, inputs_size);
7537
7538 OSLNode *node = graph->create_osl_node<OSLNode>(node_memory, *from);
7539 node->type = new NodeType(*(from->type));
7540 return node;
7541}
7542
7544{
7545 /* pointer to default value storage, which is the same as our actual value */
7546 const size_t num_inputs = type->inputs.size();
7547 const size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
7548 return (char *)this + align_up(sizeof(OSLNode), 16) + inputs_size;
7549}
7550
7551void OSLNode::add_input(ustring name, SocketType::Type socket_type, const int flags)
7552{
7553 char *memory = input_default_value();
7554 const size_t offset = memory - (char *)this;
7555 const_cast<NodeType *>(type)->register_input(
7556 name, name, socket_type, offset, memory, nullptr, nullptr, flags | SocketType::LINKABLE);
7557}
7558
7560{
7561 const_cast<NodeType *>(type)->register_output(name, name, socket_type);
7562}
7563
7564void OSLNode::compile(SVMCompiler & /*compiler*/)
7565{
7566 /* doesn't work for SVM, obviously ... */
7567}
7568
7569void OSLNode::compile(OSLCompiler &compiler)
7570{
7571 if (!filepath.empty()) {
7572 compiler.add(this, filepath.c_str(), true);
7573 }
7574 else {
7575 compiler.add(this, bytecode_hash.c_str(), false);
7576 }
7577}
7578
7579/* Normal Map */
7580
7582{
7583 NodeType *type = NodeType::add("normal_map", create, NodeType::SHADER);
7584
7585 static NodeEnum space_enum;
7586 space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
7587 space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
7588 space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
7589 space_enum.insert("blender_object", NODE_NORMAL_MAP_BLENDER_OBJECT);
7590 space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
7591 SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
7592
7593 SOCKET_STRING(attribute, "Attribute", ustring());
7594
7595 SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
7596 SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f));
7597
7598 SOCKET_OUT_NORMAL(normal, "Normal");
7599
7600 return type;
7601}
7602
7603NormalMapNode::NormalMapNode() : ShaderNode(get_node_type()) {}
7604
7606{
7607 if (shader->has_surface_link() && space == NODE_NORMAL_MAP_TANGENT) {
7608 if (attribute.empty()) {
7609 /* We don't need the UV ourselves, but we need to compute the tangent from it. */
7610 attributes->add(ATTR_STD_UV);
7613 }
7614 else {
7615 attributes->add(attribute);
7616 attributes->add(ustring((string(attribute.c_str()) + ".undisplaced_tangent").c_str()));
7617 attributes->add(ustring((string(attribute.c_str()) + ".undisplaced_tangent_sign").c_str()));
7618 }
7619
7621 }
7622
7624}
7625
7626void NormalMapNode::compile(SVMCompiler &compiler)
7627{
7628 ShaderInput *color_in = input("Color");
7629 ShaderInput *strength_in = input("Strength");
7630 ShaderOutput *normal_out = output("Normal");
7631 int attr = 0;
7632 int attr_sign = 0;
7633
7634 if (space == NODE_NORMAL_MAP_TANGENT) {
7635 if (attribute.empty()) {
7637 attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN_UNDISPLACED);
7638 }
7639 else {
7640 attr = compiler.attribute(
7641 ustring((string(attribute.c_str()) + ".undisplaced_tangent").c_str()));
7642 attr_sign = compiler.attribute(
7643 ustring((string(attribute.c_str()) + ".undisplaced_tangent_sign").c_str()));
7644 }
7645 }
7646
7647 compiler.add_node(NODE_NORMAL_MAP,
7648 compiler.encode_uchar4(compiler.stack_assign(color_in),
7649 compiler.stack_assign(strength_in),
7650 compiler.stack_assign(normal_out),
7651 space),
7652 attr,
7653 attr_sign);
7654}
7655
7656void NormalMapNode::compile(OSLCompiler &compiler)
7657{
7658 if (space == NODE_NORMAL_MAP_TANGENT) {
7659 if (attribute.empty()) {
7660 compiler.parameter("attr_name", ustring("geom:undisplaced_tangent"));
7661 compiler.parameter("attr_sign_name", ustring("geom:undisplaced_tangent_sign"));
7662 }
7663 else {
7664 compiler.parameter("attr_name",
7665 ustring((string(attribute.c_str()) + ".undisplaced_tangent").c_str()));
7666 compiler.parameter(
7667 "attr_sign_name",
7668 ustring((string(attribute.c_str()) + ".undisplaced_tangent_sign").c_str()));
7669 }
7670 }
7671
7672 compiler.parameter(this, "space");
7673 compiler.add(this, "node_normal_map");
7674}
7675
7676/* Radial Tiling */
7677
7679{
7680 NodeType *type = NodeType::add("radial_tiling", create, NodeType::SHADER);
7681
7682 SOCKET_BOOLEAN(use_normalize, "Normalize", false);
7683 SOCKET_IN_POINT(vector, "Vector", zero_float3());
7684 SOCKET_IN_FLOAT(r_gon_sides, "Sides", 5.0f);
7685 SOCKET_IN_FLOAT(r_gon_roundness, "Roundness", 0.0f);
7686
7687 SOCKET_OUT_POINT(segment_coordinates, "Segment Coordinates");
7688 SOCKET_OUT_FLOAT(segment_id, "Segment ID");
7689 SOCKET_OUT_FLOAT(max_unit_parameter, "Segment Width");
7690 SOCKET_OUT_FLOAT(x_axis_A_angle_bisector, "Segment Rotation");
7691
7692 return type;
7693}
7694
7695RadialTilingNode::RadialTilingNode() : ShaderNode(get_node_type()) {}
7696
7698{
7699 ShaderInput *vector_in = input("Vector");
7700 ShaderInput *r_gon_sides_in = input("Sides");
7701 ShaderInput *r_gon_roundness_in = input("Roundness");
7702
7703 ShaderOutput *segment_coordinates_out = output("Segment Coordinates");
7704 ShaderOutput *segment_id_out = output("Segment ID");
7705 ShaderOutput *max_unit_parameter_out = output("Segment Width");
7706 ShaderOutput *x_axis_A_angle_bisector_out = output("Segment Rotation");
7707
7708 compiler.add_node(NODE_RADIAL_TILING,
7709 use_normalize,
7710 compiler.encode_uchar4(compiler.stack_assign(vector_in),
7711 compiler.stack_assign(r_gon_sides_in),
7712 compiler.stack_assign(r_gon_roundness_in),
7713 compiler.stack_assign(segment_coordinates_out)),
7714 compiler.encode_uchar4(compiler.stack_assign(segment_id_out),
7715 compiler.stack_assign(max_unit_parameter_out),
7716 compiler.stack_assign(x_axis_A_angle_bisector_out)));
7717}
7718
7720{
7721 compiler.parameter(this, "use_normalize");
7722 compiler.add(this, "node_radial_tiling");
7723}
7724
7725/* Tangent */
7726
7728{
7729 NodeType *type = NodeType::add("tangent", create, NodeType::SHADER);
7730
7731 static NodeEnum direction_type_enum;
7732 direction_type_enum.insert("radial", NODE_TANGENT_RADIAL);
7733 direction_type_enum.insert("uv_map", NODE_TANGENT_UVMAP);
7734 SOCKET_ENUM(direction_type, "Direction Type", direction_type_enum, NODE_TANGENT_RADIAL);
7735
7736 static NodeEnum axis_enum;
7737 axis_enum.insert("x", NODE_TANGENT_AXIS_X);
7738 axis_enum.insert("y", NODE_TANGENT_AXIS_Y);
7739 axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
7740 SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
7741
7742 SOCKET_STRING(attribute, "Attribute", ustring());
7743
7744 SOCKET_OUT_NORMAL(tangent, "Tangent");
7745
7746 return type;
7747}
7748
7749TangentNode::TangentNode() : ShaderNode(get_node_type()) {}
7750
7752{
7753 if (shader->has_surface_link()) {
7754 if (direction_type == NODE_TANGENT_UVMAP) {
7755 if (attribute.empty()) {
7756 /* We don't need the UV ourselves, but we need to compute the tangent from it. */
7757 attributes->add(ATTR_STD_UV);
7759 }
7760 else {
7761 attributes->add(attribute);
7762 attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7763 }
7764 }
7765 else {
7767 }
7768 }
7769
7771}
7772
7773void TangentNode::compile(SVMCompiler &compiler)
7774{
7775 ShaderOutput *tangent_out = output("Tangent");
7776 int attr;
7777
7778 if (direction_type == NODE_TANGENT_UVMAP) {
7779 if (attribute.empty()) {
7780 attr = compiler.attribute(ATTR_STD_UV_TANGENT);
7781 }
7782 else {
7783 attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7784 }
7785 }
7786 else {
7787 attr = compiler.attribute(ATTR_STD_GENERATED);
7788 }
7789
7790 compiler.add_node(
7791 NODE_TANGENT,
7792 compiler.encode_uchar4(compiler.stack_assign(tangent_out), direction_type, axis),
7793 attr);
7794}
7795
7796void TangentNode::compile(OSLCompiler &compiler)
7797{
7798 if (direction_type == NODE_TANGENT_UVMAP) {
7799 if (attribute.empty()) {
7800 compiler.parameter("attr_name", ustring("geom:tangent"));
7801 }
7802 else {
7803 compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
7804 }
7805 }
7806
7807 compiler.parameter(this, "direction_type");
7808 compiler.parameter(this, "axis");
7809 compiler.add(this, "node_tangent");
7810}
7811
7812/* Bevel */
7813
7815{
7816 NodeType *type = NodeType::add("bevel", create, NodeType::SHADER);
7817
7818 SOCKET_INT(samples, "Samples", 4);
7819
7820 SOCKET_IN_FLOAT(radius, "Radius", 0.05f);
7822
7823 SOCKET_OUT_NORMAL(bevel, "Normal");
7824
7825 return type;
7826}
7827
7828BevelNode::BevelNode() : ShaderNode(get_node_type()) {}
7829
7830void BevelNode::compile(SVMCompiler &compiler)
7831{
7832 ShaderInput *radius_in = input("Radius");
7833 ShaderInput *normal_in = input("Normal");
7834 ShaderOutput *normal_out = output("Normal");
7835
7836 compiler.add_node(NODE_BEVEL,
7837 compiler.encode_uchar4(samples,
7838 compiler.stack_assign(radius_in),
7839 compiler.stack_assign_if_linked(normal_in),
7840 compiler.stack_assign(normal_out)));
7841}
7842
7843void BevelNode::compile(OSLCompiler &compiler)
7844{
7845 compiler.parameter(this, "samples");
7846 compiler.add(this, "node_bevel");
7847}
7848
7849/* Displacement */
7850
7852{
7853 NodeType *type = NodeType::add("displacement", create, NodeType::SHADER);
7854
7855 static NodeEnum space_enum;
7856 space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
7857 space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
7858
7859 SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_OBJECT);
7860
7861 SOCKET_IN_FLOAT(height, "Height", 0.0f);
7862 SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.5f);
7863 SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
7865
7866 SOCKET_OUT_VECTOR(displacement, "Displacement");
7867
7868 return type;
7869}
7870
7871DisplacementNode::DisplacementNode() : ShaderNode(get_node_type()) {}
7872
7874{
7875 if (folder.all_inputs_constant()) {
7876 if ((height - midlevel == 0.0f) || (scale == 0.0f)) {
7877 folder.make_zero();
7878 }
7879 }
7880}
7881
7883{
7884 ShaderInput *height_in = input("Height");
7885 ShaderInput *midlevel_in = input("Midlevel");
7886 ShaderInput *scale_in = input("Scale");
7887 ShaderInput *normal_in = input("Normal");
7888 ShaderOutput *displacement_out = output("Displacement");
7889
7890 compiler.add_node(NODE_DISPLACEMENT,
7891 compiler.encode_uchar4(compiler.stack_assign(height_in),
7892 compiler.stack_assign(midlevel_in),
7893 compiler.stack_assign(scale_in),
7894 compiler.stack_assign_if_linked(normal_in)),
7895 compiler.stack_assign(displacement_out),
7896 space);
7897}
7898
7900{
7901 compiler.parameter(this, "space");
7902 compiler.add(this, "node_displacement");
7903}
7904
7905/* Vector Displacement */
7906
7908{
7909 NodeType *type = NodeType::add("vector_displacement", create, NodeType::SHADER);
7910
7911 static NodeEnum space_enum;
7912 space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
7913 space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
7914 space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
7915
7916 SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
7917 SOCKET_STRING(attribute, "Attribute", ustring());
7918
7919 SOCKET_IN_COLOR(vector, "Vector", zero_float3());
7920 SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
7921 SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
7922
7923 SOCKET_OUT_VECTOR(displacement, "Displacement");
7924
7925 return type;
7926}
7927
7928VectorDisplacementNode::VectorDisplacementNode() : ShaderNode(get_node_type()) {}
7929
7931{
7932 if (folder.all_inputs_constant()) {
7933 if ((vector == zero_float3() && midlevel == 0.0f) || (scale == 0.0f)) {
7934 folder.make_zero();
7935 }
7936 }
7937}
7938
7940{
7941 if (shader->has_surface_link() && space == NODE_NORMAL_MAP_TANGENT) {
7942 if (attribute.empty()) {
7943 attributes->add(ATTR_STD_UV);
7946 }
7947 else {
7948 attributes->add(attribute);
7949 attributes->add(ustring((string(attribute.c_str()) + ".undisplaced_tangent").c_str()));
7950 attributes->add(ustring((string(attribute.c_str()) + ".undisplaced_tangent_sign").c_str()));
7951 }
7952 }
7953
7955}
7956
7958{
7959 ShaderInput *vector_in = input("Vector");
7960 ShaderInput *midlevel_in = input("Midlevel");
7961 ShaderInput *scale_in = input("Scale");
7962 ShaderOutput *displacement_out = output("Displacement");
7963 int attr = 0;
7964 int attr_sign = 0;
7965
7966 if (space == NODE_NORMAL_MAP_TANGENT) {
7967 if (attribute.empty()) {
7969 attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN_UNDISPLACED);
7970 }
7971 else {
7972 attr = compiler.attribute(
7973 ustring((string(attribute.c_str()) + ".undisplaced_tangent").c_str()));
7974 attr_sign = compiler.attribute(
7975 ustring((string(attribute.c_str()) + ".undisplaced_tangent_sign").c_str()));
7976 }
7977 }
7978
7979 compiler.add_node(NODE_VECTOR_DISPLACEMENT,
7980 compiler.encode_uchar4(compiler.stack_assign(vector_in),
7981 compiler.stack_assign(midlevel_in),
7982 compiler.stack_assign(scale_in),
7983 compiler.stack_assign(displacement_out)),
7984 attr,
7985 attr_sign);
7986
7987 compiler.add_node(space);
7988}
7989
7991{
7992 if (space == NODE_NORMAL_MAP_TANGENT) {
7993 if (attribute.empty()) {
7994 compiler.parameter("attr_name", ustring("geom:undisplaced_tangent"));
7995 compiler.parameter("attr_sign_name", ustring("geom:undisplaced_tangent_sign"));
7996 }
7997 else {
7998 compiler.parameter("attr_name",
7999 ustring((string(attribute.c_str()) + ".undisplaced_tangent").c_str()));
8000 compiler.parameter(
8001 "attr_sign_name",
8002 ustring((string(attribute.c_str()) + ".undisplaced_tangent_sign").c_str()));
8003 }
8004 }
8005
8006 compiler.parameter(this, "space");
8007 compiler.add(this, "node_vector_displacement");
8008}
8009
KDTree *BLI_kdtree_nd_ new(unsigned int nodes_len_capacity)
Definition kdtree_impl.h:98
MINLINE float signf(float f)
unsigned int uint
@ NODE_VECTOR_MATH_NORMALIZE
@ NODE_VECTOR_MATH_LENGTH
@ NODE_VECTOR_MATH_SIGN
@ NODE_VECTOR_MATH_CROSS_PRODUCT
@ NODE_VECTOR_MATH_CEIL
@ NODE_VECTOR_MATH_MODULO
@ NODE_VECTOR_MATH_ADD
@ NODE_VECTOR_MATH_COSINE
@ NODE_VECTOR_MATH_REFLECT
@ NODE_VECTOR_MATH_WRAP
@ NODE_VECTOR_MATH_REFRACT
@ NODE_VECTOR_MATH_POWER
@ NODE_VECTOR_MATH_DOT_PRODUCT
@ NODE_VECTOR_MATH_ABSOLUTE
@ NODE_VECTOR_MATH_DIVIDE
@ NODE_VECTOR_MATH_TANGENT
@ NODE_VECTOR_MATH_DISTANCE
@ NODE_VECTOR_MATH_FLOOR
@ NODE_VECTOR_MATH_SNAP
@ NODE_VECTOR_MATH_SINE
@ NODE_VECTOR_MATH_FRACTION
@ NODE_VECTOR_MATH_PROJECT
@ NODE_VECTOR_MATH_MULTIPLY
@ NODE_VECTOR_MATH_SCALE
@ NODE_VECTOR_MATH_MAXIMUM
@ NODE_VECTOR_MATH_FACEFORWARD
@ NODE_VECTOR_MATH_SUBTRACT
@ NODE_VECTOR_MATH_MULTIPLY_ADD
@ NODE_VECTOR_MATH_MINIMUM
@ NODE_MATH_SINH
@ NODE_MATH_SMOOTH_MIN
@ NODE_MATH_TRUNC
@ NODE_MATH_COSH
@ NODE_MATH_SIGN
@ NODE_MATH_DEGREES
@ NODE_MATH_MODULO
@ NODE_MATH_ABSOLUTE
@ NODE_MATH_DIVIDE
@ NODE_MATH_SINE
@ NODE_MATH_FLOORED_MODULO
@ NODE_MATH_ARCTAN2
@ NODE_MATH_ARCCOSINE
@ NODE_MATH_MULTIPLY_ADD
@ NODE_MATH_POWER
@ NODE_MATH_WRAP
@ NODE_MATH_ARCTANGENT
@ NODE_MATH_MINIMUM
@ NODE_MATH_SQRT
@ NODE_MATH_CEIL
@ NODE_MATH_TANH
@ NODE_MATH_GREATER_THAN
@ NODE_MATH_ADD
@ NODE_MATH_FRACTION
@ NODE_MATH_EXPONENT
@ NODE_MATH_LESS_THAN
@ NODE_MATH_ARCSINE
@ NODE_MATH_MAXIMUM
@ NODE_MATH_LOGARITHM
@ NODE_MATH_COMPARE
@ NODE_MATH_INV_SQRT
@ NODE_MATH_MULTIPLY
@ NODE_MATH_PINGPONG
@ NODE_MATH_ROUND
@ NODE_MATH_FLOOR
@ NODE_MATH_SUBTRACT
@ NODE_MATH_COSINE
@ NODE_MATH_SNAP
@ NODE_MATH_TANGENT
@ NODE_MATH_SMOOTH_MAX
@ NODE_MATH_RADIANS
@ NODE_CLAMP_RANGE
@ NODE_CLAMP_MINMAX
@ NODE_VECTOR_ROTATE_TYPE_AXIS
@ NODE_VECTOR_ROTATE_TYPE_AXIS_Z
@ NODE_VECTOR_ROTATE_TYPE_AXIS_X
@ NODE_VECTOR_ROTATE_TYPE_EULER_XYZ
@ NODE_VECTOR_ROTATE_TYPE_AXIS_Y
@ NODE_COMBSEP_COLOR_RGB
@ NODE_COMBSEP_COLOR_HSV
@ NODE_COMBSEP_COLOR_HSL
@ NODE_MAP_RANGE_STEPPED
@ NODE_MAP_RANGE_SMOOTHERSTEP
@ NODE_MAP_RANGE_SMOOTHSTEP
@ NODE_MAP_RANGE_LINEAR
@ NODE_MAPPING_TYPE_POINT
@ NODE_MAPPING_TYPE_VECTOR
@ NODE_MAPPING_TYPE_TEXTURE
@ NODE_MAPPING_TYPE_NORMAL
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
void constant_fold(const ConstantFolder &folder) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
ClosureType closure
bool has_bump() override
BsdfBaseNode(const NodeType *node_type)
BsdfNode(const NodeType *node_type)
void compile(SVMCompiler &compiler, ShaderInput *bsdf_y, ShaderInput *bsdf_z, ShaderInput *data_y=nullptr, ShaderInput *data_z=nullptr, ShaderInput *data_w=nullptr)
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
static bool colorspace_is_data(ustring colorspace)
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
void make_one() const
void discard() const
void bypass(ShaderOutput *output) const
void bypass_or_discard(ShaderInput *input) const
void fold_mapping(NodeMappingType type) const
ShaderGraph *const graph
void fold_mix_float(bool clamp_factor, bool clamp) const
bool all_inputs_constant() const
bool try_bypass_or_make_constant(ShaderInput *input, bool clamp=false) const
void make_zero() const
bool is_zero(ShaderInput *input) const
bool is_one(ShaderInput *input) const
void fold_math(NodeMathType type) const
void make_constant(const float value) const
ShaderOutput *const output
void fold_mix(NodeMix type, bool clamp) const
void make_constant_clamp(const float value, bool clamp) const
void fold_vector_math(NodeVectorMathType type) const
void fold_mix_color(NodeMix type, bool clamp_factor, bool clamp) const
float value_float
void constant_fold(const ConstantFolder &folder) override
float3 value_vector
ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert=false)
float3 value_color
void compile(SVMCompiler &compiler, const int type, ShaderInput *value_in, ShaderOutput *value_out)
CurvesNode(const NodeType *node_type)
void constant_fold(const ConstantFolder &folder, ShaderInput *value_in)
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
ShaderNode * clone(ShaderGraph *graph) const override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
ImageParams image_params() const
int get_aov_offset(Scene *scene, string name, bool &is_color)
Definition film.cpp:454
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
virtual void get_uv_tiles(ustring map, unordered_set< int > &tiles)=0
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void simplify_settings(Scene *scene) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
ShaderNode * clone(ShaderGraph *graph) const override
~IESLightNode() override
bool empty() const
ImageHandle add_image(const string &filename, const ImageParams &params)
bool is_float() const
InterpolationType interpolation
ExtensionType extension
ImageParams image_params() const
void cull_tiles(Scene *scene, ShaderGraph *graph)
ShaderNode * clone(ShaderGraph *graph) const override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void constant_fold(const ConstantFolder &folder) override
int add_ies_from_file(const string &filename)
bool is_linear_operation() override
void expand(ShaderGraph *graph) override
void constant_fold(const ConstantFolder &folder) override
void expand(ShaderGraph *graph) override
void constant_fold(const ConstantFolder &folder) override
bool is_linear_operation() override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void simplify_settings(Scene *scene) override
void constant_fold(const ConstantFolder &folder) override
bool is_linear_operation() override
void constant_fold(const ConstantFolder &folder) override
bool is_linear_operation() override
void constant_fold(const ConstantFolder &folder) override
bool is_linear_operation() override
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
bool is_linear_operation() override
bool is_linear_operation() override
void constant_fold(const ConstantFolder &folder) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void parameter_array(const char *name, const float f[], int arraylen)
Definition osl.cpp:1658
void add(ShaderNode *node, const char *name, bool isfilepath=false)
Definition osl.cpp:1636
ShaderType output_type()
Definition scene/osl.h:181
void parameter_texture(const char *name, ustring filename, ustring colorspace)
Definition osl.cpp:1662
void parameter(ShaderNode *node, const char *name)
Definition osl.cpp:1638
bool background
Definition scene/osl.h:186
void parameter_color_array(const char *name, const array< float3 > &f)
Definition osl.cpp:1660
void parameter_texture_ies(const char *name, const int svm_slot)
Definition osl.cpp:1670
Scene * scene
Definition scene/osl.h:187
void parameter_color(const char *name, const float3 f)
Definition osl.cpp:1642
string bytecode_hash
void add_input(ustring name, SocketType::Type type, const int flags=0)
static OSLNode * create(ShaderGraph *graph, const size_t num_inputs, const OSLNode *from=nullptr)
void add_output(ustring name, SocketType::Type type)
~OSLNode() override
ShaderNode * clone(ShaderGraph *graph) const override
char * input_default_value()
void attributes(Shader *shader, AttributeRequestSet *attributes) override
string filepath
void simplify_settings(Scene *scene) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
bool has_surface_bssrdf() override
void simplify_settings(Scene *scene) override
bool has_nonzero_weight(const char *name)
bool has_surface_transparent() override
bool has_bssrdf_bump() override
bool has_surface_emission() override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
bool has_surface_transparent() override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
ShaderGraph * current_graph
Definition scene/svm.h:119
bool background
Definition scene/svm.h:120
int stack_assign_if_not_equal(ShaderInput *input, const float value)
Definition svm.cpp:313
int stack_find_offset(const int size)
Definition svm.cpp:193
uint encode_uchar4(const uint x, const uint y=0, const uint z=0, const uint w=0)
Definition svm.cpp:391
int stack_assign_if_linked(ShaderInput *input)
Definition svm.cpp:295
uint attribute_standard(ustring name)
Definition svm.cpp:435
void add_node(ShaderNodeType type, const int a=0, const int b=0, const int c=0)
Definition svm.cpp:406
void stack_link(ShaderInput *input, ShaderOutput *output)
Definition svm.cpp:331
ShaderType output_type()
Definition scene/svm.h:113
uint closure_mix_weight_offset()
Definition scene/svm.h:104
bool is_linked(ShaderInput *input)
Definition svm.cpp:290
uint get_bump_state_offset()
Definition scene/svm.h:108
uint attribute(ustring name)
Definition svm.cpp:425
void stack_clear_offset(SocketType::Type type, const int offset)
Definition svm.cpp:232
Scene * scene
Definition scene/svm.h:118
int stack_assign(ShaderOutput *output)
Definition svm.cpp:280
ScatterVolumeNode(const NodeType *node_type)
bool background
Definition scene.h:76
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
T * create_node(Args &&...args)
void connect(ShaderOutput *from, ShaderInput *to)
void relink(ShaderInput *from, ShaderInput *to)
T * create_osl_node(void *node_memory, Args &&...args)
SocketType::Type type() const
ShaderOutput * link
const SocketType & socket_type
ShaderInput * input(const char *name)
ShaderNodeSpecialType special_type
float bump_filter_width
void disconnect_unused_input(const char *name)
ShaderNode(const NodeType *type)
unique_ptr_vector< ShaderInput > inputs
ShaderBump bump
ShaderOutput * output(const char *name)
virtual void compile(SVMCompiler &compiler)=0
virtual void attributes(Shader *shader, AttributeRequestSet *attributes)
unique_ptr_vector< ShaderOutput > outputs
vector< ShaderInput * > links
ShaderNode * parent
bool has_surface_link() const
bool has_volume
bool has_surface
NODE_DECLARE unique_ptr< ShaderGraph > graph
float get_sun_size()
void simplify_settings(Scene *scene) override
ImageHandle handle
float get_sun_average_radiance()
bool has_bssrdf_bump() override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
Transform compute_transform()
void compile(SVMCompiler &compiler, const int offset_in, const int offset_out)
void compile_end(SVMCompiler &compiler, ShaderInput *vector_in, const int vector_offset)
Mapping x_mapping
Mapping z_mapping
Mapping y_mapping
int compile_begin(SVMCompiler &compiler, ShaderInput *vector_in)
TextureMapping tex_mapping
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void constant_fold(const ConstantFolder &folder) override
void constant_fold(const ConstantFolder &folder) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void constant_fold(const ConstantFolder &folder) override
bool is_linear_operation() override
void expand(ShaderGraph *graph) override
void constant_fold(const ConstantFolder &folder) override
bool is_linear_operation() override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void attributes(Shader *shader, AttributeRequestSet *attributes) override
void expand(ShaderGraph *graph) override
ClosureType closure
void compile(SVMCompiler &compiler, ShaderInput *density, ShaderInput *param1=nullptr, ShaderInput *param2=nullptr)
VolumeNode(const NodeType *node_type)
void push_back_slow(const T &t)
nullptr float
ccl_device float3 svm_separate_color(NodeCombSepColorType type, const float3 color)
Definition color_util.h:396
ccl_device_noinline_cpu float3 svm_mix(NodeMix type, const float t, const float3 c1, const float3 c2)
Definition color_util.h:309
ccl_device float3 svm_combine_color(NodeCombSepColorType type, const float3 color)
Definition color_util.h:383
ccl_device_noinline_cpu float3 svm_mix_clamped_factor(NodeMix type, const float t, const float3 c1, const float3 c2)
Definition color_util.h:360
ccl_device_inline float3 svm_brightness_contrast(float3 color, const float brightness, const float contrast)
Definition color_util.h:369
CCL_NAMESPACE_BEGIN ustring u_colorspace_auto
reduce_max(value.rgb)") DEFINE_VALUE("REDUCE(lhs
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
static float get_float(PointerRNA &ptr, const char *name)
#define M_PI_2_F
#define M_SQRT2_F
#define SVM_STACK_INVALID
#define expf(x)
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define fmodf(x, y)
#define acosf(x)
#define copysignf(x, y)
#define __float_as_int(x)
#define __float_as_uint(x)
#define CLOSURE_WEIGHT_CUTOFF
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
IMETHOD void random(Vector &a)
addDelta operator for displacement rotational velocity.
Definition frames.inl:1282
uint pos
uint col
#define input
#define assert(assertion)
#define in
#define out
#define output
constexpr T clamp(T, U, U) RET
float distance(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, 3 > float3
VecBase< int, 4 > int4
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
CCL_NAMESPACE_BEGIN ccl_device float invert(const float color, const float factor)
Definition invert.h:11
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
const ccl_global KernelWorkTile * tile
@ NODE_ENVIRONMENT_MIRROR_BALL
@ NODE_ENVIRONMENT_EQUIRECTANGULAR
@ NODE_INFO_OB_INDEX
@ NODE_INFO_MAT_INDEX
@ NODE_INFO_OB_RANDOM
@ NODE_INFO_OB_COLOR
@ NODE_INFO_OB_LOCATION
@ NODE_INFO_OB_ALPHA
@ NODE_ATTR_OUTPUT_FLOAT
@ NODE_ATTR_OUTPUT_FLOAT_ALPHA
@ NODE_ATTR_OUTPUT_FLOAT3
ShaderNodeType
NodeBumpOffset
@ NODE_BUMP_OFFSET_DY
@ NODE_BUMP_OFFSET_CENTER
@ NODE_BUMP_OFFSET_DX
@ NODE_WAVE_BANDS_DIRECTION_Z
@ NODE_WAVE_BANDS_DIRECTION_DIAGONAL
@ NODE_WAVE_BANDS_DIRECTION_Y
@ NODE_WAVE_BANDS_DIRECTION_X
@ NODE_INFO_CURVE_IS_STRAND
@ NODE_INFO_CURVE_TANGENT_NORMAL
@ NODE_INFO_CURVE_THICKNESS
@ NODE_PRINCIPLED_HAIR_CHIANG
@ NODE_PRINCIPLED_HAIR_HUANG
@ NODE_NOISE_FBM
@ NODE_NOISE_HYBRID_MULTIFRACTAL
@ NODE_NOISE_RIDGED_MULTIFRACTAL
@ NODE_NOISE_HETERO_TERRAIN
@ NODE_NOISE_MULTIFRACTAL
@ NODE_AO_INSIDE
@ NODE_AO_GLOBAL_RADIUS
@ NODE_AO_ONLY_LOCAL
@ NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT
@ NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD
@ NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA
@ NODE_GABOR_TYPE_2D
@ NODE_GABOR_TYPE_3D
@ NODE_TANGENT_AXIS_Y
@ NODE_TANGENT_AXIS_X
@ NODE_TANGENT_AXIS_Z
@ NODE_PRINCIPLED_HAIR_REFLECTANCE
@ NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION
@ NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION
@ NODE_TEXCO_VOLUME_GENERATED
@ NODE_TEXCO_REFLECTION
@ NODE_TEXCO_WINDOW
@ NODE_TEXCO_OBJECT
@ NODE_TEXCO_DUPLI_UV
@ NODE_TEXCO_OBJECT_WITH_TRANSFORM
@ NODE_TEXCO_DUPLI_GENERATED
@ NODE_TEXCO_CAMERA
@ NODE_TEXCO_NORMAL
@ SHADER_TYPE_SURFACE
@ SHADER_TYPE_VOLUME
@ SHADER_TYPE_DISPLACEMENT
@ NODE_VORONOI_SMOOTH_F1
@ NODE_VORONOI_N_SPHERE_RADIUS
@ NODE_VORONOI_F1
@ NODE_VORONOI_F2
@ NODE_VORONOI_DISTANCE_TO_EDGE
@ NODE_GEOM_N
@ NODE_GEOM_T
@ NODE_GEOM_uv
@ NODE_GEOM_P
@ NODE_GEOM_Ng
@ NODE_GEOM_I
@ NODE_INFO_PAR_SIZE
@ NODE_INFO_PAR_LOCATION
@ NODE_INFO_PAR_RANDOM
@ NODE_INFO_PAR_VELOCITY
@ NODE_INFO_PAR_INDEX
@ NODE_INFO_PAR_ANGULAR_VELOCITY
@ NODE_INFO_PAR_AGE
@ NODE_INFO_PAR_LIFETIME
@ NODE_WAVE_BANDS
@ NODE_WAVE_RINGS
@ NODE_IMAGE_COMPRESS_AS_SRGB
@ NODE_IMAGE_ALPHA_UNASSOCIATE
@ NODE_VORONOI_EUCLIDEAN
@ NODE_VORONOI_MANHATTAN
@ NODE_VORONOI_CHEBYCHEV
@ NODE_VORONOI_MINKOWSKI
@ NODE_SKY_SINGLE_SCATTERING
@ NODE_SKY_PREETHAM
@ NODE_SKY_MULTIPLE_SCATTERING
@ NODE_SKY_HOSEK
@ NODE_WAVE_PROFILE_TRI
@ NODE_WAVE_PROFILE_SIN
@ NODE_WAVE_PROFILE_SAW
@ NODE_MIX_DIV
@ NODE_MIX_SOFT
@ NODE_MIX_CLAMP
@ NODE_MIX_COL
@ NODE_MIX_LIGHT
@ NODE_MIX_MUL
@ NODE_MIX_DIFF
@ NODE_MIX_BURN
@ NODE_MIX_SUB
@ NODE_MIX_LINEAR
@ NODE_MIX_DARK
@ NODE_MIX_SAT
@ NODE_MIX_EXCLUSION
@ NODE_MIX_SCREEN
@ NODE_MIX_HUE
@ NODE_MIX_BLEND
@ NODE_MIX_OVERLAY
@ NODE_MIX_DODGE
@ NODE_MIX_VAL
@ NODE_MIX_ADD
@ NODE_LP_ray_depth
@ NODE_LP_shadow
@ NODE_LP_backfacing
@ NODE_LP_ray_glossy
@ NODE_LP_camera
@ NODE_LP_glossy
@ NODE_LP_transmission
@ NODE_LP_singular
@ NODE_LP_diffuse
@ NODE_LP_ray_diffuse
@ NODE_LP_volume_scatter
@ NODE_LP_ray_transmission
@ NODE_LP_ray_length
@ NODE_LP_ray_transparent
@ NODE_LP_reflection
@ NODE_LP_ray_portal
@ CLOSURE_VOLUME_RAYLEIGH_ID
@ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID
@ CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID
@ CLOSURE_VOLUME_MIE_ID
@ CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID
@ CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID
@ CLOSURE_BSDF_DIFFUSE_ID
@ CLOSURE_BSSRDF_BURLEY_ID
@ CLOSURE_BSDF_PRINCIPLED_ID
@ CLOSURE_BSDF_SHEEN_ID
@ CLOSURE_BSDF_TRANSPARENT_ID
@ CLOSURE_BSDF_DIFFUSE_TOON_ID
@ CLOSURE_VOLUME_DRAINE_ID
@ CLOSURE_BSDF_MICROFACET_GGX_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID
@ CLOSURE_BSDF_HAIR_TRANSMISSION_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID
@ CLOSURE_VOLUME_FOURNIER_FORAND_ID
@ CLOSURE_BSSRDF_RANDOM_WALK_ID
@ CLOSURE_BSDF_PHYSICAL_CONDUCTOR
@ CLOSURE_BSDF_HAIR_HUANG_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID
@ CLOSURE_BSDF_F82_CONDUCTOR
@ CLOSURE_BSDF_RAY_PORTAL_ID
@ CLOSURE_BSDF_GLOSSY_TOON_ID
@ CLOSURE_BSDF_HAIR_CHIANG_ID
@ CLOSURE_VOLUME_ABSORPTION_ID
@ CLOSURE_BSDF_HAIR_REFLECTION_ID
@ CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID
@ CLOSURE_BSDF_TRANSLUCENT_ID
@ CLOSURE_BSDF_ASHIKHMIN_VELVET_ID
@ NODE_INFO_POINT_RADIUS
@ NODE_INFO_POINT_POSITION
@ NODE_VECTOR_TRANSFORM_TYPE_NORMAL
@ NODE_VECTOR_TRANSFORM_TYPE_VECTOR
@ NODE_VECTOR_TRANSFORM_TYPE_POINT
@ NODE_IMAGE_PROJ_SPHERE
@ NODE_IMAGE_PROJ_TUBE
@ NODE_IMAGE_PROJ_BOX
@ NODE_IMAGE_PROJ_FLAT
@ NODE_BLEND_QUADRATIC
@ NODE_BLEND_DIAGONAL
@ NODE_BLEND_EASING
@ NODE_BLEND_RADIAL
@ NODE_BLEND_SPHERICAL
@ NODE_BLEND_QUADRATIC_SPHERE
@ NODE_BLEND_LINEAR
@ NODE_TANGENT_RADIAL
@ NODE_TANGENT_UVMAP
@ NODE_WAVE_RINGS_DIRECTION_Y
@ NODE_WAVE_RINGS_DIRECTION_SPHERICAL
@ NODE_WAVE_RINGS_DIRECTION_X
@ NODE_WAVE_RINGS_DIRECTION_Z
@ NODE_LAYER_WEIGHT_FACING
@ NODE_LAYER_WEIGHT_FRESNEL
@ NODE_NORMAL_MAP_TANGENT
@ NODE_NORMAL_MAP_WORLD
@ NODE_NORMAL_MAP_BLENDER_WORLD
@ NODE_NORMAL_MAP_BLENDER_OBJECT
@ NODE_NORMAL_MAP_OBJECT
@ NODE_CONVERT_IF
@ NODE_CONVERT_CI
@ NODE_CONVERT_CF
@ NODE_CONVERT_VF
@ NODE_CONVERT_VI
@ NODE_CONVERT_FI
@ NODE_CONVERT_IV
@ NODE_CONVERT_FV
@ NODE_LIGHT_FALLOFF_QUADRATIC
@ NODE_LIGHT_FALLOFF_LINEAR
@ NODE_LIGHT_FALLOFF_CONSTANT
AttributeStandard
@ ATTR_STD_CURVE_INTERCEPT
@ ATTR_STD_GENERATED_TRANSFORM
@ ATTR_STD_UV
@ ATTR_STD_VOLUME_TEMPERATURE
@ ATTR_STD_VERTEX_NORMAL
@ ATTR_STD_UV_TANGENT
@ ATTR_STD_NONE
@ ATTR_STD_POINT_RANDOM
@ ATTR_STD_VERTEX_COLOR
@ ATTR_STD_VOLUME_DENSITY
@ ATTR_STD_VOLUME_FLAME
@ ATTR_STD_PTEX_FACE_ID
@ ATTR_STD_VOLUME_COLOR
@ ATTR_STD_NORMAL_UNDISPLACED
@ ATTR_STD_UV_TANGENT_SIGN
@ ATTR_STD_CURVE_RANDOM
@ ATTR_STD_UV_TANGENT_SIGN_UNDISPLACED
@ ATTR_STD_UV_TANGENT_UNDISPLACED
@ ATTR_STD_PTEX_UV
@ ATTR_STD_POINTINESS
@ ATTR_STD_GENERATED
@ ATTR_STD_CURVE_LENGTH
@ ATTR_STD_RANDOM_PER_ISLAND
@ ATTR_STD_PARTICLE
static char ** types
Definition makesdna.cc:71
CCL_NAMESPACE_BEGIN ccl_device float3 svm_mapping(NodeMappingType type, const float3 vector, const float3 location, const float3 rotation, const float3 scale)
ccl_device_inline float interp(const float a, const float b, const float t)
Definition math_base.h:502
ccl_device_inline float3 one_float3()
Definition math_float3.h:26
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
CCL_NAMESPACE_BEGIN ccl_device void svm_vector_math(ccl_private float *value, ccl_private float3 *vector, NodeVectorMathType type, const float3 a, const float3 b, const float3 c, float param1)
Definition math_util.h:15
ccl_device float svm_math(NodeMathType type, const float a, float b, const float c)
Definition math_util.h:117
ccl_device float3 svm_math_blackbody_color_rec709(const float t)
Definition math_util.h:207
ccl_device_inline float3 svm_math_gamma_color(float3 color, const float gamma)
Definition math_util.h:241
#define T
#define R
#define T2
Definition md5.cpp:21
#define vector3
float average(point a)
Definition node_math.h:144
color rgb_ramp_lookup(color ramp[], float at, int interpolate, int extrapolate)
static blender::bke::bNodeSocketTemplate outputs[]
static blender::bke::bNodeSocketTemplate inputs[]
#define SOCKET_IN_NORMAL(name, ui_name, default_value,...)
Definition node_type.h:345
#define SOCKET_OUT_POINT(name, ui_name)
Definition node_type.h:392
#define SOCKET_OUT_FLOAT(name, ui_name)
Definition node_type.h:380
#define SOCKET_OUT_COLOR(name, ui_name)
Definition node_type.h:384
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition node_type.h:211
#define SOCKET_INT(name, ui_name, default_value,...)
Definition node_type.h:205
#define SOCKET_IN_COLOR(name, ui_name, default_value,...)
Definition node_type.h:321
#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:259
#define SOCKET_TRANSFORM(name, ui_name, default_value,...)
Definition node_type.h:225
#define SOCKET_OUT_NORMAL(name, ui_name)
Definition node_type.h:396
#define SOCKET_IN_FLOAT(name, ui_name, default_value,...)
Definition node_type.h:313
#define SOCKET_IN_CLOSURE(name, ui_name,...)
Definition node_type.h:361
#define SOCKET_OFFSETOF(T, name)
Definition node_type.h:186
#define SOCKET_INT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:257
#define SOCKET_VECTOR_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:265
#define SOCKET_IN_VECTOR(name, ui_name, default_value,...)
Definition node_type.h:329
#define NODE_DEFINE(structname)
Definition node_type.h:152
#define SOCKET_VECTOR(name, ui_name, default_value,...)
Definition node_type.h:215
#define SOCKET_IN_POINT(name, ui_name, default_value,...)
Definition node_type.h:337
#define SOCKET_COLOR_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:262
#define SOCKET_COLOR(name, ui_name, default_value,...)
Definition node_type.h:213
#define SOCKET_OUT_VECTOR(name, ui_name)
Definition node_type.h:388
#define SOCKET_IN_STRING(name, ui_name, default_value,...)
Definition node_type.h:353
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition node_type.h:203
#define SOCKET_IN_BOOLEAN(name, ui_name, default_value,...)
Definition node_type.h:302
#define SOCKET_STRING(name, ui_name, default_value,...)
Definition node_type.h:223
#define SOCKET_ENUM(name, ui_name, values, default_value,...)
Definition node_type.h:227
#define SOCKET_OUT_CLOSURE(name, ui_name)
Definition node_type.h:400
const char * name
#define sqr
#define fabsf
#define M_2PI_F
#define make_float2
#define tanf
#define make_float4
#define M_PI_F
#define cosf
#define atan2f
ccl_device_inline float float_ramp_lookup(KernelGlobals kg, const int offset, float f, bool interpolate, bool extrapolate, const int table_size)
Definition ramp.h:19
ustring u_colorspace_raw
@ SHADER_SPECIAL_TYPE_LIGHT_PATH
@ SHADER_SPECIAL_TYPE_PROXY
@ SHADER_SPECIAL_TYPE_GEOMETRY
@ SHADER_SPECIAL_TYPE_OUTPUT_AOV
@ SHADER_SPECIAL_TYPE_COMBINE_CLOSURE
@ SHADER_SPECIAL_TYPE_BUMP
@ SHADER_SPECIAL_TYPE_AUTOCONVERT
@ SHADER_SPECIAL_TYPE_OUTPUT
@ SHADER_SPECIAL_TYPE_CLOSURE
@ SHADER_SPECIAL_TYPE_OSL
@ SHADER_BUMP_DX
@ SHADER_BUMP_DY
static float2 sky_spherical_coordinates(const float3 dir)
static void sky_texture_precompute_hosek(SunSky *sunsky, const float3 dir, float turbidity, const float ground_albedo)
static void sky_texture_precompute_preetham(SunSky *sunsky, const float3 dir, const float turbidity)
static void sky_texture_precompute_nishita(SunSky *sunsky, bool multiple_scattering, bool sun_disc, const float sun_size, const float sun_intensity, const float sun_elevation, const float sun_rotation, const float altitude, const float air_density, const float aerosol_density, const float ozone_density)
static float sky_perez_function(const float lam[6], float theta, const float gamma)
#define TEXTURE_MAPPING_DEFINE(TextureNode)
void SKY_arhosekskymodelstate_free(SKY_ArHosekSkyModelState *state)
SKY_ArHosekSkyModelState * SKY_arhosek_xyz_skymodelstate_alloc_init(const double turbidity, const double albedo, const double elevation)
float3 sun_direction(float sun_cos_theta)
Definition sky_math.h:457
void SKY_single_scattering_precompute_sun(float sun_elevation, float angular_diameter, float altitude, float air_density, float aerosol_density, float r_pixel_bottom[3], float r_pixel_top[3])
void SKY_multiple_scattering_precompute_sun(float sun_elevation, float angular_diameter, float altitude, float air_density, float aerosol_density, float ozone_density, float r_pixel_bottom[3], float r_pixel_top[3])
float SKY_earth_intersection_angle(float altitude)
#define saturate(a)
Definition smaa.cc:315
#define min(a, b)
Definition sort.cc:36
bool string_endswith(const string_view s, const string_view end)
Definition string.cpp:120
static AttributeStandard name_standard(const char *name)
void insert(const char *x, const int y)
Definition node_enum.h:21
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=nullptr)
float get_float(const SocketType &input) const
const NodeType * type
Definition graph/node.h:178
float3 get_float3(const SocketType &input) const
ustring name
Definition graph/node.h:177
SKY_ArHosekSkyModelConfiguration configs[11]
Definition sky_hosek.h:312
Film * film
Definition scene.h:128
unique_ptr< LightManager > light_manager
Definition scene.h:146
SceneParams params
Definition scene.h:168
unique_ptr_vector< Geometry > geometry
Definition scene.h:140
unique_ptr< ShaderManager > shader_manager
Definition scene.h:148
unique_ptr< ImageManager > image_manager
Definition scene.h:145
static size_t max_size()
Definition node_type.cpp:93
static bool is_float3(Type type)
static ustring type_name(Type type)
static void * zero_default_value()
Definition node_type.cpp:98
@ LINK_TEXTURE_UV
Definition node_type.h:70
@ LINK_TEXTURE_GENERATED
Definition node_type.h:68
@ LINK_TEXTURE_INCOMING
Definition node_type.h:71
@ LINK_POSITION
Definition node_type.h:74
float config_z[9]
float config_x[9]
float radiance_y
float radiance_z
float nishita_data[11]
float config_y[9]
float theta
float radiance_x
float4 y
Definition transform.h:23
float4 x
Definition transform.h:23
float4 z
Definition transform.h:23
float x
float y
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
@ IMAGE_ALPHA_ASSOCIATED
Definition texture.h:60
@ IMAGE_ALPHA_CHANNEL_PACKED
Definition texture.h:61
@ IMAGE_ALPHA_AUTO
Definition texture.h:63
@ IMAGE_ALPHA_IGNORE
Definition texture.h:62
@ IMAGE_ALPHA_UNASSOCIATED
Definition texture.h:59
@ INTERPOLATION_LINEAR
Definition texture.h:24
@ INTERPOLATION_SMART
Definition texture.h:27
@ INTERPOLATION_CLOSEST
Definition texture.h:25
@ INTERPOLATION_CUBIC
Definition texture.h:26
@ EXTENSION_REPEAT
Definition texture.h:73
@ EXTENSION_CLIP
Definition texture.h:77
@ EXTENSION_EXTEND
Definition texture.h:75
@ EXTENSION_MIRROR
Definition texture.h:79
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
CCL_NAMESPACE_BEGIN Transform transform_transposed_inverse(const Transform &tfm)
Definition transform.cpp:15
ccl_device_inline Transform transform_identity()
Definition transform.h:322
ccl_device_inline Transform transform_scale(const float3 s)
Definition transform.h:280
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:525
ccl_device_inline Transform transform_translate(const float3 t)
Definition transform.h:270
ccl_device_inline Transform transform_euler(const float3 euler)
Definition transform.h:315
ccl_device_inline size_t divide_up(const size_t x, const size_t y)
Definition types_base.h:52
ccl_device_inline size_t align_up(const size_t offset, const size_t alignment)
Definition types_base.h:47