glOrtho and the z-buffer


I’m trying to populate the z-buffer while drawing quads in glOrtho() mode, so that the quads are correctly obscured by the objects that were previously drawn in gluPerspective() mode. Has anyone seen a conversion formula to keep the z-buffer correct when using these modes together?

My code looks like this:

gluPerspective(45, x/y, 1, 1000);
draw 3D objects

glOrtho(0, x, 0, y, -1, 1);
draw quads on screen

Your near/far-plane distances have to be equal in both projections.
Your perspective projections uses (1, 1000) the orthogonal projection (-1, 1)

I don’t think you can just mix objects projected with orthogonal and perspective projection like that.

AFAIK does the orthographic projection create a linear distribution of z-values, while the perspective projection does not.

Define “correctly obscured”.

Thanks guys.

Yes, I realize that in perspective mode the z-buffer values are not linear. In Ortho, they are linear. That’s why I am asking for a formula to join the two modes.

“correctly obscured” would mean that in Ortho-mode, I could correctly determine a z-value that would draw a 2D quad behind or in front of a 3D quad.

I can make this happen by experimenting with random or sequenced values, but I cannot figure out a ratio or formula to make the modes work together predictably. Trying to make this work has made it clear to me why nobody works with voxel terrain any more.

Please let me know if you think of something to try.


This shouldn’t be too difficult.

The z-buffer is (unless you bound the z-range) between 0 and 1, regardless of the state of the projection matrix. It is the projection matrix’s job to go from camera-space Z to the [0, 1] Z.

All gluPerspective does is set up the projection matrix. It creates this transform. glOrtho does the same thing. It just so happens that the perspective transform isn’t linear. That’s not a problem.

What you need is a function F(z) that takes a z in camera space and transforms it as the perspective matrix does, returning the post-projection depth value on the range [0, 1]. Converting that to the pre-ortho-projection space is trivial, since ortho space is linear.

Fortunately, this function has already been written for you: gluProject. The X, Y values don’t matter, since you’re only looking for Z. This returns the post-projection depth, which you can easily transform into the ortho space.

That’s some good information, Korval. I currently use gluProject to convert 3D points to screen coordinates. gluProject can be super slow if it requires a call to glGetFloat(). What you’ve written may help me solve this. I’ll work on it and let you know.