问题描述
我刚接触OpenGL和图形编程。我一直在读一本教科书,这是一个非常彻底,写得很好。然而,我已经在代码中的一点,我不太理解,我想知道这些线在我之前继续。
GLuint abuffer;
glGenVertexArrays(1,& abuffer);
glBindVertexArray(abuffer);
缓冲;
glGenBuffers(1,& buffer);
glBindBuffer(GL_ARRAY_BUFFER,buffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(points),points,GL_STATIC_DRAW);
本书解释前三行是创建一个顶点数组对象,用于将相关数据与顶点数组捆绑。第二行找到一个未使用的名称(我猜这是一个存储在abuffer中的无符号整数标识符),第三行创建对象/使其生效。
第4到第7行创建一个缓冲对象来存储我们的数据,第5行给我们一个未使用的标识符(类似于第2行的顶点数组对象?),第6行创建缓冲区,第7行在CPU上分配足够的内存,并为GL_STATIC_DRAW创建一个指向我们的数据(点)的指针。 对象被激活是什么意思?你什么时候会使用abuffer?一个顶点数组绑定相关数据是什么意思,什么时候是与这个顶点数组对象相关联的数据? 我对abuffer之间的关系感到困惑和缓冲液。我很困惑顶点数组与缓冲区对象的关系,以及在什么点形成的关系。我不确定他们是否,事实上是相关的,但他们立即出现在教科书之一。 任何帮助将不胜感激。谢谢。 从低层次的角度来看,你可以把数组视为有两个部分: 关于数组的大小,形状和类型的信息(例如,32位浮点数,元素每个)。 数组数据,只是一个大的字节。 即使底层概念基本上保持不变,但你指定数组的方式在过去几年中已经改变了几次。 这是你
今天应该做的事。很少找到无法运行OpenGL 3.x的人,但仍然有钱花在你的软件上。
OpenGL 3.0 / ARB_vertex_array_object
OpenGL中的一个缓冲区对象是一个大的blob位。想想活动缓冲区只是一个全局变量,并且有一堆函数使用活动缓冲区而不是使用参数。这些全局状态变量是OpenGL的丑陋的一面(在
直接状态访问之前,如下所示)。
GLuint缓冲区;
//创建缓冲区
glGenBuffers(1,& buffer);
//使缓冲区成为活动数组缓冲区
//即:opengl-> array_buffer = buffer
glBindBuffer(GL_ARRAY_BUFFER,buffer);
//将一堆数据上传到活动数组缓冲区
// ie opengl-> array_buffer = new buffer(sizeof(points),points,STATIC_DRAW)
glBufferData(GL_ARRAY_BUFFER,sizeof (点),点,GL_STATIC_DRAW);
现在,您的典型顶点着色器将顶点 blob位。所以你需要指定如何将blob的位(缓冲区)解码为顶点。这是数组的工作。同样,有一个active数组,你可以认为它只是一个全局变量:
GLuint数组;
//创建数组
glGenVertexArrays(1,& array);
//使数组成为活动数组
//即,opengl-> vertex_array = array
glBindVertexArray(array);
//使缓冲区成为活动数组缓冲区
//即,opengl-> array_buffer = buffer
glBindBuffer(GL_ARRAY_BUFFER,buffer);
//将活动缓冲区连接到活动数组
//作为每个有4个浮点数的向量数组。
// ie opengl-> vertex_array.attributes [attr] = {
// type = GL_FLOAT,
// size = 4,
// data = opengl-> ; array_buffer
//}
glVertexAttribPointer(attr,4,GL_FLOAT,GL_FALSE,0,0);
//启用顶点属性
glEnableVertexAttribArray(attr);
OpenGL 2.0(旧方式)
在OpenGL 2.x中,没有顶点数组,数据只是全局的。你仍然必须调用 glVertexAttribPointer()
和 glEnableVertexAttribArray()
,但是你必须每次都调用它们您使用了缓冲区。在OpenGL 3.x中,你只需设置数组一次。
回到OpenGL 1.5,你实际上可以使用缓冲区,但是你使用一个单独的函数来绑定每个种类的数据。例如, glVertexPointer()
用于顶点数据, glNormalPointer()
用于正常数据。在OpenGL 1.5之前,没有缓冲区,但您可以使用指向您的应用程序内存的指针。
OpenGL 4.3 / ARB_vertex_attrib_binding
在4.3中,或者如果您有ARB_vertex_attrib_binding扩展,则可以单独指定属性格式和属性数据。这是很好的,因为它允许你轻松地在不同的缓冲区之间切换一个顶点数组。
//创建和绑定数组。
GLuint array;
glGenVertexArrays(1,& array);
glBindVertexArray(array);
//启用我的属性
glEnableVertexAttribArray(loc_attrib);
glEnableVertexAttribArray(normal_attrib);
glEnableVertexAttribArray(texcoord_attrib);
//设置属性的格式
glVertexAttribFormat(loc_attrib,3,GL_FLOAT,GL_FALSE,0);
glVertexAttribFormat(normal_attrib,3,GL_FLOAT,GL_FALSE,12);
glVertexAttribFormat(texcoord_attrib,2,GL_FLOAT,GL_FALSE,24);
//使我的属性全部使用绑定0
glVertexAttribBinding(loc_attrib,0);
glVertexAttribBinding(normal_attrib,0);
glVertexAttribBinding(texcoord_attrib,0);
//快速绑定所有属性以使用buffer
//这将替换对glVertexAttribPointer()的几个调用
//注意:您不需要绑定缓冲区第一!尼斯!
glBindVertexBuffer(0,buffer,0,32);
//快速绑定所有属性以使用buffer2
glBindVertexBuffer(0,buffer2,0,32);
OpenGL 4.5 / ARB_direct_state_access
4.5,或者如果你有ARB_direct_state_access扩展,你不再需要调用 glBindBuffer()
或 glBindVertexArray()
设置事情...你直接指定数组和缓冲区。你只需要绑定数组在结尾绘制它。
//创建数组,不绑定它。
//而不是绑定它,我们将它传递到下面的函数。
GLuint array;
glGenVertexArrays(1,& array);
//启用我的属性
glEnableVertexArrayAttrib(array,loc_attrib);
glEnableVertexArrayAttrib(array,normal_attrib);
glEnableVertexArrayAttrib(array,texcoord_attrib);
//设置属性的格式
glVertexArrayAttribFormat(array,loc_attrib,3,GL_FLOAT,GL_FALSE,0);
glVertexArrayAttribFormat(array,normal_attrib,3,GL_FLOAT,GL_FALSE,12);
glVertexArrayAttribFormat(array,texcoord_attrib,2,GL_FLOAT,GL_FALSE,24);
//使我的属性全部使用绑定0
glVertexArrayAttribBinding(array,loc_attrib,0);
glVertexArrayAttribBinding(array,normal_attrib,0);
glVertexArrayAttribBinding(array,texcoord_attrib,0);
//快速绑定所有属性以使用buffer
glVertexArrayVertexBuffer(array,0,buffer,0,32);
//快速绑定所有属性以使用buffer2
glVertexArrayVertexBuffer(array,0,buffer2,0,32);
//你仍然需要绑定数组来绘制。
glBindVertexArray(array);
glDrawArrays(...);
也许ARB_direct_state_access是未来的方式,也许它只是暂时停止更好(Mantle几乎肯定会影响下一个OpenGL标准)。无论哪种方式,丑陋的全局变量都消失了。
I'm new to OpenGL and Graphics Programming. I've been reading a textbook which has been really thorough and well-written so far.However, I've hit a point in the code that I'm not quite understanding and I'd like to make sense of these lines before I move on.
GLuint abuffer;
glGenVertexArrays(1, &abuffer);
glBindVertexArray(abuffer);
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
The book explains that the first three lines are creating a vertex-array object, which is used to bundle associated data with a vertex array. The second line finds an unused name (I'm guessing an unsigned integer identifier stored in abuffer) and the third line creates the object / makes it active.
The book explains that the 4th-7th lines creating a buffer object to store our data, with the 5th line giving us an unused identifier (similar to line 2 for the vertex array object?), the 6th line creating the buffer, and the 7th line allocating sufficient memory on the CPU and creating a pointer to our data (points) for GL_STATIC_DRAW.
What does it mean for the object to be active? When would you subsequently use abuffer? What does it mean for a vertex array to bundle associated data, and when was the data associated with this vertex-array object?
I'm confused about the relationship between abuffer and buffer. I'm confused about what the vertex array's relationship with the buffer object is, and at what point that relationship is formed. I'm not sure whether they are, in fact related, but they are presented in the textbook one immediately after the other.
Any help would be appreciated. Thanks.
From a low-level perspective, you can think of an array as having two parts to it:
Information about the size, shape, and type of the array (e.g., 32-bit floating point numbers, containing rows of vectors with four elements each).
The array data, which is little more than a big blob of bytes.
Even though the low-level concept has mostly stayed the same, the way you specify arrays has changed several times over the years.
OpenGL 3.0 / ARB_vertex_array_object
This is the way you probably should be doing things today. It is very rare to find people who can't run OpenGL 3.x and yet still have money to spend on your software.
A buffer object in OpenGL is a big blob of bits. Think of the "active" buffer as just a global variable, and there are a bunch of functions which use the active buffer instead of using a parameter. These global state variables are the ugly side of OpenGL (prior todirect state access, which is covered below).
GLuint buffer;
// Create a buffer
glGenBuffers(1, &buffer);
// Make the buffer the active array buffer
// i.e. opengl->array_buffer = buffer
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Upload a bunch of data into the active array buffer
// i.e. opengl->array_buffer = new buffer(sizeof(points), points, STATIC_DRAW)
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
Now, your typical vertex shader takes vertexes as input, not a big blob of bits. So you need to specify how the blob of bits (the buffer) is decoded into vertexes. That is the job of the array. Likewise, there is an "active" array which you can think of as just a global variable:
GLuint array;
// Create an array
glGenVertexArrays(1, &array);
// Make the array the active array
// i.e., opengl->vertex_array = array
glBindVertexArray(array);
// Make the buffer the active array buffer
// i.e., opengl->array_buffer = buffer
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Attach the active buffer to the active array,
// as an array of vectors with 4 floats each.
// i.e. opengl->vertex_array.attributes[attr] = {
// type = GL_FLOAT,
// size = 4,
// data = opengl->array_buffer
// }
glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, 0);
// Enable the vertex attribute
glEnableVertexAttribArray(attr);
OpenGL 2.0 (the old way)
In OpenGL 2.x, there weren't vertex arrays and the data was just global. You still had to call glVertexAttribPointer()
and glEnableVertexAttribArray()
, but you had to call them every time that you used a buffer. In OpenGL 3.x, you just set up the array once.
Going back to OpenGL 1.5, you could actually use buffers, but you used a separate function to bind each kind of data. For example, glVertexPointer()
was for vertex data, and glNormalPointer()
was for normal data. Prior to OpenGL 1.5, there weren't buffers, but you could use pointers into your application memory.
OpenGL 4.3 / ARB_vertex_attrib_binding
In 4.3, or if you have the ARB_vertex_attrib_binding extension, you can specify the attribute format and the attribute data separately. This is nice because it lets you easily switch one vertex array between different buffers.
// Create and bind the array.
GLuint array;
glGenVertexArrays(1, &array);
glBindVertexArray(array);
// Enable my attributes
glEnableVertexAttribArray(loc_attrib);
glEnableVertexAttribArray(normal_attrib);
glEnableVertexAttribArray(texcoord_attrib);
// Set up the formats for my attributes
glVertexAttribFormat(loc_attrib, 3, GL_FLOAT, GL_FALSE, 0);
glVertexAttribFormat(normal_attrib, 3, GL_FLOAT, GL_FALSE, 12);
glVertexAttribFormat(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24);
// Make my attributes all use binding 0
glVertexAttribBinding(loc_attrib, 0);
glVertexAttribBinding(normal_attrib, 0);
glVertexAttribBinding(texcoord_attrib, 0);
// Quickly bind all attributes to use "buffer"
// This replaces several calls to glVertexAttribPointer()
// Note: you don't need to bind the buffer first! Nice!
glBindVertexBuffer(0, buffer, 0, 32);
// Quickly bind all attributes to use "buffer2"
glBindVertexBuffer(0, buffer2, 0, 32);
OpenGL 4.5 / ARB_direct_state_access
In OpenGL 4.5, or if you have the ARB_direct_state_access extension, you no longer need to call glBindBuffer()
or glBindVertexArray()
just to set things up... you specify the arrays and buffers directly. You only need to bind the array at the end to draw it.
// Create the array, don't bind it.
// Instead of binding it, we pass it to the functions below.
GLuint array;
glGenVertexArrays(1, &array);
// Enable my attributes
glEnableVertexArrayAttrib(array, loc_attrib);
glEnableVertexArrayAttrib(array, normal_attrib);
glEnableVertexArrayAttrib(array, texcoord_attrib);
// Set up the formats for my attributes
glVertexArrayAttribFormat(array, loc_attrib, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(array, normal_attrib, 3, GL_FLOAT, GL_FALSE, 12);
glVertexArrayAttribFormat(array, texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24);
// Make my attributes all use binding 0
glVertexArrayAttribBinding(array, loc_attrib, 0);
glVertexArrayAttribBinding(array, normal_attrib, 0);
glVertexArrayAttribBinding(array, texcoord_attrib, 0);
// Quickly bind all attributes to use "buffer"
glVertexArrayVertexBuffer(array, 0, buffer, 0, 32);
// Quickly bind all attributes to use "buffer2"
glVertexArrayVertexBuffer(array, 0, buffer2, 0, 32);
// You still have to bind the array to draw.
glBindVertexArray(array);
glDrawArrays(...);
Maybe ARB_direct_state_access is the way of the future, or maybe it's just a temporary stop on the way to something better (Mantle will almost certainly influence the next OpenGL standard). Either way, the ugly global variables are gone.
这篇关于glBindVertexArrays和glBindBuffer的作用是什么,它们的关系是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!