TA入门笔记(四)

参考may佬《技术美术百人计划》
冯乐乐《Unity Shader入门精要》
写给VR手游开发小白的教程:(四)补充篇,详细介绍Unity中相机的投影矩阵
投影矩阵的推导(Deriving Projection Matrices)
Eric Lengyel. Mathematics for 30 game programming and computer graphics (3rd Edition). 2011 by Charles River Media

图形1.2.3 MVP矩阵变换

变换矩阵

  • 将3D物体转化到2D平面
  • 为各个空间的运用做准备

MVP矩阵

MVP矩阵分别是模型(Model)矩阵、观察(View)矩阵、投影(Projection)矩阵。

坐标空间

  • 因为一些概念只有在特定的坐标空间下才有意义,才更容易理解,所以我们需要在不同的情况下使用不同的坐标空间。
  • 顶点的起始坐标位于局部空间(模型空间),在这里被称作局部坐标(Local Coordinate),之后会变为世界坐标(World Coordinate)、观察坐标(View Coordinate)、裁剪坐标(Clip Coordinate),最后以屏幕坐标(Screen Coordinate)结束。
  • 在这里插入图片描述

M矩阵

模型空间 → \rightarrow 世界空间

  • 将顶点坐标从模型空间变换到世界空间的过程被称作模型变换
  • 模型变换依次进行了缩放、旋转、平移的操作,对应操作依次进行矩阵变换即可得出模型变换的变换矩阵,即M矩阵(注意矩阵的左乘顺序)
  • M m o d e l = [ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] [ cos ⁡ θ 0 sin ⁡ θ 0 0 1 0 0 − sin ⁡ θ 0 cos ⁡ θ 0 0 0 0 1 ] [ k x 0 0 0 0 k y 0 0 0 0 k z 0 0 0 0 1 ] M_{model}=\begin{bmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} \cos \theta & 0 & \sin \theta & 0 \\ 0 & 1 & 0 & 0 \\ -\sin \theta & 0 & \cos \theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} k_x & 0 & 0 & 0 \\ 0 & k_y & 0 & 0 \\ 0 & 0 &k_ z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} Mmodel=100001000010txtytz1cosθ0sinθ00100sinθ0cosθ00001kx0000ky0000kz00001
  • P w o r l d = M m o d e l P m o d e l P_{world}=M_{model}P_{model} Pworld=MmodelPmodel

V矩阵

世界空间 → \rightarrow 观察空间

  • 将顶点坐标从世界空间变换到观察空间,被叫做观察变换
  • 变换步骤:
    • 平移整个观察空间,让摄像机原点位于世界坐标的原点,坐标轴与世界空间中的坐标轴重合
    • 摄像机在世界空间中是先旋转再平移的,因此为了将摄像机移回初始状态(位于原点,坐标轴重合),需要进行逆变换
    • 在Unity中模型空间和世界空间都是左手系,观察空间却是右手系,z轴方向相反,因此需要对z取反
    • 所以观察变换的顺序为先平移,再旋转,最后对z分量取反
  • M v i e w = [ 1 0 0 0 0 1 0 0 0 0 − 1 0 0 0 0 0 ] [ 1 0 0 0 0 cos ⁡ θ − sin ⁡ θ 0 0 sin ⁡ θ cos ⁡ θ 0 0 0 0 1 ] [ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] M_{view}=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 0 \end{bmatrix}\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos \theta & -\sin \theta & 0 \\ 0 & \sin \theta & \cos \theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}\begin{bmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 &1 & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix} Mview=100001000010000010000cosθsinθ00sinθcosθ00001100001000010txtytz1
  • P v i e w = M v i e w P w o r l d P_{view}=M_{view}P_{world} Pview=MviewPworld

P矩阵

