1

我有一个顶点数据类型,其中包括位置 (3)、纹理 (2) 和顶点法线 (3)。我正在使用(请参见此处)将这些传递给顶点着色器glVertexAttribPointer

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

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

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

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

这是完整的最小工作示例以及两个测试对象(完整,n20r4_d5.obj;非常部分,test11.obj)。

4

1 回答 1

4

您使用的是 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()),但是您设置事物的方式会使这有点混乱。

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

于 2014-02-21T22:25:37.753 回答