GPU skinning refactoring
This commit is contained in:
parent
83cceecccd
commit
2ef2e456f7
@ -758,7 +758,7 @@ namespace ZL
|
||||
|
||||
prepared = true;
|
||||
}
|
||||
|
||||
/*
|
||||
void BoneSystem::ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const
|
||||
{
|
||||
int startingKeyFrame = -1;
|
||||
@ -815,7 +815,7 @@ namespace ZL
|
||||
outMatrices[i] = currentBoneMatrixWorld4 * invertedStartBoneMatrixWorld4;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
void BoneSystem::Interpolate(int frame)
|
||||
{
|
||||
int startingFrame = -1;
|
||||
@ -928,18 +928,18 @@ namespace ZL
|
||||
|
||||
}
|
||||
|
||||
void BoneAnimationData::prepareGpuSkinningVBOs() {
|
||||
void GpuSkinningShaderData::prepareGpuSkinningVBOs(BoneSystem& model) {
|
||||
if (gpuSkinningPrepared)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
model.gpuBoneData.PrepareGpuSkinningData(model.verticesBoneWeight);
|
||||
gpuBoneData.PrepareGpuSkinningData(model.verticesBoneWeight);
|
||||
|
||||
// Upload bind-pose mesh (static, done once)
|
||||
bindPoseMutable.AssignFrom(model.startMesh);
|
||||
|
||||
auto& gpu = model.gpuBoneData;
|
||||
auto& gpu = gpuBoneData;
|
||||
|
||||
boneIndices0VBO = std::make_shared<VBOHolder>();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, boneIndices0VBO->getBuffer());
|
||||
@ -964,5 +964,90 @@ namespace ZL
|
||||
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;
|
||||
float boneLength;
|
||||
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;
|
||||
std::vector<int> children;
|
||||
@ -59,22 +57,18 @@ namespace ZL
|
||||
std::vector<Animation> animations;
|
||||
int startingFrame = 0;
|
||||
|
||||
GpuBoneData gpuBoneData;
|
||||
|
||||
void LoadFromFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
||||
void LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
||||
|
||||
void Interpolate(int frame);
|
||||
|
||||
// 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;
|
||||
float currentFrame = 0.f;
|
||||
int lastFrame = -1;
|
||||
int totalFrames = 1;
|
||||
|
||||
struct GpuSkinningShaderData {
|
||||
GpuBoneData gpuBoneData;
|
||||
|
||||
// GPU skinning data (lazily initialized)
|
||||
VertexRenderStruct bindPoseMutable;
|
||||
@ -85,10 +79,22 @@ namespace ZL
|
||||
bool gpuSkinningPrepared = false;
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*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();
|
||||
|
||||
@ -70,8 +70,8 @@ public:
|
||||
bool canAttack = false;
|
||||
Character* attackTarget = nullptr;
|
||||
bool isPlayer = false;
|
||||
bool useGpuSkinning = true;
|
||||
//bool useGpuSkinning = false;
|
||||
//bool useGpuSkinning = true;
|
||||
bool useGpuSkinning = false;
|
||||
|
||||
float interactionRadius = 0.0f;
|
||||
|
||||
@ -97,6 +97,8 @@ private:
|
||||
// if the requested state has no loaded animation.
|
||||
AnimationState resolveActiveState() const;
|
||||
|
||||
bool prepareGpuSkinning();
|
||||
|
||||
// GPU skinning: draw using shader-based skinning
|
||||
void drawGpuSkinning(Renderer& renderer);
|
||||
// Shadow: draw into depth map (no texture, no projection push)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user