观察空间 → \rightarrow 裁剪空间

  • 用于判断顶点是否在可见范围内,为投影做准备(虽然叫做投影变换,但是并没有真正进行投影工作)

  • 位于视锥体内的图元保留,视锥体之外的图元将被剔除,与裁剪平面相交的图元会被裁剪

    • 为什么要进行投影变换?
      视锥体并不是规则的几何体,而是截掉顶部的锥体,这对做裁剪很不利
  • 透视投影
    在这里插入图片描述

    • 根据Near和Far以及视场角FOV可以求出视锥体近裁剪平面和远裁剪平面的高度:
      • n e a r C l i p P l a n e H e i g h t = 2 ⋅ N e a r ⋅ tan ⁡ F O V 2 nearClipPlaneHeight=2·Near·\tan\frac{FOV}{2} nearClipPlaneHeight=2Neartan2FOV
      • f a r C l i p P l a n e H e i g h t = 2 ⋅ F a r ⋅ tan ⁡ F O V 2 farClipPlaneHeight=2·Far·\tan\frac{FOV}{2} farClipPlaneHeight=2Fartan2FOV
    • 根据摄像机的纵横比Aspect得到裁剪平面的宽度
      • A s p e c t = n e a r C l i p P l a n e W i d t h n e a r C l i p P l a n e H e i g h t Aspect=\frac{nearClipPlaneWidth}{nearClipPlaneHeight} Aspect=nearClipPlaneHeightnearClipPlaneWidth
      • A s p e c t = f a r C l i p P l a n e W i d t h f a r C l i p P l a n e H e i g h t Aspect=\frac{farClipPlaneWidth}{farClipPlaneHeight} Aspect=farClipPlaneHeightfarClipPlaneWidth
    • M f r u s t u m = [ cot ⁡ F O V 2 A s p e c t 0 0 0 0 cot ⁡ F O V 2 0 0 0 0 − F a r + N e a r F a r − N e a r − 2 ⋅ N e a r ⋅ F a r F a r − N e a r 0 0 − 1 0 ] M_{frustum}=\begin{bmatrix} \frac{\cot\frac{FOV}{2}}{Aspect} & 0 & 0 & 0 \\ 0 & \cot\frac{FOV}{2} & 0 & 0 \\ 0 & 0 & -\frac{Far+Near}{Far-Near} & -\frac{2·Near·Far}{Far-Near} \\ 0 & 0 & -1 & 0 \end{bmatrix} Mfrustum=Aspectcot2FOV0000cot2FOV0000FarNearFar+Near100FarNear2NearFar0
    • P c l i p = M f r u s t u m P v i e w = [ x cot ⁡ F O V 2 A s p e c t y cot ⁡ F O V 2 − z F a r + N e a r F a r − N e a r − 2 ⋅ N e a r ⋅ F a r F a r − N e a r − z ] P_{clip}=M_{frustum}P_{view}=\begin{bmatrix} x\frac{\cot\frac{FOV}{2}}{Aspect} \\ y\cot\frac{FOV}{2} \\ -z\frac{Far+Near}{Far-Near}-\frac{2·Near·Far}{Far-Near} \\ -z \end{bmatrix} Pclip=MfrustumPview=xAspectcot2FOVycot2FOVzFarNearFar+NearFarNear2NearFarz
    • 可以看出,投影矩阵本质是对 x x x y y y z z z分量进行了不同程度的缩放(同时对 z z z分量进行了平移),此时顶点的 w w w分量不再是1,而是原先 z z z分量的取反。
    • 如果一个顶点在视锥体内,那么它变换后的坐标需满足:
      − w ≤ x ≤ w -w\leq x\leq w wxw
      − w ≤ y ≤ w -w\leq y\leq w wyw
      − w ≤ z ≤ w -w\leq z\leq w wzw
      在这里插入图片描述
  • 正交投影
    在这里插入图片描述

    • 根据Near和Far以及Size可以得到裁剪平面高度
      • n e a r C l i p P l a n e H e i g h t = f a r C l i p P l a n e H e i g h t = 2 ⋅ S i z e nearClipPlaneHeight=farClipPlaneHeight=2·Size nearClipPlaneHeight=farClipPlaneHeight=2Size
    • 根据摄像机纵横比Aspect得到裁剪平面宽度
      • f a r C l i p P l a n e W i d t h = n e a r C l i p P l a n e W i d t h = A s p e c t ⋅ n e a r C l i p P l a n e H e i g h t farClipPlaneWidth=nearClipPlaneWidth=Aspect·nearClipPlaneHeight farClipPlaneWidth=nearClipPlaneWidth=AspectnearClipPlaneHeight
    • M f r u s t u m = [ 1 A s p e c t ⋅ S i z e 0 0 0 0 1 S i z e 0 0 0 0 − 2 F a r − N e a r − F a r + N e a r F a r − N e a r 0 0 0 1 ] M_{frustum}=\begin{bmatrix} \frac{1}{Aspect·Size} & 0 & 0 & 0 \\ 0 & \frac{1}{Size} & 0 & 0 \\ 0 & 0 & -\frac{2}{Far-Near} & -\frac{Far+Near}{Far-Near} \\ 0 & 0 & 0 & 1 \end{bmatrix} Mfrustum=AspectSize10000Size10000FarNear2000FarNearFar+Near1
    • P c l i p = M o r t h o P v i e w = [ x A s p e c t ⋅ S i z e ⋅ y S i z e − 2 z F a r − N e a r − F a r + N e a r F a r − N e a r 1 ] P_{clip}=M_{ortho}P_{view}=\begin{bmatrix} \frac{x}{Aspect·Size·} \\ \frac{y}{Size} \\ -\frac{2z}{Far-Near}-\frac{Far+Near}{Far-Near} \\ 1 \end{bmatrix} Pclip=MorthoPview=AspectSizexSizeyFarNear2zFarNearFar+Near1
    • 如果一个顶点在视锥体内,那么它变换后的坐标需满足:
      − w ≤ x ≤ w -w\leq x\leq w wxw
      − w ≤ y ≤ w -w\leq y\leq w wyw
      − w ≤ z ≤ w -w\leq z\leq w wzw
      在这里插入图片描述
