一.前提
Games101 lecture4-lecture5
考虑将三位物体转换二维图像需要的步骤,我们需要以下变换来达成目的,
model transformation(模型(基础)变换--Object就位)
view/camera transformation(视图变换--调整相机)
projection transformation(投影变换--变换到[−1,1]3,忽略深度信息z,变成[−1,1]2)
viewport transformation(视口变换--投影到屏幕空间)
如下图所示(Fundamentals of Computer Graphics (3rd Edition) 7.1 Viewing Transformations Figure 7.2):

二.视图变换
首先需要定义一个相机,一个相机有三个属性,位置(Positon)ee,观测方向(Look-at/ gaze direction)gg和向上方向(Up direction)tt。
同时只要相机和物体之间没有相对运动,观测结果就不会改变,则可以让相机固定在原点,向上方向为Y方向,看向−Z方向,而这就需要通过变换矩阵Mview来自达成(需要注意的是物体也会随着相机移动而移动,因为要保证两者之间没有相对运动),该矩阵需要完成如下操作:
- 将原来在任意点ee的相机平移到原点
- 将观测方向gg旋转到−Z方向
- 将向上方向tt旋转到Y方向
- 将{ggXtt}方向旋转到X方向(当前两个方向旋转完成之后,X方向自然对齐)
如下图所示:

Mview先平移在旋转(和仿射变换不同),即Mview=RviewTview。
最后结果如下:
Mview=RviewTview=⎡⎢
⎢
⎢
⎢⎣xgXtygXtzgXt0xtytzt0x−gy−gz−g00001⎤⎥
⎥
⎥
⎥⎦⎡⎢
⎢
⎢⎣100−xe010−ye001−ze0001⎤⎥
⎥
⎥⎦
1.推导过程
首先是平移到原点,可以很自然的写出其平移矩阵Tview如下:
Tview=⎡⎢
⎢
⎢⎣100−xe010−ye001−ze0001⎤⎥
⎥
⎥⎦
接着考虑旋转,将任意方向旋转到X,Y,−Z方向上不容易写出,但是可以考虑其逆变换,写出将X(1,0,0),Y(0,1,0),Z(0,0,1)旋转到{ggXtt},tt,−g−g的旋转矩阵R−1view,并且由于旋转矩阵是正交矩阵,所以只要写出R−1view,其转置矩阵即为所求,如下所示:
R−1view=⎡⎢
⎢
⎢
⎢⎣xgXtxtx−g0ygXtyty−g0zgXtztz−g00001⎤⎥
⎥
⎥
⎥⎦
可以通过将上述矩阵应用与三轴来检验其正确性。Rview如下所示:
Rview=R(−1)(−1)view=RTview=⎡⎢
⎢
⎢
⎢⎣xgXtygXtzgXt0xtytzt0x−gy−gz−g00001⎤⎥
⎥
⎥
⎥⎦
所以最终的Mview如开头所示。
三.投影变换
投影变换目的就是将物体变换到[−1,1]3。想要得到二维图像,可以去掉z,变成[−1,1]2。变换分为两种,正交(orthographic)投影和透视(prespective)投影。透视投影存在近大远小的现象,而正交投影则不会,这是两者的本质区别,两者分别如下图所示:
图片来源:https://stackoverflow.com/questions/36573283/from-perspective-picture-to-orthographic-picture

上图中透视投影围成一个视锥(四棱锥),而视锥中从某一个深度到另一个深度之间的区域叫做frustum,而透视投影就是将frustum中的东西显示到近平面(Near clip plane)上。
1.正交投影(右手系)
首先定义一个空间中的立方体(只需定义6个面,左右上下前后),[l,r]x[b,t]x[f,n],需要注意的是远平面(f)和近平面(n),有nn>ff因为看向−Z(右手系),所以物体越远则其对应的Z的值越小,反之越大。如果是左手系则越远Z越大,因为看向的+Z方向。然后将立方体中心平移到原点,并将其缩放成canonical(正则规范标准立方体) cube[−1,1]3,忽略z,则变为[−1,1]2。
如下图所示:

先将立方体中心(r+l2,t+b2,n+f2)平移到原点,然后缩放到[−1,1]3(长宽高为2),这里的缩放其实就是将立方体的长宽高缩放为2,其变换矩阵Mortho如下:
Mortho=⎡⎢
⎢
⎢
⎢
⎢
⎢⎣2r−l00002t−b00002n−f00001⎤⎥
⎥
⎥
⎥
⎥
⎥⎦⎡⎢
⎢
⎢
⎢
⎢
⎢⎣100−r+l2010−t+b2001−n+f20001⎤⎥
⎥
⎥
⎥
⎥
⎥⎦=⎡⎢
⎢
⎢
⎢
⎢
⎢⎣2r−l00−r+lr−l02t−b0−t+bt−b002n−f−n+fn−f0001⎤⎥
⎥
⎥
⎥
⎥
⎥⎦
2.透视投影
(1)视锥定义
透视投影的视锥定义只要定义两个东西1.垂直可视角度Y 2.宽高比aspect,如下图所示:

