GPU skinning refactoring

This commit is contained in:
Vladislav Khorev committed 2026-04-16 17:48:23 +03:00
1 parent 83cceecccd
commit 2ef2e456f7
4 files changed
+161 -138

No files matched your search

+50 -120
View File
@@ -27,9 +27,6 @@ void Character::loadBinaryAnimation(AnimationState state, const std::string& fil
data.totalFrames = 1;
}
}
/*void Character::setTexture(std::shared_ptr<Texture> tex) {
texture = tex;
}*/
void Character::setTarget(const Eigen::Vector3f& target,
std::function<void()> onArrived) {
@@ -259,7 +256,7 @@ void Character::update(int64_t deltaMs) {
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
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 {
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
}
@@ -310,14 +307,15 @@ void Character::drawGpuSkinning(Renderer& renderer) {
}
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;
anim.model.ComputeSkinningMatrices(
anim.model.animations[0].keyFrames[0].frame, anim.skinningMatrices);
if (anim.skinningMatrices.empty()) return;
anim.gpuSkinningShaderData.ComputeSkinningMatrices(anim.model.startBones, anim.model.animations[0].keyFrames, static_cast<int>(anim.currentFrame));
if (anim.gpuSkinningShaderData.skinningMatrices.empty()) return;
}
static const std::string skinningShaderName = "skinning";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
@@ -337,51 +335,56 @@ void Character::drawGpuSkinning(Renderer& renderer) {
// Upload bone skinning matrices
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
static_cast<int>(anim.skinningMatrices.size()), false,
anim.skinningMatrices[0].data());
static_cast<int>(anim.gpuSkinningShaderData.skinningMatrices.size()), false,
anim.gpuSkinningShaderData.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());
if (anim.gpuSkinningShaderData.bindPoseMutable.vao) {
glBindVertexArray(anim.gpuSkinningShaderData.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()));
anim.gpuSkinningShaderData.RenderVBO(renderer);
renderer.PopMatrix();
renderer.PopProjectionMatrix();
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 ====================
void Character::drawShadowDepth(Renderer& renderer) {
@@ -418,14 +421,7 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
auto it = animations.find(drawState);
if (it == animations.end()) return;
auto& anim = it->second;
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;
}
if (!prepareGpuSkinning()) return;
static const std::string shadowSkinningShader = "shadow_depth_skinning";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
@@ -440,36 +436,10 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
static_cast<int>(anim.skinningMatrices.size()), false,
anim.skinningMatrices[0].data());
#ifndef EMSCRIPTEN
#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()));
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
it->second.gpuSkinningShaderData.RenderVBO(renderer);
renderer.PopMatrix();
renderer.shaderManager.PopShader();
@@ -528,15 +498,7 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
auto& anim = it->second;
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;
}
if (!prepareGpuSkinning()) return;
static const std::string skinningShadowShader = "skinning_shadow";
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
@@ -562,44 +524,12 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
static_cast<int>(anim.skinningMatrices.size()), false,
anim.skinningMatrices[0].data());
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
#ifndef EMSCRIPTEN
#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()));
it->second.gpuSkinningShaderData.RenderVBO(renderer);
renderer.PopMatrix();
renderer.PopProjectionMatrix();