• 概述
  • 透视投影
  • 正交投影

概述

计算机显示器是一个2D平面。OpenGL渲染的3D场景必须以2D图像方式投影到计算机屏幕上。GL_PROJECTION矩阵用于该投影变换。首先,它将所有定点数据从观察坐标转换到裁减坐标。接着,这些裁减坐标通过除以w分量的方式转换到归一化设备坐标(NDC)。

因此,我们需要记住一点:裁减变换(视锥剔除)与NDC变换都保存在GL_PROJECTION矩阵中。下述章节描述如何从6个限定参数(左、右、下、上、近平面、远平面)构建投影矩阵。

注意,视锥剔除(裁减)在裁减坐标上执行,并且在除以wc之前。裁减坐标xc、yc、zc会与wc做比较检测。如果任一坐标小于-wc或大于wc,则该顶点将会抛弃。

接着,OpenGL重新构建那些裁减掉的多边形的边。

 
被视锥裁减的三角形

透视投影

 
OpenGL透视视锥体与NDC

在透视投影中,截棱锥体(观察坐标)中的3D点会被映射到立方体(NDC)中。x坐标的范围从[l,f]到[-1,1],y坐标的范围从[b,t]到[-1,1],z坐标的范围从[n,f]到[-1,1]。

注意,观察坐标为右手坐标系,NDC使用左右坐标系。也就是说,位于原点的照相机在观察坐标中看向-Z轴,而在NDC中看向+Z轴。因为glFrustum()只接收正的近平面与远平面距离值,我们需要在构建GL_PROJECTION矩阵时对他们取反。

OpenGL中,观察空间中的3D点被投影到近平面(投影平面)上。下图展示观察空间中的点(xe,ye,ze)如何投影到近平面上的点(xp,yp,zp)。

 
视锥体的俯视图
 
视锥体的侧视图

从视锥体的俯视图看出,使用相似三角形比率计算方式将观察空间的x坐标xe被映射到xp

从视锥体的侧视图看出,yp也使用相同的方式计算出:

注意,xp与yp二者都依赖于ze,它们与-ze成反比例。也就是说,它们都被-ze除。这是构建GL_PROJECTION矩阵的第一点提示。在观察坐标通过与GL_PROJECTION矩阵相乘变换之后,裁减坐标依旧是其次坐标。它最终通过除以裁减坐标的w分量才变成归一化设备坐标(NDC)。(更详细描述参考OpenGL变换。)

,

因此,我们可以将裁减坐标的w分量设置为-ze。这样,GL_PROJECTION矩阵的第四行变为(0,0,-1,0)。

接着,我们通过线性关系将xp与yp映射到NDC中的xn与yn:[l,r]=>[-1,1],[b,t]=>[-1,1]。


映射xp到xn


映射yp到yn

然后,我们用上面的方程式替换xp与yp

   

注意,我们为透视除法(xc/wc, yc/wc)将每个等式相被-ze整除。前面我们已经将wc设置为-ze,大括号中的项为裁减坐标中xc与yc

从这个等式,我们可以发现GL_PROJECTION矩阵的第一与第二行。

现在,我们仅仅解决GL_PROJECTION矩阵的3行。由于观察空间中的ze总是投影到近平面上的-n点,zn的计算方法与其他坐标的计算方法有稍许不同。不过我们需要唯一的z值来进行裁剪与深度测试。此外,我们也会进行逆投影(逆变换)操作。因为,我们知道z并不依赖于x与y的值,我们借助w分量找寻zn与ze之间的关系。因此,我们可以像这样指定GL_PROJECTION矩阵的第三行:

在观察空间,we等于1。因此,等式变为:

为了计算系数A与B,我们使用(ze,zn)关系式(-n,-1)与(-f,1),且将它们带入到上述等式。

为了求解A与B,重写等式(1):

