Unity Shader 图形学,透视投影矩阵,正交投影矩阵的原理及推导,最直观地理解矩阵的意义

前言

我在阅读《unityshader入门精要》时,发现书上并没有给出投影矩阵的推导过程
投影矩阵在图形学有很关键的作用,在游戏开发,虚拟现实和增强现实,机器人学,机器视觉都有涉及到
我想用最直观的方式,解释透视正交投影如何得到的
想要看懂本文,要对缩放旋转平移,3大矩阵要清晰透彻的认识

正交投影

我们先从简单的正交投影开始,想要学习透视矩阵的,建议先学会正交矩阵
在这里插入图片描述
Size:竖直方向上高度的一半,NearHeight/2
Aspect,摄像机横纵比,Aspect= N e a r W i d t h N e a r H e i g h t {\frac{NearWidth}{NearHeight}} NearHeightNearWidth
根据已知的Size,Near,Far,Apect求出变换矩阵
在这里插入图片描述
先将长方体进行缩放,让xyz都在[-1,1],
如下图所示,
对于y轴,对于点2.y= N e a r H e i g h t 2 \frac{NearHeight}{2} 2NearHeight=Size,Size=>1,k2= 1 S i z e \frac{1}{Size} Size1
直观的理解就是y轴从Size=>1,y轴缩放大小是 1 S i z e \frac{1}{Size} Size1
Aspect(简称a)= N e a r W i d t h N e a r H e i g h t {\frac{NearWidth}{NearHeight}} NearHeightNearWidth,w=ah,x=ay

对于x轴
注意是变换之前a=x/y => x=ay
x’=k1x
y’=k2y
x’=y’=1(变换之后的x’,y’坐标都为1)
k1x=k2y
k1=k2 * y x \frac{y}{x} xy
a= x y \frac{x}{y} yx
k1= k 2 a \frac{k2}{a} ak2
k2= 1 S i z e \frac{1}{Size} Size1
k1= 1 A s p e c t ∗ S i z e \frac{1}{Aspect*Size} AspectSize1
w=ah为什么不是k1=ak2,而是k1=k2/a,这是因为知道的是变换之前的比值,变换之后x’=y’,
假设是横屏,宽度大于高度,即a>1,x>y,想要x’=y’,则x’=kx,k<1,即1/a

请添加图片描述

对于z轴,观察长方体变换前后的长度,z=Far-Near,z’=2,z轴要翻转,乘以-1,
Far-Near=>2
z’=k3z,
k3= − 2 F a r − N e a r -\frac{2}{Far-Near} FarNear2
矩阵:
[ 1 S i z e 0 0 0 0 1 A s p e c t S i z e 0 0 0 0 − 2 F a r − N e a r ? 0 0 0 1 ] \begin{bmatrix} \frac{1}{Size}& 0 & 0 & 0 \\ 0 & \frac{1}{AspectSize} & 0&0\\ 0 & 0 & -\frac{2}{Far-Near}&?\\ 0 & 0 & 0& 1\\ \end{bmatrix} Size10000AspectSize10000FarNear2000?1
再考虑z轴上的平移就可以求出完整的矩阵了
平移,由2部分组成,如上图所示,在经过缩放后的空间观察,
一部分是,摄像机到裁剪平面的距离,另一部分是正方体长度的一半
摄像机到裁剪平面的距离,由于经过缩放,大小不是Near,而是Near*k3= − 2 N e a r F a r − N e a r -\frac{2Near}{Far-Near} FarNear2Near
正方体长度的一半,注意z轴翻转了,1, − 2 N e a r F a r − N e a r -\frac{2Near}{Far-Near} FarNear2Near-1= − 2 N e a r F a r − N e a r -\frac{2Near}{Far-Near} FarNear2Near- F a r − N e a r F a r − N e a r \frac{Far-Near}{Far-Near} FarNearFarNear
= − N e a r − F a r F a r − N e a r \frac{-Near-Far}{Far-Near} FarNearNearFar= − F a r + N e a r F a r − N e a r -\frac{Far+Near}{Far-Near} FarNearFar+Near(和书上的写法保持一致)
至此,正交矩阵就推导出来了
[ 1 S i z e 0 0 0 0 1 A s p e c t 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 ] \begin{bmatrix} \frac{1}{Size}& 0 & 0 & 0 \\ 0 & \frac{1}{AspectSize} & 0&0\\ 0 & 0 & -\frac{2}{Far-Near}&-\frac{Far+Near}{Far-Near}\\ 0 & 0 & 0& 1\\ \end{bmatrix} Size10000AspectSize10000FarNear2000FarNearFar+Near1
如果不理解矩阵为什么要怎么写,可以查查关于缩放旋转平移,3大矩阵的资料

