Working on optimization: GPU skinning and binary animations
This commit is contained in:
1 parent
a589765b7e
commit
f708843747
24 files changed
+890
-489525
No files matched your search
+137
-35
@@ -1,6 +1,8 @@
|
||||
#include "Character.h"
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include "GameConstants.h"
|
||||
#include "Environment.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
@@ -15,7 +17,16 @@ void Character::loadAnimation(AnimationState state, const std::string& filename,
|
||||
data.totalFrames = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Character::loadBinaryAnimation(AnimationState state, const std::string& filename, const std::string& zipFile) {
|
||||
auto& data = animations[state];
|
||||
data.model.LoadFromBinaryFile(filename, zipFile);
|
||||
if (!data.model.animations.empty() && !data.model.animations[0].keyFrames.empty()) {
|
||||
data.totalFrames = data.model.animations[0].keyFrames.back().frame + 1;
|
||||
}
|
||||
else {
|
||||
data.totalFrames = 1;
|
||||
}
|
||||
}
|
||||
/*void Character::setTexture(std::shared_ptr<Texture> tex) {
|
||||
texture = tex;
|
||||
}*/
|
||||
@@ -123,38 +134,6 @@ void Character::update(int64_t deltaMs) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (isPlayer) //Player should decide only by himself
|
||||
{
|
||||
if (attackTarget != nullptr)
|
||||
{
|
||||
auto pos = attackTarget->position;
|
||||
float distToTarget = (position - pos).norm();
|
||||
|
||||
if (distToTarget > 1.0)
|
||||
{
|
||||
setTarget(Eigen::Vector3f(pos.x(), 0.f, pos.z()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (battle_state != 1)
|
||||
{
|
||||
setTarget(position);
|
||||
battle_state = 1;
|
||||
//player->attack = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (battle_state != 0)
|
||||
{
|
||||
battle_state = 0;
|
||||
attack = 0;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (battle_state == 1)
|
||||
{
|
||||
if (currentState == AnimationState::STAND || currentState == AnimationState::WALK) {
|
||||
@@ -226,17 +205,32 @@ void Character::update(int64_t deltaMs) {
|
||||
|
||||
|
||||
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
|
||||
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
|
||||
if (useGpuSkinning) {
|
||||
anim.model.ComputeSkinningMatrices(static_cast<int>(anim.currentFrame), anim.skinningMatrices);
|
||||
} else {
|
||||
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
|
||||
}
|
||||
anim.lastFrame = static_cast<int>(anim.currentFrame);
|
||||
}
|
||||
}
|
||||
|
||||
void Character::draw(Renderer& renderer) {
|
||||
//std::cout << "draw called for Character at position: " << position.transpose() << std::endl;
|
||||
if (useGpuSkinning) {
|
||||
drawGpuSkinning(renderer);
|
||||
return;
|
||||
}
|
||||
|
||||
AnimationState drawState = resolveActiveState();
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end() || !texture) return;
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
|
||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
@@ -250,6 +244,114 @@ void Character::draw(Renderer& renderer) {
|
||||
renderer.DrawVertexRenderStruct(anim.modelMutable);
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
|
||||
void Character::prepareGpuSkinningVBOs(AnimationData& anim) {
|
||||
if (anim.gpuSkinningPrepared) return;
|
||||
|
||||
anim.model.PrepareGpuSkinningData();
|
||||
|
||||
// Upload bind-pose mesh (static, done once)
|
||||
anim.bindPoseMutable.AssignFrom(anim.model.startMesh);
|
||||
|
||||
auto& gpu = anim.model.gpuBoneData;
|
||||
|
||||
anim.boneIndices0VBO = std::make_shared<VBOHolder>();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices0VBO->getBuffer());
|
||||
glBufferData(GL_ARRAY_BUFFER, gpu.boneIndices0.size() * sizeof(Eigen::Vector4f),
|
||||
gpu.boneIndices0.data(), GL_STATIC_DRAW);
|
||||
|
||||
anim.boneIndices1VBO = std::make_shared<VBOHolder>();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneIndices1VBO->getBuffer());
|
||||
glBufferData(GL_ARRAY_BUFFER, gpu.boneIndices1.size() * sizeof(Eigen::Vector2f),
|
||||
gpu.boneIndices1.data(), GL_STATIC_DRAW);
|
||||
|
||||
anim.boneWeights0VBO = std::make_shared<VBOHolder>();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights0VBO->getBuffer());
|
||||
glBufferData(GL_ARRAY_BUFFER, gpu.boneWeights0.size() * sizeof(Eigen::Vector4f),
|
||||
gpu.boneWeights0.data(), GL_STATIC_DRAW);
|
||||
|
||||
anim.boneWeights1VBO = std::make_shared<VBOHolder>();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, anim.boneWeights1VBO->getBuffer());
|
||||
glBufferData(GL_ARRAY_BUFFER, gpu.boneWeights1.size() * sizeof(Eigen::Vector2f),
|
||||
gpu.boneWeights1.data(), GL_STATIC_DRAW);
|
||||
|
||||
anim.gpuSkinningPrepared = true;
|
||||
}
|
||||
|
||||
void Character::drawGpuSkinning(Renderer& renderer) {
|
||||
AnimationState drawState = resolveActiveState();
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end() || !texture) return;
|
||||
|
||||
auto& anim = it->second;
|
||||
prepareGpuSkinningVBOs(anim);
|
||||
|
||||
if (anim.skinningMatrices.empty()) return;
|
||||
|
||||
static const std::string skinningShaderName = "skinning";
|
||||
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
||||
|
||||
renderer.shaderManager.PushShader(skinningShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
|
||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(modelScale);
|
||||
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
// Upload bone skinning matrices
|
||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||
static_cast<int>(anim.skinningMatrices.size()), false,
|
||||
anim.skinningMatrices[0].data());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
||||
|
||||
// Bind VAO (desktop only)
|
||||
#ifndef EMSCRIPTEN
|
||||
#ifndef __ANDROID__
|
||||
if (anim.bindPoseMutable.vao) {
|
||||
glBindVertexArray(anim.bindPoseMutable.vao->getBuffer());
|
||||
renderer.shaderManager.EnableVertexAttribArrays();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Bind position and texcoord VBOs
|
||||
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.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
Reference in new issue
Block a user