P矩阵推导

先从正交投影开始
为了方便计算,定义视锥体的范围为从 ( l , b , n ) (l,b,n) (l,b,n) ( r , t , f ) (r,t,f) (r,t,f)
在这里插入图片描述
根据这张图可知,正交投影将视锥体的范围映射到(-1,-1,-1)至(1,1,1),即将三个坐标的范围变换至 [ − 1 , 1 ] [-1,1] [1,1]

x x x轴开始

l ≤ x ≤ r l\leq x\leq r lxr

经过一系列变换将中间项变成形如 p x + q px+q px+q的形式

0 ≤ x − l ≤ r − l 0\leq x-l\leq r-l 0xlrl

− 1 ≤ 2 ( x − l ) r − l − 1 ≤ 1 -1\leq \frac{2(x-l)}{r-l}-1\leq 1 1rl2(xl)11

− 1 ≤ 2 x r − l − r + l r − l ≤ 1 -1\leq \frac{2x}{r-l}-\frac{r+l}{r-l}\leq 1 1rl2xrlr+l1

这个中间项即转换 x x x的公式

x ′ = 2 x r − l − r + l r − l x'=\frac{2x}{r-l}-\frac{r+l}{r-l} x=rl2xrlr+l

同理可得 y y y的转换公式

y ′ = 2 y t − b − t + b t − b y'=\frac{2y}{t-b}-\frac{t+b}{t-b} y=tb2ytbt+b

需要注意的是,视锥体经过转换之后从右手系转换到了左手系,因此 z z z是从 [ − f , − n ] [-f,-n] [f,n]映射到 [ − 1 , 1 ] [-1,1] [1,1]

tips:OpenGL的z分量映射到[-1,1],DirectX的z分量则是映射到[0,1]

− n ≤ z ≤ − f -n\leq z\leq -f nzf

− 1 ≤ − 2 z f − n − f + n f − n ≤ 1 -1\leq -\frac{2z}{f-n}-\frac{f+n}{f-n}\leq 1 1fn2zfnf+n1

得到 z z z的转换公式

z ′ = − 2 z f − n − f + n f − n z'=-\frac{2z}{f-n}-\frac{f+n}{f-n} z=fn2zfnf+n

w分量为1,此时的转换矩阵为

P o = [ 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − t + b t − b 0 0 − 2 z f − n − f + n f − n 0 0 0 1 ] P_o=\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{2z}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{bmatrix} Po=rl20000tb20000fn2z0rlr+ltbt+bfnf+n1

