【问题标题】:glVertexAttribPointer: normals being drawn instead of verticesglVertexAttribPointer:绘制法线而不是顶点
【发布时间】:2014-02-22 06:40:52
【问题描述】:

我有一个顶点数据类型,它包括位置 (3)、纹理 (2) 和顶点法线 (3)。我将使用glVertexAttribPointer 将这些传递给vertex shader(请参阅here)。

不幸的是,无论我加载什么模型,它都给了我死星——基本上是一个顶点球体,只有在我切换到线框渲染时才可见。

我尝试从我的模块中删除一堆顶点,最终到达了一个部分构建的死星。在这一点上,很明显它正在绘制法线,就好像它们是顶点一样。我根本不知道顶点正在被绘制。

我通过drawing two additional triangles 证实了我的假设——一个代表顶点应该在哪里,另一个代表法线。我还将它们缩放了 1.1,这样它们就可以与对象本身区分开来。是的,它绝对是在绘制法线而不是顶点。

有人知道为什么吗?我尝试在着色器中切换属性的顺序,但这并没有帮助(奇怪)。

Here's the complete minimum working example 以及两个测试对象(完整,n20r4_d5.obj;非常部分,test11.obj)。

【问题讨论】:

    标签: opengl assimp


    【解决方案1】:

    您使用的是 OpenGL 2.1,因此您必须使用 glGetAttribLocation() 提取属性索引。您不能只希望 GLSL 编译器将顶点放在 0 上,将 texcoords 放在 2 上:

    void render(Shader* shader_program = NULL) 
    {
        if (shader_program) 
            shader_program->bind();
    
        GLint position_loc = glGetAttribLocation( shader_program->id(), "position" );
        GLint tex_loc = glGetAttribLocation( shader_program->id(), "tex" );
        GLint normal_loc = glGetAttribLocation( shader_program->id(), "normal" );
    
        glEnableVertexAttribArray( position_loc );
        glEnableVertexAttribArray( normal_loc );
        glEnableVertexAttribArray( tex_loc );
    
        for (size_t i = 0; i < entries.size(); ++i) 
        {
            glBindBuffer(GL_ARRAY_BUFFER, entries[i].vb);
    
            // I think this tells it where to look for the vertex information we've loaded.
            glVertexAttribPointer(position_loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
            glVertexAttribPointer(normal_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12); // starts at 12 because 3 floats for position before 2 floats for normal
            glVertexAttribPointer(tex_loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20); // makes room for 5 floats
            ...
    

    您也可以在链接着色器之前告诉 OpenGL 将它们放置在哪里 (glBindAttribLocation()),但是您的设置方式会让这有点混乱。

    在 OpenGL 3.1+ 中,您可以强制编译器通过 layout qualifier 将属性放在特定索引上。

    【讨论】:

    • 布局限定符的要点。如果您有一组使用一致布局的着色器,您可以在 C/C++ 代码中创建一个枚举并更直观地引用属性
    • 嗯。为什么着色器程序以不同于声明方式的方式对事物进行排序?这对我来说是不直观的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多