Hardware Skinning Support

- Supports GL, D3D9 & D3D11
- Extends vertex formats & shadergen to support blend indices and weights
- Adds basic support for using 4x3 matrices for shader constants
- Supports software fallback
This commit is contained in:
James Urquhart 2015-01-10 19:41:25 +00:00
parent 507c239a87
commit 3496c549b5
72 changed files with 2533 additions and 1327 deletions

View file

@ -101,6 +101,30 @@ Var * AppVertConnectorGLSL::getElement( RegisterType type,
return newVar;
}
case RT_BLENDINDICES:
{
Var *newVar = new Var;
newVar->constNum = mCurBlendIndicesElem;
mElementList.push_back(newVar);
char out[32];
dSprintf((char*)out, sizeof(out), "vBlendIndex%d", mCurBlendIndicesElem);
mCurBlendIndicesElem += 1;
newVar->setConnectName(out);
return newVar;
}
case RT_BLENDWEIGHT:
{
Var *newVar = new Var;
newVar->constNum = mCurBlendWeightsElem;
mElementList.push_back(newVar);
char out[32];
dSprintf((char*)out, sizeof(out), "vBlendWeight%d", mCurBlendWeightsElem);
mCurBlendWeightsElem += 1;
newVar->setConnectName(out);
return newVar;
}
default:
break;
}

View file

@ -33,6 +33,7 @@
#include "core/util/autoPtr.h"
#include "lighting/advanced/advancedLightBinManager.h"
#include "ts/tsShape.h"
LangElement * ShaderFeatureGLSL::setupTexSpaceMat( Vector<ShaderComponent*> &, // componentList
Var **texSpaceMat )
@ -2795,4 +2796,68 @@ void ImposterVertFeatureGLSL::determineFeature( Material *material,
{
if ( features.hasFeature( MFT_ImposterVert ) )
outFeatureData->features.addFeature( MFT_ImposterVert );
}
}
//****************************************************************************
// HardwareSkinningFeatureGLSL
//****************************************************************************
void HardwareSkinningFeatureGLSL::processVert(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd)
{
MultiLine *meta = new MultiLine;
Var *inPosition = (Var*)LangElement::find("inPosition");
Var *inNormal = (Var*)LangElement::find("inNormal");
if (!inPosition)
inPosition = (Var*)LangElement::find("position");
if (!inNormal)
inNormal = (Var*)LangElement::find("normal");
Var* posePos = new Var("posePos", "vec3");
Var* poseNormal = new Var("poseNormal", "vec3");
Var* poseMat = new Var("poseMat", "mat4x3");
Var* poseRotMat = new Var("poseRotMat", "mat3x3");
Var* nodeTransforms = (Var*)LangElement::find("nodeTransforms");
if (!nodeTransforms)
{
nodeTransforms = new Var("nodeTransforms", "mat4x3");
nodeTransforms->uniform = true;
nodeTransforms->arraySize = TSShape::smMaxSkinBones;
nodeTransforms->constSortPos = cspPrimitive;
}
U32 numIndices = mVertexFormat->getNumBlendIndices();
meta->addStatement(new GenOp(" @ = vec3(0.0);\r\n", new DecOp(posePos)));
meta->addStatement(new GenOp(" @ = vec3(0.0);\r\n", new DecOp(poseNormal)));
meta->addStatement(new GenOp(" @;\r\n", new DecOp(poseMat)));
meta->addStatement(new GenOp(" @;\r\n int i;\r\n", new DecOp(poseRotMat)));
for (U32 i = 0; i<numIndices; i++)
{
// NOTE: To keep things simple, we assume all 4 bone indices are used in each element chunk.
LangElement* inIndices = (Var*)LangElement::find(String::ToString("vBlendIndex%d", i));
LangElement* inWeights = (Var*)LangElement::find(String::ToString("vBlendWeight%d", i));
AssertFatal(inIndices && inWeights, "Something went wrong here");
AssertFatal(poseMat && nodeTransforms && posePos && inPosition && inWeights && poseNormal && inNormal && poseRotMat, "Something went REALLY wrong here");
meta->addStatement(new GenOp(" for (i=0; i<4; i++) {\r\n"));
meta->addStatement(new GenOp(" int poseIdx = int(@[i]);\r\n", inIndices));
meta->addStatement(new GenOp(" float poseWeight = @[i];\r\n", inWeights));
meta->addStatement(new GenOp(" @ = @[poseIdx];\r\n", poseMat, nodeTransforms));
meta->addStatement(new GenOp(" @ = mat3x3(@);\r\n", poseRotMat, poseMat));
meta->addStatement(new GenOp(" @ += (@ * vec4(@, 1)).xyz * poseWeight;\r\n", posePos, poseMat, inPosition));
meta->addStatement(new GenOp(" @ += ((@ * @) * poseWeight);\r\n", poseNormal, poseRotMat, inNormal));
meta->addStatement(new GenOp(" }\r\n"));
}
// Assign new position and normal
meta->addStatement(new GenOp(" @ = @;\r\n", inPosition, posePos));
meta->addStatement(new GenOp(" @ = normalize(@);\r\n", inNormal, poseNormal));
output = meta;
}

View file

@ -659,4 +659,17 @@ public:
MaterialFeatureData *outFeatureData );
};
/// Hardware Skinning
class HardwareSkinningFeatureGLSL : public ShaderFeatureGLSL
{
protected:
public:
virtual void processVert(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd);
virtual String getName() { return "Hardware Skinning"; }
};
#endif // _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_

View file

@ -113,6 +113,9 @@ const char* ShaderGenComponentFactoryGLSL::typeToString( GFXDeclType type )
case GFXDeclType_Float3:
return "vec3";
case GFXDeclType_UByte4:
return "vec4";
case GFXDeclType_Float4:
case GFXDeclType_Color:
return "vec4";
@ -160,6 +163,16 @@ ShaderComponent* ShaderGenComponentFactoryGLSL::createVertexInputConnector( cons
var = vertComp->getElement( RT_COLOR );
var->setName( "diffuse" );
}
else if (element.isSemantic(GFXSemantic::BLENDINDICES))
{
var = vertComp->getElement(RT_BLENDINDICES);
var->setName(String::ToString("vBlendIndex%d", element.getSemanticIndex()));
}
else if (element.isSemantic(GFXSemantic::BLENDWEIGHT))
{
var = vertComp->getElement(RT_BLENDWEIGHT);
var->setName(String::ToString("vBlendWeight%d", element.getSemanticIndex()));
}
else if ( element.isSemantic( GFXSemantic::TEXCOORD ) )
{
var = vertComp->getElement( RT_TEXCOORD );

View file

@ -105,6 +105,7 @@ void _initShaderGenGLSL( ShaderGen *shaderGen )
FEATUREMGR->registerFeature( MFT_DeferredMatInfoFlags, new DeferredMatInfoFlagsGLSL );
FEATUREMGR->registerFeature( MFT_DeferredEmptySpec, new DeferredEmptySpecGLSL );
FEATUREMGR->registerFeature( MFT_SkyBox, new NamedFeatureGLSL( "skybox" ) );
FEATUREMGR->registerFeature( MFT_HardwareSkinning, new HardwareSkinningFeatureGLSL );
}
MODULE_BEGIN( ShaderGenGLSL )