c++openglvertex-buffervertex-array-object

glGenVertexArrays and glGenBuffers arguments


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.


Solution

  • 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.