使用 "in" 关键字传递整数顶点属性的问题
Issue with passing integer vertex attributes with "in" keyword
我正在研究骨骼动画。我有一个基本上看起来像
的顶点结构
struct MeshVertex
{
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 tex;
glm::vec3 tangent;
glm::vec3 bitangent;
uint32_t ids[4] = {};
float weights[4] = {};
void print() const;
};
网格是一个只有一根骨头的基本立方体。因此每个顶点的 ids = {0,0,0,0}
和 weights = {1.0f,0.0f,0.0f,0.0f}
。在我的网格 class 中,我有一个处理属性的静态函数 Mesh::genFormat()
。 vao
是网格 class 中的静态 int
而 for_i
只是我用来做循环的一个方便的宏。请注意,我正确使用了 glVertexArrayAttribIFormat.
Mesh::Mesh(const std::vector<MeshVertex>& vertices, const std::vector<uint>& indices, const std::vector<Texture>& textures)
{
m_textures = textures;
m_num_indices = indices.size();
// create vertex and index buffers
glCreateBuffers(1, &m_vbo);
glCreateBuffers(1, &m_ibo);
glNamedBufferData(m_vbo, sizeof(MeshVertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glNamedBufferData(m_ibo, sizeof(uint) * indices.size(), &indices[0], GL_STATIC_DRAW);
}
void Mesh::genFormat()
{
glCreateVertexArrays(1, &vao);
for_i(7) { glEnableVertexArrayAttrib(vao, i); }
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, false, offsetof(MeshVertex, pos)));
glVertexArrayAttribFormat(vao, 1, 3, GL_FLOAT, false, offsetof(MeshVertex, normal));
glVertexArrayAttribFormat(vao, 2, 2, GL_FLOAT, false, offsetof(MeshVertex, tex));
glVertexArrayAttribFormat(vao, 3, 3, GL_FLOAT, false, offsetof(MeshVertex, tangent));
glVertexArrayAttribFormat(vao, 4, 3, GL_FLOAT, false, offsetof(MeshVertex, bitangent));
glVertexArrayAttribIFormat(vao, 5, 4, GL_UNSIGNED_INT, offsetof(MeshVertex, ids)));
glVertexArrayAttribFormat(vao, 6, 4, GL_FLOAT, false, offsetof(MeshVertex, weights)));
for_i(7) { glVertexArrayAttribBinding(vao, i, 0); }
glBindVertexArray(0);
}
以下 GLSL 不会呈现任何内容。
#version 460 core
layout(location = 0) in vec3 Pos;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec2 Tex;
layout(location = 3) in vec3 Tan;
layout(location = 4) in vec3 BiTan;
layout(location = 5) in uvec4 BoneIds;
layout(location = 6) in vec4 Weights;
out vec3 normal;
out vec2 tex;
layout(binding = 2, std140) uniform Camera
{
mat4 VP;
vec4 cpos;
};
uniform mat4 node;
uniform mat4 bones_inverse_bind_mesh_parent[50];
void main()
{
tex = Tex;
mat4 W = mat4(0.0f);
if (Weights[0] != 0.0f)
{
for (uint i = 0; i < 4; i++)
W = W + (Weights[i] * bones_inverse_bind_mesh_parent[BoneIds[i]]);
W = node * W;
}
else
W = node;
gl_Position = VP * W * vec4(Pos, 1.0);
}
因为 BoneIds[i]
总是零,如果我替换
W = W + (Weights[i] * bones_inverse_bind_mesh_parent[BoneIds[i]]);
和
W = W + (Weights[i] * bones_inverse_bind_mesh_parent[0]);
结果应该没有变化。我的矩阵变换目前有点偏离(稍后修复),但现在立方体渲染良好。所以 BoneIds
有问题。在用这个头撞墙一段时间后,我改为替换
layout(location = 5) in uvec4 BoneIds;
和
layout(location = 5) varying uvec4 BoneIds;
在网上看到一些旧的 GLSL 后,现在一切正常。我不明白的是为什么。我已经在互联网上看到大量使用 in
关键字处理整数属性的 GLSL 代码。
更新:
如果我将 Mesh::genFormat()
中的 glVertexArrayAttribIFormat 替换为
glVertexArrayAttribFormat(vao, 5, 4, GL_UNSIGNED_INT, false, offsetof(MeshVertex, ids));
C++ 和
layout(location = 5) in vec4 BoneIds;
在 GLSL 中以及在 glsl 代码中将骨骼 ID 从 float 转换为 int,该代码也有效。
好的,我解决了这个问题,尽管我不太明白这是如何解决问题的。我首选的图形处理器是自动的,但当我强迫它在我的集成显卡上使用 NVIDIA 处理器时,一切正常。 image of solution
更新:
我认为它就像支持 OpenGL 4.4 的英特尔处理器显卡一样简单,glVertexArrayAttribIFormat
出现在 OpenGL 4.5 中。
我正在研究骨骼动画。我有一个基本上看起来像
的顶点结构struct MeshVertex
{
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 tex;
glm::vec3 tangent;
glm::vec3 bitangent;
uint32_t ids[4] = {};
float weights[4] = {};
void print() const;
};
网格是一个只有一根骨头的基本立方体。因此每个顶点的 ids = {0,0,0,0}
和 weights = {1.0f,0.0f,0.0f,0.0f}
。在我的网格 class 中,我有一个处理属性的静态函数 Mesh::genFormat()
。 vao
是网格 class 中的静态 int
而 for_i
只是我用来做循环的一个方便的宏。请注意,我正确使用了 glVertexArrayAttribIFormat.
Mesh::Mesh(const std::vector<MeshVertex>& vertices, const std::vector<uint>& indices, const std::vector<Texture>& textures)
{
m_textures = textures;
m_num_indices = indices.size();
// create vertex and index buffers
glCreateBuffers(1, &m_vbo);
glCreateBuffers(1, &m_ibo);
glNamedBufferData(m_vbo, sizeof(MeshVertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glNamedBufferData(m_ibo, sizeof(uint) * indices.size(), &indices[0], GL_STATIC_DRAW);
}
void Mesh::genFormat()
{
glCreateVertexArrays(1, &vao);
for_i(7) { glEnableVertexArrayAttrib(vao, i); }
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, false, offsetof(MeshVertex, pos)));
glVertexArrayAttribFormat(vao, 1, 3, GL_FLOAT, false, offsetof(MeshVertex, normal));
glVertexArrayAttribFormat(vao, 2, 2, GL_FLOAT, false, offsetof(MeshVertex, tex));
glVertexArrayAttribFormat(vao, 3, 3, GL_FLOAT, false, offsetof(MeshVertex, tangent));
glVertexArrayAttribFormat(vao, 4, 3, GL_FLOAT, false, offsetof(MeshVertex, bitangent));
glVertexArrayAttribIFormat(vao, 5, 4, GL_UNSIGNED_INT, offsetof(MeshVertex, ids)));
glVertexArrayAttribFormat(vao, 6, 4, GL_FLOAT, false, offsetof(MeshVertex, weights)));
for_i(7) { glVertexArrayAttribBinding(vao, i, 0); }
glBindVertexArray(0);
}
以下 GLSL 不会呈现任何内容。
#version 460 core
layout(location = 0) in vec3 Pos;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec2 Tex;
layout(location = 3) in vec3 Tan;
layout(location = 4) in vec3 BiTan;
layout(location = 5) in uvec4 BoneIds;
layout(location = 6) in vec4 Weights;
out vec3 normal;
out vec2 tex;
layout(binding = 2, std140) uniform Camera
{
mat4 VP;
vec4 cpos;
};
uniform mat4 node;
uniform mat4 bones_inverse_bind_mesh_parent[50];
void main()
{
tex = Tex;
mat4 W = mat4(0.0f);
if (Weights[0] != 0.0f)
{
for (uint i = 0; i < 4; i++)
W = W + (Weights[i] * bones_inverse_bind_mesh_parent[BoneIds[i]]);
W = node * W;
}
else
W = node;
gl_Position = VP * W * vec4(Pos, 1.0);
}
因为 BoneIds[i]
总是零,如果我替换
W = W + (Weights[i] * bones_inverse_bind_mesh_parent[BoneIds[i]]);
和
W = W + (Weights[i] * bones_inverse_bind_mesh_parent[0]);
结果应该没有变化。我的矩阵变换目前有点偏离(稍后修复),但现在立方体渲染良好。所以 BoneIds
有问题。在用这个头撞墙一段时间后,我改为替换
layout(location = 5) in uvec4 BoneIds;
和
layout(location = 5) varying uvec4 BoneIds;
在网上看到一些旧的 GLSL 后,现在一切正常。我不明白的是为什么。我已经在互联网上看到大量使用 in
关键字处理整数属性的 GLSL 代码。
更新:
如果我将 Mesh::genFormat()
中的 glVertexArrayAttribIFormat 替换为
glVertexArrayAttribFormat(vao, 5, 4, GL_UNSIGNED_INT, false, offsetof(MeshVertex, ids));
C++ 和
layout(location = 5) in vec4 BoneIds;
在 GLSL 中以及在 glsl 代码中将骨骼 ID 从 float 转换为 int,该代码也有效。
好的,我解决了这个问题,尽管我不太明白这是如何解决问题的。我首选的图形处理器是自动的,但当我强迫它在我的集成显卡上使用 NVIDIA 处理器时,一切正常。 image of solution
更新:
我认为它就像支持 OpenGL 4.4 的英特尔处理器显卡一样简单,glVertexArrayAttribIFormat
出现在 OpenGL 4.5 中。