透视投影

  1. 基本概念:
    NearHeight: 近裁剪面的高度
    FarHeight: 远裁剪面的高度
    Near:摄像机离近裁剪面的距离
    Far:摄像机离近裁剪面的距离
    FOV:Field of View,视野范围

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

为什么上面的变换不能像正交变换一样,直接转化为[-1,1]标准化的立方体
而是要变换为一个棱台,这是因为矩阵的线性变换,可以将长方体变换为立方体,
无法将一个棱台转换为立方体,棱台转换为立方体需要非线性变换函数,
4×4的变换矩阵,只能对空间进行缩放旋转平移,空间中任意2个原本平行的直线变换后仍然平行,这3大变换显然不能将棱台转换为立方体.因为棱台=>正方体,棱台的两侧的直线不平行=>平行,线性变换无法实现
将w存储变换之前的z,将变换之后的点xyz都除以w,就都变换到[-1,1],此变换是非线性的,缩放值是不固定的,对
不同的平面(平行于xOy的平面),缩放值为平面之前离摄像机的距离
这也是为什么变换后xy有Near,Far
上面的变换可以分为以下几步

  • 对视锥体进行缩放,让它的xyzw等于缩放之后的xyzw
  • 对视锥体的z方向进行平移
  • 翻转z轴

tan F O V 2 \frac{FOV}{2} 2FOV= n e a r H e i g h t 2 N e a r \frac{\frac{nearHeight}{2}}{Near} Near2nearHeight
tan F O V 2 \frac{FOV}{2} 2FOV等于近裁剪面的高度的一半/Near
Aspect,摄像机横纵比,Aspect= N e a r W i d t h N e a r H e i g h t {\frac{NearWidth}{NearHeight}} NearHeightNearWidth
先考虑缩放
y轴的缩放,对于下图点2.y来说 N e a r H e i g h t 2 \frac{NearHeight}{2} 2NearHeight=>Near
对于y轴,由 n e a r H e i g h t 2 = > N e a r \frac{nearHeight}{2}=>Near 2nearHeight=>Near,
即将原来的y乘以 N e a r N e a r H e i g h t 2 \frac{Near}{\frac{NearHeight}{2}} 2NearHeightNear=>y’
y* N e a r N e a r H e i g h t 2 \frac{Near}{\frac{NearHeight}{2}} 2NearHeightNear=y’
y’=ky,k= N e a r N e a r H e i g h t 2 \frac{Near}{\frac{NearHeight}{2}} 2NearHeightNear
由①=>cot F O V 2 \frac{FOV}{2} 2FOV= N e a r n e a r H e i g h t 2 \frac{Near}{\frac{nearHeight}{2}} 2nearHeightNear
由②③得k=cot F O V 2 \frac{FOV}{2} 2FOV
怎么直观理解cot F O V 2 \frac{FOV}{2} 2FOV,
其实就是点2.y变换前后的缩放,
恰好等于Near/近裁剪面的高度的一半,即cot F O V 2 \frac{FOV}{2} 2FOV

因为,NearWidth=Aspect*NearHeight,w=ah
NearHeight= N e a r W i d t h A s p e c t \frac{NearWidth}{Aspect} AspectNearWidth,h=w/a
对于x轴的缩放=y轴的缩放/Aspect
对于x轴,由NearWidth/2=>Near,即将原来的x乘以 N e a r N e a r W i d t h 2 \frac{Near}{\frac{NearWidth}{2}} 2NearWidthNear
w=ah为什么不是k1=ak2,而是k1=k2/a,这是因为知道的是变换之前的比值,变换之后x’=y’,
假设是横屏,宽度大于高度,即a>1,x>y,想要x’=y’,则x’=kx,k<1,即1/a

