Pre-transform bones with inverse bind instead of sending it to the shader

This commit is contained in:
parax0 2016-04-27 20:36:50 -06:00
parent 401fe22b75
commit 50dcc9cc1a
7 changed files with 19 additions and 35 deletions

View File

@ -227,7 +227,6 @@ bool CShaderGenerator::CreateVertexShader(const CMaterial& rkMat)
ShaderCode << "layout(std140) uniform BoneTransformBlock\n" ShaderCode << "layout(std140) uniform BoneTransformBlock\n"
<< "{\n" << "{\n"
<< " mat4 BoneTransforms[100];\n" << " mat4 BoneTransforms[100];\n"
<< " mat4 InverseBindTransforms[100];\n"
<< "};\n" << "};\n"
<< "\n"; << "\n";
} }
@ -260,11 +259,10 @@ bool CShaderGenerator::CreateVertexShader(const CMaterial& rkMat)
<< " \n" << " \n"
<< " if (BoneIdx > 0)\n" << " if (BoneIdx > 0)\n"
<< " {\n" << " {\n"
<< " mat4 BoneSpaceTransform = InverseBindTransforms[BoneIdx] * BoneTransforms[BoneIdx];\n" << " ModelSpacePos += vec3(vec4(RawPosition, 1) * BoneTransforms[BoneIdx] * Weight);\n";
<< " ModelSpacePos += vec3(vec4(RawPosition, 1) * BoneSpaceTransform * Weight);\n";
if (VtxDesc & eNormal) if (VtxDesc & eNormal)
ShaderCode << " ModelSpaceNormal += RawNormal.xyz * inverse(transpose(mat3(BoneSpaceTransform))) * Weight;\n"; ShaderCode << " ModelSpaceNormal += RawNormal.xyz * inverse(transpose(mat3(BoneTransforms[BoneIdx]))) * Weight;\n";
ShaderCode << " }\n" ShaderCode << " }\n"
<< " }\n" << " }\n"

View File

@ -14,7 +14,6 @@ u32 CGraphics::mActiveContext = -1;
bool CGraphics::mInitialized = false; bool CGraphics::mInitialized = false;
std::vector<CVertexArrayManager*> CGraphics::mVAMs; std::vector<CVertexArrayManager*> CGraphics::mVAMs;
bool CGraphics::mIdentityBoneTransforms = false; bool CGraphics::mIdentityBoneTransforms = false;
const CSkeleton *CGraphics::mpkCurrentSkeleton = nullptr;
CGraphics::SMVPBlock CGraphics::sMVPBlock; CGraphics::SMVPBlock CGraphics::sMVPBlock;
CGraphics::SVertexBlock CGraphics::sVertexBlock; CGraphics::SVertexBlock CGraphics::sVertexBlock;
@ -47,7 +46,7 @@ void CGraphics::Initialize()
mpVertexBlockBuffer = new CUniformBuffer(sizeof(sVertexBlock)); mpVertexBlockBuffer = new CUniformBuffer(sizeof(sVertexBlock));
mpPixelBlockBuffer = new CUniformBuffer(sizeof(sPixelBlock)); mpPixelBlockBuffer = new CUniformBuffer(sizeof(sPixelBlock));
mpLightBlockBuffer = new CUniformBuffer(sizeof(sLightBlock)); mpLightBlockBuffer = new CUniformBuffer(sizeof(sLightBlock));
mpBoneTransformBuffer = new CUniformBuffer(sizeof(CTransform4f) * 200); mpBoneTransformBuffer = new CUniformBuffer(sizeof(CTransform4f) * 100);
sLightMode = eWorldLighting; sLightMode = eWorldLighting;
sNumLights = 0; sNumLights = 0;
@ -197,24 +196,13 @@ void CGraphics::LoadBoneTransforms(const CBoneTransformData& rkData)
mIdentityBoneTransforms = false; mIdentityBoneTransforms = false;
} }
void CGraphics::LoadBoneInverseBindTransforms(CSkeleton *pSkel)
{
if (mpkCurrentSkeleton != pSkel)
{
mpBoneTransformBuffer->BufferRange(pSkel->InverseBindMatricesData(), sizeof(CTransform4f) * 100, pSkel->InverseBindMatricesSize());
mpkCurrentSkeleton = pSkel;
mIdentityBoneTransforms = false;
}
}
void CGraphics::LoadIdentityBoneTransforms() void CGraphics::LoadIdentityBoneTransforms()
{ {
static CTransform4f IdentityTransforms[200]; static const CTransform4f skIdentityTransforms[100];
if (!mIdentityBoneTransforms) if (!mIdentityBoneTransforms)
{ {
mpBoneTransformBuffer->Buffer(&IdentityTransforms); mpBoneTransformBuffer->Buffer(&skIdentityTransforms);
mpkCurrentSkeleton = nullptr;
mIdentityBoneTransforms = true; mIdentityBoneTransforms = true;
} }
} }

