参考课程P4:
https://www.bilibili.com/video/BV1X7411F744?p=4
注:关于这部分知识,可以参考冯乐乐 Unity Shader入门精要的4.6节,会有实例讲述MVP的全过程,我也会在后续笔记中做记录。
我们可以这样来描述视图变换的任务:将虚拟世界中以(x,y,z)为坐标的物体变换到 以一个个像素位置(x,y) 来表示的屏幕坐标系之中(2维),这确实是一个较为复杂的过程,但是整个过程可以被细分为如下几个步骤:
- 模型变换(modeling tranformation):这一步的目的是将虚拟世界中或者更具体点,游戏场景中的物体调整至他们应该在的位置
- 摄像机变换(view/camera tranformation):在游戏中我们真正在乎的是摄像机(或者说眼睛)所看到的东西,也就是需要得到物体与摄像机的相对位置
- 投影变换(projection tranformation):根据摄像机变换得到了所有可视范围内的物体对于摄像机的相对位置坐标(x,y,z)之后,便是根据是平行投影还是透视投影,将三维空间投影至标准二维平面([-1,1]^2)之上 (tips:这里的z并没有丢掉,为了之后的遮挡关系检测)
- 视口变换(viewport transformation):将处于标准平面映射到屏幕分辨率范围之内,即[-1,1]^2 ->[0,width]*[0,height], 其中width和height指屏幕分辨率大小
M在前面的坐标变换中已经说了,现在重点看view/camera tranformation。
一、view/camera tranformation
1.相机的定义
image.png- 相机的位置 e
- 相机看向的方向 g
- 相机向上的方向 t
2.相机位置
image.png上面的截图说的是,考虑到运动的相对性,如果相机和物体一起移动,那么拍出来的照片是相同的。沿着这种思路,把相机放在世界坐标的原点,并让坐标轴与世界空间重合,然后再让物体移动,就能达到同样的效果。
这里也介绍一下正常的思路,根据基变换的思路。要得到世界坐标的物体在相机空间的坐标,可以把世界坐标的基转换到相机空间。以Unity举例,我们更容易获得的是摄像机在世界空间中的坐标,所以需要对这个变换进行求逆,才能得到我们的目标矩阵。
这两种思路,最终选择的是把相机移到原点的思路。视频中说到这样做的好处:会让操作得到简化
3.移动相机的具体步骤
image.png因为相机到达目前的位置,是先进行了缩放、旋转,再平移。现在为了恢复到原点,就是逆过来操作,需要先做逆平移,再做逆旋转。如下图:
image.png
相机旋转到世界坐标轴的矩阵是很难写的,但是反过来世界坐标轴旋转到相机当前的基坐标却很简单,即从x旋转到g叉乘t(也就是e),y旋转到t,z旋转到-g非常简单,如图:
这里看过前面的线代系列,加上右手法则,很容易理解
然后再去求这个变换的逆,就是我们想要的目标了。而旋转矩阵是一个正交矩阵,直接转置即可得到最终答案:
image.png
上面的公式只是讲述了原理,具体例可以参考冯乐乐 Unity Shader入门精要的4.6节。
二、projection
1.正交投影 orthographic
image.png把左侧的立方体,映射到中心的标准立方体。这样做是为了什么呢?大佬没有讲,有弹幕说是为了裁剪。
其中,l,r,b,t,f,n对应的是left,right,bottom,top,far,near。因为我们现在右手坐标系,相机是向-Z方向看,所以离我们远的物体,它的Z值是更小的。这样就有点反直觉,因为感觉上,值越大,应该是离得越远。如果是左手坐标系,就不会有这个问题。
操作步骤很简单,先平移,再缩放:
image.png
平移的数值是在求中点,正负号可以忽略,图中这个位置才是负的。然后缩放是因为要放到一个-1到1,即长度为2的正方体里,缩放倍数就是r-l/(2/r-l)=2
有人提问,这样处理之后,正方体就被拉伸了呀,答案是所有物体放到-1,1的立方体后,后续还会做视口变换。
2.透视投影 prerspective
image.png把那个远平面挤压成和近平面一样大,再做一个正交投影就达到目的了。挤的要求:
- 近平面不变
- 远平面在收缩时,Z轴的值不能变,即f值不能变
- 远平面的中心点不能变
为了做这个挤压操作,可以切开来看:
image.png
这里利用相似三角形即可,然后齐次坐标,是可以同时扩大z倍的,就得到如下结果:
image.png
这里z为什么是unknown呢,弹幕里有人表示,两个平面的z确实没变,但中间的那些点都是不一样的。 image.png
现在已经能得到这个矩阵的一部分数值了。剩下的事情就是算出问号部分的。现在已知:
近平面的Z是不变的,即x,y,n,1。这里利用齐次坐标的性质变成这样:
image.png
现在思路一下,什么样的矩阵左乘x,y,n,1。能在第三行出现一个n^2呢,那必然是一个前两个格子都是0的矩阵,这样才能把x,y都消掉:
image.png
这里可能不好理解,为什么要构造一个n^2,其实是类似高中时那种特殊值求函数的思路,也可以叫特殊系数法。
现在还一个条件,即远平面的中心点0,0,f,1映射完之后还是0,0,f,1。这里利用齐次坐标的性质变成这样:
image.png
所以根据远平面就可以得到Af+B=f^2
然后结合上面根据近平面得到的结论:
image.png
两个式子联合:
image.png
现在可以完成最后一步了:
image.png
网友评论