文档章节

OpenGL投影矩阵的构造

李勇2
 李勇2
发布于 2015/03/02 09:38
字数 1210
阅读 22
收藏 0
点赞 0
评论 0

参考:

http://www.songho.ca/opengl/gl_projectionmatrix.html


3D空间中的对象,最终显示在屏幕上,需要进行一系列的矩阵变化,将其从世界空间,转化到屏幕上。

坐标的具体转化过程是:


世界坐标world---->视坐标eye-----》不同的投影方法(平行投影,透视投影)投影面上坐标--->正则坐标(将可视体转化成2*2*2的正方体)---->屏幕坐标(像素点)

其中modelView矩阵 将世界坐标转化到eye坐标,  而projection矩阵将视坐标转化到正则坐标, 之后的像素生成不由我们控制。


Opengl使用的矩阵和一般数学中使用的矩阵不同,两者互为转置(transpose), 这有点类似于2维数组存储时行有先还是列优先的问题, 普通是行优先, 而OPENGL采用的是列优先的存储方式。(详细见数据结构---数组---多维数组的存储方式)


有了以上讨论,要构造一个投影矩阵就需要知道:

   采用的投影方法, 如何转化到正则坐标


照相机的坐标系:照相机在原点, 面朝Z负方向, 向上是y轴。


可视体:平行投影中是一个和照相机坐标轴平行的立方体, 由left right bottom top near 和 far 6个值来定义, 其中near表示 近平面距离照相机的位置, far表示远平面距离照相机的距离

下图是一个平行投影的可视体。

1:平行投影

        对于任意在这个可视体中的点,我们需要将其转化到一个正则可视体的坐标系中2*2*2

        即将[left, right]->[-1, 1]  [-near, -far]-->[-1, 1]  [bottom, top]->[-1, 1]

        假设点的eye坐标: xe ye ze we

        则正则坐标  xn yn zn wn


        其中wn 应该是1 表示没有透视效果

        xn = (1-(-1))/(R-L)*(xe-L)+-1

        yn = (1-(-1))/(T-B)*(ye-B) + -1 

        zn = (1-(-1))/(-F-(-n))*(ze-(-n)) + -1

        wn = 1

         

        xn = 2/(R-L)*xe- (R+L)/(R-L)

        yn = 2/(T-B)*ye-(T+B)/(T-B) 

        zn = 2/(N-F)*ze - (-F+-N)/(N-F)

       wn = 1

       通常视坐标中的we = 1

       所以数学上的投影矩阵形式是:

      2/(R-L)       0         0       -(R+L)/(R-L)

      0           2/(T-B)     0       -(T+B)/(T-B)

      0                0     2/(N-F)      (F+N)/(N-F)

      0                0          0                1               

      

2: 透视投影

        透视投影需要首先将视坐标转化到可视体的近面上, 接着再进行正则化。

       

            因此有3钟坐标:

           xe ye ze we  视坐标

           xp yp zp wp 近平面投影坐标

           xc yc zc wc 切割空间坐标

           xn yn zn wn 正则坐标


           因为透视投影有近大远小的特点,需要引入切割空间坐标 用于转化到 正则坐标 xn = xc/wc  yn = yc/wc  zn = zc/wc

            其中wc 和 ze 相关:  wc = -ze  

            而投影矩阵 * 视坐标的结果是 切割空间坐标  即: projectionMatrix * (xe, ye, ze, we) = (xc, yc, zc, wc)

     

第一步:

           缩放x y 方向           

           xp = -n/ze * xe

           yp = -n/ze * ye

第二步 正则化 可视体:          

          设近平面的 范围是 Left  Right Bottom Top

           两个平面的z位置是  [-Near,   -Far]

          所以 [L, R] ->[-1, 1]  [B, T]--->[-1, 1]  [-N, -F]--->[-1, 1]

           类似于平行投影我们得到 xn xp yn yp zn ze 之间的关系,   需要注意zn 是和 ze 之间存在关系, 因为ze范围才是在[-N, -F] 

           xn = 2/(R-L)*xp- (R+L)/(R-L)

           yn = 2/(T-B)*yp-(T+B)/(T-B) 

           zn = zc/wc 

           zc 和 ze 之间的关系不明确, 但是必须是线性关系  即 zc = A*ze + B*xe + C*ye + D*we


