views:

128

answers:

2

I wondering if there is a faster (GPU time) way to draw a full-screen quad in OpenGL:

NewList();
PushMatrix();
LoadIdentity();
MatrixMode(PROJECTION);
PushMatrix();
LoadIdentity();
Begin(QUADS);
Vertex(-1,-1,0);  Vertex(1,-1,0);  Vertex(1,1,0);  Vertex(-1,1,0);
End();
PopMatrix();
MatrixMode(MODELVIEW);
PopMatrix();
EndList();

note that the pixels must interact with the stencil buffer.

A: 

If you just want to draw the whole viewport in a specified color, you can use glClear:

glClearColor(/* specify color here*/);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

Edit: with what you've added, it's apparent that won't work. That does leave a bit of a question: by "fastest" do you mean fastest to write (i.e., you'd like simpler code) or fastest to execute?

Simplicity

If you want simplicity, glDrawPixels should work:

glRasterPos2i(-1,-1);
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);

where 'image' will just be a block of data initialized to the desired color.

Speed

To improve execution speed, you could:

  1. put the calls into a display list and execute that when needed. How much this will help varies widely with the hardware and driver. More useful with nVidia than ATI, for example.
  2. Use a texture. Similar to glDrawPixels, but leaving the texture resident in texture memory can improve speed quite a bit.
  3. In theory, you'd also gain some speed by calling glDrawArrays instead of using glBegin/glVertex/glend. In reality, given that you only have four vertices, this probably won't make enough difference to care about.
Jerry Coffin
thanks for the answer. I just added a little precision to the question: the pixels will be filtered by the stencil buffer.
Soubok
+1  A: 

Faster where ? on the CPU ? The amount of work for a full screen quad is negligeable on the CPU compared to the work required to happen on the GPU.

So what matters most in this case is usually to optimize the GPU side, and believe it or not, there is one thing that is fairly significant. All the GPUs I know internally convert a quad to 2 triangles. Each of those triangles get rasterized separately. As it happens, you end up not using the GPU to its fullest, because on the diagonal between the 2 triangles, the GPU will have to work twice (this is because the GPU works on typically 16 or 32 pixels at once, in shapes of square or rectangle. The minimum is 4, which is already doing extra work).

How to avoid that extra work on the edge ? Draw a single triangle over the full region, and scissor to the region you want to draw to.

Something like (although I usually go from 0 to 1 rather than -1 to 1...):

glBegin(GL_TRIANGLES);
glVertex(-1,-1,0);  glVertex(3,-1,0);  Vertex(-1,3,0);
glEnd();
Bahbar
Thanks, but what is the GPU performance impact if a triangle is bigger than the viewport ?
Soubok
@Soubok: one of 2 things, either it gets clipped, and you're back to square one (because clipping will generate more triangles), or it is inside the GPU guard-band and the extra pixels are simply not rasterized. Guard-bands are huge these days, so this 2x size is usually fine.
Bahbar