[译][译]OpenGL投影矩阵

栏目: 编程工具 · 发布时间: 6年前

内容简介:这是关于OpenGL投影矩阵的一篇译文,原文在电脑显示屏是一个2D平面,为了能够在这个2D平面上显示OpenGL渲染的3D场景,我们必须将3D场景当作2D图像投影到这个2D平面(计算机屏幕)上.GL_PROJECTION 矩阵就是用来做这种投影变换的.首先,该矩阵将所有观察空间的顶点坐标变换到裁剪空间,接着,将变换后的顶点坐标(即裁剪坐标)的每个分量

这是关于OpenGL投影矩阵的一篇译文,原文在 这里 .

概览(Overview)

电脑显示屏是一个2D平面,为了能够在这个2D平面上显示OpenGL渲染的3D场景,我们必须将3D场景当作2D图像投影到这个2D平面(计算机屏幕)上.GL_PROJECTION 矩阵就是用来做这种投影变换的.首先,该矩阵将所有观察空间的顶点坐标变换到裁剪空间,接着,将变换后的顶点坐标(即裁剪坐标)的每个分量 ( x , y , z , w ) (x,y,z,w) 除以坐标的 w w 分量,使其变换为标准化设备坐标(NDC).

[译][译]OpenGL投影矩阵

这里我们需要注意的一点就是 : GL_PROJECTION 矩阵同时整合了裁剪(视锥体剔除)和标准化设备坐标(NDC)变换的功能( 译注:这里不是指 GL_PROJECTION 矩阵本身整合了这些功能,而是指 OpenGL 的 GL_PROJECTION 矩阵模式整合了这些功能 ).接下来的内容就是描述如何从6个边界参数(left, right, bottom, top, near 和 far) 构造出这个投影矩阵.

值得一提的是,视锥体剔除是在裁剪空间进行的(NDC变换之前) : 裁剪坐标中的 x c x_c , y c y_c z c z_c 分量会分别与 w c w_c 分量进行比较,如果其中任一分量小于 w c -w_c ,或者大于 w c w_c ,则该坐标对应的顶点就会被丢弃(即发生了裁剪).

接着, 如果发生了裁剪, OpenGL 会重新构建发生裁剪的多边形边缘.

透视投影

在透视投影中,视锥体(观察空间)中的一个3D坐标点会被映射到一个立方体中(NDC);其中 x x 坐标范围会从 [ l , r ] [l, r] 映射到 [ 1 , 1 ] [-1, 1] , y y 坐标范围会从 [ b , t ] [b, t] 映射到 [ 1 , 1 ] [-1, 1] , z z 坐标范围会从 [ n , f ] [-n, -f] 映射到 [ 1 , 1 ] [-1, 1] .

[译][译]OpenGL投影矩阵

这里需要注意的是,观察空间是在右手坐标系下(OpenGL 使用右手坐标系)定义的,但是 NDC 却是在左手坐标系下定义的.换句话说就是,观察空间中的摄像机是指向 -Z 轴的,但是在 NDC 中,摄像机指向的却是 +Z 轴( 译注:NDC变换会改变左右手坐标系 ).由于 glFrustum() 函数只接受正的近/远裁剪面距离,所以我们需要在构造 GL_PROJECTION 矩阵的过程中将近/远裁剪面距离变成负数( 译注:因为在观察空间中,摄像机是指向 -Z 轴的 ).

在 OpenGL 中,观察空间中3D坐标点是投影到近裁剪面(即投影面)上的.下面的示意图展示了一个在观察空间中的坐标点 ( x e , y e , z e ) (x_e, y_e, z_e) ,是如何投影到近裁剪面坐标点 ( x p , y p , z p ) (x_p, y_p, z_p) 上的.

[译][译]OpenGL投影矩阵 [译][译]OpenGL投影矩阵 从视锥体的顶部视图可以看到, x e x_e (观察空间中的 x x 坐标)的投影坐标 x p x_p 可以使用相似三角形对应边长成比例来求解:

[译][译]OpenGL投影矩阵

从视锥体的侧面视图来看, y p y_p 也可以使用类似的方式求解:

[译][译]OpenGL投影矩阵

注意到 x p x_p y p y_p 的数值都是依赖于 z e z_e 的,并且两者的数值大小都反比与 z e -z_e (这两个数值的求解都除以了 z e -z_e ).这是我们构建 GL_PROJECTION 矩阵的第一条线索.在观察空间中的坐标经过 GL_PROJECTION 矩阵变换之后,得到的裁剪坐标还是一个 齐次坐标 ,需要将坐标的各个分量除以坐标的 w w 分量才能将其变换为标准化设备坐标(NDC).(更多细节可以看 这里 )

[译][译]OpenGL投影矩阵 [译][译]OpenGL投影矩阵 所以,我们可以将裁减坐标的 w w 分量设置为 z e -z_e ,基于此,GL_PROJECTION 矩阵的第四行便可以确定了,应为 ( 0 , 0 , 1 , 0 ) (0, 0, -1, 0) .

[译][译]OpenGL投影矩阵

接下来,我们要将 x p x_p y p y_p 线性映射到 NDC 下的 x n x_n y n y_n , 即 [ l , r ] [l, r] [ 1 , 1 ] [-1, 1] , [ b , t ] [b, t] [ 1 , 1 ] [-1, 1] .

[译][译]OpenGL投影矩阵

[译][译]OpenGL投影矩阵

然后,我们将 x p x_p y p y_p 的表达式代入上面的等式.

[译][译]OpenGL投影矩阵 [译][译]OpenGL投影矩阵 由于要进行透视除法的关系 ( x c / w c , y c / w c ) (x_c/w_c, y_c/w_c) ,我们将等式都调整成了除以 z e -z_e 的形式.我们先前已经设置了 wc 为 z e -z_e ,所以等式括号里项即是裁剪坐标 x c x_c y c y_c .

通过这些等式,我们就可以确定 GL_PROJECTION 矩阵的第一行和第二行了:

[译][译]OpenGL投影矩阵

现在,我们只需要求解出 GL_PROJECTION 矩阵的第三行便可以了,不过计算 z n z_n 和之前计算的 x n x_n y n y_n 有些不同,因为观察空间中的 z e z_e 总是会被投影到近裁剪面上(数值为 n -n ),而我们需要的是唯一的 z z 值以进行裁剪和深度检测,另外的,我们也应该能够"反投影"(unproject,投影的逆变换) z n z_n .由于我们知道 z z 坐标并不依赖与 x x 坐标和 y y 坐标,所以我们可以借助 w w 分量来求解 z n z_n z e z_e 的关系,计算方法如下:

[译][译]OpenGL投影矩阵

观察空间中, w e w_e 等于 1 1 ,所以上面的等式可以化简为:

[译][译]OpenGL投影矩阵

为了计算 A A B B 这两个参数,我们可以利用 ( z e , z n ) (z_e, z_n) 的两个条件关系: ( n , 1 ) (-n, -1) ( f , 1 ) (-f, 1) ( 译注:即 z e = n z_e = -n 时, z n = 1 z_n = -1 ; z e = f z_e = -f 时, z n = 1 z_n = 1 ),代入上面的等式,我们有:

[译][译]OpenGL投影矩阵

[译][译]OpenGL投影矩阵

[译][译]OpenGL投影矩阵

[译][译]OpenGL投影矩阵

通过上面的计算,我们得到了系数 A A B B 的表达式,于是 z e z_e z n z_n 的关系式变为:

[译][译]OpenGL投影矩阵

最终,我们得到了完整的 GL_PROJECTION 矩阵:

[译][译]OpenGL投影矩阵

上面的投影矩阵对应于一般的视锥体投影,如果视锥体是上下左右对称的话(即 r = l , t = b r = -l, t = -b ),则上面的投影矩阵可以做如下简化:

[译][译]OpenGL投影矩阵

在我们继续讲解之前,我们再来观察一下 z e z_e z n z_n 的关系,也就是上面的等式 ( 3 ) (3) .注意到该等式是个非线性的有理函数,当 z e z_e 靠近近裁剪面的时候,对应 z n z_n 的精度会比较高,当 z e z_e 靠近远裁剪面的时候,对应 z n z_n 的精度则比较低.于是,当 [ n , f ] [-n, -f] 的范围变大的时候,就会发生深度缓冲的精度问题(z-fighting),因为此时靠近远裁剪面的 z e z_e 的微小变化并不会影响 z n z_n 的数值( 译注:数学角度讲, z e z_e 的任何变化其实都会影响到 z n z_n 的数值,这里说不会影响 z n z_n 的数值是从计算机中数值精度表示有限的角度来讲的 ),所以我们应该尽量缩短 n n f f 之间的距离,以最小化上述的深度缓冲精度问题.

[译][译]OpenGL投影矩阵

正交投影

为正交投影构建一个 GL_PROJECTION 矩阵比上面说的透视投影要简单多了.

[译][译]OpenGL投影矩阵

所有观察空间的 x e x_e , y e y_e z e z_e 分量都被线性的映射到 NDC 中,我们要做的就是将长方体(观察空间)缩放成一个立方体(NDC),然后将其移动到原点位置.我们马上来算一下 GL_PROJECTION 矩阵的各个元素:

[译][译]OpenGL投影矩阵 [译][译]OpenGL投影矩阵 [译][译]OpenGL投影矩阵

由于在正交投影中,我们不需要 w w 分量的参与,所以 GL_PROJECTION 矩阵的第四行设置为了 ( 0 , 0 , 0 , 1 ) (0, 0, 0, 1) .最终的 GL_PROJECTION 矩阵表示如下:

[译][译]OpenGL投影矩阵

同透视投影一样,如果视锥体是上下左右对称的话(即 r = l , t = b r = -l, t = -b ),上面的 GL_PROJECTION 矩阵可以简化为:

[译][译]OpenGL投影矩阵


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Neural Networks for Applied Sciences and Engineering

Neural Networks for Applied Sciences and Engineering

Samarasinghe, Sandhya / CRC Pr I Llc / 2006-9 / $ 118.59

In response to the exponentially increasing need to analyze vast amounts of data, Neural Networks for Applied Sciences and Engineering: From Fundamentals to Complex Pattern Recognition provides scient......一起来看看 《Neural Networks for Applied Sciences and Engineering》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具