From a92ea1ffab177f1f21214fa37da61e28e512a4ba Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 29 Nov 2025 08:15:55 +0000 Subject: [PATCH] vertex position node Cross api support for vertex positions matrixmultiplyop added for multiplying matrix with other types automatically expands or shortens vec types to suit the matrix Added identity to the matrix initialization op. --- .../source/shaderGen/NODE/shaderGenNodes.cpp | 252 +++++++++++++++--- Engine/source/shaderGen/NODE/shaderGenNodes.h | 27 ++ Engine/source/shaderGen/shaderFeature.cpp | 67 +++++ Engine/source/shaderGen/shaderOp.cpp | 113 +++++++- Engine/source/shaderGen/shaderOp.h | 15 +- 5 files changed, 418 insertions(+), 56 deletions(-) diff --git a/Engine/source/shaderGen/NODE/shaderGenNodes.cpp b/Engine/source/shaderGen/NODE/shaderGenNodes.cpp index 8634bc32d..2ef78ab47 100644 --- a/Engine/source/shaderGen/NODE/shaderGenNodes.cpp +++ b/Engine/source/shaderGen/NODE/shaderGenNodes.cpp @@ -15,11 +15,13 @@ #include "materials/materialFeatureTypes.h" +ImplementFeatureType(SNF_VertexPosition, U32(-1), -1, false); ImplementFeatureType(SNF_DefaultTexCoord, U32(-1), -1, false); ImplementFeatureType(SNF_TextureFeature, U32(-1), -1, false); ImplementFeatureType(SNF_NormalMapFeature, U32(-1), -1, false); ImplementEnumType(ShaderNodeFeature_enum, "Shader node features. Each of thes relates to a specific node for generating a shader.\n\n") + { ShaderNodeFeature_enum::eSNF_VertexPosition, "SNF_VertexPosition", "Setup vertex position." }, { ShaderNodeFeature_enum::eSNF_DefaultTexCoord, "SNF_DefaultTexCoord", "Setup the default texcoord." }, { ShaderNodeFeature_enum::eSNF_TextureFeature, "SNF_TextureFeature", "Sample a Texture - Params: (string,string,GFXSamplerStateData,bool)." }, { ShaderNodeFeature_enum::eSNF_NormalMapFeature,"SNF_NormalMapFeature", "Convert a texture to a normalmap - Params: (string,float,bool,bool)." }, @@ -29,6 +31,7 @@ namespace { void register_node_features(GFXAdapterType type) { + FEATUREMGR->registerFeature(SNF_VertexPosition, new NodeVertexPositionFeature); FEATUREMGR->registerFeature(SNF_DefaultTexCoord, new DefaultTexcoordFeature); FEATUREMGR->registerFeature(SNF_TextureFeature, new TextureFeature, TextureFeature::createFunction); FEATUREMGR->registerFeature(SNF_NormalMapFeature, new NormalMapFeature, NormalMapFeature::createFunction); @@ -51,6 +54,125 @@ MODULE_INIT MODULE_END; +Var* ShaderFeatureNode::getObjTrans(Vector& componentList, + bool useInstancing, + MultiLine* meta) +{ + Var* objTrans = (Var*)LangElement::find("objTrans"); + if (objTrans) + return objTrans; + + if (useInstancing) + { + ShaderConnector* vertStruct = dynamic_cast(componentList[C_VERT_STRUCT]); + Var* instObjTrans = vertStruct->getElement(RT_TEXCOORD, 4, 4); + instObjTrans->setStructName("IN"); + instObjTrans->setName("inst_objectTrans"); + + mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 0); + mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 1); + mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 2); + mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 3); + + objTrans = new Var; + objTrans->setType(GFXSCT_Float4x4); + objTrans->setName("objTrans"); + + Vector matrixVars; + matrixVars.push_back(instObjTrans); + meta->addStatement(new GenOp(" @ = @;", new DecOp(objTrans), new MatrixInitializeOp(objTrans, matrixVars))); + } + else + { + objTrans = new Var; + objTrans->setType(GFXSCT_Float4x4); + objTrans->setName("objTrans"); + objTrans->uniform = true; + objTrans->constSortPos = cspPrimitive; + } + + return objTrans; +} + +Var* ShaderFeatureNode::getModelView( Vector& componentList, + bool useInstancing, + MultiLine* meta) +{ + Var* modelview = (Var*)LangElement::find("modelview"); + if (modelview) + return modelview; + + if (useInstancing) + { + Var* objTrans = getObjTrans(componentList, useInstancing, meta); + + Var* viewProj = (Var*)LangElement::find("viewProj"); + if (!viewProj) + { + viewProj = new Var; + viewProj->setType(GFXSCT_Float4x4); + viewProj->setName("viewProj"); + viewProj->uniform = true; + viewProj->constSortPos = cspPass; + } + + modelview = new Var; + modelview->setType(GFXSCT_Float4x4); + modelview->setName("modelview"); + meta->addStatement(new GenOp(" @ = @; // Instancing!\r\n", new DecOp(modelview), new MatrixMultiplyOp(viewProj, objTrans))); + } + else + { + modelview = new Var; + modelview->setType(GFXSCT_Float4x4); + modelview->setName("modelview"); + modelview->uniform = true; + modelview->constSortPos = cspPrimitive; + } + + return modelview; +} + +Var* ShaderFeatureNode::getWorldView( Vector& componentList, + bool useInstancing, + MultiLine* meta) +{ + Var* worldView = (Var*)LangElement::find("worldViewOnly"); + if (worldView) + return worldView; + + if (useInstancing) + { + Var* objTrans = getObjTrans(componentList, useInstancing, meta); + + Var* worldToCamera = (Var*)LangElement::find("worldToCamera"); + if (!worldToCamera) + { + worldToCamera = new Var; + worldToCamera->setType(GFXSCT_Float4x4); + worldToCamera->setName("worldToCamera"); + worldToCamera->uniform = true; + worldToCamera->constSortPos = cspPass; + } + + worldView = new Var; + worldView->setType(GFXSCT_Float4x4); + worldView->setName("worldViewOnly"); + + meta->addStatement(new GenOp(" @ = @; // Instancing!\r\n", new DecOp(worldView), new MatrixMultiplyOp(worldToCamera, objTrans) )); + } + else + { + worldView = new Var; + worldView->setType(GFXSCT_Float4x4); + worldView->setName("worldViewOnly"); + worldView->uniform = true; + worldView->constSortPos = cspPrimitive; + } + + return worldView; +} + void ShaderFeatureNode::setupTextureSample( const String& samplerName, GFXShaderConstType samplerType, Vector& componentList, @@ -69,43 +191,7 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName, Var* samplerVar = dynamic_cast(LangElement::find(sampVarName)); - Var* textureVar; - - if (!isGL) // HLSL requires both Texture + SamplerState - { - if (!samplerVar) - { - samplerVar = new Var; - samplerVar->setType(isComparison ? "SamplerComparisonState" : "SamplerState"); - samplerVar->setName(sampVarName); - samplerVar->uniform = true; - samplerVar->sampler = true; - samplerVar->constNum = Var::getTexUnitNum(); - } - - textureVar = dynamic_cast(LangElement::find(texVarName)); - if (!textureVar) - { - textureVar = new Var; - textureVar->setType(LangElement::samplerTypeToString(samplerType)); // Texture2D, TextureCube, etc. - textureVar->setName(texVarName); - textureVar->uniform = true; - textureVar->texture = true; - textureVar->constNum = samplerVar->constNum; - } - } - else - { - if (!samplerVar) - { - samplerVar = new Var; - samplerVar->setType(LangElement::samplerTypeToString(samplerType)); - samplerVar->setName(sampVarName); - samplerVar->uniform = true; - samplerVar->sampler = true; - samplerVar->constNum = Var::getTexUnitNum(); - } - } + Var* textureVar = NULL; // The sampled color variable (e.g. "samplerName_col") should always be new but just in case Var* sampledColor = (Var*)LangElement::find(resultVarName); @@ -123,6 +209,16 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName, if (isGL) { // ---------------- GLSL Sampling ---------------- + if (!samplerVar) + { + samplerVar = new Var; + samplerVar->setType(LangElement::constTypeToString(samplerType, true)); + samplerVar->setName(sampVarName); + samplerVar->uniform = true; + samplerVar->sampler = true; + samplerVar->constNum = Var::getTexUnitNum(); + } + if (isComparison) { if (useGather) @@ -149,6 +245,27 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName, else { // ---------------- HLSL Sampling ---------------- + if (!samplerVar) + { + samplerVar = new Var; + samplerVar->setType(isComparison ? "SamplerComparisonState" : "SamplerState"); + samplerVar->setName(sampVarName); + samplerVar->uniform = true; + samplerVar->sampler = true; + samplerVar->constNum = Var::getTexUnitNum(); + } + + textureVar = dynamic_cast(LangElement::find(texVarName)); + if (!textureVar) + { + textureVar = new Var; + textureVar->setType(LangElement::constTypeToString(samplerType, true)); // Texture2D, TextureCube, etc. + textureVar->setName(texVarName); + textureVar->uniform = true; + textureVar->texture = true; + textureVar->constNum = samplerVar->constNum; + } + if (isComparison) { if (useGather) @@ -192,8 +309,7 @@ Var* ShaderFeatureNode::getOutTexCoord(const char* name, GFXShaderConstType type // Statement allows for casting of different types which // eliminates vector truncation problems. - String statement = String::ToString(" @ = (%s)@;\r\n", type); - meta->addStatement(new GenOp(statement, texCoord, inTex)); + meta->addStatement(new GenOp(" @ = (@)@;\r\n", texCoord, new TypeOp(type), inTex)); } @@ -265,6 +381,57 @@ LangElement* ShaderFeatureNode::assignColor(LangElement* elem, Material::BlendOp return NULL; } +//-------------------------------------------------------- +// Vertex position. +//-------------------------------------------------------- + +void NodeVertexPositionFeature::processVert(Vector& componentList, const MaterialFeatureData& fd) +{ + // First check for an input position from a previous feature + // then look for the default vertex position. + Var* inPosition = (Var*)LangElement::find("inPosition"); + if (!inPosition) + inPosition = (Var*)LangElement::find("position"); + + const bool glsl = (GFX->getAdapterType() == OpenGL); + + // grab connector position + ShaderConnector* connectComp = dynamic_cast(componentList[C_CONNECTOR]); + Var* outPosition = connectComp->getElement( glsl ? RT_POSITION : RT_SVPOSITION); + + if (glsl) + { + outPosition->setName("gl_Position"); + } + else + { + outPosition->setName("hpos"); + outPosition->setStructName("OUT"); + } + + MultiLine* meta = new MultiLine; + + Var* modelview = getModelView(componentList, fd.features[MFT_UseInstancing], meta); + + meta->addStatement(new GenOp(" @ = @;\r\n", outPosition, new MatrixMultiplyOp( modelview, new CastOp(inPosition, GFXSCT_Float4, "x;y;z")))); + + output = meta; +} + +void NodeVertexPositionFeature::processPix(Vector& componentList, const MaterialFeatureData& fd) +{ + const bool glsl = (GFX->getAdapterType() == OpenGL); + + if (!glsl) + { + // grab connector position + ShaderConnector* connectComp = dynamic_cast(componentList[C_CONNECTOR]); + Var* outPosition = connectComp->getElement(RT_SVPOSITION); + outPosition->setName("vpos"); + outPosition->setStructName("IN"); + } +} + //-------------------------------------------------------- // Setup the default texcoord //-------------------------------------------------------- @@ -352,10 +519,10 @@ void NormalMapFeature::processPix(Vector& componentList, const meta->addStatement(expandNormalMap(sampledColor, tempNormDecl, tempNorm, fd)); meta->addStatement( - new GenOp(" @.xy *= float2(@, @);\r\n", tempNorm, params->flipX ? -1.0f : 1.0f, params->flipY ? -1.0f : 1.0f)); + new GenOp(" @.xy *= @(@, @);\r\n", tempNorm, new TypeOp(GFXSCT_Float2), params->flipX ? -1.0f : 1.0f, params->flipY ? -1.0f : 1.0f)); - meta->addStatement(new GenOp(" @.xyz = normalize( float3( @.xy * @, @.z ) );\r\n", - tempNorm, tempNorm, params->strength, tempNorm)); + meta->addStatement(new GenOp(" @.xyz = normalize( @( @.xy * @, @.z ) );\r\n", + tempNorm, new TypeOp(GFXSCT_Float3), tempNorm, params->strength, tempNorm)); // write back into our known variable. meta->addStatement(new GenOp(" @ = @;\r\n", sampledColor, tempNorm)); @@ -363,3 +530,4 @@ void NormalMapFeature::processPix(Vector& componentList, const output = meta; } + diff --git a/Engine/source/shaderGen/NODE/shaderGenNodes.h b/Engine/source/shaderGen/NODE/shaderGenNodes.h index b1082f3d8..d93f3ca80 100644 --- a/Engine/source/shaderGen/NODE/shaderGenNodes.h +++ b/Engine/source/shaderGen/NODE/shaderGenNodes.h @@ -20,6 +20,7 @@ #include "gfx/gfxAPI.h" #endif +DeclareFeatureType(SNF_VertexPosition); DeclareFeatureType(SNF_DefaultTexCoord); DeclareFeatureType(SNF_TextureFeature); DeclareFeatureType(SNF_NormalMapFeature); @@ -29,6 +30,7 @@ DeclareFeatureType(SNF_NormalMapFeature); /// enum ShaderNodeFeature_enum { + eSNF_VertexPosition, eSNF_DefaultTexCoord, eSNF_TextureFeature, eSNF_NormalMapFeature, @@ -39,6 +41,18 @@ DefineEnumType(ShaderNodeFeature_enum); class ShaderFeatureNode : public ShaderFeature { public: + + /// + Var* getObjTrans( Vector& componentList, + bool useInstancing, + MultiLine* meta); + + Var* getModelView(Vector& componentList, + bool useInstancing, + MultiLine* meta); + + Var* getWorldView(Vector& componentList, bool useInstancing, MultiLine* meta); + void setupTextureSample(const String& samplerName, GFXShaderConstType samplerType, Vector& componentList, @@ -58,6 +72,19 @@ public: LangElement* assignColor(LangElement* elem, Material::BlendOp blend, LangElement* lerpElem = NULL, ShaderFeature::OutputTarget outputTarget = ShaderFeature::DefaultTarget) override; }; +class NodeVertexPositionFeature : public ShaderFeatureNode +{ + void processVert(Vector& componentList, + const MaterialFeatureData& fd) override; + + void processPix(Vector& componentList, + const MaterialFeatureData& fd) override; + + String getName() override + { + return "NodeVertexPositionFeature"; + } +}; class DefaultTexcoordFeature : public ShaderFeatureNode { diff --git a/Engine/source/shaderGen/shaderFeature.cpp b/Engine/source/shaderGen/shaderFeature.cpp index 00bbd7c9d..6dfd7b553 100644 --- a/Engine/source/shaderGen/shaderFeature.cpp +++ b/Engine/source/shaderGen/shaderFeature.cpp @@ -38,6 +38,73 @@ void ShaderFeature::addDependency( const ShaderDependency *dependsOn ) mDependencies.push_back( dependsOn ); } +Var* ShaderFeature::getVertTexCoord(const String& name) +{ + Var* inTex = NULL; + + for (U32 i = 0; i < LangElement::elementList.size(); i++) + { + if (!String::compare((char*)LangElement::elementList[i]->name, name.c_str())) + { + inTex = dynamic_cast(LangElement::elementList[i]); + if (inTex) + { + // NOTE: This used to do this check... + // + // String::compare( (char*)inTex->structName, "IN" ) + // + // ... to ensure that the var was from the input + // vertex structure, but this kept some features + // ( ie. imposter vert ) from decoding their own + // coords for other features to use. + // + // If we run into issues with collisions between + // IN vars and local vars we may need to revise. + + break; + } + } + } + + return inTex; +} + +LangElement* ShaderFeature::expandNormalMap(LangElement* sampleNormalOp, LangElement* normalDecl, LangElement* normalVar, const MaterialFeatureData& fd) +{ + MultiLine* meta = new MultiLine; + const bool hasBc3 = fd.features.hasFeature(MFT_IsBC3nm, getProcessIndex()); + const bool hasBc5 = fd.features.hasFeature(MFT_IsBC5nm, getProcessIndex()); + + if (hasBc3 || hasBc5) + { + if (fd.features[MFT_ImposterVert]) + { + // The imposter system uses object space normals and + // encodes them with the z axis in the alpha component. + meta->addStatement(new GenOp(" @ = @( normalize( @.xyw * 2.0 - 1.0 ), 0.0 ); // Obj DXTnm\r\n", normalDecl, new TypeOp(GFXSCT_Float4), sampleNormalOp)); + } + else if (hasBc3) + { + // BC3 Swizzle trick + meta->addStatement(new GenOp(" @ = @( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, new TypeOp(GFXSCT_Float4), sampleNormalOp)); + meta->addStatement(new GenOp(" @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar)); + } + else if (hasBc5) + { + // BC5 + meta->addStatement(new GenOp(" @ = @( @.gr * 2.0 - 1.0, 0.0, 0.0 ); // bc5nm\r\n", normalDecl, new TypeOp(GFXSCT_Float4), sampleNormalOp)); + meta->addStatement(new GenOp(" @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // bc5nm\r\n", normalVar, normalVar, normalVar)); + } + } + else + { + meta->addStatement(new GenOp(" @ = @;\r\n", normalDecl, sampleNormalOp)); + meta->addStatement(new GenOp(" @.xyz = @.xyz * 2.0 - 1.0;\r\n", normalVar, normalVar)); + } + + return meta; +} + ShaderFeature::Resources ShaderFeature::getResources( const MaterialFeatureData &fd ) { Resources temp; diff --git a/Engine/source/shaderGen/shaderOp.cpp b/Engine/source/shaderGen/shaderOp.cpp index 80e467080..8a514f21c 100644 --- a/Engine/source/shaderGen/shaderOp.cpp +++ b/Engine/source/shaderGen/shaderOp.cpp @@ -26,7 +26,7 @@ #include "shaderOp.h" -bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo) +bool ShaderOp::resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo) { outVar = nullptr; outInfo = nullptr; @@ -35,18 +35,18 @@ bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& o if (Var* v = dynamic_cast(elem)) { outVar = v; - outInfo = LangElement::getTypeInfo(LangElement::stringToConstType((const char*)v->type)); + outInfo = getTypeInfo(stringToConstType((const char*)v->type)); return outInfo != nullptr; } // INDEX OP: arrVar[index] if (IndexOp* idx = dynamic_cast(elem)) { - Var* arr = idx->arrVar; + Var* arr = dynamic_cast(idx->mInput[0]); if (!arr) return false; - const ShaderTypeInfo* arrInfo = LangElement::getTypeInfo(LangElement::stringToConstType((const char*)arr->type)); + const ShaderTypeInfo* arrInfo = getTypeInfo(stringToConstType((const char*)arr->type)); if (!arrInfo) return false; @@ -56,10 +56,23 @@ bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& o return true; } + if (CastOp* cast = dynamic_cast(elem)) + { + Var* castVar = dynamic_cast(cast->mInput[0]); + if (!castVar) + return false; + + const ShaderTypeInfo* castInfo = getTypeInfo(cast->mTargetType);// get the casts target type. + if (!castInfo) + return false; + + outVar = castVar; + outInfo = castInfo; + } + return false; } - //************************************************************************** // Shader Operations //************************************************************************** @@ -117,9 +130,8 @@ void EchoOp::print( Stream &stream ) //************************************************************************** // Index operation //************************************************************************** -IndexOp::IndexOp( Var* var, U32 index ) : Parent( NULL, NULL ) +IndexOp::IndexOp( Var* var, U32 index ) : Parent(var, NULL ) { - arrVar = var; // need to keep hold of it for casts. mInput[0] = var; mIndex = index; } @@ -266,13 +278,13 @@ void CastOp::print(Stream& stream) const ShaderTypeInfo* dstInfo = getTypeInfo(mTargetType); // no info? types match? nothing to do. - if (!srcInfo || !dstInfo || (srcInfo->type == dstInfo->type)) + if (!srcInfo || !dstInfo) { srcElem->print(stream); // print something.... return; } - bool glsl = (GFX->getAdapterType() == OpenGL); + const bool glsl = (GFX->getAdapterType() == OpenGL); const char* dstName = glsl ? dstInfo->glslName : dstInfo->hlslName; U32 srcSize = srcInfo->cols; @@ -322,7 +334,7 @@ void CastOp::print(Stream& stream) } // vector -> vector widening - if (srcSize < dstSize) + if (srcSize <= dstSize) { WRITESTR(dstName); WRITESTR("("); @@ -452,7 +464,18 @@ void MatrixInitializeOp::print(Stream& stream) // If not enough elements → pad with zeros while (count < matSize) { - WRITESTR("0"); + U32 row = count / cols; + U32 col = count % cols; + + if (row == col) + { + WRITESTR("1"); + } + else + { + WRITESTR("0"); + } + count++; if (count < matSize) @@ -472,3 +495,71 @@ void MatrixInitializeOp::print(Stream& stream) } } +MatrixMultiplyOp::MatrixMultiplyOp(LangElement* left, LangElement* right) : Parent(left, right) +{ + mInput[0] = left; + mInput[1] = right; +} + +void MatrixMultiplyOp::print(Stream& stream) +{ + LangElement* leftElem = mInput[0]; + Var* leftVar = nullptr; + const ShaderTypeInfo* leftInfo = nullptr; + + if (!resolveSourceType(leftElem, leftVar, leftInfo)) + { + return; + } + + LangElement* rightElem = mInput[0]; + Var* rightVar = nullptr; + const ShaderTypeInfo* rightInfo = nullptr; + + if (!resolveSourceType(rightElem, rightVar, rightInfo)) + { + return; + } + + if (leftInfo->isMatrix() && rightInfo->isVector()) + { + if (rightInfo->cols != leftInfo->cols) + { + rightElem = new CastOp(rightVar, (GFXShaderConstType)(GFXSCT_Float + (leftInfo->cols - 1))); + } + } + + if (leftInfo->isVector() && rightInfo->isMatrix()) + { + if (rightInfo->cols != leftInfo->cols) + { + leftElem = new CastOp(leftVar, (GFXShaderConstType)(GFXSCT_Float + (rightInfo->cols - 1))); + } + } + + else if (leftInfo->isMatrix() && rightInfo->isMatrix()) + { + if (leftInfo->cols != rightInfo->rows) + Con::warnf("MatrixMultiplyOp: incompatible matrices: (%dx%d) × (%dx%d)", + leftInfo->rows, leftInfo->cols, + rightInfo->rows, rightInfo->cols); + } + + const bool glsl = (GFX->getAdapterType() == OpenGL); + + if (!glsl) + { + WRITESTR("mul("); + leftElem->print(stream); + WRITESTR(", "); + rightElem->print(stream); + WRITESTR(")"); + } + else + { + leftElem->print(stream); + WRITESTR(" * "); + rightElem->print(stream); + } + +} diff --git a/Engine/source/shaderGen/shaderOp.h b/Engine/source/shaderGen/shaderOp.h index 8a42168dd..7fb3da152 100644 --- a/Engine/source/shaderGen/shaderOp.h +++ b/Engine/source/shaderGen/shaderOp.h @@ -45,7 +45,7 @@ */ //************************************************************************** -bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo); + ///************************************************************************** /// Shader operation base class @@ -56,6 +56,7 @@ protected: LangElement * mInput[2]; public: + bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo); ShaderOp( LangElement *in1, LangElement *in2 ); }; @@ -118,7 +119,6 @@ class IndexOp : public ShaderOp typedef ShaderOp Parent; U32 mIndex; public: - Var* arrVar; IndexOp( Var* var, U32 index ); void print( Stream &stream ) override; }; @@ -185,10 +185,10 @@ public: class CastOp : public ShaderOp { typedef ShaderOp Parent; - GFXShaderConstType mTargetType; Vector mSwizzle; // "x", "y", "z", "w" Vector mFillValues; // "0", "0", "0", "1" public: + GFXShaderConstType mTargetType; CastOp( LangElement* srcVar, GFXShaderConstType type, const char* swizzleStr = "x;y;z;w", @@ -243,4 +243,13 @@ public: */ //---------------------------------------------------------------------------- +class MatrixMultiplyOp : public ShaderOp +{ + typedef ShaderOp Parent; +public: + MatrixMultiplyOp(LangElement* left, LangElement* right); + + void print(Stream& stream) override; +}; + #endif // _SHADEROP_H_