由于z轴会穿过视锥体的中心,因此 r = − l , t = − b r=-l,t=-b r=l,t=b,通过摄像机组件可以获得以下信息

在这里插入图片描述

n e a r C l i p P l a n e H e i g h t = f a r C l i p P l a n e H e i g h t = 2 ⋅ S i z e nearClipPlaneHeight=farClipPlaneHeight=2·Size nearClipPlaneHeight=farClipPlaneHeight=2Size

f a r C l i p P l a n e W i d t h = n e a r C l i p P l a n e W i d t h = A s p e c t ⋅ n e a r C l i p P l a n e H e i g h t farClipPlaneWidth=nearClipPlaneWidth=Aspect·nearClipPlaneHeight farClipPlaneWidth=nearClipPlaneWidth=AspectnearClipPlaneHeight

代入之后可得到正交投影矩阵

M f r u s t u m = [ 1 A s p e c t ⋅ S i z e 0 0 0 0 1 S i z e 0 0 0 0 − 2 F a r − N e a r − F a r + N e a r F a r − N e a r 0 0 0 1 ] M_{frustum}=\begin{bmatrix} \frac{1}{Aspect·Size} & 0 & 0 & 0 \\ 0 & \frac{1}{Size} & 0 & 0 \\ 0 & 0 & -\frac{2}{Far-Near} & -\frac{Far+Near}{Far-Near} \\ 0 & 0 & 0 & 1 \end{bmatrix} Mfrustum=AspectSize10000Size10000FarNear2000FarNearFar+Near1

接下来是透视投影,对 x , y x,y x,y的处理可以分两步:

  1. 给定视锥体中的点 ( x , y , z ) (x,y, z) (x,y,z),把它投影到近平面 z = n z=n z=n。由于投影点在近平面上,所以它的 x x x坐标范围在 [ l , r ] [l, r] [l,r] y y y坐标范围在 [ b , t ] [b, t] [b,t]
  2. 使用在正交投影中推导的公式,把 x x x坐标从 [ l , r ] [l, r] [l,r]映射到 [ − 1 , 1 ] [-1, 1] [1,1],把 y y y坐标范围从 [ b , t ] [b, t] [b,t]映射到 [ − 1 , 1 ] [-1, 1] [1,1]

在这里插入图片描述
根据相似三角形,可知 x x x坐标为 x n z \frac{xn}{z} zxn y y y坐标为 y n z \frac{yn}{z} zyn

将以上坐标带入之前推导的公式中

x ′ = ( 2 n r − l ) x z − r + l r − l x'=(\frac{2n}{r-l})\frac{x}{z}-\frac{r+l}{r-l} x=(rl2n)zxrlr+l

y ′ = ( 2 n t − b ) y z − t + b t − b y'=(\frac{2n}{t-b})\frac{y}{z}-\frac{t+b}{t-b} y=(tb2n)zytbt+b

消去分母上的 z z z

x ′ z = ( 2 n r − l ) x − r + l r − l z x'z=(\frac{2n}{r-l})x-\frac{r+l}{r-l}z xz=(rl2n)xrlr+lz

y ′ z = ( 2 n t − b ) y − t + b t − b z y'z=(\frac{2n}{t-b})y-\frac{t+b}{t-b}z yz=(tb2n)ytbt+bz

为了将等式写入矩阵,需要转化成形如 x ′ = c 1 x + c 2 y + c 3 z + c 4 x'=c_1x+c_2y+c_3z+c_4 x=c1x+c2y+c3z+c4的格式,为此需要获得一个相似的 z ′ z z'z zz的公式,然后就可以通过一个变换矩阵将 ( x , y , z ) (x,y,z) (x,y,z)映射到 ( x ′ z , y ′ z , z ′ z ) (x'z,y'z,z'z) (xz,yz,zz),再将各部分除以 z z z即可得到需要的 ( x ′ , y ′ , z ′ ) (x',y',z') (x,y,z)

