Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding code used to draw quads in OpenGL 3.3+ core using triangles

I'm trying to draw a quad for a background (2D) using OpenGL 3.x+. Quads are deprecated, so the goal is to use two triangles to make a rectangle that fills the screen. It's working, but I'm not 100% clear on everything here.

  1. Setup

    GLuint positionBufferObject;
    GLfloat vertexPositions[] =
    {
        -1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f,  1.0f, 0.0f, 1.0f,
         1.0f,  1.0f, 0.0f, 1.0f,
         1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 0.0f, 1.0f,
    };
    glGenBuffers(1, &positionBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
    
    • I understand the vertexPositions, it's an array of vertices.
    • glGenBuffers() is saying, I want 1 buffer and assign id to &positionBufferObject?
    • glBufferData() uploads the vertexPositions to the GPU's memory; but how does it know were to upload it since I didn't give it an ID?
  2. Draw

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
    glDisableVertexAttribArray(0);
    
    • glEnableVertexAttribArray() just says I'm going to be drawing with array 0?
    • glDrawArrays() - what if I want to draw two vertex arrays? How does it know which ones to render? It knows that from the above command?
    • Not sure what glVertexAttribPointer() does?
    • glDrawArrays() is clear.
  3. Clean up, I think this is right?

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glDeleteBuffers(1, &positionBufferObject);
    

    I only do the setup/cleanup once.

Bonus points:

  • Is this the most effective way to render this? I read that I'm suppose to be submitting and be rendering in "batches" [?] since 3.x+ doesn't do immediate mode any more. There is also only one array, so batches won't help performance in this case, but if I had say "a very large number" of vertxArrays to draw, would it be the same process?
  • In setup they are storing the array id as positionBufferObject, but have it hardcoded in the rendering loop. Seems like it would get confusing after a dozen or so arrays, why isn't it good practice to use the variable instead of hardcode it?
like image 666
user697111 Avatar asked Apr 29 '11 02:04

user697111


2 Answers

glGenBuffers(1, &positionBufferObject); says "make a vertex buffer object, and positionBufferObject is its ID."

glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject); says "positionBufferObject is now the current GL_ARRAY_BUFFER."

glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW); says "upload vertexPositions to the ID currently bound to GL_ARRAY_BUFFER (which is positionBufferObject)."

glEnableVertexAttribArray(0); says "vertex attribute array 0 is now available for use."

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); says "vertex attribute array 0 is to be interpreted as consisting of groups of 4 floats."

glDrawArrays(GL_TRIANGLE_STRIP, 0, 5); says "draw a triangle strip with five indices from every enabled array."

glDisableVertexAttribArray(0); says "we're done for the time being with vertex attribute array 0."

like image 125
dfan Avatar answered Oct 10 '22 00:10

dfan


In answer to user697111's question about multiple arrays, it's quite simple.

Each vertex attribute needs to be associated with a buffer object. Rather than specifying the buffer object with glVertexAttribPointer, the association is done through GL_ARRAY_BUFFER. When you call glVertexAttribPointer (or any gl*Pointer call), the buffer that is currently bound to GL_ARRAY_BUFFER will be used as the source for that attribute. So, consider the following:

glBindBuffer(GL_ARRAY_BUFFER, myPositionData);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, ..., 0);
glBindBuffer(GL_ARRAY_BUFFER, myColorData);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, ..., 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(...);

Attribute 0 will come from the buffer object myPositionData, and attribute 1 will come from the buffer object myColorData. The fact that I undid the binding to GL_ARRAY_BUFFER before calling glDrawArrays does not change where the data for those attributes comes from.

like image 29
Nicol Bolas Avatar answered Oct 10 '22 00:10

Nicol Bolas