大家好,欢迎来到IT知识分享网。
变换(Transformation)
一.变换的大体流程(一张照片是怎么出来的)
变换的任务,是将虚拟世界中以(X,Y,Z)为坐标的物体(3D)变换到以一个个像素位置(x,y)来表示的屏幕坐标系之中(2D)。
同样是从3D到2D,变换的过程和拍全家福的过程比较类似。
整个过程可以分为以下几个步骤
1.模型变换(modeling)
模型变换,又称M变换,这一步的目的是将虚拟世界中或者具体点,游戏场景中的物体调整到他们应该在的位置。
模型变换将物体从模型坐标系(也称局部坐标系),变换到世界坐标系。
可以把模型变换理解为拍照片时决定站位,摆pos的问题,这一步的操作就叫做模型变换。
2.视图变换/摄像机变换(view/camera)
视图变换,又称V变换。这一步的目的是设定摄像机,或者说是眼睛的位置。得到物体与摄像机的相对位置。
因为需要得到物体与相机的相对位置,所以这步的变换,是把物体从世界坐标系,变换到观察坐标系。
可以把视图变换/摄像机变换理解成,拍照时,全家人保持之前决定好的相对位置,大小,旋转朝向等细节的前提下,全家移步到摄影棚(即把摄影棚的相机当做坐标原点),然后摆正相机(相机自身的旋转),是的相机朝向我们(相机的朝向),同时设定好相机离我们的距离(与相机的距离),才能拍出好的照片来。
3.投影变换(projection)
投影变换,在摄像机变换后,我们得到了所有可视范围内物体相对于摄像机的相对位置坐标(x,y,z),之后根据具体情况选择平行投影或者是透视投影,将三维空间投影到裁剪坐标系当中(clip space),先进行齐次裁剪,之后再经过透视除法,转化到NDC(规范化设备坐标系)中。(注意,这里的z值并没有被丢掉,而是存在Zbuffer之中,后续还会有深度测试等相关的处理)。
这步的过程,是从摄像机空间到裁剪坐标系,之后裁剪坐标系经过齐次除法后,到达标准化设备坐标(NDC)。
这步骤的过程,就类比为按下快门,拍摄好物体,从3D转化为2D平面上。
4.视口变换(viewport)
视口变换(viewport transform):
将处于标准平面映射到屏幕分辨率范围之内,即从[-1,1]->[0,width]*[0,height],其中width和height指屏幕分辨率大小。
可以理解为洗照片?把照片从相机小格内(NDC),直接洗成一个超级无敌大(屏幕那么大)的照片,挂起来。
那么每一步都做了什么工作呢?
二.各个变换的具体实现形式
1.模型变换
模型变换主要是利用基础的变换矩阵将世界中的物体调整到我们想要的位置。(局部坐标系->世界坐标系)。
主要手段是基础变换矩阵,缩放,旋转,平移等仿射变换。
其中要注意,因为矩阵乘法不满足交换律,所以说顺序很重要。尤其是平移和旋转的顺序。
一般是先线性变化,后仿射变换。
同时处理矩阵时都是左乘,所以越往右的矩阵越早乘。
2.视图变换(摄像机变换)
摄像机变换比较复杂,类比拍照时,我们要处理相机位置、朝向、上下(不能拿成上下颠倒)等相机细节。
核心问题是把摄像机坐标系,移动到标准的x,y,z坐标系,相机和物体坐标系重合,则就可以得到相对位置信息了。
为此,我们定义相机坐标系三个参数。(本文用右手系进行推导)。
相机或者眼睛位置(position),也就是相机坐标系的原点。 我们可以标记为e,单位向量
观察方向(LookAt),我们可以标记为g,单位向量,(g要朝向物体)
视点正上方向(UpDirection),我们可以标记为t(view-up vector) (判断是否倒立)
永远让相机不动,认为相机永远在原点,头顶指向Y,看向-Z的方向。
示意图如下:
那么接下来,我们就只需要用变换矩阵对相机坐标系进行变换即可。
分2步:
- 1.平移相机到坐标轴原点(即使e变为(0,0,0));
- 2.旋转g到-z,旋转t到y,旋转(g叉乘t)到x.(即使g变为(0,0,-1),t变为(0,1,0));
数学表达式:
这里是先平移,后旋转。因为这里是处理步骤。。。(其他地方一般都是先旋转再平移)
- 1.移动到原点
首先是一个平移变换,这个是比较简单的。
- 2.进行旋转
移动到原点后,我们要通过旋转,使(gx,gy,gz) 变为 (0,0,-1) ,(tx,ty,tz) 变为 (0,1,0)。这一步我们有点无从下手,因为我们之前讨论旋转矩阵时都是绕什么什么轴旋转多少多少度,而在这里我们并不知道应该绕什么轴旋转多少度。
这里利用一个性质。
旋转矩阵必为正交阵,而正交阵的逆等于他的转置。
我们不知道如何去求(gx,gy,gz) 变为 (0,0,-1),(tx,ty,tz) 变为 (0,1,0),但是我们知道如何将(0,0,-1)变为(gx,gy,gz), (0,1,0)变为(tx,ty,tz)。也就是上面的逆变换。
我们上面就是求得逆,也就是他的转置,所以在转置回来,就可以得到视图变换的变换矩阵了。
通过前面的公式我们知道,旋转矩阵中的值即为x,y,z三个轴的单位向量旋转后的值。在这里(0,1,0)变为了t,(0,0,1)变为了-g(-gx,-gy,-gz)。根据叉乘的定义可得摄像机自身的x轴方向(g叉乘t),即(1,0,0)变为了(g叉乘t)。所以我们得下图的情况。
3.投影变换(projection transform)
摄像机对好要拍摄的物体后,就差最后按下快门变成照片这一步了,而这一步也就是我们的投影变换,即从三维变成二维。在图形学中,投影变换分为如下两种,分别为正交投影和透视投影。
3.1正交投影变换
正交投影没有近小远大的现象,视线是相互平行的,类似于平行光照,在无穷远处。
根据视图变化,确定了我们所拍摄的空间。如下图:
正交投影变换:对于正交投影来说,l<r,b<t,f<n.
从图中我们也可以发现当从三维变为二维时,空间内的物体的x轴和y轴位置不会发生变换,而是在z轴方向进行了压缩。我们可以把空间中的物体的z轴都设置为0,那么空间中的所有物体都会被压缩到xy平面上,也就是变为二维的了。
然而更规范化的做法是将上述摄像机所观测的空间(即长方体,设为 S )变换成一个标准立方体(canonical cube)。何为标准立方体?即以原点为中心,边长为2的立方体,也就是立方形在x,y,z三个轴上都是从-1到1。
整个变换过程就是我们的正交投影变换,其对应矩阵即为正交投影变换矩阵。该变换我们可以分为如下两步(这也体现了视图变换的重要性,使得我们做投影变换变得很简单):
- 1.平移变换,将长方体S平移到原点
- 2.缩放变换,将长方体S的宽高缩放到2
首先是移到原点的平移变换,即把长方体S的中心点移动到原点,那么我们就要求出长方体中心点的坐标。
根据前面的数据,可以知道,l+r/2,t+b/2,n+f/2;
因此平移矩阵(设为M)即为:
接着是将长方体S变为边长为2的立方体的缩放变换,那么我们只需要知道长方体的长宽高即可。我们设x轴方向的为长度,即为 r-l ,y轴方向的为高度,即为 t-b ,z轴方向的为宽度,即为 n-f 。
因此可以得出最终的正交投影变换为:
注:该变化会导致物体的被拉伸(因为长方体变成了立方体),在后续的视口变化中会再次处理。
3.2透视投影变换
透视投影就是最类似人眼所看东西的方式,遵循近大远小,如果说正交投影都是水平光线,那么透视投影则显然不是了(左透视,右正交),观测区域不再是正方体了,而是一个四棱台,又称视椎体。
我们来看在视图变换后,透视投影在坐标系中的样子,如下图:
正交投影是先把相机观测空间压成一个标准立方体,对于视椎体要如何压缩呢?
- 1.我们可以通过某种变换,先把视椎体压缩成长方体。
- 2.把长方体移到原点上压缩成标准立方体,即等于执行正交投影变换。
所以只需要计算出第一步的变换矩阵就可以了,然后将它乘以正交投影变换矩阵,即可得到我们的透视投影变换矩阵。
我们可以从x轴方向看向yz平面,来观察视椎体,进行理解。
图中原点表示视点,z=-n代表投影平面,利用相似三角形求解
y’/y = n/z,x’/y = n/z。
利用齐次坐标性质,希望找到一个矩阵完成如下的变换:
即:
首先,矩阵的前两行和最后一行很快可以确定出来,根据最后的齐次坐标,如下:
运用透视投影的一个性质:
视椎体上近平面远平面上的z坐标不变。
所以第三行一定是(0,0,A,B)的形式。
待定系数法求
可以得到An+B = n²。
同理可得Af+B=f²。
联立可得,A=n+f,B=-nf;
所以最后的变换矩阵是:
闫神有个问题:经过变换后,视椎体的中心往近平面还是远平面积压了?
经过透视投影变换后,视椎体的中心点在变换后离摄像机更远了。
证明:
这就说明,原来的中心(n+f)/2,现在变成了(n²+f²)/(n+f);
所以透视投影变化矩阵为
对称视椎体
对于对称视椎体,也就是N为近平面的中心点,F为远平面的中心点。我们可以得到
因此正交投影矩阵可简化成
透视投影矩阵简化为:
使用视角FOV和宽高比Aspect ratio来表示透视投影矩阵
之后带入之前的透视投影矩阵公式,即可得到透视投影矩阵为:
支线任务:裁剪空间
mv变换后,视图空间下的某个点对应的齐次坐标为(x,y,z,1),那么经过透视投影变换后,其齐次坐标应为:
也就是说经过齐次变换,我们会得到一个齐次坐标(x,y,z,w)。其中w是变换前视图空间下z的值,而该齐次坐标所在的空间即为裁剪空间,也称齐次裁剪空间。
接着GPU会在裁剪空间下做裁剪,剔除掉不在视椎体内的顶点。
怎么做?
支线任务:标准化设备坐标(NDC),也是上文讲到的标准立方体。
根据齐次坐标的定义我们知道 (x,y,z,w) 与 (x/w,y/w,z/w,1) 是等价的,即把裁剪空间下的(x,y,z,w)分别除以w,这一步我们称之为透视除法(Perspective Divide)。
裁剪空间做完透视除法,进入标准化设备坐标。
NDC就是标准立方体,也就是裁剪空间中做完裁剪后再做透视除法得到的坐标。NDC中的顶点最后都要输出到屏幕空间当中。
OpenGL当中,视图空间是右手系,而裁剪空间和NDC是左手系。因此还需要一个坐标变换。详见
https://zhuanlan.zhihu.com/p/
4.视口变换(viewport transformation)
视口变换是将顶点数据从标准化设备坐标系(NDC)转化到屏幕坐标系。
转换很简单。
从[-1,1]->[0,w],[-1,1]->[0,h]
参考:闫令琪Games101 learnopengl
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/146444.html