switching between two OpenGL matrices

Bit of a noob question methinks. :smiley: I have a game with 2D and 3D stuff to draw. I’ve been doing this:


// setup 3D matrix
while (true) {
   GL11.glMatrixMode(GL11.GL_PROJECTION);
   GL11.glPushMatrix();
   GL11.glLoadIdentity();
   GL11.glOrtho(0, 480, 320, 0, 1, -1);
   GL11.glMatrixMode(GL11.GL_MODELVIEW);
   GL11.glPushMatrix();
   GL11.glLoadIdentity();
   // draw 2D stuff
   GL11.glMatrixMode(GL11.GL_PROJECTION);
   GL11.glPopMatrix();
   GL11.glMatrixMode(GL11.GL_MODELVIEW);
   GL11.glPopMatrix();
   // draw 3D stuff
}

Is this the right approach? Now I have the need to switch between drawing 2D and 3D stuff many times per frame, so that the graphics are layered correctly. What would the most efficient way to do this?

Are you rendering translucent stuff, or can you get away with just relying on the z-buffer?

Some layers are translucent, yes. Am I able to use the depth buffer when some stuff is ortho and some is perspective?

Good question. I would think you’d be OK as long as the near and far clip planes are the same.

Since you’re rendering translucent stuff, you are pretty much limited to rendering in back-to-front order, so it’s either:

  • Live with the matrix changes (are they actually a problem?)
  • Scale the 2D layers based on their distance from the camera to counteract the perspective view matrix

edit: actually less sure about the z-buffer being OK - it’s farther between the corners of the near and far clip planes than it is in the center with a perspective projection. No idea what would happen there.

True, I don’t know that the matrix changes will be a problem. I just see I’m going to be switching them a bunch, so was wondering if there are any tricks I’m missing, or if I should even worry about this.

My perspective layers are drawn at an angle. It might be pretty tricky to fake ortho and still get the layers drawn at the correct depths.

FWIW, I’m also implementing this on the iPhone. Below are the current OpenGL calls, organized a bit differently than the LWJGL above:


// setup 2D view
while (true) {
   // draw 2D stuff
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glLoadIdentity();
   glRotatef(...);
   glFrustumf(...);
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   glLoadIdentity();
   glMultMatrixf(...);
   glTranslatef(...);
   // draw 3D stuff
   glPopMatrix();
   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
}

It certainly seems like a lot of stuff, especially if that is happening multiple times per frame. Is the way I’m doing this ideal? Does it matter if I push and pop ortho or would it be better to push and pop perspective?

If the Matrix changes are a problem (profile it), you can just aggregate the needed 2d-stuff in some way (make yourself a descriptor object, which stores what you need to do in 2d and append it to a list) and draw all the 2d stuff in the end after one matrix change.

Unfortunately, I can’t do that. I need to draw some 2D stuff, then some 3D stuff on top, then more 2D stuff, then more 3D stuff, etc. That I need to layer the 2D and 3D stuff means I need to change the matrix a lot, it seems.

Matrix manipulation (glLoadIdentity, glRotatef, etc.) is all cpu side. Only when you actually start drawing a batch is the final matrix sent to the graphics card.

If you really want to you could handle all the matrix maths yourself and just use glLoadMatrix (so you’d just need glMatrixMode() and glLoadMatrix() between each switch) but I think you’d be wasting your time.

There’s a (significant) overhead to each call to opengl in java due to JNI, so that speaks a lot for doing the math yourself and using glLoadMatrix()
However, glLoadMatrix is almost always slower than glTranslates and glRotates, as those are quite heavily optimized.

If you’re simply switching back and forth between two modes, I’d suggest using display lists.
It’s a single glCallList per switch, and it’s super duper fast.