将等式(1')带入等式(2),然后求解A:

将A带入等式(1)中,求出B:

我们解出A与B。因此ze与zn的关系变为:

最后,我们解出GL_PROJECTION矩阵的所有元素。完整的投影矩阵为:


   OpenGL透视投影矩阵

该投影矩阵为通用截面体。如果视锥体为对称的,即r=-l且t=-b,则矩阵可简化为:

在开始后面讲述之前,请回顾ze与zn之间的关系:等式(3)。你会注意到它是一个有理数方程且ze与zn并非线性关系。也就是说近平面具有非常高的精度,而远平面的精度很低。如果[-n,-f]的范围变得很大,会引起深度精度问题(深度冲突):远平面附近ze的小变化不会影响zn值。为了最小化深度缓存精度问题,n与f的距离应该尽可能小。


深度缓存精度比较

正交投影


正交椎体与归一化设备坐标(NDC)

构造正交投影的GL_PROJECTION矩阵比透视投影模式简单很多。

观察空间的xe、ye与ze分量都线性映射到NDC。我们只需将长方体缩放为正方体,然后移动它到原点。让我们使用线性关系推导出GL_PROJECTION中的所有元素。


映射xe到xn


映射ye到yn


映射ze到zn

因为对于正交投影并不需要w分量,GL_PROJECTION矩阵的第4行依旧为(0,0,0,1)。因此,正交投影完整的GL_PROJECTION矩阵为:


OpenGL正交投影矩阵

如果视锥体是对称的(r=-l且t=-b),它可以进一步简化。

英文原文:http://www.songho.ca/opengl/gl_projectionmatrix.html

OpenGL投影矩阵的更多相关文章

  1. OpenGL投影矩阵【转】

    OpenGL投影矩阵 概述 透视投影 正交投影 概述 计算机显示器是一个2D平面.OpenGL渲染的3D场景必须以2D图像方式投影到计算机屏幕上.GL_PROJECTION矩阵用于该投影变换.首先,它 ...

  2. 关于Opengl投影矩阵

    读 http://www.songho.ca/opengl/gl_projectionmatrix.html 0.投影矩阵的功能: 将眼睛空间中的坐标点 [图A的视椎体]     映射到     一个 ...

  3. 【脚下生根】之深度探索安卓OpenGL投影矩阵

    世界变化真快,前段时间windows开发技术热还在如火如荼,web技术就开始来势汹汹,正当web呈现欣欣向荣之际,安卓小机器人,咬过一口的苹果,winPhone开发平台又如闪电般划破了混沌的web世界 ...

  4. OpenGL投影矩阵(Projection Matrix)构造方法

    (翻译,图片也来自原文) 一.概述 绝大部分计算机的显示器是二维的(a 2D surface).在OpenGL中一个3D场景需要被投影到屏幕上成为一个2D图像(image).这称为投影变换(参见这或这 ...

  5. DX与OpenGL投影矩阵的区别

    之前学习DX和OpenGL时到是知道一点,但是没仔细研究过,只是跟着教程抄个公式就过了,看双API引擎时发现转换时是个问题,必须搞懂,gamedev上找了个解释,希望用得上. https://www. ...

  6. OpenGL中两种计算投影矩阵的函数

    OpenGL无意间同时看到两种创建投影矩阵的写法,可以说它们完成的是同样的功能,但写法完全不同,可以观摩一下什么叫做异曲同工之妙... 第一种: gltMakeShadowMatrix函数是重点 // ...

  7. Android OpenGL ES(六)----进入三维在代码中创建投影矩阵和旋转矩阵

    我们如今准备好在代码中加入透视投影了. Android的Matrix类为它准备了两个方法------frustumM()和perspectiveM(). 不幸的是.frustumM()的个缺陷,它会影 ...

  8. [OpenGL](翻译+补充)投影矩阵的推导

    1.简介 基本是翻译和补充 http://www.songho.ca/opengl/gl_projectionmatrix.html 计算机显示器是一个2D的平面,一个3D的场景要被OpenGL渲染必 ...

  9. OpenGL中投影矩阵的推导

    本文主要是对红宝书(第八版)第五章中给出的透视投影矩阵和正交投影矩阵做一个简单推导.投影矩阵的目的是:原始点P(x,y,z)对应后投影点P'(x',y',z')满足x',y',z'∈[-1,1]. 一 ...

随机推荐

  1. css cursor 的可选值(鼠标的各种样式)

    crosshair; 十字准心 The cursor render as a crosshair游标表现为十字准线 cursor: pointer; cursor: hand;写两个是为了照顾IE5, ...

  2. linux(centos)下挂载nefs文件系统

    有时候,在将硬盘插到Linux系统上,挂载硬盘时一直提示:unknown filesystem type 'ntfs'.在尝试网上的方法也遇到了一些问题. 这是有的 linux 发行版并不默认支持挂载 ...

  3. 遗传算法的C语言实现(一):以非线性函数求极值为例

    以前搞数学建模的时候,研究过(其实也不算是研究,只是大概了解)一些人工智能算法,比如前面已经说过的粒子群算法(PSO),还有著名的遗传算法(GA),模拟退火算法(SA),蚁群算法(ACA)等.当时懂得 ...

  4. MySQL数据库7 - 汇总和分组数据

    一 汇总和分组数据 查询语句 ---> 结果集(多条数据) ---> 聚合函数  ----> 单行记录 1.常用的聚合函数: sum()         数字             ...

  5. join()方法之我见

    JavaScript join() 方法 定义和用法 join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 语法 arrayObject.join(separa ...

  6. Errore Http 404.2

    问题一:IIS 7.5 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理 404.2就一个http status code, 在msdn上说:404.2 - ISAPI or CGI rest ...

  7. The first day to learn Englisht

    IF you want to go fast,to alone. IF you want to go far,go with others.

  8. 关于BT网络的一些改进

    这几天一直在研究如何改进现有的BT网络的效率,现在有了一点小小的成果 大概思路是这样的,对于一些已经拓扑结构以及节点之间延迟的网络(并不算太苛刻,对于例如数据中心的网络来说,是可以实现的), 普通的B ...

  9. html中meta的介绍

    前言 meta是html语言head区的一个辅助性标签.也许你认为这些代码可有可无.其实如果你能够用好meta标签,会给你带来意想不到的效果,meta标签的作用有:搜索引擎优化(SEO),定义页面使用 ...

  10. jQuery学习总结

    1:jQuery是什么 jQuery是继prototype之后又一个优秀的Javascript框架.它是轻量级的js库,兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, O ...