图形学初识--视图+投影变换

前言

前面章节主要讲解了一些常用的变换矩阵,这一节咱们主要讲解一些视图变换和投影变换。

有些小伙伴可能不了解图形学,会有所疑惑这些矩阵有啥用,其实这都是为了后面"MVP变换"做铺垫,但是如果一上来冒然的介绍MVP,会因小失大!因此作者决定将其放在后面介绍渲染管线的时候介绍它,不要着急哦!

正文

视图变换

为什么要有视图变换?

想象一个三维场景中,各个地方的物体已经摆好了。这时候有一个好奇心宝宝,想要从不同的视角去观察,物体摆放的合不合适,那怎么办呢?

答:需要引入类似"摄像机"的概念,就像现实中一样,摄像师扛着摄像机跑,从而拍到了不同的画面,虚拟的三维场景也是一样!为此引入视图变换,来满足虚拟摄像机的需求!

视图变换是什么?

本质上,它和前面章节提到的旋转变换、平移变换类似,最终结果呈现也就是一个矩阵的表达式罢了。

视图变换如何定义?

定义摄像机:

让我们思考一个问题,如果我们是摄影师,需要某漂亮国的一处景点,摄像机需要有哪些属性呢?

答:摄像机的位置、摄像机镜头朝向、摄像机顶部朝向等等。

人都是懒的,如果在三维空间中为了方便显示在二维中,最简单的摄像机如下所示:

在这里插入图片描述

摄像机相关属性:

  • 位置摆放在原点
  • 摄像机镜头朝向-z轴方向

此时这种情况,所有物体都可以直接沿着z轴投射到摄像机的屏幕中,非常方便!

但是往往事与愿违,如果摄像机变化到下述的形态,就不方便直接按照z轴投射了!

在这里插入图片描述

所以,我们就需要达成一个目标:将摄像机恢复到原点,并且镜头朝向-z轴!

摄像机变换:

这个问题如何思考呢?其实我们可以逆过程思考,我们可以想一想:原本在原点并看向-z轴的一台摄像机,是如何变化到上述情况的!

然后咱们上述目标的达成也就是应用此过程的逆变换!

正向过程变换示意图如下:

1、摄像机先绕原点旋转

2、摄像机进行平移

在这里插入图片描述

自之前章节的学习,我们知道,这个过程也就可以表述为:先旋转变换,再平移变换。公式如下:
M = T ∗ R 注: R 为旋转矩阵, T 为平移矩阵 M = T * R\\ 注:R为旋转矩阵,T为平移矩阵 M=TR注:R为旋转矩阵,T为平移矩阵

上述的逆变换也就显而易见:
M − 1 = R − 1 ∗ T − 1 M^{-1} = R^{-1}*T^{-1} M1=R1T1
所以,只要应用此变换,就可以实现将任意位置和朝向的摄像机,变换到位于原点并看向-z轴的情形!如下示意图:

在这里插入图片描述

目标重申:

既然我们要求场景的物体和摄像机保持相对静止,那么只需要针对所有物体进行上述的变换,不就实现了咱们的目标么!Successfully!

构建矩阵:

为了方便,咱们定义摄像机朝向为: f r o n t ⃗ \vec {front} front 向量,简称 f ⃗ \vec f f ;摄像机顶部向量为 u ⃗ \vec u u ,以及一个摄像机的 r i g h t ⃗ \vec {right} right 向量,简称: r ⃗ \vec r r ,示意图如下:

在这里插入图片描述

