4

在有关 OpenGL 3.0+ 的教程中,我们以这种方式创建顶点数组对象和顶点缓冲区对象:

GLuint VAO, VBO; 
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);

在这里,VAO 是一个unsigned int( GLuint),我们将 a̶ ̶r̶e̶f̶e̶r̶e̶n̶c̶e̶ 它的地址传递给函数glGenVertexArray。但是,根据文档,函数的第二个参数应该是( )的数组。 VBO 和. 我不明白为什么上面的代码适用于这样的论点。unsigned intGLuint*glGenBuffers

我试图用这个替换上面的代码(并在我的代码的其他地方进行必要的修改):

GLuint VAO[1];
GLuint VBO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);

它编译并执行,但我得到了一个意想不到的行为:我的纹理矩形使用第一种语法呈现,而不是第二种语法。我不明白为什么会发生这种情况。

编辑:谢谢。如前所述,第二个代码中存在索引错误。

4

3 回答 3

5

规范中的函数签名是:

void glGenVertexArrays( GLsizei n,
                        GLuint *arrays);

所以arrays需要一个GLuint 指针,在该指针中写入n * sizeof(GLuint)数据字节是有效的。

写成这样是完全正确和有效的:

GLuint VAO, VBO; 
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);

因为glGenVertexArrays希望有一个指针指向将数据字节GLuint写入(在您的情况下)有效的位置,并且因为可以保存这么多的数据,所以这样写是正确的。如果您每次调用只创建一个 id,则更可取。n * sizeof(GLuint)1VAO

正如其他人已经说过的那样,数组中的第一个元素具有索引0。至此,它必须是:

GLuint VAO[1];
GLuint VBO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);

如果你想在一次调用中创建更多元素,你想使用std::arrayover []

std::array<GLuint,3> VAOs;
std::array<GLuint,3> VBOs;

glGenVertexArrays(VAOs.size(), &VAOs[0]);
glGenBuffers(VBOs.size(), &VBOs[0]);

请注意unsigned intGLuint不一定是相同的类型或大小,unsigned int具有最小保证数量范围,但大小仍可能在不同平台上有所不同。GLuint另一方面具有定义的大小。

于 2017-08-24T12:04:08.607 回答
2

第一个索引是 0

GLuint VAO[1];
GLuint VBO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
于 2017-08-24T11:22:44.247 回答
1

C 和 C++ 中的数组表示为指针。反过来说,指针相当于一个元素的数组。因此,如果您正在创建单个缓冲区对象,您可以像在第一个示例中那样简单地声明一个变量并传递一个指向它的指针(它不是引用,它是一个指针),这没有任何问题。我自己一直都是这样做的。

为什么你的第二个例子不起作用,请参阅上面乔纳森奥尔森的回答。

于 2017-08-24T11:54:42.833 回答