3D数学-透视投影

3D数学-透视投影

好记性不如烂笔头啊,还是记录一下!


概述

投影变换完成的是如何将三维模型显示到二维视口上,这是一个三维到二维的过程。你可以将投影变换看作是调整照相机的焦距,它模拟了为照相机选择镜头的过程。投影变换是所有变换中最复杂的一个。


近大远小

近大远小是众所周知的光学现象。之所以出现这种现象,是因为离人眼近的物体在视网膜上的投影大,而离眼睛远的物体在视网膜上的投影小。如下图所示,红色箭头和蓝色箭头的高度相同,但是蓝色箭头离眼睛近,因此它在视网膜上的投影,要大于红色箭头的投影。

3D数学-透视投影_1.jpg

然而物体看上去的大小,除了与它离眼睛的远近有关,还和物体本身的尺寸有关。视角(angle of view 或者 field of view 视域)可以取代上述两者,直接比较物体看上去的大小。在计算机图形学中,为了让三维物体显示在屏幕上有立体感,有必要模拟人眼近大远小这一个特性,利用透视投影矩阵可以方便地完成这项任务。


视锥体

视锥体是一个三维体,他的位置和摄像机相关,视锥体的形状决定了模型如何从camera space投影到屏幕上。透视投影使用棱锥作为视锥体,摄像机位于棱锥的椎顶。该棱锥被前后两个平面截断,形成一个棱台,叫做View Frustum,只有位于Frustum内部的模型才是可见的。我们也通常称这个为裁剪空间,在这个裁剪空间中有两个平面比较特殊,我们分辨称为近裁剪平面(near clip plane)远裁剪平面(far clip plane)

3D数学-透视投影_2.jpg

投影矩阵的本质

投影矩阵有两个目的:

  • 首先是为投影做准备。这是个迷惑点。虽然投影矩阵的名称包含了投影二字,但是它并没有进行真正的投影工作,而是在为投影做准备。真正得投影发生在后面得齐次除法(homogeneous division)过程中。经过投影矩阵的变换后,顶点的w分量会具有特殊的意义。
  • 其次是对xyz分量进行缩放。如果用视锥体的6个裁剪平面来进行裁剪会比较麻烦,而经过投影矩阵的缩放后,久可以直接使用w分量作为一个范围值。如果xyz分量都位于这个范围内,就说明该顶点位于裁剪空间内,如下图所示:
3D数学-透视投影_3.png

投影矩阵推导

3D数学-透视投影_5.gif

如图所示:

<x_{e}, y_{e}, z_{e}>是相机空间中的一个坐标点

<x_{p}, y_{p}, z_{p}>表示该坐标点在近裁剪平面(near clip plane)上的投影坐标

<x_{n}, y_{n}, z_{n}>表示经过透视投影后在规范化设备坐标系(Normalized Device Coordinates)中的坐标

l表示近裁剪平面(near clip plane)的左边,即x=l

r表示近裁剪平面(near clip plane)的右边,即x=r

t表示近裁剪平面(near clip plane)的上边,即y=t

b表示近裁剪平面(near clip plane)的下边,即y=b

有以下关系式:

\frac{x_{e}}{x_{p}}=\frac{z_{e}}{-n}

可解出得:

x_{p}=-\frac{nx_{e}}{z_{e}}

同理:

y_{p}=-\frac{ny_{e}}{z_{e}}

现在需要将x_{p}映射到x_{n}x_{p}得范围是[l, r]x_{n}得范围是[-1, 1],可以利用简单线性插值的方法获得以下关系式:

\frac{x_{p}-l}{r-l}=\frac{x_{n}-(-1)}{1-(-1)}

同理可得到以下方程组:

\begin{cases} \frac{x_{p}-l}{r-l}=\frac{x_{n}-(-1)}{1-(-1)} \\[2ex] \frac{y_{p}-b}{t-b}=\frac{y_{n}-(-1)}{1-(-1)} \\[2ex] x_{p}=-\frac{nx_{e}}{z_{e}} \\[2ex] y_{p}=-\frac{ny_{e}}{z_{e}} \end{cases}

可解出得:

\begin{cases} x_{n}=(-\frac{x_{e}}{z_{e}})\frac{2n}{r-l}-\frac{r+l}{r-l} \\[2ex] y_{n}=(-\frac{y_{e}}{z_{e}})\frac{2n}{t-b}-\frac{t+b}{t-b} \end{cases}

最后看看z_{n},当视锥体内的顶点投影到近裁剪平面(near clip plane)的时候,实际上z_{p}的值已经没有意义了,因为所有近裁剪平面(near clip plane)上的点,他们的z_{p}值都是-n,看起来我们甚至可以抛弃这个z_{p}值,可以么?当然不行!不要忘记还有深度测试。<x_{e}, y_{e}, z_{e}><x_{p}, y_{p}, z_{p}>这条直线上的点都会投影到<x_{p}, y_{p}, z_{p}>这个点,那么如果直线上有多个点投影到同一个点时,如何确定最终保留哪一个呢?当然时距离观察者最近的这个了,也就是深度值(z_{e})最小的,所以z_{p}可以直接保存为z_{e}的值。由于在光栅化的过程中,要进行z坐标的倒数的插值(参考《3D数学-透视校正插值》),因此映射函数应为\frac{1}{z}的函数,同时允许深度投影是线性插值,则可以获得以下映射函数的表达式:

z_{n}=\frac{A}{z_{e}}+B

在映射前,z_{e}的范围是[-f,-n]。在映射后,z_{e}的范围是[-1,1]。需要找到-n \rightarrow -1-f \rightarrow 1的映射关系(该映射应该将z坐标反向,因为齐次裁剪空间为左手坐标系), 将数据代入上面的一次式,可得下面的方程组:

