OpenGL正交投影和透视投影矩阵推导

1.整体流程图

20140918202127843.jpg

2.个人推导总结

参考文档在这里和这里
为了方便性,这里使用左手坐标系来推导

  • 正交投影推导
    20140407181049609.jpg

    结合图,我们知道,正交投影其实就是将目标视域体[L,B,N]至[R,T,F]的区域
    度量到规则视域体[-1,-1,0]至[1,1,1]的区域中,请仔细理解这句话,这意味着,我可以将很大的一个区域映射到的规则视域体cvv中,也可以将很小的区域映射到使视域体中,而这个区域的具体的大小是由L,B,N 至R,T,F的区域大小决定的。
    下面是推导过程,假设有一个点(x,y,z)位于视域体[L,B,N]至[R,T,F]的区域中 ,那么x,y,z 分别满足如下不等式



对第一个不等式

做如下变换
两边减去L:
两边除以R-L:
两边乘以2:
两边减去1:

整理得:

也就是说,原先在目标视域体[L,B,N]至[R,T,F]的区域中的x ,如果规范到[-1,-1,0]至[1,1,1]的区域中变成x',则有如下关系

只所以我们能进行上述变化是因为这里的映射关系是线性关系

这里有一个容易忽略的事实,为啥说叫裁剪,对上面的等式我们可以尝试一下,

如果取一个大于的数,比如,
那么经过变换后得到
也就是任何的的取值不在之间的数值都会被映射到[-1,1]的区间之外, 而这些区间之外的点会被后续裁剪掉,也就是裁剪真正的逻辑判断

那么同样的道理我们只需要将x,R,L替换成y,T,B就能得到y'的映射关系式如下

如果z的范围也是映射到[-1,1]则可以继续同理,但这里因为是[0,1],所以做一些微的改变

两边减去N:

两边除以F-N:

因此z'的映射关系为

又因为这里只涉及简单的缩放和平移,
于是齐次项

于是一共得到四个式子




将上述四个个等式写成矩阵形式(对此抱有疑问的童鞋请自觉阅读矩阵乘法相关知识)

\begin{bmatrix}x'\\y'\\z'\\w'\end{bmatrix}=\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{1}{F-N}&-\frac{N}{F-N}\\0&0&0&1\end{bmatrix}\begin{bmatrix}x\\y\\z\\1\end{bmatrix}

也就是说,映射过程其实使用的就是上述矩阵,更进一步的,我们来看看这个矩阵都做了什么

\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{1}{F-N}&-\frac{N}{F-N}\\0&0&0&1\\\end{bmatrix}=\begin{bmatrix}\frac{2}{R-L}&0&0&0\\0&\frac{2}{T-B}&0&0\\0&0&\frac{1}{F-N}&0\\0&0&0&1\end{bmatrix}*\begin{bmatrix}1&0&0&-\frac{R+L}{2}\\0&1&0&-\frac{T+B}{2}\\0&0&1&-N\\0&0&0&1\end{bmatrix}

可以看到,正交投影矩阵可以拆分成两个矩阵的乘积,首先进行矩阵

的位移操作,即将整个v视域体的x方向和y方向的中心位置对齐cvv中心位置,同时cv视域体z方向移动到贴近cvv原点的位置。
然后进行vv视域体的拉伸,即左乘以矩阵

映射到cvv视域体的范围区间[-1,-1,0]至[1,1,1]。。这样,cv视域体的物体就完整的映射到ccv视域盒子中了。
正交投影先到这个位置。接下来推导透视投影。

  • 透视投影推导
    20140407181827046.jpg

同样,结合图形我们可以知道透视投影本质上是对视锥体的映射到cvv盒子的过程。
我们回想前面讲的正交投影,想一想透视投影会有什么不同。。
透视投影实际上是对现实世界近大远小的模拟,如果观察铁轨,你会发现两条平行轨道最终交汇于一点。即灭点。

前面的关于正交投影的工作其实并不是毫无作用,借助一下前面正交投影的推导,我想到一种方式来拆分这个从视锥体到cvv的映射过程,
1.首先将视锥体转化为正交投影的vv体,注意下图中的蓝色盒子区域,


QQ截图20171201110233.png

2.接下来执行和正交投影一模一样的操作,即vv到cvv。


QQ截图20171201111933.png

这么一拆分是不是清晰明白了很多呢有木有。
接下来是验证过程,
首先是计算步骤1
观察一下这个视锥体

QQ截图20171201110233.png

我们换个x0z切面视角

QQ截图20171201114647.png

要将视锥体转换成规则视域体,由上图根据相似三角形规则,我们有

整理得

同理可得y的关系式为

假设我们需要映射一个坐标点到标准cvv视域体从上的等式中,我们发现上面两个等式包含一项,也就是说这里的的取值和原始坐标点是一个反比的关系,即距离越远(即值越大),和越小
那对于和的映射关系应该怎么写呢
其实简单的处理就是