计算xn yn 和 xe ye 的关系: 将1/-ze 提出来, 作为wc 坐标缩放因子

           xn = (2/(R-L)*n*xe+(R+L)/(R-L)*ze ) / -ze

           yn = (2/(T-B)*n*ye+(T+B)/(T-B)*ze)/ -ze

           所以

               xc = 2/(R-L)*n*xe+(R+L)/(R-L)*ze 

              yc = 2/(T-B)*n*ye+(T+B)/(T-B)*ze

              wc = -ze

 初步的投影矩阵 xe ye we  xc yc wc 的关系是:                   

            2/(R-L)*n          0               (R+L)/(R-L)       0

            0                  2/(T-B)*n       (T+B)/(T-B)        0

            ?                          ?                       A                B

             0                        0                       -1                0

而ze 和 zc之间存在关系   zc 和 xe, ye 之间是独立的, 所以上面的投影矩阵的第3行前两列为0, 后两列 系数是 A B  

           zn = (Aze + Bwe)/wc = (Aze+B)/ -ze  视坐标的we = 1

           根据[-N, -F] ---> [-1, 1] 的正则关系

           -1 = (A*-N+B)/ N

            1 = (A*-F+B) /  F

           A*-N + B = -N

           A*-F + B = F

          determ = F-N

          A = -(N+F)/(F-N)

          B = -2NF/(F-N)   


          zn = Aze+B/-ze  =  -A + B/-ze = (N+F)/(F-N) - B/ze            zn的值最后将存储在深度缓存中, 取值范围[-1, 1]

         设 F-N = diff           zn = 2N/diff + 1 + 2NF/(diff*ze)

         其中 ze [-N, -F], ze 越靠近 -F 则zn 变化率越小 d(zn)/d(ze) = -2NF/(diff*ze*ze)


所以得到了整个透视投影矩阵:

         求解矩阵采用待定系数法, 已知 坐标轴之间的独立关系, 以及变换后 取值范围的关系, 求解系数。

          

          

 

   

 


                      


           

本文转载自:http://blog.csdn.net/liyong748/article/details/7853785

共有 人打赏支持
李勇2

李勇2

粉丝 45
博文 188
码字总数 62209
作品 0
广州
程序员
图片和图形之应用投影和相机视图(13)

原文 概要 在OpenGL ES环境中,投影和相机视图允许您以更接近您用眼睛看物体的方式显示绘制的对象。这种物理观察的模拟是通过绘制物体坐标的数学变换完成的: 投影 - 此变换根据GLSurfaceVi...

lichong951 ⋅ 05/26 ⋅ 0

计算机图形与OpenGL学习六(二维观察2.OpenGL二维观察函数)

OpenGL二维观察函数 本节概念性内容较多,为便于理解与记忆,可以查看之前文章的实例中的函数操作 1. OpenGL投影模式 在选择OpenGL裁剪窗口和视口之前,必须建立合适的模式以便构建从世界坐标...

lhs322 ⋅ 04/17 ⋅ 0

图片和图形之添加Motion(14)

原文 概要 在屏幕上绘制的对象是OpenGL的一个非常基本的功能,但你可以与其他Android图形framwork类,包括做这个Canvas和 Drawable对象。OpenGL ES提供了附加功能,用于以三维或以其他独特方...

lichong951 ⋅ 05/26 ⋅ 0

图片和图形之用OpenGL ES显示图形(9)

原文 概要 Android框架提供了大量用于创建有吸引力的功能性图形用户界面的标准工具。但是,如果您想要更多地控制应用程序在屏幕上绘制的内容,或者冒险进入三维图形,则需要使用其他工具。A...

lichong951 ⋅ 05/26 ⋅ 0

OpenGL实现物体动画和视频特效

OpenGL实现视频的水印、滤镜?OpenGL实现视频的剪裁、旋转? 2D/3D物体的 旋转,平移,缩放? OpenGL图片滤镜与视频滤镜? 矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合,最早来自于方...

shareus ⋅ 04/24 ⋅ 0

cocos2dx学习笔记之Director(导演类)

在Cocos2d-x中,把统筹游戏大局的类抽象为导演类(Director),Director是整个cocos2d-x引擎的核心,是整个游戏的导航仪。游戏中的一些常用操作就是由Director来控制的,比如OpenGL ES的初始...

AndyZhouX ⋅ 05/08 ⋅ 0

【ARtooklit】坐标系的平移与旋转

