/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #ifndef __NSHADER_BLOCK__ #define __NSHADER_BLOCK__ #include "core/shader.h" #include "color/color.h" #include "math/matrix3.h" #include "math/matrix4.h" #include "nstring/nstring.h" namespace GS { namespace NML { class Tag; } namespace Core { struct ShaderBlockPin; struct ShaderBlock; typedef ShaderBlock * pShaderBlock; /*! @short Block shader value. Used by the raytracer software implementation of the shader blocks. */ struct ShaderBlockValue { enum BlockValueType { BlockValueNone = 0, BlockValueVector, BlockValueMatrix3, BlockValueMatrix4, BlockValueTexture }; BlockValueType type; // Can't union those and most of all we don't want runtime allocations here... Vector4 v; Matrix3 m3; Matrix4 m4; String t; void Set(const float &_f) { v.x = _f; type = BlockValueVector; } void Set(const Vector4 &_v) { v = _v; type = BlockValueVector; } void Set(const Matrix3 &_m) { m3 = _m; type = BlockValueMatrix3; } void Set(const Matrix4 &_m) { m4 = _m; type = BlockValueMatrix4; } void Set(const char *_t) { t = _t; type = BlockValueTexture; } ShaderBlockValue() : type(BlockValueNone) {} }; /*! @short Base render block. A render block is a component of a render map. It represents an input, an operator to the render map. @author Emmanuel Julien (ejulien@gsworks.fr) */ struct ShaderBlock { enum BlockType { TypeNone = 0, // Input blocks. TypeGeometryVertex, TypeGeometryNormal, TypeGeometryUV, TypeGeometrySkinning, TypeGeometryVertexColor, TypeGeometryTangentFrame, TypeRenderBuffer, TypeTexture, TypeTextureSampler, TypeConstant, TypeColor, TypeMaterialParam, TypeMaterialTexture, TypeScreenUV, TypeViewVector, TypeViewport, // Matrix blocks. TypeNormalViewMatrix, TypeNormalMatrix, TypeModelViewMatrix, TypeModelMatrix, // Operator blocks. TypeMix, TypeAdd, TypeMul, TypeSub, TypeDiv, TypeDot, TypeCross, TypeClamp, TypeNormalize, TypeSwizzle, TypeBuild, TypeSin, TypeCos, TypePow, TypeAbs, // Packing operators. TypeUnpackColorToVector, TypePackVectorToColor, // Engine parameters. TypeClock, TypeInvalid }; /// Verbose block type. static const char *BlockTypeToString(BlockType type) { switch (type) { case TypeNone: return "None"; case TypeGeometryVertex: return "Geometry Vertex"; case TypeGeometryNormal: return "Geometry Normal"; case TypeGeometryUV: return "Geometry UV"; case TypeGeometrySkinning: return "Geometry Skinning"; case TypeGeometryVertexColor: return "Geometry RGB"; case TypeGeometryTangentFrame: return "Geometry Tangent Frame"; case TypeRenderBuffer: return "Render Buffer"; case TypeTexture: return "Texture"; case TypeTextureSampler: return "Texture Sampler"; case TypeConstant: return "Constant"; case TypeColor: return "Color"; case TypeMaterialParam: return "Material Parameter"; case TypeMaterialTexture: return "Material Texture"; case TypeScreenUV: return "Screen UV"; case TypeViewVector: return "View Vector"; case TypeViewport: return "Viewport"; case TypeNormalViewMatrix: return "Normal View Matrix"; case TypeNormalMatrix: return "Normal Matrix "; ///< ! The additional space is NEEDED! (Normal matrix is the name of a legacy version of this node) case TypeModelViewMatrix: return "Model View Matrix"; case TypeModelMatrix: return "Model Matrix"; case TypeMix: return "Mix"; case TypeAdd: return "Add"; case TypeMul: return "Multiply"; case TypeSub: return "Subtract"; case TypeDiv: return "Divide"; case TypeDot: return "Dot"; case TypeCross: return "Cross"; case TypeClamp: return "Clamp"; case TypeNormalize: return "Normalize"; case TypeSwizzle: return "Swizzle"; case TypeBuild: return "Build"; case TypeSin: return "Sinus"; case TypeCos: return "Cosinus"; case TypePow: return "Pow"; case TypeAbs: return "Abs"; case TypeUnpackColorToVector: return "Unpack color to vector"; case TypePackVectorToColor: return "Pack vector to color"; case TypeClock: return "Clock"; case TypeInvalid: break; } return "Invalid"; } Vector2 pos; BlockType type; /* @name Block input/output. @{ */ /// Get input count. virtual uint GetInputCount() const = 0; /// Get input block. virtual ShaderBlock *GetInput(uint n) const = 0; /// Set input. virtual bool SetInput(uint n, ShaderBlock *in) = 0; /// Get input pin. virtual const ShaderBlockPin *GetInputPin(uint n) const = 0; /// Get block output pin. virtual const ShaderBlockPin *GetOutputPin() const = 0; /// Evaluate block output type. virtual int GetOutputType() const = 0; /// @} /// Get block label. virtual String GetLabel() const = 0; /// Get block id. virtual String GetId() const = 0; /// Is this block equivalent to another block. bool IsEquivalent(const ShaderBlock *input_block) const; /// Gather all of this block children. void GatherChildren(List &children); /// Import block map from metatag. static Array *BlockMapFromMetaTag(NML::Tag &); /// Import branch from metatag. static ShaderBlock *BranchFromMetaTag(NML::Tag &, Array *block_map = 0); static NML::Tag *BlockMapAsMetaTag(const List &block_map); NML::Tag *BranchAsMetaTag(List &block_map); NML::Tag *ParamAsMetaTag() const; ShaderBlock() : type(TypeNone) {} virtual ~ShaderBlock() {} }; //------------------------------------------------------------------------------ #define __SpecializeBlock(__LABEL__, __INPUT_COUNT__)\ static ShaderBlockPin input_pin[__INPUT_COUNT__];\ static ShaderBlockPin output_pin;\ \ ShaderBlock *input[__INPUT_COUNT__];\ \ String GetLabel() const\ { return __LABEL__; }\ uint GetInputCount() const\ { return __INPUT_COUNT__; }\ bool SetInput(uint n, ShaderBlock *block)\ {\ if (n >= __INPUT_COUNT__)\ return false;\ if (block && !(input_pin[n].compatibility & block->GetOutputType()))\ return false;\ input[n] = block;\ return true;\ }\ ShaderBlock *GetInput(uint n) const\ { return (n < __INPUT_COUNT__) ? input[n] : 0; }\ const ShaderBlockPin *GetInputPin(uint n) const\ { return (n < __INPUT_COUNT__) ? &input_pin[n] : 0; }\ const ShaderBlockPin *GetOutputPin() const\ { return &output_pin; }\ int GetOutputType() const; #define __SpecializeBlockNoInput(__LABEL__)\ static ShaderBlockPin output_pin;\ \ String GetLabel() const\ { return __LABEL__; }\ uint GetInputCount() const\ { return 0; }\ bool SetInput(uint /*n*/, ShaderBlock */*block*/)\ { return false; }\ ShaderBlock *GetInput(uint /*n*/) const\ { return 0; }\ const ShaderBlockPin *GetInputPin(uint /*n*/) const\ { return 0; }\ const ShaderBlockPin *GetOutputPin() const\ { return &output_pin; }\ int GetOutputType() const; //------------------------------------------------------------------------------ /* @short Render block pin description. @author Emmanuel Julien (ejulien@gsworks.fr) */ struct ShaderBlockPin { const char *name, *desc; int compatibility; ///< Pin connection compatibility }; struct SinusShaderBlock : public ShaderBlock { __SpecializeBlock("Sinus", 1) String GetId() const { return "Sin"; } SinusShaderBlock(ShaderBlock *block = 0) { type = TypeSin; input[0] = block; } }; struct CosinusShaderBlock : public ShaderBlock { __SpecializeBlock("Cosinus", 1) String GetId() const { return "Cos"; } CosinusShaderBlock(ShaderBlock *block = 0) { type = TypeCos; input[0] = block; } }; struct PowShaderBlock : public ShaderBlock { __SpecializeBlock("Pow", 2) String GetId() const { return "Pow"; } PowShaderBlock(ShaderBlock *v = 0, ShaderBlock *p = 0) { type = TypePow; input[0] = v; input[1] = p; } }; struct AbsShaderBlock : public ShaderBlock { __SpecializeBlock("Abs", 1) String GetId() const { return "Abs"; } AbsShaderBlock(ShaderBlock *v = 0) { type = TypeAbs; input[0] = v; } }; struct ClockShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Clock") String GetId() const { return "Clock"; } ClockShaderBlock() { type = TypeClock; } }; struct ScreenUVShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Screen UV") String GetId() const { return "ScreenUV"; } ScreenUVShaderBlock() { type = TypeScreenUV; } }; struct ViewVectorShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("View Vector") String GetId() const { return "ViewV"; } ViewVectorShaderBlock() { type = TypeViewVector; } }; struct ViewportShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Viewport") String GetId() const { return "Viewport"; } ViewportShaderBlock() { type = TypeViewport; } }; struct NormalViewMatrixShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Normal View Matrix") String GetId() const { return "NormalViewMatrix"; } NormalViewMatrixShaderBlock() { type = TypeNormalViewMatrix; } }; struct NormalMatrixShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Normal Matrix ") String GetId() const { return "NormalMatrix"; } NormalMatrixShaderBlock() { type = TypeNormalMatrix; } }; struct ModelViewMatrixShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Model View Matrix ") String GetId() const { return "ModelViewMatrix"; } ModelViewMatrixShaderBlock() { type = TypeModelViewMatrix; } }; struct ModelMatrixShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Model Matrix") String GetId() const { return "ModelMatrix"; } ModelMatrixShaderBlock() { type = TypeModelMatrix; } }; struct UnpackColorToVectorShaderBlock : public ShaderBlock { __SpecializeBlock("Unpack Color", 1) String GetId() const { return "UnpackColor"; } UnpackColorToVectorShaderBlock(ShaderBlock *block = 0) { type = TypeUnpackColorToVector; input[0] = block; } }; struct PackVectorToColorShaderBlock : public ShaderBlock { __SpecializeBlock("Pack Vector", 1) String GetId() const { return "PackVector"; } PackVectorToColorShaderBlock(ShaderBlock *block = 0) { type = TypePackVectorToColor; input[0] = block; } }; struct MixOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Mix", 3) String GetId() const { return "Mix"; } MixOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0, ShaderBlock *k = 0) { type = TypeMix; input[0] = a; input[1] = b; input[2] = k; } }; struct AddOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Add", 2) String GetId() const { return "Add"; } AddOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) { type = TypeAdd; input[0] = a; input[1] = b; } }; struct MulOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Mul", 2) String GetId() const { return "Mul"; } MulOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) { type = TypeMul; input[0] = a; input[1] = b; } }; struct SubOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Sub", 2) String GetId() const { return "Sub"; } SubOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) { type = TypeSub; input[0] = a; input[1] = b; } }; struct DivOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Div", 2) String GetId() const { return "Div"; } DivOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) { type = TypeDiv; input[0] = a; input[1] = b; } }; struct DotOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Dot", 2) String GetId() const { return "Dot"; } DotOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) { type = TypeDot; input[0] = a; input[1] = b; } }; struct CrossOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Cross", 2) String GetId() const { return "Cross"; } CrossOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) { type = TypeCross; input[0] = a; input[1] = b; } }; struct NormalizeOperatorShaderBlock : public ShaderBlock { __SpecializeBlock("Normalize", 1) String GetId() const { return "Norm"; } NormalizeOperatorShaderBlock(ShaderBlock *a = 0) { type = TypeNormalize; input[0] = a; } }; struct ClampShaderBlock : public ShaderBlock { __SpecializeBlock("Clamp", 3) String GetId() const { return "Clamp"; } ClampShaderBlock(ShaderBlock *v = 0, ShaderBlock *a = 0, ShaderBlock *b = 0) { type = TypeClamp; input[0] = v; input[1] = a; input[2] = b; } }; struct SwizzleShaderBlock : public ShaderBlock { enum Swizzle { SwizzleNone = 0, SwizzleX, SwizzleY, SwizzleZ, SwizzleW }; __SpecializeBlock("Swizzle", 1) String GetId() const { return String::Format("Swizzle%d%d%d%d", swizzle[0], swizzle[1], swizzle[2], swizzle[3]); } Swizzle swizzle[4]; SwizzleShaderBlock(ShaderBlock *block = 0, Swizzle x = SwizzleNone, Swizzle y = SwizzleNone, Swizzle z = SwizzleNone, Swizzle w = SwizzleNone) { type = TypeSwizzle; swizzle[0] = x; swizzle[1] = y; swizzle[2] = z; swizzle[3] = w; input[0] = block; } }; struct BuildShaderBlock : public ShaderBlock { enum Build { BuildZero = 0, BuildOne, BuildX, BuildY, BuildZ, BuildW }; __SpecializeBlock("Build", 4) Build build[4]; String GetId() const { return String::Format("Build%d%d%d%d", build[0], build[1], build[2], build[3]); } BuildShaderBlock(ShaderBlock *a = 0, Build x = BuildX, ShaderBlock *b = 0, Build y = BuildY, ShaderBlock *c = 0, Build z = BuildZ, ShaderBlock *d = 0, Build w = BuildW) { type = TypeBuild; build[0] = x; build[1] = y; build[2] = z; build[3] = w; input[0] = a; input[1] = b; input[2] = c; input[3] = d; } }; struct GeometryUVShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("UV Stream") int channel; String GetId() const { return String::Format("UV%d", channel); } GeometryUVShaderBlock(int uv_channel = 0) { type = TypeGeometryUV; channel = uv_channel; } }; struct GeometryVertexShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Vertex Stream") String GetId() const { return String("Vertex"); } GeometryVertexShaderBlock() { type = TypeGeometryVertex; } }; struct GeometryNormalShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Normal Stream") bool smooth; String GetId() const { return String(smooth ? "NormalSmooth" : "Normal"); } GeometryNormalShaderBlock() { type = TypeGeometryNormal; smooth = true; } }; struct GeometrySkinningShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Skinning Matrix") String GetId() const { return String("SkinMtx"); } GeometrySkinningShaderBlock() { type = TypeGeometrySkinning; } }; struct GeometryVertexColorShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Vertex Color Stream") String GetId() const { return String("VertexColor"); } GeometryVertexColorShaderBlock() { type = TypeGeometryVertexColor; } }; struct GeometryTangentFrameShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Tangent Frame") String GetId() const { return String("TangentMtx"); } GeometryTangentFrameShaderBlock() { type = TypeGeometryTangentFrame; } }; struct RenderBufferShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Render Buffer") enum RenderBuffer { Depth = 0 }; RenderBuffer buffer; String GetId() const { return String("RenderBuffer"); } RenderBufferShaderBlock(RenderBuffer _buffer = Depth) { type = TypeRenderBuffer; buffer = _buffer; } }; struct TextureShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Texture") enum TextureType { Texture2D = 0, Texture3D, TextureCube }; TextureType texture_type; String texture; String GetId() const; TextureShaderBlock(const char *name = 0) { type = TypeTexture; texture = name; texture_type = Texture2D; } }; struct TextureSamplerShaderBlock : public ShaderBlock { __SpecializeBlock("Texture Sampler", 2) enum SamplerType { Sampler2D = 0, Sampler3D, SamplerCube }; SamplerType sampler_type; String GetId() const { return String::Format("TexSampler%d", (int)sampler_type); } TextureSamplerShaderBlock(ShaderBlock *texture = 0, ShaderBlock *uv = 0) { type = TypeTextureSampler; sampler_type = Sampler2D; input[0] = texture; input[1] = uv; } }; struct MaterialParamShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Material Parameter") enum MaterialParam { MaterialDiffuse = 0, MaterialSpecular, MaterialSelf, MaterialAmbient, MaterialGlossiness, MaterialOpacity, MaterialReflection }; MaterialParam param; String GetId() const; MaterialParamShaderBlock(MaterialParam p = MaterialDiffuse) { type = TypeMaterialParam; param = p; } }; struct MaterialTextureShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Material Texture") enum TextureType { Texture2D = 0, Texture3D, TextureCube }; TextureType texture_type; int slot; String GetId() const; MaterialTextureShaderBlock(int n = 0) { type = TypeMaterialTexture; texture_type = Texture2D; slot = n; } }; struct ColorShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Color") Color color; String GetId() const { return "Color"; } ColorShaderBlock(float r = 1, float g = 1, float b = 1, float a = 1) { type = TypeColor; color.Set(r, g, b, a); } }; struct ConstantShaderBlock : public ShaderBlock { __SpecializeBlockNoInput("Constant") float constant[4]; ShaderInput::DataType constant_type; String GetId() const; ConstantShaderBlock() { type = TypeConstant; constant_type = ShaderInput::NoData; constant[0] = constant[1] = constant[2] = constant[3] = 0; } ConstantShaderBlock(float v) { type = TypeConstant; constant_type = ShaderInput::Float; constant[0] = v; constant[1] = constant[2] = constant[3] = 0; } ConstantShaderBlock(float u, float v) { type = TypeConstant; constant_type = ShaderInput::Vector2; constant[0] = u; constant[1] = v; constant[2] = constant[3] = 0; } ConstantShaderBlock(float x, float y, float z) { type = TypeConstant; constant_type = ShaderInput::Vector3; constant[0] = x; constant[1] = y; constant[2] = z; constant[3] = 0; } ConstantShaderBlock(float x, float y, float z, float w) { type = TypeConstant; constant_type = ShaderInput::Vector4; constant[0] = x; constant[1] = y; constant[2] = z; constant[3] = w; } }; } // Core } // GS #endif // __NSHADER_BLOCK__