【问题标题】:Issue with passing integer vertex attributes with "in" keyword使用“in”关键字传递整数顶点属性的问题
【发布时间】:2021-02-25 17:29:43
【问题描述】:

我正在研究骨骼动画。我有一个基本上看起来像的顶点结构

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} 用于每个顶点。在我的网格类中,我有一个处理属性的静态函数Mesh::genFormat()vao 是网格类中的静态 intfor_i 只是我用来执行 for 循环的一个方便的宏。请注意,我正确使用 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,该代码也可以工作。

【问题讨论】:

  • 很难说没有看到 VBO 部分 - glVertexArrayVertexBuffer 。我没有看到发布的代码有任何问题。驱动程序在幕后做了很多魔术,所以大量错误代码可以工作,直到稍微改变。所以,我仍然会寻找一些错误。尝试更改位置值,如果其中仍然存在一些隐藏的错误,它也可能会破坏新代码。
  • @Quimby 你提到驱动程序让我想到检查 nvidia 控制面板,非常感谢!

标签: c++ opengl glsl glm-math


【解决方案1】:

好的,我解决了这个问题,尽管我不太明白这是如何解决问题的。我首选的图形处理器是自动的,但是当我强迫它在集成显卡上使用 NVIDIA 处理器时,一切正常。 image of solution

更新:

我认为这就像我的英特尔处理器图形支持 OpenGL 4.4 和 glVertexArrayAttribIFormat 出现在 OpenGL 4.5 中一样简单。

【讨论】:

  • 这样做时要非常小心。这正是我所说的,您的代码中可能仍然存在错误,但 NVIDIA 驱动程序会解决这个问题,而英特尔不会。例如。如果您删除显式位置,驱动程序仍然很有可能分配相同的数字,但它可能不会,它甚至可能在着色器编译之间发生变化。根据我的经验,NVIDIA 修复了很多东西,Intel 最少(这不是坏事),AMD 也是如此。充分利用您的两个 GPU 并确保它在两个 GPU 上都能正常工作(当然,除非它只是您的眼睛的玩具项目)。
  • 谢谢,这是个好建议。以后对GPU的认知度会更高!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多