\begin{cases} -1=\frac{A}{-n}+B \\[2ex] 1=\frac{A}{-f}+B \end{cases}

解出可得:

\begin{cases} A=\frac{2nf}{f-n} \\[2ex] B=\frac{f+n}{f-n} \end{cases}

可以得到z坐标映射到[-1,1]的映射函数为:

z_{n}=-\frac{2nf}{f-n}(-\frac{1}{z_{e}})+\frac{f+n}{f-n}

整理可得:

\begin{cases} x_{n}=(-\frac{x_{e}}{z_{e}})\frac{2n}{r-l}-\frac{r+l}{r-l} \\[2ex] y_{n}=(-\frac{y_{e}}{z_{e}})\frac{2n}{t-b}-\frac{t+b}{t-b} \\[2ex] z_{n}=(-\frac{1}{z_{e}})(-\frac{2nf}{f-n})+\frac{f+n}{f-n} \end{cases}

可以发现以上等式中都除以-z_{e},则3D点<x_{n}, y_{n}, z_{n}>对应的齐次坐标为:

<-x_{n}z_{e}, -y_{n}z_{e}, -z_{n}z_{e}, -z_{e}>

-x_{n}z_{e}-y_{n}z_{e}-z_{n}z_{e}分别为:

\begin{cases} -x_{n}z_{e}=x_{e}\frac{2n}{r-l}+z_{e}\frac{r+l}{r-l} \\[2ex] -y_{n}z_{e}=y_{e}\frac{2n}{t-b}+z_{e}\frac{t+b}{t-b} \\[2ex] -z_{n}z_{e}=z_{e}(-\frac{f+n}{f-n})-\frac{2nf}{f-n} \end{cases}

以上函数组为点P_{e}的线性函数组,因此可以用一个4 \times 4的矩阵M_{frustum}来表示P_{n}点的计算公式:

P_{n} = M_{frustum} \cdot P_{e} = \begin{bmatrix} \frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0 \\[2ex] 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0 \\[2ex] 0 & 0 & -\frac{f+n}{f-n} & -\frac{2nf}{f-n} \\[2ex] 0 & 0 & -1 & 0 \end{bmatrix} \cdot \begin{bmatrix} x_{e} \\[2ex] y_{e} \\[2ex] z_{e} \\[2ex] 1 \end{bmatrix}

M_{frustum}就是最终的透视变换矩阵。相机空间中的顶点,如果在视锥体中,则变换后就在规范化设备坐标系(Normalized Device Coordinates)中。如果在视锥体外,变换后就在规范化设备坐标系(Normalized Device Coordinates)外,而规范化设备坐标系(Normalized Device Coordinates)本身的规则性对于多边形的裁剪很有利。

投影矩阵的另一种形式

视角(angle of view 或者 field of view 视域)是视锥体再xz平面或者yz平面的开角角度,也可以用来描述透视投影矩阵。具体哪个平面都可以,OpenGLD3D都使用yz平面,Aspect是投影平面的宽高比,如图所示:

![avatar][image5]

可以得到一下关系式:

\begin{cases} Aspect = \frac{r}{t} \\[2ex] t = n \times \tan\frac{fov}{2} \\[2ex] b = -t \\[2ex] r = t \times Aspect \\[2ex] l = -r \end{cases}

所以M_{frustum}还可以写成:

M_{frustum}= \begin{bmatrix} \frac{\cot\frac{fov}{2}}{Aspect} & 0 & 0 & 0 \\[2ex] 0 & \cot\frac{fov}{2} & 0 & 0 \\[2ex] 0 & 0 & -\frac{f+n}{f-n} & -\frac{2nf}{f-n} \\[2ex] 0 & 0 & -1 & 0 \end{bmatrix}

z-fighting

还有一点需要额外注意,上述变换矩阵的过程中,x_{n}x_{e}y_{n}y_{e}是线性的,但是z_{n}z_{e}是非线性的:

z_{n}=(-\frac{1}{z_{e}})(-\frac{2nf}{f-n})+\frac{f+n}{f-n}

z_{e}越接近-fz_{n}越接近1,z_{e}越接近-nz_{n}越接近-1。也就是说,z_{n}越大,离相机越远,反之离相机越近。z_{n}z_{e}的变化关系如下图所示:

3D数学-透视投影_6.png

通过观察左侧图,我们发现:当相机坐标系中的点越接近近裁剪平面(near clip plane)时,z_{e}上发生的微小变化都会导致z_{n}的剧烈变化;而当点越接近远裁剪平面(far clip plane)时,z_{n}z_{e}上发生的变化不敏感。在做渲染时,z方向的绝对深度并没有意义,我们只需要知道各点的相对深度,确定遮挡关系,保证靠近相机的点挡住它后面离相机远的点即可。因此,越接近近裁剪平面(near clip plane)的点,它的深度渲染就越准确,而越接近远裁剪平面(far clip plane)的点,它的深度渲染就越不准确。

此外,对比上面的左右两幅图,我们发现:当远裁剪平面(far clip plane)近裁剪平面(near clip plane)距离较大时,接近远裁剪平面(far clip plane)的点的z_{n}z_{e}的变化十分不敏感,这样导致的问题称为z-fighting。因此,在条件允许的情况下,应该尽量减小两个裁剪平面之间的距离。

附一张z方向的映射关系图:

3D数学-透视投影_7.png

饮水思源

参考文献:

《3D游戏与图形学中的数学方法》

《透视投影详解》

《Perspective Projection Matrix 透视投影矩阵的推导》

《图形学扫盲--(2)透视投影(Perspective Projection)》


版权声明:原创技术文章,撰写不易,转载请注明出处!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355