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

ali*_*ali 32 opengl buffer vbo vertices vao

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

  1. 我是否必须为每个对象创建一个VAO和VBO?
  2. 或者应该为每个对象的VBO(顶点,纹理数据等)创建一个VAO?

有许多教程和书籍,但我仍然不知道如何理解和使用这些概念.

And*_*man 54

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

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

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

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

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

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

然而,它们比指针更复杂,就像用C语言那样知道它们.顶点指针跟踪指定时绑定的缓冲区对象,其地址空间的偏移量,顶点属性之间的跨距以及如何解释底层数据(例如,是保留整数值还是将它们转换为浮点数[ 0.0,1.0通过归一化到数据类型的范围]).

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

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

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


除此之外,除非您的对象共享顶点数据,否则通常需要为每个对象提供一组唯一的VBO.

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

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

  • 非常感谢.现在我明白了VAO和VBO究竟是什么.看起来我必须对我想要创建的3D对象有一个清晰的概述,然后选择使用VAO和VBO来节省内存和CPU/GPU时间的最佳方法. (3认同)

gla*_*ert 8

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

OGLDEV

OpenGL-Tutorial.org

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

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