Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ GLBindVertexArray和glBindBuffer的作用是什么?它们之间的关系是什么?_C++_Opengl - Fatal编程技术网

C++ GLBindVertexArray和glBindBuffer的作用是什么?它们之间的关系是什么?

C++ GLBindVertexArray和glBindBuffer的作用是什么?它们之间的关系是什么?,c++,opengl,C++,Opengl,我不熟悉OpenGL和图形编程。我一直在阅读一本到目前为止写得非常透彻和好的教科书。然而,我在代码中遇到了一个我不太理解的点,我想在继续之前理解一下这些行 GLuint abuffer; glGenVertexArrays(1, &abuffer); glBindVertexArray(abuffer); 本书解释了前三行是创建顶点数组对象,该对象用于将关联数据与顶点数组绑定。第二行查找未使用的名称(我猜是存储在abuffer中的无符号整数标识符),第三行创建对象/使其处于活动状态

我不熟悉OpenGL和图形编程。我一直在阅读一本到目前为止写得非常透彻和好的教科书。然而,我在代码中遇到了一个我不太理解的点,我想在继续之前理解一下这些行

GLuint abuffer;

glGenVertexArrays(1, &abuffer);
glBindVertexArray(abuffer);

本书解释了前三行是创建顶点数组对象,该对象用于将关联数据与顶点数组绑定。第二行查找未使用的名称(我猜是存储在
abuffer
中的无符号整数标识符),第三行创建对象/使其处于活动状态

这本书解释了第4-7行创建缓冲区对象来存储数据,第5行给我们一个未使用的标识符(类似于顶点数组对象的第2行?),第6行创建缓冲区,第7行在CPU上分配足够的内存并创建指向数据(点)的指针对于
GL\u STATIC\u DRAW

对象处于活动状态意味着什么?您以后什么时候会使用
abuffer
?顶点数组绑定关联数据意味着什么?数据何时与此顶点数组对象关联

我对
abuffer
buffer
之间的关系感到困惑。我不清楚顶点数组与缓冲区对象的关系是什么,以及这种关系是在什么时候形成的。我不确定它们是否真的相关,但它们一个接一个地出现在教科书中


任何帮助都将不胜感激。谢谢。

OpenGL是一个有状态的界面。这是糟糕的,过时的和丑陋的,但这是留给你的遗产

顶点数组对象是一组缓冲区绑定,驱动程序可以使用这些绑定获取绘制调用的数据,大多数教程仅使用一个,从未解释如何使用多个VAO


缓冲区绑定告诉opengl将该缓冲区用于相关方法,特别是
glVertexAttributePointer
方法。

VertexArray和VBO之间没有关系

顶点数组在RAM中分配内存,并向API发送指针。VBO在图形卡中分配内存-系统内存没有它的地址。如果需要从系统访问vbo数据,则需要先将其从vbo复制到系统


此外,在较新版本的OpenGL中,顶点数组被完全删除(在3.0中被取消加密,在3.1中被删除)

您对本书的解释并不完全正确。顶点数组对象不存储任何数据。它们是一类称为容器的对象,类似于帧缓冲区对象。您可以将其他对象附着/关联到它们,但它们本身从不存储数据。因此,它们不是上下文可共享的资源

基本上,顶点数组对象在OpenGL 3.0中封装顶点数组状态。从OpenGL 3.1(代替
GL\u ARB\u兼容性
)和OpenGL 3.2+核心配置文件开始,您必须始终具有非零VAO绑定,才能使
glVertexAttributePointer(…)
glDrawArrays(…)
等命令正常工作。绑定的VAO为这些命令形成必要的上下文,并持久地存储状态

在较旧版本的GL(和兼容性)中,VAOs存储的状态是全局状态机的一部分

还值得一提的是,
GL\u ARRAY\u BUFFER
的“当前”绑定不是VAOs跟踪的状态之一。虽然此绑定由
glvertexattributepointer(…)
等命令使用,但VAO不存储绑定,它们只存储指针(GL 4.3附带引入的扩展使这一点有点复杂,因此为了简单起见,让我们忽略它)