既然咱们已经知道了新的坐标系的三个基向量 r ⃗ 、 u ⃗ 、 − f ⃗ \vec{r}、\vec{u}、\vec{-f} r u f ,分别对应于心坐标系的x、y、z轴,所以咱们自然而然就知道了旋转矩阵 R R R,如下:
R = [ r x u x − f x 0 r y u y − f y 0 r z u z − f z 0 0 0 0 1 ] R = \begin{bmatrix} r_x & u_x & -f_x & 0\\ r_y & u_y & -f_y & 0\\ r_z & u_z & -f_z & 0\\ 0 & 0 & 0 & 1\\ \end{bmatrix} R= rxryrz0uxuyuz0fxfyfz00001
所以咱们可以自然而然得到R的逆矩阵,如下:
R − 1 = [ r x r y r z 0 u x u y u z 0 − f x − f y − f z 0 0 0 0 1 ] R^{-1}=\begin{bmatrix} r_x & r_y & r_z & 0\\ u_x & u_y & u_z & 0\\ -f_x & -f_y & -f_z & 0\\ 0 & 0 & 0 & 1\\ \end{bmatrix} R1= rxuxfx0ryuyfy0rzuzfz00001

我们假设摄像机的位置位于: P = ( p x , p y , p z ) P = (p_x,p_y,p_z) P=(px,py,pz) ,则可以构建一下的平移矩阵及其逆矩阵:

T = [ 1 0 0 p x 0 1 0 p y 0 0 1 p z 0 0 0 1 ] T=\begin{bmatrix} 1 & 0 & 0 & p_x\\ 0 & 1 & 0 & p_y\\ 0 & 0 & 1 & p_z\\ 0 & 0 & 0 & 1\\ \end{bmatrix}\\ T= 100001000010pxpypz1

T − 1 = [ 1 0 0 − p x 0 1 0 − p y 0 0 1 − p z 0 0 0 1 ] T^{-1}=\begin{bmatrix} 1 & 0 & 0 & -p_x\\ 0 & 1 & 0 & -p_y\\ 0 & 0 & 1 & -p_z\\ 0 & 0 & 0 & 1\\ \end{bmatrix} T1= 100001000010pxpypz1
根据之前的结论,视图变换矩阵为: M − 1 = R − 1 ∗ T − 1 M^{-1} = R^{-1}*T^{-1} M1=R1T1,因此如下:

M − 1 = [ r x r y r z 0 u x u y u z 0 − f x − f y − f z 0 0 0 0 1 ] ∗ [ 1 0 0 − p x 0 1 0 − p y 0 0 1 − p z 0 0 0 1 ] = [ r x r y r z − r ⃗ ⋅ p ⃗ u x u y u z − u ⃗ ⋅ p ⃗ − f x − f y − f z f ⃗ ⋅ p ⃗ 0 0 0 1 ] \begin{align} M^{-1}&=\begin{bmatrix} r_x & r_y & r_z & 0\\ u_x & u_y & u_z & 0\\ -f_x & -f_y & -f_z & 0\\ 0 & 0 & 0 & 1\\ \end{bmatrix}*\begin{bmatrix} 1 & 0 & 0 & -p_x\\ 0 & 1 & 0 & -p_y\\ 0 & 0 & 1 & -p_z\\ 0 & 0 & 0 & 1\\ \end{bmatrix}\\ &= \begin{bmatrix} r_x & r_y & r_z & -\vec{r} \cdot \vec{p}\\ u_x & u_y & u_z & -\vec{u} \cdot \vec{p}\\ -f_x & -f_y & -f_z & \vec{f} \cdot \vec{p}\\ 0 & 0 & 0 & 1\\ \end{bmatrix} \end{align} M1= rxuxfx0ryuyfy0rzuzfz00001 100001000010pxpypz1 = rxuxfx0ryuyfy0rzuzfz0r p u p f p 1

总结: 为了灵活的从摄像机视角观察物体,并且方便按照z轴投射,咱们只需要针对三维场景的物体应用上述的变换矩阵即可!

投影变换

1、正交投影

正交投影是什么?

它是一种平行投影,用于将三维空间场景映射到2D的平面上。直观上理解,有点类似截面图或者压扁了的感觉!所以它本质上没有所谓的近大远小的特点。如图所示

在这里插入图片描述

它常常应用于CAD制图等领域!

为什么需要正交投影?

