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