问题描述
我试图理解这两个,如何使用它们以及它们之间的关系.假设我要创建一个简单的地形和一个带纹理的立方体.对于这两个对象,我都有一个三角形顶点数组,对于立方体,我都有一个包含纹理数据的数组.我的问题是:我如何使用VAO和VBO来创建和渲染这两个?
I am trying to understand these two, how to use them and how they are related. Let's say I want to create a simple terrain and a textured cube. For both objects I have the array of triangles vertices and for the cube I have an array containing the texture's data. My question is: how do I use VAOs and VBOs to create and render these two?
- 我必须为每个对象创建一个VAO和VBO吗?
- 还是应该为每个对象的VBO(顶点,纹理数据等)创建VAO?
有许多教程和书籍,但是我仍然对如何理解和使用这些概念一无所知.
There are many tutorials and books but I still don't get the very idea of how these concepts must be understood and used.
推荐答案
从根本上讲,您需要了解两件事:
-
从概念上讲,顶点阵列对象(VAO)只是精简状态包装器.
Vertex Array Objects (VAOs) are conceptually nothing but thin state wrappers.
顶点缓冲对象(VBO)存储实际数据.
Vertex Buffer Objects (VBOs) store actual data.
另一种思考方式是VAO描述存储在一个或多个VBO中的数据.
Another way of thinking about this is that VAOs describe the data stored in one or more VBOs.
将VBO(通常是缓冲区对象)视为存储在服务器(GPU)内存中的非结构化数据数组.您可以根据需要将顶点数据布置在多个数组中,也可以将它们打包到一个数组中.无论哪种情况,缓冲区对象都归结为要存储数据的位置.
Think of VBOs (and buffer objects in general) as unstructured arrays of data stored in server (GPU) memory. You can layout your vertex data in multiple arrays if you want, or you can pack them into a single array. In either case, buffer objects boil down to locations where you will store data.
顶点数组对象"将实际的 指针 跟踪到绘制命令所需的VBO内存.
Vertex Array Objects track the actual pointers to VBO memory needed for draw commands.
它们比指针复杂一点,因为您会以C之类的语言来了解它们.顶点指针跟踪指定时绑定的缓冲区对象,其地址空间的偏移量,顶点属性之间的跨度以及如何解释基础数据( eg 是保留整数值还是通过归一化为数据类型的范围,将它们转换为浮点[ 0.0 , 1.0 ].
They are a little bit more sophisticated than pointers as you would know them in a language like C, however. Vertex pointers keep track of the buffer object that was bound when they were specified, the offset into its address space, stride between vertex attributes and how to interpret the underlying data (e.g. whether to keep integer values or to convert them to floating-point [0.0,1.0] by normalizing to the data type's range).
例如,整数数据通常会转换为浮点数,但这是用于指定顶点指针的命令( glVertexAttribPointer (...)
与 glVertexAttribIPointer (...)
)来确定此行为.
For example, integer data is usually converted to floating-point, but it is the command you use to specify the vertex pointer (glVertexAttribPointer (...)
vs. glVertexAttribIPointer (...)
) that determines this behavior.
顶点数组对象还跟踪当前绑定到GL_ELEMENT_ARRAY_BUFFER
的缓冲区对象.
Vertex Array Objects also track the buffer object currently bound to GL_ELEMENT_ARRAY_BUFFER
.
GL_ELEMENT_ARRAY_BUFFER
是命令所在的位置: glDrawElements (...)
从(假设非零绑定)获取其索引列表,并且没有 glElementArrayPointer (...)
命令. glDrawElements (...)
将指针和绘制命令合并为一个操作,并将使用存储在活动顶点数组对象"中的绑定来完成此操作.
GL_ELEMENT_ARRAY_BUFFER
is where the command: glDrawElements (...)
sources its list of indices from (assuming a non-zero binding) and there is no glElementArrayPointer (...)
command. glDrawElements (...)
combines the pointer and draw command into a single operation, and will use the binding stored in the active Vertex Array Object to accomplish this.
通过这种方式,除非对象共享顶点数据,否则通常每个对象都需要一组唯一的VBO.
With that out of the way, unless your objects share vertex data you are generally going to need a unique set of VBOs for each.
如果需要,您可以对整个软件使用单个VAO,或者可以利用以下事实:更改绑定的VAO几乎会改变绘制不同对象所需的全部状态.
You can use a single VAO for your entire software if you want, or you can take advantage of the fact that changing the bound VAO changes nearly the entire set of states necessary to draw different objects.
因此,绘制地形和立方体可以像更改绑定的VAO一样简单.如果需要为每个纹理应用不同的纹理,则可能需要做更多的事情,但是VAO负责所有与顶点数据相关的设置.
Thus, drawing your terrain and cube could be as simple as changing the bound VAO. You may have to do more than that if you need to apply different textures to each of them, but the VAO takes care of all vertex data related setup.
这篇关于顶点数组对象和顶点缓冲区对象的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!