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

@ -33,6 +33,7 @@
#include "core/util/autoPtr.h"
#include "lighting/advanced/advancedLightBinManager.h"
#include "ts/tsShape.h"
LangElement * ShaderFeatureHLSL::setupTexSpaceMat( Vector<ShaderComponent*> &, // componentList
Var **texSpaceMat )
@ -2991,3 +2992,66 @@ void ImposterVertFeatureHLSL::determineFeature( Material *material,
outFeatureData->features.addFeature( MFT_ImposterVert );
}
//****************************************************************************
// HardwareSkinningFeatureHLSL
//****************************************************************************
void HardwareSkinningFeatureHLSL::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", "float3");
Var* poseNormal = new Var("poseNormal", "float3");
Var* poseMat = new Var("poseMat", "float4x3");
Var* poseRotMat = new Var("poseRotMat", "float3x3");
Var* nodeTransforms = (Var*)LangElement::find("nodeTransforms");
if (!nodeTransforms)
{
nodeTransforms = new Var("nodeTransforms", "float4x3");
nodeTransforms->uniform = true;
nodeTransforms->arraySize = TSShape::smMaxSkinBones;
nodeTransforms->constSortPos = cspPotentialPrimitive;
}
U32 numIndices = mVertexFormat->getNumBlendIndices();
meta->addStatement( new GenOp( " @ = 0.0;\r\n", new DecOp( posePos ) ) );
meta->addStatement( new GenOp( " @ = 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( "blendIndices%d", i ));
LangElement* inWeights = (Var*)LangElement::find(String::ToString( "blendWeight%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( " @ = (float3x3)@;\r\n", poseRotMat, poseMat) );
meta->addStatement( new GenOp( " @ += (mul(float4(@, 1), @)).xyz * poseWeight;\r\n", posePos, inPosition, poseMat) );
meta->addStatement( new GenOp( " @ += (mul(@,@) * poseWeight);\r\n", poseNormal, inNormal, poseRotMat) );
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;
}