问题描述
我目前正在开发一个涉及很多相机移动的应用程序。我已经编写了自己的lookAt
函数,该函数似乎正常工作。现在,我想实现自己的frustum
函数。目前,我有一个以原点为中心的1x1x1立方体。我正在尝试更改视图,以便可以在所有轴上从-2到2进行查看,以检查我的功能是否正常运行。
这是我的函数的代码:
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;
}
我传入的是近端,右边和顶部,为2。远端,左边和底部都以-2传入。 当我使用这些参数调用函数时,它将返回以下矩阵:
┏ -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
我不确定这是正确的,还是我的问题出在其他地方,或者该功能是否已关闭。
解决方法
我传递的是近,右和顶部为2。传递的是远,左和底部为-2。
近平面的负值无效。在透视投影中,投影矩阵描述了从针孔相机看到的世界中3D点到视口中2D点的映射。透视投影矩阵定义Viewing Frustum:
因此,近平面和远平面必须为正值:
0 < near < far
透视投影矩阵可以由frustum定义。
距离left
,right
,bottom
和top
是指从视图中心到视锥面在近平面上的距离。 near
和far
指定到截头锥体的近平面和远平面的距离。
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
投影矩阵是从视图空间转换为剪辑空间或分别归一化的设备空间。在OpenGL中,视图空间通常是右手坐标系,而规范化的设备空间是左手坐标系。投影矩阵镜像z轴以实现变换。因此,z分量必须反转:
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;
}
您需要确保几何形状在视锥的近平面和远平面之间。截去了所有平截头体之外的几何体。
请注意,由于0 < near < far
,视图空间Z坐标为0的几何将被裁剪。