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

@ -1426,6 +1426,8 @@ String GFXD3D11Device::_createTempShaderInternal(const GFXVertexFormat *vertexFo
StringBuilder mainBodyData;
//make shader
mainBodyData.append("VertOut main(VertIn IN){VertOut OUT;");
bool addedPadding = false;
for (U32 i = 0; i < elemCount; i++)
{
const GFXVertexElement &element = vertexFormat->getElement(i);
@ -1433,6 +1435,8 @@ String GFXD3D11Device::_createTempShaderInternal(const GFXVertexFormat *vertexFo
String semanticOut = semantic;
String type;
AssertFatal(!(addedPadding && !element.isSemantic(GFXSemantic::PADDING)), "Padding added before data");
if (element.isSemantic(GFXSemantic::POSITION))
{
semantic = "POSITION";
@ -1458,6 +1462,21 @@ String GFXD3D11Device::_createTempShaderInternal(const GFXVertexFormat *vertexFo
semantic = "BINORMAL";
semanticOut = semantic;
}
else if (element.isSemantic(GFXSemantic::BLENDINDICES))
{
semantic = String::ToString("BLENDINDICES%d", element.getSemanticIndex());
semanticOut = semantic;
}
else if (element.isSemantic(GFXSemantic::BLENDWEIGHT))
{
semantic = String::ToString("BLENDWEIGHT%d", element.getSemanticIndex());
semanticOut = semantic;
}
else if (element.isSemantic(GFXSemantic::PADDING))
{
addedPadding = true;
continue;
}
else
{
//Anything that falls thru to here will be a texture coord.
@ -1481,6 +1500,9 @@ String GFXD3D11Device::_createTempShaderInternal(const GFXVertexFormat *vertexFo
case DXGI_FORMAT_R8G8B8A8_UNORM:
type = "float4";
break;
case DXGI_FORMAT_R8G8B8A8_UINT:
type = "uint4";
break;
}
StringBuilder in;
@ -1570,16 +1592,17 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor
U32 stream;
D3D11_INPUT_ELEMENT_DESC *vd = new D3D11_INPUT_ELEMENT_DESC[ elemCount];
for ( U32 i=0; i < elemCount; i++ )
S32 elemIndex = 0;
for (S32 i = 0; i < elemCount; i++, elemIndex++)
{
const GFXVertexElement &element = vertexFormat->getElement( i );
const GFXVertexElement &element = vertexFormat->getElement(elemIndex);
stream = element.getStreamIndex();
vd[i].InputSlot = stream;
vd[i].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
vd[i].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
vd[i].Format = GFXD3D11DeclType[element.getType()];
// If instancing is enabled, the per instance data is only used on stream 1.
if (vertexFormat->hasInstancing() && stream == 1)
@ -1596,16 +1619,32 @@ GFXVertexDecl* GFXD3D11Device::allocVertexDecl( const GFXVertexFormat *vertexFor
// texture coords for now... this may change later.
vd[i].SemanticIndex = 0;
if ( element.isSemantic( GFXSemantic::POSITION ) )
if (element.isSemantic(GFXSemantic::POSITION))
vd[i].SemanticName = "POSITION";
else if ( element.isSemantic( GFXSemantic::NORMAL ) )
else if (element.isSemantic(GFXSemantic::NORMAL))
vd[i].SemanticName = "NORMAL";
else if ( element.isSemantic( GFXSemantic::COLOR ) )
else if (element.isSemantic(GFXSemantic::COLOR))
vd[i].SemanticName = "COLOR";
else if ( element.isSemantic( GFXSemantic::TANGENT ) )
else if (element.isSemantic(GFXSemantic::TANGENT))
vd[i].SemanticName = "TANGENT";
else if ( element.isSemantic( GFXSemantic::BINORMAL ) )
else if (element.isSemantic(GFXSemantic::BINORMAL))
vd[i].SemanticName = "BINORMAL";
else if (element.isSemantic(GFXSemantic::BLENDWEIGHT))
{
vd[i].SemanticName = "BLENDWEIGHT";
vd[i].SemanticIndex = element.getSemanticIndex();
}
else if (element.isSemantic(GFXSemantic::BLENDINDICES))
{
vd[i].SemanticName = "BLENDINDICES";
vd[i].SemanticIndex = element.getSemanticIndex();
}
else if (element.isSemantic(GFXSemantic::PADDING))
{
i--;
elemCount--;
continue;
}
else
{
//Anything that falls thru to here will be a texture coord.

View file

@ -152,5 +152,6 @@ void GFXD3D11EnumTranslate::init()
GFXD3D11DeclType[GFXDeclType_Float3] = DXGI_FORMAT_R32G32B32_FLOAT;
GFXD3D11DeclType[GFXDeclType_Float4] = DXGI_FORMAT_R32G32B32A32_FLOAT;
GFXD3D11DeclType[GFXDeclType_Color] = DXGI_FORMAT_B8G8R8A8_UNORM; // DXGI_FORMAT_R8G8B8A8_UNORM;
GFXD3D11DeclType[GFXDeclType_UByte4] = DXGI_FORMAT_R8G8B8A8_UINT;
}

View file

@ -150,9 +150,11 @@ bool GFXD3D11ConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstTyp
(
(pd.constType == GFXSCT_Float2x2 ||
pd.constType == GFXSCT_Float3x3 ||
pd.constType == GFXSCT_Float4x3 ||
pd.constType == GFXSCT_Float4x4) &&
(constType == GFXSCT_Float2x2 ||
constType == GFXSCT_Float3x3 ||
constType == GFXSCT_Float4x3 ||
constType == GFXSCT_Float4x4)
), "Mismatched const type!");
@ -161,6 +163,7 @@ bool GFXD3D11ConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstTyp
{
case GFXSCT_Float2x2:
case GFXSCT_Float3x3:
case GFXSCT_Float4x3:
case GFXSCT_Float4x4:
return setMatrix(pd, constType, size, data, basePointer);
break;
@ -201,6 +204,40 @@ bool GFXD3D11ConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderCo
return false;
}
else if (pd.constType == GFXSCT_Float4x3)
{
F32 buffer[4 * 4];
const U32 csize = 48;
// Loop through and copy
bool ret = false;
U8* currDestPointer = basePointer + pd.offset;
const U8* currSourcePointer = static_cast<const U8*>(data);
const U8* endData = currSourcePointer + size;
while (currSourcePointer < endData)
{
#ifdef TORQUE_DOUBLE_CHECK_43MATS
Point4F col;
((MatrixF*)currSourcePointer)->getRow(3, &col);
AssertFatal(col.x == 0.0f && col.y == 0.0f && col.z == 0.0f && col.w == 1.0f, "3rd row used");
#endif
if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0)
{
dMemcpy(currDestPointer, currSourcePointer, csize);
ret = true;
}
else if (pd.constType == GFXSCT_Float4x3)
{
ret = true;
}
currDestPointer += csize;
currSourcePointer += sizeof(MatrixF);
}
return ret;
}
else
{
PROFILE_SCOPE(GFXD3D11ConstBufferLayout_setMatrix_not4x4);
@ -480,8 +517,15 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF&
AssertFatal(!h->isSampler(), "Handle is sampler constant!" );
AssertFatal(h->mShader == mShader, "Mismatched shaders!");
MatrixF transposed;
mat.transposeTo(transposed);
MatrixF transposed;
if (matrixType == GFXSCT_Float4x3)
{
transposed = mat;
}
else
{
mat.transposeTo(transposed);
}
if (h->mInstancingConstant)
{
@ -510,9 +554,17 @@ void GFXD3D11ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF*
static Vector<MatrixF> transposed;
if (arraySize > transposed.size())
transposed.setSize(arraySize);
for (U32 i = 0; i < arraySize; i++)
mat[i].transposeTo(transposed[i]);
transposed.setSize(arraySize);
if (matrixType == GFXSCT_Float4x3)
{
dMemcpy(transposed.address(), mat, arraySize * sizeof(MatrixF));
}
else
{
for (U32 i = 0; i < arraySize; i++)
mat[i].transposeTo(transposed[i]);
}
// TODO: Maybe support this in the future?
if (h->mInstancingConstant)
@ -1190,19 +1242,13 @@ bool GFXD3D11Shader::_convertShaderVariable(const D3D11_SHADER_TYPE_DESC &typeDe
case D3D_SVC_MATRIX_ROWS:
case D3D_SVC_MATRIX_COLUMNS:
{
switch (typeDesc.Columns)
switch (typeDesc.Rows)
{
case 3:
if (typeDesc.Rows == 3)
{
desc.constType = GFXSCT_Float3x3;
}
desc.constType = typeDesc.Columns == 4 ? GFXSCT_Float3x4 : GFXSCT_Float3x3;
break;
case 4:
if (typeDesc.Rows == 4)
{
desc.constType = GFXSCT_Float4x4;
}
desc.constType = typeDesc.Columns == 3 ? GFXSCT_Float4x3 : GFXSCT_Float4x4;
break;
}
}
@ -1513,6 +1559,9 @@ U32 GFXD3D11Shader::getAlignmentValue(const GFXShaderConstType constType) const
case GFXSCT_Float3x3 :
return mRowSizeF * 3;
break;
case GFXSCT_Float4x3:
return mRowSizeF * 3;
break;
case GFXSCT_Float4x4 :
return mRowSizeF * 4;
break;