glGenVertexArrays and glGenBuffers arguments
Asked Answered
M

3

5

In a tutorial about OpenGL 3.0+, we create a Vertex Array Object and Vertex Buffer Object this way:

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

Here, VAO is an unsigned int (GLuint) and we pass a̶ ̶r̶e̶f̶e̶r̶e̶n̶c̶e̶ its address to it in the function glGenVertexArray. However, according to the documentation, the second argument of the function should be an array of unsigned int (GLuint*). Same goes for VBO and glGenBuffers. I don't understand why the above code works with such arguments.

I've tried to replace the above code by this one (and do the necessary modifications elsewhere in my code) :

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

It compiles and executes, but I get an unexpected behaviour : my textured rectangle renders with the first syntax but not with the second one. I don't understand why this happens as well.

EDIT : Thank you. As stated, there is an indexing mistake in the second code.

Michail answered 24/8, 2017 at 11:15 Comment(2)
[0] is the first element of the array in C/C++, not [1].Portulaca
@Portulaca , Jonathan Olsen , Oops, I'm dumb.. Thank you very much !Michail
G
6

The function signature in the specs is:

void glGenVertexArrays( GLsizei n,
                        GLuint *arrays);

So arrays expects a GLuint pointer where it is valid to write n * sizeof(GLuint) bytes of data to.

It is perfectly fine and valid to write:

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

Because glGenVertexArrays wants to have an pointer to GLuint where it is valid to write n * sizeof(GLuint) bytes of data to (in your case 1) and because VAO can hold this amount of data, it is correct to write it that way. And and is preferable if you create only one id per call.

As already stated by others the first element in an array has the index 0. As of that it has to be:

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

If you want to create more elements in one call, you want to use std::array over [].

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

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

As a note unsigned int and GLuint does not necessarily the same type or size, unsigned int has a minimum guaranteed number range, but the size could still vary on different platforms. GLuint on the other hand has a defined size.

Gospel answered 24/8, 2017 at 12:4 Comment(1)
Thank you for the clarifications. It's kind of confusing because when I learnt C++, we didn't touch to C pointers and arrays at all (we learnt about smart pointers, std::vector and std::array instead). Now, with OpenGL, I discovered those objects. I learnt that, if not initialized, a C pointer is the same as an array, so I always read the documentation to see which one it's supposed to be. I don't know if they are always interchangeable when you use a function. That might be the case since apparently, an array is represented as a C pointer.Michail
A
2

First index is 0

GLuint VAO[1];
GLuint VBO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
Amund answered 24/8, 2017 at 11:22 Comment(0)
A
1

An array in C and C++ is represented as a pointer. Putting this the other way around, a pointer is equivalent to an array of one element. Therefore, if you are creating a single buffer object, you can simply declare a single variable and pass a pointer to it like you do in your first example (it's not a reference, it's a pointer) and there is nothing wrong with that. I've always done it that way myself.

For why your second example doesn't work, see Jonathan Olson's answer above.

Alon answered 24/8, 2017 at 11:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.