games101-4-Transformation1

MVP变换

局部空间-世界空间-观察空间-裁剪空间-屏幕空间

局部坐标-世界坐标-观察坐标-裁剪坐标(会变成NDC坐标)-屏幕坐标-光栅化-片元

​ 一般可以直接将坐标定义在世界空间,M矩阵取单位矩阵。(当需要对物体进行修改的时候,在局部空间中来操作更方便;如果要对一个物体做出一个相对于其它物体位置的操作时,在世界坐标系中来操作更方便;)

View变换

确定相机坐标系:

(1)相机位置坐标e

(2)观察方向g:由相机位置指向目标物体

(3)视点正方向t

计算相机坐标系三个轴的方法:

(1)观察方向向量g:目标物体坐标减相机坐标e,再除以长度变成单位向量

(2)辅助向量up:一般设置成(0,1,0),认为相机本身不会歪

(3)向量g×t(e):通过向量g和辅助向量叉乘得到,此时向量g×t一定垂直于g和t所在平面,再除以长度变成单位向量

(4)视点正方向t向量:通过向量g×t和g向量叉乘得到,再除以长度变成单位向量

image-20230702162236905 image-20230702162254649

​ 如果相机和目标物体的相对位置不变,则最后的观察结果都相同。因此当相机处于任意位置时,可以将相机移动到原点,相机始终看向-z方向,且相机坐标系的剩下两个轴与世界坐标系的两个轴X,Y方向一致。之后将物体坐标进行相同的变换,即可得到相机在原位置时相同的结果(将作用于相机的矩阵作用在物体上)。

image-20230702162356943

下面求解view矩阵:

image-20230702162404488

(1)平移操作,将e点移动到原点

img

(2)旋转操作

由于计算从相机坐标系到世界坐标系的旋转矩阵较为复杂,因此可以先计算从世界坐标系变换到相机坐标系将y轴旋转到t轴,将z轴旋转到-g轴,将x轴旋转到g×t的轴。

img

该操作为将相机坐标系变换到世界坐标系的逆操作,因此求出来的R矩阵为目标R矩阵的逆矩阵,也是目标R矩阵的转置矩阵。

img

(3)最后求出的M矩阵如下,对目标物体坐标进行M矩阵变换

img

Projection变换

img

Orthographic projection 正交投影

假设相机在原点,看向-z轴。

将视线范围内的物体(假设在一个立方体中,该立方体通过六个数定义,注意越远z值越小,立方体外的部分都会被剪裁)全部压缩到[-1,1]范围内的正方体中,变成NDC坐标。先将立方体的重心平移到原点,再将立方体进行缩放(此处先不考虑旋转):

img

img

正交投影坐标的相对位置都不会改变,只需将物体全部转换到一个[−1,1]的正方体之中即可(其中x,y坐标便是投影结果,保留z是为了之后的深度检测)。压缩到一个正方体是为了之后的计算更加的方便在转换到屏幕坐标的时候就会重新拉伸回来。

img

正交投影不会影响w值,w仍为1,进行透视除法后没有任何作用。由于这个原因,正射投影主要用于二维渲染以及一些建筑或工程的程序,在这些场景中更希望顶点不会被透视所干扰。(opengl使用右手坐标系,此处越远z越小,在opengl中NDC坐标会变换成左手坐标,越远z越大)

Perspective projection 透视投影

(1) 将视锥体压缩成立方体

距离越远,压缩程度越大,形成近大远小的效果。

img

近平面n的xyz坐标不变,远平面f中心的xyz值不变。

根据相似三角形:

img

imgimg

(x,y,z,1),(kx,ky,kz,k!=0)都是三维空间中的点(x,y,z)。

可得矩阵:

img

近平面n的xyz坐标不变:

img

img

远平面f中心的xyz值不变:

img

img

最后解的img

(2)将立方体变换到[-1,1]的正方体

将目标物体经过上述变换后,再进行正交投影变换即可:

img

*为什么在(1)中中间压缩的点z值不知道?*
img

Persp->ortho矩阵会改变顶点的w值(w=z<0),在进行完透视投影的MVP变换后,得离观察者越远的顶点坐标w分量的绝对值越大。顶点坐标的每个分量都会除以它的w分量,距离观察者越远顶点坐标就会越小。(最后的顶点应该被赋值到顶点着色器中的gl_Position输出,OpenGL将会自动进行透视除法和裁剪。)。

比较更新后的z值和原z值:

img

因为n≥z≥f,所以(z-n)(f-z)值>0,因为z<0,方程最左侧的分数值小<0,即更新后的z值小于原z值,即透视投影之后,中间物体距离相机更远。所以在推算时不知道z值。

*如何确定视锥体?*

利用垂直可视角度或者水平可视角度、近平面距离、远平面距离(距离相机的距离)以及进平面宽高比(width/heigth)可以确定一个视锥体。(在opengl中,可视角度一般取45°,近平面取0.1,远平面100.0f)

img

如下图所示,相机在原点看向-z轴。已知Y(垂直可视角度)和n,可以计算出height/2->height,通过宽高比可以得到width。远平面可以通过Y和f计算。

img

如果只是图元(Primitive),例如三角形,的一部分超出了裁剪体积(Clipping Volume),则OpenGL会重新构建这个三角形为一个或多个三角形让其能够适合这个裁剪范围。

视口变换

屏幕可以看作一组xy的像素数组,数组的大小xy为分辨率。此处认为在一个像素内部颜色不变,像素的颜色值通过RGB三个0-255之间的数表示。

img

像素坐标从(0,0)到(x-1,y-1)。像素(x,y)的中心在(x+0.5,y+0.5),这些像素的覆盖范围从(0,0)到(x,y)。

视口变换就是将物体坐标从[-1,1]的正方体变到x*y的屏幕。

img

该变换与z无关,z保持不变用于后续深度测试。先把正方体的x、y进行缩放

img

再将缩放后的立方体中心平移到屏幕中心:

img

*为什么不能先平移再缩放?*

缩放会将每个坐标以原点为中心进行缩放(也就是位移向量也会被缩放),而不是物体中心,如下白色正方形按照缩放矩阵缩小一半的结果是蓝色正方形而不是红色正方形。

img

显示图像:将显存中的一块区映射到屏幕。

(区分 view变换:先平移再旋转 正交投影:先平移再缩放)

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码

请我喝杯咖啡吧~

支付宝
微信