diff options
Diffstat (limited to 'intern/cycles/scene/shader_nodes.h')
-rw-r--r-- | intern/cycles/scene/shader_nodes.h | 1569 |
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..b8a439fa9b9 --- /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/util_array.h" +#include "util/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__ */ |