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.
This commit is contained in:
marauder2k7 2025-11-29 08:15:55 +00:00
parent cff7a8060d
commit a92ea1ffab
5 changed files with 418 additions and 56 deletions

View file

@ -15,11 +15,13 @@
#include "materials/materialFeatureTypes.h" #include "materials/materialFeatureTypes.h"
ImplementFeatureType(SNF_VertexPosition, U32(-1), -1, false);
ImplementFeatureType(SNF_DefaultTexCoord, U32(-1), -1, false); ImplementFeatureType(SNF_DefaultTexCoord, U32(-1), -1, false);
ImplementFeatureType(SNF_TextureFeature, U32(-1), -1, false); ImplementFeatureType(SNF_TextureFeature, U32(-1), -1, false);
ImplementFeatureType(SNF_NormalMapFeature, 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") 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_DefaultTexCoord, "SNF_DefaultTexCoord", "Setup the default texcoord." },
{ ShaderNodeFeature_enum::eSNF_TextureFeature, "SNF_TextureFeature", "Sample a Texture - Params: (string,string,GFXSamplerStateData,bool)." }, { 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)." }, { 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) void register_node_features(GFXAdapterType type)
{ {
FEATUREMGR->registerFeature(SNF_VertexPosition, new NodeVertexPositionFeature);
FEATUREMGR->registerFeature(SNF_DefaultTexCoord, new DefaultTexcoordFeature); FEATUREMGR->registerFeature(SNF_DefaultTexCoord, new DefaultTexcoordFeature);
FEATUREMGR->registerFeature(SNF_TextureFeature, new TextureFeature, TextureFeature::createFunction); FEATUREMGR->registerFeature(SNF_TextureFeature, new TextureFeature, TextureFeature::createFunction);
FEATUREMGR->registerFeature(SNF_NormalMapFeature, new NormalMapFeature, NormalMapFeature::createFunction); FEATUREMGR->registerFeature(SNF_NormalMapFeature, new NormalMapFeature, NormalMapFeature::createFunction);
@ -51,6 +54,125 @@ MODULE_INIT
MODULE_END; MODULE_END;
Var* ShaderFeatureNode::getObjTrans(Vector<ShaderComponent*>& componentList,
bool useInstancing,
MultiLine* meta)
{
Var* objTrans = (Var*)LangElement::find("objTrans");
if (objTrans)
return objTrans;
if (useInstancing)
{
ShaderConnector* vertStruct = dynamic_cast<ShaderConnector*>(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<LangElement*> 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<ShaderComponent*>& 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<ShaderComponent*>& 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, void ShaderFeatureNode::setupTextureSample( const String& samplerName,
GFXShaderConstType samplerType, GFXShaderConstType samplerType,
Vector<ShaderComponent*>& componentList, Vector<ShaderComponent*>& componentList,
@ -69,43 +191,7 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName,
Var* samplerVar = dynamic_cast<Var*>(LangElement::find(sampVarName)); Var* samplerVar = dynamic_cast<Var*>(LangElement::find(sampVarName));
Var* textureVar; Var* textureVar = NULL;
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<Var*>(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();
}
}
// The sampled color variable (e.g. "samplerName_col") should always be new but just in case // The sampled color variable (e.g. "samplerName_col") should always be new but just in case
Var* sampledColor = (Var*)LangElement::find(resultVarName); Var* sampledColor = (Var*)LangElement::find(resultVarName);
@ -123,6 +209,16 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName,
if (isGL) if (isGL)
{ {
// ---------------- GLSL Sampling ---------------- // ---------------- 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 (isComparison)
{ {
if (useGather) if (useGather)
@ -149,6 +245,27 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName,
else else
{ {
// ---------------- HLSL Sampling ---------------- // ---------------- 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<Var*>(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 (isComparison)
{ {
if (useGather) if (useGather)
@ -192,8 +309,7 @@ Var* ShaderFeatureNode::getOutTexCoord(const char* name, GFXShaderConstType type
// Statement allows for casting of different types which // Statement allows for casting of different types which
// eliminates vector truncation problems. // eliminates vector truncation problems.
String statement = String::ToString(" @ = (%s)@;\r\n", type); meta->addStatement(new GenOp(" @ = (@)@;\r\n", texCoord, new TypeOp(type), inTex));
meta->addStatement(new GenOp(statement, texCoord, inTex));
} }
@ -265,6 +381,57 @@ LangElement* ShaderFeatureNode::assignColor(LangElement* elem, Material::BlendOp
return NULL; return NULL;
} }
//--------------------------------------------------------
// Vertex position.
//--------------------------------------------------------
void NodeVertexPositionFeature::processVert(Vector<ShaderComponent*>& 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<ShaderConnector*>(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<ShaderComponent*>& componentList, const MaterialFeatureData& fd)
{
const bool glsl = (GFX->getAdapterType() == OpenGL);
if (!glsl)
{
// grab connector position
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
Var* outPosition = connectComp->getElement(RT_SVPOSITION);
outPosition->setName("vpos");
outPosition->setStructName("IN");
}
}
//-------------------------------------------------------- //--------------------------------------------------------
// Setup the default texcoord // Setup the default texcoord
//-------------------------------------------------------- //--------------------------------------------------------
@ -352,10 +519,10 @@ void NormalMapFeature::processPix(Vector<ShaderComponent*>& componentList, const
meta->addStatement(expandNormalMap(sampledColor, tempNormDecl, tempNorm, fd)); meta->addStatement(expandNormalMap(sampledColor, tempNormDecl, tempNorm, fd));
meta->addStatement( 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", meta->addStatement(new GenOp(" @.xyz = normalize( @( @.xy * @, @.z ) );\r\n",
tempNorm, tempNorm, params->strength, tempNorm)); tempNorm, new TypeOp(GFXSCT_Float3), tempNorm, params->strength, tempNorm));
// write back into our known variable. // write back into our known variable.
meta->addStatement(new GenOp(" @ = @;\r\n", sampledColor, tempNorm)); meta->addStatement(new GenOp(" @ = @;\r\n", sampledColor, tempNorm));
@ -363,3 +530,4 @@ void NormalMapFeature::processPix(Vector<ShaderComponent*>& componentList, const
output = meta; output = meta;
} }

View file

@ -20,6 +20,7 @@
#include "gfx/gfxAPI.h" #include "gfx/gfxAPI.h"
#endif #endif
DeclareFeatureType(SNF_VertexPosition);
DeclareFeatureType(SNF_DefaultTexCoord); DeclareFeatureType(SNF_DefaultTexCoord);
DeclareFeatureType(SNF_TextureFeature); DeclareFeatureType(SNF_TextureFeature);
DeclareFeatureType(SNF_NormalMapFeature); DeclareFeatureType(SNF_NormalMapFeature);
@ -29,6 +30,7 @@ DeclareFeatureType(SNF_NormalMapFeature);
/// </summary> /// </summary>
enum ShaderNodeFeature_enum enum ShaderNodeFeature_enum
{ {
eSNF_VertexPosition,
eSNF_DefaultTexCoord, eSNF_DefaultTexCoord,
eSNF_TextureFeature, eSNF_TextureFeature,
eSNF_NormalMapFeature, eSNF_NormalMapFeature,
@ -39,6 +41,18 @@ DefineEnumType(ShaderNodeFeature_enum);
class ShaderFeatureNode : public ShaderFeature class ShaderFeatureNode : public ShaderFeature
{ {
public: public:
///
Var* getObjTrans( Vector<ShaderComponent*>& componentList,
bool useInstancing,
MultiLine* meta);
Var* getModelView(Vector<ShaderComponent*>& componentList,
bool useInstancing,
MultiLine* meta);
Var* getWorldView(Vector<ShaderComponent*>& componentList, bool useInstancing, MultiLine* meta);
void setupTextureSample(const String& samplerName, void setupTextureSample(const String& samplerName,
GFXShaderConstType samplerType, GFXShaderConstType samplerType,
Vector<ShaderComponent*>& componentList, Vector<ShaderComponent*>& componentList,
@ -58,6 +72,19 @@ public:
LangElement* assignColor(LangElement* elem, Material::BlendOp blend, LangElement* lerpElem = NULL, ShaderFeature::OutputTarget outputTarget = ShaderFeature::DefaultTarget) override; LangElement* assignColor(LangElement* elem, Material::BlendOp blend, LangElement* lerpElem = NULL, ShaderFeature::OutputTarget outputTarget = ShaderFeature::DefaultTarget) override;
}; };
class NodeVertexPositionFeature : public ShaderFeatureNode
{
void processVert(Vector<ShaderComponent*>& componentList,
const MaterialFeatureData& fd) override;
void processPix(Vector<ShaderComponent*>& componentList,
const MaterialFeatureData& fd) override;
String getName() override
{
return "NodeVertexPositionFeature";
}
};
class DefaultTexcoordFeature : public ShaderFeatureNode class DefaultTexcoordFeature : public ShaderFeatureNode
{ {

View file

@ -38,6 +38,73 @@ void ShaderFeature::addDependency( const ShaderDependency *dependsOn )
mDependencies.push_back( 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<Var*>(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 ) ShaderFeature::Resources ShaderFeature::getResources( const MaterialFeatureData &fd )
{ {
Resources temp; Resources temp;

View file

@ -26,7 +26,7 @@
#include "shaderOp.h" #include "shaderOp.h"
bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo) bool ShaderOp::resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo)
{ {
outVar = nullptr; outVar = nullptr;
outInfo = nullptr; outInfo = nullptr;
@ -35,18 +35,18 @@ bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& o
if (Var* v = dynamic_cast<Var*>(elem)) if (Var* v = dynamic_cast<Var*>(elem))
{ {
outVar = v; outVar = v;
outInfo = LangElement::getTypeInfo(LangElement::stringToConstType((const char*)v->type)); outInfo = getTypeInfo(stringToConstType((const char*)v->type));
return outInfo != nullptr; return outInfo != nullptr;
} }
// INDEX OP: arrVar[index] // INDEX OP: arrVar[index]
if (IndexOp* idx = dynamic_cast<IndexOp*>(elem)) if (IndexOp* idx = dynamic_cast<IndexOp*>(elem))
{ {
Var* arr = idx->arrVar; Var* arr = dynamic_cast<Var*>(idx->mInput[0]);
if (!arr) if (!arr)
return false; return false;
const ShaderTypeInfo* arrInfo = LangElement::getTypeInfo(LangElement::stringToConstType((const char*)arr->type)); const ShaderTypeInfo* arrInfo = getTypeInfo(stringToConstType((const char*)arr->type));
if (!arrInfo) if (!arrInfo)
return false; return false;
@ -56,10 +56,23 @@ bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& o
return true; return true;
} }
if (CastOp* cast = dynamic_cast<CastOp*>(elem))
{
Var* castVar = dynamic_cast<Var*>(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; return false;
} }
//************************************************************************** //**************************************************************************
// Shader Operations // Shader Operations
//************************************************************************** //**************************************************************************
@ -117,9 +130,8 @@ void EchoOp::print( Stream &stream )
//************************************************************************** //**************************************************************************
// Index operation // 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; mInput[0] = var;
mIndex = index; mIndex = index;
} }
@ -266,13 +278,13 @@ void CastOp::print(Stream& stream)
const ShaderTypeInfo* dstInfo = getTypeInfo(mTargetType); const ShaderTypeInfo* dstInfo = getTypeInfo(mTargetType);
// no info? types match? nothing to do. // no info? types match? nothing to do.
if (!srcInfo || !dstInfo || (srcInfo->type == dstInfo->type)) if (!srcInfo || !dstInfo)
{ {
srcElem->print(stream); // print something.... srcElem->print(stream); // print something....
return; return;
} }
bool glsl = (GFX->getAdapterType() == OpenGL); const bool glsl = (GFX->getAdapterType() == OpenGL);
const char* dstName = glsl ? dstInfo->glslName : dstInfo->hlslName; const char* dstName = glsl ? dstInfo->glslName : dstInfo->hlslName;
U32 srcSize = srcInfo->cols; U32 srcSize = srcInfo->cols;
@ -322,7 +334,7 @@ void CastOp::print(Stream& stream)
} }
// vector -> vector widening // vector -> vector widening
if (srcSize < dstSize) if (srcSize <= dstSize)
{ {
WRITESTR(dstName); WRITESTR(dstName);
WRITESTR("("); WRITESTR("(");
@ -452,7 +464,18 @@ void MatrixInitializeOp::print(Stream& stream)
// If not enough elements → pad with zeros // If not enough elements → pad with zeros
while (count < matSize) while (count < matSize)
{ {
WRITESTR("0"); U32 row = count / cols;
U32 col = count % cols;
if (row == col)
{
WRITESTR("1");
}
else
{
WRITESTR("0");
}
count++; count++;
if (count < matSize) 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);
}
}

View file

@ -45,7 +45,7 @@
*/ */
//************************************************************************** //**************************************************************************
bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo);
///************************************************************************** ///**************************************************************************
/// Shader operation base class /// Shader operation base class
@ -56,6 +56,7 @@ protected:
LangElement * mInput[2]; LangElement * mInput[2];
public: public:
bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo);
ShaderOp( LangElement *in1, LangElement *in2 ); ShaderOp( LangElement *in1, LangElement *in2 );
}; };
@ -118,7 +119,6 @@ class IndexOp : public ShaderOp
typedef ShaderOp Parent; typedef ShaderOp Parent;
U32 mIndex; U32 mIndex;
public: public:
Var* arrVar;
IndexOp( Var* var, U32 index ); IndexOp( Var* var, U32 index );
void print( Stream &stream ) override; void print( Stream &stream ) override;
}; };
@ -185,10 +185,10 @@ public:
class CastOp : public ShaderOp class CastOp : public ShaderOp
{ {
typedef ShaderOp Parent; typedef ShaderOp Parent;
GFXShaderConstType mTargetType;
Vector<String> mSwizzle; // "x", "y", "z", "w" Vector<String> mSwizzle; // "x", "y", "z", "w"
Vector<String> mFillValues; // "0", "0", "0", "1" Vector<String> mFillValues; // "0", "0", "0", "1"
public: public:
GFXShaderConstType mTargetType;
CastOp( LangElement* srcVar, CastOp( LangElement* srcVar,
GFXShaderConstType type, GFXShaderConstType type,
const char* swizzleStr = "x;y;z;w", 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_ #endif // _SHADEROP_H_