对于x轴的缩放有2种方式推导
方法1:
注意是变换之前a=x/y => x=ay
x’=k1x
y’=k2y
x’=y’=Near(变换之后的x’,y’坐标都为Near)
k1x=k2y
k1=k2 * y x \frac{y}{x} xy
a= x y \frac{x}{y} yx
k1= k 2 a \frac{k2}{a} ak2
k2=cot F O V 2 \frac{FOV}{2} 2FOV
k1= c o t F O V 2 A s p e c t \frac{cot\frac{FOV}{2}}{Aspect} Aspectcot2FOV

方法2:
x * N e a r N e a r W i d t h 2 \frac{Near}{\frac{NearWidth}{2}} 2NearWidthNear=x’,k2= N e a r N e a r W i d t h 2 \frac{Near}{\frac{NearWidth}{2}} 2NearWidthNear
②=> N e a r h 2 \frac{Near}{\frac{h}{2}} 2hNear=> N e a r w / a 2 \frac{Near}{\frac{w/a}{2}} 2w/aNear=> N e a r w 2 a \frac{Near}{\frac{w}{2a}} 2awNear
cot F O V 2 \frac{FOV}{2} 2FOV= N e a r n e a r H e i g h t 2 \frac{Near}{\frac{nearHeight}{2}} 2nearHeightNear
=>cot F O V 2 \frac{FOV}{2} 2FOV= N e a r w 2 a \frac{Near}{\frac{w}{2a}} 2awNear
=> c o t F O V 2 a \frac{cot\frac{FOV}{2}}{a} acot2FOV= N e a r w 2 \frac{Near}{\frac{w}{2}} 2wNear
k2= N e a r w 2 \frac{Near}{\frac{w}{2}} 2wNear= c o t F O V 2 a \frac{cot\frac{FOV}{2}}{a} acot2FOV
所以,x,y的缩放倍数已经得到
[ c o t F O V 2 A s p e c t 0 0 0 0 c o t F O V 2 0 0 0 0 ? ? 0 0 ? 0 ] \begin{bmatrix} \frac{cot\frac{FOV}{2}}{Aspect} & 0 & 0 & 0 \\ 0 & cot\frac{FOV}{2} & 0&0\\ 0 & 0 & ?&?\\ 0 & 0 & ?& 0\\ \end{bmatrix} Aspectcot2FOV0000cot2FOV0000??00?0
与上面的图片一样,方便查看图片
在这里插入图片描述

下面讲解怎么得到z轴的缩放
对于视锥体,在z方向,之前视锥体的长度为Far-Near,变换之后的大小为Far+Near,
所以k3= F a r + N e a r F a r − N e a r \frac{Far+Near}{Far-Near} FarNearFar+Near,对z轴进行翻转,k3=- F a r + N e a r F a r − N e a r \frac{Far+Near}{Far-Near} FarNearFar+Near
下面讲解z轴的平移和z轴的翻转,平移分两部分,在经过缩放后的空间观察,
一部分是变换后的点2的z,即z’2 =k3Near,另一部分是Near
z’=k3z,k3= F a r + N e a r N e a r − F a r \frac{Far+Near}{Near-Far} NearFarFar+Near,Near F a r + N e a r N e a r − F a r \frac{Far+Near}{Near-Far} NearFarFar+Near= N e a r ∗ F a r + N e a r 2 N e a r − F a r \frac{Near*Far+Near^{2}}{Near-Far} NearFarNearFar+Near2
加上变换之后的,-Near(因为z轴的翻转), N e a r ∗ F a r + N e a r 2 N e a r − F a r \frac{Near*Far+Near^{2}}{Near-Far} NearFarNearFar+Near2-Near=
N e a r ∗ F a r + N e a r 2 N e a r − F a r \frac{Near*Far+Near^{2}}{Near-Far} NearFarNearFar+Near2- N e a r 2 − N e a r ∗ F a r N e a r − F a r \frac{Near^{2}-Near*Far}{Near-Far} NearFarNear2NearFar= 2 ∗ N e a r ∗ F a r N e a r − F a r \frac{2*Near*Far}{Near-Far} NearFar2NearFar
至此,缩放平移都完成了
要w保存之前的z,设置第4行3列为1即可
透视矩阵就推导出来了
[ c o t F O V 2 A s p e c t 0 0 0 0 c o t 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 ] \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} Aspectcot2FOV0000cot2FOV0000FarNearFar+Near100FarNear2NearFar0

猜你喜欢

转载自blog.csdn.net/qq_58047420/article/details/134278171