View File

@ -29,9 +29,7 @@ class CGraphics
static u32 mActiveContext; static u32 mActiveContext;
static bool mInitialized; static bool mInitialized;
static std::vector<CVertexArrayManager*> mVAMs; static std::vector<CVertexArrayManager*> mVAMs;
static bool mIdentityBoneTransforms; static bool mIdentityBoneTransforms;
static const CSkeleton *mpkCurrentSkeleton;
public: public:
// SMVPBlock // SMVPBlock
@ -109,7 +107,6 @@ public:
static void SetupAmbientColor(); static void SetupAmbientColor();
static void SetIdentityMVP(); static void SetIdentityMVP();
static void LoadBoneTransforms(const CBoneTransformData& rkData); static void LoadBoneTransforms(const CBoneTransformData& rkData);
static void LoadBoneInverseBindTransforms(CSkeleton *pSkel);
static void LoadIdentityBoneTransforms(); static void LoadIdentityBoneTransforms();
}; };

View File

@ -29,6 +29,13 @@ void CBone::UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float
for (u32 iChild = 0; iChild < mChildren.size(); iChild++) for (u32 iChild = 0; iChild < mChildren.size(); iChild++)
mChildren[iChild]->UpdateTransform(rData, pAnim, Time, AnchorRoot); mChildren[iChild]->UpdateTransform(rData, pAnim, Time, AnchorRoot);
rTransform *= mInvBind;
}
CVector3f CBone::TransformedPosition(const CBoneTransformData& rkData) const
{
return rkData[mID] * AbsolutePosition();
} }
bool CBone::IsRoot() const bool CBone::IsRoot() const
@ -84,12 +91,12 @@ void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData& rkDat
for (u32 iBone = 0; iBone < mBones.size(); iBone++) for (u32 iBone = 0; iBone < mBones.size(); iBone++)
{ {
CBone *pBone = mBones[iBone]; CBone *pBone = mBones[iBone];
const CTransform4f& rkBoneTransform = rkData[pBone->ID()]; CVector3f BonePos = pBone->TransformedPosition(rkData);
// Draw bone // Draw bone
CTransform4f Transform; CTransform4f Transform;
Transform.Scale(skSphereRadius); Transform.Scale(skSphereRadius);
Transform.Translate(rkBoneTransform.ExtractTranslation()); Transform.Translate(BonePos);
CGraphics::sMVPBlock.ModelMatrix = Transform; CGraphics::sMVPBlock.ModelMatrix = Transform;
CGraphics::UpdateMVPBlock(); CGraphics::UpdateMVPBlock();
CDrawUtil::DrawSphere(CColor::skWhite); CDrawUtil::DrawSphere(CColor::skWhite);
@ -100,8 +107,8 @@ void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData& rkDat
for (u32 iChild = 0; iChild < pBone->NumChildren(); iChild++) for (u32 iChild = 0; iChild < pBone->NumChildren(); iChild++)
{ {
const CTransform4f& rkChildTransform = rkData[pBone->ChildByIndex(iChild)->ID()]; CVector3f ChildPos = pBone->ChildByIndex(iChild)->TransformedPosition(rkData);
CDrawUtil::DrawLine(rkBoneTransform.ExtractTranslation(), rkChildTransform.ExtractTranslation()); CDrawUtil::DrawLine(BonePos, ChildPos);
} }
} }
} }

