GPU skinning refactoring
This commit is contained in:
parent
83cceecccd
commit
2ef2e456f7
@ -758,7 +758,7 @@ namespace ZL
|
|||||||
|
|
||||||
prepared = true;
|
prepared = true;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
void BoneSystem::ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const
|
void BoneSystem::ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const
|
||||||
{
|
{
|
||||||
int startingKeyFrame = -1;
|
int startingKeyFrame = -1;
|
||||||
@ -815,7 +815,7 @@ namespace ZL
|
|||||||
outMatrices[i] = currentBoneMatrixWorld4 * invertedStartBoneMatrixWorld4;
|
outMatrices[i] = currentBoneMatrixWorld4 * invertedStartBoneMatrixWorld4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void BoneSystem::Interpolate(int frame)
|
void BoneSystem::Interpolate(int frame)
|
||||||
{
|
{
|
||||||
int startingFrame = -1;
|
int startingFrame = -1;
|
||||||
@ -928,18 +928,18 @@ namespace ZL
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoneAnimationData::prepareGpuSkinningVBOs() {
|
void GpuSkinningShaderData::prepareGpuSkinningVBOs(BoneSystem& model) {
|
||||||
if (gpuSkinningPrepared)
|
if (gpuSkinningPrepared)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
model.gpuBoneData.PrepareGpuSkinningData(model.verticesBoneWeight);
|
gpuBoneData.PrepareGpuSkinningData(model.verticesBoneWeight);
|
||||||
|
|
||||||
// Upload bind-pose mesh (static, done once)
|
// Upload bind-pose mesh (static, done once)
|
||||||
bindPoseMutable.AssignFrom(model.startMesh);
|
bindPoseMutable.AssignFrom(model.startMesh);
|
||||||
|
|
||||||
auto& gpu = model.gpuBoneData;
|
auto& gpu = gpuBoneData;
|
||||||
|
|
||||||
boneIndices0VBO = std::make_shared<VBOHolder>();
|
boneIndices0VBO = std::make_shared<VBOHolder>();
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, boneIndices0VBO->getBuffer());
|
glBindBuffer(GL_ARRAY_BUFFER, boneIndices0VBO->getBuffer());
|
||||||
@ -964,5 +964,90 @@ namespace ZL
|
|||||||
gpuSkinningPrepared = true;
|
gpuSkinningPrepared = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GpuSkinningShaderData::RenderVBO(Renderer& renderer)
|
||||||
|
{
|
||||||
|
// Bind position and texcoord VBOs
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, bindPoseMutable.positionVBO->getBuffer());
|
||||||
|
renderer.VertexAttribPointer3fv("vPosition", 0, NULL);
|
||||||
|
|
||||||
|
if (bindPoseMutable.texCoordVBO) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, bindPoseMutable.texCoordVBO->getBuffer());
|
||||||
|
renderer.VertexAttribPointer2fv("vTexCoord", 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind bone index VBOs
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, boneIndices0VBO->getBuffer());
|
||||||
|
renderer.VertexAttribPointer4fv("aBoneIndices0", 0, NULL);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, boneIndices1VBO->getBuffer());
|
||||||
|
renderer.VertexAttribPointer2fv("aBoneIndices1", 0, NULL);
|
||||||
|
|
||||||
|
// Bind bone weight VBOs
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, boneWeights0VBO->getBuffer());
|
||||||
|
renderer.VertexAttribPointer4fv("aBoneWeights0", 0, NULL);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, boneWeights1VBO->getBuffer());
|
||||||
|
renderer.VertexAttribPointer2fv("aBoneWeights1", 0, NULL);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(bindPoseMutable.data.PositionData.size()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuSkinningShaderData::ComputeSkinningMatrices(const std::vector<Bone>& startBones, const std::vector<AnimationKeyFrame>& keyFrames, int frame)
|
||||||
|
{
|
||||||
|
int startingKeyFrame = -1;
|
||||||
|
for (size_t i = 0; i < keyFrames.size() - 1; i++)
|
||||||
|
{
|
||||||
|
int oldFrame = keyFrames[i].frame;
|
||||||
|
int nextFrame = keyFrames[i + 1].frame;
|
||||||
|
if (frame >= oldFrame && frame < nextFrame)
|
||||||
|
{
|
||||||
|
startingKeyFrame = static_cast<int>(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
skinningMatrices.resize(startBones.size());
|
||||||
|
|
||||||
|
if (startingKeyFrame == -1)
|
||||||
|
{
|
||||||
|
for (auto& m : skinningMatrices) m = Matrix4f::Identity();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modifiedFrameNumber = frame - keyFrames[startingKeyFrame].frame;
|
||||||
|
int diffFrames = keyFrames[startingKeyFrame + 1].frame - keyFrames[startingKeyFrame].frame;
|
||||||
|
float t = (modifiedFrameNumber + 0.f) / diffFrames;
|
||||||
|
|
||||||
|
const std::vector<Bone>& oneFrameBones = keyFrames[startingKeyFrame].bones;
|
||||||
|
const std::vector<Bone>& nextFrameBones = keyFrames[startingKeyFrame + 1].bones;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < startBones.size(); i++)
|
||||||
|
{
|
||||||
|
Vector3f interpPos;
|
||||||
|
interpPos(0) = oneFrameBones[i].boneStartWorld(0) + t * (nextFrameBones[i].boneStartWorld(0) - oneFrameBones[i].boneStartWorld(0));
|
||||||
|
interpPos(1) = oneFrameBones[i].boneStartWorld(1) + t * (nextFrameBones[i].boneStartWorld(1) - oneFrameBones[i].boneStartWorld(1));
|
||||||
|
interpPos(2) = oneFrameBones[i].boneStartWorld(2) + t * (nextFrameBones[i].boneStartWorld(2) - oneFrameBones[i].boneStartWorld(2));
|
||||||
|
|
||||||
|
Matrix3f oneFrameBonesMatrix = oneFrameBones[i].boneMatrixWorld.block<3, 3>(0, 0);
|
||||||
|
Matrix3f nextFrameBonesMatrix = nextFrameBones[i].boneMatrixWorld.block<3, 3>(0, 0);
|
||||||
|
|
||||||
|
Eigen::Quaternionf q1 = Eigen::Quaternionf(oneFrameBonesMatrix).normalized();
|
||||||
|
Eigen::Quaternionf q2 = Eigen::Quaternionf(nextFrameBonesMatrix).normalized();
|
||||||
|
Eigen::Quaternionf result = q1.slerp(t, q2);
|
||||||
|
|
||||||
|
Matrix3f boneMatrixWorld3 = result.toRotationMatrix();
|
||||||
|
|
||||||
|
Matrix4f currentBoneMatrixWorld4 = Eigen::Matrix4f::Identity();
|
||||||
|
currentBoneMatrixWorld4.block<3, 3>(0, 0) = boneMatrixWorld3;
|
||||||
|
currentBoneMatrixWorld4.block<3, 1>(0, 3) = interpPos;
|
||||||
|
|
||||||
|
Matrix4f startBoneMatrixWorld4 = keyFrames[0].bones[i].boneMatrixWorld;
|
||||||
|
Matrix4f invertedStartBoneMatrixWorld4 = startBoneMatrixWorld4.inverse();
|
||||||
|
|
||||||
|
skinningMatrices[i] = currentBoneMatrixWorld4 * invertedStartBoneMatrixWorld4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -12,8 +12,6 @@ namespace ZL
|
|||||||
Vector3f boneStartWorld;
|
Vector3f boneStartWorld;
|
||||||
float boneLength;
|
float boneLength;
|
||||||
Matrix4f boneMatrixWorld;
|
Matrix4f boneMatrixWorld;
|
||||||
// boneVector = boneLength * (0, 1, 0) <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
||||||
// Then multiply by boneMatrixWorld <20> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
|
||||||
|
|
||||||
int parent;
|
int parent;
|
||||||
std::vector<int> children;
|
std::vector<int> children;
|
||||||
@ -59,22 +57,18 @@ namespace ZL
|
|||||||
std::vector<Animation> animations;
|
std::vector<Animation> animations;
|
||||||
int startingFrame = 0;
|
int startingFrame = 0;
|
||||||
|
|
||||||
GpuBoneData gpuBoneData;
|
|
||||||
|
|
||||||
void LoadFromFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
void LoadFromFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
||||||
void LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
void LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
||||||
|
|
||||||
void Interpolate(int frame);
|
void Interpolate(int frame);
|
||||||
|
|
||||||
// GPU skinning: compute skinning matrices without modifying the mesh
|
// GPU skinning: compute skinning matrices without modifying the mesh
|
||||||
void ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const;
|
//void ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BoneAnimationData {
|
|
||||||
BoneSystem model;
|
struct GpuSkinningShaderData {
|
||||||
float currentFrame = 0.f;
|
GpuBoneData gpuBoneData;
|
||||||
int lastFrame = -1;
|
|
||||||
int totalFrames = 1;
|
|
||||||
|
|
||||||
// GPU skinning data (lazily initialized)
|
// GPU skinning data (lazily initialized)
|
||||||
VertexRenderStruct bindPoseMutable;
|
VertexRenderStruct bindPoseMutable;
|
||||||
@ -85,10 +79,22 @@ namespace ZL
|
|||||||
bool gpuSkinningPrepared = false;
|
bool gpuSkinningPrepared = false;
|
||||||
std::vector<Eigen::Matrix4f> skinningMatrices;
|
std::vector<Eigen::Matrix4f> skinningMatrices;
|
||||||
|
|
||||||
void prepareGpuSkinningVBOs();
|
void prepareGpuSkinningVBOs(BoneSystem& model);
|
||||||
|
void RenderVBO(Renderer& renderer);
|
||||||
|
void ComputeSkinningMatrices(const std::vector<Bone>& startBones, const std::vector<AnimationKeyFrame>& keyFrames, int frame);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoneAnimationData {
|
||||||
|
BoneSystem model;
|
||||||
|
float currentFrame = 0.f;
|
||||||
|
int lastFrame = -1;
|
||||||
|
int totalFrames = 1;
|
||||||
|
|
||||||
|
GpuSkinningShaderData gpuSkinningShaderData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -27,9 +27,6 @@ void Character::loadBinaryAnimation(AnimationState state, const std::string& fil
|
|||||||
data.totalFrames = 1;
|
data.totalFrames = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*void Character::setTexture(std::shared_ptr<Texture> tex) {
|
|
||||||
texture = tex;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void Character::setTarget(const Eigen::Vector3f& target,
|
void Character::setTarget(const Eigen::Vector3f& target,
|
||||||
std::function<void()> onArrived) {
|
std::function<void()> onArrived) {
|
||||||
@ -259,7 +256,7 @@ void Character::update(int64_t deltaMs) {
|
|||||||
|
|
||||||
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
|
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
|
||||||
if (useGpuSkinning) {
|
if (useGpuSkinning) {
|
||||||
anim.model.ComputeSkinningMatrices(static_cast<int>(anim.currentFrame), anim.skinningMatrices);
|
anim.gpuSkinningShaderData.ComputeSkinningMatrices(anim.model.startBones, anim.model.animations[0].keyFrames, static_cast<int>(anim.currentFrame));
|
||||||
} else {
|
} else {
|
||||||
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
|
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
|
||||||
}
|
}
|
||||||
@ -310,14 +307,15 @@ void Character::drawGpuSkinning(Renderer& renderer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& anim = it->second;
|
auto& anim = it->second;
|
||||||
anim.prepareGpuSkinningVBOs();
|
anim.gpuSkinningShaderData.prepareGpuSkinningVBOs(anim.model);
|
||||||
|
|
||||||
if (anim.skinningMatrices.empty())
|
if (anim.gpuSkinningShaderData.skinningMatrices.empty())
|
||||||
{
|
{
|
||||||
if (anim.model.animations.empty() || anim.model.animations[0].keyFrames.empty()) return;
|
if (anim.model.animations.empty() || anim.model.animations[0].keyFrames.empty()) return;
|
||||||
anim.model.ComputeSkinningMatrices(
|
|
||||||
anim.model.animations[0].keyFrames[0].frame, anim.skinningMatrices);
|
anim.gpuSkinningShaderData.ComputeSkinningMatrices(anim.model.startBones, anim.model.animations[0].keyFrames, static_cast<int>(anim.currentFrame));
|
||||||
if (anim.skinningMatrices.empty()) return;
|
|
||||||
|
if (anim.gpuSkinningShaderData.skinningMatrices.empty()) return;
|
||||||
}
|
}
|
||||||
static const std::string skinningShaderName = "skinning";
|
static const std::string skinningShaderName = "skinning";
|
||||||
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
||||||
@ -337,51 +335,56 @@ void Character::drawGpuSkinning(Renderer& renderer) {
|
|||||||
|
|
||||||
// Upload bone skinning matrices
|
// Upload bone skinning matrices
|
||||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||||
static_cast<int>(anim.skinningMatrices.size()), false,
|
static_cast<int>(anim.gpuSkinningShaderData.skinningMatrices.size()), false,
|
||||||
anim.skinningMatrices[0].data());
|
anim.gpuSkinningShaderData.skinningMatrices[0].data());
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
||||||
|
|
||||||
// Bind VAO (desktop only)
|
// Bind VAO (desktop only)
|
||||||
#ifndef EMSCRIPTEN
|
#ifndef EMSCRIPTEN
|
||||||
#ifndef __ANDROID__
|
#ifndef __ANDROID__
|
||||||
if (anim.bindPoseMutable.vao) {
|
if (anim.gpuSkinningShaderData.bindPoseMutable.vao) {
|
||||||
glBindVertexArray(anim.bindPoseMutable.vao->getBuffer());
|
glBindVertexArray(anim.gpuSkinningShaderData.bindPoseMutable.vao->getBuffer());
|
||||||
renderer.shaderManager.EnableVertexAttribArrays();
|
renderer.shaderManager.EnableVertexAttribArrays();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Bind position and texcoord VBOs
|
anim.gpuSkinningShaderData.RenderVBO(renderer);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.positionVBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer3fv("vPosition", 0, NULL);
|
|
||||||
|
|
||||||
if (anim.bindPoseMutable.texCoordVBO) {
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.texCoordVBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("vTexCoord", 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind bone index VBOs
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices0VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer4fv("aBoneIndices0", 0, NULL);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices1VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("aBoneIndices1", 0, NULL);
|
|
||||||
|
|
||||||
// Bind bone weight VBOs
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights0VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer4fv("aBoneWeights0", 0, NULL);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights1VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("aBoneWeights1", 0, NULL);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(anim.bindPoseMutable.data.PositionData.size()));
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
renderer.PopMatrix();
|
||||||
renderer.PopProjectionMatrix();
|
renderer.PopProjectionMatrix();
|
||||||
renderer.shaderManager.PopShader();
|
renderer.shaderManager.PopShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Character::prepareGpuSkinning()
|
||||||
|
{
|
||||||
|
AnimationState drawState = resolveActiveState();
|
||||||
|
auto it = animations.find(drawState);
|
||||||
|
if (it == animations.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& anim = it->second;
|
||||||
|
anim.gpuSkinningShaderData.prepareGpuSkinningVBOs(anim.model);
|
||||||
|
if (anim.gpuSkinningShaderData.skinningMatrices.empty()) {
|
||||||
|
if (anim.model.animations.empty() || anim.model.animations[0].keyFrames.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
anim.gpuSkinningShaderData.ComputeSkinningMatrices(anim.model.startBones, anim.model.animations[0].keyFrames, static_cast<int>(anim.currentFrame));
|
||||||
|
|
||||||
|
if (anim.gpuSkinningShaderData.skinningMatrices.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== Shadow depth pass ====================
|
// ==================== Shadow depth pass ====================
|
||||||
|
|
||||||
void Character::drawShadowDepth(Renderer& renderer) {
|
void Character::drawShadowDepth(Renderer& renderer) {
|
||||||
@ -418,14 +421,7 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
|
|||||||
auto it = animations.find(drawState);
|
auto it = animations.find(drawState);
|
||||||
if (it == animations.end()) return;
|
if (it == animations.end()) return;
|
||||||
|
|
||||||
auto& anim = it->second;
|
if (!prepareGpuSkinning()) return;
|
||||||
anim.prepareGpuSkinningVBOs();
|
|
||||||
if (anim.skinningMatrices.empty()) {
|
|
||||||
if (anim.model.animations.empty() || anim.model.animations[0].keyFrames.empty()) return;
|
|
||||||
anim.model.ComputeSkinningMatrices(
|
|
||||||
anim.model.animations[0].keyFrames[0].frame, anim.skinningMatrices);
|
|
||||||
if (anim.skinningMatrices.empty()) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const std::string shadowSkinningShader = "shadow_depth_skinning";
|
static const std::string shadowSkinningShader = "shadow_depth_skinning";
|
||||||
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
||||||
@ -440,36 +436,10 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
|
|||||||
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
|
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
|
||||||
|
|
||||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||||
static_cast<int>(anim.skinningMatrices.size()), false,
|
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
|
||||||
anim.skinningMatrices[0].data());
|
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
|
||||||
|
|
||||||
#ifndef EMSCRIPTEN
|
it->second.gpuSkinningShaderData.RenderVBO(renderer);
|
||||||
#ifndef __ANDROID__
|
|
||||||
if (anim.bindPoseMutable.vao) {
|
|
||||||
glBindVertexArray(anim.bindPoseMutable.vao->getBuffer());
|
|
||||||
renderer.shaderManager.EnableVertexAttribArrays();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.positionVBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer3fv("vPosition", 0, NULL);
|
|
||||||
|
|
||||||
if (anim.bindPoseMutable.texCoordVBO) {
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.texCoordVBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("vTexCoord", 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices0VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer4fv("aBoneIndices0", 0, NULL);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices1VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("aBoneIndices1", 0, NULL);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights0VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer4fv("aBoneWeights0", 0, NULL);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights1VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("aBoneWeights1", 0, NULL);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(anim.bindPoseMutable.data.PositionData.size()));
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
renderer.PopMatrix();
|
||||||
renderer.shaderManager.PopShader();
|
renderer.shaderManager.PopShader();
|
||||||
@ -528,15 +498,7 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
|
|||||||
auto it = animations.find(drawState);
|
auto it = animations.find(drawState);
|
||||||
if (it == animations.end() || !texture) return;
|
if (it == animations.end() || !texture) return;
|
||||||
|
|
||||||
auto& anim = it->second;
|
if (!prepareGpuSkinning()) return;
|
||||||
anim.prepareGpuSkinningVBOs();
|
|
||||||
|
|
||||||
if (anim.skinningMatrices.empty()) {
|
|
||||||
if (anim.model.animations.empty() || anim.model.animations[0].keyFrames.empty()) return;
|
|
||||||
anim.model.ComputeSkinningMatrices(
|
|
||||||
anim.model.animations[0].keyFrames[0].frame, anim.skinningMatrices);
|
|
||||||
if (anim.skinningMatrices.empty()) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const std::string skinningShadowShader = "skinning_shadow";
|
static const std::string skinningShadowShader = "skinning_shadow";
|
||||||
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
||||||
@ -562,44 +524,12 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
|
|||||||
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
|
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
|
||||||
|
|
||||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||||
static_cast<int>(anim.skinningMatrices.size()), false,
|
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
|
||||||
anim.skinningMatrices[0].data());
|
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
||||||
|
|
||||||
#ifndef EMSCRIPTEN
|
it->second.gpuSkinningShaderData.RenderVBO(renderer);
|
||||||
#ifndef __ANDROID__
|
|
||||||
if (anim.bindPoseMutable.vao) {
|
|
||||||
glBindVertexArray(anim.bindPoseMutable.vao->getBuffer());
|
|
||||||
renderer.shaderManager.EnableVertexAttribArrays();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.positionVBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer3fv("vPosition", 0, NULL);
|
|
||||||
|
|
||||||
if (anim.bindPoseMutable.texCoordVBO) {
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.texCoordVBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("vTexCoord", 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind normals for diffuse lighting (skinning_shadow shader skins them)
|
|
||||||
if (anim.bindPoseMutable.normalVBO) {
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.bindPoseMutable.normalVBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer3fv("vNormal", 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices0VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer4fv("aBoneIndices0", 0, NULL);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices1VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("aBoneIndices1", 0, NULL);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights0VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer4fv("aBoneWeights0", 0, NULL);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights1VBO->getBuffer());
|
|
||||||
renderer.VertexAttribPointer2fv("aBoneWeights1", 0, NULL);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(anim.bindPoseMutable.data.PositionData.size()));
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
renderer.PopMatrix();
|
||||||
renderer.PopProjectionMatrix();
|
renderer.PopProjectionMatrix();
|
||||||
|
|||||||
@ -70,8 +70,8 @@ public:
|
|||||||
bool canAttack = false;
|
bool canAttack = false;
|
||||||
Character* attackTarget = nullptr;
|
Character* attackTarget = nullptr;
|
||||||
bool isPlayer = false;
|
bool isPlayer = false;
|
||||||
bool useGpuSkinning = true;
|
//bool useGpuSkinning = true;
|
||||||
//bool useGpuSkinning = false;
|
bool useGpuSkinning = false;
|
||||||
|
|
||||||
float interactionRadius = 0.0f;
|
float interactionRadius = 0.0f;
|
||||||
|
|
||||||
@ -97,6 +97,8 @@ private:
|
|||||||
// if the requested state has no loaded animation.
|
// if the requested state has no loaded animation.
|
||||||
AnimationState resolveActiveState() const;
|
AnimationState resolveActiveState() const;
|
||||||
|
|
||||||
|
bool prepareGpuSkinning();
|
||||||
|
|
||||||
// GPU skinning: draw using shader-based skinning
|
// GPU skinning: draw using shader-based skinning
|
||||||
void drawGpuSkinning(Renderer& renderer);
|
void drawGpuSkinning(Renderer& renderer);
|
||||||
// Shadow: draw into depth map (no texture, no projection push)
|
// Shadow: draw into depth map (no texture, no projection push)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user