为此需要一个公式形如 z ′ z = p z + q z'z=pz+q zz=pz+q,已知需要把 [ − f , − n ] [-f,-n] [f,n]映射到 [ − 1 , 1 ] [-1,1] [1,1]因此当 z = − f z=-f z=f z ′ = 1 z'=1 z=1, z = − n z=-n z=n z ′ = − 1 z'=-1 z=1,可得方程组

tips:此处映射关系要注意,-f  , -n ---> -1  ,  1
					     |     |_______|     |
						 |___________________|

− f = p f + q -f=pf+q f=pf+q
n = p n + q n=pn+q n=pn+q

解得 p = − f + n f − n , q = − 2 n f f − n p=-\frac{f+n}{f-n},q=-\frac{2nf}{f-n} p=fnf+n,q=fn2nf

代入得到 z ′ z = ( − f + n f − n ) z − 2 n f f − n z'z=(-\frac{f+n}{f-n})z-\frac{2nf}{f-n} zz=(fnf+n)zfn2nf

由于此时是在为点 ( x ′ z , y ′ z , z ′ z , w ′ z ) (x'z,y'z,z'z,w'z) (xz,yz,zz,wz)做变换,所以把 w ′ = 1 w'=1 w=1写作 w ′ z = z w'z=z wz=z,得到最终用于透视投影的等式为

x ′ z = ( 2 n r − l ) x − r + l r − l z x'z=(\frac{2n}{r-l})x-\frac{r+l}{r-l}z xz=(rl2n)xrlr+lz

y ′ z = ( 2 n t − b ) y − t + b t − b z y'z=(\frac{2n}{t-b})y-\frac{t+b}{t-b}z yz=(tb2n)ytbt+bz

z ′ z = ( − f + n f − n ) z − 2 n f f − n z'z=(-\frac{f+n}{f-n})z-\frac{2nf}{f-n} zz=(fnf+n)zfn2nf

w ′ z = z w'z=z wz=z

写成矩阵的形式为

P p = [ 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 n f f − n 0 0 1 0 ] P_p=\begin{bmatrix} \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{2nf}{f-n} \\ 0 & 0 & 1 & 0 \end{bmatrix} Pp=rl2n0000tb2n00rlr+ltbt+bfnf+n100fn2nf0

根据摄像机组件获得以下信息
在这里插入图片描述

n e a r C l i p P l a n e H e i g h t = 2 ⋅ N e a r ⋅ tan ⁡ F O V 2 nearClipPlaneHeight=2·Near·\tan\frac{FOV}{2} nearClipPlaneHeight=2Neartan2FOV
f a r C l i p P l a n e H e i g h t = 2 ⋅ F a r ⋅ tan ⁡ F O V 2 farClipPlaneHeight=2·Far·\tan\frac{FOV}{2} farClipPlaneHeight=2Fartan2FOV

A s p e c t = n e a r C l i p P l a n e W i d t h n e a r C l i p P l a n e H e i g h t Aspect=\frac{nearClipPlaneWidth}{nearClipPlaneHeight} Aspect=nearClipPlaneHeightnearClipPlaneWidth
A s p e c t = f a r C l i p P l a n e W i d t h f a r C l i p P l a n e H e i g h t Aspect=\frac{farClipPlaneWidth}{farClipPlaneHeight} Aspect=farClipPlaneHeightfarClipPlaneWidth

最终求得透视投影矩阵为

M f r u s t u m = [ cot ⁡ F O V 2 A s p e c t 0 0 0 0 cot ⁡ F O V 2 0 0 0 0 − F a r + N e a r F a r − N e a r − 2 ⋅ N e a r ⋅ F a r F a r − N e a r 0 0 − 1 0 ] M_{frustum}=\begin{bmatrix} \frac{\cot\frac{FOV}{2}}{Aspect} & 0 & 0 & 0 \\ 0 & \cot\frac{FOV}{2} & 0 & 0 \\ 0 & 0 & -\frac{Far+Near}{Far-Near} & -\frac{2·Near·Far}{Far-Near} \\ 0 & 0 & -1 & 0 \end{bmatrix} Mfrustum=Aspectcot2FOV0000cot2FOV0000FarNearFar+Near100FarNear2NearFar0

坐标空间的应用

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值