我每帧都需要为每个渲染的网格调用glVertexAttribPointer()吗?

8

我看到其他人的代码只在初始化vao时调用glVertexAttribPointer()。当我这样做时,场景中只有第一个对象被渲染,但如果我每帧*每个对象都调用它,一切都会正常渲染...这是否意味着我必须在绘制之前为每个对象设置glVertexAttribPointer()?或者我还有什么遗漏?!

        glBindVertexArray(mesh->getVao());
        glBindBuffer(GL_ARRAY_BUFFER, mesh->getVbo());

        for(int i = 0; i < 5; i++)
            glEnableVertexAttribArray(i);

        // Vertex Positions
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex UVs
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex Normals
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex Tangents
        glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex Binormals
        glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);

        // Draw
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getVbo());
        glDrawElements(GL_TRIANGLES, mesh->getNumberOfIndices(), GL_UNSIGNED_SHORT, (void*)0);

        for (int i = 0; i < 5; i++)
            glDisableVertexAttribArray(i);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

这是每个对象一个绘制调用。它可以完美地工作,但我真的需要为每个对象在每帧中调用glVertexAttribPointer()吗?

1个回答

9

顶点属性指针和索引缓冲器是VAO状态的一部分,因此它们只需要在开始时调用一次。

初始化:

glGenVertexArray(1, &vao);
glBindVertexArray(vao);

for(int i = 0; i < 5; i++)
    glEnableVertexAttribArray(i);

// Vertex Positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
offset++;
// Vertex UVs
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
offset++;
// Vertex Normals
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
offset++;
// Vertex Tangents
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
offset++;
// Vertex Binormals
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);

// Index Buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getVbo());

//Unbind VAO
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //Unbind the index buffer AFTER the vao has been unbinded

在每个帧调用中

glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, mesh->getNumberOfIndices(), GL_UNSIGNED_SHORT, (void*)0);
glBindVertexArray(0);

2
这太棒了!非常感谢!我看其他人的代码也无法理解,但我可以看出我不需要调用它一百万次,你帮了我大忙,谢谢 :) - GDN9
1
最后一个问题:我不需要在任何时候禁用 VertexAttribArray 吗?(如果我这样做,就什么都不会渲染)谢谢。 - GDN9
1
不,除非您想从VAO中删除此属性。 - BDL
1
@JerryLundegaard:在OpenGL 3.3+(核心配置文件)中,使用VAO是强制性的。在早期版本中,是的,您必须在每个绘制调用之前调用顶点设置。我不建议使用先前的核心配置文件版本。 - BDL
1
@JerryLundegaard:只要你不改变它,它就会记住它。但通常当你有一个非平凡的应用程序时,你会渲染不止一个形状。如果你需要更详细的答案,我建议你提一个新问题。 - BDL
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接