1、实际上,在三维场景中,我们的物体范围可能非常大,但是咱们屏幕空间是有限的,所以为了关注特别需要的区域,需要定义一个类似包围盒体的东西,盒体的需要显示,盒体外的咱们不需要显示

2、为了规范化坐标为NDC坐标,方便后续在屏幕中显示

NDC坐标,其实就是一个x、y、z都在 [-1,1] 范围内的规范化的坐标!

如图所示:

在这里插入图片描述

正交投影矩阵是啥?

(1)约定以下都在视图变换后的摄像机坐标系下定义。

一个立方体包围盒,也就是上、下、左、右、前、后这几个属性定义而成,如图所示:

在这里插入图片描述

(2)为了达到NDC坐标的 [ − 1 , 1 ] 3 [-1,1]^3 [1,1]3 的要求,我们需要规范两件事情:

  • 盒体中心规范到原点
  • 盒体长度缩放至2X2X2的标准长度

因此,上述操作也就对应两个变换矩阵,先平移到中心,再进行缩放。

我们定义包围盒体的x范围: [ l , r ] [l,r] [l,r],y范围: [ b , t ] [b,t] [b,t],z范围: [ n , f ] [n,f] [n,f],因而我们得出以下平移矩阵和缩放矩阵:
T = [ 1 0 0 − r + l 2 1 0 0 − t + b 2 1 0 0 − n + f 2 0 0 0 1 ] T= \begin{bmatrix} 1&0&0&-\frac{r+l}{2}\\ 1&0&0&-\frac{t+b}{2}\\ 1&0&0&-\frac{n+f}{2}\\ 0&0&0&1\\ \end{bmatrix} T= 1110000000002r+l2t+b2n+f1

S = [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 f − n 0 0 0 0 1 ] S= \begin{bmatrix} \frac{2}{r-l}&0&0&0\\ 0&\frac{2}{t-b}&0&0\\ 0&0&\frac{2}{f-n}&0\\ 0&0&0&1\\ \end{bmatrix} S= rl20000tb20000fn200001

从而我们得到正交投影变换矩阵: O r t h o = S ∗ T Ortho = S*T Ortho=ST

O r t h o = [ 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − t + b t − b 0 0 2 f − n − n + f f − n 0 0 0 1 ] Ortho= \begin{bmatrix} \frac{2}{r-l}&0&0&-\frac{r+l}{r-l}\\ 0&\frac{2}{t-b}&0&-\frac{t+b}{t-b}\\ 0&0&\frac{2}{f-n}&-\frac{n+f}{f-n}\\ 0&0&0&1\\ \end{bmatrix} Ortho= rl20000tb20000fn20rlr+ltbt+bfnn+f1

2、透视投影

为什么需要透视投影?

上面的正交投影已经说过,它最大的缺点就是没有近大远小的特性,但是在现实中如果没有这样的特性,几乎三维场景就是非常"假"的一个状态。

因此,为了能够体现近大远小的特性,又发明了透视投影这一说。有点类似于素描的“透视”的概念!

透视投影是什么?

视线从摄像机触发,看向-z轴方向,可视范围为near到far的一个视锥体。最终所有物体都达到近平面near上!如下图所示:

在这里插入图片描述

如何定义透视投影变换?

既然知道最终所有物体都投射到近平面上,因此我们将增加几个近平面的属性,完善一下上述的示意图:

在这里插入图片描述

重新定义以下透视投影变换最终目的: 将视锥体内的物体坐标变换至xyz都为[-1,1]的标准NDC坐标,如下图所示:

在这里插入图片描述

开始推导投影变换矩阵:

(1)基本思路:

  • 因为我们无法直接对矩阵得知,我们需要从投影前后的坐标关系进行反推矩阵
  • 又因为最终坐标是达到近平面上得,所以以此作为突破口

(2)咱们逆y轴进行俯视观察上述示意图,得到下面得截面图:

在这里插入图片描述