在ARToolKit 六个步骤中,步骤四是arGetTransMat函数计算摄像头的转移矩阵,就是为了让摄像头和标识卡之间的坐标相对应,为了让摄像头和标识卡之间有很好的联系。 那么arGetTransMat函数是如...

qq_38643064 ⋅ 05/05 ⋅ 0

【Opengl Android】在安卓上渲染一个obj模型

工具:eclipse 一、获得一个obj文件并分析内容 3D溜溜网 点击打开链接 可以下载到很多模型文件 用3dmax打开 导出外部格式文件obj 即可得到一个obj模型 将格式改为txt 即可看到里面的数据内容...

qq_35263780 ⋅ 04/22 ⋅ 0

图片和图形之构建一个OpenGL ES环境(10)

原文 概要 构建一个OpenGL ES环境 为了在Android应用程序中使用OpenGL ES绘制图形,您必须为它们创建一个视图容器。其中一种更直接的方法是实现a GLSurfaceView和a GLSurfaceView.Renderer。...

lichong951 ⋅ 05/26 ⋅ 0

关于opengl中多重纹理,离屏与渲染到屏幕切换,可编程管线有固定管线切换的理解

最近用opengl写项目时遇见几个问题,感觉比较通用写下啦分享; 一, opengl多重纹理的使用 二, opengl离屏渲染与渲染到屏幕切换使用 三, opengl可编程管线与固定管线切换使用 经过一个成功...

lixiaoguang20 ⋅ 04/23 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Sqoop

1.Sqoop: 《=》 SQL to Hadoop 背景 1)场景:数据在RDBMS中,我们如何使用Hive或者Hadoop来进行数据分析呢? 1) RDBMS ==> Hadoop(广义) 2) Hadoop ==> RDBMS 2)原来可以通过MapReduce I...

GordonNemo ⋅ 45分钟前 ⋅ 0

全量构建和增量构建的区别

1.全量构建每次更新时都需要更新整个数据集,增量构建只对需要更新的时间范围进行更新,所以计算量会较小。 2.全量构建查询时不需要合并不同Segment,增量构建查询时需要合并不同Segment的结...

无精疯 ⋅ 55分钟前 ⋅ 0

如何将S/4HANA系统存储的图片文件用Java程序保存到本地

我在S/4HANA的事务码MM02里为Material维护图片文件作为附件: 通过如下简单的ABAP代码即可将图片文件的二进制内容读取出来: REPORT zgos_api.DATA ls_appl_object TYPE gos_s_obj.DA...

JerryWang_SAP ⋅ 今天 ⋅ 0

云计算的选择悖论如何对待?

导读 人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云...

问题终结者 ⋅ 今天 ⋅ 0

637. Average of Levels in Binary Tree - LeetCode

Question 637. Average of Levels in Binary Tree Solution 思路:定义一个map,层数作为key,value保存每层的元素个数和所有元素的和,遍历这个树,把map里面填值,遍历结束后,再遍历这个map,把每...

yysue ⋅ 今天 ⋅ 0

IDEA配置和使用

版本控制 svn IDEA版本控制工具不能使用 VCS-->Enable Version Control Integration File-->Settings-->Plugins 搜索Subversion,勾选SVN和Git插件 删除.idea文件夹重新生成项目 安装SVN客户......

bithup ⋅ 今天 ⋅ 0

PE格式第三讲扩展,VA,RVA,FA的概念

作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶VA概念 VA (virtual Address) 虚拟地址的意思 ,比如随便打开一个PE,找下它的虚拟地址 这边...

simpower ⋅ 今天 ⋅ 0

180623-SpringBoot之logback配置文件

SpringBoot配置logback 项目的日志配置属于比较常见的case了,之前接触和使用的都是Spring结合xml的方式,引入几个依赖,然后写个 logback.xml 配置文件即可,那么在SpringBoot中可以怎么做?...

小灰灰Blog ⋅ 今天 ⋅ 0

冒泡排序

原理:比较两个相邻的元素,将值大的元素交换至右端。 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第...

人觉非常君 ⋅ 今天 ⋅ 0

Vagrant setup

安装软件 brew cask install virtualboxbrew cask install vagrant 创建project mkdir -p mst/vmcd mst/vmvagrant init hashicorp/precise64vagrant up hashicorp/precise64是一个box......

遥借东风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部