VAOs请记住绑定到
GL\u ELEMENT\u ARRAY\u BUFFER
的内容,以便索引绘图命令(如
gldrawerelements(…)
)按预期运行(例如,VAOs重复使用最后绑定的元素数组BUFFER)。

从低级角度看,可以将数组视为包含两部分:

  • 有关数组大小、形状和类型的信息(例如,32位浮点数,包含每行四个元素的向量)

  • 数组数据,只不过是一大块字节

尽管低级概念基本上保持不变,但多年来指定数组的方式已经改变了好几次

OpenGL 3.0/ARB_顶点_数组_对象 这是你今天应该做的事情。很少有人不能运行OpenGL3.x,但仍然有钱买你的软件

OpenGL中的缓冲区对象是一大块位。将“活动”缓冲区视为一个全局变量,有许多函数使用活动缓冲区而不是参数。这些全局状态变量是OpenGL(在 直接状态访问,如下所述)

现在,典型的顶点着色器将顶点作为输入,而不是一大块位。因此,您需要指定位块(缓冲区)如何解码为顶点。这就是阵列的工作。同样,有一个“活动”数组,您可以将其视为一个全局变量:

GLuint array;
// Generate a name for a new array.
glGenVertexArrays(1, &array);
// Make the new array active, creating it if necessary.
glBindVertexArray(array);

// Make the buffer the active array buffer.
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Attach the active buffer to the active array,
// as an array of vectors with 4 floats each.
// Kind of like:
// opengl->current_vertex_array->attributes[attr] = {
//     type = GL_FLOAT,
//     size = 4,
//     data = opengl->current_array_buffer
// }
glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, 0);
// Enable the vertex attribute
glEnableVertexAttribArray(attr);
OpenGL 2.0(旧方法) 在OpenGL2.x中,没有顶点数组,数据只是全局的。您仍然必须调用
glVertexAttribPointer()
glEnableVertexAttribArray()
,但每次使用缓冲区时都必须调用它们。在OpenGL3.x中,只需设置一次数组

回到OpenGL 1.5,您实际上可以使用缓冲区,但是您使用了一个单独的函数来绑定每种数据。例如,
glVertexPointer()
用于顶点数据,
glNormalPointer()
用于普通数据。在OpenGL 1.5之前,没有缓冲区,但是
GLuint buffer;

// Generate a name for a new buffer.
// e.g. buffer = 2
glGenBuffers(1, &buffer);

// Make the new buffer active, creating it if necessary.
// Kind of like:
// if (opengl->buffers[buffer] == null)
//     opengl->buffers[buffer] = new Buffer()
// opengl->current_array_buffer = opengl->buffers[buffer]
glBindBuffer(GL_ARRAY_BUFFER, buffer);

// Upload a bunch of data into the active array buffer
// Kind of like:
// opengl->current_array_buffer->data = new byte[sizeof(points)]
// memcpy(opengl->current_array_buffer->data, points, sizeof(points))
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
GLuint array;
// Generate a name for a new array.
glGenVertexArrays(1, &array);
// Make the new array active, creating it if necessary.
glBindVertexArray(array);

// Make the buffer the active array buffer.
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Attach the active buffer to the active array,
// as an array of vectors with 4 floats each.
// Kind of like:
// opengl->current_vertex_array->attributes[attr] = {
//     type = GL_FLOAT,
//     size = 4,
//     data = opengl->current_array_buffer
// }
glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, 0);
// Enable the vertex attribute
glEnableVertexAttribArray(attr);
GLuint array;
// Generate a name for a new array array.
glGenVertexArrays(1, &array);
// Make the new array active, creating it if necessary.
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);
GLuint array;
// Generate a name for the array and create it.
// Note that glGenVertexArrays() won't work here.
glCreateVertexArrays(1, &array);
// Instead of binding it, we pass it to the functions below.

// 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(...);
// This defines part of a "vertex array", sort of
VkVertexInputAttributeDescription attrib[3];
attrib[0].location = 0; // Feed data into shader input #0
attrib[0].binding = 0;  // Get data from buffer bound to slot #0
attrib[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attrib[0].offset = 0;
// repeat for attrib[1], attrib[2]