假设某一个摄像机坐标系下得坐标为 ( x e , y e , z e ) (x_e,y_e,z_e) (xe,ye,ze) ,它投影到进平面后,得到 p = ( x p , y p , z p ) p=(x_p,y_p,z_p) p=(xp,yp,zp) ,根据相似三角形可以得到如下等式:
x p x e = − n z e \frac{x_p}{x_e} = \frac{-n}{z_e} xexp=zen
从而咱们得到投影到近平面上点的x坐标: x p = n x e − z e x_p = \frac{nx_e}{-z_e} xp=zenxe

(3)类似的,咱们逆x轴进行观察,得到下面得截面图:

在这里插入图片描述

也可以类似得到进平面上的y坐标: y p = n y e − z e y_p = \frac{ny_e}{-z_e} yp=zenye

有人可能发现了,这里的z_e不能为0,因为它在分母上,这个问题马上后面就会处理掉,大家不要着急!

(4)目前已得到投影到进平面上点的坐标,接下来要对其进行缩放到标准的[-1,1]的NDC坐标内

这里以y坐标为例,因为近平面是和z=0的平面平行关系,所以他们的缩放也必定是线性关系,如下示意图:

在这里插入图片描述

已知两点 ( t , 1 ) , ( b , − 1 ) (t,1),(b,-1) (t,1),(b,1), 因此咱们可以计算出 y p 和 y n d c y_p和y_{ndc} ypyndc 关系如下:
y n d c = 2 t − b y p − t + b t − b y_{ndc} = \frac{2}{t-b}y_p - \frac{t+b}{t-b} yndc=tb2yptbt+b

同理可以得到 x p 和 x n d c x_p和x_{ndc} xpxndc 的关系,如下:
x n d c = 2 r − l y p − r + l r − l x_{ndc} = \frac{2}{r-l}y_p - \frac{r+l}{r-l} xndc=rl2yprlr+l

这里我们根据之前求的 y p 和 y e y_p和y_e ypye的关系、 x p 和 x e x_p和x_e xpxe的关系,进行等式替换,得到如下:
当 z e ≠ 0 时 x n d c = 2 r − l y p − r + l r − l = 2 r − l ∗ n x e − z e − r + l r − l = 1 − z e ( 2 n r − l x e + r + l r − l z e ) \begin{align} 当&z_e \neq 0时\\ x_{ndc} &= \frac{2}{r-l}y_p - \frac{r+l}{r-l}\\ &= \frac{2}{r-l}*\frac{nx_e}{-z_e} - \frac{r+l}{r-l}\\ &= \frac{1}{-z_e}(\frac{2n}{r-l}x_e + \frac{r+l}{r-l}z_e) \end{align} xndcze=0=rl2yprlr+l=rl2zenxerlr+l=ze1(rl2nxe+rlr+lze)
同理,得到:
当 z e ≠ 0 时 y n d c = 2 r − l y p − r + l r − l = 2 r − l ∗ n x e − z e − r + l r − l = 1 − z e ( 2 n t − b y e + t + b t − b y e ) \begin{align} 当&z_e \neq 0时\\ y_{ndc} &= \frac{2}{r-l}y_p - \frac{r+l}{r-l}\\ &= \frac{2}{r-l}*\frac{nx_e}{-z_e} - \frac{r+l}{r-l}\\ &= \frac{1}{-z_e}(\frac{2n}{t-b}y_e + \frac{t+b}{t-b}y_e) \end{align} yndcze=0=rl2yprlr+l=rl2zenxerlr+l=ze1(tb2nye+tbt+bye)

于是我们得到了 x n d c 和 y n d c x_{ndc}和y_{ndc} xndcyndc的坐标表示,但是此时 z n d c z_{ndc} zndc 还未知,并且上述也不能兼容 z e = = 0 z_e == 0 ze==0的情况,所以咱们继续扩充知识

(5)利用齐次坐标,引入剪裁空间

