Reputation: 53
I'm currently working on an application that will involve lots of camera movement. I've written my own lookAt
function which seems to be working properly. I now want to implement my own frustum
function. Currently I have a 1x1x1 cube centered at the origin. I am trying to change my view so that I can see from -2 to 2 on all axes as a check to see if my function is working properly.
Here is the code for my function:
mat4 frustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
{
mat4 f;
f.x.x = 2*near/(right-left);
f.y.x = 0;
f.z.x = (right + left)/(right - left);
f.w.x = 0;
f.x.y = 0;
f.y.y = 2*near/(top-bottom);
f.z.y = (top + bottom)/(top - bottom);
f.w.y = 0;
f.x.z = 0;
f.y.z = 0;
f.z.z = (far+near)/(far-near);
f.w.z = 2*(far*near)/(far-near);
f.x.w = 0;
f.y.w = 0;
f.z.w = -1.0;
f.w.w = 0;
return f;
}
I am passing in near, right and top as 2. far, left and bottom are being passed in as -2. When I call my function with these arguments it returns the following matrix:
┏ -1.000000 0.000000 0.000000 0.000000
┃ 0.000000 -1.000000 0.000000 0.000000
┃ 0.000000 0.000000 0.000000 -2.000000
┗ 0.000000 0.000000 -1.000000 0.000000
I am unsure if this is correct and my issue lies elsewhere or if something in the function is off.
Upvotes: 1
Views: 298
Reputation: 210889
I am passing in near, right and top as 2. far, left and bottom are being passed in as -2.
A negative value for the near plane is not valid. In perspective projection, the projection matrix describes the mapping of 3D points in the world, as seen from a pinhole camera, onto 2D points in the viewport. The perspective projection matrix defines a Viewing Frustum:
Hence the near plane and the far plane have to be positive values:
0 < near < far
A perspective projection matrix can be defined by a frustum.
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 of 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
The projection matrix is transforms from view space to clip space respectively normalized device space. In OpenGL, the view space is commonly a right-handed coordinate system and the normalized device space is a left-handed system. The projection matrix mirrors the z-axis to achieve the transformation. Therefore, the z components have to be inverted:
mat4 frustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
{
mat4 f;
f.x.x = 2*near/(right-left);
f.y.x = 0;
f.z.x = (right + left)/(right - left);
f.w.x = 0;
f.x.y = 0;
f.y.y = 2*near/(top-bottom);
f.z.y = (top + bottom)/(top - bottom);
f.w.y = 0;
f.x.z = 0;
f.y.z = 0;
f.z.z = - (far+near)/(far-near);
f.w.z = - 2*(far*near)/(far-near);
f.x.w = 0;
f.y.w = 0;
f.z.w = -1.0;
f.w.w = 0;
return f;
}
You need to make sure that the geometry is between the near and far planes of the viewing frustum. All the geometry which is out of the frustum is clipped.
Notice that the geometry with a view space Z coordinate of 0 will be clipped, because 0 < near < far
.
Upvotes: 2