Page 1 of 1

[Q] Drawing a quad using modern OpenGL?

Posted: Wed Jul 16, 2014 6:29 am
by 0x0000000
Hello all.

Over the past couple of weeks I have been attempting to learn modern OpenGL. I have gotten to the point where I am going to begin drawing primitives to the screen. I would like to know how to draw a quad.

Back with legacy OpenGL all you had to do would be glBegin(GL_QUADS) ... glEnd() but now I have to supply my own vertices to the shader. I read about OpenGL VBOs and since they can be created from a static array of vertices would it be better for me to do this:

Code: Select all

const GLfloat _quadBase[] = {
    0, 0, 1,
    1, 0, 1,
    0, 1, 1,
    1, 0, 1,
    1, 1, 1,
    0, 1, 1
}
// Generate VBO here.
void drawQuad(KHVec2 pos, KHVec2 size) {
    scale(size.x, size.y); // Scale the _quadBase
    translate(pos.x, pos.y);
    // Submit _quadBase vertices to shader
}
Or should I just generate a new VBO with the vertices altered?

Any help is appreciated!

Re: [Q] Drawing a quad using modern OpenGL?

Posted: Wed Jul 16, 2014 10:49 am
by Falco Girgis
0x0000000 wrote:Hello all.

Over the past couple of weeks I have been attempting to learn modern OpenGL. I have gotten to the point where I am going to begin drawing primitives to the screen. I would like to know how to draw a quad.

Back with legacy OpenGL all you had to do would be glBegin(GL_QUADS) ... glEnd() but now I have to supply my own vertices to the shader. I read about OpenGL VBOs and since they can be created from a static array of vertices would it be better for me to do this:

Code: Select all

const GLfloat _quadBase[] = {
    0, 0, 1,
    1, 0, 1,
    0, 1, 1,
    1, 0, 1,
    1, 1, 1,
    0, 1, 1
}
// Generate VBO here.
void drawQuad(KHVec2 pos, KHVec2 size) {
    scale(size.x, size.y); // Scale the _quadBase
    translate(pos.x, pos.y);
    // Submit _quadBase vertices to shader
}
Or should I just generate a new VBO with the vertices altered?

Any help is appreciated!
It depends on the geometry. If its transform is static, you can save calculation time by pretransforming the vertices before uploading the VBO. If not, or if you want to use the same quad VBO for all quads, then you submit your modelview and/or projection matrices as uniforms to your vertex shader and do the transformations there.

WARNING: I've done plenty of experimenting and benchmarking on the subject, and if your geometry is just a series of quads (ie a 2D game), you are going to be wasting a shitload of time uploading an entire matrix uniform to your vertex shader to transform every single onscreen sprite into world space. It's actually faster to take your quad into world space on the CPU, then just keep the view and projection matrices on the GPU. It's even faster yet if you transform into world space on the CPU with SIMD/vector instructions (SEE on x86 or NEON on ARM) before submitting geometry to your vertex shader.

Re: [Q] Drawing a quad using modern OpenGL?

Posted: Wed Jul 16, 2014 9:30 pm
by 0x0000000
Thanks for the reply!

So what you are saying is instead of calling glUniform4fv or something of the sort I would calculate the modelview matrix and transform the quads position on the CPU, then directly submit the transformed vertices to the vertex shader? And yes, my game is tile-based so I will be drawing many quads to the screen each frame.

Currently the graphics framework I have coded uses a modelview matrix and a projection matrix, however I could split the modelview into model and view if that's what you mean. I will reiterate by posting some pseudo-code:

Code: Select all

drawQuad(Vec2 pos, Vec2 size) {
    GLfloat vertices = {pos.x, pos.y, 1,
                        pos.x + size.x, pos.y, 1,
                        pos.x, pos.y + size.y, 1,
                        pos.x, pos.y + size.y, 1,
                        pos.x + size.x, pos.y + size. y, 1
                        pos.x + size.x, pos.y, 1};

    // Generate VBO, submit vertices to vertex shader.
}

// In vertex shader
in vec3 worldSpace;

uniform mat4 projection;
uniform mat4 view;

main() {
    gl_Position = worldSpace * view * projection; // Is this order correct?
}
EDIT:

You mentioned that if my transforms were static I could pre-calculate the vertices. Do you mean something like generating a gigantic VBO with all the tile vertices for the map, and just drawing the single VBO? Sorry if my understanding is completely off, I'm pretty new to this.