既然上述由于除法的存在,导致分母为0的情况需要特殊考虑,人总是懒惰的,既然如此,有没有兼容=0的考虑方法呢?

答: 有的,那就将分母给去掉,只需要乘 − z e -z_e ze即可

咱们因此剪裁空间的概念,由于剪裁的英文为clip,所以咱们定义如下:
p c ( x ) = x n d c ∗ ( − z e ) = 2 n r − l x e + r + l r − l z e p c ( y ) = y n d c ∗ ( − z e ) = 2 n t − b y e + t + b t − b z e p c ( z ) =   ? p c ( w ) = − z e \begin{align} p_c(x) &= x_{ndc}*(-z_e) = \frac{2n}{r-l}x_e + \frac{r+l}{r-l}z_e\\ p_c(y) &= y_{ndc}*(-z_e) = \frac{2n}{t-b}y_e + \frac{t+b}{t-b}z_e\\ p_c(z) &= \ ?\\ p_c(w) &= -z_e \end{align} pc(x)pc(y)pc(z)pc(w)=xndc(ze)=rl2nxe+rlr+lze=yndc(ze)=tb2nye+tbt+bze= ?=ze

(6)已经考虑的差不多了,回归本源,开始利用坐标前后关系进行反推投影变换矩阵

这里先从 p c ( w ) = − z e p_c(w) = -z_e pc(w)=ze 作为突破口,我们可以得到如下的关系:

( x c y c z c w c ) = ( ? ? ? ? ? ? ? ? ? ? ? ? 0 0 − 1 0 ) ( x e y e z e w e ) \begin{pmatrix} x_c\\y_c\\z_c\\w_c \end{pmatrix} =\begin{pmatrix} ?&?&?&?\\ ?&?&?&?\\ ?&?&?&?\\ 0&0&-1&0\\ \end{pmatrix} \begin{pmatrix} x_e\\y_e\\z_e\\w_e \end{pmatrix} xcyczcwc = ???0???0???1???0 xeyezewe

然后再利用x、y坐标的前后关系,可以补齐前两行:
( x c y c z c w c ) = ( 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 ? ? ? ? 0 0 − 1 0 ) ( x e y e z e w e ) \begin{pmatrix} x_c\\y_c\\z_c\\w_c \end{pmatrix} =\begin{pmatrix} \frac{2n}{r-l}&0&\frac{r+l}{r-l}&0\\ 0&\frac{2n}{t-b}&\frac{t+b}{t-b}&0\\ ?&?&?&?\\ 0&0&-1&0\\ \end{pmatrix} \begin{pmatrix} x_e\\y_e\\z_e\\w_e \end{pmatrix} xcyczcwc = rl2n0?00tb2n?0rlr+ltbt+b?100?0 xeyezewe

(7)此时只剩跟z坐标相关的第三行的矩阵元素未知,需要回忆回忆额外的条件才行

我们知道,原本位于近平面上的坐标,无论x、y取什么值,它的坐标 z e = − n z_e = -n ze=n 是一直成立的,也就是说与xy无关,所以咱们可以补充第三行的前两个参数,并且设后两个为A和B
( x c y c z c w c ) = ( 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 0 0 A B 0 0 − 1 0 ) ( x e y e z e w e ) \begin{pmatrix} x_c\\y_c\\z_c\\w_c \end{pmatrix} =\begin{pmatrix} \frac{2n}{r-l}&0&\frac{r+l}{r-l}&0\\ 0&\frac{2n}{t-b}&\frac{t+b}{t-b}&0\\ 0&0&A&B\\ 0&0&-1&0\\ \end{pmatrix} \begin{pmatrix} x_e\\y_e\\z_e\\w_e \end{pmatrix} xcyczcwc = rl2n0000tb2n00rlr+ltbt+bA100B0 xeyezewe