这样z的取值范围就刚好映射到(n,f)之间,这样当时,,而时,,非常的合理
然而图形学大佬做出了一个违背祖宗的决定,他们说,既然,都是和是反比关系
那么我们构造一个等式,(这么做的理由目前没想明白,直觉上来看,是在构造矩阵的时候,可以把提取出来,做统一透视除法操作,先留个坑,-----已填坑,看文末
,让也和成反比关系,是两个待定系数,

求解过程如下,
给定约束条件,
于是有


解方程组
得且
把和代入原来的假设
于是自然得到

将z的表达式重新替换,得到新的四个等式写到一起,如下




写成矩阵形式

请注意,这里仅仅是视锥体到规则视域体,并不是直接就到了cvv盒子体内,如果没看懂,请往回翻
以上是第一步骤部分,

那么接下来就简单了,
2.第二步骤,即vv到cvv的正交投影过程,当得到这个规则视域体中的点(x,y,z,1)之后,我们只需要对规则视域体进行正交投影,就能变成最终我们需要的标准cvv体
我们可以很简单的得到这个矩阵
使用

左乘正交投影矩阵,还记得吧,就是这个

忘记的请往回翻)即
\\\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}{F-N}&-\frac{FN}{F-N}\\0&0&1&0\end{bmatrix}=\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{1}{F-N}&-\frac{N}{F-N}\\0&0&0&1\end{bmatrix}*\begin{bmatrix}N&0&0&0\\0&N&0&0\\0&0&F+N&-NF\\0&0&1&0\end{bmatrix}

这便是最终的投影矩阵,从上述过程也可以看出投影矩阵本质上依然包含了正交投影部分的过程。有没有一种豁然开朗的感觉,这便是透视投影矩阵的本质,即先进行视锥体到规则视域体的变换,然后规则视域体进行正交投影变换

需要强调的是,相机空间的点
经过投影矩阵变化后的点是在齐次裁剪空间的点,
为了更加详细的说明,我们简单再列一下
\begin{bmatrix}x\\y\\z\\w\end{bmatrix}=\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}{F-N}&-\frac{FN}{F-N}\\0&0&1&0\end{bmatrix}\begin{bmatrix}x0\\y0\\z0\\1\end{bmatrix}





即投影矩阵只是虚晃一枪,并没有执行真正的透视除法操作,因为在执行透视除法之前,还有一个步骤是进行裁剪判断,这里判断方法是计算



这么判断的前提是因为的范围是和的取值范围均是到,z最终的取值范围是到,因此可以再执行透视除法之前先这么简单判断,如果透视除法的cvv换个样子,那么裁剪判断也需要相应的去改变

最后,当需要真实的展示在中,则需要再进行透视除法,即,各项除以,才能得到中的

相关问题说明,为何你发现很多地方的看到的投影矩阵有些微的差别,那么我分析主要有几个原因

  • 这里的cvv体是这个区间内。而其他地方可能使用的是作为cvv盒子区间,比如使用作为标准cvv区间,则投影矩阵应该是下面的形式
    (最开始推导的时候没特别注意,后来翻阅的投影矩阵实现,确实其中值使用的是的区间)

\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}= \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{F+N}{F-N}\\0&0&0&1\end{bmatrix} * \begin{bmatrix}N&0&0&0\\0&N&0&0\\0&0&F+N&NF\\0&0&-1&0\end{bmatrix}

  • 很多矩阵你会发现,部分写成0,部分写成了0,那是因为他们默认,以及写成的简略模式所致,其实真实情况未必如此,不一定非要等于,且也不一定非要等于,那么在这里我还是更喜欢保留,等等,因为这才是投影矩阵本来的样子。

以上~~

填坑---2023-02-14

对于投影矩阵的推导取的填坑解释

image.png

image.png

这里有两条线,一条是,这里等价于前面提到的,
也就是说假如的深度从到的时候,的取值也从到

而另一条线,等价于,即从近平面深度到远平面深度

可以看到,通过上述方式待定系数求出的最终曲线函数,本质上还是增函数,即随着深度的增大,值也增大
区别在于
是线性函数
而是非线性函数,那这样到底有什么好处呢,

我们知道在三维世界中,距离玩家或者说相机观察视角近的位置是需要更加精确的表达的,
也就是对于近处的深度,我们希望近处物体的深度值相对更具有区分度
而对于远处的物体的深度,其实我们没有那么在乎,因为已经很远了,在视野中远处的物体其实占比非常小,也不太需要精确渲染

有了上面这个概念,我们再来看这个曲线函数,可以看到,当定义域在的范围内时候,其值域范围是
反观函数,当定义域在的范围内,其值域范围还是
也就是说,曲线函数的形式,提供了近处深度更大范围的值域取值,这对于对深度敏感的一些操作是非常有好处的

你可能感兴趣的:(OpenGL正交投影和透视投影矩阵推导)