View File

@ -19,7 +19,6 @@ class CSkeleton : public CResource
CBone *mpRootBone; CBone *mpRootBone;
std::vector<CBone*> mBones; std::vector<CBone*> mBones;
std::vector<CTransform4f> mInvBindMatrices;
static const float skSphereRadius; static const float skSphereRadius;
@ -34,9 +33,6 @@ public:
std::pair<s32,float> RayIntersect(const CRay& rkRay, const CBoneTransformData& rkData); std::pair<s32,float> RayIntersect(const CRay& rkRay, const CBoneTransformData& rkData);
inline u32 NumBones() const { return mBones.size(); } inline u32 NumBones() const { return mBones.size(); }
inline const CTransform4f& BoneInverseBindMatrix(u32 BoneID) const { return mInvBindMatrices[BoneID]; }
inline const void* InverseBindMatricesData() const { return mInvBindMatrices.data(); }
inline u32 InverseBindMatricesSize() const { return mInvBindMatrices.size() * sizeof(CTransform4f); }
}; };
class CBone class CBone
@ -49,10 +45,12 @@ class CBone
u32 mID; u32 mID;
CVector3f mPosition; CVector3f mPosition;
TString mName; TString mName;
CTransform4f mInvBind;
public: public:
CBone(CSkeleton *pSkel); CBone(CSkeleton *pSkel);
void UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot); void UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot);
CVector3f TransformedPosition(const CBoneTransformData& rkData) const;
bool IsRoot() const; bool IsRoot() const;
// Accessors // Accessors
@ -64,7 +62,6 @@ public:
inline CVector3f Position() const { return mPosition; } inline CVector3f Position() const { return mPosition; }
inline CVector3f AbsolutePosition() const { return mPosition + (mpParent ? mpParent->AbsolutePosition() : CVector3f::skZero); } inline CVector3f AbsolutePosition() const { return mPosition + (mpParent ? mpParent->AbsolutePosition() : CVector3f::skZero); }
inline TString Name() const { return mName; } inline TString Name() const { return mName; }
inline const CTransform4f& InverseBindMtx() const { return mpSkeleton->BoneInverseBindMatrix(mID); }
}; };
#endif // CSKELETON_H #endif // CSKELETON_H

View File

@ -14,12 +14,10 @@ void CSkeletonLoader::SetLocalBoneCoords(CBone *pBone)
void CSkeletonLoader::CalculateBoneInverseBindMatrices() void CSkeletonLoader::CalculateBoneInverseBindMatrices()
{ {
mpSkeleton->mInvBindMatrices.resize(mpSkeleton->MaxBoneID() + 1);
for (u32 iBone = 0; iBone < mpSkeleton->mBones.size(); iBone++) for (u32 iBone = 0; iBone < mpSkeleton->mBones.size(); iBone++)
{ {
CBone *pBone = mpSkeleton->mBones[iBone]; CBone *pBone = mpSkeleton->mBones[iBone];
mpSkeleton->mInvBindMatrices[pBone->ID()] = CTransform4f::TranslationMatrix(-pBone->AbsolutePosition()); pBone->mInvBind = CTransform4f::TranslationMatrix(-pBone->AbsolutePosition());
} }
} }

View File

@ -73,7 +73,6 @@ void CCharacterNode::Draw(FRenderOptions Options, int ComponentIndex, const SVie
// Draw surface OR draw entire model // Draw surface OR draw entire model
CGraphics::LoadBoneTransforms(mTransformData); CGraphics::LoadBoneTransforms(mTransformData);
CGraphics::LoadBoneInverseBindTransforms(pSkel);
CModel *pModel = mpCharacter->NodeModel(mActiveCharSet); CModel *pModel = mpCharacter->NodeModel(mActiveCharSet);
if (ComponentIndex < 0) if (ComponentIndex < 0)