Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/scene/shader_nodes.h')
-rw-r--r--intern/cycles/scene/shader_nodes.h1569
1 files changed, 1569 insertions, 0 deletions
diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h
new file mode 100644
index 00000000000..64a2b1c7843
--- /dev/null
+++ b/intern/cycles/scene/shader_nodes.h
@@ -0,0 +1,1569 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NODES_H__
+#define __NODES_H__
+
+#include "graph/node.h"
+#include "scene/image.h"
+#include "scene/shader_graph.h"
+
+#include "util/array.h"
+#include "util/string.h"
+
+CCL_NAMESPACE_BEGIN
+
+class ImageManager;
+class LightManager;
+class Scene;
+class Shader;
+
+/* Texture Mapping */
+
+class TextureMapping {
+ public:
+ TextureMapping();
+ Transform compute_transform();
+ bool skip();
+ void compile(SVMCompiler &compiler, int offset_in, int offset_out);
+ int compile(SVMCompiler &compiler, ShaderInput *vector_in);
+ void compile(OSLCompiler &compiler);
+
+ int compile_begin(SVMCompiler &compiler, ShaderInput *vector_in);
+ void compile_end(SVMCompiler &compiler, ShaderInput *vector_in, int vector_offset);
+
+ float3 translation;
+ float3 rotation;
+ float3 scale;
+
+ float3 min, max;
+ bool use_minmax;
+
+ enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 };
+ Type type;
+
+ enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
+ Mapping x_mapping, y_mapping, z_mapping;
+
+ enum Projection { FLAT, CUBE, TUBE, SPHERE };
+ Projection projection;
+};
+
+/* Nodes */
+
+class TextureNode : public ShaderNode {
+ public:
+ explicit TextureNode(const NodeType *node_type) : ShaderNode(node_type)
+ {
+ }
+ TextureMapping tex_mapping;
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, translation)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, rotation)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, scale)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, min)
+ NODE_SOCKET_API_STRUCT_MEMBER(float3, tex_mapping, max)
+ NODE_SOCKET_API_STRUCT_MEMBER(bool, tex_mapping, use_minmax)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Type, tex_mapping, type)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, x_mapping)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, y_mapping)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Mapping, tex_mapping, z_mapping)
+ NODE_SOCKET_API_STRUCT_MEMBER(TextureMapping::Projection, tex_mapping, projection)
+};
+
+/* Any node which uses image manager's slot should be a subclass of this one. */
+class ImageSlotTextureNode : public TextureNode {
+ public:
+ explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type)
+ {
+ special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
+ }
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const ImageSlotTextureNode &other_node = (const ImageSlotTextureNode &)other;
+ return TextureNode::equals(other) && handle == other_node.handle;
+ }
+
+ ImageHandle handle;
+};
+
+class ImageTextureNode : public ImageSlotTextureNode {
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
+ ShaderNode *clone(ShaderGraph *graph) const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const ImageTextureNode &other_node = (const ImageTextureNode &)other;
+ return ImageSlotTextureNode::equals(other) && animated == other_node.animated;
+ }
+
+ ImageParams image_params() const;
+
+ /* Parameters. */
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(ustring, colorspace)
+ NODE_SOCKET_API(ImageAlphaType, alpha_type)
+ NODE_SOCKET_API(NodeImageProjection, projection)
+ NODE_SOCKET_API(InterpolationType, interpolation)
+ NODE_SOCKET_API(ExtensionType, extension)
+ NODE_SOCKET_API(float, projection_blend)
+ NODE_SOCKET_API(bool, animated)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API_ARRAY(array<int>, tiles)
+
+ protected:
+ void cull_tiles(Scene *scene, ShaderGraph *graph);
+};
+
+class EnvironmentTextureNode : public ImageSlotTextureNode {
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
+ ShaderNode *clone(ShaderGraph *graph) const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const EnvironmentTextureNode &other_node = (const EnvironmentTextureNode &)other;
+ return ImageSlotTextureNode::equals(other) && animated == other_node.animated;
+ }
+
+ ImageParams image_params() const;
+
+ /* Parameters. */
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(ustring, colorspace)
+ NODE_SOCKET_API(ImageAlphaType, alpha_type)
+ NODE_SOCKET_API(NodeEnvironmentProjection, projection)
+ NODE_SOCKET_API(InterpolationType, interpolation)
+ NODE_SOCKET_API(bool, animated)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class SkyTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(SkyTextureNode)
+
+ NODE_SOCKET_API(NodeSkyType, sky_type)
+ NODE_SOCKET_API(float3, sun_direction)
+ NODE_SOCKET_API(float, turbidity)
+ NODE_SOCKET_API(float, ground_albedo)
+ NODE_SOCKET_API(bool, sun_disc)
+ NODE_SOCKET_API(float, sun_size)
+ NODE_SOCKET_API(float, sun_intensity)
+ NODE_SOCKET_API(float, sun_elevation)
+ NODE_SOCKET_API(float, sun_rotation)
+ NODE_SOCKET_API(float, altitude)
+ NODE_SOCKET_API(float, air_density)
+ NODE_SOCKET_API(float, dust_density)
+ NODE_SOCKET_API(float, ozone_density)
+ NODE_SOCKET_API(float3, vector)
+ ImageHandle handle;
+
+ float get_sun_size()
+ {
+ /* Clamping for numerical precision. */
+ return fmaxf(sun_size, 0.0005f);
+ }
+};
+
+class OutputNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(OutputNode)
+
+ NODE_SOCKET_API(Node *, surface)
+ NODE_SOCKET_API(Node *, volume)
+ NODE_SOCKET_API(float3, displacement)
+ NODE_SOCKET_API(float3, normal)
+
+ /* Don't allow output node de-duplication. */
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ return false;
+ }
+};
+
+class OutputAOVNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(OutputAOVNode)
+ virtual void simplify_settings(Scene *scene);
+
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float3, color)
+
+ NODE_SOCKET_API(ustring, name)
+
+ /* Don't allow output node de-duplication. */
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ return false;
+ }
+
+ int offset;
+ bool is_color;
+};
+
+class GradientTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(GradientTextureNode)
+
+ NODE_SOCKET_API(NodeGradientType, gradient_type)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class NoiseTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(NoiseTextureNode)
+
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(float, w)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, detail)
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, distortion)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class VoronoiTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(VoronoiTextureNode)
+
+ virtual int get_feature()
+ {
+ int result = ShaderNode::get_feature();
+ if (dimensions == 4) {
+ result |= KERNEL_FEATURE_NODE_VORONOI_EXTRA;
+ }
+ else if (dimensions >= 2 && feature == NODE_VORONOI_SMOOTH_F1) {
+ result |= KERNEL_FEATURE_NODE_VORONOI_EXTRA;
+ }
+ return result;
+ }
+
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(NodeVoronoiDistanceMetric, metric)
+ NODE_SOCKET_API(NodeVoronoiFeature, feature)
+ NODE_SOCKET_API(float, w)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, exponent)
+ NODE_SOCKET_API(float, smoothness)
+ NODE_SOCKET_API(float, randomness)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class MusgraveTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(MusgraveTextureNode)
+
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(NodeMusgraveType, musgrave_type)
+ NODE_SOCKET_API(float, w)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, detail)
+ NODE_SOCKET_API(float, dimension)
+ NODE_SOCKET_API(float, lacunarity)
+ NODE_SOCKET_API(float, offset)
+ NODE_SOCKET_API(float, gain)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class WaveTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(WaveTextureNode)
+
+ NODE_SOCKET_API(NodeWaveType, wave_type)
+ NODE_SOCKET_API(NodeWaveBandsDirection, bands_direction)
+ NODE_SOCKET_API(NodeWaveRingsDirection, rings_direction)
+ NODE_SOCKET_API(NodeWaveProfile, profile)
+
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, distortion)
+ NODE_SOCKET_API(float, detail)
+ NODE_SOCKET_API(float, detail_scale)
+ NODE_SOCKET_API(float, detail_roughness)
+ NODE_SOCKET_API(float, phase)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class MagicTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(MagicTextureNode)
+
+ NODE_SOCKET_API(int, depth)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, distortion)
+};
+
+class CheckerTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(CheckerTextureNode)
+
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float3, color1)
+ NODE_SOCKET_API(float3, color2)
+ NODE_SOCKET_API(float, scale)
+};
+
+class BrickTextureNode : public TextureNode {
+ public:
+ SHADER_NODE_CLASS(BrickTextureNode)
+
+ NODE_SOCKET_API(float, offset)
+ NODE_SOCKET_API(float, squash)
+ NODE_SOCKET_API(int, offset_frequency)
+ NODE_SOCKET_API(int, squash_frequency)
+
+ NODE_SOCKET_API(float3, color1)
+ NODE_SOCKET_API(float3, color2)
+ NODE_SOCKET_API(float3, mortar)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float, mortar_size)
+ NODE_SOCKET_API(float, mortar_smooth)
+ NODE_SOCKET_API(float, bias)
+ NODE_SOCKET_API(float, brick_width)
+ NODE_SOCKET_API(float, row_height)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class PointDensityTextureNode : public ShaderNode {
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
+
+ ~PointDensityTextureNode();
+ ShaderNode *clone(ShaderGraph *graph) const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ /* Parameters. */
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(NodeTexVoxelSpace, space)
+ NODE_SOCKET_API(InterpolationType, interpolation)
+ NODE_SOCKET_API(Transform, tfm)
+ NODE_SOCKET_API(float3, vector)
+
+ /* Runtime. */
+ ImageHandle handle;
+
+ ImageParams image_params() const;
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const PointDensityTextureNode &other_node = (const PointDensityTextureNode &)other;
+ return ShaderNode::equals(other) && handle == other_node.handle;
+ }
+};
+
+class IESLightNode : public TextureNode {
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
+
+ ~IESLightNode();
+ ShaderNode *clone(ShaderGraph *graph) const;
+
+ NODE_SOCKET_API(ustring, filename)
+ NODE_SOCKET_API(ustring, ies)
+
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float3, vector)
+
+ private:
+ LightManager *light_manager;
+ int slot;
+
+ void get_slot();
+};
+
+class WhiteNoiseTextureNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(WhiteNoiseTextureNode)
+
+ NODE_SOCKET_API(int, dimensions)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float, w)
+};
+
+class MappingNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(MappingNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float3, location)
+ NODE_SOCKET_API(float3, rotation)
+ NODE_SOCKET_API(float3, scale)
+ NODE_SOCKET_API(NodeMappingType, mapping_type)
+};
+
+class RGBToBWNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(RGBToBWNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, color)
+};
+
+class ConvertNode : public ShaderNode {
+ public:
+ ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
+ ConvertNode(const ConvertNode &other);
+ SHADER_NODE_BASE_CLASS(ConvertNode)
+
+ void constant_fold(const ConstantFolder &folder);
+
+ private:
+ SocketType::Type from, to;
+
+ union {
+ float value_float;
+ int value_int;
+ float3 value_color;
+ float3 value_vector;
+ float3 value_point;
+ float3 value_normal;
+ };
+ ustring value_string;
+
+ static const int MAX_TYPE = 12;
+ static bool register_types();
+ static Node *create(const NodeType *type);
+ static const NodeType *node_types[MAX_TYPE][MAX_TYPE];
+ static bool initialized;
+};
+
+class BsdfBaseNode : public ShaderNode {
+ public:
+ BsdfBaseNode(const NodeType *node_type);
+
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return closure;
+ }
+ virtual bool has_bump();
+
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
+ return false;
+ }
+
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_BSDF;
+ }
+
+ protected:
+ ClosureType closure;
+};
+
+class BsdfNode : public BsdfBaseNode {
+ public:
+ explicit BsdfNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(BsdfNode)
+
+ void compile(SVMCompiler &compiler,
+ ShaderInput *param1,
+ ShaderInput *param2,
+ ShaderInput *param3 = NULL,
+ ShaderInput *param4 = NULL);
+
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, surface_mix_weight)
+};
+
+class AnisotropicBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(AnisotropicBsdfNode)
+
+ NODE_SOCKET_API(float3, tangent)
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, anisotropy)
+ NODE_SOCKET_API(float, rotation)
+ NODE_SOCKET_API(ClosureType, distribution)
+
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+};
+
+class DiffuseBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(DiffuseBsdfNode)
+
+ NODE_SOCKET_API(float, roughness)
+};
+
+/* Disney principled BRDF */
+class PrincipledBsdfNode : public BsdfBaseNode {
+ public:
+ SHADER_NODE_CLASS(PrincipledBsdfNode)
+
+ void expand(ShaderGraph *graph);
+ bool has_surface_bssrdf();
+ bool has_bssrdf_bump();
+ 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);
+
+ NODE_SOCKET_API(float3, base_color)
+ NODE_SOCKET_API(float3, subsurface_color)
+ NODE_SOCKET_API(float3, subsurface_radius)
+ NODE_SOCKET_API(float, subsurface_ior)
+ NODE_SOCKET_API(float, subsurface_anisotropy)
+ NODE_SOCKET_API(float, metallic)
+ NODE_SOCKET_API(float, subsurface)
+ NODE_SOCKET_API(float, specular)
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, specular_tint)
+ NODE_SOCKET_API(float, anisotropic)
+ NODE_SOCKET_API(float, sheen)
+ NODE_SOCKET_API(float, sheen_tint)
+ NODE_SOCKET_API(float, clearcoat)
+ NODE_SOCKET_API(float, clearcoat_roughness)
+ NODE_SOCKET_API(float, ior)
+ NODE_SOCKET_API(float, transmission)
+ NODE_SOCKET_API(float, anisotropic_rotation)
+ NODE_SOCKET_API(float, transmission_roughness)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float3, clearcoat_normal)
+ NODE_SOCKET_API(float3, tangent)
+ NODE_SOCKET_API(float, surface_mix_weight)
+ NODE_SOCKET_API(ClosureType, distribution)
+ NODE_SOCKET_API(ClosureType, subsurface_method)
+ NODE_SOCKET_API(float3, emission)
+ NODE_SOCKET_API(float, emission_strength)
+ NODE_SOCKET_API(float, alpha)
+
+ private:
+ ClosureType distribution_orig;
+
+ public:
+ bool has_integrator_dependency();
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+};
+
+class TranslucentBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(TranslucentBsdfNode)
+};
+
+class TransparentBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(TransparentBsdfNode)
+
+ bool has_surface_transparent()
+ {
+ return true;
+ }
+};
+
+class VelvetBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(VelvetBsdfNode)
+
+ NODE_SOCKET_API(float, sigma)
+};
+
+class GlossyBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(GlossyBsdfNode)
+
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
+
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(ClosureType, distribution)
+
+ private:
+ float roughness_orig;
+ ClosureType distribution_orig;
+};
+
+class GlassBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(GlassBsdfNode)
+
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
+
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, IOR)
+ NODE_SOCKET_API(ClosureType, distribution)
+
+ private:
+ float roughness_orig;
+ ClosureType distribution_orig;
+};
+
+class RefractionBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(RefractionBsdfNode)
+
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
+
+ NODE_SOCKET_API(float, roughness)
+ NODE_SOCKET_API(float, IOR)
+ NODE_SOCKET_API(ClosureType, distribution)
+
+ private:
+ float roughness_orig;
+ ClosureType distribution_orig;
+};
+
+class ToonBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(ToonBsdfNode)
+
+ NODE_SOCKET_API(float, smooth)
+ NODE_SOCKET_API(float, size)
+ NODE_SOCKET_API(ClosureType, component)
+};
+
+class SubsurfaceScatteringNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(SubsurfaceScatteringNode)
+ bool has_surface_bssrdf()
+ {
+ return true;
+ }
+ bool has_bssrdf_bump();
+ ClosureType get_closure_type()
+ {
+ return method;
+ }
+
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float3, radius)
+ NODE_SOCKET_API(float, subsurface_ior)
+ NODE_SOCKET_API(float, subsurface_anisotropy)
+ NODE_SOCKET_API(ClosureType, method)
+};
+
+class EmissionNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(EmissionNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ bool has_surface_emission()
+ {
+ return true;
+ }
+ bool has_volume_support()
+ {
+ return true;
+ }
+
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_EMISSION;
+ }
+
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, surface_mix_weight)
+};
+
+class BackgroundNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(BackgroundNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_EMISSION;
+ }
+
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, surface_mix_weight)
+};
+
+class HoldoutNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(HoldoutNode)
+ virtual ClosureType get_closure_type()
+ {
+ return CLOSURE_HOLDOUT_ID;
+ }
+
+ NODE_SOCKET_API(float, surface_mix_weight)
+ NODE_SOCKET_API(float, volume_mix_weight)
+};
+
+class AmbientOcclusionNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(AmbientOcclusionNode)
+
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_feature()
+ {
+ return KERNEL_FEATURE_NODE_RAYTRACE;
+ }
+
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, distance)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(int, samples)
+
+ NODE_SOCKET_API(bool, only_local)
+ NODE_SOCKET_API(bool, inside)
+};
+
+class VolumeNode : public ShaderNode {
+ public:
+ VolumeNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(VolumeNode)
+
+ void compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2);
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_VOLUME;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return closure;
+ }
+ virtual bool has_volume_support()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, density)
+ NODE_SOCKET_API(float, volume_mix_weight)
+
+ protected:
+ ClosureType closure;
+
+ public:
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ /* TODO(sergey): With some care Volume nodes can be de-duplicated. */
+ return false;
+ }
+};
+
+class AbsorptionVolumeNode : public VolumeNode {
+ public:
+ SHADER_NODE_CLASS(AbsorptionVolumeNode)
+};
+
+class ScatterVolumeNode : public VolumeNode {
+ public:
+ SHADER_NODE_CLASS(ScatterVolumeNode)
+
+ NODE_SOCKET_API(float, anisotropy)
+};
+
+class PrincipledVolumeNode : public VolumeNode {
+ public:
+ SHADER_NODE_CLASS(PrincipledVolumeNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(ustring, density_attribute)
+ NODE_SOCKET_API(ustring, color_attribute)
+ NODE_SOCKET_API(ustring, temperature_attribute)
+
+ NODE_SOCKET_API(float, anisotropy)
+ NODE_SOCKET_API(float3, absorption_color)
+ NODE_SOCKET_API(float, emission_strength)
+ NODE_SOCKET_API(float3, emission_color)
+ NODE_SOCKET_API(float, blackbody_intensity)
+ NODE_SOCKET_API(float3, blackbody_tint)
+ NODE_SOCKET_API(float, temperature)
+};
+
+/* Interface between the I/O sockets and the SVM/OSL backend. */
+class PrincipledHairBsdfNode : public BsdfBaseNode {
+ public:
+ SHADER_NODE_CLASS(PrincipledHairBsdfNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+
+ /* Longitudinal roughness. */
+ NODE_SOCKET_API(float, roughness)
+ /* Azimuthal roughness. */
+ NODE_SOCKET_API(float, radial_roughness)
+ /* Randomization factor for roughnesses. */
+ NODE_SOCKET_API(float, random_roughness)
+ /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
+ NODE_SOCKET_API(float, coat)
+ /* Index of reflection. */
+ NODE_SOCKET_API(float, ior)
+ /* Cuticle tilt angle. */
+ NODE_SOCKET_API(float, offset)
+ /* Direct coloring's color. */
+ NODE_SOCKET_API(float3, color)
+ /* Melanin concentration. */
+ NODE_SOCKET_API(float, melanin)
+ /* Melanin redness ratio. */
+ NODE_SOCKET_API(float, melanin_redness)
+ /* Dye color. */
+ NODE_SOCKET_API(float3, tint)
+ /* Randomization factor for melanin quantities. */
+ NODE_SOCKET_API(float, random_color)
+ /* Absorption coefficient (unfiltered). */
+ NODE_SOCKET_API(float3, absorption_coefficient)
+
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, surface_mix_weight)
+ /* If linked, here will be the given random number. */
+ NODE_SOCKET_API(float, random)
+ /* Selected coloring parametrization. */
+ NODE_SOCKET_API(NodePrincipledHairParametrization, parametrization)
+};
+
+class HairBsdfNode : public BsdfNode {
+ public:
+ SHADER_NODE_CLASS(HairBsdfNode)
+ ClosureType get_closure_type()
+ {
+ return component;
+ }
+
+ NODE_SOCKET_API(ClosureType, component)
+ NODE_SOCKET_API(float, offset)
+ NODE_SOCKET_API(float, roughness_u)
+ NODE_SOCKET_API(float, roughness_v)
+ NODE_SOCKET_API(float3, tangent)
+};
+
+class GeometryNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(GeometryNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ int get_group();
+
+ NODE_SOCKET_API(float3, normal_osl)
+};
+
+class TextureCoordinateNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(TextureCoordinateNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(float3, normal_osl)
+ NODE_SOCKET_API(bool, from_dupli)
+ NODE_SOCKET_API(bool, use_transform)
+ NODE_SOCKET_API(Transform, ob_tfm)
+};
+
+class UVMapNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(UVMapNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(bool, from_dupli)
+};
+
+class LightPathNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(LightPathNode)
+};
+
+class LightFalloffNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(LightFalloffNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, smooth)
+};
+
+class ObjectInfoNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(ObjectInfoNode)
+};
+
+class ParticleInfoNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(ParticleInfoNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+};
+
+class HairInfoNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(HairInfoNode)
+
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_HAIR;
+ }
+};
+
+class VolumeInfoNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(VolumeInfoNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ void expand(ShaderGraph *graph);
+};
+
+class VertexColorNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(VertexColorNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(ustring, layer_name)
+};
+
+class ValueNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(ValueNode)
+
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, value)
+};
+
+class ColorNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(ColorNode)
+
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, value)
+};
+
+class AddClosureNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(AddClosureNode)
+ void constant_fold(const ConstantFolder &folder);
+};
+
+class MixClosureNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(MixClosureNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, fac)
+};
+
+class MixClosureWeightNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(MixClosureWeightNode)
+
+ NODE_SOCKET_API(float, weight)
+ NODE_SOCKET_API(float, fac)
+};
+
+class InvertNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(InvertNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(float3, color)
+};
+
+class MixNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(MixNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(NodeMix, mix_type)
+ NODE_SOCKET_API(bool, use_clamp)
+ NODE_SOCKET_API(float3, color1)
+ NODE_SOCKET_API(float3, color2)
+ NODE_SOCKET_API(float, fac)
+};
+
+class CombineRGBNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(CombineRGBNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, r)
+ NODE_SOCKET_API(float, g)
+ NODE_SOCKET_API(float, b)
+};
+
+class CombineHSVNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(CombineHSVNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, h)
+ NODE_SOCKET_API(float, s)
+ NODE_SOCKET_API(float, v)
+};
+
+class CombineXYZNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(CombineXYZNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, x)
+ NODE_SOCKET_API(float, y)
+ NODE_SOCKET_API(float, z)
+};
+
+class GammaNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(GammaNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, gamma)
+};
+
+class BrightContrastNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(BrightContrastNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, bright)
+ NODE_SOCKET_API(float, contrast)
+};
+
+class SeparateRGBNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(SeparateRGBNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, color)
+};
+
+class SeparateHSVNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(SeparateHSVNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, color)
+};
+
+class SeparateXYZNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(SeparateXYZNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, vector)
+};
+
+class HSVNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(HSVNode)
+
+ NODE_SOCKET_API(float, hue)
+ NODE_SOCKET_API(float, saturation)
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(float3, color)
+};
+
+class AttributeNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(AttributeNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(ustring, attribute)
+};
+
+class CameraNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(CameraNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+};
+
+class FresnelNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(FresnelNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, IOR)
+};
+
+class LayerWeightNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(LayerWeightNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, blend)
+};
+
+class WireframeNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(WireframeNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(float, size)
+ NODE_SOCKET_API(bool, use_pixel_size)
+};
+
+class WavelengthNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(WavelengthNode)
+
+ NODE_SOCKET_API(float, wavelength)
+};
+
+class BlackbodyNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(BlackbodyNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, temperature)
+};
+
+class MapRangeNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(MapRangeNode)
+ void expand(ShaderGraph *graph);
+
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float, from_min)
+ NODE_SOCKET_API(float, from_max)
+ NODE_SOCKET_API(float, to_min)
+ NODE_SOCKET_API(float, to_max)
+ NODE_SOCKET_API(float, steps)
+ NODE_SOCKET_API(NodeMapRangeType, range_type)
+ NODE_SOCKET_API(bool, clamp)
+};
+
+class ClampNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(ClampNode)
+ void constant_fold(const ConstantFolder &folder);
+ NODE_SOCKET_API(float, value)
+ NODE_SOCKET_API(float, min)
+ NODE_SOCKET_API(float, max)
+ NODE_SOCKET_API(NodeClampType, clamp_type)
+};
+
+class MathNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(MathNode)
+ void expand(ShaderGraph *graph);
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float, value1)
+ NODE_SOCKET_API(float, value2)
+ NODE_SOCKET_API(float, value3)
+ NODE_SOCKET_API(NodeMathType, math_type)
+ NODE_SOCKET_API(bool, use_clamp)
+};
+
+class NormalNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(NormalNode)
+
+ NODE_SOCKET_API(float3, direction)
+ NODE_SOCKET_API(float3, normal)
+};
+
+class VectorMathNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(VectorMathNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API(float3, vector1)
+ NODE_SOCKET_API(float3, vector2)
+ NODE_SOCKET_API(float3, vector3)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(NodeVectorMathType, math_type)
+};
+
+class VectorRotateNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(VectorRotateNode)
+
+ NODE_SOCKET_API(NodeVectorRotateType, rotate_type)
+ NODE_SOCKET_API(bool, invert)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float3, center)
+ NODE_SOCKET_API(float3, axis)
+ NODE_SOCKET_API(float, angle)
+ NODE_SOCKET_API(float3, rotation)
+};
+
+class VectorTransformNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(VectorTransformNode)
+
+ NODE_SOCKET_API(NodeVectorTransformType, transform_type)
+ NODE_SOCKET_API(NodeVectorTransformConvertSpace, convert_from)
+ NODE_SOCKET_API(NodeVectorTransformConvertSpace, convert_to)
+ NODE_SOCKET_API(float3, vector)
+};
+
+class BumpNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(BumpNode)
+ void constant_fold(const ConstantFolder &folder);
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_feature()
+ {
+ return KERNEL_FEATURE_NODE_BUMP;
+ }
+
+ NODE_SOCKET_API(bool, invert)
+ NODE_SOCKET_API(bool, use_object_space)
+ NODE_SOCKET_API(float, height)
+ NODE_SOCKET_API(float, sample_center)
+ NODE_SOCKET_API(float, sample_x)
+ NODE_SOCKET_API(float, sample_y)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float, distance)
+};
+
+class CurvesNode : public ShaderNode {
+ public:
+ explicit CurvesNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(CurvesNode)
+
+ NODE_SOCKET_API_ARRAY(array<float3>, curves)
+ NODE_SOCKET_API(float, min_x)
+ NODE_SOCKET_API(float, max_x)
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(float3, value)
+
+ protected:
+ using ShaderNode::constant_fold;
+ void constant_fold(const ConstantFolder &folder, ShaderInput *value_in);
+ void compile(SVMCompiler &compiler, int type, ShaderInput *value_in, ShaderOutput *value_out);
+ void compile(OSLCompiler &compiler, const char *name);
+};
+
+class RGBCurvesNode : public CurvesNode {
+ public:
+ SHADER_NODE_CLASS(RGBCurvesNode)
+ void constant_fold(const ConstantFolder &folder);
+};
+
+class VectorCurvesNode : public CurvesNode {
+ public:
+ SHADER_NODE_CLASS(VectorCurvesNode)
+ void constant_fold(const ConstantFolder &folder);
+};
+
+class FloatCurveNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(FloatCurveNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API_ARRAY(array<float>, curve)
+ NODE_SOCKET_API(float, min_x)
+ NODE_SOCKET_API(float, max_x)
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(float, value)
+};
+
+class RGBRampNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(RGBRampNode)
+ void constant_fold(const ConstantFolder &folder);
+
+ NODE_SOCKET_API_ARRAY(array<float3>, ramp)
+ NODE_SOCKET_API_ARRAY(array<float>, ramp_alpha)
+ NODE_SOCKET_API(float, fac)
+ NODE_SOCKET_API(bool, interpolate)
+};
+
+class SetNormalNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(SetNormalNode)
+ NODE_SOCKET_API(float3, direction)
+};
+
+class OSLNode final : public ShaderNode {
+ public:
+ static OSLNode *create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from = NULL);
+ ~OSLNode();
+
+ static void operator delete(void *ptr)
+ {
+ /* Override delete operator to silence new-delete-type-mismatch ASAN warnings
+ * regarding size mismatch in the destructor. This is intentional as we allocate
+ * extra space at the end of the node. */
+ ::operator delete(ptr);
+ }
+ static void operator delete(void *, void *)
+ {
+ /* Deliberately empty placement delete operator, to avoid MSVC warning C4291. */
+ }
+
+ ShaderNode *clone(ShaderGraph *graph) const;
+
+ char *input_default_value();
+ void add_input(ustring name, SocketType::Type type);
+ void add_output(ustring name, SocketType::Type type);
+
+ SHADER_NODE_NO_CLONE_CLASS(OSLNode)
+
+ /* Ideally we could better detect this, but we can't query this now. */
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ bool has_volume_support()
+ {
+ return true;
+ }
+
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ return false;
+ }
+
+ string filepath;
+ string bytecode_hash;
+};
+
+class NormalMapNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(NormalMapNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(NodeNormalMapSpace, space)
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(float, strength)
+ NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float3, normal_osl)
+};
+
+class TangentNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(TangentNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+
+ NODE_SOCKET_API(NodeTangentDirectionType, direction_type)
+ NODE_SOCKET_API(NodeTangentAxis, axis)
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(float3, normal_osl)
+};
+
+class BevelNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(BevelNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_feature()
+ {
+ return KERNEL_FEATURE_NODE_RAYTRACE;
+ }
+
+ NODE_SOCKET_API(float, radius)
+ NODE_SOCKET_API(float3, normal)
+ NODE_SOCKET_API(int, samples)
+};
+
+class DisplacementNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(DisplacementNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_feature()
+ {
+ return KERNEL_FEATURE_NODE_BUMP;
+ }
+
+ NODE_SOCKET_API(NodeNormalMapSpace, space)
+ NODE_SOCKET_API(float, height)
+ NODE_SOCKET_API(float, midlevel)
+ NODE_SOCKET_API(float, scale)
+ NODE_SOCKET_API(float3, normal)
+};
+
+class VectorDisplacementNode : public ShaderNode {
+ public:
+ SHADER_NODE_CLASS(VectorDisplacementNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_feature()
+ {
+ return KERNEL_FEATURE_NODE_BUMP;
+ }
+
+ NODE_SOCKET_API(NodeNormalMapSpace, space)
+ NODE_SOCKET_API(ustring, attribute)
+ NODE_SOCKET_API(float3, vector)
+ NODE_SOCKET_API(float, midlevel)
+ NODE_SOCKET_API(float, scale)
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __NODES_H__ */