c++ - 如何为着色器的每个顶点提供 14 个浮点值?
问题描述
我已经下载了一个模型,并将其导出为.fbx
. 该模型包含几个动画(准确地说是 6 个),我想显示其中一个。根据 Anton Gerdelan 关于 openGL 的书,我编写了一个导入器,它使用 assimp 解析模型、缓冲相关顶点数据并检索动画所需的偏移矩阵。
在骨骼动画方面没有太多经验,我想我已经能够对 anton 的导入器进行必要的更改,以便它可以在我需要的更复杂的模型上工作。但是,导入器假设每个顶点仅受 1 个骨骼影响,但不幸的是,情况并非如此。
经过一番修改,我发现模型的每个顶点一次最多可以受到 14 个骨骼的影响。由于我不确定如何将 14 个值传递给包含boneId
相关内容的着色器,因此weight
我尝试更改代码以一次最多容纳 4 个骨骼。这是解析骨骼 id 和权重并缓冲它们的代码:
*bone_count = (int)mesh->mNumBones;
char bone_names[256][64];
struct vertexdata {
int IDs[4];
float Weights[4];
int ptr;
};
vector<vertexdata> vdata;
vdata.resize(*point_count);
for (int i = 0; i < *point_count; i++) {
vdata[i].ptr = 0;
}
for (int b_i = 0; b_i < *bone_count; b_i++) {
const aiBone* bone = mesh->mBones[b_i];
strcpy(bone_names[b_i], bone->mName.data);
printf("bone_names[%i]=%s\n", b_i, bone_names[b_i]);
bone_offset_mats[b_i] = convert_assimp_matrix(bone->mOffsetMatrix);
//getting weights for each bone
int num_weights = (int)bone->mNumWeights;
for (int w_i = 0; w_i < num_weights; w_i++) {
aiVertexWeight weight = bone->mWeights[w_i];
int vid = weight.mVertexId;
float vweight = weight.mWeight;
if (vdata[vid].ptr < 4) {
vdata[vid].IDs[vdata[vid].ptr] = b_i;
vdata[vid].Weights[vdata[vid].ptr] = vweight;
vdata[vid].ptr++;
}
int vertex_id = (int)weight.mVertexId;
}
}
//buffering bone id data
GLuint vbo1;
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBufferData(GL_ARRAY_BUFFER, sizeof(vdata[0]) * vdata.size(), &vdata[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribIPointer(3, 4, GL_INT, sizeof(vertexdata), (const GLvoid*)0);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(vertexdata), (const GLvoid*)16);
在着色器中:
顶点着色器
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 norm;
layout (location = 2) in vec2 UV;
layout (location = 3) in ivec4 boneIDs;
layout (location = 4) in vec4 Weights;
uniform mat4 view, projection, model;
uniform mat4 bone_matrices[40];
out vec2 tCoords;
void main()
{
mat4 boneTransform = bone_matrices[boneIDs[0]] * Weights[0];
boneTransform += bone_matrices[boneIDs[1]] * Weights[1];
boneTransform += bone_matrices[boneIDs[2]] * Weights[2];
boneTransform += bone_matrices[boneIDs[3]] * Weights[3];
tCoords = UV;
gl_Position = projection * view * boneTransform * model * vec4(pos, 1.0);
}
片段着色器
#version 330 core
in vec2 tCoords;
out vec4 fragColour;
uniform sampler2D tex;
void main()
{
fragColour = texture(tex, tCoords);
}
模型渲染正确,但我没有观察到任何运动。同样,对骨骼动画了解不多,我只能假设这是因为我没有包括影响每个顶点的每个骨骼以及相应的权重。但是,在缓冲数据时,着色器最多只能接受vec4
每个顶点 4 个值。如何传递 14 个 ID 和 14 个权重?这可能是动画无法正常工作的原因吗?
解决方案
推荐阅读
- rust - 简单特征所需的类型注释
- sql - SQL 查询获取组的最新记录并计算这些特定记录的值
- javascript - JavaScript new.window 使用 javascript 函数
- android - Android文件选择器和上传获取文件未找到错误
- python - 如何智能更改项目范围内的函数签名?
- php - Laravel:一个数组有一个对象,排序后将其转换为数组
- c# - 如何解密 AES CBC?
- ruby - 无法使用 RSpec(rspec:找不到命令)
- typescript - 通用元组是否可以将 keyof 与其值匹配?
- html - 我可以使用 Tailwind CSS 实用程序类创建砌体布局吗?