原文

OpenGL Projection Matrix

Related Topics: OpenGL Transformation

Updates: The MathML version is available here.

Overview

A computer monitor is a 2D surface. A 3D scene rendered by OpenGL must be projected onto the computer screen as a 2D image. GL_PROJECTION matrix is used for this projection transformation. First, it transforms all vertex data from the eye coordinates to the clip coordinates. Then, these clip coordinates are also transformed to the normalized device coordinates (NDC) by dividing with w component of the clip coordinates.

 
A triangle clipped by frustum

Therefore, we have to keep in mind that both clipping (frustum culling) and NDC transformations are integrated into GL_PROJECTIONmatrix. The following sections describe how to build the projection matrix from 6 parameters; leftrightbottomtopnear and farboundary values.

Note that the frustum culling (clipping) is performed in the clip coordinates, just before dividing by wc. The clip coordinates, xc, ycand zc are tested by comparing with wc. If any clip coordinate is less than -wc, or greater than wc, then the vertex will be discarded. 

Then, OpenGL will reconstruct the edges of the polygon where clipping occurs.

Perspective Projection

 
Perspective Frustum and Normalized Device Coordinates (NDC)

In perspective projection, a 3D point in a truncated pyramid frustum (eye coordinates) is mapped to a cube (NDC); the range of x-coordinate from [l, r] to [-1, 1], the y-coordinate from [b, t] to [-1, 1] and the z-coordinate from [n, f] to [-1, 1].

Note that the eye coordinates are defined in the right-handed coordinate system, but NDC uses the left-handed coordinate system. That is, the camera at the origin is looking along -Z axis in eye space, but it is looking along +Z axis in NDC. Since glFrustum() accepts only positive values of near and far distances, we need to negate them during the construction of GL_PROJECTION matrix.

In OpenGL, a 3D point in eye space is projected onto the near plane (projection plane). The following diagrams show how a point (xe, ye, ze) in eye space is projected to (xp, yp, zp) on the near plane.

 
Top View of Frustum
 
Side View of Frustum

From the top view of the frustum, the x-coordinate of eye space, xe is mapped to xp, which is calculated by using the ratio of similar triangles; 

From the side view of the frustum, yp is also calculated in a similar way; 

