Full screen textured quad EXT

Any chance of a full screen textured quad extension? I know this may sound trivial, but it’s annoying having to switch to ortho mode to do a full-screen quad correctly.

Also, it could completely bypass clipping, lighting and transform, and basically just jump straight to rasterization.

I notice in Nvidia’s latest docs about in-game special effects, they mention full-screen post processes becoming more used with increased in fill-rate. These kind of effects alwasy use full-screen quads.

It would be top if we could just do a single function call, and it would blast the screen with the current bound textures, with a predefined set of texture coords, so we dont even have to specify those either.

I know the performance increase would probably be neglibable… (or maybe not if alot of the setup pipline is skipped, though it’s only 4 vertices…) but it would be nice…

Nutty

could be part of GL_NV_window_pos… (nvidia always creates their own versions of standart-extensions to …improve usage…)

btw, cass, when will GL_EXT_window_pos (or is it GL_ARB_window_pos) be in the drivers?

void draw_full_screen_quad( void )
{
glPushMatrix()
glLoadIdentity()
glBegin( GL_QUADS );
glTexCoord2f(0,0);glVertex2f(0,0);
glTexCoord2f(1,0);glVertex2f(window_Width,0);
glTexCoord2f(1,1);glVertex2f(window_Width,window_Height);
glTexCoord2f(0,1);glVertex2f(0,window_Height);
glEnd();
glPopMatrix()
}

try this

When I do something similary, I have problems with what coordinates to pass within the texture, as well as for the quad’s edges.

I can’t pass [0,1] for texture coordinates, because with texture filtering, that will filter with the border or with the repeat. Thus, I have to adjust the texture coordinate in by half a pixel on each side.

Then comes the question: should I pass [0,1] for the quad, or should I pass the center of the corner pixels for the quad, too? If I pass the entire quad, then in effect, my texture will be stretched by one pixel across the screen. If I pass the center of the corner pixels, it seems as if it would match up, but then my GF2MX drops one pixel on the right (or left, depending on where I wiggle it).

So far, I’ve found mostly joy by adjusting the right/top coordinate in by half a pixel, and the left/bottom coordinate not at all, which makes no sense whatsoever.

Someone, please enlighten me on what the a) the right behaviour is supposed to be and b) thus what the right thing to do is.

Isnt it better (in terms of performance) to not render full screen polygons? Isnt it better to break up into maybe 25 quads?

jwatte, with or without CLAMP_TO_EDGE?
V-man

Thanks Zed, I’ll try that.

V-Man, I can’t see why splitting the quad up could possibly improve performance. Apart from break up the fill-rate a bit.

Unless the framebuffer is block arranged, and rendering to litte small squares at a time, rather than entire raster lines, is better for the GFX cache?? Perhaps better for texture cache also…

I’ll do some timings on this at home.

JWatte, never noticed a problem myself, but then I dont pay much attention to edges of stuff, maybe I should…

Nutty

Zed, that doesn’t work at all.

I assume glVertex2f is the same as glVertex3f(x, y, 0.0f)?

Like it is with Texture coords. Which means it wont pass the clipping plane, and it just doesn’t work at all. You at least need to setup an ortho projection matrix, so that a Z value that clears the near clipping plane, doesn’t scale the quad.

Or am I being lame or something? I was thinking of using a VP, that justs writes out HPOS position, and avoid using any matrices. Should be quite quick. I assume HPOS goes from -1,-1, to 1,1? or something similar…

Nutty

Originally posted by zed:
[b]void draw_full_screen_quad( void )
{
glPushMatrix()
glLoadIdentity()
glBegin( GL_QUADS );
glTexCoord2f(0,0);glVertex2f(0,0);
glTexCoord2f(1,0);glVertex2f(window_Width,0);
glTexCoord2f(1,1);glVertex2f(window_Width,window_Height);
glTexCoord2f(0,1);glVertex2f(0,window_Height);
glEnd();
glPopMatrix()
}

try this [/b]

I think it should look like this…still messy:-

void draw_full_screen_quad( void )
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glBegin( GL_QUADS );
glTexCoord2f(0,0);glVertex2f(-window_Width0.5f,-window_Height0.5f);
glTexCoord2f(1,0);glVertex2f(window_Width0.5f,-window_Height0.5f);
glTexCoord2f(1,1);glVertex2f(window_Width0.5f,window_Height0.5f);
glTexCoord2f(0,1);glVertex2f(-window_Width0.5f,window_Height0.5f);
glEnd();

glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}

Or this even!!

void draw_full_screen_quad(void)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glBegin( GL_QUADS );

  glTexCoord2f(0,0);
  glVertex2f(-1.0f, -1.0f);
  glTexCoord2f(1,0);
  glVertex2f(1.0f, -1.0f);
  glTexCoord2f(1,1);
  glVertex2f(1.0f, 1.0f);
  glTexCoord2f(0,1);
  glVertex2f(-1.0f, 1.0f);

glEnd();

glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}

I’ve tested this one, and it works. No more glOrtho()

Nutty

Yes, that’s it - god I feel slow today…

I have to wonder though, why get rid of glOrtho? You are still changing both the projection and modelview matrices so I fail to see what you have really achieved other than making the code harder to read. When using glOrtho its more obvious what you are doing.

Well, I believe this is what happens when you call glOrtho()…

void
_math_matrix_ortho( GLmatrix *mat,
GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval )
{
GLfloat x, y, z;
GLfloat tx, ty, tz;
GLfloat m[16];

x = 2.0 / (right-left);
y = 2.0 / (top-bottom);
z = -2.0 / (farval-nearval);
tx = -(right+left) / (right-left);
ty = -(top+bottom) / (top-bottom);
tz = -(farval+nearval) / (farval-nearval);

#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = 0.0F; M(0,3) = tx;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = 0.0F; M(1,3) = ty;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = z; M(2,3) = tz;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = 0.0F; M(3,3) = 1.0F;
#undef M

matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
}

(taken from the mesa source code)

All this will be done on the CPU, as only the final matrix is uploaded to the GPU…
so, we’re saving a fair amount of calculation. Reason enough, I would have thought.

[edit]
Also, you no longer need to know the dimensions of the viewport to draw the quad…makes the code a bit tidier.

[This message has been edited by knackered (edited 04-22-2002).]

Couldn’t you just save that matrix after creating the RC and then load it instead of the identity matrix? That would eliminate all that code. Its what I do. As far as having to know what the viewport dimensions are, well, what’s wrong with that? You have to know that anyway, so I don’t see what you gain from using [-1…1] instead of [0, width] (if you wanted to use that range, nothing stopping you from using [-1…1] with glOrtho), etc.

DFrey, glLoadIdentity is much more optimised than loading an arbituary matrix.
I think you’re splitting hairs.

Originally posted by DFrey:
Couldn’t you just save that matrix after creating the RC and then load it instead of the identity matrix? That would eliminate all that code. Its what I do. As far as having to know what the viewport dimensions are, well, what’s wrong with that? You have to know that anyway, so I don’t see what you gain from using [-1…1] instead of [0, width] (if you wanted to use that range, nothing stopping you from using [-1…1] with glOrtho), etc.

the clue is he does NOT need to know the viewport, as left-right goes from -1 to 1 if you simply load the identities, and that always for the current viewport… now thats cool, isn’t it?

kieran, am I splitting hairs? Of course. That’s no mystery to me.

“… does NOT need to know the viewport …”

But that is not true! The viewport is a fundamental element of the render context. And again, there is nothing stopping one from using [-1,1] range with glOrtho. My argument centers on the readibility of the code, not its speed.

when you set all your matrices to identity, gl spec defines the viewport for glVertex and other functions that sets positions to -1 = left, 1 = right…

that means you don’t need to know the size of your currently glViewport… wich helps a lot if you dont know it and you would need to query it first with a glget, for example…

and

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glRectf(-1,-1,1,1);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();

it actually fits in this textbox… no faster way possible extept if you drop the pushs and pops (say you do it at the end anyways…

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRectf(-1,-1,1,1);

now that is short and easy, isn’t it?

well ok, glRectf does not send good texcoords as far as i know but for fullscreen drawing of a simple quad its usefull (for stencilshadows for example i used this one time

To hell with tex coords! Cheers for glTexGen!

i’m always for a simple little vertexprogram to bind… with glBegin(GL_QUADS);glVertex1ub(0);glVertex1ub(1);glVertex1ub(2);glVertex1ub(3);glEnd();

and the program uses the indecee for the right edge…
if you want to save mem-bandwith of the vertex-data

>>Zed, that doesn’t work at all. <<

true, (i just typed it in) z of 0 will most likely fall outside the near clip plane.

of course the whole thing is irrelavent, the bottleneck in the function is gonna be fillrate + not what calls u use to set up the vertices positions