Reputation: 840
I'm trying to create a 3D manipulation program using C++ and openGL. I'm relatively new to openGL so I often have to look up the documentation to find the right function to do what I want. I thought I had a good understanding of orthogonal vs perspective projections (in that glOrtho
creates an orthogonal projection where different z-values don't look different and glFrustum
creates a perspective projection where z-values that are closer look bigger). However, when I swap out glOrtho
and glFrustum
in my program, I don't see any difference. I replicated a small program below that shows the effects. For reference, I'm using openGL with freeglut.
#include "GL/freeglut.h"
void initFunc()
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glColor3f(1.0f, 1.0f, 0.0f);
glLineWidth(1.0f);
glutWireTeapot(0.3);
glTranslatef(0, -0.5, -0.5);
glutWireTeapot(0.3);
glutSwapBuffers();
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Teapot Perspective");
initFunc();
glutDisplayFunc(displayFunc);
glutMainLoop();
}
I'm drawing two teapots slightly offset in both the y and z axes. From what I understand, the glOrtho
should render the two teapots as identical with only a y offset, whereas the glFrustum
should render one of them bigger than the other. However, both of them render the teapots identically.
Am I missing something here? Are there other steps I have to take to properly set up a perspective projection? Or am I misunderstanding how glFrustum
works? I've also tried using gluPerspective
instead of glFrustum
but I can't seem to find the right values to use. I experimented with a FOV of 90, aspect of 1, and various z values but they all either produce no teapot, or a teapot distorted beyond recognition. Furthermore, the gluPerspective
appears to have different behavior than a glFrustum
call with corresponding parameters. I'm not sure what I'm missing here.
Upvotes: 1
Views: 2343
Reputation: 211176
At Orthographic Projection the coordinates in the view space are linearly mapped to clip space coordinates and the clip space coordinates are equal to the normalized device coordinates, because the w
component is 1 (for a cartesian input coordinate).
The values for left, right, bottom, top, near and far define a box. All the geometry which is inside the volume of the box is "visible" on the viewport.
The Orthographic Projection Matrix, defined by glOrtho
is:
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2/(r-l) 0 0 0
y: 0 2/(t-b) 0 0
z: 0 0 -2/(f-n) 0
t: -(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport.
The eye space coordinates in the camera frustum (a truncated pyramid) are mapped to a cube (the normalized device coordinates).
A perspective projection matrix can be defined by a frustum (glFrustum
).
The distances left
, right
, bottom
and top
, are the distances from the center of the view to the side faces of the frustum, on the near plane. near
and far
specify the distances to the near and far plane on the frustum.
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2*n/(r-l) 0 0 0
y: 0 2*n/(t-b) 0 0
z: (r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1
t: 0 0 -2*f*n/(f-n) 0
A specification like this from you question:
glFrustum(-1, 1, -1, 1, -1, 1);
does not define a proper frustum, because the value for the near plane is negative and the value for the far plane is positive.
If you would check for OpenGL errors (by glGetError
), then you would get an INVALID_OPERATION
error.
void Frustum( double l, double r, double b, double t, double n, double f );
the coordinates (
l
b
−n
)T and (r
t
−n
)T specify the points on the near clipping plane that are mapped to the lower left and upper right corners of the window, respectively (assuming that the eye is located at (0 0 0)T).f
gives the distance from the eye to the far clipping plane.Errors An INVALID_VALUE error is generated if
n <= 0
,f <= 0
,l == r
,b == t
, orn == f
.
Upvotes: 3