/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "core/shader_block.h" #include "log/log.h" using namespace GS::Core; using GS::String; // Tools. ShaderBlockPin SwizzleShaderBlock::input_pin[] = { { "Input", "Source input to extract components from.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin SwizzleShaderBlock::output_pin = { "Swizzled", "Swizzled input.", ShaderInput::NoData }; ShaderBlockPin BuildShaderBlock::input_pin[] = { { "Input X", "Source component of the built vector.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input Y", "Source component of the built vector.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input Z", "Source component of the built vector.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input W", "Source component of the built vector.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin BuildShaderBlock::output_pin = { "Built", "Built vector.", ShaderInput::NoData }; ShaderBlockPin ClampShaderBlock::input_pin[] = { { "Input", "Source to clamp.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Min", "Minimum value.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Max", "Maximum value.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin ClampShaderBlock::output_pin = { "Clamped", "Clamped input.", ShaderInput::NoData }; ShaderBlockPin UnpackColorToVectorShaderBlock::input_pin[] = { { "Input", "Vector in the [0;1] range.", ShaderInput::Float | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin UnpackColorToVectorShaderBlock::output_pin = { "Unpacked [-1;1]", "Vector in the [-1;1] range.", ShaderInput::NoData }; ShaderBlockPin PackVectorToColorShaderBlock::input_pin[] = { { "Input", "Vector in the [-1;1] range.", ShaderInput::Float | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin PackVectorToColorShaderBlock::output_pin = { "Packed [0;1]", "Vector in the [0;1] range.", ShaderInput::NoData }; // Operator. ShaderBlockPin MixOperatorShaderBlock::input_pin[] = { { "Input A", "Source input A.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input B", "Source input B.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input K", "Source input K.", ShaderInput::Float } }; ShaderBlockPin MixOperatorShaderBlock::output_pin = { "A*K+B*(1-K)", "Input A * Input K + Input B * (1.0 - Input K).", ShaderInput::NoData }; ShaderBlockPin AddOperatorShaderBlock::input_pin[] = { { "Input A", "Source input A.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input B", "Source input B.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin AddOperatorShaderBlock::output_pin = { "A+B", "Input A + Input B.", ShaderInput::NoData }; ShaderBlockPin SubOperatorShaderBlock::input_pin[] = { { "Input A", "Source input A.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input B", "Source input B.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin SubOperatorShaderBlock::output_pin = { "A-B", "Input A - Input B.", ShaderInput::NoData }; ShaderBlockPin MulOperatorShaderBlock::input_pin[] = { { "Input A", "Source input A.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 | ShaderInput::Matrix3 | ShaderInput::Matrix4 }, { "Input B", "Source input B.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 | ShaderInput::Matrix3 | ShaderInput::Matrix4 } }; ShaderBlockPin MulOperatorShaderBlock::output_pin = { "A*B", "Input A * Input B.", ShaderInput::NoData }; ShaderBlockPin DivOperatorShaderBlock::input_pin[] = { { "Input A", "Source input A.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input B", "Source input B.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin DivOperatorShaderBlock::output_pin = { "A/B", "Input A / Input B.", ShaderInput::NoData }; ShaderBlockPin DotOperatorShaderBlock::input_pin[] = { { "Input A", "Source input A.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 }, { "Input B", "Source input B.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin DotOperatorShaderBlock::output_pin = { "A.Dot(B)", "The cosinus of the angle between A and B.", ShaderInput::NoData }; ShaderBlockPin CrossOperatorShaderBlock::input_pin[] = { { "Input A", "Source input A.", ShaderInput::Vector3 }, { "Input B", "Source input B.", ShaderInput::Vector3 } }; ShaderBlockPin CrossOperatorShaderBlock::output_pin = { "A.Cross(B)", "A vector perpendicular to both A and B.", ShaderInput::NoData }; ShaderBlockPin NormalizeOperatorShaderBlock::input_pin[] = { { "Input", "Source input.", ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin NormalizeOperatorShaderBlock::output_pin = { "Normalized", "Normalized input.", ShaderInput::NoData }; ShaderBlockPin CosinusShaderBlock::input_pin[] = { { "Input", "Input value in radian.", ShaderInput::Float } }; ShaderBlockPin CosinusShaderBlock::output_pin = { "Cosinus", "Cosinus of input.", ShaderInput::NoData }; ShaderBlockPin SinusShaderBlock::input_pin[] = { { "Input", "Input value in radian.", ShaderInput::Float } }; ShaderBlockPin SinusShaderBlock::output_pin = { "Sinus", "Sinus of input.", ShaderInput::NoData }; ShaderBlockPin PowShaderBlock::input_pin[] = { { "Value", "Input value.", ShaderInput::Float }, { "Power", "Power to raise value to.", ShaderInput::Float } }; ShaderBlockPin PowShaderBlock::output_pin = { "Pow", "Value raised to power.", ShaderInput::NoData }; ShaderBlockPin AbsShaderBlock::input_pin[] = { { "Value", "Input value.", ShaderInput::Float | ShaderInput::Vector2 | ShaderInput::Vector3 | ShaderInput::Vector4 } }; ShaderBlockPin AbsShaderBlock::output_pin = { "Abs", "Absolute value of input.", ShaderInput::NoData }; // Texture ShaderBlockPin TextureSamplerShaderBlock::input_pin[] = { { "Texture", "Texture input.", ShaderInput::Texture2D }, { "UV Stream", "UV stream input.", ShaderInput::Vector2 | ShaderInput::Vector3 } }; ShaderBlockPin TextureSamplerShaderBlock::output_pin = { "Texel", "Texture sample.", ShaderInput::NoData }; // No input blocks. ShaderBlockPin GeometryVertexShaderBlock::output_pin = { "Vertex", "Vertex stream.", ShaderInput::NoData }; ShaderBlockPin GeometrySkinningShaderBlock::output_pin = { "Skinned", "Skinned vector.", ShaderInput::NoData }; ShaderBlockPin GeometryNormalShaderBlock::output_pin = { "Normal", "Normal stream.", ShaderInput::NoData }; ShaderBlockPin GeometryUVShaderBlock::output_pin = { "UV", "UV stream.", ShaderInput::NoData }; ShaderBlockPin GeometryVertexColorShaderBlock::output_pin = { "Color", "Vertex color stream.", ShaderInput::NoData }; ShaderBlockPin GeometryTangentFrameShaderBlock::output_pin = { "Tangent", "Tangent frame.", ShaderInput::NoData }; ShaderBlockPin RenderBufferShaderBlock::output_pin = { "Buffer", "Texture object.", ShaderInput::NoData }; ShaderBlockPin TextureShaderBlock::output_pin = { "Texture", "Texture object.", ShaderInput::NoData }; ShaderBlockPin ConstantShaderBlock::output_pin = { "Constant", "Constant value.", ShaderInput::NoData }; ShaderBlockPin ColorShaderBlock::output_pin = { "Color", "RGBA Color.", ShaderInput::NoData }; ShaderBlockPin MaterialParamShaderBlock::output_pin = { "Parameter", "Material parameter.", ShaderInput::NoData }; ShaderBlockPin MaterialTextureShaderBlock::output_pin = { "Slot", "Texture slot.", ShaderInput::NoData }; ShaderBlockPin ClockShaderBlock::output_pin = { "Clock (s)", "System clock in second.", ShaderInput::NoData }; ShaderBlockPin ScreenUVShaderBlock::output_pin = { "Screen UV", "Screen position.", ShaderInput::NoData }; ShaderBlockPin ViewVectorShaderBlock::output_pin = { "World View", "View vector in world space.", ShaderInput::NoData }; ShaderBlockPin ViewportShaderBlock::output_pin = { "Viewport", "Viewport origin and dimension in 2d.", ShaderInput::NoData }; ShaderBlockPin NormalViewMatrixShaderBlock::output_pin = { "Normal View Matrix", "Normal view matrix.", ShaderInput::NoData }; ShaderBlockPin NormalMatrixShaderBlock::output_pin = { "Normal Matrix", "Normal matrix.", ShaderInput::NoData }; ShaderBlockPin ModelViewMatrixShaderBlock::output_pin = { "Model View Matrix", "Model view matrix.", ShaderInput::NoData }; ShaderBlockPin ModelMatrixShaderBlock::output_pin = { "Model Matrix", "Model matrix.", ShaderInput::NoData }; //------------------------------------------------------------------------------ String TextureShaderBlock::GetId() const { return String("Texture") + texture; } String ConstantShaderBlock::GetId() const { switch (constant_type) { case ShaderInput::NoData: return String("ConstNone"); case ShaderInput::Float: return String("ConstFloat"); case ShaderInput::Vector2: return String("ConstVec2"); case ShaderInput::Vector3: return String("ConstVec3"); case ShaderInput::Vector4: return String("ConstVec4"); } __ERR__(__LOG_E__ << "Unknown constant.\n", String("ConstUnk")) } String MaterialParamShaderBlock::GetId() const { return String::Format("MatParm%d", param); } String MaterialTextureShaderBlock::GetId() const { return String::Format("MatTexture%d", slot); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool ShaderBlock::IsEquivalent(const ShaderBlock *input_block) const { if (this == input_block) return true; if (type == input_block->type) switch (type) { case ShaderBlock::TypeRenderBuffer: { RenderBufferShaderBlock *a = (RenderBufferShaderBlock *)this, *b = (RenderBufferShaderBlock *)input_block; return a->buffer == b->buffer; } case ShaderBlock::TypeTextureSampler: { TextureSamplerShaderBlock *a = (TextureSamplerShaderBlock *)this, *b = (TextureSamplerShaderBlock *)input_block; return (a->sampler_type == b->sampler_type) && a->input[0] && a->input[1] && b->input[0] && b->input[1] ? a->input[0]->IsEquivalent(b->input[0]) && a->input[1]->IsEquivalent(b->input[1]) : false; } case ShaderBlock::TypeTexture: { TextureShaderBlock *a = (TextureShaderBlock *)this, *b = (TextureShaderBlock *)input_block; return a->texture == b->texture; } case ShaderBlock::TypeGeometryUV: { GeometryUVShaderBlock *a = (GeometryUVShaderBlock *)this, *b = (GeometryUVShaderBlock *)input_block; return a->channel == b->channel; } case ShaderBlock::TypeMaterialParam: { MaterialParamShaderBlock *a = (MaterialParamShaderBlock *)this, *b = (MaterialParamShaderBlock *)input_block; return a->param == b->param; } case ShaderBlock::TypeClock: case ShaderBlock::TypeScreenUV: case ShaderBlock::TypeViewVector: case ShaderBlock::TypeViewport: case ShaderBlock::TypeNormalViewMatrix: case ShaderBlock::TypeNormalMatrix: case ShaderBlock::TypeModelViewMatrix: case ShaderBlock::TypeModelMatrix: case ShaderBlock::TypeGeometryVertex: case ShaderBlock::TypeGeometrySkinning: case ShaderBlock::TypeGeometryNormal: case ShaderBlock::TypeGeometryVertexColor: case ShaderBlock::TypeGeometryTangentFrame: return true; } return false; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ int UnpackColorToVectorShaderBlock::GetOutputType() const { return !input[0] ? ShaderInput::NoData : input[0]->GetOutputType(); } int PackVectorToColorShaderBlock::GetOutputType() const { return !input[0] ? ShaderInput::NoData : input[0]->GetOutputType(); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ int MixOperatorShaderBlock::GetOutputType() const { return (!input[0] || !input[1] || !input[2] || (input[0]->GetOutputType() != input[1]->GetOutputType()) || (input[2]->GetOutputType() != ShaderInput::Float)) ? ShaderInput::NoData : input[0]->GetOutputType(); } int DotOperatorShaderBlock::GetOutputType() const { return (!input[0] || !input[1] || (input[0]->GetOutputType() != input[1]->GetOutputType())) ? ShaderInput::NoData : ShaderInput::Float; } int CrossOperatorShaderBlock::GetOutputType() const { return (!input[0] || !input[1] || ((input[0]->GetOutputType() != input[1]->GetOutputType()) && (input[0]->GetOutputType() != ShaderInput::Vector3))) ? ShaderInput::NoData : ShaderInput::Vector3; } int AddOperatorShaderBlock::GetOutputType() const { return (!input[0] || !input[1] || (input[0]->GetOutputType() != input[1]->GetOutputType())) ? ShaderInput::NoData : input[0]->GetOutputType(); } int SubOperatorShaderBlock::GetOutputType() const { return (!input[0] || !input[1] || (input[0]->GetOutputType() != input[1]->GetOutputType())) ? ShaderInput::NoData : input[0]->GetOutputType(); } int DivOperatorShaderBlock::GetOutputType() const { return (!input[0] || !input[1] || (input[0]->GetOutputType() != input[1]->GetOutputType())) ? ShaderInput::NoData : input[0]->GetOutputType(); } int MulOperatorShaderBlock::GetOutputType() const { if (!input[0] || !input[1]) return ShaderInput::NoData; int type_0 = input[0]->GetOutputType(), type_1 = input[1]->GetOutputType(); if (type_0 > type_1) { int tmp = type_0; type_0 = type_1; type_1 = tmp; } // Switch on largest type. switch (type_1) { case ShaderInput::Matrix3: return (type_0 != ShaderInput::Vector3) ? ShaderInput::NoData : ShaderInput::Vector3; case ShaderInput::Matrix4: return (type_0 != ShaderInput::Vector4) ? ShaderInput::NoData : ShaderInput::Vector4; case ShaderInput::Float: case ShaderInput::Vector2: case ShaderInput::Vector3: case ShaderInput::Vector4: return (type_0 != type_1) ? ShaderInput::NoData : type_0; } return ShaderInput::NoData; } int ClampShaderBlock::GetOutputType() const { if (!input[0] || !input[1] || !input[2]) return ShaderInput::NoData; int type[3] = { input[0]->GetOutputType(), input[1]->GetOutputType(), input[2]->GetOutputType() }; if (type[1] != type[2]) // min/max must match. return ShaderInput::NoData; if (type[0] != type[1]) return ShaderInput::NoData; // input and min/max types must match. return type[0]; } int NormalizeOperatorShaderBlock::GetOutputType() const { return !input[0] ? ShaderInput::NoData : input[0]->GetOutputType(); } //------------------------------------------------------------------------------ //----------------------------------------------------------- int SwizzleShaderBlock::GetOutputType() const //----------------------------------------------------------- { if (!input[0] || (input[0]->GetOutputType() == ShaderInput::NoData)) return ShaderInput::NoData; int output_count = 0; for (int n = 0; n < 4; ++n) if (swizzle[n] != SwizzleNone) output_count++; switch (output_count) { case 1: return ShaderInput::Float; case 2: return ShaderInput::Vector2; case 3: return ShaderInput::Vector3; case 4: return ShaderInput::Vector4; } return ShaderInput::NoData; } //--------------------------------------------------------- int BuildShaderBlock::GetOutputType() const //--------------------------------------------------------- { int output_count = 0; for (int n = 0; n < 4; ++n) switch (build[n]) { case BuildZero: case BuildOne: output_count++; break; default: if (!input[n]) n = 4; else { if (input[n]->GetOutputType() == ShaderInput::NoData) return ShaderInput::NoData; output_count++; } break; } switch (output_count) { case 1: return ShaderInput::Float; case 2: return ShaderInput::Vector2; case 3: return ShaderInput::Vector3; case 4: return ShaderInput::Vector4; } return ShaderInput::NoData; } int CosinusShaderBlock::GetOutputType() const { return ShaderInput::Float; } int SinusShaderBlock::GetOutputType() const { return ShaderInput::Float; } int PowShaderBlock::GetOutputType() const { return ShaderInput::Float; } int AbsShaderBlock::GetOutputType() const { return !input[0] ? ShaderInput::NoData : input[0]->GetOutputType(); } int GeometryVertexShaderBlock::GetOutputType() const { return ShaderInput::Vector4; } int GeometryUVShaderBlock::GetOutputType() const { return ShaderInput::Vector2; } int GeometryNormalShaderBlock::GetOutputType() const { return ShaderInput::Vector3; } int GeometrySkinningShaderBlock::GetOutputType() const { return ShaderInput::Matrix4; } int GeometryVertexColorShaderBlock::GetOutputType() const { return ShaderInput::Vector3; } int GeometryTangentFrameShaderBlock::GetOutputType() const { return ShaderInput::Matrix3; } int RenderBufferShaderBlock::GetOutputType() const { return ShaderInput::Texture2D; } int TextureShaderBlock::GetOutputType() const { return ShaderInput::Texture2D; } int TextureSamplerShaderBlock::GetOutputType() const { return (input[0] && input[1]) ? ShaderInput::Vector4 : ShaderInput::NoData; } int ConstantShaderBlock::GetOutputType() const { return constant_type; } int ColorShaderBlock::GetOutputType() const { return ShaderInput::Vector4; } int MaterialParamShaderBlock::GetOutputType() const { switch (param) { case MaterialGlossiness: case MaterialOpacity: case MaterialReflection: return ShaderInput::Float; } return ShaderInput::Vector4; } int MaterialTextureShaderBlock::GetOutputType() const { return ShaderInput::Texture2D; } int ScreenUVShaderBlock::GetOutputType() const { return ShaderInput::Vector2; } int ViewVectorShaderBlock::GetOutputType() const { return ShaderInput::Vector3; } int ViewportShaderBlock::GetOutputType() const { return ShaderInput::Vector4; } int NormalViewMatrixShaderBlock::GetOutputType() const { return ShaderInput::Matrix3; } int NormalMatrixShaderBlock::GetOutputType() const { return ShaderInput::Matrix3; } int ModelViewMatrixShaderBlock::GetOutputType() const { return ShaderInput::Matrix4; } int ModelMatrixShaderBlock::GetOutputType() const { return ShaderInput::Matrix4; } int ClockShaderBlock::GetOutputType() const { return ShaderInput::Float; }