What dimensions should you use for a perspective projection frustum?

What dimensions should you use for a perspective projection frustum? Initially I created a perspective matrix based on the width and height of the screen, with a calculated zNear value based on a 45degree FOV.

// OpenGL example
// For height of 800, zNear is calculated to be ~965.
zNear = (height / 2.0f) / tan(Deg2Rad(45.0f) / 2.0));
zFar = 100000.0f;
glFrustum(-width / 2.0f, width / 2.0f, -height / 2.0f, height / 2.0f, zNear, zFar);

But then I realised that this isn't a sensible idea and you shouldn't base your frustum on pixels, and you should use logical units instead (else when the window / screen changes size, objects will change position or size).

So now I'm wondering what dimensions I should use for the logical planes of the frustum? How do you choose a zNear value? Is it sensible to base it on the desired FOV? I'm aware that having a small zNear value can mess with the z-buffer, which is why I initially based it on the FOV.

My current thoughts are of using a logical near plane of TopLeft: -10000, -10000 and BottomRight: 10000, 10000. But then that generates a zNear value of ~24142 based on 45degrees FOV, which seems awfully high. What advice do you have? What dimensions should you use for a projection frustum?

zNear and zFar are measured in world space, not in anything to do with pixels. Their scale will depend on the scale of the scene you're rendering and how close/far the camera will be to the geometry. For instance, if your scene is modeled in meters, you might set zNear to 0.1 and zFar to 1000 or so. This would let you get the camera as close as 10 cm from the geometry before it starts clipping, and let you see distances of up to 1 km. You can adjust these values if you have a smaller or larger scene or if you use different units.

For most cases, it's simpler to use gluPerspective instead of glFrustum. That lets you work in terms of the FOV and aspect ratio, which is more convenient than the width/height of the image on the near plane. If you compare the formulas listed in the docs for gluPerspective and glFrustum you can see how these functions correspond to each other. They do the same thing, except that gluPerspective has more convenient parameters, and doesn't handle off-center frusta (which are uncommon anyway).

• Hi, I'm familiar with the difference between gluPerspective and glFrustum, but if you use gluPerspective, how do you know where to place your objects in world space? e.g. if you do gluPerspective(45.0f, 16.0f / 9.0f, 1.0f, 100.0f); then it results in a size of 1.47x0.83. But how would you know where to place your objects? Commented Apr 18, 2014 at 20:41
• @MarkIngram You can place them anywhere, but they will only be seen within a vertical FOV of 45 degrees and between 1 unit and 100 units away from the camera. You need to choose your units however you like them. If the units are meters, then the frustum will cover 100 meters. Where you place your objects depends on where you want them to appear in the viewport (and how far away). Commented Apr 18, 2014 at 20:45
• @JosephMansfield Hi, I realise the dimensions are logical, but you don't actually know the size of the viewport, if you use gluPerspective. Unless you manually calculate it yourself. i.e. if the size is 1.47x0.83 (see comment above) then you need to know to place all your objects within that area. Commented Apr 18, 2014 at 20:49
• @MarkIngram That's the nature of 3D rendering. Games typically allow the player to adjust the FOV, because the most comfortable FOV depends on the size of their display and their distance from it. The comfortable FOV for a smaller or further away display will give a smaller view of the game world, simply because the player is effectively looking through a smaller window into that world. You could do the maths to ensure that all objects are placed within the frustum, but that means that a smaller FOV will squash the objects together. Commented Apr 18, 2014 at 20:59
• @JosephMansfield So if you specify a FOV, how do you know the dimensions of your zNear plane? If you're laying out a scene, how do you arrange the objects? If I use glFrustum, then I know the dimensions of the zNear plane, so I know exactly where I can place my objects. Commented Apr 18, 2014 at 21:53

zNear is not really related to field of view. FOV specifies the angle of the frustrum, while zNear describes the distance to the nearest clipping plane. As an example, here are two frustrums with the same FOV, but different near clipping planes.

And here is another frustrum with the same zNear as the first, but different FOV.

A good approach to clipping planes is simply to put the zNear as far away as possible and the zFar as near as possible, while still encompassing your world. Putting zNear closer to the camera than any world object will ever sit is a waste of Z-buffer values that will never be used. If your world isn't very large, you don't need to worry about this too much, as you have plenty of Z-buffer to spare. If you're trying to render an insect 1cm from the camera at the same time as mountains 10km away... you'll probably experience some issues with Z-buffer precision!

As the diagrams should hopefully illustrate, it's actually the width and height of the frustrum that really depend on FOV.

And finally, a tip that really helped me: there are helper functions to ease the calculation of frustrums. Check out gluPerspective(). Instead of doing the math yourself, you just pass it FOV, aspect ratio, zNear, and zFar, and it will helpfully calculate the other 4 boundaries of the frustrum for you.

• Hi, I've got my own versions of glFrustum and gluPerspective, so I'm familiar with the maths, it's just knowing what dimensions to use, and if I use gluPerspective, then how do I know where to place my objects in the world? i.e. if the size is equal to 1.47x0.83 as calculated by gluPerspective, then how do I know where to put the objects? Commented Apr 18, 2014 at 20:44
• Sorry - how do you obtain that size? The frustrum is a 3D shape, I'm not sure what that 2D size describes. Are you referring to the size of your zNear rectangle? If your objects are all distance D from the camera, the size of the screen in world space at D is given by D * tan(FOV/2). That gives you the height since FOV refers to the Y coordinate - use the aspect ratio to get the width Commented Apr 18, 2014 at 21:06
• If I'm not understanding you correctly... could you explain where on this frustrum you mean when you say "size"? upload.wikimedia.org/wikipedia/commons/thumb/8/8f/… Commented Apr 18, 2014 at 21:14
• Yes, I was referring to the zNear plane / rectangle. My size was based on the comment I made on the other answer in this thread. I guess I'm puzzled by whether the FOV, or the zNear plane size is the most important thing. Should I try to enforce a zNear plane of size X by Y, or just enforce a FOV? Commented Apr 18, 2014 at 21:34
• @MarkIngram Normally you pick the FOV and let the zNear plane size be whatever it is. The zNear plane size is really irrelevant for the process of modeling a scene and rendering. Commented Apr 19, 2014 at 4:34