Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do the arguments for frustum in OpenGL mean?

I've understood that a frustum is a clipping cube inside which the camera can see. I just don't understand the arguments needed to define it. From here, it looks like you specify parts of some kind of space. But for example, top and bottom of what? What do ratio and -ratio represent? Here's an example function that I'm talking about:

Matrix.frustumM(matrixHandle, 0, ratio, -ratio, -1, 1, 3, 7);
like image 375
Muteking Avatar asked Apr 26 '14 11:04

Muteking


2 Answers

Ok, let's start with the last two parameters. They specify the near and far clipping planes. They actually specify how far they are from the camera.

The far plane doesn't really affect transformation, but if the distance of an object from the camera is greater than the specified far plane, you won't see it. That being said, you should probably set it to a reasonable value because it affects how the depth value is calculated.

The depth is usually stored in 8 bits (don't hold me to that) so you essentially only have 256 possible depths. That means that if your far clipping plane is really high, two objects that are close to each other might get the same depth value even though one of them is behind the other. This results in something called z-fighting. There's a wiki article on that http://en.wikipedia.org/wiki/Z-fighting.

Ok. So that's the far plane. Now, the left/right, top/bottom ones. Imagine a rectangle that has the following vertices (left, top), (right, top), (right, bottom), (left, bottom). You then take that rectangle, and move it away from the camera as much as is specified in the near plane argument. Then you draw lines from the camera through each of the vertices. Then you take an infinite plane (parallel to rectangle you just moved) and place it as far away from the camera as specified by the far plane argument. The places where your four lines intersect that infinite plane are the vertices of a new rectangle that will represent the back of your view frustum.

Your frustum now consists of those two rectangles and the lines connecting them.

The reason for those ratio, -ratio arguments is because the example chose 1 and -1 for the top and bottom values. The aspect ratio of your screen, for example, is expressed as width/height. This means that you get the width of the screen by multiplying the height with the aspect ratio. This is the same thing. The right value should be ratio * top but since top is 1, just the ratio remains.

Now this is all pretty abstract stuff. It's kind of hard to visualize how each of those parameters affect the actual image. Luckily, there's this pretty great thing that lets you play with the values http://relativity.net.au/gaming/java/Frustum.html

Try changing the left and right to -2 and 2. This results in the image being squished horizontally. As you can see, the actual "window" there is square shaped, but if it were instead twice as wide as it is tall, the image would stretch back to original proportions.

If we kept -1, 1 values with that kind of a window, the image would appear stretched out.

like image 117
Luka Horvat Avatar answered Nov 11 '22 17:11

Luka Horvat


A frustum is not a cube, it is just a ..., well, a frustum. In computer graphics, one uses pryamid frustums to represent perspective projection. The eye point represents the top of the pyramid, and it has a rectangular base (since that is the shape defined by most display devices, and windows are typically rectangular, too). The frustum itself defines (or is defined by, as a matter at how you look at it) by the angles - the field f view - both in vertical and horizontal dimensions, the near and far planes limiting the pyramid, and the horizontal and vertical shift for "off axis-projection" (just like lens shift of projectors). Most of the time, a symmetric frustum is used, however, those 6 degress of freedom do exist. And the classic frustum() function of GL or of matrix libraries also has 6 parameters, but the way the frustum is defined is a bit different:

The parameters near and far define the distances to the near anf far clipping plane, respectively (along the viewing direction). As a side node: in OpenGL, often the convention is used that the viewing direction is along -z, and the near and far parameters are interpreted to mean z=-near and z=-far instead, since those should lie in front of the camera.

The rest of the parameters, left, right, top and bottom are interpreted as on the near plane - they define an axis-aligned rectangle on the z=-near plane. So the field of view angles are defined through the relation of those parameters and the near value. For a symmetric frustum (which means that the center point your camera is directed at will appear in the center of your viewport), you should set the parameters such that left=-right and bottom=-top.

From here looks like you specify parts of some kind of space. But for example, top and bottom of what?

You should be aware that this is just a transformation matrix. Typically, you have some kind of view transformation which transforms the vertex coordinates into an eye space, where the camera is a at a well-defined location and oriented in a well defined way, like camera is at origin and looking into -z direction. The perspective projection is achieved by then applying a projection matrix, as the one you get from a frustum() function. So the space the parameters of the frustum() function are interpreted in are the eye space, and are to be intrerpreted relative to your camera position and orientation.

What do ratio and -ratio represent?

Well, one could say thay are just some values defining some symmetrical horizontal field of view. However, you should be aware that the projection matrix typically takes the aspect ratio of your output window into account. If your window is wider than it is tall, your horizontal field of view will be greater than the vertical field of view (otherwise you will get some distortion and objects which are square in eye space will not appear as squares in window space). To keep the apsect ratio, the ratio (right-left) / (top-bottom) of your parameters should equalt the aspect ratio (width/height) of your window - so the ratio in your example is very likely just the aspect ratio.

like image 37
derhass Avatar answered Nov 11 '22 19:11

derhass