Blender  V3.3
shader_nodes.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "scene/shader_nodes.h"
5 #include "scene/colorspace.h"
6 #include "scene/constant_fold.h"
7 #include "scene/film.h"
8 #include "scene/image.h"
9 #include "scene/image_sky.h"
10 #include "scene/integrator.h"
11 #include "scene/light.h"
12 #include "scene/mesh.h"
13 #include "scene/osl.h"
14 #include "scene/scene.h"
15 #include "scene/svm.h"
16 
17 #include "sky_model.h"
18 
19 #include "util/color.h"
20 #include "util/foreach.h"
21 #include "util/log.h"
22 #include "util/transform.h"
23 
24 #include "kernel/tables.h"
25 
26 #include "kernel/svm/color_util.h"
28 #include "kernel/svm/math_util.h"
29 #include "kernel/svm/ramp_util.h"
30 
32 
33 /* Texture Mapping */
34 
35 #define TEXTURE_MAPPING_DEFINE(TextureNode) \
36  SOCKET_POINT(tex_mapping.translation, "Translation", zero_float3()); \
37  SOCKET_VECTOR(tex_mapping.rotation, "Rotation", zero_float3()); \
38  SOCKET_VECTOR(tex_mapping.scale, "Scale", one_float3()); \
39 \
40  SOCKET_VECTOR(tex_mapping.min, "Min", make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); \
41  SOCKET_VECTOR(tex_mapping.max, "Max", make_float3(FLT_MAX, FLT_MAX, FLT_MAX)); \
42  SOCKET_BOOLEAN(tex_mapping.use_minmax, "Use Min Max", false); \
43 \
44  static NodeEnum mapping_axis_enum; \
45  mapping_axis_enum.insert("none", TextureMapping::NONE); \
46  mapping_axis_enum.insert("x", TextureMapping::X); \
47  mapping_axis_enum.insert("y", TextureMapping::Y); \
48  mapping_axis_enum.insert("z", TextureMapping::Z); \
49  SOCKET_ENUM(tex_mapping.x_mapping, "x_mapping", mapping_axis_enum, TextureMapping::X); \
50  SOCKET_ENUM(tex_mapping.y_mapping, "y_mapping", mapping_axis_enum, TextureMapping::Y); \
51  SOCKET_ENUM(tex_mapping.z_mapping, "z_mapping", mapping_axis_enum, TextureMapping::Z); \
52 \
53  static NodeEnum mapping_type_enum; \
54  mapping_type_enum.insert("point", TextureMapping::POINT); \
55  mapping_type_enum.insert("texture", TextureMapping::TEXTURE); \
56  mapping_type_enum.insert("vector", TextureMapping::VECTOR); \
57  mapping_type_enum.insert("normal", TextureMapping::NORMAL); \
58  SOCKET_ENUM(tex_mapping.type, "Type", mapping_type_enum, TextureMapping::TEXTURE); \
59 \
60  static NodeEnum mapping_projection_enum; \
61  mapping_projection_enum.insert("flat", TextureMapping::FLAT); \
62  mapping_projection_enum.insert("cube", TextureMapping::CUBE); \
63  mapping_projection_enum.insert("tube", TextureMapping::TUBE); \
64  mapping_projection_enum.insert("sphere", TextureMapping::SPHERE); \
65  SOCKET_ENUM(tex_mapping.projection, "Projection", mapping_projection_enum, TextureMapping::FLAT);
66 
68 {
69 }
70 
72 {
74 
75  if (x_mapping != NONE)
76  mmat[0][x_mapping - 1] = 1.0f;
77  if (y_mapping != NONE)
78  mmat[1][y_mapping - 1] = 1.0f;
79  if (z_mapping != NONE)
80  mmat[2][z_mapping - 1] = 1.0f;
81 
82  float3 scale_clamped = scale;
83 
84  if (type == TEXTURE || type == NORMAL) {
85  /* keep matrix invertible */
86  if (fabsf(scale.x) < 1e-5f)
87  scale_clamped.x = signf(scale.x) * 1e-5f;
88  if (fabsf(scale.y) < 1e-5f)
89  scale_clamped.y = signf(scale.y) * 1e-5f;
90  if (fabsf(scale.z) < 1e-5f)
91  scale_clamped.z = signf(scale.z) * 1e-5f;
92  }
93 
94  Transform smat = transform_scale(scale_clamped);
97 
98  Transform mat;
99 
100  switch (type) {
101  case TEXTURE:
102  /* inverse transform on texture coordinate gives
103  * forward transform on texture */
104  mat = tmat * rmat * smat;
105  mat = transform_inverse(mat);
106  break;
107  case POINT:
108  /* full transform */
109  mat = tmat * rmat * smat;
110  break;
111  case VECTOR:
112  /* no translation for vectors */
113  mat = rmat * smat;
114  break;
115  case NORMAL:
116  /* no translation for normals, and inverse transpose */
117  mat = rmat * smat;
118  mat = transform_transposed_inverse(mat);
119  break;
120  }
121 
122  /* projection last */
123  mat = mat * mmat;
124 
125  return mat;
126 }
127 
129 {
130  if (translation != zero_float3())
131  return false;
132  if (rotation != zero_float3())
133  return false;
134  if (scale != one_float3())
135  return false;
136 
137  if (x_mapping != X || y_mapping != Y || z_mapping != Z)
138  return false;
139  if (use_minmax)
140  return false;
141 
142  return true;
143 }
144 
145 void TextureMapping::compile(SVMCompiler &compiler, int offset_in, int offset_out)
146 {
147  compiler.add_node(NODE_TEXTURE_MAPPING, offset_in, offset_out);
148 
150  compiler.add_node(tfm.x);
151  compiler.add_node(tfm.y);
152  compiler.add_node(tfm.z);
153 
154  if (use_minmax) {
155  compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
156  compiler.add_node(float3_to_float4(min));
157  compiler.add_node(float3_to_float4(max));
158  }
159 
160  if (type == NORMAL) {
161  compiler.add_node(NODE_VECTOR_MATH,
163  compiler.encode_uchar4(offset_out, offset_out, offset_out),
164  compiler.encode_uchar4(SVM_STACK_INVALID, offset_out));
165  }
166 }
167 
168 /* Convenience function for texture nodes, allocating stack space to output
169  * a modified vector and returning its offset */
171 {
172  if (!skip()) {
173  int offset_in = compiler.stack_assign(vector_in);
174  int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
175 
176  compile(compiler, offset_in, offset_out);
177 
178  return offset_out;
179  }
180 
181  return compiler.stack_assign(vector_in);
182 }
183 
184 void TextureMapping::compile_end(SVMCompiler &compiler, ShaderInput *vector_in, int vector_offset)
185 {
186  if (!skip()) {
187  compiler.stack_clear_offset(vector_in->type(), vector_offset);
188  }
189 }
190 
192 {
193  if (!skip()) {
194  compiler.parameter("mapping", compute_transform());
195  compiler.parameter("use_mapping", 1);
196  }
197 }
198 
199 /* Image Texture */
200 
202 {
203  NodeType *type = NodeType::add("image_texture", create, NodeType::SHADER);
204 
206 
207  SOCKET_STRING(filename, "Filename", ustring());
208  SOCKET_STRING(colorspace, "Colorspace", u_colorspace_auto);
209 
210  static NodeEnum alpha_type_enum;
211  alpha_type_enum.insert("auto", IMAGE_ALPHA_AUTO);
212  alpha_type_enum.insert("unassociated", IMAGE_ALPHA_UNASSOCIATED);
213  alpha_type_enum.insert("associated", IMAGE_ALPHA_ASSOCIATED);
214  alpha_type_enum.insert("channel_packed", IMAGE_ALPHA_CHANNEL_PACKED);
215  alpha_type_enum.insert("ignore", IMAGE_ALPHA_IGNORE);
216  SOCKET_ENUM(alpha_type, "Alpha Type", alpha_type_enum, IMAGE_ALPHA_AUTO);
217 
218  static NodeEnum interpolation_enum;
219  interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
220  interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
221  interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
222  interpolation_enum.insert("smart", INTERPOLATION_SMART);
223  SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
224 
225  static NodeEnum extension_enum;
226  extension_enum.insert("periodic", EXTENSION_REPEAT);
227  extension_enum.insert("clamp", EXTENSION_EXTEND);
228  extension_enum.insert("black", EXTENSION_CLIP);
229  SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT);
230 
231  static NodeEnum projection_enum;
232  projection_enum.insert("flat", NODE_IMAGE_PROJ_FLAT);
233  projection_enum.insert("box", NODE_IMAGE_PROJ_BOX);
234  projection_enum.insert("sphere", NODE_IMAGE_PROJ_SPHERE);
235  projection_enum.insert("tube", NODE_IMAGE_PROJ_TUBE);
236  SOCKET_ENUM(projection, "Projection", projection_enum, NODE_IMAGE_PROJ_FLAT);
237 
238  SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f);
239 
240  SOCKET_INT_ARRAY(tiles, "Tiles", array<int>());
241  SOCKET_BOOLEAN(animated, "Animated", false);
242 
244 
245  SOCKET_OUT_COLOR(color, "Color");
246  SOCKET_OUT_FLOAT(alpha, "Alpha");
247 
248  return type;
249 }
250 
251 ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(get_node_type())
252 {
253  colorspace = u_colorspace_raw;
254  animated = false;
255  tiles.push_back_slow(1001);
256 }
257 
259 {
260  ImageTextureNode *node = graph->create_node<ImageTextureNode>(*this);
261  node->handle = handle;
262  return node;
263 }
264 
266 {
268  params.animated = animated;
269  params.interpolation = interpolation;
270  params.extension = extension;
271  params.alpha_type = alpha_type;
272  params.colorspace = colorspace;
273  return params;
274 }
275 
277 {
278  /* Box projection computes its own UVs that always lie in the
279  * 1001 tile, so there's no point in loading any others. */
280  if (projection == NODE_IMAGE_PROJ_BOX) {
281  tiles.clear();
282  tiles.push_back_slow(1001);
283  return;
284  }
285 
286  if (!scene->params.background) {
287  /* During interactive renders, all tiles are loaded.
288  * While we could support updating this when UVs change, that could lead
289  * to annoying interruptions when loading images while editing UVs. */
290  return;
291  }
292 
293  /* Only check UVs for tile culling if there are multiple tiles. */
294  if (tiles.size() < 2) {
295  return;
296  }
297 
298  ShaderInput *vector_in = input("Vector");
299  ustring attribute;
300  if (vector_in->link) {
301  ShaderNode *node = vector_in->link->parent;
302  if (node->type == UVMapNode::get_node_type()) {
303  UVMapNode *uvmap = (UVMapNode *)node;
304  attribute = uvmap->get_attribute();
305  }
306  else if (node->type == TextureCoordinateNode::get_node_type()) {
307  if (vector_in->link != node->output("UV")) {
308  return;
309  }
310  }
311  else {
312  return;
313  }
314  }
315 
316  unordered_set<int> used_tiles;
317  /* TODO(lukas): This is quite inefficient. A fairly simple improvement would
318  * be to have a cache in each mesh that is indexed by attribute.
319  * Additionally, building a graph-to-meshes list once could help. */
320  foreach (Geometry *geom, scene->geometry) {
321  foreach (Node *node, geom->get_used_shaders()) {
322  Shader *shader = static_cast<Shader *>(node);
323  if (shader->graph == graph) {
324  geom->get_uv_tiles(attribute, used_tiles);
325  }
326  }
327  }
328 
329  array<int> new_tiles;
330  foreach (int tile, tiles) {
331  if (used_tiles.count(tile)) {
332  new_tiles.push_back_slow(tile);
333  }
334  }
335  tiles.steal_data(new_tiles);
336 }
337 
339 {
340 #ifdef WITH_PTEX
341  /* todo: avoid loading other texture coordinates when using ptex,
342  * and hide texture coordinate socket in the UI */
343  if (shader->has_surface_link() && string_endswith(filename, ".ptx")) {
344  /* ptex */
347  }
348 #endif
349 
351 }
352 
354 {
355  ShaderInput *vector_in = input("Vector");
356  ShaderOutput *color_out = output("Color");
357  ShaderOutput *alpha_out = output("Alpha");
358 
359  if (handle.empty()) {
360  cull_tiles(compiler.scene, compiler.current_graph);
361  ImageManager *image_manager = compiler.scene->image_manager;
362  handle = image_manager->add_image(filename.string(), image_params(), tiles);
363  }
364 
365  /* All tiles have the same metadata. */
366  const ImageMetaData metadata = handle.metadata();
367  const bool compress_as_srgb = metadata.compress_as_srgb;
368  const ustring known_colorspace = metadata.colorspace;
369 
370  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
371  uint flags = 0;
372 
373  if (compress_as_srgb) {
375  }
376  if (!alpha_out->links.empty()) {
377  const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
378  alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
379  alpha_type == IMAGE_ALPHA_IGNORE);
380 
381  if (unassociate_alpha) {
383  }
384  }
385 
386  if (projection != NODE_IMAGE_PROJ_BOX) {
387  /* If there only is one image (a very common case), we encode it as a negative value. */
388  int num_nodes;
389  if (handle.num_tiles() == 1) {
390  num_nodes = -handle.svm_slot();
391  }
392  else {
393  num_nodes = divide_up(handle.num_tiles(), 2);
394  }
395 
396  compiler.add_node(NODE_TEX_IMAGE,
397  num_nodes,
398  compiler.encode_uchar4(vector_offset,
400  compiler.stack_assign_if_linked(alpha_out),
401  flags),
402  projection);
403 
404  if (num_nodes > 0) {
405  for (int i = 0; i < num_nodes; i++) {
406  int4 node;
407  node.x = tiles[2 * i];
408  node.y = handle.svm_slot(2 * i);
409  if (2 * i + 1 < tiles.size()) {
410  node.z = tiles[2 * i + 1];
411  node.w = handle.svm_slot(2 * i + 1);
412  }
413  else {
414  node.z = -1;
415  node.w = -1;
416  }
417  compiler.add_node(node.x, node.y, node.z, node.w);
418  }
419  }
420  }
421  else {
422  assert(handle.num_tiles() == 1);
423  compiler.add_node(NODE_TEX_IMAGE_BOX,
424  handle.svm_slot(),
425  compiler.encode_uchar4(vector_offset,
427  compiler.stack_assign_if_linked(alpha_out),
428  flags),
429  __float_as_int(projection_blend));
430  }
431 
432  tex_mapping.compile_end(compiler, vector_in, vector_offset);
433 }
434 
436 {
437  ShaderOutput *alpha_out = output("Alpha");
438 
439  tex_mapping.compile(compiler);
440 
441  if (handle.empty()) {
442  ImageManager *image_manager = compiler.scene->image_manager;
443  handle = image_manager->add_image(filename.string(), image_params());
444  }
445 
446  const ImageMetaData metadata = handle.metadata();
447  const bool is_float = metadata.is_float();
448  const bool compress_as_srgb = metadata.compress_as_srgb;
449  const ustring known_colorspace = metadata.colorspace;
450 
451  if (handle.svm_slot() == -1) {
452  compiler.parameter_texture(
453  "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace);
454  }
455  else {
456  compiler.parameter_texture("filename", handle);
457  }
458 
459  const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
460  alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
461  alpha_type == IMAGE_ALPHA_IGNORE);
462  const bool is_tiled = (filename.find("<UDIM>") != string::npos ||
463  filename.find("<UVTILE>") != string::npos) ||
464  handle.num_tiles() > 1;
465 
466  compiler.parameter(this, "projection");
467  compiler.parameter(this, "projection_blend");
468  compiler.parameter("compress_as_srgb", compress_as_srgb);
469  compiler.parameter("ignore_alpha", alpha_type == IMAGE_ALPHA_IGNORE);
470  compiler.parameter("unassociate_alpha", !alpha_out->links.empty() && unassociate_alpha);
471  compiler.parameter("is_float", is_float);
472  compiler.parameter("is_tiled", is_tiled);
473  compiler.parameter(this, "interpolation");
474  compiler.parameter(this, "extension");
475 
476  compiler.add(this, "node_image_texture");
477 }
478 
479 /* Environment Texture */
480 
482 {
483  NodeType *type = NodeType::add("environment_texture", create, NodeType::SHADER);
484 
486 
487  SOCKET_STRING(filename, "Filename", ustring());
488  SOCKET_STRING(colorspace, "Colorspace", u_colorspace_auto);
489 
490  static NodeEnum alpha_type_enum;
491  alpha_type_enum.insert("auto", IMAGE_ALPHA_AUTO);
492  alpha_type_enum.insert("unassociated", IMAGE_ALPHA_UNASSOCIATED);
493  alpha_type_enum.insert("associated", IMAGE_ALPHA_ASSOCIATED);
494  alpha_type_enum.insert("channel_packed", IMAGE_ALPHA_CHANNEL_PACKED);
495  alpha_type_enum.insert("ignore", IMAGE_ALPHA_IGNORE);
496  SOCKET_ENUM(alpha_type, "Alpha Type", alpha_type_enum, IMAGE_ALPHA_AUTO);
497 
498  static NodeEnum interpolation_enum;
499  interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
500  interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
501  interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
502  interpolation_enum.insert("smart", INTERPOLATION_SMART);
503  SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
504 
505  static NodeEnum projection_enum;
506  projection_enum.insert("equirectangular", NODE_ENVIRONMENT_EQUIRECTANGULAR);
507  projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL);
508  SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR);
509 
510  SOCKET_BOOLEAN(animated, "Animated", false);
511 
513 
514  SOCKET_OUT_COLOR(color, "Color");
515  SOCKET_OUT_FLOAT(alpha, "Alpha");
516 
517  return type;
518 }
519 
520 EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(get_node_type())
521 {
522  colorspace = u_colorspace_raw;
523  animated = false;
524 }
525 
527 {
529  node->handle = handle;
530  return node;
531 }
532 
534 {
536  params.animated = animated;
537  params.interpolation = interpolation;
538  params.extension = EXTENSION_REPEAT;
539  params.alpha_type = alpha_type;
540  params.colorspace = colorspace;
541  return params;
542 }
543 
545 {
546 #ifdef WITH_PTEX
547  if (shader->has_surface_link() && string_endswith(filename, ".ptx")) {
548  /* ptex */
551  }
552 #endif
553 
555 }
556 
558 {
559  ShaderInput *vector_in = input("Vector");
560  ShaderOutput *color_out = output("Color");
561  ShaderOutput *alpha_out = output("Alpha");
562 
563  if (handle.empty()) {
564  ImageManager *image_manager = compiler.scene->image_manager;
565  handle = image_manager->add_image(filename.string(), image_params());
566  }
567 
568  const ImageMetaData metadata = handle.metadata();
569  const bool compress_as_srgb = metadata.compress_as_srgb;
570  const ustring known_colorspace = metadata.colorspace;
571 
572  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
573  uint flags = 0;
574 
575  if (compress_as_srgb) {
577  }
578 
579  compiler.add_node(NODE_TEX_ENVIRONMENT,
580  handle.svm_slot(),
581  compiler.encode_uchar4(vector_offset,
583  compiler.stack_assign_if_linked(alpha_out),
584  flags),
585  projection);
586 
587  tex_mapping.compile_end(compiler, vector_in, vector_offset);
588 }
589 
591 {
592  if (handle.empty()) {
593  ImageManager *image_manager = compiler.scene->image_manager;
594  handle = image_manager->add_image(filename.string(), image_params());
595  }
596 
597  tex_mapping.compile(compiler);
598 
599  const ImageMetaData metadata = handle.metadata();
600  const bool is_float = metadata.is_float();
601  const bool compress_as_srgb = metadata.compress_as_srgb;
602  const ustring known_colorspace = metadata.colorspace;
603 
604  if (handle.svm_slot() == -1) {
605  compiler.parameter_texture(
606  "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace);
607  }
608  else {
609  compiler.parameter_texture("filename", handle);
610  }
611 
612  compiler.parameter(this, "projection");
613  compiler.parameter(this, "interpolation");
614  compiler.parameter("compress_as_srgb", compress_as_srgb);
615  compiler.parameter("ignore_alpha", alpha_type == IMAGE_ALPHA_IGNORE);
616  compiler.parameter("is_float", is_float);
617  compiler.add(this, "node_environment_texture");
618 }
619 
620 /* Sky Texture */
621 
623 {
624  return make_float2(acosf(dir.z), atan2f(dir.x, dir.y));
625 }
626 
627 typedef struct SunSky {
628  /* sun direction in spherical and cartesian */
629  float theta, phi;
630 
631  /* Parameter */
633  float config_x[9], config_y[9], config_z[9], nishita_data[10];
635 
636 /* Preetham model */
637 static float sky_perez_function(float lam[6], float theta, float gamma)
638 {
639  return (1.0f + lam[0] * expf(lam[1] / cosf(theta))) *
640  (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cosf(gamma) * cosf(gamma));
641 }
642 
643 static void sky_texture_precompute_preetham(SunSky *sunsky, float3 dir, float turbidity)
644 {
645  /*
646  * We re-use the SunSky struct of the new model, to avoid extra variables
647  * zenith_Y/x/y is now radiance_x/y/z
648  * perez_Y/x/y is now config_x/y/z
649  */
650 
651  float2 spherical = sky_spherical_coordinates(dir);
652  float theta = spherical.x;
653  float phi = spherical.y;
654 
655  sunsky->theta = theta;
656  sunsky->phi = phi;
657 
658  float theta2 = theta * theta;
659  float theta3 = theta2 * theta;
660  float T = turbidity;
661  float T2 = T * T;
662 
663  float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta);
664  sunsky->radiance_x = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
665  sunsky->radiance_x *= 0.06f;
666 
667  sunsky->radiance_y = (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 +
668  (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) * T +
669  (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f);
670 
671  sunsky->radiance_z = (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 +
672  (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) * T +
673  (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f);
674 
675  sunsky->config_x[0] = (0.1787f * T - 1.4630f);
676  sunsky->config_x[1] = (-0.3554f * T + 0.4275f);
677  sunsky->config_x[2] = (-0.0227f * T + 5.3251f);
678  sunsky->config_x[3] = (0.1206f * T - 2.5771f);
679  sunsky->config_x[4] = (-0.0670f * T + 0.3703f);
680 
681  sunsky->config_y[0] = (-0.0193f * T - 0.2592f);
682  sunsky->config_y[1] = (-0.0665f * T + 0.0008f);
683  sunsky->config_y[2] = (-0.0004f * T + 0.2125f);
684  sunsky->config_y[3] = (-0.0641f * T - 0.8989f);
685  sunsky->config_y[4] = (-0.0033f * T + 0.0452f);
686 
687  sunsky->config_z[0] = (-0.0167f * T - 0.2608f);
688  sunsky->config_z[1] = (-0.0950f * T + 0.0092f);
689  sunsky->config_z[2] = (-0.0079f * T + 0.2102f);
690  sunsky->config_z[3] = (-0.0441f * T - 1.6537f);
691  sunsky->config_z[4] = (-0.0109f * T + 0.0529f);
692 
693  /* unused for old sky model */
694  for (int i = 5; i < 9; i++) {
695  sunsky->config_x[i] = 0.0f;
696  sunsky->config_y[i] = 0.0f;
697  sunsky->config_z[i] = 0.0f;
698  }
699 
700  sunsky->radiance_x /= sky_perez_function(sunsky->config_x, 0, theta);
701  sunsky->radiance_y /= sky_perez_function(sunsky->config_y, 0, theta);
702  sunsky->radiance_z /= sky_perez_function(sunsky->config_z, 0, theta);
703 }
704 
705 /* Hosek / Wilkie */
707  float3 dir,
708  float turbidity,
709  float ground_albedo)
710 {
711  /* Calculate Sun Direction and save coordinates */
712  float2 spherical = sky_spherical_coordinates(dir);
713  float theta = spherical.x;
714  float phi = spherical.y;
715 
716  /* Clamp Turbidity */
717  turbidity = clamp(turbidity, 0.0f, 10.0f);
718 
719  /* Clamp to Horizon */
720  theta = clamp(theta, 0.0f, M_PI_2_F);
721 
722  sunsky->theta = theta;
723  sunsky->phi = phi;
724 
725  float solarElevation = M_PI_2_F - theta;
726 
727  /* Initialize Sky Model */
728  SKY_ArHosekSkyModelState *sky_state;
730  (double)turbidity, (double)ground_albedo, (double)solarElevation);
731 
732  /* Copy values from sky_state to SunSky */
733  for (int i = 0; i < 9; ++i) {
734  sunsky->config_x[i] = (float)sky_state->configs[0][i];
735  sunsky->config_y[i] = (float)sky_state->configs[1][i];
736  sunsky->config_z[i] = (float)sky_state->configs[2][i];
737  }
738  sunsky->radiance_x = (float)sky_state->radiances[0];
739  sunsky->radiance_y = (float)sky_state->radiances[1];
740  sunsky->radiance_z = (float)sky_state->radiances[2];
741 
742  /* Free sky_state */
744 }
745 
746 /* Nishita improved */
748  bool sun_disc,
749  float sun_size,
750  float sun_intensity,
751  float sun_elevation,
752  float sun_rotation,
753  float altitude,
754  float air_density,
755  float dust_density)
756 {
757  /* sample 2 sun pixels */
758  float pixel_bottom[3];
759  float pixel_top[3];
761  sun_elevation, sun_size, altitude, air_density, dust_density, pixel_bottom, pixel_top);
762  /* limit sun rotation between 0 and 360 degrees */
763  sun_rotation = fmodf(sun_rotation, M_2PI_F);
764  if (sun_rotation < 0.0f) {
765  sun_rotation += M_2PI_F;
766  }
767  sun_rotation = M_2PI_F - sun_rotation;
768  /* send data to svm_sky */
769  sunsky->nishita_data[0] = pixel_bottom[0];
770  sunsky->nishita_data[1] = pixel_bottom[1];
771  sunsky->nishita_data[2] = pixel_bottom[2];
772  sunsky->nishita_data[3] = pixel_top[0];
773  sunsky->nishita_data[4] = pixel_top[1];
774  sunsky->nishita_data[5] = pixel_top[2];
775  sunsky->nishita_data[6] = sun_elevation;
776  sunsky->nishita_data[7] = sun_rotation;
777  sunsky->nishita_data[8] = sun_disc ? sun_size : -1.0f;
778  sunsky->nishita_data[9] = sun_intensity;
779 }
780 
782 {
783  NodeType *type = NodeType::add("sky_texture", create, NodeType::SHADER);
784 
786 
787  static NodeEnum type_enum;
788  type_enum.insert("preetham", NODE_SKY_PREETHAM);
789  type_enum.insert("hosek_wilkie", NODE_SKY_HOSEK);
790  type_enum.insert("nishita_improved", NODE_SKY_NISHITA);
791  SOCKET_ENUM(sky_type, "Type", type_enum, NODE_SKY_NISHITA);
792 
793  SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f));
794  SOCKET_FLOAT(turbidity, "Turbidity", 2.2f);
795  SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f);
796  SOCKET_BOOLEAN(sun_disc, "Sun Disc", true);
797  SOCKET_FLOAT(sun_size, "Sun Size", 0.009512f);
798  SOCKET_FLOAT(sun_intensity, "Sun Intensity", 1.0f);
799  SOCKET_FLOAT(sun_elevation, "Sun Elevation", 15.0f * M_PI_F / 180.0f);
800  SOCKET_FLOAT(sun_rotation, "Sun Rotation", 0.0f);
801  SOCKET_FLOAT(altitude, "Altitude", 1.0f);
802  SOCKET_FLOAT(air_density, "Air", 1.0f);
803  SOCKET_FLOAT(dust_density, "Dust", 1.0f);
804  SOCKET_FLOAT(ozone_density, "Ozone", 1.0f);
805 
807 
808  SOCKET_OUT_COLOR(color, "Color");
809 
810  return type;
811 }
812 
813 SkyTextureNode::SkyTextureNode() : TextureNode(get_node_type())
814 {
815 }
816 
817 void SkyTextureNode::compile(SVMCompiler &compiler)
818 {
819  ShaderInput *vector_in = input("Vector");
820  ShaderOutput *color_out = output("Color");
821 
822  SunSky sunsky;
823  if (sky_type == NODE_SKY_PREETHAM)
824  sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity);
825  else if (sky_type == NODE_SKY_HOSEK)
826  sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
827  else if (sky_type == NODE_SKY_NISHITA) {
828  /* Clamp altitude to reasonable values.
829  * Below 1m causes numerical issues and above 60km is space. */
830  float clamped_altitude = clamp(altitude, 1.0f, 59999.0f);
831 
833  sun_disc,
834  get_sun_size(),
835  sun_intensity,
836  sun_elevation,
837  sun_rotation,
838  clamped_altitude,
839  air_density,
840  dust_density);
841  /* precomputed texture image parameters */
842  ImageManager *image_manager = compiler.scene->image_manager;
843  ImageParams impar;
845  impar.extension = EXTENSION_EXTEND;
846 
847  /* precompute sky texture */
848  if (handle.empty()) {
849  SkyLoader *loader = new SkyLoader(
850  sun_elevation, clamped_altitude, air_density, dust_density, ozone_density);
851  handle = image_manager->add_image(loader, impar);
852  }
853  }
854  else
855  assert(false);
856 
857  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
858 
859  compiler.stack_assign(color_out);
860  compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), sky_type);
861  /* nishita doesn't need this data */
862  if (sky_type != NODE_SKY_NISHITA) {
863  compiler.add_node(__float_as_uint(sunsky.phi),
864  __float_as_uint(sunsky.theta),
865  __float_as_uint(sunsky.radiance_x),
866  __float_as_uint(sunsky.radiance_y));
867  compiler.add_node(__float_as_uint(sunsky.radiance_z),
868  __float_as_uint(sunsky.config_x[0]),
869  __float_as_uint(sunsky.config_x[1]),
870  __float_as_uint(sunsky.config_x[2]));
871  compiler.add_node(__float_as_uint(sunsky.config_x[3]),
872  __float_as_uint(sunsky.config_x[4]),
873  __float_as_uint(sunsky.config_x[5]),
874  __float_as_uint(sunsky.config_x[6]));
875  compiler.add_node(__float_as_uint(sunsky.config_x[7]),
876  __float_as_uint(sunsky.config_x[8]),
877  __float_as_uint(sunsky.config_y[0]),
878  __float_as_uint(sunsky.config_y[1]));
879  compiler.add_node(__float_as_uint(sunsky.config_y[2]),
880  __float_as_uint(sunsky.config_y[3]),
881  __float_as_uint(sunsky.config_y[4]),
882  __float_as_uint(sunsky.config_y[5]));
883  compiler.add_node(__float_as_uint(sunsky.config_y[6]),
884  __float_as_uint(sunsky.config_y[7]),
885  __float_as_uint(sunsky.config_y[8]),
886  __float_as_uint(sunsky.config_z[0]));
887  compiler.add_node(__float_as_uint(sunsky.config_z[1]),
888  __float_as_uint(sunsky.config_z[2]),
889  __float_as_uint(sunsky.config_z[3]),
890  __float_as_uint(sunsky.config_z[4]));
891  compiler.add_node(__float_as_uint(sunsky.config_z[5]),
892  __float_as_uint(sunsky.config_z[6]),
893  __float_as_uint(sunsky.config_z[7]),
894  __float_as_uint(sunsky.config_z[8]));
895  }
896  else {
897  compiler.add_node(__float_as_uint(sunsky.nishita_data[0]),
898  __float_as_uint(sunsky.nishita_data[1]),
899  __float_as_uint(sunsky.nishita_data[2]),
900  __float_as_uint(sunsky.nishita_data[3]));
901  compiler.add_node(__float_as_uint(sunsky.nishita_data[4]),
902  __float_as_uint(sunsky.nishita_data[5]),
903  __float_as_uint(sunsky.nishita_data[6]),
904  __float_as_uint(sunsky.nishita_data[7]));
905  compiler.add_node(__float_as_uint(sunsky.nishita_data[8]),
906  __float_as_uint(sunsky.nishita_data[9]),
907  handle.svm_slot(),
908  0);
909  }
910 
911  tex_mapping.compile_end(compiler, vector_in, vector_offset);
912 }
913 
914 void SkyTextureNode::compile(OSLCompiler &compiler)
915 {
916  tex_mapping.compile(compiler);
917 
918  SunSky sunsky;
919  if (sky_type == NODE_SKY_PREETHAM)
920  sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity);
921  else if (sky_type == NODE_SKY_HOSEK)
922  sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo);
923  else if (sky_type == NODE_SKY_NISHITA) {
924  /* Clamp altitude to reasonable values.
925  * Below 1m causes numerical issues and above 60km is space. */
926  float clamped_altitude = clamp(altitude, 1.0f, 59999.0f);
927 
929  sun_disc,
930  get_sun_size(),
931  sun_intensity,
932  sun_elevation,
933  sun_rotation,
934  clamped_altitude,
935  air_density,
936  dust_density);
937  /* precomputed texture image parameters */
938  ImageManager *image_manager = compiler.scene->image_manager;
939  ImageParams impar;
941  impar.extension = EXTENSION_EXTEND;
942 
943  /* precompute sky texture */
944  if (handle.empty()) {
945  SkyLoader *loader = new SkyLoader(
946  sun_elevation, clamped_altitude, air_density, dust_density, ozone_density);
947  handle = image_manager->add_image(loader, impar);
948  }
949  }
950  else
951  assert(false);
952 
953  compiler.parameter(this, "sky_type");
954  compiler.parameter("theta", sunsky.theta);
955  compiler.parameter("phi", sunsky.phi);
956  compiler.parameter_color("radiance",
957  make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z));
958  compiler.parameter_array("config_x", sunsky.config_x, 9);
959  compiler.parameter_array("config_y", sunsky.config_y, 9);
960  compiler.parameter_array("config_z", sunsky.config_z, 9);
961  compiler.parameter_array("nishita_data", sunsky.nishita_data, 10);
962  /* nishita texture */
963  if (sky_type == NODE_SKY_NISHITA) {
964  compiler.parameter_texture("filename", handle);
965  }
966  compiler.add(this, "node_sky_texture");
967 }
968 
969 /* Gradient Texture */
970 
972 {
973  NodeType *type = NodeType::add("gradient_texture", create, NodeType::SHADER);
974 
976 
977  static NodeEnum type_enum;
978  type_enum.insert("linear", NODE_BLEND_LINEAR);
979  type_enum.insert("quadratic", NODE_BLEND_QUADRATIC);
980  type_enum.insert("easing", NODE_BLEND_EASING);
981  type_enum.insert("diagonal", NODE_BLEND_DIAGONAL);
982  type_enum.insert("radial", NODE_BLEND_RADIAL);
983  type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE);
984  type_enum.insert("spherical", NODE_BLEND_SPHERICAL);
985  SOCKET_ENUM(gradient_type, "Type", type_enum, NODE_BLEND_LINEAR);
986 
988 
989  SOCKET_OUT_COLOR(color, "Color");
990  SOCKET_OUT_FLOAT(fac, "Fac");
991 
992  return type;
993 }
994 
995 GradientTextureNode::GradientTextureNode() : TextureNode(get_node_type())
996 {
997 }
998 
1000 {
1001  ShaderInput *vector_in = input("Vector");
1002  ShaderOutput *color_out = output("Color");
1003  ShaderOutput *fac_out = output("Fac");
1004 
1005  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1006 
1007  compiler.add_node(NODE_TEX_GRADIENT,
1008  compiler.encode_uchar4(gradient_type,
1009  vector_offset,
1010  compiler.stack_assign_if_linked(fac_out),
1011  compiler.stack_assign_if_linked(color_out)));
1012 
1013  tex_mapping.compile_end(compiler, vector_in, vector_offset);
1014 }
1015 
1017 {
1018  tex_mapping.compile(compiler);
1019 
1020  compiler.parameter(this, "gradient_type");
1021  compiler.add(this, "node_gradient_texture");
1022 }
1023 
1024 /* Noise Texture */
1025 
1027 {
1028  NodeType *type = NodeType::add("noise_texture", create, NodeType::SHADER);
1029 
1031 
1032  static NodeEnum dimensions_enum;
1033  dimensions_enum.insert("1D", 1);
1034  dimensions_enum.insert("2D", 2);
1035  dimensions_enum.insert("3D", 3);
1036  dimensions_enum.insert("4D", 4);
1037  SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
1038 
1040  SOCKET_IN_FLOAT(w, "W", 0.0f);
1041  SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
1042  SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
1043  SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
1044  SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
1045 
1046  SOCKET_OUT_FLOAT(fac, "Fac");
1047  SOCKET_OUT_COLOR(color, "Color");
1048 
1049  return type;
1050 }
1051 
1052 NoiseTextureNode::NoiseTextureNode() : TextureNode(get_node_type())
1053 {
1054 }
1055 
1056 void NoiseTextureNode::compile(SVMCompiler &compiler)
1057 {
1058  ShaderInput *vector_in = input("Vector");
1059  ShaderInput *w_in = input("W");
1060  ShaderInput *scale_in = input("Scale");
1061  ShaderInput *detail_in = input("Detail");
1062  ShaderInput *roughness_in = input("Roughness");
1063  ShaderInput *distortion_in = input("Distortion");
1064  ShaderOutput *fac_out = output("Fac");
1065  ShaderOutput *color_out = output("Color");
1066 
1067  int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
1068  int w_stack_offset = compiler.stack_assign_if_linked(w_in);
1069  int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
1070  int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
1071  int roughness_stack_offset = compiler.stack_assign_if_linked(roughness_in);
1072  int distortion_stack_offset = compiler.stack_assign_if_linked(distortion_in);
1073  int fac_stack_offset = compiler.stack_assign_if_linked(fac_out);
1074  int color_stack_offset = compiler.stack_assign_if_linked(color_out);
1075 
1076  compiler.add_node(
1077  NODE_TEX_NOISE,
1078  dimensions,
1079  compiler.encode_uchar4(
1080  vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset),
1081  compiler.encode_uchar4(
1082  roughness_stack_offset, distortion_stack_offset, fac_stack_offset, color_stack_offset));
1083  compiler.add_node(
1085 
1086  compiler.add_node(
1088 
1089  tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
1090 }
1091 
1092 void NoiseTextureNode::compile(OSLCompiler &compiler)
1093 {
1094  tex_mapping.compile(compiler);
1095  compiler.parameter(this, "dimensions");
1096  compiler.add(this, "node_noise_texture");
1097 }
1098 
1099 /* Voronoi Texture */
1100 
1102 {
1103  NodeType *type = NodeType::add("voronoi_texture", create, NodeType::SHADER);
1104 
1106 
1107  static NodeEnum dimensions_enum;
1108  dimensions_enum.insert("1D", 1);
1109  dimensions_enum.insert("2D", 2);
1110  dimensions_enum.insert("3D", 3);
1111  dimensions_enum.insert("4D", 4);
1112  SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
1113 
1114  static NodeEnum metric_enum;
1115  metric_enum.insert("euclidean", NODE_VORONOI_EUCLIDEAN);
1116  metric_enum.insert("manhattan", NODE_VORONOI_MANHATTAN);
1117  metric_enum.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
1118  metric_enum.insert("minkowski", NODE_VORONOI_MINKOWSKI);
1119  SOCKET_ENUM(metric, "Distance Metric", metric_enum, NODE_VORONOI_EUCLIDEAN);
1120 
1121  static NodeEnum feature_enum;
1122  feature_enum.insert("f1", NODE_VORONOI_F1);
1123  feature_enum.insert("f2", NODE_VORONOI_F2);
1124  feature_enum.insert("smooth_f1", NODE_VORONOI_SMOOTH_F1);
1125  feature_enum.insert("distance_to_edge", NODE_VORONOI_DISTANCE_TO_EDGE);
1126  feature_enum.insert("n_sphere_radius", NODE_VORONOI_N_SPHERE_RADIUS);
1127  SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_F1);
1128 
1130  SOCKET_IN_FLOAT(w, "W", 0.0f);
1131  SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
1132  SOCKET_IN_FLOAT(smoothness, "Smoothness", 5.0f);
1133  SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
1134  SOCKET_IN_FLOAT(randomness, "Randomness", 1.0f);
1135 
1136  SOCKET_OUT_FLOAT(distance, "Distance");
1137  SOCKET_OUT_COLOR(color, "Color");
1138  SOCKET_OUT_POINT(position, "Position");
1139  SOCKET_OUT_FLOAT(w, "W");
1140  SOCKET_OUT_FLOAT(radius, "Radius");
1141 
1142  return type;
1143 }
1144 
1145 VoronoiTextureNode::VoronoiTextureNode() : TextureNode(get_node_type())
1146 {
1147 }
1148 
1150 {
1151  ShaderInput *vector_in = input("Vector");
1152  ShaderInput *w_in = input("W");
1153  ShaderInput *scale_in = input("Scale");
1154  ShaderInput *smoothness_in = input("Smoothness");
1155  ShaderInput *exponent_in = input("Exponent");
1156  ShaderInput *randomness_in = input("Randomness");
1157 
1158  ShaderOutput *distance_out = output("Distance");
1159  ShaderOutput *color_out = output("Color");
1160  ShaderOutput *position_out = output("Position");
1161  ShaderOutput *w_out = output("W");
1162  ShaderOutput *radius_out = output("Radius");
1163 
1164  int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
1165  int w_in_stack_offset = compiler.stack_assign_if_linked(w_in);
1166  int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
1167  int smoothness_stack_offset = compiler.stack_assign_if_linked(smoothness_in);
1168  int exponent_stack_offset = compiler.stack_assign_if_linked(exponent_in);
1169  int randomness_stack_offset = compiler.stack_assign_if_linked(randomness_in);
1170  int distance_stack_offset = compiler.stack_assign_if_linked(distance_out);
1171  int color_stack_offset = compiler.stack_assign_if_linked(color_out);
1172  int position_stack_offset = compiler.stack_assign_if_linked(position_out);
1173  int w_out_stack_offset = compiler.stack_assign_if_linked(w_out);
1174  int radius_stack_offset = compiler.stack_assign_if_linked(radius_out);
1175 
1176  compiler.add_node(NODE_TEX_VORONOI, dimensions, feature, metric);
1177  compiler.add_node(
1178  compiler.encode_uchar4(
1179  vector_stack_offset, w_in_stack_offset, scale_stack_offset, smoothness_stack_offset),
1180  compiler.encode_uchar4(exponent_stack_offset,
1181  randomness_stack_offset,
1182  distance_stack_offset,
1183  color_stack_offset),
1184  compiler.encode_uchar4(position_stack_offset, w_out_stack_offset, radius_stack_offset),
1185  __float_as_int(w));
1186 
1187  compiler.add_node(__float_as_int(scale),
1188  __float_as_int(smoothness),
1189  __float_as_int(exponent),
1190  __float_as_int(randomness));
1191 
1192  tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
1193 }
1194 
1196 {
1197  tex_mapping.compile(compiler);
1198 
1199  compiler.parameter(this, "dimensions");
1200  compiler.parameter(this, "feature");
1201  compiler.parameter(this, "metric");
1202  compiler.add(this, "node_voronoi_texture");
1203 }
1204 
1205 /* IES Light */
1206 
1208 {
1210 
1212 
1213  SOCKET_STRING(ies, "IES", ustring());
1214  SOCKET_STRING(filename, "File Name", ustring());
1215 
1216  SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
1218 
1219  SOCKET_OUT_FLOAT(fac, "Fac");
1220 
1221  return type;
1222 }
1223 
1224 IESLightNode::IESLightNode() : TextureNode(get_node_type())
1225 {
1226  light_manager = NULL;
1227  slot = -1;
1228 }
1229 
1231 {
1232  IESLightNode *node = graph->create_node<IESLightNode>(*this);
1233 
1234  node->light_manager = NULL;
1235  node->slot = -1;
1236 
1237  return node;
1238 }
1239 
1241 {
1242  if (light_manager) {
1243  light_manager->remove_ies(slot);
1244  }
1245 }
1246 
1247 void IESLightNode::get_slot()
1248 {
1249  assert(light_manager);
1250 
1251  if (slot == -1) {
1252  if (ies.empty()) {
1253  slot = light_manager->add_ies_from_file(filename.string());
1254  }
1255  else {
1256  slot = light_manager->add_ies(ies.string());
1257  }
1258  }
1259 }
1260 
1261 void IESLightNode::compile(SVMCompiler &compiler)
1262 {
1263  light_manager = compiler.scene->light_manager;
1264  get_slot();
1265 
1266  ShaderInput *strength_in = input("Strength");
1267  ShaderInput *vector_in = input("Vector");
1268  ShaderOutput *fac_out = output("Fac");
1269 
1270  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1271 
1272  compiler.add_node(NODE_IES,
1273  compiler.encode_uchar4(compiler.stack_assign_if_linked(strength_in),
1274  vector_offset,
1275  compiler.stack_assign(fac_out),
1276  0),
1277  slot,
1278  __float_as_int(strength));
1279 
1280  tex_mapping.compile_end(compiler, vector_in, vector_offset);
1281 }
1282 
1283 void IESLightNode::compile(OSLCompiler &compiler)
1284 {
1285  light_manager = compiler.scene->light_manager;
1286  get_slot();
1287 
1288  tex_mapping.compile(compiler);
1289 
1290  compiler.parameter_texture_ies("filename", slot);
1291  compiler.add(this, "node_ies_light");
1292 }
1293 
1294 /* White Noise Texture */
1295 
1297 {
1298  NodeType *type = NodeType::add("white_noise_texture", create, NodeType::SHADER);
1299 
1300  static NodeEnum dimensions_enum;
1301  dimensions_enum.insert("1D", 1);
1302  dimensions_enum.insert("2D", 2);
1303  dimensions_enum.insert("3D", 3);
1304  dimensions_enum.insert("4D", 4);
1305  SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
1306 
1307  SOCKET_IN_POINT(vector, "Vector", zero_float3());
1308  SOCKET_IN_FLOAT(w, "W", 0.0f);
1309 
1310  SOCKET_OUT_FLOAT(value, "Value");
1311  SOCKET_OUT_COLOR(color, "Color");
1312 
1313  return type;
1314 }
1315 
1316 WhiteNoiseTextureNode::WhiteNoiseTextureNode() : ShaderNode(get_node_type())
1317 {
1318 }
1319 
1321 {
1322  ShaderInput *vector_in = input("Vector");
1323  ShaderInput *w_in = input("W");
1324  ShaderOutput *value_out = output("Value");
1325  ShaderOutput *color_out = output("Color");
1326 
1327  int vector_stack_offset = compiler.stack_assign(vector_in);
1328  int w_stack_offset = compiler.stack_assign(w_in);
1329  int value_stack_offset = compiler.stack_assign(value_out);
1330  int color_stack_offset = compiler.stack_assign(color_out);
1331 
1332  compiler.add_node(NODE_TEX_WHITE_NOISE,
1333  dimensions,
1334  compiler.encode_uchar4(vector_stack_offset, w_stack_offset),
1335  compiler.encode_uchar4(value_stack_offset, color_stack_offset));
1336 }
1337 
1339 {
1340  compiler.parameter(this, "dimensions");
1341  compiler.add(this, "node_white_noise_texture");
1342 }
1343 
1344 /* Musgrave Texture */
1345 
1347 {
1348  NodeType *type = NodeType::add("musgrave_texture", create, NodeType::SHADER);
1349 
1351 
1352  static NodeEnum dimensions_enum;
1353  dimensions_enum.insert("1D", 1);
1354  dimensions_enum.insert("2D", 2);
1355  dimensions_enum.insert("3D", 3);
1356  dimensions_enum.insert("4D", 4);
1357  SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
1358 
1359  static NodeEnum type_enum;
1360  type_enum.insert("multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
1361  type_enum.insert("fBM", NODE_MUSGRAVE_FBM);
1362  type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
1363  type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
1364  type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
1365  SOCKET_ENUM(musgrave_type, "Type", type_enum, NODE_MUSGRAVE_FBM);
1366 
1368  SOCKET_IN_FLOAT(w, "W", 0.0f);
1369  SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
1370  SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
1371  SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f);
1372  SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f);
1373  SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
1374  SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
1375 
1376  SOCKET_OUT_FLOAT(fac, "Fac");
1377 
1378  return type;
1379 }
1380 
1381 MusgraveTextureNode::MusgraveTextureNode() : TextureNode(get_node_type())
1382 {
1383 }
1384 
1386 {
1387  ShaderInput *vector_in = input("Vector");
1388  ShaderInput *w_in = input("W");
1389  ShaderInput *scale_in = input("Scale");
1390  ShaderInput *detail_in = input("Detail");
1391  ShaderInput *dimension_in = input("Dimension");
1392  ShaderInput *lacunarity_in = input("Lacunarity");
1393  ShaderInput *offset_in = input("Offset");
1394  ShaderInput *gain_in = input("Gain");
1395  ShaderOutput *fac_out = output("Fac");
1396 
1397  int vector_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
1398  int w_stack_offset = compiler.stack_assign_if_linked(w_in);
1399  int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
1400  int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
1401  int dimension_stack_offset = compiler.stack_assign_if_linked(dimension_in);
1402  int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
1403  int offset_stack_offset = compiler.stack_assign_if_linked(offset_in);
1404  int gain_stack_offset = compiler.stack_assign_if_linked(gain_in);
1405  int fac_stack_offset = compiler.stack_assign(fac_out);
1406 
1407  compiler.add_node(
1408  NODE_TEX_MUSGRAVE,
1409  compiler.encode_uchar4(musgrave_type, dimensions, vector_stack_offset, w_stack_offset),
1410  compiler.encode_uchar4(scale_stack_offset,
1411  detail_stack_offset,
1412  dimension_stack_offset,
1413  lacunarity_stack_offset),
1414  compiler.encode_uchar4(offset_stack_offset, gain_stack_offset, fac_stack_offset));
1415  compiler.add_node(
1416  __float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(dimension));
1417  compiler.add_node(__float_as_int(lacunarity), __float_as_int(offset), __float_as_int(gain));
1418 
1419  tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
1420 }
1421 
1423 {
1424  tex_mapping.compile(compiler);
1425 
1426  compiler.parameter(this, "musgrave_type");
1427  compiler.parameter(this, "dimensions");
1428  compiler.add(this, "node_musgrave_texture");
1429 }
1430 
1431 /* Wave Texture */
1432 
1434 {
1435  NodeType *type = NodeType::add("wave_texture", create, NodeType::SHADER);
1436 
1438 
1439  static NodeEnum type_enum;
1440  type_enum.insert("bands", NODE_WAVE_BANDS);
1441  type_enum.insert("rings", NODE_WAVE_RINGS);
1442  SOCKET_ENUM(wave_type, "Type", type_enum, NODE_WAVE_BANDS);
1443 
1444  static NodeEnum bands_direction_enum;
1445  bands_direction_enum.insert("x", NODE_WAVE_BANDS_DIRECTION_X);
1446  bands_direction_enum.insert("y", NODE_WAVE_BANDS_DIRECTION_Y);
1447  bands_direction_enum.insert("z", NODE_WAVE_BANDS_DIRECTION_Z);
1448  bands_direction_enum.insert("diagonal", NODE_WAVE_BANDS_DIRECTION_DIAGONAL);
1449  SOCKET_ENUM(
1450  bands_direction, "Bands Direction", bands_direction_enum, NODE_WAVE_BANDS_DIRECTION_X);
1451 
1452  static NodeEnum rings_direction_enum;
1453  rings_direction_enum.insert("x", NODE_WAVE_RINGS_DIRECTION_X);
1454  rings_direction_enum.insert("y", NODE_WAVE_RINGS_DIRECTION_Y);
1455  rings_direction_enum.insert("z", NODE_WAVE_RINGS_DIRECTION_Z);
1456  rings_direction_enum.insert("spherical", NODE_WAVE_RINGS_DIRECTION_SPHERICAL);
1457  SOCKET_ENUM(
1458  rings_direction, "Rings Direction", rings_direction_enum, NODE_WAVE_BANDS_DIRECTION_X);
1459 
1460  static NodeEnum profile_enum;
1461  profile_enum.insert("sine", NODE_WAVE_PROFILE_SIN);
1462  profile_enum.insert("saw", NODE_WAVE_PROFILE_SAW);
1463  profile_enum.insert("tri", NODE_WAVE_PROFILE_TRI);
1464  SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN);
1465 
1467  SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
1468  SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
1469  SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
1470  SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f);
1471  SOCKET_IN_FLOAT(detail_roughness, "Detail Roughness", 0.5f);
1472  SOCKET_IN_FLOAT(phase, "Phase Offset", 0.0f);
1473  SOCKET_OUT_COLOR(color, "Color");
1474  SOCKET_OUT_FLOAT(fac, "Fac");
1475 
1476  return type;
1477 }
1478 
1479 WaveTextureNode::WaveTextureNode() : TextureNode(get_node_type())
1480 {
1481 }
1482 
1483 void WaveTextureNode::compile(SVMCompiler &compiler)
1484 {
1485  ShaderInput *vector_in = input("Vector");
1486  ShaderInput *scale_in = input("Scale");
1487  ShaderInput *distortion_in = input("Distortion");
1488  ShaderInput *detail_in = input("Detail");
1489  ShaderInput *dscale_in = input("Detail Scale");
1490  ShaderInput *droughness_in = input("Detail Roughness");
1491  ShaderInput *phase_in = input("Phase Offset");
1492  ShaderOutput *color_out = output("Color");
1493  ShaderOutput *fac_out = output("Fac");
1494 
1495  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1496 
1497  int scale_ofs = compiler.stack_assign_if_linked(scale_in);
1498  int distortion_ofs = compiler.stack_assign_if_linked(distortion_in);
1499  int detail_ofs = compiler.stack_assign_if_linked(detail_in);
1500  int dscale_ofs = compiler.stack_assign_if_linked(dscale_in);
1501  int droughness_ofs = compiler.stack_assign_if_linked(droughness_in);
1502  int phase_ofs = compiler.stack_assign_if_linked(phase_in);
1503  int color_ofs = compiler.stack_assign_if_linked(color_out);
1504  int fac_ofs = compiler.stack_assign_if_linked(fac_out);
1505 
1506  compiler.add_node(NODE_TEX_WAVE,
1507  compiler.encode_uchar4(wave_type, bands_direction, rings_direction, profile),
1508  compiler.encode_uchar4(vector_offset, scale_ofs, distortion_ofs),
1509  compiler.encode_uchar4(detail_ofs, dscale_ofs, droughness_ofs, phase_ofs));
1510 
1511  compiler.add_node(compiler.encode_uchar4(color_ofs, fac_ofs),
1512  __float_as_int(scale),
1513  __float_as_int(distortion),
1514  __float_as_int(detail));
1515 
1516  compiler.add_node(__float_as_int(detail_scale),
1517  __float_as_int(detail_roughness),
1518  __float_as_int(phase),
1520 
1521  tex_mapping.compile_end(compiler, vector_in, vector_offset);
1522 }
1523 
1524 void WaveTextureNode::compile(OSLCompiler &compiler)
1525 {
1526  tex_mapping.compile(compiler);
1527 
1528  compiler.parameter(this, "wave_type");
1529  compiler.parameter(this, "bands_direction");
1530  compiler.parameter(this, "rings_direction");
1531  compiler.parameter(this, "profile");
1532 
1533  compiler.add(this, "node_wave_texture");
1534 }
1535 
1536 /* Magic Texture */
1537 
1539 {
1540  NodeType *type = NodeType::add("magic_texture", create, NodeType::SHADER);
1541 
1543 
1544  SOCKET_INT(depth, "Depth", 2);
1545 
1547  SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
1548  SOCKET_IN_FLOAT(distortion, "Distortion", 1.0f);
1549 
1550  SOCKET_OUT_COLOR(color, "Color");
1551  SOCKET_OUT_FLOAT(fac, "Fac");
1552 
1553  return type;
1554 }
1555 
1556 MagicTextureNode::MagicTextureNode() : TextureNode(get_node_type())
1557 {
1558 }
1559 
1560 void MagicTextureNode::compile(SVMCompiler &compiler)
1561 {
1562  ShaderInput *vector_in = input("Vector");
1563  ShaderInput *scale_in = input("Scale");
1564  ShaderInput *distortion_in = input("Distortion");
1565  ShaderOutput *color_out = output("Color");
1566  ShaderOutput *fac_out = output("Fac");
1567 
1568  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1569 
1570  compiler.add_node(NODE_TEX_MAGIC,
1571  compiler.encode_uchar4(depth,
1573  compiler.stack_assign_if_linked(fac_out)),
1574  compiler.encode_uchar4(vector_offset,
1575  compiler.stack_assign_if_linked(scale_in),
1576  compiler.stack_assign_if_linked(distortion_in)));
1577  compiler.add_node(__float_as_int(scale), __float_as_int(distortion));
1578 
1579  tex_mapping.compile_end(compiler, vector_in, vector_offset);
1580 }
1581 
1582 void MagicTextureNode::compile(OSLCompiler &compiler)
1583 {
1584  tex_mapping.compile(compiler);
1585 
1586  compiler.parameter(this, "depth");
1587  compiler.add(this, "node_magic_texture");
1588 }
1589 
1590 /* Checker Texture */
1591 
1593 {
1594  NodeType *type = NodeType::add("checker_texture", create, NodeType::SHADER);
1595 
1597 
1599  SOCKET_IN_COLOR(color1, "Color1", zero_float3());
1600  SOCKET_IN_COLOR(color2, "Color2", zero_float3());
1601  SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
1602 
1603  SOCKET_OUT_COLOR(color, "Color");
1604  SOCKET_OUT_FLOAT(fac, "Fac");
1605 
1606  return type;
1607 }
1608 
1609 CheckerTextureNode::CheckerTextureNode() : TextureNode(get_node_type())
1610 {
1611 }
1612 
1614 {
1615  ShaderInput *vector_in = input("Vector");
1616  ShaderInput *color1_in = input("Color1");
1617  ShaderInput *color2_in = input("Color2");
1618  ShaderInput *scale_in = input("Scale");
1619 
1620  ShaderOutput *color_out = output("Color");
1621  ShaderOutput *fac_out = output("Fac");
1622 
1623  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1624 
1625  compiler.add_node(NODE_TEX_CHECKER,
1626  compiler.encode_uchar4(vector_offset,
1627  compiler.stack_assign(color1_in),
1628  compiler.stack_assign(color2_in),
1629  compiler.stack_assign_if_linked(scale_in)),
1630  compiler.encode_uchar4(compiler.stack_assign_if_linked(color_out),
1631  compiler.stack_assign_if_linked(fac_out)),
1632  __float_as_int(scale));
1633 
1634  tex_mapping.compile_end(compiler, vector_in, vector_offset);
1635 }
1636 
1638 {
1639  tex_mapping.compile(compiler);
1640 
1641  compiler.add(this, "node_checker_texture");
1642 }
1643 
1644 /* Brick Texture */
1645 
1647 {
1648  NodeType *type = NodeType::add("brick_texture", create, NodeType::SHADER);
1649 
1651 
1652  SOCKET_FLOAT(offset, "Offset", 0.5f);
1653  SOCKET_INT(offset_frequency, "Offset Frequency", 2);
1654  SOCKET_FLOAT(squash, "Squash", 1.0f);
1655  SOCKET_INT(squash_frequency, "Squash Frequency", 2);
1656 
1658 
1659  SOCKET_IN_COLOR(color1, "Color1", zero_float3());
1660  SOCKET_IN_COLOR(color2, "Color2", zero_float3());
1661  SOCKET_IN_COLOR(mortar, "Mortar", zero_float3());
1662  SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
1663  SOCKET_IN_FLOAT(mortar_size, "Mortar Size", 0.02f);
1664  SOCKET_IN_FLOAT(mortar_smooth, "Mortar Smooth", 0.0f);
1665  SOCKET_IN_FLOAT(bias, "Bias", 0.0f);
1666  SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f);
1667  SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f);
1668 
1669  SOCKET_OUT_COLOR(color, "Color");
1670  SOCKET_OUT_FLOAT(fac, "Fac");
1671 
1672  return type;
1673 }
1674 
1675 BrickTextureNode::BrickTextureNode() : TextureNode(get_node_type())
1676 {
1677 }
1678 
1679 void BrickTextureNode::compile(SVMCompiler &compiler)
1680 {
1681  ShaderInput *vector_in = input("Vector");
1682  ShaderInput *color1_in = input("Color1");
1683  ShaderInput *color2_in = input("Color2");
1684  ShaderInput *mortar_in = input("Mortar");
1685  ShaderInput *scale_in = input("Scale");
1686  ShaderInput *mortar_size_in = input("Mortar Size");
1687  ShaderInput *mortar_smooth_in = input("Mortar Smooth");
1688  ShaderInput *bias_in = input("Bias");
1689  ShaderInput *brick_width_in = input("Brick Width");
1690  ShaderInput *row_height_in = input("Row Height");
1691 
1692  ShaderOutput *color_out = output("Color");
1693  ShaderOutput *fac_out = output("Fac");
1694 
1695  int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
1696 
1697  compiler.add_node(NODE_TEX_BRICK,
1698  compiler.encode_uchar4(vector_offset,
1699  compiler.stack_assign(color1_in),
1700  compiler.stack_assign(color2_in),
1701  compiler.stack_assign(mortar_in)),
1702  compiler.encode_uchar4(compiler.stack_assign_if_linked(scale_in),
1703  compiler.stack_assign_if_linked(mortar_size_in),
1704  compiler.stack_assign_if_linked(bias_in),
1705  compiler.stack_assign_if_linked(brick_width_in)),
1706  compiler.encode_uchar4(compiler.stack_assign_if_linked(row_height_in),
1708  compiler.stack_assign_if_linked(fac_out),
1709  compiler.stack_assign_if_linked(mortar_smooth_in)));
1710 
1711  compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
1712  __float_as_int(scale),
1713  __float_as_int(mortar_size),
1714  __float_as_int(bias));
1715 
1716  compiler.add_node(__float_as_int(brick_width),
1717  __float_as_int(row_height),
1719  __float_as_int(squash));
1720 
1721  compiler.add_node(
1723 
1724  tex_mapping.compile_end(compiler, vector_in, vector_offset);
1725 }
1726 
1727 void BrickTextureNode::compile(OSLCompiler &compiler)
1728 {
1729  tex_mapping.compile(compiler);
1730 
1731  compiler.parameter(this, "offset");
1732  compiler.parameter(this, "offset_frequency");
1733  compiler.parameter(this, "squash");
1734  compiler.parameter(this, "squash_frequency");
1735  compiler.add(this, "node_brick_texture");
1736 }
1737 
1738 /* Point Density Texture */
1739 
1741 {
1742  NodeType *type = NodeType::add("point_density_texture", create, NodeType::SHADER);
1743 
1744  SOCKET_STRING(filename, "Filename", ustring());
1745 
1746  static NodeEnum space_enum;
1747  space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
1748  space_enum.insert("world", NODE_TEX_VOXEL_SPACE_WORLD);
1749  SOCKET_ENUM(space, "Space", space_enum, NODE_TEX_VOXEL_SPACE_OBJECT);
1750 
1751  static NodeEnum interpolation_enum;
1752  interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
1753  interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
1754  interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
1755  interpolation_enum.insert("smart", INTERPOLATION_SMART);
1756  SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
1757 
1758  SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
1759 
1761 
1762  SOCKET_OUT_FLOAT(density, "Density");
1763  SOCKET_OUT_COLOR(color, "Color");
1764 
1765  return type;
1766 }
1767 
1768 PointDensityTextureNode::PointDensityTextureNode() : ShaderNode(get_node_type())
1769 {
1770 }
1771 
1773 {
1774 }
1775 
1777 {
1778  /* Increase image user count for new node. We need to ensure to not call
1779  * add_image again, to work around access of freed data on the Blender
1780  * side. A better solution should be found to avoid this. */
1782  node->handle = handle; /* TODO: not needed? */
1783  return node;
1784 }
1785 
1787 {
1788  if (shader->has_volume)
1790 
1792 }
1793 
1795 {
1797  params.interpolation = interpolation;
1798  return params;
1799 }
1800 
1802 {
1803  ShaderInput *vector_in = input("Vector");
1804  ShaderOutput *density_out = output("Density");
1805  ShaderOutput *color_out = output("Color");
1806 
1807  const bool use_density = !density_out->links.empty();
1808  const bool use_color = !color_out->links.empty();
1809 
1810  if (use_density || use_color) {
1811  if (handle.empty()) {
1812  ImageManager *image_manager = compiler.scene->image_manager;
1813  handle = image_manager->add_image(filename.string(), image_params());
1814  }
1815 
1816  const int slot = handle.svm_slot();
1817  if (slot != -1) {
1818  compiler.stack_assign(vector_in);
1819  compiler.add_node(NODE_TEX_VOXEL,
1820  slot,
1821  compiler.encode_uchar4(compiler.stack_assign(vector_in),
1822  compiler.stack_assign_if_linked(density_out),
1824  space));
1825  if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
1826  compiler.add_node(tfm.x);
1827  compiler.add_node(tfm.y);
1828  compiler.add_node(tfm.z);
1829  }
1830  }
1831  else {
1832  if (use_density) {
1833  compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(density_out));
1834  }
1835  if (use_color) {
1836  compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
1837  compiler.add_node(
1838  NODE_VALUE_V,
1840  }
1841  }
1842  }
1843 }
1844 
1846 {
1847  ShaderOutput *density_out = output("Density");
1848  ShaderOutput *color_out = output("Color");
1849 
1850  const bool use_density = !density_out->links.empty();
1851  const bool use_color = !color_out->links.empty();
1852 
1853  if (use_density || use_color) {
1854  if (handle.empty()) {
1855  ImageManager *image_manager = compiler.scene->image_manager;
1856  handle = image_manager->add_image(filename.string(), image_params());
1857  }
1858 
1859  compiler.parameter_texture("filename", handle);
1860  if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
1861  compiler.parameter("mapping", tfm);
1862  compiler.parameter("use_mapping", 1);
1863  }
1864  compiler.parameter(this, "interpolation");
1865  compiler.add(this, "node_voxel_texture");
1866  }
1867 }
1868 
1869 /* Normal */
1870 
1872 {
1874 
1875  SOCKET_VECTOR(direction, "direction", zero_float3());
1876 
1877  SOCKET_IN_NORMAL(normal, "Normal", zero_float3());
1878 
1879  SOCKET_OUT_NORMAL(normal, "Normal");
1880  SOCKET_OUT_FLOAT(dot, "Dot");
1881 
1882  return type;
1883 }
1884 
1885 NormalNode::NormalNode() : ShaderNode(get_node_type())
1886 {
1887 }
1888 
1889 void NormalNode::compile(SVMCompiler &compiler)
1890 {
1891  ShaderInput *normal_in = input("Normal");
1892  ShaderOutput *normal_out = output("Normal");
1893  ShaderOutput *dot_out = output("Dot");
1894 
1895  compiler.add_node(NODE_NORMAL,
1896  compiler.stack_assign(normal_in),
1897  compiler.stack_assign(normal_out),
1898  compiler.stack_assign(dot_out));
1899  compiler.add_node(
1900  __float_as_int(direction.x), __float_as_int(direction.y), __float_as_int(direction.z));
1901 }
1902 
1903 void NormalNode::compile(OSLCompiler &compiler)
1904 {
1905  compiler.parameter(this, "direction");
1906  compiler.add(this, "node_normal");
1907 }
1908 
1909 /* Mapping */
1910 
1912 {
1914 
1915  static NodeEnum type_enum;
1916  type_enum.insert("point", NODE_MAPPING_TYPE_POINT);
1917  type_enum.insert("texture", NODE_MAPPING_TYPE_TEXTURE);
1918  type_enum.insert("vector", NODE_MAPPING_TYPE_VECTOR);
1919  type_enum.insert("normal", NODE_MAPPING_TYPE_NORMAL);
1920  SOCKET_ENUM(mapping_type, "Type", type_enum, NODE_MAPPING_TYPE_POINT);
1921 
1922  SOCKET_IN_POINT(vector, "Vector", zero_float3());
1923  SOCKET_IN_POINT(location, "Location", zero_float3());
1924  SOCKET_IN_POINT(rotation, "Rotation", zero_float3());
1925  SOCKET_IN_POINT(scale, "Scale", one_float3());
1926 
1927  SOCKET_OUT_POINT(vector, "Vector");
1928 
1929  return type;
1930 }
1931 
1932 MappingNode::MappingNode() : ShaderNode(get_node_type())
1933 {
1934 }
1935 
1937 {
1938  if (folder.all_inputs_constant()) {
1939  float3 result = svm_mapping((NodeMappingType)mapping_type, vector, location, rotation, scale);
1940  folder.make_constant(result);
1941  }
1942  else {
1943  folder.fold_mapping((NodeMappingType)mapping_type);
1944  }
1945 }
1946 
1947 void MappingNode::compile(SVMCompiler &compiler)
1948 {
1949  ShaderInput *vector_in = input("Vector");
1950  ShaderInput *location_in = input("Location");
1951  ShaderInput *rotation_in = input("Rotation");
1952  ShaderInput *scale_in = input("Scale");
1953  ShaderOutput *vector_out = output("Vector");
1954 
1955  int vector_stack_offset = compiler.stack_assign(vector_in);
1956  int location_stack_offset = compiler.stack_assign(location_in);
1957  int rotation_stack_offset = compiler.stack_assign(rotation_in);
1958  int scale_stack_offset = compiler.stack_assign(scale_in);
1959  int result_stack_offset = compiler.stack_assign(vector_out);
1960 
1961  compiler.add_node(
1962  NODE_MAPPING,
1963  mapping_type,
1964  compiler.encode_uchar4(
1965  vector_stack_offset, location_stack_offset, rotation_stack_offset, scale_stack_offset),
1966  result_stack_offset);
1967 }
1968 
1969 void MappingNode::compile(OSLCompiler &compiler)
1970 {
1971  compiler.parameter(this, "mapping_type");
1972  compiler.add(this, "node_mapping");
1973 }
1974 
1975 /* RGBToBW */
1976 
1978 {
1980 
1981  SOCKET_IN_COLOR(color, "Color", zero_float3());
1982  SOCKET_OUT_FLOAT(val, "Val");
1983 
1984  return type;
1985 }
1986 
1987 RGBToBWNode::RGBToBWNode() : ShaderNode(get_node_type())
1988 {
1989 }
1990 
1992 {
1993  if (folder.all_inputs_constant()) {
1994  float val = folder.scene->shader_manager->linear_rgb_to_gray(color);
1995  folder.make_constant(val);
1996  }
1997 }
1998 
1999 void RGBToBWNode::compile(SVMCompiler &compiler)
2000 {
2001  compiler.add_node(NODE_CONVERT,
2003  compiler.stack_assign(inputs[0]),
2004  compiler.stack_assign(outputs[0]));
2005 }
2006 
2007 void RGBToBWNode::compile(OSLCompiler &compiler)
2008 {
2009  compiler.add(this, "node_rgb_to_bw");
2010 }
2011 
2012 /* Convert */
2013 
2014 const NodeType *ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
2015 bool ConvertNode::initialized = ConvertNode::register_types();
2016 
2017 Node *ConvertNode::create(const NodeType *type)
2018 {
2019  return new ConvertNode(type->inputs[0].type, type->outputs[0].type);
2020 }
2021 
2022 bool ConvertNode::register_types()
2023 {
2024  const int num_types = 8;
2033 
2034  for (size_t i = 0; i < num_types; i++) {
2035  SocketType::Type from = types[i];
2036  ustring from_name(SocketType::type_name(from));
2037  ustring from_value_name("value_" + from_name.string());
2038 
2039  for (size_t j = 0; j < num_types; j++) {
2040  SocketType::Type to = types[j];
2041  ustring to_name(SocketType::type_name(to));
2042  ustring to_value_name("value_" + to_name.string());
2043 
2044  string node_name = "convert_" + from_name.string() + "_to_" + to_name.string();
2045  NodeType *type = NodeType::add(node_name.c_str(), create, NodeType::SHADER);
2046 
2047  type->register_input(from_value_name,
2048  from_value_name,
2049  from,
2052  NULL,
2053  NULL,
2055  type->register_output(to_value_name, to_value_name, to);
2056 
2057  assert(from < MAX_TYPE);
2058  assert(to < MAX_TYPE);
2059 
2060  node_types[from][to] = type;
2061  }
2062  }
2063 
2064  return true;
2065 }
2066 
2068  : ShaderNode(node_types[from_][to_])
2069 {
2070  from = from_;
2071  to = to_;
2072 
2073  if (from == to)
2075  else if (autoconvert)
2077 }
2078 
2079 /* Union usage requires a manual copy constructor. */
2081  : ShaderNode(other),
2082  from(other.from),
2083  to(other.to),
2084  value_color(other.value_color),
2085  value_string(other.value_string)
2086 {
2087 }
2088 
2090 {
2091  /* proxy nodes should have been removed at this point */
2093 
2094  /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
2095 
2096  if (folder.all_inputs_constant()) {
2097  if (from == SocketType::FLOAT) {
2098  if (SocketType::is_float3(to)) {
2100  }
2101  }
2102  else if (SocketType::is_float3(from)) {
2103  if (to == SocketType::FLOAT) {
2104  if (from == SocketType::COLOR) {
2105  /* color to float */
2106  float val = folder.scene->shader_manager->linear_rgb_to_gray(value_color);
2107  folder.make_constant(val);
2108  }
2109  else {
2110  /* vector/point/normal to float */
2112  }
2113  }
2114  else if (SocketType::is_float3(to)) {
2115  folder.make_constant(value_color);
2116  }
2117  }
2118  }
2119  else {
2120  ShaderInput *in = inputs[0];
2121  ShaderNode *prev = in->link->parent;
2122 
2123  /* no-op conversion of A to B to A */
2124  if (prev->type == node_types[to][from]) {
2125  ShaderInput *prev_in = prev->inputs[0];
2126 
2128  prev_in->link) {
2129  folder.bypass(prev_in->link);
2130  }
2131  }
2132  }
2133 }
2134 
2135 void ConvertNode::compile(SVMCompiler &compiler)
2136 {
2137  /* proxy nodes should have been removed at this point */
2139 
2140  ShaderInput *in = inputs[0];
2141  ShaderOutput *out = outputs[0];
2142 
2143  if (from == SocketType::FLOAT) {
2144  if (to == SocketType::INT)
2145  /* float to int */
2146  compiler.add_node(
2147  NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
2148  else
2149  /* float to float3 */
2150  compiler.add_node(
2151  NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
2152  }
2153  else if (from == SocketType::INT) {
2154  if (to == SocketType::FLOAT)
2155  /* int to float */
2156  compiler.add_node(
2157  NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
2158  else
2159  /* int to vector/point/normal */
2160  compiler.add_node(
2161  NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
2162  }
2163  else if (to == SocketType::FLOAT) {
2164  if (from == SocketType::COLOR)
2165  /* color to float */
2166  compiler.add_node(
2167  NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
2168  else
2169  /* vector/point/normal to float */
2170  compiler.add_node(
2171  NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
2172  }
2173  else if (to == SocketType::INT) {
2174  if (from == SocketType::COLOR)
2175  /* color to int */
2176  compiler.add_node(
2177  NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
2178  else
2179  /* vector/point/normal to int */
2180  compiler.add_node(
2181  NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out));
2182  }
2183  else {
2184  /* float3 to float3 */
2185  if (in->link) {
2186  /* no op in SVM */
2187  compiler.stack_link(in, out);
2188  }
2189  else {
2190  /* set 0,0,0 value */
2191  compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
2192  compiler.add_node(NODE_VALUE_V, value_color);
2193  }
2194  }
2195 }
2196 
2197 void ConvertNode::compile(OSLCompiler &compiler)
2198 {
2199  /* proxy nodes should have been removed at this point */
2201 
2202  if (from == SocketType::FLOAT)
2203  compiler.add(this, "node_convert_from_float");
2204  else if (from == SocketType::INT)
2205  compiler.add(this, "node_convert_from_int");
2206  else if (from == SocketType::COLOR)
2207  compiler.add(this, "node_convert_from_color");
2208  else if (from == SocketType::VECTOR)
2209  compiler.add(this, "node_convert_from_vector");
2210  else if (from == SocketType::POINT)
2211  compiler.add(this, "node_convert_from_point");
2212  else if (from == SocketType::NORMAL)
2213  compiler.add(this, "node_convert_from_normal");
2214  else
2215  assert(0);
2216 }
2217 
2218 /* Base type for all closure-type nodes */
2219 
2220 BsdfBaseNode::BsdfBaseNode(const NodeType *node_type) : ShaderNode(node_type)
2221 {
2223 }
2224 
2226 {
2227  /* detect if anything is plugged into the normal input besides the default */
2228  ShaderInput *normal_in = input("Normal");
2229  return (normal_in && normal_in->link &&
2231 }
2232 
2233 /* BSDF Closure */
2234 
2235 BsdfNode::BsdfNode(const NodeType *node_type) : BsdfBaseNode(node_type)
2236 {
2237 }
2238 
2240  ShaderInput *param1,
2241  ShaderInput *param2,
2242  ShaderInput *param3,
2243  ShaderInput *param4)
2244 {
2245  ShaderInput *color_in = input("Color");
2246  ShaderInput *normal_in = input("Normal");
2247  ShaderInput *tangent_in = input("Tangent");
2248 
2249  if (color_in->link)
2250  compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
2251  else
2252  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
2253 
2254  int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID;
2255  int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) :
2257  int param3_offset = (param3) ? compiler.stack_assign(param3) : SVM_STACK_INVALID;
2258  int param4_offset = (param4) ? compiler.stack_assign(param4) : SVM_STACK_INVALID;
2259 
2260  compiler.add_node(
2261  NODE_CLOSURE_BSDF,
2262  compiler.encode_uchar4(closure,
2263  (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID,
2264  (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID,
2265  compiler.closure_mix_weight_offset()),
2266  __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f),
2267  __float_as_int((param2) ? get_float(param2->socket_type) : 0.0f));
2268 
2269  compiler.add_node(normal_offset, tangent_offset, param3_offset, param4_offset);
2270 }
2271 
2272 void BsdfNode::compile(SVMCompiler &compiler)
2273 {
2274  compile(compiler, NULL, NULL);
2275 }
2276 
2277 void BsdfNode::compile(OSLCompiler & /*compiler*/)
2278 {
2279  assert(0);
2280 }
2281 
2282 /* Anisotropic BSDF Closure */
2283 
2285 {
2286  NodeType *type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER);
2287 
2288  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2290  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2291 
2292  static NodeEnum distribution_enum;
2293  distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
2294  distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
2295  distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
2296  distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
2297  SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
2298 
2299  SOCKET_IN_VECTOR(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
2300 
2301  SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
2302  SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
2303  SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
2304 
2305  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2306 
2307  return type;
2308 }
2309 
2310 AnisotropicBsdfNode::AnisotropicBsdfNode() : BsdfNode(get_node_type())
2311 {
2313 }
2314 
2316 {
2317  if (shader->has_surface_link()) {
2318  ShaderInput *tangent_in = input("Tangent");
2319 
2320  if (!tangent_in->link)
2322  }
2323 
2325 }
2326 
2328 {
2329  closure = distribution;
2330 
2333  compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
2334  else
2335  BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
2336 }
2337 
2339 {
2340  compiler.parameter(this, "distribution");
2341  compiler.add(this, "node_anisotropic_bsdf");
2342 }
2343 
2344 /* Glossy BSDF Closure */
2345 
2347 {
2348  NodeType *type = NodeType::add("glossy_bsdf", create, NodeType::SHADER);
2349 
2350  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2352  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2353 
2354  static NodeEnum distribution_enum;
2355  distribution_enum.insert("sharp", CLOSURE_BSDF_REFLECTION_ID);
2356  distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
2357  distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
2358  distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
2359  distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
2360  SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
2361  SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
2362 
2363  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2364 
2365  return type;
2366 }
2367 
2368 GlossyBsdfNode::GlossyBsdfNode() : BsdfNode(get_node_type())
2369 {
2371  distribution_orig = NBUILTIN_CLOSURES;
2372 }
2373 
2375 {
2376  if (distribution_orig == NBUILTIN_CLOSURES) {
2377  roughness_orig = roughness;
2378  distribution_orig = distribution;
2379  }
2380  else {
2381  /* By default we use original values, so we don't worry about restoring
2382  * defaults later one and can only do override when needed.
2383  */
2384  roughness = roughness_orig;
2385  distribution = distribution_orig;
2386  }
2387  Integrator *integrator = scene->integrator;
2388  ShaderInput *roughness_input = input("Roughness");
2389  if (integrator->get_filter_glossy() == 0.0f) {
2390  /* Fallback to Sharp closure for Roughness close to 0.
2391  * NOTE: Keep the epsilon in sync with kernel!
2392  */
2393  if (!roughness_input->link && roughness <= 1e-4f) {
2394  VLOG_DEBUG << "Using sharp glossy BSDF.";
2395  distribution = CLOSURE_BSDF_REFLECTION_ID;
2396  }
2397  }
2398  else {
2399  /* If filter glossy is used we replace Sharp glossy with GGX so we can
2400  * benefit from closure blur to remove unwanted noise.
2401  */
2402  if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFLECTION_ID) {
2403  VLOG_DEBUG << "Using GGX glossy with filter glossy.";
2404  distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
2405  roughness = 0.0f;
2406  }
2407  }
2408  closure = distribution;
2409 }
2410 
2412 {
2413  ShaderInput *roughness_input = input("Roughness");
2414  return !roughness_input->link &&
2415  (distribution == CLOSURE_BSDF_REFLECTION_ID || roughness <= 1e-4f);
2416 }
2417 
2418 void GlossyBsdfNode::compile(SVMCompiler &compiler)
2419 {
2420  closure = distribution;
2421 
2423  BsdfNode::compile(compiler, NULL, NULL);
2425  BsdfNode::compile(compiler, input("Roughness"), NULL, NULL, input("Color"));
2426  else
2427  BsdfNode::compile(compiler, input("Roughness"), NULL);
2428 }
2429 
2430 void GlossyBsdfNode::compile(OSLCompiler &compiler)
2431 {
2432  compiler.parameter(this, "distribution");
2433  compiler.add(this, "node_glossy_bsdf");
2434 }
2435 
2436 /* Glass BSDF Closure */
2437 
2439 {
2440  NodeType *type = NodeType::add("glass_bsdf", create, NodeType::SHADER);
2441 
2442  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2444  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2445 
2446  static NodeEnum distribution_enum;
2447  distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
2448  distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
2449  distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
2450  distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
2451  SOCKET_ENUM(
2452  distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
2453  SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
2454  SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
2455 
2456  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2457 
2458  return type;
2459 }
2460 
2461 GlassBsdfNode::GlassBsdfNode() : BsdfNode(get_node_type())
2462 {
2463  closure = CLOSURE_BSDF_SHARP_GLASS_ID;
2464  distribution_orig = NBUILTIN_CLOSURES;
2465 }
2466 
2468 {
2469  if (distribution_orig == NBUILTIN_CLOSURES) {
2470  roughness_orig = roughness;
2471  distribution_orig = distribution;
2472  }
2473  else {
2474  /* By default we use original values, so we don't worry about restoring
2475  * defaults later one and can only do override when needed.
2476  */
2477  roughness = roughness_orig;
2478  distribution = distribution_orig;
2479  }
2480  Integrator *integrator = scene->integrator;
2481  ShaderInput *roughness_input = input("Roughness");
2482  if (integrator->get_filter_glossy() == 0.0f) {
2483  /* Fallback to Sharp closure for Roughness close to 0.
2484  * NOTE: Keep the epsilon in sync with kernel!
2485  */
2486  if (!roughness_input->link && roughness <= 1e-4f) {
2487  VLOG_DEBUG << "Using sharp glass BSDF.";
2488  distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
2489  }
2490  }
2491  else {
2492  /* If filter glossy is used we replace Sharp glossy with GGX so we can
2493  * benefit from closure blur to remove unwanted noise.
2494  */
2495  if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_SHARP_GLASS_ID) {
2496  VLOG_DEBUG << "Using GGX glass with filter glossy.";
2497  distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
2498  roughness = 0.0f;
2499  }
2500  }
2501  closure = distribution;
2502 }
2503 
2505 {
2506  ShaderInput *roughness_input = input("Roughness");
2507  return !roughness_input->link &&
2508  (distribution == CLOSURE_BSDF_SHARP_GLASS_ID || roughness <= 1e-4f);
2509 }
2510 
2511 void GlassBsdfNode::compile(SVMCompiler &compiler)
2512 {
2513  closure = distribution;
2514 
2516  BsdfNode::compile(compiler, NULL, input("IOR"));
2518  BsdfNode::compile(compiler, input("Roughness"), input("IOR"), input("Color"));
2519  else
2520  BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
2521 }
2522 
2523 void GlassBsdfNode::compile(OSLCompiler &compiler)
2524 {
2525  compiler.parameter(this, "distribution");
2526  compiler.add(this, "node_glass_bsdf");
2527 }
2528 
2529 /* Refraction BSDF Closure */
2530 
2532 {
2533  NodeType *type = NodeType::add("refraction_bsdf", create, NodeType::SHADER);
2534 
2535  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2537  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2538 
2539  static NodeEnum distribution_enum;
2540  distribution_enum.insert("sharp", CLOSURE_BSDF_REFRACTION_ID);
2541  distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
2542  distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
2543  SOCKET_ENUM(
2544  distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
2545 
2546  SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
2547  SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
2548 
2549  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2550 
2551  return type;
2552 }
2553 
2554 RefractionBsdfNode::RefractionBsdfNode() : BsdfNode(get_node_type())
2555 {
2556  closure = CLOSURE_BSDF_REFRACTION_ID;
2557  distribution_orig = NBUILTIN_CLOSURES;
2558 }
2559 
2561 {
2562  if (distribution_orig == NBUILTIN_CLOSURES) {
2563  roughness_orig = roughness;
2564  distribution_orig = distribution;
2565  }
2566  else {
2567  /* By default we use original values, so we don't worry about restoring
2568  * defaults later one and can only do override when needed.
2569  */
2570  roughness = roughness_orig;
2571  distribution = distribution_orig;
2572  }
2573  Integrator *integrator = scene->integrator;
2574  ShaderInput *roughness_input = input("Roughness");
2575  if (integrator->get_filter_glossy() == 0.0f) {
2576  /* Fallback to Sharp closure for Roughness close to 0.
2577  * NOTE: Keep the epsilon in sync with kernel!
2578  */
2579  if (!roughness_input->link && roughness <= 1e-4f) {
2580  VLOG_DEBUG << "Using sharp refraction BSDF.";
2581  distribution = CLOSURE_BSDF_REFRACTION_ID;
2582  }
2583  }
2584  else {
2585  /* If filter glossy is used we replace Sharp glossy with GGX so we can
2586  * benefit from closure blur to remove unwanted noise.
2587  */
2588  if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFRACTION_ID) {
2589  VLOG_DEBUG << "Using GGX refraction with filter glossy.";
2591  roughness = 0.0f;
2592  }
2593  }
2594  closure = distribution;
2595 }
2596 
2598 {
2599  ShaderInput *roughness_input = input("Roughness");
2600  return !roughness_input->link &&
2601  (distribution == CLOSURE_BSDF_REFRACTION_ID || roughness <= 1e-4f);
2602 }
2603 
2605 {
2606  closure = distribution;
2607 
2609  BsdfNode::compile(compiler, NULL, input("IOR"));
2610  else
2611  BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
2612 }
2613 
2615 {
2616  compiler.parameter(this, "distribution");
2617  compiler.add(this, "node_refraction_bsdf");
2618 }
2619 
2620 /* Toon BSDF Closure */
2621 
2623 {
2625 
2626  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2628  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2629 
2630  static NodeEnum component_enum;
2631  component_enum.insert("diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
2632  component_enum.insert("glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
2633  SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_DIFFUSE_TOON_ID);
2634  SOCKET_IN_FLOAT(size, "Size", 0.5f);
2635  SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
2636 
2637  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2638 
2639  return type;
2640 }
2641 
2642 ToonBsdfNode::ToonBsdfNode() : BsdfNode(get_node_type())
2643 {
2644  closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
2645 }
2646 
2647 void ToonBsdfNode::compile(SVMCompiler &compiler)
2648 {
2649  closure = component;
2650 
2651  BsdfNode::compile(compiler, input("Size"), input("Smooth"));
2652 }
2653 
2654 void ToonBsdfNode::compile(OSLCompiler &compiler)
2655 {
2656  compiler.parameter(this, "component");
2657  compiler.add(this, "node_toon_bsdf");
2658 }
2659 
2660 /* Velvet BSDF Closure */
2661 
2663 {
2664  NodeType *type = NodeType::add("velvet_bsdf", create, NodeType::SHADER);
2665 
2666  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2668  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2669  SOCKET_IN_FLOAT(sigma, "Sigma", 1.0f);
2670 
2671  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2672 
2673  return type;
2674 }
2675 
2676 VelvetBsdfNode::VelvetBsdfNode() : BsdfNode(get_node_type())
2677 {
2679 }
2680 
2681 void VelvetBsdfNode::compile(SVMCompiler &compiler)
2682 {
2683  BsdfNode::compile(compiler, input("Sigma"), NULL);
2684 }
2685 
2686 void VelvetBsdfNode::compile(OSLCompiler &compiler)
2687 {
2688  compiler.add(this, "node_velvet_bsdf");
2689 }
2690 
2691 /* Diffuse BSDF Closure */
2692 
2694 {
2695  NodeType *type = NodeType::add("diffuse_bsdf", create, NodeType::SHADER);
2696 
2697  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2699  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2700  SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
2701 
2702  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2703 
2704  return type;
2705 }
2706 
2707 DiffuseBsdfNode::DiffuseBsdfNode() : BsdfNode(get_node_type())
2708 {
2709  closure = CLOSURE_BSDF_DIFFUSE_ID;
2710 }
2711 
2712 void DiffuseBsdfNode::compile(SVMCompiler &compiler)
2713 {
2714  BsdfNode::compile(compiler, input("Roughness"), NULL);
2715 }
2716 
2717 void DiffuseBsdfNode::compile(OSLCompiler &compiler)
2718 {
2719  compiler.add(this, "node_diffuse_bsdf");
2720 }
2721 
2722 /* Disney principled BSDF Closure */
2724 {
2725  NodeType *type = NodeType::add("principled_bsdf", create, NodeType::SHADER);
2726 
2727  static NodeEnum distribution_enum;
2728  distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
2729  distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
2730  SOCKET_ENUM(
2731  distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
2732 
2733  static NodeEnum subsurface_method_enum;
2734  subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
2735  subsurface_method_enum.insert("random_walk_fixed_radius",
2737  subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
2738  SOCKET_ENUM(subsurface_method,
2739  "Subsurface Method",
2740  subsurface_method_enum,
2742 
2743  SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
2744  SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
2745  SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
2746  SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
2747  SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
2748  SOCKET_IN_FLOAT(subsurface_ior, "Subsurface IOR", 1.4f);
2749  SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
2750  SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
2751  SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
2752  SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
2753  SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
2754  SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
2755  SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
2756  SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
2757  SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
2758  SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
2759  SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
2760  SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f);
2761  SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
2762  SOCKET_IN_COLOR(emission, "Emission", zero_float3());
2763  SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 1.0f);
2764  SOCKET_IN_FLOAT(alpha, "Alpha", 1.0f);
2766  SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", zero_float3(), SocketType::LINK_NORMAL);
2767  SOCKET_IN_NORMAL(tangent, "Tangent", zero_float3(), SocketType::LINK_TANGENT);
2768  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2769 
2770  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
2771 
2772  return type;
2773 }
2774 
2775 PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(get_node_type())
2776 {
2777  closure = CLOSURE_BSDF_PRINCIPLED_ID;
2779  distribution_orig = NBUILTIN_CLOSURES;
2780 }
2781 
2783 {
2784  ShaderOutput *principled_out = output("BSDF");
2785 
2786  ShaderInput *emission_in = input("Emission");
2787  ShaderInput *emission_strength_in = input("Emission Strength");
2788  if ((emission_in->link || emission != zero_float3()) &&
2789  (emission_strength_in->link || emission_strength != 0.0f)) {
2790  /* Create add closure and emission, and relink inputs. */
2791  AddClosureNode *add = graph->create_node<AddClosureNode>();
2792  EmissionNode *emission_node = graph->create_node<EmissionNode>();
2793  ShaderOutput *new_out = add->output("Closure");
2794 
2795  graph->add(add);
2796  graph->add(emission_node);
2797 
2798  graph->relink(emission_strength_in, emission_node->input("Strength"));
2799  graph->relink(emission_in, emission_node->input("Color"));
2800  graph->relink(principled_out, new_out);
2801  graph->connect(emission_node->output("Emission"), add->input("Closure1"));
2802  graph->connect(principled_out, add->input("Closure2"));
2803 
2804  principled_out = new_out;
2805  }
2806  else {
2807  /* Disconnect unused links if the other value is zero, required before
2808  * we remove the input from the node entirely. */
2809  if (emission_in->link) {
2810  emission_in->disconnect();
2811  }
2812  if (emission_strength_in->link) {
2813  emission_strength_in->disconnect();
2814  }
2815  }
2816 
2817  ShaderInput *alpha_in = input("Alpha");
2818  if (alpha_in->link || alpha != 1.0f) {
2819  /* Create mix and transparent BSDF for alpha transparency. */
2820  MixClosureNode *mix = graph->create_node<MixClosureNode>();
2821  TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
2822 
2823  graph->add(mix);
2824  graph->add(transparent);
2825 
2826  graph->relink(alpha_in, mix->input("Fac"));
2827  graph->relink(principled_out, mix->output("Closure"));
2828  graph->connect(transparent->output("BSDF"), mix->input("Closure1"));
2829  graph->connect(principled_out, mix->input("Closure2"));
2830  }
2831 
2832  remove_input(emission_in);
2833  remove_input(emission_strength_in);
2834  remove_input(alpha_in);
2835 }
2836 
2838 {
2839  ShaderInput *subsurface_in = input("Subsurface");
2840  return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
2841 }
2842 
2844 {
2845  if (shader->has_surface_link()) {
2846  ShaderInput *tangent_in = input("Tangent");
2847 
2848  if (!tangent_in->link)
2850  }
2851 
2853 }
2854 
2856  ShaderInput *p_metallic,
2857  ShaderInput *p_subsurface,
2858  ShaderInput *p_subsurface_radius,
2859  ShaderInput *p_subsurface_ior,
2860  ShaderInput *p_subsurface_anisotropy,
2861  ShaderInput *p_specular,
2862  ShaderInput *p_roughness,
2863  ShaderInput *p_specular_tint,
2864  ShaderInput *p_anisotropic,
2865  ShaderInput *p_sheen,
2866  ShaderInput *p_sheen_tint,
2867  ShaderInput *p_clearcoat,
2868  ShaderInput *p_clearcoat_roughness,
2869  ShaderInput *p_ior,
2870  ShaderInput *p_transmission,
2871  ShaderInput *p_anisotropic_rotation,
2872  ShaderInput *p_transmission_roughness)
2873 {
2874  ShaderInput *base_color_in = input("Base Color");
2875  ShaderInput *subsurface_color_in = input("Subsurface Color");
2876  ShaderInput *normal_in = input("Normal");
2877  ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
2878  ShaderInput *tangent_in = input("Tangent");
2879 
2880  float3 weight = one_float3();
2881 
2882  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
2883 
2884  int normal_offset = compiler.stack_assign_if_linked(normal_in);
2885  int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
2886  int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
2887  int specular_offset = compiler.stack_assign(p_specular);
2888  int roughness_offset = compiler.stack_assign(p_roughness);
2889  int specular_tint_offset = compiler.stack_assign(p_specular_tint);
2890  int anisotropic_offset = compiler.stack_assign(p_anisotropic);
2891  int sheen_offset = compiler.stack_assign(p_sheen);
2892  int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
2893  int clearcoat_offset = compiler.stack_assign(p_clearcoat);
2894  int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
2895  int ior_offset = compiler.stack_assign(p_ior);
2896  int transmission_offset = compiler.stack_assign(p_transmission);
2897  int transmission_roughness_offset = compiler.stack_assign(p_transmission_roughness);
2898  int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
2899  int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
2900  int subsurface_ior_offset = compiler.stack_assign(p_subsurface_ior);
2901  int subsurface_anisotropy_offset = compiler.stack_assign(p_subsurface_anisotropy);
2902 
2903  compiler.add_node(NODE_CLOSURE_BSDF,
2904  compiler.encode_uchar4(closure,
2905  compiler.stack_assign(p_metallic),
2906  compiler.stack_assign(p_subsurface),
2907  compiler.closure_mix_weight_offset()),
2908  __float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
2909  __float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
2910 
2911  compiler.add_node(
2912  normal_offset,
2913  tangent_offset,
2914  compiler.encode_uchar4(
2915  specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
2916  compiler.encode_uchar4(
2917  sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
2918 
2919  compiler.add_node(compiler.encode_uchar4(ior_offset,
2920  transmission_offset,
2921  anisotropic_rotation_offset,
2922  transmission_roughness_offset),
2923  distribution,
2924  subsurface_method,
2926 
2927  float3 bc_default = get_float3(base_color_in->socket_type);
2928 
2929  compiler.add_node(
2930  ((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
2931  __float_as_int(bc_default.x),
2932  __float_as_int(bc_default.y),
2933  __float_as_int(bc_default.z));
2934 
2935  compiler.add_node(clearcoat_normal_offset,
2936  subsurface_radius_offset,
2937  subsurface_ior_offset,
2938  subsurface_anisotropy_offset);
2939 
2940  float3 ss_default = get_float3(subsurface_color_in->socket_type);
2941 
2942  compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) :
2944  __float_as_int(ss_default.x),
2945  __float_as_int(ss_default.y),
2946  __float_as_int(ss_default.z));
2947 }
2948 
2950 {
2951  ShaderInput *roughness_input = input("Roughness");
2952  return !roughness_input->link && roughness <= 1e-4f;
2953 }
2954 
2956 {
2957  compile(compiler,
2958  input("Metallic"),
2959  input("Subsurface"),
2960  input("Subsurface Radius"),
2961  input("Subsurface IOR"),
2962  input("Subsurface Anisotropy"),
2963  input("Specular"),
2964  input("Roughness"),
2965  input("Specular Tint"),
2966  input("Anisotropic"),
2967  input("Sheen"),
2968  input("Sheen Tint"),
2969  input("Clearcoat"),
2970  input("Clearcoat Roughness"),
2971  input("IOR"),
2972  input("Transmission"),
2973  input("Anisotropic Rotation"),
2974  input("Transmission Roughness"));
2975 }
2976 
2978 {
2979  compiler.parameter(this, "distribution");
2980  compiler.parameter(this, "subsurface_method");
2981  compiler.add(this, "node_principled_bsdf");
2982 }
2983 
2985 {
2986  return has_surface_bssrdf() && has_bump();
2987 }
2988 
2989 /* Translucent BSDF Closure */
2990 
2992 {
2993  NodeType *type = NodeType::add("translucent_bsdf", create, NodeType::SHADER);
2994 
2995  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
2997  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
2998 
2999  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3000 
3001  return type;
3002 }
3003 
3004 TranslucentBsdfNode::TranslucentBsdfNode() : BsdfNode(get_node_type())
3005 {
3006  closure = CLOSURE_BSDF_TRANSLUCENT_ID;
3007 }
3008 
3010 {
3011  BsdfNode::compile(compiler, NULL, NULL);
3012 }
3013 
3015 {
3016  compiler.add(this, "node_translucent_bsdf");
3017 }
3018 
3019 /* Transparent BSDF Closure */
3020 
3022 {
3023  NodeType *type = NodeType::add("transparent_bsdf", create, NodeType::SHADER);
3024 
3025  SOCKET_IN_COLOR(color, "Color", one_float3());
3026  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3027 
3028  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3029 
3030  return type;
3031 }
3032 
3033 TransparentBsdfNode::TransparentBsdfNode() : BsdfNode(get_node_type())
3034 {
3035  closure = CLOSURE_BSDF_TRANSPARENT_ID;
3036 }
3037 
3039 {
3040  BsdfNode::compile(compiler, NULL, NULL);
3041 }
3042 
3044 {
3045  compiler.add(this, "node_transparent_bsdf");
3046 }
3047 
3048 /* Subsurface Scattering Closure */
3049 
3051 {
3052  NodeType *type = NodeType::add("subsurface_scattering", create, NodeType::SHADER);
3053 
3054  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3056  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3057 
3058  static NodeEnum method_enum;
3059  method_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
3060  method_enum.insert("random_walk_fixed_radius", CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID);
3061  method_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
3062  SOCKET_ENUM(method, "Method", method_enum, CLOSURE_BSSRDF_RANDOM_WALK_ID);
3063 
3064  SOCKET_IN_FLOAT(scale, "Scale", 0.01f);
3065  SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f));
3066 
3067  SOCKET_IN_FLOAT(subsurface_ior, "IOR", 1.4f);
3068  SOCKET_IN_FLOAT(subsurface_anisotropy, "Anisotropy", 0.0f);
3069 
3070  SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF");
3071 
3072  return type;
3073 }
3074 
3075 SubsurfaceScatteringNode::SubsurfaceScatteringNode() : BsdfNode(get_node_type())
3076 {
3077  closure = method;
3078 }
3079 
3081 {
3082  closure = method;
3083  BsdfNode::compile(compiler, input("Scale"), input("IOR"), input("Radius"), input("Anisotropy"));
3084 }
3085 
3087 {
3088  closure = method;
3089  compiler.parameter(this, "method");
3090  compiler.add(this, "node_subsurface_scattering");
3091 }
3092 
3094 {
3095  /* detect if anything is plugged into the normal input besides the default */
3096  ShaderInput *normal_in = input("Normal");
3097  return (normal_in->link &&
3099 }
3100 
3101 /* Emissive Closure */
3102 
3104 {
3106 
3107  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3108  SOCKET_IN_FLOAT(strength, "Strength", 10.0f);
3109  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3110 
3111  SOCKET_OUT_CLOSURE(emission, "Emission");
3112 
3113  return type;
3114 }
3115 
3116 EmissionNode::EmissionNode() : ShaderNode(get_node_type())
3117 {
3118 }
3119 
3120 void EmissionNode::compile(SVMCompiler &compiler)
3121 {
3122  ShaderInput *color_in = input("Color");
3123  ShaderInput *strength_in = input("Strength");
3124 
3125  if (color_in->link || strength_in->link) {
3126  compiler.add_node(
3127  NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
3128  }
3129  else
3130  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
3131 
3132  compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
3133 }
3134 
3135 void EmissionNode::compile(OSLCompiler &compiler)
3136 {
3137  compiler.add(this, "node_emission");
3138 }
3139 
3141 {
3142  ShaderInput *color_in = input("Color");
3143  ShaderInput *strength_in = input("Strength");
3144 
3145  if ((!color_in->link && color == zero_float3()) || (!strength_in->link && strength == 0.0f)) {
3146  folder.discard();
3147  }
3148 }
3149 
3150 /* Background Closure */
3151 
3153 {
3154  NodeType *type = NodeType::add("background_shader", create, NodeType::SHADER);
3155 
3156  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3157  SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
3158  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3159 
3160  SOCKET_OUT_CLOSURE(background, "Background");
3161 
3162  return type;
3163 }
3164 
3165 BackgroundNode::BackgroundNode() : ShaderNode(get_node_type())
3166 {
3167 }
3168 
3169 void BackgroundNode::compile(SVMCompiler &compiler)
3170 {
3171  ShaderInput *color_in = input("Color");
3172  ShaderInput *strength_in = input("Strength");
3173 
3174  if (color_in->link || strength_in->link) {
3175  compiler.add_node(
3176  NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
3177  }
3178  else
3179  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
3180 
3181  compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
3182 }
3183 
3184 void BackgroundNode::compile(OSLCompiler &compiler)
3185 {
3186  compiler.add(this, "node_background");
3187 }
3188 
3190 {
3191  ShaderInput *color_in = input("Color");
3192  ShaderInput *strength_in = input("Strength");
3193 
3194  if ((!color_in->link && color == zero_float3()) || (!strength_in->link && strength == 0.0f)) {
3195  folder.discard();
3196  }
3197 }
3198 
3199 /* Holdout Closure */
3200 
3202 {
3204 
3205  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3206  SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3207 
3208  SOCKET_OUT_CLOSURE(holdout, "Holdout");
3209 
3210  return type;
3211 }
3212 
3213 HoldoutNode::HoldoutNode() : ShaderNode(get_node_type())
3214 {
3215 }
3216 
3217 void HoldoutNode::compile(SVMCompiler &compiler)
3218 {
3219  float3 value = one_float3();
3220 
3221  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value);
3222  compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
3223 }
3224 
3225 void HoldoutNode::compile(OSLCompiler &compiler)
3226 {
3227  compiler.add(this, "node_holdout");
3228 }
3229 
3230 /* Ambient Occlusion */
3231 
3233 {
3234  NodeType *type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
3235 
3236  SOCKET_INT(samples, "Samples", 16);
3237 
3238  SOCKET_IN_COLOR(color, "Color", one_float3());
3239  SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
3241 
3242  SOCKET_BOOLEAN(inside, "Inside", false);
3243  SOCKET_BOOLEAN(only_local, "Only Local", false);
3244 
3245  SOCKET_OUT_COLOR(color, "Color");
3246  SOCKET_OUT_FLOAT(ao, "AO");
3247 
3248  return type;
3249 }
3250 
3251 AmbientOcclusionNode::AmbientOcclusionNode() : ShaderNode(get_node_type())
3252 {
3253 }
3254 
3256 {
3257  ShaderInput *color_in = input("Color");
3258  ShaderInput *distance_in = input("Distance");
3259  ShaderInput *normal_in = input("Normal");
3260  ShaderOutput *color_out = output("Color");
3261  ShaderOutput *ao_out = output("AO");
3262 
3263  int flags = (inside ? NODE_AO_INSIDE : 0) | (only_local ? NODE_AO_ONLY_LOCAL : 0);
3264 
3265  if (!distance_in->link && distance == 0.0f) {
3266  flags |= NODE_AO_GLOBAL_RADIUS;
3267  }
3268 
3269  compiler.add_node(NODE_AMBIENT_OCCLUSION,
3270  compiler.encode_uchar4(flags,
3271  compiler.stack_assign_if_linked(distance_in),
3272  compiler.stack_assign_if_linked(normal_in),
3273  compiler.stack_assign(ao_out)),
3274  compiler.encode_uchar4(compiler.stack_assign(color_in),
3275  compiler.stack_assign(color_out),
3276  samples),
3278 }
3279 
3281 {
3282  compiler.parameter(this, "samples");
3283  compiler.parameter(this, "inside");
3284  compiler.parameter(this, "only_local");
3285  compiler.add(this, "node_ambient_occlusion");
3286 }
3287 
3288 /* Volume Closure */
3289 
3290 VolumeNode::VolumeNode(const NodeType *node_type) : ShaderNode(node_type)
3291 {
3293 }
3294 
3295 void VolumeNode::compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2)
3296 {
3297  ShaderInput *color_in = input("Color");
3298 
3299  if (color_in->link)
3300  compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
3301  else
3302  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
3303 
3304  compiler.add_node(
3305  NODE_CLOSURE_VOLUME,
3306  compiler.encode_uchar4(closure,
3307  (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID,
3308  (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID,
3309  compiler.closure_mix_weight_offset()),
3310  __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f),
3311  __float_as_int((param2) ? get_float(param2->socket_type) : 0.0f));
3312 }
3313 
3314 void VolumeNode::compile(SVMCompiler &compiler)
3315 {
3316  compile(compiler, NULL, NULL);
3317 }
3318 
3319 void VolumeNode::compile(OSLCompiler & /*compiler*/)
3320 {
3321  assert(0);
3322 }
3323 
3324 /* Absorption Volume Closure */
3325 
3327 {
3328  NodeType *type = NodeType::add("absorption_volume", create, NodeType::SHADER);
3329 
3330  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3331  SOCKET_IN_FLOAT(density, "Density", 1.0f);
3332  SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3333 
3334  SOCKET_OUT_CLOSURE(volume, "Volume");
3335 
3336  return type;
3337 }
3338 
3339 AbsorptionVolumeNode::AbsorptionVolumeNode() : VolumeNode(get_node_type())
3340 {
3341  closure = CLOSURE_VOLUME_ABSORPTION_ID;
3342 }
3343 
3345 {
3346  VolumeNode::compile(compiler, input("Density"), NULL);
3347 }
3348 
3350 {
3351  compiler.add(this, "node_absorption_volume");
3352 }
3353 
3354 /* Scatter Volume Closure */
3355 
3357 {
3358  NodeType *type = NodeType::add("scatter_volume", create, NodeType::SHADER);
3359 
3360  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3361  SOCKET_IN_FLOAT(density, "Density", 1.0f);
3362  SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
3363  SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3364 
3365  SOCKET_OUT_CLOSURE(volume, "Volume");
3366 
3367  return type;
3368 }
3369 
3370 ScatterVolumeNode::ScatterVolumeNode() : VolumeNode(get_node_type())
3371 {
3373 }
3374 
3376 {
3377  VolumeNode::compile(compiler, input("Density"), input("Anisotropy"));
3378 }
3379 
3381 {
3382  compiler.add(this, "node_scatter_volume");
3383 }
3384 
3385 /* Principled Volume Closure */
3386 
3388 {
3389  NodeType *type = NodeType::add("principled_volume", create, NodeType::SHADER);
3390 
3391  SOCKET_IN_STRING(density_attribute, "Density Attribute", ustring());
3392  SOCKET_IN_STRING(color_attribute, "Color Attribute", ustring());
3393  SOCKET_IN_STRING(temperature_attribute, "Temperature Attribute", ustring());
3394 
3395  SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 0.5f));
3396  SOCKET_IN_FLOAT(density, "Density", 1.0f);
3397  SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
3398  SOCKET_IN_COLOR(absorption_color, "Absorption Color", zero_float3());
3399  SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
3400  SOCKET_IN_COLOR(emission_color, "Emission Color", one_float3());
3401  SOCKET_IN_FLOAT(blackbody_intensity, "Blackbody Intensity", 0.0f);
3402  SOCKET_IN_COLOR(blackbody_tint, "Blackbody Tint", one_float3());
3403  SOCKET_IN_FLOAT(temperature, "Temperature", 1000.0f);
3404  SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3405 
3406  SOCKET_OUT_CLOSURE(volume, "Volume");
3407 
3408  return type;
3409 }
3410 
3411 PrincipledVolumeNode::PrincipledVolumeNode() : VolumeNode(get_node_type())
3412 {
3414  density_attribute = ustring("density");
3415  temperature_attribute = ustring("temperature");
3416 }
3417 
3419 {
3420  if (shader->has_volume) {
3421  ShaderInput *density_in = input("Density");
3422  ShaderInput *blackbody_in = input("Blackbody Intensity");
3423 
3424  if (density_in->link || density > 0.0f) {
3425  attributes->add_standard(density_attribute);
3426  attributes->add_standard(color_attribute);
3427  }
3428 
3429  if (blackbody_in->link || blackbody_intensity > 0.0f) {
3430  attributes->add_standard(temperature_attribute);
3431  }
3432 
3434  }
3435 
3437 }
3438 
3440 {
3441  ShaderInput *color_in = input("Color");
3442  ShaderInput *density_in = input("Density");
3443  ShaderInput *anisotropy_in = input("Anisotropy");
3444  ShaderInput *absorption_color_in = input("Absorption Color");
3445  ShaderInput *emission_in = input("Emission Strength");
3446  ShaderInput *emission_color_in = input("Emission Color");
3447  ShaderInput *blackbody_in = input("Blackbody Intensity");
3448  ShaderInput *blackbody_tint_in = input("Blackbody Tint");
3449  ShaderInput *temperature_in = input("Temperature");
3450 
3451  if (color_in->link)
3452  compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
3453  else
3454  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
3455 
3456  compiler.add_node(NODE_PRINCIPLED_VOLUME,
3457  compiler.encode_uchar4(compiler.stack_assign_if_linked(density_in),
3458  compiler.stack_assign_if_linked(anisotropy_in),
3459  compiler.stack_assign(absorption_color_in),
3460  compiler.closure_mix_weight_offset()),
3461  compiler.encode_uchar4(compiler.stack_assign_if_linked(emission_in),
3462  compiler.stack_assign(emission_color_in),
3463  compiler.stack_assign_if_linked(blackbody_in),
3464  compiler.stack_assign(temperature_in)),
3465  compiler.stack_assign(blackbody_tint_in));
3466 
3467  int attr_density = compiler.attribute_standard(density_attribute);
3468  int attr_color = compiler.attribute_standard(color_attribute);
3469  int attr_temperature = compiler.attribute_standard(temperature_attribute);
3470 
3471  compiler.add_node(__float_as_int(density),
3472  __float_as_int(anisotropy),
3473  __float_as_int(emission_strength),
3474  __float_as_int(blackbody_intensity));
3475 
3476  compiler.add_node(attr_density, attr_color, attr_temperature);
3477 }
3478 
3480 {
3481  if (Attribute::name_standard(density_attribute.c_str())) {
3482  density_attribute = ustring("geom:" + density_attribute.string());
3483  }
3484  if (Attribute::name_standard(color_attribute.c_str())) {
3485  color_attribute = ustring("geom:" + color_attribute.string());
3486  }
3487  if (Attribute::name_standard(temperature_attribute.c_str())) {
3488  temperature_attribute = ustring("geom:" + temperature_attribute.string());
3489  }
3490 
3491  compiler.add(this, "node_principled_volume");
3492 }
3493 
3494 /* Principled Hair BSDF Closure */
3495 
3497 {
3498  NodeType *type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
3499 
3500  /* Color parametrization specified as enum. */
3501  static NodeEnum parametrization_enum;
3502  parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
3503  parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
3504  parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
3505  SOCKET_ENUM(
3506  parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
3507 
3508  /* Initialize sockets to their default values. */
3509  SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
3510  SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
3511  SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
3512  SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
3513  SOCKET_IN_VECTOR(absorption_coefficient,
3514  "Absorption Coefficient",
3515  make_float3(0.245531f, 0.52f, 1.365f),
3517 
3518  SOCKET_IN_FLOAT(offset, "Offset", 2.f * M_PI_F / 180.f);
3519  SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
3520  SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
3521  SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
3522  SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
3523 
3524  SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
3525  SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
3526  SOCKET_IN_FLOAT(random, "Random", 0.0f);
3527 
3529  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3530 
3531  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3532 
3533  return type;
3534 }
3535 
3536 PrincipledHairBsdfNode::PrincipledHairBsdfNode() : BsdfBaseNode(get_node_type())
3537 {
3539 }
3540 
3541 /* Enable retrieving Hair Info -> Random if Random isn't linked. */
3543 {
3544  if (!input("Random")->link) {
3546  }
3548 }
3549 
3550 /* Prepares the input data for the SVM shader. */
3552 {
3553  compiler.add_node(NODE_CLOSURE_SET_WEIGHT, one_float3());
3554 
3555  ShaderInput *roughness_in = input("Roughness");
3556  ShaderInput *radial_roughness_in = input("Radial Roughness");
3557  ShaderInput *random_roughness_in = input("Random Roughness");
3558  ShaderInput *offset_in = input("Offset");
3559  ShaderInput *coat_in = input("Coat");
3560  ShaderInput *ior_in = input("IOR");
3561  ShaderInput *melanin_in = input("Melanin");
3562  ShaderInput *melanin_redness_in = input("Melanin Redness");
3563  ShaderInput *random_color_in = input("Random Color");
3564 
3565  int color_ofs = compiler.stack_assign(input("Color"));
3566  int tint_ofs = compiler.stack_assign(input("Tint"));
3567  int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
3568 
3569  int roughness_ofs = compiler.stack_assign_if_linked(roughness_in);
3570  int radial_roughness_ofs = compiler.stack_assign_if_linked(radial_roughness_in);
3571 
3572  int normal_ofs = compiler.stack_assign_if_linked(input("Normal"));
3573  int offset_ofs = compiler.stack_assign_if_linked(offset_in);
3574  int ior_ofs = compiler.stack_assign_if_linked(ior_in);
3575 
3576  int coat_ofs = compiler.stack_assign_if_linked(coat_in);
3577  int melanin_ofs = compiler.stack_assign_if_linked(melanin_in);
3578  int melanin_redness_ofs = compiler.stack_assign_if_linked(melanin_redness_in);
3579 
3580  ShaderInput *random_in = input("Random");
3581  int attr_random = random_in->link ? SVM_STACK_INVALID :
3582  compiler.attribute(ATTR_STD_CURVE_RANDOM);
3583  int random_in_ofs = compiler.stack_assign_if_linked(random_in);
3584  int random_color_ofs = compiler.stack_assign_if_linked(random_color_in);
3585  int random_roughness_ofs = compiler.stack_assign_if_linked(random_roughness_in);
3586 
3587  /* Encode all parameters into data nodes. */
3588  /* node */
3589  compiler.add_node(
3590  NODE_CLOSURE_BSDF,
3591  /* Socket IDs can be packed 4 at a time into a single data packet */
3592  compiler.encode_uchar4(
3593  closure, roughness_ofs, radial_roughness_ofs, compiler.closure_mix_weight_offset()),
3594  /* The rest are stored as unsigned integers */
3596  __float_as_uint(radial_roughness));
3597  /* data node */
3598  compiler.add_node(normal_ofs,
3599  compiler.encode_uchar4(offset_ofs, ior_ofs, color_ofs, parametrization),
3601  __float_as_uint(ior));
3602  /* data node 2 */
3603  compiler.add_node(compiler.encode_uchar4(
3604  coat_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs),
3605  __float_as_uint(coat),
3606  __float_as_uint(melanin),
3607  __float_as_uint(melanin_redness));
3608 
3609  /* data node 3 */
3610  compiler.add_node(
3611  compiler.encode_uchar4(tint_ofs, random_in_ofs, random_color_ofs, random_roughness_ofs),
3613  __float_as_uint(random_color),
3614  __float_as_uint(random_roughness));
3615 
3616  /* data node 4 */
3617  compiler.add_node(
3618  compiler.encode_uchar4(
3620  attr_random,
3623 }
3624 
3625 /* Prepares the input data for the OSL shader. */
3627 {
3628  compiler.parameter(this, "parametrization");
3629  compiler.add(this, "node_principled_hair_bsdf");
3630 }
3631 
3632 /* Hair BSDF Closure */
3633 
3635 {
3637 
3638  SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
3640  SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
3641 
3642  static NodeEnum component_enum;
3643  component_enum.insert("reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
3644  component_enum.insert("transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
3645  SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_HAIR_REFLECTION_ID);
3646  SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
3647  SOCKET_IN_FLOAT(roughness_u, "RoughnessU", 0.2f);
3648  SOCKET_IN_FLOAT(roughness_v, "RoughnessV", 0.2f);
3649  SOCKET_IN_VECTOR(tangent, "Tangent", zero_float3());
3650 
3651  SOCKET_OUT_CLOSURE(BSDF, "BSDF");
3652 
3653  return type;
3654 }
3655 
3656 HairBsdfNode::HairBsdfNode() : BsdfNode(get_node_type())
3657 {
3659 }
3660 
3661 void HairBsdfNode::compile(SVMCompiler &compiler)
3662 {
3663  closure = component;
3664 
3665  BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"));
3666 }
3667 
3668 void HairBsdfNode::compile(OSLCompiler &compiler)
3669 {
3670  compiler.parameter(this, "component");
3671  compiler.add(this, "node_hair_bsdf");
3672 }
3673 
3674 /* Geometry */
3675 
3677 {
3679 
3681  normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
3682 
3683  SOCKET_OUT_POINT(position, "Position");
3684  SOCKET_OUT_NORMAL(normal, "Normal");
3685  SOCKET_OUT_NORMAL(tangent, "Tangent");
3686  SOCKET_OUT_NORMAL(true_normal, "True Normal");
3687  SOCKET_OUT_VECTOR(incoming, "Incoming");
3688  SOCKET_OUT_POINT(parametric, "Parametric");
3689  SOCKET_OUT_FLOAT(backfacing, "Backfacing");
3690  SOCKET_OUT_FLOAT(pointiness, "Pointiness");
3691  SOCKET_OUT_FLOAT(random_per_island, "Random Per Island");
3692 
3693  return type;
3694 }
3695 
3696 GeometryNode::GeometryNode() : ShaderNode(get_node_type())
3697 {
3698  special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
3699 }
3700 
3702 {
3703  if (shader->has_surface_link()) {
3704  if (!output("Tangent")->links.empty()) {
3706  }
3707  if (!output("Pointiness")->links.empty()) {
3709  }
3710  if (!output("Random Per Island")->links.empty()) {
3712  }
3713  }
3714 
3716 }
3717 
3718 void GeometryNode::compile(SVMCompiler &compiler)
3719 {
3720  ShaderOutput *out;
3721  ShaderNodeType geom_node = NODE_GEOMETRY;
3722  ShaderNodeType attr_node = NODE_ATTR;
3723 
3724  if (bump == SHADER_BUMP_DX) {
3725  geom_node = NODE_GEOMETRY_BUMP_DX;
3726  attr_node = NODE_ATTR_BUMP_DX;
3727  }
3728  else if (bump == SHADER_BUMP_DY) {
3729  geom_node = NODE_GEOMETRY_BUMP_DY;
3730  attr_node = NODE_ATTR_BUMP_DY;
3731  }
3732 
3733  out = output("Position");
3734  if (!out->links.empty()) {
3735  compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
3736  }
3737 
3738  out = output("Normal");
3739  if (!out->links.empty()) {
3740  compiler.add_node(geom_node, NODE_GEOM_N, compiler.stack_assign(out));
3741  }
3742 
3743  out = output("Tangent");
3744  if (!out->links.empty()) {
3745  compiler.add_node(geom_node, NODE_GEOM_T, compiler.stack_assign(out));
3746  }
3747 
3748  out = output("True Normal");
3749  if (!out->links.empty()) {
3750  compiler.add_node(geom_node, NODE_GEOM_Ng, compiler.stack_assign(out));
3751  }
3752 
3753  out = output("Incoming");
3754  if (!out->links.empty()) {
3755  compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
3756  }
3757 
3758  out = output("Parametric");
3759  if (!out->links.empty()) {
3760  compiler.add_node(geom_node, NODE_GEOM_uv, compiler.stack_assign(out));
3761  }
3762 
3763  out = output("Backfacing");
3764  if (!out->links.empty()) {
3765  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_backfacing, compiler.stack_assign(out));
3766  }
3767 
3768  out = output("Pointiness");
3769  if (!out->links.empty()) {
3770  if (compiler.output_type() != SHADER_TYPE_VOLUME) {
3771  compiler.add_node(
3773  }
3774  else {
3775  compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
3776  }
3777  }
3778 
3779  out = output("Random Per Island");
3780  if (!out->links.empty()) {
3781  if (compiler.output_type() != SHADER_TYPE_VOLUME) {
3782  compiler.add_node(attr_node,
3784  compiler.stack_assign(out),
3786  }
3787  else {
3788  compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
3789  }
3790  }
3791 }
3792 
3793 void GeometryNode::compile(OSLCompiler &compiler)
3794 {
3795  if (bump == SHADER_BUMP_DX)
3796  compiler.parameter("bump_offset", "dx");
3797  else if (bump == SHADER_BUMP_DY)
3798  compiler.parameter("bump_offset", "dy");
3799  else
3800  compiler.parameter("bump_offset", "center");
3801 
3802  compiler.add(this, "node_geometry");
3803 }
3804 
3805 /* TextureCoordinate */
3806 
3808 {
3809  NodeType *type = NodeType::add("texture_coordinate", create, NodeType::SHADER);
3810 
3811  SOCKET_BOOLEAN(from_dupli, "From Dupli", false);
3812  SOCKET_BOOLEAN(use_transform, "Use Transform", false);
3813  SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity());
3814 
3816  normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
3817 
3818  SOCKET_OUT_POINT(generated, "Generated");
3819  SOCKET_OUT_NORMAL(normal, "Normal");
3820  SOCKET_OUT_POINT(UV, "UV");
3821  SOCKET_OUT_POINT(object, "Object");
3822  SOCKET_OUT_POINT(camera, "Camera");
3823  SOCKET_OUT_POINT(window, "Window");
3824  SOCKET_OUT_NORMAL(reflection, "Reflection");
3825 
3826  return type;
3827 }
3828 
3829 TextureCoordinateNode::TextureCoordinateNode() : ShaderNode(get_node_type())
3830 {
3831 }
3832 
3834 {
3835  if (shader->has_surface_link()) {
3836  if (!from_dupli) {
3837  if (!output("Generated")->links.empty())
3839  if (!output("UV")->links.empty())
3840  attributes->add(ATTR_STD_UV);
3841  }
3842  }
3843 
3844  if (shader->has_volume) {
3845  if (!from_dupli) {
3846  if (!output("Generated")->links.empty()) {
3848  }
3849  }
3850  }
3851 
3853 }
3854 
3856 {
3857  ShaderOutput *out;
3858  ShaderNodeType texco_node = NODE_TEX_COORD;
3859  ShaderNodeType attr_node = NODE_ATTR;
3860  ShaderNodeType geom_node = NODE_GEOMETRY;
3861 
3862  if (bump == SHADER_BUMP_DX) {
3863  texco_node = NODE_TEX_COORD_BUMP_DX;
3864  attr_node = NODE_ATTR_BUMP_DX;
3865  geom_node = NODE_GEOMETRY_BUMP_DX;
3866  }
3867  else if (bump == SHADER_BUMP_DY) {
3868  texco_node = NODE_TEX_COORD_BUMP_DY;
3869  attr_node = NODE_ATTR_BUMP_DY;
3870  geom_node = NODE_GEOMETRY_BUMP_DY;
3871  }
3872 
3873  out = output("Generated");
3874  if (!out->links.empty()) {
3875  if (compiler.background) {
3876  compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
3877  }
3878  else {
3879  if (from_dupli) {
3880  compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, compiler.stack_assign(out));
3881  }
3882  else if (compiler.output_type() == SHADER_TYPE_VOLUME) {
3883  compiler.add_node(texco_node, NODE_TEXCO_VOLUME_GENERATED, compiler.stack_assign(out));
3884  }
3885  else {
3886  int attr = compiler.attribute(ATTR_STD_GENERATED);
3887  compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
3888  }
3889  }
3890  }
3891 
3892  out = output("Normal");
3893  if (!out->links.empty()) {
3894  compiler.add_node(texco_node, NODE_TEXCO_NORMAL, compiler.stack_assign(out));
3895  }
3896 
3897  out = output("UV");
3898  if (!out->links.empty()) {
3899  if (from_dupli) {
3900  compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
3901  }
3902  else {
3903  int attr = compiler.attribute(ATTR_STD_UV);
3904  compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
3905  }
3906  }
3907 
3908  out = output("Object");
3909  if (!out->links.empty()) {
3910  compiler.add_node(texco_node, NODE_TEXCO_OBJECT, compiler.stack_assign(out), use_transform);
3911  if (use_transform) {
3912  Transform ob_itfm = transform_inverse(ob_tfm);
3913  compiler.add_node(ob_itfm.x);
3914  compiler.add_node(ob_itfm.y);
3915  compiler.add_node(ob_itfm.z);
3916  }
3917  }
3918 
3919  out = output("Camera");
3920  if (!out->links.empty()) {
3921  compiler.add_node(texco_node, NODE_TEXCO_CAMERA, compiler.stack_assign(out));
3922  }
3923 
3924  out = output("Window");
3925  if (!out->links.empty()) {
3926  compiler.add_node(texco_node, NODE_TEXCO_WINDOW, compiler.stack_assign(out));
3927  }
3928 
3929  out = output("Reflection");
3930  if (!out->links.empty()) {
3931  if (compiler.background) {
3932  compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
3933  }
3934  else {
3935  compiler.add_node(texco_node, NODE_TEXCO_REFLECTION, compiler.stack_assign(out));
3936  }
3937  }
3938 }
3939 
3941 {
3942  if (bump == SHADER_BUMP_DX)
3943  compiler.parameter("bump_offset", "dx");
3944  else if (bump == SHADER_BUMP_DY)
3945  compiler.parameter("bump_offset", "dy");
3946  else
3947  compiler.parameter("bump_offset", "center");
3948 
3949  if (compiler.background)
3950  compiler.parameter("is_background", true);
3951  if (compiler.output_type() == SHADER_TYPE_VOLUME)
3952  compiler.parameter("is_volume", true);
3953  compiler.parameter(this, "use_transform");
3954  Transform ob_itfm = transform_inverse(ob_tfm);
3955  compiler.parameter("object_itfm", ob_itfm);
3956 
3957  compiler.parameter(this, "from_dupli");
3958 
3959  compiler.add(this, "node_texture_coordinate");
3960 }
3961 
3962 /* UV Map */
3963 
3965 {
3967 
3968  SOCKET_STRING(attribute, "attribute", ustring());
3969  SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
3970 
3971  SOCKET_OUT_POINT(UV, "UV");
3972 
3973  return type;
3974 }
3975 
3976 UVMapNode::UVMapNode() : ShaderNode(get_node_type())
3977 {
3978 }
3979 
3981 {
3982  if (shader->has_surface) {
3983  if (!from_dupli) {
3984  if (!output("UV")->links.empty()) {
3985  if (attribute != "")
3986  attributes->add(attribute);
3987  else
3988  attributes->add(ATTR_STD_UV);
3989  }
3990  }
3991  }
3992 
3994 }
3995 
3996 void UVMapNode::compile(SVMCompiler &compiler)
3997 {
3998  ShaderOutput *out = output("UV");
3999  ShaderNodeType texco_node = NODE_TEX_COORD;
4000  ShaderNodeType attr_node = NODE_ATTR;
4001  int attr;
4002 
4003  if (bump == SHADER_BUMP_DX) {
4004  texco_node = NODE_TEX_COORD_BUMP_DX;
4005  attr_node = NODE_ATTR_BUMP_DX;
4006  }
4007  else if (bump == SHADER_BUMP_DY) {
4008  texco_node = NODE_TEX_COORD_BUMP_DY;
4009  attr_node = NODE_ATTR_BUMP_DY;
4010  }
4011 
4012  if (!out->links.empty()) {
4013  if (from_dupli) {
4014  compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
4015  }
4016  else {
4017  if (attribute != "")
4018  attr = compiler.attribute(attribute);
4019  else
4020  attr = compiler.attribute(ATTR_STD_UV);
4021 
4022  compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
4023  }
4024  }
4025 }
4026 
4027 void UVMapNode::compile(OSLCompiler &compiler)
4028 {
4029  if (bump == SHADER_BUMP_DX)
4030  compiler.parameter("bump_offset", "dx");
4031  else if (bump == SHADER_BUMP_DY)
4032  compiler.parameter("bump_offset", "dy");
4033  else
4034  compiler.parameter("bump_offset", "center");
4035 
4036  compiler.parameter(this, "from_dupli");
4037  compiler.parameter(this, "attribute");
4038  compiler.add(this, "node_uv_map");
4039 }
4040 
4041 /* Light Path */
4042 
4044 {
4045  NodeType *type = NodeType::add("light_path", create, NodeType::SHADER);
4046 
4047  SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray");
4048  SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray");
4049  SOCKET_OUT_FLOAT(is_diffuse_ray, "Is Diffuse Ray");
4050  SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray");
4051  SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray");
4052  SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray");
4053  SOCKET_OUT_FLOAT(is_transmission_ray, "Is Transmission Ray");
4054  SOCKET_OUT_FLOAT(is_volume_scatter_ray, "Is Volume Scatter Ray");
4055  SOCKET_OUT_FLOAT(ray_length, "Ray Length");
4056  SOCKET_OUT_FLOAT(ray_depth, "Ray Depth");
4057  SOCKET_OUT_FLOAT(diffuse_depth, "Diffuse Depth");
4058  SOCKET_OUT_FLOAT(glossy_depth, "Glossy Depth");
4059  SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth");
4060  SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth");
4061 
4062  return type;
4063 }
4064 
4065 LightPathNode::LightPathNode() : ShaderNode(get_node_type())
4066 {
4067 }
4068 
4069 void LightPathNode::compile(SVMCompiler &compiler)
4070 {
4071  ShaderOutput *out;
4072 
4073  out = output("Is Camera Ray");
4074  if (!out->links.empty()) {
4075  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_camera, compiler.stack_assign(out));
4076  }
4077 
4078  out = output("Is Shadow Ray");
4079  if (!out->links.empty()) {
4080  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_shadow, compiler.stack_assign(out));
4081  }
4082 
4083  out = output("Is Diffuse Ray");
4084  if (!out->links.empty()) {
4085  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_diffuse, compiler.stack_assign(out));
4086  }
4087 
4088  out = output("Is Glossy Ray");
4089  if (!out->links.empty()) {
4090  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_glossy, compiler.stack_assign(out));
4091  }
4092 
4093  out = output("Is Singular Ray");
4094  if (!out->links.empty()) {
4095  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_singular, compiler.stack_assign(out));
4096  }
4097 
4098  out = output("Is Reflection Ray");
4099  if (!out->links.empty()) {
4100  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, compiler.stack_assign(out));
4101  }
4102 
4103  out = output("Is Transmission Ray");
4104  if (!out->links.empty()) {
4105  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, compiler.stack_assign(out));
4106  }
4107 
4108  out = output("Is Volume Scatter Ray");
4109  if (!out->links.empty()) {
4110  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_volume_scatter, compiler.stack_assign(out));
4111  }
4112 
4113  out = output("Ray Length");
4114  if (!out->links.empty()) {
4115  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, compiler.stack_assign(out));
4116  }
4117 
4118  out = output("Ray Depth");
4119  if (!out->links.empty()) {
4120  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, compiler.stack_assign(out));
4121  }
4122 
4123  out = output("Diffuse Depth");
4124  if (!out->links.empty()) {
4125  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_diffuse, compiler.stack_assign(out));
4126  }
4127 
4128  out = output("Glossy Depth");
4129  if (!out->links.empty()) {
4130  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_glossy, compiler.stack_assign(out));
4131  }
4132 
4133  out = output("Transparent Depth");
4134  if (!out->links.empty()) {
4135  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transparent, compiler.stack_assign(out));
4136  }
4137 
4138  out = output("Transmission Depth");
4139  if (!out->links.empty()) {
4140  compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transmission, compiler.stack_assign(out));
4141  }
4142 }
4143 
4144 void LightPathNode::compile(OSLCompiler &compiler)
4145 {
4146  compiler.add(this, "node_light_path");
4147 }
4148 
4149 /* Light Falloff */
4150 
4152 {
4153  NodeType *type = NodeType::add("light_falloff", create, NodeType::SHADER);
4154 
4155  SOCKET_IN_FLOAT(strength, "Strength", 100.0f);
4156  SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
4157 
4158  SOCKET_OUT_FLOAT(quadratic, "Quadratic");
4159  SOCKET_OUT_FLOAT(linear, "Linear");
4160  SOCKET_OUT_FLOAT(constant, "Constant");
4161 
4162  return type;
4163 }
4164 
4165 LightFalloffNode::LightFalloffNode() : ShaderNode(get_node_type())
4166 {
4167 }
4168 
4169 void LightFalloffNode::compile(SVMCompiler &compiler)
4170 {
4171  ShaderInput *strength_in = input("Strength");
4172  ShaderInput *smooth_in = input("Smooth");
4173 
4174  ShaderOutput *out = output("Quadratic");
4175  if (!out->links.empty()) {
4176  compiler.add_node(NODE_LIGHT_FALLOFF,
4178  compiler.encode_uchar4(compiler.stack_assign(strength_in),
4179  compiler.stack_assign(smooth_in),
4180  compiler.stack_assign(out)));
4181  }
4182 
4183  out = output("Linear");
4184  if (!out->links.empty()) {
4185  compiler.add_node(NODE_LIGHT_FALLOFF,
4187  compiler.encode_uchar4(compiler.stack_assign(strength_in),
4188  compiler.stack_assign(smooth_in),
4189  compiler.stack_assign(out)));
4190  }
4191 
4192  out = output("Constant");
4193  if (!out->links.empty()) {
4194  compiler.add_node(NODE_LIGHT_FALLOFF,
4196  compiler.encode_uchar4(compiler.stack_assign(strength_in),
4197  compiler.stack_assign(smooth_in),
4198  compiler.stack_assign(out)));
4199  }
4200 }
4201 
4202 void LightFalloffNode::compile(OSLCompiler &compiler)
4203 {
4204  compiler.add(this, "node_light_falloff");
4205 }
4206 
4207 /* Object Info */
4208 
4210 {
4211  NodeType *type = NodeType::add("object_info", create, NodeType::SHADER);
4212 
4213  SOCKET_OUT_VECTOR(location, "Location");
4214  SOCKET_OUT_COLOR(color, "Color");
4215  SOCKET_OUT_FLOAT(alpha, "Alpha");
4216  SOCKET_OUT_FLOAT(object_index, "Object Index");
4217  SOCKET_OUT_FLOAT(material_index, "Material Index");
4218  SOCKET_OUT_FLOAT(random, "Random");
4219 
4220  return type;
4221 }
4222 
4223 ObjectInfoNode::ObjectInfoNode() : ShaderNode(get_node_type())
4224 {
4225 }
4226 
4227 void ObjectInfoNode::compile(SVMCompiler &compiler)
4228 {
4229  ShaderOutput *out = output("Location");
4230  if (!out->links.empty()) {
4231  compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_LOCATION, compiler.stack_assign(out));
4232  }
4233 
4234  out = output("Color");
4235  if (!out->links.empty()) {
4236  compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_COLOR, compiler.stack_assign(out));
4237  }
4238 
4239  out = output("Alpha");
4240  if (!out->links.empty()) {
4241  compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_ALPHA, compiler.stack_assign(out));
4242  }
4243 
4244  out = output("Object Index");
4245  if (!out->links.empty()) {
4246  compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out));
4247  }
4248 
4249  out = output("Material Index");
4250  if (!out->links.empty()) {
4251  compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_MAT_INDEX, compiler.stack_assign(out));
4252  }
4253 
4254  out = output("Random");
4255  if (!out->links.empty()) {
4256  compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_RANDOM, compiler.stack_assign(out));
4257  }
4258 }
4259 
4260 void ObjectInfoNode::compile(OSLCompiler &compiler)
4261 {
4262  compiler.add(this, "node_object_info");
4263 }
4264 
4265 /* Particle Info */
4266 
4268 {
4269  NodeType *type = NodeType::add("particle_info", create, NodeType::SHADER);
4270 
4271  SOCKET_OUT_FLOAT(index, "Index");
4272  SOCKET_OUT_FLOAT(random, "Random");
4273  SOCKET_OUT_FLOAT(age, "Age");
4274  SOCKET_OUT_FLOAT(lifetime, "Lifetime");
4275  SOCKET_OUT_POINT(location, "Location");
4276 #if 0 /* not yet supported */
4277  SOCKET_OUT_QUATERNION(rotation, "Rotation");
4278 #endif
4279  SOCKET_OUT_FLOAT(size, "Size");
4280  SOCKET_OUT_VECTOR(velocity, "Velocity");
4281  SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity");
4282 
4283  return type;
4284 }
4285 
4286 ParticleInfoNode::ParticleInfoNode() : ShaderNode(get_node_type())
4287 {
4288 }
4289 
4291 {
4292  if (!output("Index")->links.empty())
4294  if (!output("Random")->links.empty())
4296  if (!output("Age")->links.empty())
4298  if (!output("Lifetime")->links.empty())
4300  if (!output("Location")->links.empty())
4302 #if 0 /* not yet supported */
4303  if (!output("Rotation")->links.empty())
4305 #endif
4306  if (!output("Size")->links.empty())
4308  if (!output("Velocity")->links.empty())
4310  if (!output("Angular Velocity")->links.empty())
4312 
4314 }
4315 
4316 void ParticleInfoNode::compile(SVMCompiler &compiler)
4317 {
4318  ShaderOutput *out;
4319 
4320  out = output("Index");
4321  if (!out->links.empty()) {
4322  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
4323  }
4324 
4325  out = output("Random");
4326  if (!out->links.empty()) {
4327  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
4328  }
4329 
4330  out = output("Age");
4331  if (!out->links.empty()) {
4332  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, compiler.stack_assign(out));
4333  }
4334 
4335  out = output("Lifetime");
4336  if (!out->links.empty()) {
4337  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, compiler.stack_assign(out));
4338  }
4339 
4340  out = output("Location");
4341  if (!out->links.empty()) {
4342  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, compiler.stack_assign(out));
4343  }
4344 
4345  /* quaternion data is not yet supported by Cycles */
4346 #if 0
4347  out = output("Rotation");
4348  if (!out->links.empty()) {
4349  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, compiler.stack_assign(out));
4350  }
4351 #endif
4352 
4353  out = output("Size");
4354  if (!out->links.empty()) {
4355  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, compiler.stack_assign(out));
4356  }
4357 
4358  out = output("Velocity");
4359  if (!out->links.empty()) {
4360  compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, compiler.stack_assign(out));
4361  }
4362 
4363  out = output("Angular Velocity");
4364  if (!out->links.empty()) {
4365  compiler.add_node(
4366  NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, compiler.stack_assign(out));
4367  }
4368 }
4369 
4370 void ParticleInfoNode::compile(OSLCompiler &compiler)
4371 {
4372  compiler.add(this, "node_particle_info");
4373 }
4374 
4375 /* Hair Info */
4376 
4378 {
4380 
4381  SOCKET_OUT_FLOAT(is_strand, "Is Strand");
4382  SOCKET_OUT_FLOAT(intercept, "Intercept");
4383  SOCKET_OUT_FLOAT(size, "Length");
4384  SOCKET_OUT_FLOAT(thickness, "Thickness");
4385  SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal");
4386  SOCKET_OUT_FLOAT(index, "Random");
4387 
4388  return type;
4389 }
4390 
4391 HairInfoNode::HairInfoNode() : ShaderNode(get_node_type())
4392 {
4393 }
4394 
4396 {
4397  if (shader->has_surface_link()) {
4398  ShaderOutput *intercept_out = output("Intercept");
4399 
4400  if (!intercept_out->links.empty())
4402 
4403  if (!output("Length")->links.empty())
4405 
4406  if (!output("Random")->links.empty())
4408  }
4409 
4411 }
4412 
4413 void HairInfoNode::compile(SVMCompiler &compiler)
4414 {
4415  ShaderOutput *out;
4416 
4417  out = output("Is Strand");
4418  if (!out->links.empty()) {
4419  compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, compiler.stack_assign(out));
4420  }
4421 
4422  out = output("Intercept");
4423  if (!out->links.empty()) {
4424  int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
4425  compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
4426  }
4427 
4428  out = output("Length");
4429  if (!out->links.empty()) {
4430  int attr = compiler.attribute(ATTR_STD_CURVE_LENGTH);
4431  compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
4432  }
4433 
4434  out = output("Thickness");
4435  if (!out->links.empty()) {
4436  compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, compiler.stack_assign(out));
4437  }
4438 
4439  out = output("Tangent Normal");
4440  if (!out->links.empty()) {
4441  compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
4442  }
4443 
4444  out = output("Random");
4445  if (!out->links.empty()) {
4446  int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
4447  compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
4448  }
4449 }
4450 
4451 void HairInfoNode::compile(OSLCompiler &compiler)
4452 {
4453  compiler.add(this, "node_hair_info");
4454 }
4455 
4456 /* Point Info */
4457 
4459 {
4460  NodeType *type = NodeType::add("point_info", create, NodeType::SHADER);
4461 
4462  SOCKET_OUT_POINT(position, "Position");
4463  SOCKET_OUT_FLOAT(radius, "Radius");
4464  SOCKET_OUT_FLOAT(random, "Random");
4465 
4466  return type;
4467 }
4468 
4469 PointInfoNode::PointInfoNode() : ShaderNode(get_node_type())
4470 {
4471 }
4472 
4474 {
4475  if (shader->has_surface_link()) {
4476  if (!output("Random")->links.empty())
4478  }
4479 
4481 }
4482 
4483 void PointInfoNode::compile(SVMCompiler &compiler)
4484 {
4485  ShaderOutput *out;
4486 
4487  out = output("Position");
4488  if (!out->links.empty()) {
4489  compiler.add_node(NODE_POINT_INFO, NODE_INFO_POINT_POSITION, compiler.stack_assign(out));
4490  }
4491 
4492  out = output("Radius");
4493  if (!out->links.empty()) {
4494  compiler.add_node(NODE_POINT_INFO, NODE_INFO_POINT_RADIUS, compiler.stack_assign(out));
4495  }
4496 
4497  out = output("Random");
4498  if (!out->links.empty()) {
4499  int attr = compiler.attribute(ATTR_STD_POINT_RANDOM);
4500  compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
4501  }
4502 }
4503 
4504 void PointInfoNode::compile(OSLCompiler &compiler)
4505 {
4506  compiler.add(this, "node_point_info");
4507 }
4508 
4509 /* Volume Info */
4510 
4512 {
4513  NodeType *type = NodeType::add("volume_info", create, NodeType::SHADER);
4514 
4515  SOCKET_OUT_COLOR(color, "Color");
4516  SOCKET_OUT_FLOAT(density, "Density");
4517  SOCKET_OUT_FLOAT(flame, "Flame");
4518  SOCKET_OUT_FLOAT(temperature, "Temperature");
4519 
4520  return type;
4521 }
4522 
4523 VolumeInfoNode::VolumeInfoNode() : ShaderNode(get_node_type())
4524 {
4525 }
4526 
4527 /* The requested attributes are not updated after node expansion.
4528  * So we explicitly request the required attributes.
4529  */
4531 {
4532  if (shader->has_volume) {
4533  if (!output("Color")->links.empty()) {
4535  }
4536  if (!output("Density")->links.empty()) {
4538  }
4539  if (!output("Flame")->links.empty()) {
4541  }
4542  if (!output("Temperature")->links.empty()) {
4544  }
4546  }
4548 }
4549 
4551 {
4552  ShaderOutput *color_out = output("Color");
4553  if (!color_out->links.empty()) {
4554  AttributeNode *attr = graph->create_node<AttributeNode>();
4555  attr->set_attribute(ustring("color"));
4556  graph->add(attr);
4557  graph->relink(color_out, attr->output("Color"));
4558  }
4559 
4560  ShaderOutput *density_out = output("Density");
4561  if (!density_out->links.empty()) {
4562  AttributeNode *attr = graph->create_node<AttributeNode>();
4563  attr->set_attribute(ustring("density"));
4564  graph->add(attr);
4565  graph->relink(density_out, attr->output("Fac"));
4566  }
4567 
4568  ShaderOutput *flame_out = output("Flame");
4569  if (!flame_out->links.empty()) {
4570  AttributeNode *attr = graph->create_node<AttributeNode>();
4571  attr->set_attribute(ustring("flame"));
4572  graph->add(attr);
4573  graph->relink(flame_out, attr->output("Fac"));
4574  }
4575 
4576  ShaderOutput *temperature_out = output("Temperature");
4577  if (!temperature_out->links.empty()) {
4578  AttributeNode *attr = graph->create_node<AttributeNode>();
4579  attr->set_attribute(ustring("temperature"));
4580  graph->add(attr);
4581  graph->relink(temperature_out, attr->output("Fac"));
4582  }
4583 }
4584 
4586 {
4587 }
4588 
4590 {
4591 }
4592 
4594 {
4595  NodeType *type = NodeType::add("vertex_color", create, NodeType::SHADER);
4596 
4597  SOCKET_STRING(layer_name, "Layer Name", ustring());
4598  SOCKET_OUT_COLOR(color, "Color");
4599  SOCKET_OUT_FLOAT(alpha, "Alpha");
4600 
4601  return type;
4602 }
4603 
4604 VertexColorNode::VertexColorNode() : ShaderNode(get_node_type())
4605 {
4606 }
4607 
4609 {
4610  if (!(output("Color")->links.empty() && output("Alpha")->links.empty())) {
4611  if (layer_name != "")
4612  attributes->add_standard(layer_name);
4613  else
4615  }
4617 }
4618 
4619 void VertexColorNode::compile(SVMCompiler &compiler)
4620 {
4621  ShaderOutput *color_out = output("Color");
4622  ShaderOutput *alpha_out = output("Alpha");
4623  int layer_id = 0;
4624 
4625  if (layer_name != "") {
4626  layer_id = compiler.attribute(layer_name);
4627  }
4628  else {
4629  layer_id = compiler.attribute(ATTR_STD_VERTEX_COLOR);
4630  }
4631 
4633 
4634  if (bump == SHADER_BUMP_DX)
4635  node = NODE_VERTEX_COLOR_BUMP_DX;
4636  else if (bump == SHADER_BUMP_DY)
4637  node = NODE_VERTEX_COLOR_BUMP_DY;
4638  else {
4639  node = NODE_VERTEX_COLOR;
4640  }
4641 
4642  compiler.add_node(
4643  node, layer_id, compiler.stack_assign(color_out), compiler.stack_assign(alpha_out));
4644 }
4645 
4646 void VertexColorNode::compile(OSLCompiler &compiler)
4647 {
4648  if (bump == SHADER_BUMP_DX) {
4649  compiler.parameter("bump_offset", "dx");
4650  }
4651  else if (bump == SHADER_BUMP_DY) {
4652  compiler.parameter("bump_offset", "dy");
4653  }
4654  else {
4655  compiler.parameter("bump_offset", "center");
4656  }
4657 
4658  if (layer_name.empty()) {
4659  compiler.parameter("layer_name", ustring("geom:vertex_color"));
4660  }
4661  else {
4662  if (Attribute::name_standard(layer_name.c_str()) != ATTR_STD_NONE) {
4663  compiler.parameter("name", (string("geom:") + layer_name.c_str()).c_str());
4664  }
4665  else {
4666  compiler.parameter("layer_name", layer_name.c_str());
4667  }
4668  }
4669 
4670  compiler.add(this, "node_vertex_color");
4671 }
4672 
4673 /* Value */
4674 
4676 {
4678 
4679  SOCKET_FLOAT(value, "Value", 0.0f);
4680  SOCKET_OUT_FLOAT(value, "Value");
4681 
4682  return type;
4683 }
4684 
4685 ValueNode::ValueNode() : ShaderNode(get_node_type())
4686 {
4687 }
4688 
4690 {
4691  folder.make_constant(value);
4692 }
4693 
4694 void ValueNode::compile(SVMCompiler &compiler)
4695 {
4696  ShaderOutput *val_out = output("Value");
4697 
4698  compiler.add_node(NODE_VALUE_F, __float_as_int(value), compiler.stack_assign(val_out));
4699 }
4700 
4701 void ValueNode::compile(OSLCompiler &compiler)
4702 {
4703  compiler.parameter("value_value", value);
4704  compiler.add(this, "node_value");
4705 }
4706 
4707 /* Color */
4708 
4710 {
4712 
4713  SOCKET_COLOR(value, "Value", zero_float3());
4714  SOCKET_OUT_COLOR(color, "Color");
4715 
4716  return type;
4717 }
4718 
4719 ColorNode::ColorNode() : ShaderNode(get_node_type())
4720 {
4721 }
4722 
4724 {
4725  folder.make_constant(value);
4726 }
4727 
4728 void ColorNode::compile(SVMCompiler &compiler)
4729 {
4730  ShaderOutput *color_out = output("Color");
4731 
4732  if (!color_out->links.empty()) {
4733  compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
4734  compiler.add_node(NODE_VALUE_V, value);
4735  }
4736 }
4737 
4738 void ColorNode::compile(OSLCompiler &compiler)
4739 {
4740  compiler.parameter_color("color_value", value);
4741 
4742  compiler.add(this, "node_value");
4743 }
4744 
4745 /* Add Closure */
4746 
4748 {
4749  NodeType *type = NodeType::add("add_closure", create, NodeType::SHADER);
4750 
4751  SOCKET_IN_CLOSURE(closure1, "Closure1");
4752  SOCKET_IN_CLOSURE(closure2, "Closure2");
4753  SOCKET_OUT_CLOSURE(closure, "Closure");
4754 
4755  return type;
4756 }
4757 
4758 AddClosureNode::AddClosureNode() : ShaderNode(get_node_type())
4759 {
4760  special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
4761 }
4762 
4763 void AddClosureNode::compile(SVMCompiler & /*compiler*/)
4764 {
4765  /* handled in the SVM compiler */
4766 }
4767 
4768 void AddClosureNode::compile(OSLCompiler &compiler)
4769 {
4770  compiler.add(this, "node_add_closure");
4771 }
4772 
4774 {
4775  ShaderInput *closure1_in = input("Closure1");
4776  ShaderInput *closure2_in = input("Closure2");
4777 
4778  /* remove useless add closures nodes */
4779  if (!closure1_in->link) {
4780  folder.bypass_or_discard(closure2_in);
4781  }
4782  else if (!closure2_in->link) {
4783  folder.bypass_or_discard(closure1_in);
4784  }
4785 }
4786 
4787 /* Mix Closure */
4788 
4790 {
4791  NodeType *type = NodeType::add("mix_closure", create, NodeType::SHADER);
4792 
4793  SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
4794  SOCKET_IN_CLOSURE(closure1, "Closure1");
4795  SOCKET_IN_CLOSURE(closure2, "Closure2");
4796 
4797  SOCKET_OUT_CLOSURE(closure, "Closure");
4798 
4799  return type;
4800 }
4801 
4802 MixClosureNode::MixClosureNode() : ShaderNode(get_node_type())
4803 {
4804  special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
4805 }
4806 
4807 void MixClosureNode::compile(SVMCompiler & /*compiler*/)
4808 {
4809  /* handled in the SVM compiler */
4810 }
4811 
4812 void MixClosureNode::compile(OSLCompiler &compiler)
4813 {
4814  compiler.add(this, "node_mix_closure");
4815 }
4816 
4818 {
4819  ShaderInput *fac_in = input("Fac");
4820  ShaderInput *closure1_in = input("Closure1");
4821  ShaderInput *closure2_in = input("Closure2");
4822 
4823  /* remove useless mix closures nodes */
4824  if (closure1_in->link == closure2_in->link) {
4825  folder.bypass_or_discard(closure1_in);
4826  }
4827  /* remove unused mix closure input when factor is 0.0 or 1.0
4828  * check for closure links and make sure factor link is disconnected */
4829  else if (!fac_in->link) {
4830  /* factor 0.0 */
4831  if (fac <= 0.0f) {
4832  folder.bypass_or_discard(closure1_in);
4833  }
4834  /* factor 1.0 */
4835  else if (fac >= 1.0f) {
4836  folder.bypass_or_discard(closure2_in);
4837  }
4838  }
4839 }
4840 
4841 /* Mix Closure */
4842 
4844 {
4845  NodeType *type = NodeType::add("mix_closure_weight", create, NodeType::SHADER);
4846 
4847  SOCKET_IN_FLOAT(weight, "Weight", 1.0f);
4848  SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
4849 
4850  SOCKET_OUT_FLOAT(weight1, "Weight1");
4851  SOCKET_OUT_FLOAT(weight2, "Weight2");
4852 
4853  return type;
4854 }
4855 
4856 MixClosureWeightNode::MixClosureWeightNode() : ShaderNode(get_node_type())
4857 {
4858 }
4859 
4861 {
4862  ShaderInput *weight_in = input("Weight");
4863  ShaderInput *fac_in = input("Fac");
4864  ShaderOutput *weight1_out = output("Weight1");
4865  ShaderOutput *weight2_out = output("Weight2");
4866 
4867  compiler.add_node(NODE_MIX_CLOSURE,
4868  compiler.encode_uchar4(compiler.stack_assign(fac_in),
4869  compiler.stack_assign(weight_in),
4870  compiler.stack_assign(weight1_out),
4871  compiler.stack_assign(weight2_out)));
4872 }
4873 
4874 void MixClosureWeightNode::compile(OSLCompiler & /*compiler*/)
4875 {
4876  assert(0);
4877 }
4878 
4879 /* Invert */
4880 
4882 {
4884 
4885  SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
4886  SOCKET_IN_COLOR(color, "Color", zero_float3());
4887 
4888  SOCKET_OUT_COLOR(color, "Color");
4889 
4890  return type;
4891 }
4892 
4893 InvertNode::InvertNode() : ShaderNode(get_node_type())
4894 {
4895 }
4896 
4898 {
4899  ShaderInput *fac_in = input("Fac");
4900  ShaderInput *color_in = input("Color");
4901 
4902  if (!fac_in->link) {
4903  /* evaluate fully constant node */
4904  if (!color_in->link) {
4905  folder.make_constant(interp(color, one_float3() - color, fac));
4906  }
4907  /* remove no-op node */
4908  else if (fac == 0.0f) {
4909  folder.bypass(color_in->link);
4910  }
4911  }
4912 }
4913 
4914 void InvertNode::compile(SVMCompiler &compiler)
4915 {
4916  ShaderInput *fac_in = input("Fac");
4917  ShaderInput *color_in = input("Color");
4918  ShaderOutput *color_out = output("Color");
4919 
4920  compiler.add_node(NODE_INVERT,
4921  compiler.stack_assign(fac_in),
4922  compiler.stack_assign(color_in),
4923  compiler.stack_assign(color_out));
4924 }
4925 
4926 void InvertNode::compile(OSLCompiler &compiler)
4927 {
4928  compiler.add(this, "node_invert");
4929 }
4930 
4931 /* Mix */
4932 
4934 {
4936 
4937  static NodeEnum type_enum;
4938  type_enum.insert("mix", NODE_MIX_BLEND);
4939  type_enum.insert("add", NODE_MIX_ADD);
4940  type_enum.insert("multiply", NODE_MIX_MUL);
4941  type_enum.insert("screen", NODE_MIX_SCREEN);
4942  type_enum.insert("overlay", NODE_MIX_OVERLAY);
4943  type_enum.insert("subtract", NODE_MIX_SUB);
4944  type_enum.insert("divide", NODE_MIX_DIV);
4945  type_enum.insert("difference", NODE_MIX_DIFF);
4946  type_enum.insert("darken", NODE_MIX_DARK);
4947  type_enum.insert("lighten", NODE_MIX_LIGHT);
4948  type_enum.insert("dodge", NODE_MIX_DODGE);
4949  type_enum.insert("burn", NODE_MIX_BURN);
4950  type_enum.insert("hue", NODE_MIX_HUE);
4951  type_enum.insert("saturation", NODE_MIX_SAT);
4952  type_enum.insert("value", NODE_MIX_VAL);
4953  type_enum.insert("color", NODE_MIX_COLOR);
4954  type_enum.insert("soft_light", NODE_MIX_SOFT);
4955  type_enum.insert("linear_light", NODE_MIX_LINEAR);
4956  SOCKET_ENUM(mix_type, "Type", type_enum, NODE_MIX_BLEND);
4957 
4958  SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
4959 
4960  SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
4961  SOCKET_IN_COLOR(color1, "Color1", zero_float3());
4962  SOCKET_IN_COLOR(color2, "Color2", zero_float3());
4963 
4964  SOCKET_OUT_COLOR(color, "Color");
4965 
4966  return type;
4967 }
4968 
4969 MixNode::MixNode() : ShaderNode(get_node_type())
4970 {
4971 }
4972 
4973 void MixNode::compile(SVMCompiler &compiler)
4974 {
4975  ShaderInput *fac_in = input("Fac");
4976  ShaderInput *color1_in = input("Color1");
4977  ShaderInput *color2_in = input("Color2");
4978  ShaderOutput *color_out = output("Color");
4979 
4980  compiler.add_node(NODE_MIX,
4981  compiler.stack_assign(fac_in),
4982  compiler.stack_assign(color1_in),
4983  compiler.stack_assign(color2_in));
4984  compiler.add_node(NODE_MIX, mix_type, compiler.stack_assign(color_out));
4985 
4986  if (use_clamp) {
4987  compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
4988  compiler.add_node(NODE_MIX, NODE_MIX_CLAMP, compiler.stack_assign(color_out));
4989  }
4990 }
4991 
4992 void MixNode::compile(OSLCompiler &compiler)
4993 {
4994  compiler.parameter(this, "mix_type");
4995  compiler.parameter(this, "use_clamp");
4996  compiler.add(this, "node_mix");
4997 }
4998 
5000 {
5001  if (folder.all_inputs_constant()) {
5002  folder.make_constant_clamp(svm_mix(mix_type, fac, color1, color2), use_clamp);
5003  }
5004  else {
5005  folder.fold_mix(mix_type, use_clamp);
5006  }
5007 }
5008 
5009 /* Combine Color */
5010 
5012 {
5013  NodeType *type = NodeType::add("combine_color", create, NodeType::SHADER);
5014 
5015  static NodeEnum type_enum;
5016  type_enum.insert("rgb", NODE_COMBSEP_COLOR_RGB);
5017  type_enum.insert("hsv", NODE_COMBSEP_COLOR_HSV);
5018  type_enum.insert("hsl", NODE_COMBSEP_COLOR_HSL);
5019  SOCKET_ENUM(color_type, "Type", type_enum, NODE_COMBSEP_COLOR_RGB);
5020 
5021  SOCKET_IN_FLOAT(r, "Red", 0.0f);
5022  SOCKET_IN_FLOAT(g, "Green", 0.0f);
5023  SOCKET_IN_FLOAT(b, "Blue", 0.0f);
5024 
5025  SOCKET_OUT_COLOR(color, "Color");
5026 
5027  return type;
5028 }
5029 
5030 CombineColorNode::CombineColorNode() : ShaderNode(get_node_type())
5031 {
5032 }
5033 
5035 {
5036  if (folder.all_inputs_constant()) {
5037  folder.make_constant(svm_combine_color(color_type, make_float3(r, g, b)));
5038  }
5039 }
5040 
5041 void CombineColorNode::compile(SVMCompiler &compiler)
5042 {
5043  ShaderInput *red_in = input("Red");
5044  ShaderInput *green_in = input("Green");
5045  ShaderInput *blue_in = input("Blue");
5046  ShaderOutput *color_out = output("Color");
5047 
5048  int red_stack_offset = compiler.stack_assign(red_in);
5049  int green_stack_offset = compiler.stack_assign(green_in);
5050  int blue_stack_offset = compiler.stack_assign(blue_in);
5051  int color_stack_offset = compiler.stack_assign(color_out);
5052 
5053  compiler.add_node(
5054  NODE_COMBINE_COLOR,
5055  color_type,
5056  compiler.encode_uchar4(red_stack_offset, green_stack_offset, blue_stack_offset),
5057  color_stack_offset);
5058 }
5059 
5060 void CombineColorNode::compile(OSLCompiler &compiler)
5061 {
5062  compiler.parameter(this, "color_type");
5063  compiler.add(this, "node_combine_color");
5064 }
5065 
5066 /* Combine RGB */
5067 
5069 {
5070  NodeType *type = NodeType::add("combine_rgb", create, NodeType::SHADER);
5071 
5072  SOCKET_IN_FLOAT(r, "R", 0.0f);
5073  SOCKET_IN_FLOAT(g, "G", 0.0f);
5074  SOCKET_IN_FLOAT(b, "B", 0.0f);
5075 
5076  SOCKET_OUT_COLOR(image, "Image");
5077 
5078  return type;
5079 }
5080 
5081 CombineRGBNode::CombineRGBNode() : ShaderNode(get_node_type())
5082 {
5083 }
5084 
5086 {
5087  if (folder.all_inputs_constant()) {
5088  folder.make_constant(make_float3(r, g, b));
5089  }
5090 }
5091 
5092 void CombineRGBNode::compile(SVMCompiler &compiler)
5093 {
5094  ShaderInput *red_in = input("R");
5095  ShaderInput *green_in = input("G");
5096  ShaderInput *blue_in = input("B");
5097  ShaderOutput *color_out = output("Image");
5098 
5099  compiler.add_node(
5100  NODE_COMBINE_VECTOR, compiler.stack_assign(red_in), 0, compiler.stack_assign(color_out));
5101 
5102  compiler.add_node(
5103  NODE_COMBINE_VECTOR, compiler.stack_assign(green_in), 1, compiler.stack_assign(color_out));
5104 
5105  compiler.add_node(
5106  NODE_COMBINE_VECTOR, compiler.stack_assign(blue_in), 2, compiler.stack_assign(color_out));
5107 }
5108 
5109 void CombineRGBNode::compile(OSLCompiler &compiler)
5110 {
5111  compiler.add(this, "node_combine_rgb");
5112 }
5113 
5114 /* Combine XYZ */
5115 
5117 {
5118  NodeType *type = NodeType::add("combine_xyz", create, NodeType::SHADER);
5119 
5120  SOCKET_IN_FLOAT(x, "X", 0.0f);
5121  SOCKET_IN_FLOAT(y, "Y", 0.0f);
5122  SOCKET_IN_FLOAT(z, "Z", 0.0f);
5123 
5124  SOCKET_OUT_VECTOR(vector, "Vector");
5125 
5126  return type;
5127 }
5128 
5129 CombineXYZNode::CombineXYZNode() : ShaderNode(get_node_type())
5130 {
5131 }
5132 
5134 {
5135  if (folder.all_inputs_constant()) {
5136  folder.make_constant(make_float3(x, y, z));
5137  }
5138 }
5139 
5140 void CombineXYZNode::compile(SVMCompiler &compiler)
5141 {
5142  ShaderInput *x_in = input("X");
5143  ShaderInput *y_in = input("Y");
5144  ShaderInput *z_in = input("Z");
5145  ShaderOutput *vector_out = output("Vector");
5146 
5147  compiler.add_node(
5148  NODE_COMBINE_VECTOR, compiler.stack_assign(x_in), 0, compiler.stack_assign(vector_out));
5149 
5150  compiler.add_node(
5151  NODE_COMBINE_VECTOR, compiler.stack_assign(y_in), 1, compiler.stack_assign(vector_out));
5152 
5153  compiler.add_node(
5154  NODE_COMBINE_VECTOR, compiler.stack_assign(z_in), 2, compiler.stack_assign(vector_out));
5155 }
5156 
5157 void CombineXYZNode::compile(OSLCompiler &compiler)
5158 {
5159  compiler.add(this, "node_combine_xyz");
5160 }
5161 
5162 /* Combine HSV */
5163 
5165 {
5166  NodeType *type = NodeType::add("combine_hsv", create, NodeType::SHADER);
5167 
5168  SOCKET_IN_FLOAT(h, "H", 0.0f);
5169  SOCKET_IN_FLOAT(s, "S", 0.0f);
5170  SOCKET_IN_FLOAT(v, "V", 0.0f);
5171 
5172  SOCKET_OUT_COLOR(color, "Color");
5173 
5174  return type;
5175 }
5176 
5177 CombineHSVNode::CombineHSVNode() : ShaderNode(get_node_type())
5178 {
5179 }
5180 
5182 {
5183  if (folder.all_inputs_constant()) {
5184  folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
5185  }
5186 }
5187 
5188 void CombineHSVNode::compile(SVMCompiler &compiler)
5189 {
5190  ShaderInput *hue_in = input("H");
5191  ShaderInput *saturation_in = input("S");
5192  ShaderInput *value_in = input("V");
5193  ShaderOutput *color_out = output("Color");
5194 
5195  compiler.add_node(NODE_COMBINE_HSV,
5196  compiler.stack_assign(hue_in),
5197  compiler.stack_assign(saturation_in),
5198  compiler.stack_assign(value_in));
5199  compiler.add_node(NODE_COMBINE_HSV, compiler.stack_assign(color_out));
5200 }
5201 
5202 void CombineHSVNode::compile(OSLCompiler &compiler)
5203 {
5204  compiler.add(this, "node_combine_hsv");
5205 }
5206 
5207 /* Gamma */
5208 
5210 {
5212 
5213  SOCKET_IN_COLOR(color, "Color", zero_float3());
5214  SOCKET_IN_FLOAT(gamma, "Gamma", 1.0f);
5215  SOCKET_OUT_COLOR(color, "Color");
5216 
5217  return type;
5218 }
5219 
5220 GammaNode::GammaNode() : ShaderNode(get_node_type())
5221 {
5222 }
5223 
5225 {
5226  if (folder.all_inputs_constant()) {
5227  folder.make_constant(svm_math_gamma_color(color, gamma));
5228  }
5229  else {
5230  ShaderInput *color_in = input("Color");
5231  ShaderInput *gamma_in = input("Gamma");
5232 
5233  /* 1 ^ X == X ^ 0 == 1 */
5234  if (folder.is_one(color_in) || folder.is_zero(gamma_in)) {
5235  folder.make_one();
5236  }
5237  /* X ^ 1 == X */
5238  else if (folder.is_one(gamma_in)) {
5239  folder.try_bypass_or_make_constant(color_in, false);
5240  }
5241  }
5242 }
5243 
5244 void GammaNode::compile(SVMCompiler &compiler)
5245 {
5246  ShaderInput *color_in = input("Color");
5247  ShaderInput *gamma_in = input("Gamma");
5248  ShaderOutput *color_out = output("Color");
5249 
5250  compiler.add_node(NODE_GAMMA,
5251  compiler.stack_assign(gamma_in),
5252  compiler.stack_assign(color_in),
5253  compiler.stack_assign(color_out));
5254 }
5255 
5256 void GammaNode::compile(OSLCompiler &compiler)
5257 {
5258  compiler.add(this, "node_gamma");
5259 }
5260 
5261 /* Bright Contrast */
5262 
5264 {
5265  NodeType *type = NodeType::add("brightness_contrast", create, NodeType::SHADER);
5266 
5267  SOCKET_IN_COLOR(color, "Color", zero_float3());
5268  SOCKET_IN_FLOAT(bright, "Bright", 0.0f);
5269  SOCKET_IN_FLOAT(contrast, "Contrast", 0.0f);
5270 
5271  SOCKET_OUT_COLOR(color, "Color");
5272 
5273  return type;
5274 }
5275 
5276 BrightContrastNode::BrightContrastNode() : ShaderNode(get_node_type())
5277 {
5278 }
5279 
5281 {
5282  if (folder.all_inputs_constant()) {
5283  folder.make_constant(svm_brightness_contrast(color, bright, contrast));
5284  }
5285 }
5286 
5288 {
5289  ShaderInput *color_in = input("Color");
5290  ShaderInput *bright_in = input("Bright");
5291  ShaderInput *contrast_in = input("Contrast");
5292  ShaderOutput *color_out = output("Color");
5293 
5294  compiler.add_node(NODE_BRIGHTCONTRAST,
5295  compiler.stack_assign(color_in),
5296  compiler.stack_assign(color_out),
5297  compiler.encode_uchar4(compiler.stack_assign(bright_in),
5298  compiler.stack_assign(contrast_in)));
5299 }
5300 
5302 {
5303  compiler.add(this, "node_brightness");
5304 }
5305 
5306 /* Separate Color */
5307 
5309 {
5310  NodeType *type = NodeType::add("separate_color", create, NodeType::SHADER);
5311 
5312  static NodeEnum type_enum;
5313  type_enum.insert("rgb", NODE_COMBSEP_COLOR_RGB);
5314  type_enum.insert("hsv", NODE_COMBSEP_COLOR_HSV);
5315  type_enum.insert("hsl", NODE_COMBSEP_COLOR_HSL);
5316  SOCKET_ENUM(color_type, "Type", type_enum, NODE_COMBSEP_COLOR_RGB);
5317 
5318  SOCKET_IN_COLOR(color, "Color", zero_float3());
5319 
5320  SOCKET_OUT_FLOAT(r, "Red");
5321  SOCKET_OUT_FLOAT(g, "Green");
5322  SOCKET_OUT_FLOAT(b, "Blue");
5323 
5324  return type;
5325 }
5326 
5327 SeparateColorNode::SeparateColorNode() : ShaderNode(get_node_type())
5328 {
5329 }
5330 
5332 {
5333  if (folder.all_inputs_constant()) {
5334  float3 col = svm_separate_color(color_type, color);
5335 
5336  for (int channel = 0; channel < 3; channel++) {
5337  if (outputs[channel] == folder.output) {
5338  folder.make_constant(col[channel]);
5339  return;
5340  }
5341  }
5342  }
5343 }
5344 
5346 {
5347  ShaderInput *color_in = input("Color");
5348  ShaderOutput *red_out = output("Red");
5349  ShaderOutput *green_out = output("Green");
5350  ShaderOutput *blue_out = output("Blue");
5351 
5352  int color_stack_offset = compiler.stack_assign(color_in);
5353  int red_stack_offset = compiler.stack_assign(red_out);
5354  int green_stack_offset = compiler.stack_assign(green_out);
5355  int blue_stack_offset = compiler.stack_assign(blue_out);
5356 
5357  compiler.add_node(
5358  NODE_SEPARATE_COLOR,
5359  color_type,
5360  color_stack_offset,
5361  compiler.encode_uchar4(red_stack_offset, green_stack_offset, blue_stack_offset));
5362 }
5363 
5365 {
5366  compiler.parameter(this, "color_type");
5367  compiler.add(this, "node_separate_color");
5368 }
5369 
5370 /* Separate RGB */
5371 
5373 {
5374  NodeType *type = NodeType::add("separate_rgb", create, NodeType::SHADER);
5375 
5376  SOCKET_IN_COLOR(color, "Image", zero_float3());
5377 
5378  SOCKET_OUT_FLOAT(r, "R");
5379  SOCKET_OUT_FLOAT(g, "G");
5380  SOCKET_OUT_FLOAT(b, "B");
5381 
5382  return type;
5383 }
5384 
5385 SeparateRGBNode::SeparateRGBNode() : ShaderNode(get_node_type())
5386 {
5387 }
5388 
5390 {
5391  if (folder.all_inputs_constant()) {
5392  for (int channel = 0; channel < 3; channel++) {
5393  if (outputs[channel] == folder.output) {
5394  folder.make_constant(color[channel]);
5395  return;
5396  }
5397  }
5398  }
5399 }
5400 
5401 void SeparateRGBNode::compile(SVMCompiler &compiler)
5402 {
5403  ShaderInput *color_in = input("Image");
5404  ShaderOutput *red_out = output("R");
5405  ShaderOutput *green_out = output("G");
5406  ShaderOutput *blue_out = output("B");
5407 
5408  compiler.add_node(
5409  NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 0, compiler.stack_assign(red_out));
5410 
5411  compiler.add_node(
5412  NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 1, compiler.stack_assign(green_out));
5413 
5414  compiler.add_node(
5415  NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 2, compiler.stack_assign(blue_out));
5416 }
5417 
5418 void SeparateRGBNode::compile(OSLCompiler &compiler)
5419 {
5420  compiler.add(this, "node_separate_rgb");
5421 }
5422 
5423 /* Separate XYZ */
5424 
5426 {
5427  NodeType *type = NodeType::add("separate_xyz", create, NodeType::SHADER);
5428 
5429  SOCKET_IN_COLOR(vector, "Vector", zero_float3());
5430 
5431  SOCKET_OUT_FLOAT(x, "X");
5432  SOCKET_OUT_FLOAT(y, "Y");
5433  SOCKET_OUT_FLOAT(z, "Z");
5434 
5435  return type;
5436 }
5437 
5438 SeparateXYZNode::SeparateXYZNode() : ShaderNode(get_node_type())
5439 {
5440 }
5441 
5443 {
5444  if (folder.all_inputs_constant()) {
5445  for (int channel = 0; channel < 3; channel++) {
5446  if (outputs[channel] == folder.output) {
5447  folder.make_constant(vector[channel]);
5448  return;
5449  }
5450  }
5451  }
5452 }
5453 
5454 void SeparateXYZNode::compile(SVMCompiler &compiler)
5455 {
5456  ShaderInput *vector_in = input("Vector");
5457  ShaderOutput *x_out = output("X");
5458  ShaderOutput *y_out = output("Y");
5459  ShaderOutput *z_out = output("Z");
5460 
5461  compiler.add_node(
5462  NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 0, compiler.stack_assign(x_out));
5463 
5464  compiler.add_node(
5465  NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 1, compiler.stack_assign(y_out));
5466 
5467  compiler.add_node(
5468  NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 2, compiler.stack_assign(z_out));
5469 }
5470 
5471 void SeparateXYZNode::compile(OSLCompiler &compiler)
5472 {
5473  compiler.add(this, "node_separate_xyz");
5474 }
5475 
5476 /* Separate HSV */
5477 
5479 {
5480  NodeType *type = NodeType::add("separate_hsv", create, NodeType::SHADER);
5481 
5482  SOCKET_IN_COLOR(color, "Color", zero_float3());
5483 
5484  SOCKET_OUT_FLOAT(h, "H");
5485  SOCKET_OUT_FLOAT(s, "S");
5486  SOCKET_OUT_FLOAT(v, "V");
5487 
5488  return type;
5489 }
5490 
5491 SeparateHSVNode::SeparateHSVNode() : ShaderNode(get_node_type())
5492 {
5493 }
5494 
5496 {
5497  if (folder.all_inputs_constant()) {
5498  float3 hsv = rgb_to_hsv(color);
5499 
5500  for (int channel = 0; channel < 3; channel++) {
5501  if (outputs[channel] == folder.output) {
5502  folder.make_constant(hsv[channel]);
5503  return;
5504  }
5505  }
5506  }
5507 }
5508 
5509 void SeparateHSVNode::compile(SVMCompiler &compiler)
5510 {
5511  ShaderInput *color_in = input("Color");
5512  ShaderOutput *hue_out = output("H");
5513  ShaderOutput *saturation_out = output("S");
5514  ShaderOutput *value_out = output("V");
5515 
5516  compiler.add_node(NODE_SEPARATE_HSV,
5517  compiler.stack_assign(color_in),
5518  compiler.stack_assign(hue_out),
5519  compiler.stack_assign(saturation_out));
5520  compiler.add_node(NODE_SEPARATE_HSV, compiler.stack_assign(value_out));
5521 }
5522 
5523 void SeparateHSVNode::compile(OSLCompiler &compiler)
5524 {
5525  compiler.add(this, "node_separate_hsv");
5526 }
5527 
5528 /* Hue Saturation Value */
5529 
5531 {
5533 
5534  SOCKET_IN_FLOAT(hue, "Hue", 0.5f);
5535  SOCKET_IN_FLOAT(saturation, "Saturation", 1.0f);
5536  SOCKET_IN_FLOAT(value, "Value", 1.0f);
5537  SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
5538  SOCKET_IN_COLOR(color, "Color", zero_float3());
5539 
5540  SOCKET_OUT_COLOR(color, "Color");
5541 
5542  return type;
5543 }
5544 
5545 HSVNode::HSVNode() : ShaderNode(get_node_type())
5546 {
5547 }
5548 
5549 void HSVNode::compile(SVMCompiler &compiler)
5550 {
5551  ShaderInput *hue_in = input("Hue");
5552  ShaderInput *saturation_in = input("Saturation");
5553  ShaderInput *value_in = input("Value");
5554  ShaderInput *fac_in = input("Fac");
5555  ShaderInput *color_in = input("Color");
5556  ShaderOutput *color_out = output("Color");
5557 
5558  compiler.add_node(NODE_HSV,
5559  compiler.encode_uchar4(compiler.stack_assign(color_in),
5560  compiler.stack_assign(fac_in),
5561  compiler.stack_assign(color_out)),
5562  compiler.encode_uchar4(compiler.stack_assign(hue_in),
5563  compiler.stack_assign(saturation_in),
5564  compiler.stack_assign(value_in)));
5565 }
5566 
5567 void HSVNode::compile(OSLCompiler &compiler)
5568 {
5569  compiler.add(this, "node_hsv");
5570 }
5571 
5572 /* Attribute */
5573 
5575 {
5577 
5578  SOCKET_STRING(attribute, "Attribute", ustring());
5579 
5580  SOCKET_OUT_COLOR(color, "Color");
5581  SOCKET_OUT_VECTOR(vector, "Vector");
5582  SOCKET_OUT_FLOAT(fac, "Fac");
5583  SOCKET_OUT_FLOAT(alpha, "Alpha");
5584 
5585  return type;
5586 }
5587 
5588 AttributeNode::AttributeNode() : ShaderNode(get_node_type())
5589 {
5590 }
5591 
5593 {
5594  ShaderOutput *color_out = output("Color");
5595  ShaderOutput *vector_out = output("Vector");
5596  ShaderOutput *fac_out = output("Fac");
5597  ShaderOutput *alpha_out = output("Alpha");
5598 
5599  if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty() ||
5600  !alpha_out->links.empty()) {
5601  attributes->add_standard(attribute);
5602  }
5603 
5604  if (shader->has_volume) {
5606  }
5607 
5609 }
5610 
5611 void AttributeNode::compile(SVMCompiler &compiler)
5612 {
5613  ShaderOutput *color_out = output("Color");
5614  ShaderOutput *vector_out = output("Vector");
5615  ShaderOutput *fac_out = output("Fac");
5616  ShaderOutput *alpha_out = output("Alpha");
5617  ShaderNodeType attr_node = NODE_ATTR;
5618  int attr = compiler.attribute_standard(attribute);
5619 
5620  if (bump == SHADER_BUMP_DX)
5621  attr_node = NODE_ATTR_BUMP_DX;
5622  else if (bump == SHADER_BUMP_DY)
5623  attr_node = NODE_ATTR_BUMP_DY;
5624 
5625  if (!color_out->links.empty() || !vector_out->links.empty()) {
5626  if (!color_out->links.empty()) {
5627  compiler.add_node(
5628  attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_OUTPUT_FLOAT3);
5629  }
5630  if (!vector_out->links.empty()) {
5631  compiler.add_node(
5632  attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_OUTPUT_FLOAT3);
5633  }
5634  }
5635 
5636  if (!fac_out->links.empty()) {
5637  compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_OUTPUT_FLOAT);
5638  }
5639 
5640  if (!alpha_out->links.empty()) {
5641  compiler.add_node(
5642  attr_node, attr, compiler.stack_assign(alpha_out), NODE_ATTR_OUTPUT_FLOAT_ALPHA);
5643  }
5644 }
5645 
5646 void AttributeNode::compile(OSLCompiler &compiler)
5647 {
5648  if (bump == SHADER_BUMP_DX)
5649  compiler.parameter("bump_offset", "dx");
5650  else if (bump == SHADER_BUMP_DY)
5651  compiler.parameter("bump_offset", "dy");
5652  else
5653  compiler.parameter("bump_offset", "center");
5654 
5656  compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
5657  else
5658  compiler.parameter("name", attribute.c_str());
5659 
5660  compiler.add(this, "node_attribute");
5661 }
5662 
5663 /* Camera */
5664 
5666 {
5667  NodeType *type = NodeType::add("camera_info", create, NodeType::SHADER);
5668 
5669  SOCKET_OUT_VECTOR(view_vector, "View Vector");
5670  SOCKET_OUT_FLOAT(view_z_depth, "View Z Depth");
5671  SOCKET_OUT_FLOAT(view_distance, "View Distance");
5672 
5673  return type;
5674 }
5675 
5676 CameraNode::CameraNode() : ShaderNode(get_node_type())
5677 {
5678 }
5679 
5680 void CameraNode::compile(SVMCompiler &compiler)
5681 {
5682  ShaderOutput *vector_out = output("View Vector");
5683  ShaderOutput *z_depth_out = output("View Z Depth");
5684  ShaderOutput *distance_out = output("View Distance");
5685 
5686  compiler.add_node(NODE_CAMERA,
5687  compiler.stack_assign(vector_out),
5688  compiler.stack_assign(z_depth_out),
5689  compiler.stack_assign(distance_out));
5690 }
5691 
5692 void CameraNode::compile(OSLCompiler &compiler)
5693 {
5694  compiler.add(this, "node_camera");
5695 }
5696 
5697 /* Fresnel */
5698 
5700 {
5702 
5705  SOCKET_IN_FLOAT(IOR, "IOR", 1.45f);
5706 
5707  SOCKET_OUT_FLOAT(fac, "Fac");
5708 
5709  return type;
5710 }
5711 
5712 FresnelNode::FresnelNode() : ShaderNode(get_node_type())
5713 {
5714 }
5715 
5716 void FresnelNode::compile(SVMCompiler &compiler)
5717 {
5718  ShaderInput *normal_in = input("Normal");
5719  ShaderInput *IOR_in = input("IOR");
5720  ShaderOutput *fac_out = output("Fac");
5721 
5722  compiler.add_node(NODE_FRESNEL,
5723  compiler.stack_assign(IOR_in),
5724  __float_as_int(IOR),
5725  compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
5726  compiler.stack_assign(fac_out)));
5727 }
5728 
5729 void FresnelNode::compile(OSLCompiler &compiler)
5730 {
5731  compiler.add(this, "node_fresnel");
5732 }
5733 
5734 /* Layer Weight */
5735 
5737 {
5738  NodeType *type = NodeType::add("layer_weight", create, NodeType::SHADER);
5739 
5742  SOCKET_IN_FLOAT(blend, "Blend", 0.5f);
5743 
5744  SOCKET_OUT_FLOAT(fresnel, "Fresnel");
5745  SOCKET_OUT_FLOAT(facing, "Facing");
5746 
5747  return type;
5748 }
5749 
5750 LayerWeightNode::LayerWeightNode() : ShaderNode(get_node_type())
5751 {
5752 }
5753 
5754 void LayerWeightNode::compile(SVMCompiler &compiler)
5755 {
5756  ShaderInput *normal_in = input("Normal");
5757  ShaderInput *blend_in = input("Blend");
5758  ShaderOutput *fresnel_out = output("Fresnel");
5759  ShaderOutput *facing_out = output("Facing");
5760 
5761  if (!fresnel_out->links.empty()) {
5762  compiler.add_node(NODE_LAYER_WEIGHT,
5763  compiler.stack_assign_if_linked(blend_in),
5766  compiler.stack_assign_if_linked(normal_in),
5767  compiler.stack_assign(fresnel_out)));
5768  }
5769 
5770  if (!facing_out->links.empty()) {
5771  compiler.add_node(NODE_LAYER_WEIGHT,
5772  compiler.stack_assign_if_linked(blend_in),
5775  compiler.stack_assign_if_linked(normal_in),
5776  compiler.stack_assign(facing_out)));
5777  }
5778 }
5779 
5780 void LayerWeightNode::compile(OSLCompiler &compiler)
5781 {
5782  compiler.add(this, "node_layer_weight");
5783 }
5784 
5785 /* Wireframe */
5786 
5788 {
5790 
5791  SOCKET_BOOLEAN(use_pixel_size, "Use Pixel Size", false);
5792  SOCKET_IN_FLOAT(size, "Size", 0.01f);
5793  SOCKET_OUT_FLOAT(fac, "Fac");
5794 
5795  return type;
5796 }
5797 
5798 WireframeNode::WireframeNode() : ShaderNode(get_node_type())
5799 {
5800 }
5801 
5802 void WireframeNode::compile(SVMCompiler &compiler)
5803 {
5804  ShaderInput *size_in = input("Size");
5805  ShaderOutput *fac_out = output("Fac");
5807  if (bump == SHADER_BUMP_DX) {
5808  bump_offset = NODE_BUMP_OFFSET_DX;
5809  }
5810  else if (bump == SHADER_BUMP_DY) {
5811  bump_offset = NODE_BUMP_OFFSET_DY;
5812  }
5813  compiler.add_node(NODE_WIREFRAME,
5814  compiler.stack_assign(size_in),
5815  compiler.stack_assign(fac_out),
5816  compiler.encode_uchar4(use_pixel_size, bump_offset, 0, 0));
5817 }
5818 
5819 void WireframeNode::compile(OSLCompiler &compiler)
5820 {
5821  if (bump == SHADER_BUMP_DX) {
5822  compiler.parameter("bump_offset", "dx");
5823  }
5824  else if (bump == SHADER_BUMP_DY) {
5825  compiler.parameter("bump_offset", "dy");
5826  }
5827  else {
5828  compiler.parameter("bump_offset", "center");
5829  }
5830  compiler.parameter(this, "use_pixel_size");
5831  compiler.add(this, "node_wireframe");
5832 }
5833 
5834 /* Wavelength */
5835 
5837 {
5838  NodeType *type = NodeType::add("wavelength", create, NodeType::SHADER);
5839 
5840  SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f);
5841  SOCKET_OUT_COLOR(color, "Color");
5842 
5843  return type;
5844 }
5845 
5846 WavelengthNode::WavelengthNode() : ShaderNode(get_node_type())
5847 {
5848 }
5849 
5850 void WavelengthNode::compile(SVMCompiler &compiler)
5851 {
5852  ShaderInput *wavelength_in = input("Wavelength");
5853  ShaderOutput *color_out = output("Color");
5854 
5855  compiler.add_node(
5856  NODE_WAVELENGTH, compiler.stack_assign(wavelength_in), compiler.stack_assign(color_out));
5857 }
5858 
5859 void WavelengthNode::compile(OSLCompiler &compiler)
5860 {
5861  compiler.add(this, "node_wavelength");
5862 }
5863 
5864 /* Blackbody */
5865 
5867 {
5869 
5870  SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f);
5871  SOCKET_OUT_COLOR(color, "Color");
5872 
5873  return type;
5874 }
5875 
5876 BlackbodyNode::BlackbodyNode() : ShaderNode(get_node_type())
5877 {
5878 }
5879 
5881 {
5882  if (folder.all_inputs_constant()) {
5883  const float3 rgb_rec709 = svm_math_blackbody_color_rec709(temperature);
5884  const float3 rgb = folder.scene->shader_manager->rec709_to_scene_linear(rgb_rec709);
5885  folder.make_constant(max(rgb, zero_float3()));
5886  }
5887 }
5888 
5889 void BlackbodyNode::compile(SVMCompiler &compiler)
5890 {
5891  ShaderInput *temperature_in = input("Temperature");
5892  ShaderOutput *color_out = output("Color");
5893 
5894  compiler.add_node(
5895  NODE_BLACKBODY, compiler.stack_assign(temperature_in), compiler.stack_assign(color_out));
5896 }
5897 
5898 void BlackbodyNode::compile(OSLCompiler &compiler)
5899 {
5900  compiler.add(this, "node_blackbody");
5901 }
5902 
5903 /* Output */
5904 
5906 {
5908 
5909  SOCKET_IN_CLOSURE(surface, "Surface");
5910  SOCKET_IN_CLOSURE(volume, "Volume");
5911  SOCKET_IN_VECTOR(displacement, "Displacement", zero_float3());
5912  SOCKET_IN_NORMAL(normal, "Normal", zero_float3());
5913 
5914  return type;
5915 }
5916 
5917 OutputNode::OutputNode() : ShaderNode(get_node_type())
5918 {
5919  special_type = SHADER_SPECIAL_TYPE_OUTPUT;
5920 }
5921 
5922 void OutputNode::compile(SVMCompiler &compiler)
5923 {
5924  if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
5925  ShaderInput *displacement_in = input("Displacement");
5926 
5927  if (displacement_in->link) {
5928  compiler.add_node(NODE_SET_DISPLACEMENT, compiler.stack_assign(displacement_in));
5929  }
5930  }
5931 }
5932 
5933 void OutputNode::compile(OSLCompiler &compiler)
5934 {
5935  if (compiler.output_type() == SHADER_TYPE_SURFACE)
5936  compiler.add(this, "node_output_surface");
5937  else if (compiler.output_type() == SHADER_TYPE_VOLUME)
5938  compiler.add(this, "node_output_volume");
5939  else if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT)
5940  compiler.add(this, "node_output_displacement");
5941 }
5942 
5943 /* Map Range Node */
5944 
5946 {
5948 
5949  static NodeEnum type_enum;
5950  type_enum.insert("linear", NODE_MAP_RANGE_LINEAR);
5951  type_enum.insert("stepped", NODE_MAP_RANGE_STEPPED);
5952  type_enum.insert("smoothstep", NODE_MAP_RANGE_SMOOTHSTEP);
5953  type_enum.insert("smootherstep", NODE_MAP_RANGE_SMOOTHERSTEP);
5954  SOCKET_ENUM(range_type, "Type", type_enum, NODE_MAP_RANGE_LINEAR);
5955 
5956  SOCKET_IN_FLOAT(value, "Value", 1.0f);
5957  SOCKET_IN_FLOAT(from_min, "From Min", 0.0f);
5958  SOCKET_IN_FLOAT(from_max, "From Max", 1.0f);
5959  SOCKET_IN_FLOAT(to_min, "To Min", 0.0f);
5960  SOCKET_IN_FLOAT(to_max, "To Max", 1.0f);
5961  SOCKET_IN_FLOAT(steps, "Steps", 4.0f);
5962  SOCKET_IN_BOOLEAN(clamp, "Clamp", false);
5963 
5964  SOCKET_OUT_FLOAT(result, "Result");
5965 
5966  return type;
5967 }
5968 
5969 MapRangeNode::MapRangeNode() : ShaderNode(get_node_type())
5970 {
5971 }
5972 
5974 {
5975  if (clamp) {
5976  ShaderOutput *result_out = output("Result");
5977  if (!result_out->links.empty()) {
5978  ClampNode *clamp_node = graph->create_node<ClampNode>();
5979  clamp_node->set_clamp_type(NODE_CLAMP_RANGE);
5980  graph->add(clamp_node);
5981  graph->relink(result_out, clamp_node->output("Result"));
5982  graph->connect(result_out, clamp_node->input("Value"));
5983  if (input("To Min")->link) {
5984  graph->connect(input("To Min")->link, clamp_node->input("Min"));
5985  }
5986  else {
5987  clamp_node->set_min(to_min);
5988  }
5989  if (input("To Max")->link) {
5990  graph->connect(input("To Max")->link, clamp_node->input("Max"));
5991  }
5992  else {
5993  clamp_node->set_max(to_max);
5994  }
5995  }
5996  }
5997 }
5998 
5999 void MapRangeNode::compile(SVMCompiler &compiler)
6000 {
6001  ShaderInput *value_in = input("Value");
6002  ShaderInput *from_min_in = input("From Min");
6003  ShaderInput *from_max_in = input("From Max");
6004  ShaderInput *to_min_in = input("To Min");
6005  ShaderInput *to_max_in = input("To Max");
6006  ShaderInput *steps_in = input("Steps");
6007  ShaderOutput *result_out = output("Result");
6008 
6009  int value_stack_offset = compiler.stack_assign(value_in);
6010  int from_min_stack_offset = compiler.stack_assign_if_linked(from_min_in);
6011  int from_max_stack_offset = compiler.stack_assign_if_linked(from_max_in);
6012  int to_min_stack_offset = compiler.stack_assign_if_linked(to_min_in);
6013  int to_max_stack_offset = compiler.stack_assign_if_linked(to_max_in);
6014  int steps_stack_offset = compiler.stack_assign(steps_in);
6015  int result_stack_offset = compiler.stack_assign(result_out);
6016 
6017  compiler.add_node(
6018  NODE_MAP_RANGE,
6019  value_stack_offset,
6020  compiler.encode_uchar4(
6021  from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset),
6022  compiler.encode_uchar4(range_type, steps_stack_offset, result_stack_offset));
6023 
6024  compiler.add_node(__float_as_int(from_min),
6025  __float_as_int(from_max),
6026  __float_as_int(to_min),
6027  __float_as_int(to_max));
6028  compiler.add_node(__float_as_int(steps));
6029 }
6030 
6031 void MapRangeNode::compile(OSLCompiler &compiler)
6032 {
6033  compiler.parameter(this, "range_type");
6034  compiler.add(this, "node_map_range");
6035 }
6036 
6037 /* Vector Map Range Node */
6038 
6040 {
6041  NodeType *type = NodeType::add("vector_map_range", create, NodeType::SHADER);
6042 
6043  static NodeEnum type_enum;
6044  type_enum.insert("linear", NODE_MAP_RANGE_LINEAR);
6045  type_enum.insert("stepped", NODE_MAP_RANGE_STEPPED);
6046  type_enum.insert("smoothstep", NODE_MAP_RANGE_SMOOTHSTEP);
6047  type_enum.insert("smootherstep", NODE_MAP_RANGE_SMOOTHERSTEP);
6048  SOCKET_ENUM(range_type, "Type", type_enum, NODE_MAP_RANGE_LINEAR);
6049 
6050  SOCKET_IN_VECTOR(vector, "Vector", zero_float3());
6051  SOCKET_IN_VECTOR(from_min, "From_Min_FLOAT3", zero_float3());
6052  SOCKET_IN_VECTOR(from_max, "From_Max_FLOAT3", one_float3());
6053  SOCKET_IN_VECTOR(to_min, "To_Min_FLOAT3", zero_float3());
6054  SOCKET_IN_VECTOR(to_max, "To_Max_FLOAT3", one_float3());
6055  SOCKET_IN_VECTOR(steps, "Steps_FLOAT3", make_float3(4.0f));
6056  SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
6057 
6058  SOCKET_OUT_VECTOR(vector, "Vector");
6059 
6060  return type;
6061 }
6062 
6063 VectorMapRangeNode::VectorMapRangeNode() : ShaderNode(get_node_type())
6064 {
6065 }
6066 
6068 {
6069 }
6070 
6072 {
6073  ShaderInput *vector_in = input("Vector");
6074  ShaderInput *from_min_in = input("From_Min_FLOAT3");
6075  ShaderInput *from_max_in = input("From_Max_FLOAT3");
6076  ShaderInput *to_min_in = input("To_Min_FLOAT3");
6077  ShaderInput *to_max_in = input("To_Max_FLOAT3");
6078  ShaderInput *steps_in = input("Steps_FLOAT3");
6079  ShaderOutput *vector_out = output("Vector");
6080 
6081  int value_stack_offset = compiler.stack_assign(vector_in);
6082  int from_min_stack_offset = compiler.stack_assign(from_min_in);
6083  int from_max_stack_offset = compiler.stack_assign(from_max_in);
6084  int to_min_stack_offset = compiler.stack_assign(to_min_in);
6085  int to_max_stack_offset = compiler.stack_assign(to_max_in);
6086  int steps_stack_offset = compiler.stack_assign(steps_in);
6087  int result_stack_offset = compiler.stack_assign(vector_out);
6088 
6089  compiler.add_node(
6090  NODE_VECTOR_MAP_RANGE,
6091  value_stack_offset,
6092  compiler.encode_uchar4(
6093  from_min_stack_offset, from_max_stack_offset, to_min_stack_offset, to_max_stack_offset),
6094  compiler.encode_uchar4(steps_stack_offset, use_clamp, range_type, result_stack_offset));
6095 }
6096 
6098 {
6099  compiler.parameter(this, "range_type");
6100  compiler.parameter(this, "use_clamp");
6101  compiler.add(this, "node_vector_map_range");
6102 }
6103 
6104 /* Clamp Node */
6105 
6107 {
6109 
6110  static NodeEnum type_enum;
6111  type_enum.insert("minmax", NODE_CLAMP_MINMAX);
6112  type_enum.insert("range", NODE_CLAMP_RANGE);
6113  SOCKET_ENUM(clamp_type, "Type", type_enum, NODE_CLAMP_MINMAX);
6114 
6115  SOCKET_IN_FLOAT(value, "Value", 1.0f);
6116  SOCKET_IN_FLOAT(min, "Min", 0.0f);
6117  SOCKET_IN_FLOAT(max, "Max", 1.0f);
6118 
6119  SOCKET_OUT_FLOAT(result, "Result");
6120 
6121  return type;
6122 }
6123 
6124 ClampNode::ClampNode() : ShaderNode(get_node_type())
6125 {
6126 }
6127 
6129 {
6130  if (folder.all_inputs_constant()) {
6131  if (clamp_type == NODE_CLAMP_RANGE && (min > max)) {
6132  folder.make_constant(clamp(value, max, min));
6133  }
6134  else {
6135  folder.make_constant(clamp(value, min, max));
6136  }
6137  }
6138 }
6139 
6140 void ClampNode::compile(SVMCompiler &compiler)
6141 {
6142  ShaderInput *value_in = input("Value");
6143  ShaderInput *min_in = input("Min");
6144  ShaderInput *max_in = input("Max");
6145  ShaderOutput *result_out = output("Result");
6146 
6147  int value_stack_offset = compiler.stack_assign(value_in);
6148  int min_stack_offset = compiler.stack_assign(min_in);
6149  int max_stack_offset = compiler.stack_assign(max_in);
6150  int result_stack_offset = compiler.stack_assign(result_out);
6151 
6152  compiler.add_node(NODE_CLAMP,
6153  value_stack_offset,
6154  compiler.encode_uchar4(min_stack_offset, max_stack_offset, clamp_type),
6155  result_stack_offset);
6157 }
6158 
6159 void ClampNode::compile(OSLCompiler &compiler)
6160 {
6161  compiler.parameter(this, "clamp_type");
6162  compiler.add(this, "node_clamp");
6163 }
6164 
6165 /* AOV Output */
6166 
6168 {
6169  NodeType *type = NodeType::add("aov_output", create, NodeType::SHADER);
6170 
6171  SOCKET_IN_COLOR(color, "Color", zero_float3());
6172  SOCKET_IN_FLOAT(value, "Value", 0.0f);
6173 
6174  SOCKET_STRING(name, "AOV Name", ustring(""));
6175 
6176  return type;
6177 }
6178 
6179 OutputAOVNode::OutputAOVNode() : ShaderNode(get_node_type())
6180 {
6181  special_type = SHADER_SPECIAL_TYPE_OUTPUT_AOV;
6182  offset = -1;
6183 }
6184 
6186 {
6187  offset = scene->film->get_aov_offset(scene, name.string(), is_color);
6188  if (offset == -1) {
6189  offset = scene->film->get_aov_offset(scene, name.string(), is_color);
6190  }
6191 
6192  if (offset == -1 || is_color) {
6193  input("Value")->disconnect();
6194  }
6195  if (offset == -1 || !is_color) {
6196  input("Color")->disconnect();
6197  }
6198 }
6199 
6200 void OutputAOVNode::compile(SVMCompiler &compiler)
6201 {
6202  assert(offset >= 0);
6203 
6204  if (is_color) {
6205  compiler.add_node(NODE_AOV_COLOR, compiler.stack_assign(input("Color")), offset);
6206  }
6207  else {
6208  compiler.add_node(NODE_AOV_VALUE, compiler.stack_assign(input("Value")), offset);
6209  }
6210 }
6211 
6212 void OutputAOVNode::compile(OSLCompiler & /*compiler*/)
6213 {
6214  /* TODO */
6215 }
6216 
6217 /* Math */
6218 
6220 {
6222 
6223  static NodeEnum type_enum;
6224  type_enum.insert("add", NODE_MATH_ADD);
6225  type_enum.insert("subtract", NODE_MATH_SUBTRACT);
6226  type_enum.insert("multiply", NODE_MATH_MULTIPLY);
6227  type_enum.insert("divide", NODE_MATH_DIVIDE);
6228  type_enum.insert("multiply_add", NODE_MATH_MULTIPLY_ADD);
6229  type_enum.insert("sine", NODE_MATH_SINE);
6230  type_enum.insert("cosine", NODE_MATH_COSINE);
6231  type_enum.insert("tangent", NODE_MATH_TANGENT);
6232  type_enum.insert("sinh", NODE_MATH_SINH);
6233  type_enum.insert("cosh", NODE_MATH_COSH);
6234  type_enum.insert("tanh", NODE_MATH_TANH);
6235  type_enum.insert("arcsine", NODE_MATH_ARCSINE);
6236  type_enum.insert("arccosine", NODE_MATH_ARCCOSINE);
6237  type_enum.insert("arctangent", NODE_MATH_ARCTANGENT);
6238  type_enum.insert("power", NODE_MATH_POWER);
6239  type_enum.insert("logarithm", NODE_MATH_LOGARITHM);
6240  type_enum.insert("minimum", NODE_MATH_MINIMUM);
6241  type_enum.insert("maximum", NODE_MATH_MAXIMUM);
6242  type_enum.insert("round", NODE_MATH_ROUND);
6243  type_enum.insert("less_than", NODE_MATH_LESS_THAN);
6244  type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
6245  type_enum.insert("modulo", NODE_MATH_MODULO);
6246  type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
6247  type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
6248  type_enum.insert("floor", NODE_MATH_FLOOR);
6249  type_enum.insert("ceil", NODE_MATH_CEIL);
6250  type_enum.insert("fraction", NODE_MATH_FRACTION);
6251  type_enum.insert("trunc", NODE_MATH_TRUNC);
6252  type_enum.insert("snap", NODE_MATH_SNAP);
6253  type_enum.insert("wrap", NODE_MATH_WRAP);
6254  type_enum.insert("pingpong", NODE_MATH_PINGPONG);
6255  type_enum.insert("sqrt", NODE_MATH_SQRT);
6256  type_enum.insert("inversesqrt", NODE_MATH_INV_SQRT);
6257  type_enum.insert("sign", NODE_MATH_SIGN);
6258  type_enum.insert("exponent", NODE_MATH_EXPONENT);
6259  type_enum.insert("radians", NODE_MATH_RADIANS);
6260  type_enum.insert("degrees", NODE_MATH_DEGREES);
6261  type_enum.insert("smoothmin", NODE_MATH_SMOOTH_MIN);
6262  type_enum.insert("smoothmax", NODE_MATH_SMOOTH_MAX);
6263  type_enum.insert("compare", NODE_MATH_COMPARE);
6264  SOCKET_ENUM(math_type, "Type", type_enum, NODE_MATH_ADD);
6265 
6266  SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
6267 
6268  SOCKET_IN_FLOAT(value1, "Value1", 0.5f);
6269  SOCKET_IN_FLOAT(value2, "Value2", 0.5f);
6270  SOCKET_IN_FLOAT(value3, "Value3", 0.0f);
6271 
6272  SOCKET_OUT_FLOAT(value, "Value");
6273 
6274  return type;
6275 }
6276 
6277 MathNode::MathNode() : ShaderNode(get_node_type())
6278 {
6279 }
6280 
6282 {
6283  if (use_clamp) {
6284  ShaderOutput *result_out = output("Value");
6285  if (!result_out->links.empty()) {
6286  ClampNode *clamp_node = graph->create_node<ClampNode>();
6287  clamp_node->set_clamp_type(NODE_CLAMP_MINMAX);
6288  clamp_node->set_min(0.0f);
6289  clamp_node->set_max(1.0f);
6290  graph->add(clamp_node);
6291  graph->relink(result_out, clamp_node->output("Result"));
6292  graph->connect(result_out, clamp_node->input("Value"));
6293  }
6294  }
6295 }
6296 
6298 {
6299  if (folder.all_inputs_constant()) {
6300  folder.make_constant(svm_math(math_type, value1, value2, value3));
6301  }
6302  else {
6303  folder.fold_math(math_type);
6304  }
6305 }
6306 
6307 void MathNode::compile(SVMCompiler &compiler)
6308 {
6309  ShaderInput *value1_in = input("Value1");
6310  ShaderInput *value2_in = input("Value2");
6311  ShaderInput *value3_in = input("Value3");
6312  ShaderOutput *value_out = output("Value");
6313 
6314  int value1_stack_offset = compiler.stack_assign(value1_in);
6315  int value2_stack_offset = compiler.stack_assign(value2_in);
6316  int value3_stack_offset = compiler.stack_assign(value3_in);
6317  int value_stack_offset = compiler.stack_assign(value_out);
6318 
6319  compiler.add_node(
6320  NODE_MATH,
6321  math_type,
6322  compiler.encode_uchar4(value1_stack_offset, value2_stack_offset, value3_stack_offset),
6323  value_stack_offset);
6324 }
6325 
6326 void MathNode::compile(OSLCompiler &compiler)
6327 {
6328  compiler.parameter(this, "math_type");
6329  compiler.add(this, "node_math");
6330 }
6331 
6332 /* VectorMath */
6333 
6335 {
6336  NodeType *type = NodeType::add("vector_math", create, NodeType::SHADER);
6337 
6338  static NodeEnum type_enum;
6339  type_enum.insert("add", NODE_VECTOR_MATH_ADD);
6340  type_enum.insert("subtract", NODE_VECTOR_MATH_SUBTRACT);
6341  type_enum.insert("multiply", NODE_VECTOR_MATH_MULTIPLY);
6342  type_enum.insert("divide", NODE_VECTOR_MATH_DIVIDE);
6343 
6344  type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
6345  type_enum.insert("project", NODE_VECTOR_MATH_PROJECT);
6346  type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT);
6347  type_enum.insert("refract", NODE_VECTOR_MATH_REFRACT);
6348  type_enum.insert("faceforward", NODE_VECTOR_MATH_FACEFORWARD);
6349  type_enum.insert("multiply_add", NODE_VECTOR_MATH_MULTIPLY_ADD);
6350 
6351  type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
6352 
6353  type_enum.insert("distance", NODE_VECTOR_MATH_DISTANCE);
6354  type_enum.insert("length", NODE_VECTOR_MATH_LENGTH);
6355  type_enum.insert("scale", NODE_VECTOR_MATH_SCALE);
6356  type_enum.insert("normalize", NODE_VECTOR_MATH_NORMALIZE);
6357 
6358  type_enum.insert("snap", NODE_VECTOR_MATH_SNAP);
6359  type_enum.insert("floor", NODE_VECTOR_MATH_FLOOR);
6360  type_enum.insert("ceil", NODE_VECTOR_MATH_CEIL);
6361  type_enum.insert("modulo", NODE_VECTOR_MATH_MODULO);
6362  type_enum.insert("wrap", NODE_VECTOR_MATH_WRAP);
6363  type_enum.insert("fraction", NODE_VECTOR_MATH_FRACTION);
6364  type_enum.insert("absolute", NODE_VECTOR_MATH_ABSOLUTE);
6365  type_enum.insert("minimum", NODE_VECTOR_MATH_MINIMUM);
6366  type_enum.insert("maximum", NODE_VECTOR_MATH_MAXIMUM);
6367 
6368  type_enum.insert("sine", NODE_VECTOR_MATH_SINE);
6369  type_enum.insert("cosine", NODE_VECTOR_MATH_COSINE);
6370  type_enum.insert("tangent", NODE_VECTOR_MATH_TANGENT);
6371  SOCKET_ENUM(math_type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
6372 
6373  SOCKET_IN_VECTOR(vector1, "Vector1", zero_float3());
6374  SOCKET_IN_VECTOR(vector2, "Vector2", zero_float3());
6375  SOCKET_IN_VECTOR(vector3, "Vector3", zero_float3());
6376  SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
6377 
6378  SOCKET_OUT_FLOAT(value, "Value");
6379  SOCKET_OUT_VECTOR(vector, "Vector");
6380 
6381  return type;
6382 }
6383 
6384 VectorMathNode::VectorMathNode() : ShaderNode(get_node_type())
6385 {
6386 }
6387 
6389 {
6390  float value = 0.0f;
6392 
6393  if (folder.all_inputs_constant()) {
6394  svm_vector_math(&value, &vector, math_type, vector1, vector2, vector3, scale);
6395  if (folder.output == output("Value")) {
6396  folder.make_constant(value);
6397  }
6398  else if (folder.output == output("Vector")) {
6399  folder.make_constant(vector);
6400  }
6401  }
6402  else {
6403  folder.fold_vector_math(math_type);
6404  }
6405 }
6406 
6407 void VectorMathNode::compile(SVMCompiler &compiler)
6408 {
6409  ShaderInput *vector1_in = input("Vector1");
6410  ShaderInput *vector2_in = input("Vector2");
6411  ShaderInput *param1_in = input("Scale");
6412  ShaderOutput *value_out = output("Value");
6413  ShaderOutput *vector_out = output("Vector");
6414 
6415  int vector1_stack_offset = compiler.stack_assign(vector1_in);
6416  int vector2_stack_offset = compiler.stack_assign(vector2_in);
6417  int param1_stack_offset = compiler.stack_assign(param1_in);
6418  int value_stack_offset = compiler.stack_assign_if_linked(value_out);
6419  int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
6420 
6421  /* 3 Vector Operators */
6422  if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD ||
6423  math_type == NODE_VECTOR_MATH_MULTIPLY_ADD) {
6424  ShaderInput *vector3_in = input("Vector3");
6425  int vector3_stack_offset = compiler.stack_assign(vector3_in);
6426  compiler.add_node(
6427  NODE_VECTOR_MATH,
6428  math_type,
6429  compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset),
6430  compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
6431  compiler.add_node(vector3_stack_offset);
6432  }
6433  else {
6434  compiler.add_node(
6435  NODE_VECTOR_MATH,
6436  math_type,
6437  compiler.encode_uchar4(vector1_stack_offset, vector2_stack_offset, param1_stack_offset),
6438  compiler.encode_uchar4(value_stack_offset, vector_stack_offset));
6439  }
6440 }
6441 
6442 void VectorMathNode::compile(OSLCompiler &compiler)
6443 {
6444  compiler.parameter(this, "math_type");
6445  compiler.add(this, "node_vector_math");
6446 }
6447 
6448 /* Vector Rotate */
6449 
6451 {
6452  NodeType *type = NodeType::add("vector_rotate", create, NodeType::SHADER);
6453 
6454  static NodeEnum type_enum;
6455  type_enum.insert("axis", NODE_VECTOR_ROTATE_TYPE_AXIS);
6456  type_enum.insert("x_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_X);
6457  type_enum.insert("y_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Y);
6458  type_enum.insert("z_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Z);
6459  type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ);
6460  SOCKET_ENUM(rotate_type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS);
6461 
6462  SOCKET_BOOLEAN(invert, "Invert", false);
6463 
6464  SOCKET_IN_VECTOR(vector, "Vector", zero_float3());
6465  SOCKET_IN_POINT(rotation, "Rotation", zero_float3());
6466  SOCKET_IN_POINT(center, "Center", zero_float3());
6467  SOCKET_IN_VECTOR(axis, "Axis", make_float3(0.0f, 0.0f, 1.0f));
6468  SOCKET_IN_FLOAT(angle, "Angle", 0.0f);
6469  SOCKET_OUT_VECTOR(vector, "Vector");
6470 
6471  return type;
6472 }
6473 
6474 VectorRotateNode::VectorRotateNode() : ShaderNode(get_node_type())
6475 {
6476 }
6477 
6478 void VectorRotateNode::compile(SVMCompiler &compiler)
6479 {
6480  ShaderInput *vector_in = input("Vector");
6481  ShaderInput *rotation_in = input("Rotation");
6482  ShaderInput *center_in = input("Center");
6483  ShaderInput *axis_in = input("Axis");
6484  ShaderInput *angle_in = input("Angle");
6485  ShaderOutput *vector_out = output("Vector");
6486 
6487  compiler.add_node(NODE_VECTOR_ROTATE,
6488  compiler.encode_uchar4(rotate_type,
6489  compiler.stack_assign(vector_in),
6490  compiler.stack_assign(rotation_in),
6491  invert),
6492  compiler.encode_uchar4(compiler.stack_assign(center_in),
6493  compiler.stack_assign(axis_in),
6494  compiler.stack_assign(angle_in)),
6495  compiler.stack_assign(vector_out));
6496 }
6497 
6498 void VectorRotateNode::compile(OSLCompiler &compiler)
6499 {
6500  compiler.parameter(this, "rotate_type");
6501  compiler.parameter(this, "invert");
6502  compiler.add(this, "node_vector_rotate");
6503 }
6504 
6505 /* VectorTransform */
6506 
6508 {
6509  NodeType *type = NodeType::add("vector_transform", create, NodeType::SHADER);
6510 
6511  static NodeEnum type_enum;
6512  type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
6513  type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
6514  type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
6515  SOCKET_ENUM(transform_type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
6516 
6517  static NodeEnum space_enum;
6519  space_enum.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
6520  space_enum.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA);
6521  SOCKET_ENUM(convert_from, "Convert From", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
6522  SOCKET_ENUM(convert_to, "Convert To", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
6523 
6524  SOCKET_IN_VECTOR(vector, "Vector", zero_float3());
6525  SOCKET_OUT_VECTOR(vector, "Vector");
6526 
6527  return type;
6528 }
6529 
6530 VectorTransformNode::VectorTransformNode() : ShaderNode(get_node_type())
6531 {
6532 }
6533 
6535 {
6536  ShaderInput *vector_in = input("Vector");
6537  ShaderOutput *vector_out = output("Vector");
6538 
6539  compiler.add_node(
6540  NODE_VECTOR_TRANSFORM,
6541  compiler.encode_uchar4(transform_type, convert_from, convert_to),
6542  compiler.encode_uchar4(compiler.stack_assign(vector_in), compiler.stack_assign(vector_out)));
6543 }
6544 
6546 {
6547  compiler.parameter(this, "transform_type");
6548  compiler.parameter(this, "convert_from");
6549  compiler.parameter(this, "convert_to");
6550  compiler.add(this, "node_vector_transform");
6551 }
6552 
6553 /* BumpNode */
6554 
6556 {
6558 
6559  SOCKET_BOOLEAN(invert, "Invert", false);
6560  SOCKET_BOOLEAN(use_object_space, "UseObjectSpace", false);
6561 
6562  /* this input is used by the user, but after graph transform it is no longer
6563  * used and moved to sampler center/x/y instead */
6564  SOCKET_IN_FLOAT(height, "Height", 1.0f);
6565 
6566  SOCKET_IN_FLOAT(sample_center, "SampleCenter", 0.0f);
6567  SOCKET_IN_FLOAT(sample_x, "SampleX", 0.0f);
6568  SOCKET_IN_FLOAT(sample_y, "SampleY", 0.0f);
6570  SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
6571  SOCKET_IN_FLOAT(distance, "Distance", 0.1f);
6572 
6573  SOCKET_OUT_NORMAL(normal, "Normal");
6574 
6575  return type;
6576 }
6577 
6578 BumpNode::BumpNode() : ShaderNode(get_node_type())
6579 {
6580  special_type = SHADER_SPECIAL_TYPE_BUMP;
6581 }
6582 
6583 void BumpNode::compile(SVMCompiler &compiler)
6584 {
6585  ShaderInput *center_in = input("SampleCenter");
6586  ShaderInput *dx_in = input("SampleX");
6587  ShaderInput *dy_in = input("SampleY");
6588  ShaderInput *normal_in = input("Normal");
6589  ShaderInput *strength_in = input("Strength");
6590  ShaderInput *distance_in = input("Distance");
6591  ShaderOutput *normal_out = output("Normal");
6592 
6593  /* pack all parameters in the node */
6594  compiler.add_node(NODE_SET_BUMP,
6595  compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
6596  compiler.stack_assign(distance_in),
6597  invert,
6598  use_object_space),
6599  compiler.encode_uchar4(compiler.stack_assign(center_in),
6600  compiler.stack_assign(dx_in),
6601  compiler.stack_assign(dy_in),
6602  compiler.stack_assign(strength_in)),
6603  compiler.stack_assign(normal_out));
6604 }
6605 
6606 void BumpNode::compile(OSLCompiler &compiler)
6607 {
6608  compiler.parameter(this, "invert");
6609  compiler.parameter(this, "use_object_space");
6610  compiler.add(this, "node_bump");
6611 }
6612 
6614 {
6615  ShaderInput *height_in = input("Height");
6616  ShaderInput *normal_in = input("Normal");
6617 
6618  if (height_in->link == NULL) {
6619  if (normal_in->link == NULL) {
6620  GeometryNode *geom = folder.graph->create_node<GeometryNode>();
6621  folder.graph->add(geom);
6622  folder.bypass(geom->output("Normal"));
6623  }
6624  else {
6625  folder.bypass(normal_in->link);
6626  }
6627  }
6628 
6629  /* TODO(sergey): Ignore bump with zero strength. */
6630 }
6631 
6632 /* Curves node */
6633 
6634 CurvesNode::CurvesNode(const NodeType *node_type) : ShaderNode(node_type)
6635 {
6636 }
6637 
6639 {
6640  ShaderInput *fac_in = input("Fac");
6641 
6642  /* evaluate fully constant node */
6643  if (folder.all_inputs_constant()) {
6644  if (curves.size() == 0) {
6645  return;
6646  }
6647 
6648  float3 pos = (value - make_float3(min_x, min_x, min_x)) / (max_x - min_x);
6649  float3 result;
6650 
6651  result[0] = rgb_ramp_lookup(curves.data(), pos[0], true, extrapolate, curves.size()).x;
6652  result[1] = rgb_ramp_lookup(curves.data(), pos[1], true, extrapolate, curves.size()).y;
6653  result[2] = rgb_ramp_lookup(curves.data(), pos[2], true, extrapolate, curves.size()).z;
6654 
6655  folder.make_constant(interp(value, result, fac));
6656  }
6657  /* remove no-op node */
6658  else if (!fac_in->link && fac == 0.0f) {
6659  /* link is not null because otherwise all inputs are constant */
6660  folder.bypass(value_in->link);
6661  }
6662 }
6663 
6665  int type,
6666  ShaderInput *value_in,
6667  ShaderOutput *value_out)
6668 {
6669  if (curves.size() == 0)
6670  return;
6671 
6672  ShaderInput *fac_in = input("Fac");
6673 
6674  compiler.add_node(ShaderNodeType(type),
6675  compiler.encode_uchar4(compiler.stack_assign(fac_in),
6676  compiler.stack_assign(value_in),
6677  compiler.stack_assign(value_out),
6678  extrapolate),
6679  __float_as_int(min_x),
6680  __float_as_int(max_x));
6681 
6682  compiler.add_node(curves.size());
6683  for (int i = 0; i < curves.size(); i++)
6684  compiler.add_node(float3_to_float4(curves[i]));
6685 }
6686 
6687 void CurvesNode::compile(OSLCompiler &compiler, const char *name)
6688 {
6689  if (curves.size() == 0)
6690  return;
6691 
6692  compiler.parameter_color_array("ramp", curves);
6693  compiler.parameter(this, "min_x");
6694  compiler.parameter(this, "max_x");
6695  compiler.parameter(this, "extrapolate");
6696  compiler.add(this, name);
6697 }
6698 
6699 void CurvesNode::compile(SVMCompiler & /*compiler*/)
6700 {
6701  assert(0);
6702 }
6703 
6704 void CurvesNode::compile(OSLCompiler & /*compiler*/)
6705 {
6706  assert(0);
6707 }
6708 
6709 /* RGBCurvesNode */
6710 
6712 {
6713  NodeType *type = NodeType::add("rgb_curves", create, NodeType::SHADER);
6714 
6715  SOCKET_COLOR_ARRAY(curves, "Curves", array<float3>());
6716  SOCKET_FLOAT(min_x, "Min X", 0.0f);
6717  SOCKET_FLOAT(max_x, "Max X", 1.0f);
6718  SOCKET_BOOLEAN(extrapolate, "Extrapolate", true);
6719 
6720  SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
6721  SOCKET_IN_COLOR(value, "Color", zero_float3());
6722 
6723  SOCKET_OUT_COLOR(value, "Color");
6724 
6725  return type;
6726 }
6727 
6728 RGBCurvesNode::RGBCurvesNode() : CurvesNode(get_node_type())
6729 {
6730 }
6731 
6733 {
6734  CurvesNode::constant_fold(folder, input("Color"));
6735 }
6736 
6737 void RGBCurvesNode::compile(SVMCompiler &compiler)
6738 {
6739  CurvesNode::compile(compiler, NODE_CURVES, input("Color"), output("Color"));
6740 }
6741 
6742 void RGBCurvesNode::compile(OSLCompiler &compiler)
6743 {
6744  CurvesNode::compile(compiler, "node_rgb_curves");
6745 }
6746 
6747 /* VectorCurvesNode */
6748 
6750 {
6751  NodeType *type = NodeType::add("vector_curves", create, NodeType::SHADER);
6752 
6754  SOCKET_FLOAT(min_x, "Min X", 0.0f);
6755  SOCKET_FLOAT(max_x, "Max X", 1.0f);
6756  SOCKET_BOOLEAN(extrapolate, "Extrapolate", true);
6757 
6758  SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
6759  SOCKET_IN_VECTOR(value, "Vector", zero_float3());
6760 
6761  SOCKET_OUT_VECTOR(value, "Vector");
6762 
6763  return type;
6764 }
6765 
6766 VectorCurvesNode::VectorCurvesNode() : CurvesNode(get_node_type())
6767 {
6768 }
6769 
6771 {
6772  CurvesNode::constant_fold(folder, input("Vector"));
6773 }
6774 
6775 void VectorCurvesNode::compile(SVMCompiler &compiler)
6776 {
6777  CurvesNode::compile(compiler, NODE_CURVES, input("Vector"), output("Vector"));
6778 }
6779 
6780 void VectorCurvesNode::compile(OSLCompiler &compiler)
6781 {
6782  CurvesNode::compile(compiler, "node_vector_curves");
6783 }
6784 
6785 /* FloatCurveNode */
6786 
6788 {
6789  NodeType *type = NodeType::add("float_curve", create, NodeType::SHADER);
6790 
6791  SOCKET_FLOAT_ARRAY(curve, "Curve", array<float>());
6792  SOCKET_FLOAT(min_x, "Min X", 0.0f);
6793  SOCKET_FLOAT(max_x, "Max X", 1.0f);
6794  SOCKET_BOOLEAN(extrapolate, "Extrapolate", true);
6795 
6796  SOCKET_IN_FLOAT(fac, "Factor", 0.0f);
6797  SOCKET_IN_FLOAT(value, "Value", 0.0f);
6798 
6799  SOCKET_OUT_FLOAT(value, "Value");
6800 
6801  return type;
6802 }
6803 
6804 FloatCurveNode::FloatCurveNode() : ShaderNode(get_node_type())
6805 {
6806 }
6807 
6809 {
6810  ShaderInput *value_in = input("Value");
6811  ShaderInput *fac_in = input("Factor");
6812 
6813  /* evaluate fully constant node */
6814  if (folder.all_inputs_constant()) {
6815  if (curve.size() == 0) {
6816  return;
6817  }
6818 
6819  float pos = (value - min_x) / (max_x - min_x);
6820  float result = float_ramp_lookup(curve.data(), pos, true, extrapolate, curve.size());
6821 
6822  folder.make_constant(value + fac * (result - value));
6823  }
6824  /* remove no-op node */
6825  else if (!fac_in->link && fac == 0.0f) {
6826  /* link is not null because otherwise all inputs are constant */
6827  folder.bypass(value_in->link);
6828  }
6829 }
6830 
6831 void FloatCurveNode::compile(SVMCompiler &compiler)
6832 {
6833  if (curve.size() == 0)
6834  return;
6835 
6836  ShaderInput *value_in = input("Value");
6837  ShaderInput *fac_in = input("Factor");
6838  ShaderOutput *value_out = output("Value");
6839 
6840  compiler.add_node(NODE_FLOAT_CURVE,
6841  compiler.encode_uchar4(compiler.stack_assign(fac_in),
6842  compiler.stack_assign(value_in),
6843  compiler.stack_assign(value_out),
6844  extrapolate),
6845  __float_as_int(min_x),
6846  __float_as_int(max_x));
6847 
6848  compiler.add_node(curve.size());
6849  for (int i = 0; i < curve.size(); i++)
6850  compiler.add_node(make_float4(curve[i]));
6851 }
6852 
6853 void FloatCurveNode::compile(OSLCompiler &compiler)
6854 {
6855  if (curve.size() == 0)
6856  return;
6857 
6858  compiler.parameter_array("ramp", curve.data(), curve.size());
6859  compiler.parameter(this, "min_x");
6860  compiler.parameter(this, "max_x");
6861  compiler.parameter(this, "extrapolate");
6862  compiler.add(this, "node_float_curve");
6863 }
6864 
6865 /* RGBRampNode */
6866 
6868 {
6870 
6871  SOCKET_COLOR_ARRAY(ramp, "Ramp", array<float3>());
6872  SOCKET_FLOAT_ARRAY(ramp_alpha, "Ramp Alpha", array<float>());
6873  SOCKET_BOOLEAN(interpolate, "Interpolate", true);
6874 
6875  SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
6876 
6877  SOCKET_OUT_COLOR(color, "Color");
6878  SOCKET_OUT_FLOAT(alpha, "Alpha");
6879 
6880  return type;
6881 }
6882 
6883 RGBRampNode::RGBRampNode() : ShaderNode(get_node_type())
6884 {
6885 }
6886 
6888 {
6889  if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
6890  return;
6891 
6892  if (folder.all_inputs_constant()) {
6893  float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
6894 
6895  /* clamp int as well in case of NaN */
6896  int i = clamp((int)f, 0, ramp.size() - 1);
6897  float t = f - (float)i;
6898 
6899  bool use_lerp = interpolate && t > 0.0f;
6900 
6901  if (folder.output == output("Color")) {
6902  float3 color = rgb_ramp_lookup(ramp.data(), fac, use_lerp, false, ramp.size());
6903  folder.make_constant(color);
6904  }
6905  else if (folder.output == output("Alpha")) {
6906  float alpha = float_ramp_lookup(ramp_alpha.data(), fac, use_lerp, false, ramp_alpha.size());
6907  folder.make_constant(alpha);
6908  }
6909  }
6910 }
6911 
6912 void RGBRampNode::compile(SVMCompiler &compiler)
6913 {
6914  if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
6915  return;
6916 
6917  ShaderInput *fac_in = input("Fac");
6918  ShaderOutput *color_out = output("Color");
6919  ShaderOutput *alpha_out = output("Alpha");
6920 
6921  compiler.add_node(NODE_RGB_RAMP,
6922  compiler.encode_uchar4(compiler.stack_assign(fac_in),
6924  compiler.stack_assign_if_linked(alpha_out)),
6925  interpolate);
6926 
6927  compiler.add_node(ramp.size());
6928  for (int i = 0; i < ramp.size(); i++)
6929  compiler.add_node(make_float4(ramp[i].x, ramp[i].y, ramp[i].z, ramp_alpha[i]));
6930 }
6931 
6932 void RGBRampNode::compile(OSLCompiler &compiler)
6933 {
6934  if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
6935  return;
6936 
6937  compiler.parameter_color_array("ramp_color", ramp);
6938  compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
6939  compiler.parameter(this, "interpolate");
6940 
6941  compiler.add(this, "node_rgb_ramp");
6942 }
6943 
6944 /* Set Normal Node */
6945 
6947 {
6948  NodeType *type = NodeType::add("set_normal", create, NodeType::SHADER);
6949 
6950  SOCKET_IN_VECTOR(direction, "Direction", zero_float3());
6951  SOCKET_OUT_NORMAL(normal, "Normal");
6952 
6953  return type;
6954 }
6955 
6956 SetNormalNode::SetNormalNode() : ShaderNode(get_node_type())
6957 {
6958 }
6959 
6960 void SetNormalNode::compile(SVMCompiler &compiler)
6961 {
6962  ShaderInput *direction_in = input("Direction");
6963  ShaderOutput *normal_out = output("Normal");
6964 
6965  compiler.add_node(NODE_CLOSURE_SET_NORMAL,
6966  compiler.stack_assign(direction_in),
6967  compiler.stack_assign(normal_out));
6968 }
6969 
6970 void SetNormalNode::compile(OSLCompiler &compiler)
6971 {
6972  compiler.add(this, "node_set_normal");
6973 }
6974 
6975 /* OSLNode */
6976 
6977 OSLNode::OSLNode() : ShaderNode(new NodeType(NodeType::SHADER))
6978 {
6979  special_type = SHADER_SPECIAL_TYPE_OSL;
6980 }
6981 
6983 {
6984  delete type;
6985 }
6986 
6988 {
6989  return OSLNode::create(graph, this->inputs.size(), this);
6990 }
6991 
6992 OSLNode *OSLNode::create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from)
6993 {
6994  /* allocate space for the node itself and parameters, aligned to 16 bytes
6995  * assuming that's the most parameter types need */
6996  size_t node_size = align_up(sizeof(OSLNode), 16);
6997  size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
6998 
6999  char *node_memory = (char *)operator new(node_size + inputs_size);
7000  memset(node_memory, 0, node_size + inputs_size);
7001 
7002  if (!from) {
7003  OSLNode *node = new (node_memory) OSLNode();
7004  node->set_owner(graph);
7005  return node;
7006  }
7007  else {
7008  /* copy input default values and node type for cloning */
7009  memcpy(node_memory + node_size, (char *)from + node_size, inputs_size);
7010 
7011  OSLNode *node = new (node_memory) OSLNode(*from);
7012  node->type = new NodeType(*(from->type));
7013  node->set_owner(from->owner);
7014  return node;
7015  }
7016 }
7017 
7019 {
7020  /* pointer to default value storage, which is the same as our actual value */
7021  size_t num_inputs = type->inputs.size();
7022  size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
7023  return (char *)this + align_up(sizeof(OSLNode), 16) + inputs_size;
7024 }
7025 
7026 void OSLNode::add_input(ustring name, SocketType::Type socket_type)
7027 {
7028  char *memory = input_default_value();
7029  size_t offset = memory - (char *)this;
7030  const_cast<NodeType *>(type)->register_input(
7031  name, name, socket_type, offset, memory, NULL, NULL, SocketType::LINKABLE);
7032 }
7033 
7034 void OSLNode::add_output(ustring name, SocketType::Type socket_type)
7035 {
7036  const_cast<NodeType *>(type)->register_output(name, name, socket_type);
7037 }
7038 
7040 {
7041  /* doesn't work for SVM, obviously ... */
7042 }
7043 
7044 void OSLNode::compile(OSLCompiler &compiler)
7045 {
7046  if (!filepath.empty())
7047  compiler.add(this, filepath.c_str(), true);
7048  else
7049  compiler.add(this, bytecode_hash.c_str(), false);
7050 }
7051 
7052 /* Normal Map */
7053 
7055 {
7056  NodeType *type = NodeType::add("normal_map", create, NodeType::SHADER);
7057 
7058  static NodeEnum space_enum;
7059  space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
7060  space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
7061  space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
7062  space_enum.insert("blender_object", NODE_NORMAL_MAP_BLENDER_OBJECT);
7063  space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
7064  SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
7065 
7066  SOCKET_STRING(attribute, "Attribute", ustring());
7067 
7069  normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
7070  SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
7071  SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f));
7072 
7073  SOCKET_OUT_NORMAL(normal, "Normal");
7074 
7075  return type;
7076 }
7077 
7078 NormalMapNode::NormalMapNode() : ShaderNode(get_node_type())
7079 {
7080 }
7081 
7083 {
7084  if (shader->has_surface_link() && space == NODE_NORMAL_MAP_TANGENT) {
7085  if (attribute.empty()) {
7088  }
7089  else {
7090  attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7091  attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
7092  }
7093  }
7094 
7096 }
7097 
7098 void NormalMapNode::compile(SVMCompiler &compiler)
7099 {
7100  ShaderInput *color_in = input("Color");
7101  ShaderInput *strength_in = input("Strength");
7102  ShaderOutput *normal_out = output("Normal");
7103  int attr = 0, attr_sign = 0;
7104 
7105  if (space == NODE_NORMAL_MAP_TANGENT) {
7106  if (attribute.empty()) {
7107  attr = compiler.attribute(ATTR_STD_UV_TANGENT);
7108  attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
7109  }
7110  else {
7111  attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7112  attr_sign = compiler.attribute(
7113  ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
7114  }
7115  }
7116 
7117  compiler.add_node(NODE_NORMAL_MAP,
7118  compiler.encode_uchar4(compiler.stack_assign(color_in),
7119  compiler.stack_assign(strength_in),
7120  compiler.stack_assign(normal_out),
7121  space),
7122  attr,
7123  attr_sign);
7124 }
7125 
7126 void NormalMapNode::compile(OSLCompiler &compiler)
7127 {
7128  if (space == NODE_NORMAL_MAP_TANGENT) {
7129  if (attribute.empty()) {
7130  compiler.parameter("attr_name", ustring("geom:tangent"));
7131  compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
7132  }
7133  else {
7134  compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
7135  compiler.parameter("attr_sign_name",
7136  ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
7137  }
7138  }
7139 
7140  compiler.parameter(this, "space");
7141  compiler.add(this, "node_normal_map");
7142 }
7143 
7144 /* Tangent */
7145 
7147 {
7149 
7150  static NodeEnum direction_type_enum;
7151  direction_type_enum.insert("radial", NODE_TANGENT_RADIAL);
7152  direction_type_enum.insert("uv_map", NODE_TANGENT_UVMAP);
7153  SOCKET_ENUM(direction_type, "Direction Type", direction_type_enum, NODE_TANGENT_RADIAL);
7154 
7155  static NodeEnum axis_enum;
7156  axis_enum.insert("x", NODE_TANGENT_AXIS_X);
7157  axis_enum.insert("y", NODE_TANGENT_AXIS_Y);
7158  axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
7159  SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
7160 
7161  SOCKET_STRING(attribute, "Attribute", ustring());
7162 
7164  normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
7165  SOCKET_OUT_NORMAL(tangent, "Tangent");
7166 
7167  return type;
7168 }
7169 
7170 TangentNode::TangentNode() : ShaderNode(get_node_type())
7171 {
7172 }
7173 
7175 {
7176  if (shader->has_surface_link()) {
7177  if (direction_type == NODE_TANGENT_UVMAP) {
7178  if (attribute.empty())
7180  else
7181  attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7182  }
7183  else
7185  }
7186 
7188 }
7189 
7190 void TangentNode::compile(SVMCompiler &compiler)
7191 {
7192  ShaderOutput *tangent_out = output("Tangent");
7193  int attr;
7194 
7195  if (direction_type == NODE_TANGENT_UVMAP) {
7196  if (attribute.empty())
7197  attr = compiler.attribute(ATTR_STD_UV_TANGENT);
7198  else
7199  attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7200  }
7201  else
7202  attr = compiler.attribute(ATTR_STD_GENERATED);
7203 
7204  compiler.add_node(
7205  NODE_TANGENT,
7206  compiler.encode_uchar4(compiler.stack_assign(tangent_out), direction_type, axis),
7207  attr);
7208 }
7209 
7210 void TangentNode::compile(OSLCompiler &compiler)
7211 {
7212  if (direction_type == NODE_TANGENT_UVMAP) {
7213  if (attribute.empty())
7214  compiler.parameter("attr_name", ustring("geom:tangent"));
7215  else
7216  compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
7217  }
7218 
7219  compiler.parameter(this, "direction_type");
7220  compiler.parameter(this, "axis");
7221  compiler.add(this, "node_tangent");
7222 }
7223 
7224 /* Bevel */
7225 
7227 {
7229 
7230  SOCKET_INT(samples, "Samples", 4);
7231 
7232  SOCKET_IN_FLOAT(radius, "Radius", 0.05f);
7234 
7235  SOCKET_OUT_NORMAL(bevel, "Normal");
7236 
7237  return type;
7238 }
7239 
7240 BevelNode::BevelNode() : ShaderNode(get_node_type())
7241 {
7242 }
7243 
7244 void BevelNode::compile(SVMCompiler &compiler)
7245 {
7246  ShaderInput *radius_in = input("Radius");
7247  ShaderInput *normal_in = input("Normal");
7248  ShaderOutput *normal_out = output("Normal");
7249 
7250  compiler.add_node(NODE_BEVEL,
7251  compiler.encode_uchar4(samples,
7252  compiler.stack_assign(radius_in),
7253  compiler.stack_assign_if_linked(normal_in),
7254  compiler.stack_assign(normal_out)));
7255 }
7256 
7257 void BevelNode::compile(OSLCompiler &compiler)
7258 {
7259  compiler.parameter(this, "samples");
7260  compiler.add(this, "node_bevel");
7261 }
7262 
7263 /* Displacement */
7264 
7266 {
7267  NodeType *type = NodeType::add("displacement", create, NodeType::SHADER);
7268 
7269  static NodeEnum space_enum;
7270  space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
7271  space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
7272 
7273  SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_OBJECT);
7274 
7275  SOCKET_IN_FLOAT(height, "Height", 0.0f);
7276  SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.5f);
7277  SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
7279 
7280  SOCKET_OUT_VECTOR(displacement, "Displacement");
7281 
7282  return type;
7283 }
7284 
7285 DisplacementNode::DisplacementNode() : ShaderNode(get_node_type())
7286 {
7287 }
7288 
7290 {
7291  if (folder.all_inputs_constant()) {
7292  if ((height - midlevel == 0.0f) || (scale == 0.0f)) {
7293  folder.make_zero();
7294  }
7295  }
7296 }
7297 
7298 void DisplacementNode::compile(SVMCompiler &compiler)
7299 {
7300  ShaderInput *height_in = input("Height");
7301  ShaderInput *midlevel_in = input("Midlevel");
7302  ShaderInput *scale_in = input("Scale");
7303  ShaderInput *normal_in = input("Normal");
7304  ShaderOutput *displacement_out = output("Displacement");
7305 
7306  compiler.add_node(NODE_DISPLACEMENT,
7307  compiler.encode_uchar4(compiler.stack_assign(height_in),
7308  compiler.stack_assign(midlevel_in),
7309  compiler.stack_assign(scale_in),
7310  compiler.stack_assign_if_linked(normal_in)),
7311  compiler.stack_assign(displacement_out),
7312  space);
7313 }
7314 
7315 void DisplacementNode::compile(OSLCompiler &compiler)
7316 {
7317  compiler.parameter(this, "space");
7318  compiler.add(this, "node_displacement");
7319 }
7320 
7321 /* Vector Displacement */
7322 
7324 {
7325  NodeType *type = NodeType::add("vector_displacement", create, NodeType::SHADER);
7326 
7327  static NodeEnum space_enum;
7328  space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
7329  space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
7330  space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
7331 
7332  SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
7333  SOCKET_STRING(attribute, "Attribute", ustring());
7334 
7335  SOCKET_IN_COLOR(vector, "Vector", zero_float3());
7336  SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
7337  SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
7338 
7339  SOCKET_OUT_VECTOR(displacement, "Displacement");
7340 
7341  return type;
7342 }
7343 
7344 VectorDisplacementNode::VectorDisplacementNode() : ShaderNode(get_node_type())
7345 {
7346 }
7347 
7349 {
7350  if (folder.all_inputs_constant()) {
7351  if ((vector == zero_float3() && midlevel == 0.0f) || (scale == 0.0f)) {
7352  folder.make_zero();
7353  }
7354  }
7355 }
7356 
7358 {
7359  if (shader->has_surface_link() && space == NODE_NORMAL_MAP_TANGENT) {
7360  if (attribute.empty()) {
7363  }
7364  else {
7365  attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7366  attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
7367  }
7368  }
7369 
7371 }
7372 
7374 {
7375  ShaderInput *vector_in = input("Vector");
7376  ShaderInput *midlevel_in = input("Midlevel");
7377  ShaderInput *scale_in = input("Scale");
7378  ShaderOutput *displacement_out = output("Displacement");
7379  int attr = 0, attr_sign = 0;
7380 
7381  if (space == NODE_NORMAL_MAP_TANGENT) {
7382  if (attribute.empty()) {
7383  attr = compiler.attribute(ATTR_STD_UV_TANGENT);
7384  attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
7385  }
7386  else {
7387  attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
7388  attr_sign = compiler.attribute(
7389  ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
7390  }
7391  }
7392 
7393  compiler.add_node(NODE_VECTOR_DISPLACEMENT,
7394  compiler.encode_uchar4(compiler.stack_assign(vector_in),
7395  compiler.stack_assign(midlevel_in),
7396  compiler.stack_assign(scale_in),
7397  compiler.stack_assign(displacement_out)),
7398  attr,
7399  attr_sign);
7400 
7401  compiler.add_node(space);
7402 }
7403 
7405 {
7406  if (space == NODE_NORMAL_MAP_TANGENT) {
7407  if (attribute.empty()) {
7408  compiler.parameter("attr_name", ustring("geom:tangent"));
7409  compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
7410  }
7411  else {
7412  compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
7413  compiler.parameter("attr_sign_name",
7414  ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
7415  }
7416  }
7417 
7418  compiler.parameter(this, "space");
7419  compiler.add(this, "node_vector_displacement");
7420 }
7421 
typedef float(TangentPoint)[2]
KDTree *BLI_kdtree_nd_() new(unsigned int maxsize)
Definition: kdtree_impl.h:85
MINLINE float signf(float f)
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
Definition: math_color.c:208
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:13
unsigned int uint
Definition: BLI_sys_types.h:67
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
@ NODE_VECTOR_MATH_NORMALIZE
@ NODE_VECTOR_MATH_LENGTH
@ 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_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_MAP_RANGE_STEPPED
@ NODE_MAP_RANGE_SMOOTHERSTEP
@ NODE_MAP_RANGE_SMOOTHSTEP
@ NODE_MAP_RANGE_LINEAR
@ 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_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_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_CLAMP_RANGE
@ NODE_CLAMP_MINMAX
@ NODE_COMBSEP_COLOR_RGB
@ NODE_COMBSEP_COLOR_HSV
@ NODE_COMBSEP_COLOR_HSL
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model Specular Similar to the Principled BSDF node but uses the specular workflow instead of which functions by specifying the facing(along normal) reflection color. Energy is not conserved
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model Specular Similar to the Principled BSDF node but uses the specular workflow instead of metallic
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its hue
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its saturation
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model Specular BSDF
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
void constant_fold(const ConstantFolder &folder)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void attributes(Shader *shader, AttributeRequestSet *attributes)
static AttributeStandard name_standard(const char *name)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
virtual bool has_bump()
ClosureType closure
Definition: shader_nodes.h:477
BsdfBaseNode(const NodeType *node_type)
BsdfNode(const NodeType *node_type)
void compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3=NULL, ShaderInput *param4=NULL)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
static bool colorspace_is_data(ustring colorspace)
Definition: colorspace.cpp:72
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void make_one() const
void make_constant_clamp(float value, bool clamp) 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
Definition: constant_fold.h:20
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(float value) const
ShaderOutput *const output
Definition: constant_fold.h:22
void fold_mix(NodeMix type, bool clamp) const
void fold_vector_math(NodeVectorMathType type) const
void constant_fold(const ConstantFolder &folder)
float value_float
Definition: shader_nodes.h:435
float3 value_vector
Definition: shader_nodes.h:438
ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert=false)
float3 value_color
Definition: shader_nodes.h:437
CurvesNode(const NodeType *node_type)
virtual void constant_fold(const ConstantFolder &)
Definition: shader_graph.h:169
void compile(SVMCompiler &compiler, int type, ShaderInput *value_in, ShaderOutput *value_out)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
ImageParams image_params() const
ShaderNode * clone(ShaderGraph *graph) const
void attributes(Shader *shader, AttributeRequestSet *attributes)
int get_aov_offset(Scene *scene, string name, bool &is_color)
Definition: film.cpp:415
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void attributes(Shader *shader, AttributeRequestSet *attributes)
virtual void get_uv_tiles(ustring map, unordered_set< int > &tiles)=0
void simplify_settings(Scene *scene)
bool has_integrator_dependency()
bool has_integrator_dependency()
void simplify_settings(Scene *scene)
void attributes(Shader *shader, AttributeRequestSet *attributes)
ShaderNode * clone(ShaderGraph *graph) const
int num_tiles() const
bool empty() const
ImageMetaData metadata()
int svm_slot(const int tile_index=0) const
ImageHandle add_image(const string &filename, const ImageParams &params)
bool is_float() const
InterpolationType interpolation
ExtensionType extension
ImageHandle handle
Definition: shader_nodes.h:87
ImageParams image_params() const
void attributes(Shader *shader, AttributeRequestSet *attributes)
void cull_tiles(Scene *scene, ShaderGraph *graph)
ShaderNode * clone(ShaderGraph *graph) const
void constant_fold(const ConstantFolder &folder)
int add_ies(const string &ies)
int add_ies_from_file(const string &filename)
void remove_ies(int slot)
void expand(ShaderGraph *graph)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void expand(ShaderGraph *graph)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void add(ShaderNode *node, const char *name, bool isfilepath=false)
Definition: osl.cpp:1236
void parameter_array(const char *name, const float f[], int arraylen)
Definition: osl.cpp:1280
void parameter_texture_ies(const char *name, int svm_slot)
Definition: osl.cpp:1298
ShaderType output_type()
Definition: osl.h:153
void parameter_texture(const char *name, ustring filename, ustring colorspace)
Definition: osl.cpp:1288
void parameter(ShaderNode *node, const char *name)
Definition: osl.cpp:1240
bool background
Definition: osl.h:158
void parameter_color_array(const char *name, const array< float3 > &f)
Definition: osl.cpp:1284
Scene * scene
Definition: osl.h:159
void parameter_color(const char *name, float3 f)
Definition: osl.cpp:1248
string bytecode_hash
static OSLNode * create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from=NULL)
ShaderNode * clone(ShaderGraph *graph) const
void add_output(ustring name, SocketType::Type type)
char * input_default_value()
string filepath
void add_input(ustring name, SocketType::Type type)
virtual void simplify_settings(Scene *scene)
void attributes(Shader *shader, AttributeRequestSet *attributes)
ImageParams image_params() const
ShaderNode * clone(ShaderGraph *graph) const
void attributes(Shader *shader, AttributeRequestSet *attributes)
void attributes(Shader *shader, AttributeRequestSet *attributes)
bool has_integrator_dependency()
void expand(ShaderGraph *graph)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void compile(SVMCompiler &compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius, ShaderInput *subsurface_ior, ShaderInput *subsurface_anisotropy, ShaderInput *specular, ShaderInput *roughness, ShaderInput *specular_tint, ShaderInput *anisotropic, ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_roughness, ShaderInput *ior, ShaderInput *transmission, ShaderInput *anisotropic_rotation, ShaderInput *transmission_roughness)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
bool has_integrator_dependency()
void simplify_settings(Scene *scene)
ShaderGraph * current_graph
Definition: scene/svm.h:115
void add_node(ShaderNodeType type, int a=0, int b=0, int c=0)
Definition: svm.cpp:380
bool background
Definition: scene/svm.h:116
void stack_clear_offset(SocketType::Type type, int offset)
Definition: svm.cpp:239
int stack_assign_if_linked(ShaderInput *input)
Definition: svm.cpp:293
uint encode_uchar4(uint x, uint y=0, uint z=0, uint w=0)
Definition: svm.cpp:365
uint attribute_standard(ustring name)
Definition: svm.cpp:409
void stack_link(ShaderInput *input, ShaderOutput *output)
Definition: svm.cpp:309
ShaderType output_type()
Definition: scene/svm.h:109
uint closure_mix_weight_offset()
Definition: scene/svm.h:104
uint attribute(ustring name)
Definition: svm.cpp:399
Scene * scene
Definition: scene/svm.h:114
int stack_find_offset(int size)
Definition: svm.cpp:202
int stack_assign(ShaderOutput *output)
Definition: svm.cpp:284
bool background
Definition: scene.h:157
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
T * create_node(Args &&...args)
Definition: shader_graph.h:333
ShaderNode * add(ShaderNode *node)
ShaderOutput * link
Definition: shader_graph.h:103
void disconnect()
SocketType::Type type()
Definition: shader_graph.h:85
const SocketType & socket_type
Definition: shader_graph.h:101
float linear_rgb_to_gray(float3 c)
float3 rec709_to_scene_linear(float3 c)
ShaderInput * input(const char *name)
vector< ShaderOutput * > outputs
Definition: shader_graph.h:215
void remove_input(ShaderInput *input)
ShaderNodeSpecialType special_type
Definition: shader_graph.h:220
vector< ShaderInput * > inputs
Definition: shader_graph.h:214
ShaderBump bump
Definition: shader_graph.h:218
ShaderOutput * output(const char *name)
virtual void compile(SVMCompiler &compiler)=0
virtual void attributes(Shader *shader, AttributeRequestSet *attributes)
vector< ShaderInput * > links
Definition: shader_graph.h:135
ShaderNode * parent
Definition: shader_graph.h:134
bool has_surface_link() const
Definition: scene/shader.h:147
bool has_volume
Definition: scene/shader.h:107
bool has_surface
Definition: scene/shader.h:103
NODE_DECLARE ShaderGraph * graph
Definition: scene/shader.h:71
float get_sun_size()
Definition: shader_nodes.h:172
ImageHandle handle
Definition: shader_nodes.h:170
void attributes(Shader *shader, AttributeRequestSet *attributes)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void compile_end(SVMCompiler &compiler, ShaderInput *vector_in, int vector_offset)
Transform compute_transform()
Mapping x_mapping
Definition: shader_nodes.h:46
Mapping z_mapping
Definition: shader_nodes.h:46
void compile(SVMCompiler &compiler, int offset_in, int offset_out)
Mapping y_mapping
Definition: shader_nodes.h:46
int compile_begin(SVMCompiler &compiler, ShaderInput *vector_in)
float3 translation
Definition: shader_nodes.h:35
TextureMapping tex_mapping
Definition: shader_nodes.h:59
void attributes(Shader *shader, AttributeRequestSet *attributes)
void constant_fold(const ConstantFolder &folder)
void constant_fold(const ConstantFolder &folder)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void expand(ShaderGraph *graph)
void constant_fold(const ConstantFolder &folder)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void expand(ShaderGraph *graph)
void attributes(Shader *shader, AttributeRequestSet *attributes)
void compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2)
ClosureType closure
Definition: shader_nodes.h:799
VolumeNode(const NodeType *node_type)
void push_back_slow(const T &t)
ccl_device_noinline_cpu float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2)
Definition: color_util.h:250
ccl_device float3 svm_combine_color(NodeCombSepColorType type, float3 color)
Definition: color_util.h:310
ccl_device float3 svm_separate_color(NodeCombSepColorType type, float3 color)
Definition: color_util.h:323
ccl_device_inline float3 svm_brightness_contrast(float3 color, float brightness, float contrast)
Definition: color_util.h:298
CCL_NAMESPACE_BEGIN ustring u_colorspace_auto
Definition: colorspace.cpp:22
ustring u_colorspace_raw
#define cosf(x)
Definition: cuda/compat.h:101
#define expf(x)
Definition: cuda/compat.h:106
#define tanf(x)
Definition: cuda/compat.h:104
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
OperationNode * node
Depsgraph * graph
StackEntry * from
Scene scene
Curve curve
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
struct @211::@212 surface
IMETHOD void random(Vector &a)
addDelta operator for displacement rotational velocity.
Definition: frames.inl:1282
uint pos
uint col
#define mix(a, b, c)
Definition: hash.h:17
IconTextureDrawCall normal
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline Transform transform_identity()
ccl_device_inline Transform transform_euler(float3 euler)
ccl_device_inline Transform transform_translate(float3 t)
ccl_device_inline Transform transform_inverse(const Transform tfm)
ccl_device_inline Transform transform_scale(float3 s)
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition: invert.h:8
ccl_global float * color_out
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
ccl_global const KernelWorkTile * tile
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
@ 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
@ NODE_MUSGRAVE_MULTIFRACTAL
@ NODE_MUSGRAVE_RIDGED_MULTIFRACTAL
@ NODE_MUSGRAVE_HYBRID_MULTIFRACTAL
@ NODE_MUSGRAVE_HETERO_TERRAIN
@ NODE_MUSGRAVE_FBM
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
NodeMappingType
@ NODE_INFO_CURVE_IS_STRAND
@ NODE_INFO_CURVE_TANGENT_NORMAL
@ NODE_INFO_CURVE_THICKNESS
@ 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_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_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_INFO_PAR_ROTATION
@ 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_LIGHT
@ NODE_MIX_MUL
@ NODE_MIX_DIFF
@ NODE_MIX_BURN
@ NODE_MIX_SUB
@ NODE_MIX_LINEAR
@ NODE_MIX_DARK
@ NODE_MIX_SAT
@ NODE_MIX_COLOR
@ 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
#define SVM_STACK_INVALID
@ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID
@ CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID
@ CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID
@ CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID
@ CLOSURE_BSDF_HAIR_PRINCIPLED_ID
@ CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID
@ CLOSURE_BSDF_DIFFUSE_ID
@ CLOSURE_BSSRDF_BURLEY_ID
@ CLOSURE_BSDF_PRINCIPLED_ID
@ CLOSURE_BSDF_TRANSPARENT_ID
@ CLOSURE_BSDF_DIFFUSE_TOON_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_SHARP_GLASS_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID
@ CLOSURE_BSSRDF_RANDOM_WALK_ID
@ CLOSURE_BSDF_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID
@ NBUILTIN_CLOSURES
@ CLOSURE_BSDF_GLOSSY_TOON_ID
@ CLOSURE_VOLUME_ABSORPTION_ID
@ CLOSURE_BSDF_HAIR_REFLECTION_ID
@ CLOSURE_BSDF_TRANSLUCENT_ID
@ CLOSURE_BSDF_REFLECTION_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
#define CLOSURE_WEIGHT_CUTOFF
@ 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
Definition: kernel/types.h:627
@ ATTR_STD_GENERATED_TRANSFORM
Definition: kernel/types.h:621
@ ATTR_STD_UV
Definition: kernel/types.h:616
@ ATTR_STD_VOLUME_TEMPERATURE
Definition: kernel/types.h:637
@ ATTR_STD_UV_TANGENT
Definition: kernel/types.h:617
@ ATTR_STD_NONE
Definition: kernel/types.h:613
@ ATTR_STD_POINT_RANDOM
Definition: kernel/types.h:630
@ ATTR_STD_VERTEX_COLOR
Definition: kernel/types.h:619
@ ATTR_STD_VOLUME_DENSITY
Definition: kernel/types.h:633
@ ATTR_STD_VOLUME_FLAME
Definition: kernel/types.h:635
@ ATTR_STD_PTEX_FACE_ID
Definition: kernel/types.h:631
@ ATTR_STD_VOLUME_COLOR
Definition: kernel/types.h:634
@ ATTR_STD_UV_TANGENT_SIGN
Definition: kernel/types.h:618
@ ATTR_STD_CURVE_RANDOM
Definition: kernel/types.h:629
@ ATTR_STD_PTEX_UV
Definition: kernel/types.h:632
@ ATTR_STD_POINTINESS
Definition: kernel/types.h:642
@ ATTR_STD_GENERATED
Definition: kernel/types.h:620
@ ATTR_STD_CURVE_LENGTH
Definition: kernel/types.h:628
@ ATTR_STD_RANDOM_PER_ISLAND
Definition: kernel/types.h:643
@ ATTR_STD_PARTICLE
Definition: kernel/types.h:626
#define VLOG_DEBUG
Definition: log.h:86
static char ** types
Definition: makesdna.c:67
CCL_NAMESPACE_BEGIN ccl_device float3 svm_mapping(NodeMappingType type, float3 vector, float3 location, float3 rotation, float3 scale)
Definition: mapping_util.h:9
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
Definition: math_float2.h:232
ccl_device_inline float average(const float2 &a)
Definition: math_float2.h:170
ccl_device_inline float3 one_float3()
Definition: math_float3.h:89
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
CCL_NAMESPACE_BEGIN ccl_device void svm_vector_math(ccl_private float *value, ccl_private float3 *vector, NodeVectorMathType type, float3 a, float3 b, float3 c, float param1)
Definition: math_util.h:8
ccl_device float svm_math(NodeMathType type, float a, float b, float c)
Definition: math_util.h:104
ccl_device float3 svm_math_blackbody_color_rec709(float t)
Definition: math_util.h:192
ccl_device_inline float3 svm_math_gamma_color(float3 color, float gamma)
Definition: math_util.h:226
#define T
#define T2
Definition: md5.cpp:18
#define atan2f(x, y)
Definition: metal/compat.h:227
#define make_float2(x, y)
Definition: metal/compat.h:203
#define fmodf(x, y)
Definition: metal/compat.h:230
#define acosf(x)
Definition: metal/compat.h:222
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define fabsf(x)
Definition: metal/compat.h:219
#define make_float3(x, y, z)
Definition: metal/compat.h:204
bool add(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
void interpolate(const Span< T > src, const Span< int > indices, const Span< float > factors, MutableSpan< T > dst)
T clamp(const T &a, const T &min, const T &max)
T distance(const T &a, const T &b)
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static const pxr::TfToken clearcoat("clearcoat", pxr::TfToken::Immortal)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken ior("ior", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal)
static const pxr::TfToken specular("specular", pxr::TfToken::Immortal)
static const pxr::TfToken rgb("rgb", pxr::TfToken::Immortal)
color rgb_ramp_lookup(color ramp[], float at, int interpolate, int extrapolate)
Definition: node_ramp_util.h:6
#define SOCKET_IN_NORMAL(name, ui_name, default_value,...)
Definition: node_type.h:325
#define SOCKET_OUT_POINT(name, ui_name)
Definition: node_type.h:372
#define SOCKET_OUT_FLOAT(name, ui_name)
Definition: node_type.h:360
#define SOCKET_OUT_COLOR(name, ui_name)
Definition: node_type.h:364
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition: node_type.h:191
#define SOCKET_INT(name, ui_name, default_value,...)
Definition: node_type.h:187
#define SOCKET_IN_COLOR(name, ui_name, default_value,...)
Definition: node_type.h:301
#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value,...)
Definition: node_type.h:239
#define SOCKET_TRANSFORM(name, ui_name, default_value,...)
Definition: node_type.h:205
#define SOCKET_OUT_NORMAL(name, ui_name)
Definition: node_type.h:376
#define SOCKET_IN_FLOAT(name, ui_name, default_value,...)
Definition: node_type.h:293
#define SOCKET_IN_CLOSURE(name, ui_name,...)
Definition: node_type.h:341
#define SOCKET_OFFSETOF(T, name)
Definition: node_type.h:168
#define SOCKET_INT_ARRAY(name, ui_name, default_value,...)
Definition: node_type.h:237
#define SOCKET_VECTOR_ARRAY(name, ui_name, default_value,...)
Definition: node_type.h:245
#define SOCKET_IN_VECTOR(name, ui_name, default_value,...)
Definition: node_type.h:309
#define SOCKET_VECTOR(name, ui_name, default_value,...)
Definition: node_type.h:195
#define SOCKET_IN_POINT(name, ui_name, default_value,...)
Definition: node_type.h:317
#define SOCKET_COLOR_ARRAY(name, ui_name, default_value,...)
Definition: node_type.h:242
#define SOCKET_COLOR(name, ui_name, default_value,...)
Definition: node_type.h:193
#define SOCKET_OUT_VECTOR(name, ui_name)
Definition: node_type.h:368
#define SOCKET_IN_STRING(name, ui_name, default_value,...)
Definition: node_type.h:333
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition: node_type.h:185
#define SOCKET_IN_BOOLEAN(name, ui_name, default_value,...)
Definition: node_type.h:282
#define SOCKET_STRING(name, ui_name, default_value,...)
Definition: node_type.h:203
#define SOCKET_ENUM(name, ui_name, values, default_value,...)
Definition: node_type.h:207
#define SOCKET_OUT_CLOSURE(name, ui_name)
Definition: node_type.h:380
smooth(Type::FLOAT, "mask_weight")
ccl_device_inline float float_ramp_lookup(KernelGlobals kg, int offset, float f, bool interpolate, bool extrapolate, int table_size)
Definition: ramp.h:16
@ SHADER_SPECIAL_TYPE_PROXY
Definition: shader_graph.h:48
@ SHADER_SPECIAL_TYPE_GEOMETRY
Definition: shader_graph.h:50
@ SHADER_SPECIAL_TYPE_OUTPUT_AOV
Definition: shader_graph.h:57
@ SHADER_SPECIAL_TYPE_COMBINE_CLOSURE
Definition: shader_graph.h:54
@ SHADER_SPECIAL_TYPE_BUMP
Definition: shader_graph.h:56
@ SHADER_SPECIAL_TYPE_AUTOCONVERT
Definition: shader_graph.h:49
@ SHADER_SPECIAL_TYPE_OUTPUT
Definition: shader_graph.h:55
@ SHADER_SPECIAL_TYPE_CLOSURE
Definition: shader_graph.h:53
@ SHADER_SPECIAL_TYPE_OSL
Definition: shader_graph.h:51
@ SHADER_BUMP_DX
Definition: shader_graph.h:39
@ SHADER_BUMP_DY
Definition: shader_graph.h:39
static void sky_texture_precompute_hosek(SunSky *sunsky, float3 dir, float turbidity, float ground_albedo)
struct SunSky SunSky
NODE_DEFINE(ImageTextureNode)
static float2 sky_spherical_coordinates(float3 dir)
static float sky_perez_function(float lam[6], float theta, float gamma)
#define TEXTURE_MAPPING_DEFINE(TextureNode)
static void sky_texture_precompute_preetham(SunSky *sunsky, float3 dir, float turbidity)
static void sky_texture_precompute_nishita(SunSky *sunsky, bool sun_disc, float sun_size, float sun_intensity, float sun_elevation, float sun_rotation, float altitude, float air_density, float dust_density)
void SKY_arhosekskymodelstate_free(SKY_ArHosekSkyModelState *state)
Definition: sky_model.cpp:267
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)
SKY_ArHosekSkyModelState * SKY_arhosek_xyz_skymodelstate_alloc_init(const double turbidity, const double albedo, const double elevation)
Definition: sky_model.cpp:305
static const int steps
Definition: sky_nishita.cpp:19
#define min(a, b)
Definition: sort.c:35
static std::string value_string(const SpreadsheetRowFilter &row_filter, const eSpreadsheetColumnValueType data_type)
bool string_endswith(const string_view s, const string_view end)
Definition: string.cpp:111
float size[3]
void insert(const char *x, int y)
Definition: node_enum.h:20
vector< SocketType, std::allocator< SocketType > > inputs
Definition: node_type.h:118
@ SHADER
Definition: node_type.h:94
void register_output(ustring name, ustring ui_name, SocketType::Type type)
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
vector< SocketType, std::allocator< SocketType > > outputs
Definition: node_type.h:119
void register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset, const void *default_value, const NodeEnum *enum_values=NULL, const NodeType *node_type=NULL, int flags=0, int extra_flags=0)
float get_float(const SocketType &input) const
Definition: graph/node.cpp:197
const NodeType * type
Definition: graph/node.h:175
float3 get_float3(const SocketType &input) const
Definition: graph/node.cpp:209
ustring name
Definition: graph/node.h:174
SKY_ArHosekSkyModelConfiguration configs[11]
Definition: sky_model.h:316
Film * film
Definition: scene.h:208
vector< Geometry * > geometry
Definition: scene.h:214
SceneParams params
Definition: scene.h:243
ImageManager * image_manager
Definition: scene.h:222
ShaderManager * shader_manager
Definition: scene.h:224
Integrator * integrator
Definition: scene.h:210
LightManager * light_manager
Definition: scene.h:223
static size_t max_size()
Definition: node_type.cpp:85
static bool is_float3(Type type)
Definition: node_type.cpp:118
static ustring type_name(Type type)
Definition: node_type.cpp:96
static void * zero_default_value()
Definition: node_type.cpp:90
@ LINK_TEXTURE_UV
Definition: node_type.h:64
@ SVM_INTERNAL
Definition: node_type.h:58
@ LINK_NORMAL
Definition: node_type.h:66
@ LINK_TEXTURE_GENERATED
Definition: node_type.h:62
@ OSL_INTERNAL
Definition: node_type.h:59
@ LINK_TANGENT
Definition: node_type.h:68
@ LINK_TEXTURE_NORMAL
Definition: node_type.h:63
@ LINK_POSITION
Definition: node_type.h:67
float phi
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
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float z
float y
float x
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
Transform transform_transposed_inverse(const Transform &tfm)
Definition: transform.cpp:110
float max
ccl_device_inline uint __float_as_uint(float f)
Definition: util/math.h:263
ccl_device_inline int __float_as_int(float f)
Definition: util/math.h:243
#define M_PI_2_F
Definition: util/math.h:37
#define M_2PI_F
Definition: util/math.h:60
ccl_device_inline float4 float3_to_float4(const float3 a)
Definition: util/math.h:505
#define M_PI_F
Definition: util/math.h:34
@ IMAGE_ALPHA_ASSOCIATED
Definition: util/texture.h:50
@ IMAGE_ALPHA_CHANNEL_PACKED
Definition: util/texture.h:51
@ IMAGE_ALPHA_AUTO
Definition: util/texture.h:53
@ IMAGE_ALPHA_IGNORE
Definition: util/texture.h:52
@ IMAGE_ALPHA_UNASSOCIATED
Definition: util/texture.h:49
#define TEX_IMAGE_MISSING_R
Definition: util/texture.h:12
#define TEX_IMAGE_MISSING_B
Definition: util/texture.h:14
@ INTERPOLATION_LINEAR
Definition: util/texture.h:21
@ INTERPOLATION_SMART
Definition: util/texture.h:24
@ INTERPOLATION_CLOSEST
Definition: util/texture.h:22
@ INTERPOLATION_CUBIC
Definition: util/texture.h:23
@ EXTENSION_REPEAT
Definition: util/texture.h:63
@ EXTENSION_CLIP
Definition: util/texture.h:67
@ EXTENSION_EXTEND
Definition: util/texture.h:65
#define TEX_IMAGE_MISSING_G
Definition: util/texture.h:13
ccl_device_inline size_t align_up(size_t offset, size_t alignment)
Definition: util/types.h:46
ccl_device_inline size_t divide_up(size_t x, size_t y)
Definition: util/types.h:51