使用顶点数组对象和顶点缓冲区对象

时间:2014-04-26 18:15:07

标签: opengl buffer vbo vertices vao

我试图理解这两个,如何使用它们以及它们是如何相关的。让我们说我想创建一个简单的地形和一个纹理立方体。对于这两个对象,我有三角形顶点的数组,对于立方体,我有一个包含纹理数据的数组。我的问题是:如何使用VAO和VBO来创建和渲染这两个?

  1. 我是否必须为每个对象创建一个VAO和VBO?
  2. 或者应该为每个对象的VBO(顶点,纹理数据等)创建一个VAO?
  3. 有许多教程和书籍,但我仍然不知道如何理解和使用这些概念。

2 个答案:

答案 0 :(得分:51)

从根本上说,你需要了解两件事:

  1. 顶点数组对象(VAO)在概念上只是薄状态包装器。

  2. 顶点缓冲区对象(VBO)存储实际数据。

  3. 另一种思考方式是VAO描述存储在一个或多个VBO中的数据。

    将VBO(以及一般的缓冲区对象)视为存储在服务器(GPU)内存中的非结构化数据数组。如果需要,可以在多个数组中布置顶点数据,也可以将它们打包到单个数组中。在任何一种情况下,缓冲区对象都会归结为存储数据的位置。

    顶点数组对象跟踪绘制命令所需的实际 指针 到VBO内存。

    它们比指针更复杂,但是你会用C语言知道它们。顶点指针跟踪指定时绑定的缓冲区对象,其地址空间的偏移量,顶点属性之间的跨距以及如何解释基础数据(例如是否保留整数值或者通过归一化到数据类型的范围,将它们转换为浮点[ 0.0 1.0 ]。

    例如,整数数据通常转换为浮点数,但它是用于指定确定此行为的顶点指针(glVertexAttribPointer (...)glVertexAttribIPointer (...))的命令。

    顶点数组对象还会跟踪当前绑定到GL_ELEMENT_ARRAY_BUFFER的缓冲区对象。

    GL_ELEMENT_ARRAY_BUFFER是命令:glDrawElements (...)从中获取索引列表(假设非零绑定)和没有 glElementArrayPointer (...)命令。 glDrawElements (...)将指针和绘图命令组合到一个操作中,并将使用存储在活动顶点数组对象中的绑定来完成此操作。


    除此之外,除非你的对象共享顶点数据,否则你通常需要一组独特的VBO。

    如果需要,您可以将单个VAO用于整个软件,或者您可以利用更改绑定的VAO几乎改变绘制不同对象所需的整个状态集的事实。

    因此,绘制地形和立方体可能就像更改绑定的VAO一样简单。如果您需要为每个纹理应用不同的纹理,则可能需要做更多的工作,但VAO会处理所有与顶点数据相关的设置。

答案 1 :(得分:8)

你的问题在这里不容易回答,而是在教程中。您可能已经知道这两个网站,但如果没有,我将离开参考文献。

OGLDEV

OpenGL-Tutorial.org

现在试图阐明您的问题,Vertex数组对象是一个OpenGL对象,其目的是减少绘制调用的API开销。您可以将其视为顶点缓冲区及其关联状态的容器。类似于旧显示列表的东西。 通常,VAO和VBO之间存在1比1的关系;也就是说,每个VAO都包含一个唯一的VBO。但这并非绝对必要。您可以让几个VAO引用相同的VBO。

我认为,在代码中对此进行建模的最简单方法是使用VAO类/类型以及将VBO附加到其中的方法。然后为每个网格提供一个VAO实例。反过来,网格可以引用VBO类型,可以是它自己的或共享的。