既然我们知道任意的近平面上的点的z值,最终映射到ndc坐标空间都是-1;远平面上的点的z值,映射到ndc坐标上都是1,于是我们得到以下两个条件:
当 z e = − n , w e = 1 时 = > z n d c = − 1 = > z c = − z e ∗ z n d c = − n 当 z e = − f , w e = 1 时 = > z n d c = 1 = > z c = − z e ∗ z n d c = f 当z_e = -n,w_e = 1时 => z_{ndc}=-1 => z_c = -z_e * z_{ndc} = -n\\ 当z_e = -f,w_e = 1时 => z_{ndc}= 1 => z_c = -z_e * z_{ndc} = f ze=nwe=1=>zndc=1=>zc=zezndc=nze=fwe=1=>zndc=1=>zc=zezndc=f

咱们可以用待定系数法, 代入得到以下等式:
A ∗ ( − n ) + B = − n A ∗ ( − f ) + B = f A*(-n) + B = -n\\ A*(-f) + B = f A(n)+B=nA(f)+B=f
然后咱们解个二元一次方程组,即可得到:
A = − f + n f − n B = − 2 f n f − n A = -\frac{f+n}{f-n}\\ B = \frac{-2fn}{f-n} A=fnf+nB=fn2fn
于是咱们得到最终的投影变换矩阵,如下:
P e r s p e c t i v e = ( 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 0 0 − f + n f − n − 2 f n f − n 0 0 − 1 0 ) Perspective = \begin{pmatrix} \frac{2n}{r-l}&0&\frac{r+l}{r-l}&0\\ 0&\frac{2n}{t-b}&\frac{t+b}{t-b}&0\\ 0&0&-\frac{f+n}{f-n}&\frac{-2fn}{f-n}\\ 0&0&-1&0\\ \end{pmatrix} Perspective= rl2n0000tb2n00rlr+ltbt+bfnf+n100fn2fn0

透视投影矩阵的工程化(参数变换)

上面我们已经知道了,构造透视投影矩阵需要以下已知参数:

  • 近平面n,原平面f
  • 近平面的b、t、l、r

但是,在实际工程中,这样的参数设置是比较麻烦的,所以咱们引入两个新的概念:

  1. y方向上的视张角fovy
  2. 近平面的纵横比aspect

额外补充条件:并且要求近平面相对y轴左右对称,相对x轴上下对称,如下图所示:

在这里插入图片描述

咱们进行如下的参数替换:

  • t − b = 2 tan ⁡ ( f o v y / 2 ) ∗ n t-b = 2\tan(fovy /2) * n tb=2tan(fovy/2)n

  • r − l = a s p e c t ∗ ( t − b ) = 2 a s p e c t ∗ tan ⁡ ( f o v y / 2 ) ∗ n r-l = aspect*(t-b) = 2aspect*\tan(fovy / 2) * n rl=aspect(tb)=2aspecttan(fovy/2)n

因而可以推导出矩阵的所有元素替换,得到如下的最终结果:

P e r s p e c t i v e = ( 1 a s p e c t ∗ t a n ( f o v y / 2 ) 0 0 0 0 1 t a n ( f o v y / 2 ) 0 0 0 0 − f + n f − n − 2 f n f − n 0 0 − 1 0 ) Perspective = \begin{pmatrix} \frac{1}{aspect*tan(fovy/2)}&0&0&0\\ 0&\frac{1}{tan(fovy/2)}&0&0\\ 0&0&-\frac{f+n}{f-n}&\frac{-2fn}{f-n}\\ 0&0&-1&0\\ \end{pmatrix} Perspective= aspecttan(fovy/2)10000tan(fovy/2)10000fnf+n100fn2fn0

总结: 不管是透视投影还是正交投影,最终的目的都是讲摄像机坐标系下的坐标,最终变换到NDC坐标系下!

结尾:喜欢的小伙伴点点关注+赞哦!

你们的点赞就是我创作的最大动力!希望对各位小伙伴能够有所帮助哦,永远在学习的道路上伴你而行, 我是航火火,火一般的男人!

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值