glVertexAttribIPointer
时间: 2023-11-15 16:09:02 浏览: 28
glVertexAttribIPointer是一个OpenGL函数,用于指定顶点属性数组中每个元素的整数值,其中“I”表示整数。
该函数的语法为:
```
void glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
```
参数说明:
- index:指定要修改的顶点属性的索引。
- size:指定每个顶点属性的组件数。必须为1,2,3或4。
- type:指定每个组件的数据类型,可以是GL_BYTE、GL_UNSIGNED_BYTE、GL_SHORT、GL_UNSIGNED_SHORT、GL_INT、GL_UNSIGNED_INT或GL_FIXED。
- stride:指定连续顶点属性之间的字节偏移量。如果stride为0,则顶点属性将连续存储。
- pointer:指向数组中第一个顶点属性的第一个组件的指针。
该函数用于指定一个整数型顶点属性数组,与glVertexAttribPointer函数不同的是,它支持整数类型的数据,而glVertexAttribPointer只支持浮点类型的数据。
相关问题
Qt opengl assimp使用骨骼动画代码
以下是使用Qt、OpenGL和Assimp库实现骨骼动画的基本步骤:
1. 加载模型文件
使用Assimp库加载3D模型文件,包括模型的网格数据、材质信息、骨骼信息等。可以使用Assimp的Importer类来完成这一步骤。
```cpp
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenSmoothNormals | aiProcess_LimitBoneWeights);
```
2. 解析骨骼数据
遍历模型中的骨骼数据,将骨骼的信息存储到自定义的骨骼结构体中。其中包括骨骼的名称、变换矩阵、父骨骼的索引、子骨骼的数量、权重等信息。
```cpp
std::vector<Bone> bones;
processNode(scene->mRootNode, scene, bones);
```
3. 创建动画数据
遍历模型中的动画数据,将动画的信息存储到自定义的动画结构体中。其中包括动画的名称、持续时间、每个关键帧的时间戳、每个关键帧的骨骼姿势等信息。
```cpp
std::vector<Animation> animations;
processAnimations(scene, animations);
```
4. 创建顶点缓冲对象
创建顶点缓冲对象,并将模型的顶点数据、法线数据、纹理坐标数据、骨骼索引数据和权重数据存储到缓冲区中。
```cpp
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
```
5. 创建索引缓冲对象
创建索引缓冲对象,并将模型的三角形索引数据存储到缓冲区中。
```cpp
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
```
6. 创建着色器程序
创建顶点着色器和片段着色器,并将它们链接成一个着色器程序。在顶点着色器中,需要将骨骼的变换矩阵传递给顶点着色器,以便在GPU中计算每个顶点的最终位置。
```cpp
// 顶点着色器
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoord;
layout (location = 3) in ivec4 boneIDs;
layout (location = 4) in vec4 boneWeights;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
const int MAX_BONES = 100;
uniform mat4 bones[MAX_BONES];
out vec3 fragNormal;
out vec2 fragTexCoord;
void main()
{
mat4 boneTransform = bones[boneIDs[0]] * boneWeights[0]
+ bones[boneIDs[1]] * boneWeights[1]
+ bones[boneIDs[2]] * boneWeights[2]
+ bones[boneIDs[3]] * boneWeights[3];
gl_Position = projection * view * model * boneTransform * vec4(position, 1.0);
fragNormal = (model * boneTransform * vec4(normal, 0.0)).xyz;
fragTexCoord = texCoord;
}
// 片段着色器
#version 330 core
in vec3 fragNormal;
in vec2 fragTexCoord;
out vec4 fragColor;
uniform sampler2D texDiffuse;
void main()
{
fragColor = texture(texDiffuse, fragTexCoord) * vec4(fragNormal, 1.0);
}
```
7. 渲染骨骼动画
在每一帧中,根据当前时间戳计算出每个关键帧的权重,然后将骨骼的变换矩阵传递给顶点着色器,并渲染模型。
```cpp
float time = getCurrentTime();
std::vector<Matrix4f> boneTransforms = getBoneTransforms(time, animations[0]);
glUniformMatrix4fv(boneLocation, boneTransforms.size(), GL_TRUE, &boneTransforms[0][0][0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCoord));
glEnableVertexAttribArray(3);
glVertexAttribIPointer(3, 4, GL_INT, sizeof(Vertex), (void*)offsetof(Vertex, boneIDs));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, boneWeights));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, nullptr);
```
完整的代码示例可以在GitHub上找到:https://github.com/JoeyDeVries/LearnOpenGL/tree/master/src/5.advanced_lighting/3.1.shadow_mapping_base
Qt opengl assimp加载骨骼动画
加载骨骼动画的步骤可以分为以下几个:
1. 使用Assimp库加载包含骨骼动画的模型文件,并获取动画相关的信息,比如骨骼数、关键帧数、每个关键帧的变换信息等。
2. 创建OpenGL的顶点数组对象(VAO)和顶点缓冲对象(VBO),以及索引缓冲对象(IBO)。
3. 在顶点着色器中定义顶点属性,包括位置、法线、纹理坐标和骨骼权重。
4. 在顶点着色器中定义uniform变量,用于传递骨骼变换矩阵。
5. 在渲染循环中,计算每个关键帧的骨骼变换矩阵,并将其传递给顶点着色器中的uniform变量。
6. 在顶点着色器中,根据骨骼权重计算每个顶点的最终位置和法线。
7. 使用IBO和VAO绘制模型。
下面是一个简单的实现示例:
```cpp
// 加载模型
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace | aiProcess_LimitBoneWeights);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
// 加载失败
}
// 获取动画相关信息
const aiAnimation* animation = scene->mAnimations[0];
int numBones = animation->mNumChannels;
// 创建VAO、VBO和IBO
GLuint vao, vbo, ibo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCoord));
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, boneWeights));
glEnableVertexAttribArray(4);
glVertexAttribIPointer(4, 4, GL_INT, sizeof(Vertex), (void*)offsetof(Vertex, boneIndices));
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indices.size(), &indices[0], GL_STATIC_DRAW);
// 在顶点着色器中定义顶点属性和uniform变量
const char* vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aNormal;\n"
"layout (location = 2) in vec2 aTexCoord;\n"
"layout (location = 3) in vec4 aBoneWeights;\n"
"layout (location = 4) in int aBoneIndices[4];\n"
"uniform mat4 uBoneMatrices[" + std::to_string(numBones) + "];\n"
"out vec3 vNormal;\n"
"out vec2 vTexCoord;\n"
"void main()\n"
"{\n"
" vec4 position = vec4(aPos, 1.0);\n"
" vec4 normal = vec4(aNormal, 0.0);\n"
" for (int i = 0; i < 4; i++) {\n"
" position = uBoneMatrices[aBoneIndices[i]] * vec4(aPos, 1.0) * aBoneWeights[i] + position;\n"
" normal = uBoneMatrices[aBoneIndices[i]] * vec4(aNormal, 0.0) * aBoneWeights[i] + normal;\n"
" }\n"
" gl_Position = projection * view * model * position;\n"
" vNormal = normalize(normal.xyz);\n"
" vTexCoord = aTexCoord;\n"
"}\n";
// 在渲染循环中计算骨骼变换矩阵,并传递给顶点着色器
for (int i = 0; i < numBones; i++) {
aiNodeAnimation* nodeAnim = animation->mChannels[i];
std::string boneName = nodeAnim->mNodeName.C_Str();
aiMatrix4x4 boneOffset = m_BoneOffsets[boneName];
aiMatrix4x4 boneTransform = m_AnimatedTransforms[boneName];
aiMatrix4x4 globalTransform = m_GlobalInverseTransform * boneTransform * boneOffset;
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, ("uBoneMatrices[" + std::to_string(i) + "]").c_str()), 1, GL_TRUE, (float*)&globalTransform);
}
// 在顶点着色器中根据骨骼权重计算每个顶点的最终位置和法线
const char* fragmentShaderSource =
"#version 330 core\n"
"in vec3 vNormal;\n"
"in vec2 vTexCoord;\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" vec3 diffuse = texture(diffuseMap, vTexCoord).rgb;\n"
" vec3 normal = normalize(vNormal);\n"
" FragColor = vec4(diffuse * (0.5 + 0.5 * max(dot(normal, lightDir), 0.0)), 1.0);\n"
"}\n";
```