1. 问题的引出
这个问题的引出又是因为《3D游戏编程大师技巧》这书里面有的问题没讲明白,有的东西又不对。
首先宽高比这个名词的出现是因为我们的PC屏幕不是正方形的,屏幕宽度 : 屏幕高度 就是宽高比。但是我们上次搭建的相机系统的视平面是正方形的,那么当很多物体投影到视平面上后,必然最后完成的是一幅正方形的画,而屏幕是长方形的,这时只有两种办法:
1) 把照片压扁,这样画上的所有物体都被压扁了。
2) 把照片上下多余的两条分别裁下来,只保留屏幕大小的画,这样物体不会走样变形,但是这幅画有一部分看不到了。
哪种是正确的?
以人眼为例,我们的眼睛不可能因为眼睛的外框不是正方形就把东西压扁吧,所以我们要做的是不要多余的上下两条边,而不是把物体压扁。
2. 两种方式
我们可以想到有两种方法来做这件事:
1) 如Hello3DWorld这样,在已经变换到了屏幕系的图像上动手脚,把图像的多余上下边舍弃。
2) 我们将yz平面的FOV不设置为与xz平面的FOV相同,而是使视平面的宽高比和屏幕的宽高比相同。这样,上下裁剪面的方程就会有所变化,直接会将原本会出现在多余的两边的东西裁掉,也就是在3D空间裁剪做完之后,再投影到视平面上的结果已经不是正方形了,而是和屏幕的比例相同,也就是在实质上对纵向的视野进行了操作。这样的好处是在物体剔除时可以剔除更多的物体,也不需要再进行2D图像裁剪了。所以我们应该使用这种方法。
如果修改了上下裁剪面方程,从透视投影到屏幕变换的新的过程将会是这样:
得到的已经是最后的屏幕坐标了。
3. 修改生成上下裁剪面的代码
还记得如何生成上下裁剪面吗?上一篇文章讲的很细了,这里不再重复了。现在所作出的改变就是取那特殊的两点的坐标发生了变化。比如上裁剪面,以前是(-1,1) (1,1),现在变成了(-1, 1/ar) (1, 1/ar)。
把新的坐标代进求叉乘,求新的上裁剪面法向量,得:<0, d, -1/ar>
下裁剪面法向量:<0, -d, -1/ar>
这是新的创建相机的函数代码: