原文:http://blog.csdn.net/wangdingqiaoit/article/details/39010077

OpenGL学习脚印: 投影矩阵的推导

写在前面

本节内容翻译和整理自http://www.songho.ca songho的博客《OpenGL Projection Matrix》内容,以供自己和初学者熟悉投影矩阵推导过程。

通过本节,你可以了解到:

  • 投影矩阵计算的阶段
  • 透视投影和正交投影的矩阵推导

本节的要点就在于:   阅读时,自己拿笔推导一遍。

1.概览

计算机屏幕是2维的,OpenGL渲染的3D场景必须以2D形式的图像投影到屏幕上。GL_PROJECTION 矩阵就是用来设置投影变换的。首先,它将所有顶点从眼坐标(照相机坐标)转换到裁剪坐标系下。然后,这些裁剪坐标通过透视除法,即除以裁剪坐标中w分量,转换到归一化设备坐标系(NDC)。


                                                                                                      一个由视锥裁剪的三角形

因此,我们要记住,裁剪(视锥剔除frustum culling)和NDC转换都集成到了GL_PROJECTION 矩阵。接下来的部分描述了怎么样通过left, right, bottom, top, near and far 这6个界限参数来构造投影矩阵。

注意:

视锥剔除是在裁剪坐标系中进行的,并且恰好在透视除法之前进行。裁剪坐标xc, yc 和 zc 通过与wc比较来进行测试。 如果某个坐标值比Wc小或者比Wc大,那么这个顶点将被丢弃。然后,OpenGL会重新在裁剪进行的地方构造多边形的边缘。

补充内容:

实际上,眼坐标系下坐标在乘以投影矩阵后,裁剪测试和透视除法都是由GPU来执行的。而后面这两个过程处理的裁剪坐标系数据都是由投影矩阵变换的。

1. 裁剪测试也即视锥剔除

-Wc < Xc,Yc,Zc < Wc

2. NDC透视除法

Xn = Xc / Wc  Yn = Yc / Wc   Zn = Zc / Wc

这里需要注意的是,我们在构造16个参数的投影矩阵的同时,不仅要考虑到裁剪,还要考虑到透视除法的过程。这样,最终的NDC坐标才会满足:

-1 < Xn,Yn,Zn < 1

2.透视投影

在透视投影中,在眼坐标下截头椎体(a truncated pyramid frustum)内的3D点被映射到NDC下一个立方体中;x坐标从[l,r]映射到[-1,1],y坐标从[b,t]映射到[-1,1],z坐标从[n,f]映射到[-1,1]。

注意:

眼坐标系使用右手坐标系,而NDC使用左手坐标系。这就是说,眼坐标系下,在原点处的照相机朝着-Z轴看去,但是在NDC中它朝着+Z轴看去。因为glFrustum() 仅接受正的near和far距离,我们在构造GL_PROJECTION 矩阵时,需要取其相反数。眼坐标系和NDC坐标系如下图所示:

在OpenGL中,眼坐标下3D点被投影到近裁剪面(即投影平面)。下图展示了眼坐标系下点(xe, ye, ze) 如何投影到近裁剪面上的 (xp, yp, zp) 的。(左侧是视锥的俯视图,右侧是视锥的侧视图,拿出右手构成右手坐标系,然后比划比划就出来了)

根据三角形的相似性,由俯视图可得出:

由侧视图可以得出:

补充: xp 和yp其实是一个中间值,我们要找的是(Xc, Yc, Zc)和 (Xn, Yn, Zn)之间的关系,但是可以利用:

这一关系做过渡,后面利用xp和yp,映射到NDC中xn和yn的线性关系就利用到了 xp 和yp。这一点很重要。

注意,这里 xp 和yp 都依赖于ze,他们与 -ze成反比。换句话说,他们都被 -ze相除。这个事构造GL_PROJECTION    矩阵最初的线索。在眼坐标通过乘以 GL_PROJECTION    来转换时,裁剪坐标系仍然是一个齐次坐标系。通过对裁剪坐标进行透视除法得到最终的NDC坐标。下图解释了这个过程:

因此我们可以把裁剪坐标系下的w分量设为-ze,那么GL_PROJECTION矩阵第4行变为(0, 0, -1, 0),如下图(求出了投影矩阵第4行):

下现在我们把xp和yp,映射到NDC中xn和yn,他们之间是线性关系: [l, r] ⇒ [-1, 1]和[b, t] ⇒ [-1, 1].

线性关系如下图所示:

则可以推导出:

细节部分有删节,这个推导过程使用的就是简单的y=kx+b线性关系推导,同理利用[b, t] ⇒ [-1, 1]可推得:

将上面的 xp 和yp带入求得:

注意这里Xn和Yn已经是NDC中的坐标了,通过这两个坐标可以求出GL_PROJECTION 的前两行来,书写如下(求出了投影矩阵第1,2,4行):

现在怎么求出第3行呢?

找出zn与找出xnyn不同,因为 ze总是被投影近裁剪面-n上。但是我们需要唯一的Z值进行裁剪和深度测试。另外,我们还能够unproject即反向变换(inverse transform)。因为Z值不依赖于x或者y,因此我们借用w分量来找出 zn 和 ze之间的关系。

因此我们可以这样指定第3行:

在眼坐标下We等于1,因此上式变为:

我们使用(ze, zn)的关系(-n, -1)和 (-f, 1)来求解出系数A,B;

细节部分有删节,使用消元法即可求出:

我们求出了A和B,那么ze和zn关系如下式:

最终的投影矩阵如下式:

这个公式对应的是一般的视锥,如果视锥是对称的,即r = -l ,t= -b,那么有:

z-fighting

在继续之前,我们来看看表示ze和zn关系的式3.这是一个有理函数,并且ze和zn之间不是线性关系。这意味着,在近裁剪面的精度很高,而远裁剪面则很小。如果[-n, -f]范围变得大写,就会引起深度精度问题,即z-fighting。在远裁剪面附近,ze的小变化根本不影响zn值。近裁剪面和远裁剪面之间的n和f举例,应该尽可能小,来减少深度缓存的精度问题。可参考下图来帮助理解。

3.正交投影

构造正交投影的矩阵简单很多。所有的是眼坐标下xe, ye 和ze,都被线性的映射到NDC中。我们需要做的就是讲长方体视景体缩放为规范视见体,然后移动到原点。如下图所示:

以xe和xn之间映射关系为例,[l,r]=>[-1,1],则可以推导如下:

y,z也有类似推导,这里省略,最后得出投影矩阵为:

如果视锥是对称的话,即r = -l ,t= -b的话,则可以简化为:

到这里透视投影和正交投影矩阵推导完毕。

opoengl 投影矩阵的推导相关推荐

  1. 【转】投影矩阵的推导

    [转]投影矩阵的推导 原文:https://www.cnblogs.com/wonderKK/p/5695116.html 博主: 这篇文章写得非常好,对投影矩阵的推导清晰明了,但有个错误:推导的全程 ...

  2. 投影矩阵的推导(Deriving Projection Matrices)

    本文乃<投影矩阵的推导>译文,原文地址为: http://www.codeguru.com/cpp/misc/misc/math/article.php/c10123__1/Derivin ...

  3. 投影矩阵的推导(Deriving Projection Matrices)(转)

    本文乃<投影矩阵的推导>译文,原文地址为: http://www.codeguru.com/cpp/misc/misc/math/article.php/c10123__1/Derivin ...

  4. (转)投影矩阵的推导(Deriving Projection Matrices)

    转自:http://blog.csdn.net/gggg_ggg/article/details/45969499 本文乃<投影矩阵的推导>译文,原文地址为: http://www.cod ...

  5. 向任意平面的投影矩阵的推导

    概述 方法来自于<3D数学基础,图形与游戏开发>这本书. 基本原理 这个方法其实有点思维跳跃,原理是首先推导出一个任意方向n缩放比例为k的缩放矩阵,然后将k变成0,这就变成了向垂直于n的投 ...

  6. 深入理解OpenGL之投影矩阵推导

    深入理解OpenGL之投影矩阵推导 OpenGL流水线中的投影矩阵以及坐标变换 OpenGL中,投影矩阵在Vertex shader中使用,用于变换顶点.一般和Model, View矩阵结合成MVP矩 ...

  7. 投影矩阵之z坐标推导

    看了好几篇关于投影矩阵的文章,在z坐标的推导上,没有提到为什么z'和1/z成线性关系,而是通过结论中的投影矩阵,即已知z'= (zA + B)/w,并且x和x',y和y'关系式中分母都有-z,所以w为 ...

  8. 投影矩阵(投影变换)解惑

    背景 投影矩阵的推导曾经让我困惑了很久,反思可能是自己数学知识的浅薄,所以很多大神写的关于投影矩阵的推导很明晰还是看不懂,好在经过两周的努力学习和思考,终于弄明白了这个问题,特此做一个总结和大家分享一 ...

  9. 3D游戏之投影矩阵算法技术实现

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社 和<Unity3 ...

最新文章

  1. 机翻降重?掩饰抄袭?SCI期刊上的这些「奇言怪语」,不少来自中国作者
  2. 新版 Edge 浏览器或将拥有两个不同的浏览器内核
  3. randaugment
  4. 局域网读取文件_教你windows局域网如何设置共享文件
  5. t3 修改服务器配置,t3如何修改服务器地址
  6. 用国产CH32替代STM32,快来试试看!
  7. 网络安全管理实践(第2版)
  8. java中登陆界面怎么连接到下一个界面啊_JavaWeb登陆成功后跳转到上一个页面
  9. 算法:中国象棋中马的最少步数走法和不重复周游走法的实现(利用图论算法中的BFS和DFS)
  10. 五大主流浏览器及四大内核
  11. 谷歌中国进入后李开复时代:向总部架构靠拢
  12. 【练习八 结构体(强化)编程题4. 看电影】
  13. 用于地址解析的协议是服务器,用于解析域名的协议是什么?
  14. ESP8266_遥控小车网页版
  15. win7java浏览器崩溃_浏览器崩溃怎么办,教你win7系统浏览器崩溃的应对办法
  16. 区块链工程师工资小调查,工资最高的居然是杭州
  17. 【C#基础】数据结构
  18. 全球与中国混合二甲苯市场深度研究分析报告
  19. 《疯狂Java讲义》读书笔记1
  20. 使用 自定义布局 实现灵活的万能遥控器界面

热门文章

  1. Linux上通过SUU更新Dell服务器固件
  2. Nginx for Zabbix 3.2官方监控模板
  3. 详解 TCP/IP 协议
  4. 【Oracle】体系结构
  5. 【PL/SQL】开发程序
  6. SpringBoot-@ControllerAdvice 拦截异常并统一处理
  7. Spring MVC异常处理详解
  8. 模拟存储器管理C语言,操作系统-存储器管理实验C语言.doc
  9. win10 pin码如何设置
  10. websphere mq 查看队列中是否有数据_如果面试官再问你消息队列,就把这篇甩给他!...