Note that both xp and yp depend on ze; they are inversely propotional to -ze. In other words, they are both divided by -ze. It is a very first clue to construct GL_PROJECTION matrix. After the eye coordinates are transformed by multiplying GL_PROJECTION matrix, the clip coordinates are still a homogeneous coordinates. It finally becomes the normalized device coordinates (NDC) by divided by the w-component of the clip coordinates. (See more details on OpenGL Transformation.
 ,  

Therefore, we can set the w-component of the clip coordinates as -ze. And, the 4th of GL_PROJECTION matrix becomes (0, 0, -1, 0). 

Next, we map xp and yp to xn and yn of NDC with linear relationship; [l, r] ⇒ [-1, 1] and [b, t] ⇒ [-1, 1].

 
Mapping from xp to xn

 
Mapping from yp to yn

Then, we substitute xp and yp into the above equations.

 

Note that we make both terms of each equation divisible by -ze for perspective division (xc/wc, yc/wc). And we set wc to -ze earlier, and the terms inside parentheses become xc and yc of the clip coordiantes.

From these equations, we can find the 1st and 2nd rows of GL_PROJECTION matrix. 

Now, we only have the 3rd row of GL_PROJECTION matrix to solve. Finding zn is a little different from others because ze in eye space is always projected to -n on the near plane. But we need unique z value for the clipping and depth test. Plus, we should be able to unproject (inverse transform) it. Since we know z does not depend on x or y value, we borrow w-component to find the relationship between zn and ze. Therefore, we can specify the 3rd row of GL_PROJECTION matrix like this. 

In eye space, we equals to 1. Therefore, the equation becomes; 

To find the coefficients, A and B, we use the (ze, zn) relation; (-n, -1) and (-f, 1), and put them into the above equation. 

To solve the equations for A and B, rewrite eq.(1) for B; 

Substitute eq.(1') to B in eq.(2), then solve for A; 

Put A into eq.(1) to find B

We found A and B. Therefore, the relation between ze and zn becomes; 

Finally, we found all entries of GL_PROJECTION matrix. The complete projection matrix is; 
 
OpenGL Perspective Projection Matrix

This projection matrix is for a general frustum. If the viewing volume is symmetric, which is  and , then it can be simplified as; 

Before we move on, please take a look at the relation between ze and zn, eq.(3) once again. You notice it is a rational function and is non-linear relationship between ze and zn. It means there is very high precision at thenear plane, but very little precision at the far plane. If the range [-n, -f] is getting larger, it causes a depth precision problem (z-fighting); a small change of ze around the far plane does not affect on zn value. The distance between n and f should be short as possible to minimize the depth buffer precision problem.

 
Comparison of Depth Buffer Precisions

Orthographic Projection

 
Orthographic Volume and Normalized Device Coordinates (NDC)

Constructing GL_PROJECTION matrix for orthographic projection is much simpler than perspective mode.

All xe, ye and ze components in eye space are linearly mapped to NDC. We just need to scale a rectangular volume to a cube, then move it to the origin. Let's find out the elements of GL_PROJECTION using linear relationship.

 
Mapping from xe to xn

 
Mapping from ye to yn

 
Mapping from ze to zn

Since w-component is not necessary for orthographic projection, the 4th row of GL_PROJECTION matrix remains as (0, 0, 0, 1). Therefore, the complete GL_PROJECTION matrix for orthographic projection is; 
 
OpenGL Orthographic Projection Matrix

It can be further simplified if the viewing volume is symmetrical,  and 

 
 

<转载> OpenGL Projection Matrix的更多相关文章

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

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

  2. 论文阅读笔记(三)【AAAI2017】:Learning Heterogeneous Dictionary Pair with Feature Projection Matrix for Pedestrian Video Retrieval via Single Query Image

    Introduction (1)IVPR问题: 根据一张图片从视频中识别出行人的方法称为 image to video person re-id(IVPR) 应用: ① 通过嫌犯照片,从视频中识别出嫌 ...

  3. OpenGL Column-Major Matrix 使用注意事项

    这column major的矩阵是彻底把我搞晕了,以后右乘规则下的矩阵应该这么用 假设我想创建一个2x2的矩阵,数学上我这么写: 1 2 3 4 用代码创建的话这么写 // 按照 row major ...

  4. Android平台下OpenGL初步

    Android OpenGL ES 开发教程 从入门到精通 http://blog.csdn.net/zhoudailiang/article/details/50176143 http://blog ...

  5. OpenGl从零开始之坐标变换

    http://www.tuicool.com/articles/uiayYrI OpenGL学习脚印: 坐标变换过程(vertex transformation) http://blog.csdn.n ...

  6. OpenGL一些函数详解(二)

    OpenGL ES顶点数据绘制技巧 在OpenGL中,绘制一个长方体,需要将每个顶点的坐标放在一个数组中.保存坐标时有一些技巧(由于字母下标不好表示,因此将下标表示为单引号,如A1将在后文中表示为A' ...

  7. 【GISER && Painter】Chapter00:OpenGL原理学习笔记

    说明:简单了解一下OpenGL的工作原理,初步认识计算机对于图形渲染的底层设计与实现,第一次接触,也没学过C艹,欢迎各位批评指正. 一  什么是OpenGL? OpenGL是一个开放标准(specif ...

  8. OpenGL(6)——坐标系

    在掌握基本变换后,学习如何变换coordinate space. 对coordinate space进行变换的目的是将local space中各顶点坐标转换成normalized device coo ...

  9. GPU相关资料汇总

    qemu, quick emulator systemc xilinx qemu nvdla, nvidia deep learning accelerator gpgpu-sim ffgpu ope ...

随机推荐

  1. 飞凌OK6410开发板SDIO无线8189WIFI模块驱动移植

    为什么要移植?开发板不是已经提供了无线驱动吗? 貌似是这样的..本来是好用的.加入自己第三方驱动后发现WIFI用不了...最后发现飞凌提供的内核里面没有8189芯片的代码...问售后他们说那边是好的. ...

  2. Mono addin 学习笔记 1

    Mono Addin是一个开源的插件框架,其主要支持的特性如下: The main features of Mono.Addins are: Supports descriptions of add- ...

  3. oracle工作经验(左右连接、decode)

    oracle左右连接:select a.studentno, a.studentname, b.classname from students a, classes b where a.classid ...

  4. postman+newman+jenkins

    1.postman: http://itfish.net/article/59864.html(网上参考资料) 1)安装(要用爬墙软件): 进入下面地址https://chrome.google.co ...

  5. 【SSM 3】Mybatis应用,和Hibernate的区别

    PS:每次写概念性的总结,都是各种复制,各种粘,然后各种理解各种猜.但是这一步的总结,决定了我能够再这条路上走的远近和是否开心.是否创造!so,开启Ctrl A+Ctrl C的模式吧. 接触到这个概念 ...

  6. 链接测试工具xenu link sleuth的使用

    链接测试工具xenu link sleuth的使用很简单. 可以从这里下载 http://home.snafu.de/tilman/xenulink.html 但是注意到: 如果需要登录才能进入所有的 ...

  7. dispay属性的block,inline,inline-block

    转自下面的几位大神: http://www.cnblogs.com/KeithWang/p/3139517.html 总体概念 block和inline这两个概念是简略的说法,完整确切的说应该是 bl ...

  8. PYTHON入门知识

    基本数据类型 注:查看对象相关成员 var,type,dir 一.整数 如: 18.73.84 每一个整数都具备如下功能: class int(object): """ ...

  9. jQuery图片渐变特效的简单实现

    (document).ready(function() {(document).ready(function() {("div.baba").mouseleave(function ...

  10. Linux防火墙

    9.1 认识防火墙   只要能够分析与过滤进出我们管理之网域的封包数据, 就可以称为防火墙. 硬件防火墙 由厂商设计好的主机硬件, 这部硬件防火墙内的操作系统主要以提供封包数据的过滤机制为主,并将其他 ...