Oblique vs Standard projection matrix

This article describes both the standard and oblique projection matrices. Note the differences. (Performance: the former requires an additional trig call, while the latter requires two extra divisions.)

According to Mathematics for 3D Game Programming and Computer Graphics, 2nd Ed., the oblique projection matrix is what is used internally by the deprecated function glFrustum(). While I do not know if this is speculation on the author’s part, Eric Lengyel is something of a long-time expert in graphics and computational geometry, so I am inclined to accept this as fact.

What I need to understand is:

[ul]
[li]What practical usage does an oblique perspective projection ever see? Is it ever used in games, for instance?[/li][li]In a programmable pipeline, is there any good reason why we would choose to use the oblique rather than the standard projection matrix (the latter being simpler since it essentially has fewer parameters)? I can only assume it was (reputedly) used in glFrustum() because that in fixed pipeline functionality, there is obviously a need to build for all possible use cases, and the oblique projection matrix would appear to be slightly more generalised case of the standard projection matrix.[/li][/ul]

Comments & discussions most welcome. I’m writing the transformation aspect of my vertex shader, hence the questions on the available options.

The standart matrix is just a special case of the oblique matrix where l = -r and b = -t (set it in and you will get the same matrices). You use the general case if you want to set your center of projection off to the left/right or up/down, e.g. for stereo rendering or if you want to render a tile of a larger image.

Internally gluPerspective can just call glFrustum with the appropriate params evaluated from it’s own params so there’s really no reason to make a call on it. In terms of performance/etc, no matter what type of projection matrix you use it’s the very same - 16 floats, so there’s absolutely no difference. Your GPU doesn’t care; it just multiples a 4x4 matrix by a position and what type of matrix it is or how it was constructed are totally irrelevant. Typically you construct a projection matrix at most twice per frame (e.g. if you were drawing a 3D view with a 2D GUI overlay) so number of trig ops vs number of divisions is so deep into the realm of micro-optimization that it’s silly.

You can find the mathematical derivation here and some code here. One of the biggest strengths of the oblique frustum is that you can make sure “the near plane of the standard view frustum is moved so that it coincides with a given arbitrary plane”. This is great for doing shader based reflections, e.g. mirrors or water, without the need to specifiy an additional clip plane in the shader. You calculate the view-projection-matrix once before rendering a particular reflection image using an oblique frustum projection. this will make the near plane coincide with the reflector, thus not include any objects behind/below the reflection surface. Afterwards you go back to your regular view-projection-matrix and render the reflector using the reflected image. The shader code for all that stays the same - all you need is one additional shader for the reflection plane.

I think I read somewhere that this technique is actually used in games for water rendering but I don’t remember where I got that.

Indeed. That’s why performance comments were in brackets. Even so, thanks for the input.

This is what I suspected. Thank you for confirming.

Aha! Now this is very interesting indeed. Considering I did want reflections at some later stage, and also noting what @menzel has confirmed about this being a generalised case (i.e. it may be used to exactly the same effect as the standard projection matrix), I think I will use the oblique projection matrix instead.

Thanks all :slight_smile:

There are two meanings for the word “oblique” here. In the wiki article you first cited, the word oblique means that the view frustum is off center, but the near and far planes are both still perpendicular to the direction the camera is looking. When talking about an “oblique near plane”, we mean an ordinary view frustum that’s still centered (as explained above with l = -r and b = -t), but the near plane is no longer perpendicular to the direction the camera is looking. The code on terathon.com pertains to the oblique near plane, which is very useful for clipping mirrors, water surfaces, portals, etc.

Hi Eric,

An honour indeed. Many thanks for your clarification.

To confirm: In essence the view direction is modified, but the orientation of the view planes is not? A bit like a skew operation on the frustum? What purpose(s) would this serve?

The view direction isn’t really modified, but yes, you can think of the position of the screen being skewed away from the center. The only place I’ve seen this used is in stereo projections where two cameras are separated by a little distance but their view frustums both have the same projection planes. The frustum for the left eye is oblique to the right a little, and the frustum for the right eye is oblique to the left a little.

Eric Lengyel: Incidentally, I assume the oblique frustum is used in C4 but do you know of any other major engine where it finds its application (talking about your derivation, not the earlier stuff by NVIDIA)? Just curious.

OT: May I contact you via PM regarding your book?

I know I’ve heard of some using it (other than C4), but I don’t remember exactly which ones off the top of my head.

Please email me (my last name at terathon.com).