从侧面观察,则近平面距离相机距离为|n|,如下图所示:

(2)怎么做透视投影Mpersp=MorthoMpersp−>ortho
- 首先将frustum挤压成一个长方体(Mpersp−>ortho)([l,r]x[b,t]x[f,n],);
- 然后再做一次正交投影(Mortho,已知)。即可完成投影到近平面的任务。
如下图所示:

(3)前提规定
-
在挤压过程(第一步)中frustum的近平面n上点不变;
-
f平面的Z值不变,因为只是在收缩;
-
f平面的中心点是不会改变的(挤压完还是中心点)。
(4)推导过程
先单独考虑挤压过程,我们需要找到一个矩阵来完成变换。
考虑下图,从视锥的侧面看,我们需要将(x,y,z)挤压到和近平面上点(x′,y′,z′)一样的高度,考虑相似三角形,则有y′=nzy;同理(从上面看),对于x而言有x′=nzx。
需要注意的是,这里nn,zz在图上表示的是距离原点的距离(负Z方向),所以是个负数。

至此,已知挤压过程x,y的变换,z未知,将上述变换用齐次坐标,同时在基础变换中我们提到过对于齐次坐标而言,(x,y,z,w)T(w!=0)表示的点即为(xw,yw,zw,1)T。 所以有如下关系:
Mpersp−>ortho⎡⎢
⎢
⎢⎣xyz1⎤⎥
⎥
⎥⎦=⎡⎢
⎢
⎢
⎢⎣nzxnzy?1⎤⎥
⎥
⎥
⎥⎦同乘z=⎡⎢
⎢
⎢⎣nxny?z⎤⎥
⎥
⎥⎦
从中可以反推出Mpersp−>ortho如下:
Mpersp−>ortho=⎡⎢
⎢
⎢⎣n0000n00????0010⎤⎥
⎥
⎥⎦
同时因为挤压过程中近平面点不变,远平面点Z值不变。则对于一个近平面上点(x,y,n,1)T(假设近平面上的z的值为n)。考虑齐次坐标中一个点可以有很多不同的表示,同理则有(x,y,n,1)T同乘n=(nx,ny,n2,n)T变换后是不变的。所以有如下关系:
Mpersp−>ortho⎡⎢
⎢
⎢⎣xyn1⎤⎥
⎥
⎥⎦=⎡⎢
⎢
⎢⎣nxny?z⎤⎥
⎥
⎥⎦=⎡⎢
⎢
⎢
⎢⎣nxnyn2n⎤⎥
⎥
⎥
⎥⎦
则可以推出变换矩阵的第三行为(0,0,A,B),即有式子(1)如下:
[00AB]⎡⎢
⎢
⎢⎣xyn1⎤⎥
⎥
⎥⎦=n2(1)
再考虑f平面中z不变,且中心点不变,则对于其中心点(0,0,f,1)(假设远平面上z值为f)。则有如下关系式子(2):
⎡⎢
⎢
⎢⎣00f1⎤⎥
⎥
⎥⎦同乘f=⎡⎢
⎢
⎢
⎢⎣00f2f⎤⎥
⎥
⎥
⎥⎦⇒[00AB]⎡⎢
⎢
⎢⎣00f1⎤⎥
⎥
⎥⎦=⎡⎢
⎢
⎢
⎢⎣00f2f⎤⎥
⎥
⎥
⎥⎦(2)
由(1)(2)可得,如下结果
{An+B=n2Af+B=f2⇒{A=n+fB=−nf
则有
Mpersp−>ortho=⎡⎢
⎢
⎢⎣n0000n0000n+f−nf0010⎤⎥
⎥
⎥⎦
所以透视投影变换矩阵计算如下:
Mpersp=MorthoMpersp−>ortho=⎡⎢
⎢
⎢
⎢
⎢
⎢⎣2nr−l0−r+lr−l002nt−b−t+bt−b000n+fn−f−2nfn−f0010⎤⎥
⎥
⎥
⎥
⎥
⎥⎦
(5)Question:frustum中间的点的变化
在frustum中间任何一个位置,比如点(x,y,n+f2,1)T,经过挤压之后(不做第二步正交)更加靠近远平面还是近平面?(远平面)
推导过程
先将Mpersp−>ortho应用到该点上,如下:
Mpersp−>ortho⎡⎢
⎢
⎢
⎢⎣xyn+f21⎤⎥
⎥
⎥
⎥⎦=⎡⎢
⎢
⎢
⎢
⎢⎣nxny(n+f)22−nfn+f2⎤⎥
⎥
⎥
⎥
⎥⎦规范化,同除以n+f2=⎡⎢
⎢
⎢
⎢
⎢
⎢
⎢⎣2nxn+f2nyn+fn+f−2nfn+f1⎤⎥
⎥
⎥
⎥
⎥
⎥
⎥⎦
比较变换前后两点的Z值大小,如下:
n+f−2nfn+f−n+f2=n+f2−2nfn+f=(n+f)2−4nf2(n+f)=(n−f)22(n+f)
前面提到此时的n,f是个负数,所以有(n−f)2>0,(n+f)<0,即更加靠近远平面。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架