当前位置: 首页 > news >正文

opengl从画三角形到画一个立方体(三)

上一节中,我们提到了好多的空间,那么本节重点讲述的是透视空间,之前的博文中也讲到透视矩阵的推导、视图矩阵的推导,这些都讲过,但是每次涉及到坐标的变换,这些又是那么的重要,所以经常的捡起来回忆回忆还是很有意思的,每当你用一行代码搞定坐标转换的时候,如果心里感到阵阵的轻松,仿佛里面的细节你都一清二楚,那么这个时候,你才真正的掌握坐标转换。
下面就是参考的网址中http://www.songho.ca/opengl/gl_projectionmatrix.html
透视矩阵的的推导,其实之前的博文中看到的是另外一个网址的推导过程,本次是参考上面的网址,那么还有很多的书籍,我们之后也会一一给出,但大体的推导步骤都是一样的,只不过本人有个懒惰的习惯,先看看所有的其他人是怎么推导的,再总结一套简单通俗而易懂的理论给大家,这也算是知所有人,而成自己一家之言的习惯了。

上面的网址中,上来解答了我的一个疑惑,当然这也需要读者了解mvp的每个步骤之后得到的是什么空间的坐标,才能懂得这个疑惑。
文中说透视矩阵是用来做透视变换的,那为什么又要做透视变换呢?因为3D的场景必须映射到2D的空间上,因为我们的显示器是2D的呀,综上,由于我们的屏幕是2D的,所以我们要将现实中的物体映射到2D的上才能展示出来。那么怎么转换呢?这就是透视矩阵的作用了。
我们知道MVP中,M矩阵之后得到的世界空间的坐标;V之后就得到了视图空间中的坐标了。那么P之后,得到是什么,是什么?答案是NDC空间中的坐标。
我们再次说明一下,NDC的N是normalized device coordinate. 即是规格化的设备空间坐标。所谓的规格化,就是一个x/y/z是-1到1,或者0到1,这种空间中的坐标,这个根设备有关系。反正就是最多是-1到1空间中的坐标。

接下来在说一下,裁剪区域,我们知道人类的眼睛也是有一个看到范围的限制的,那么在opengl中也是有一个区域是来作此限制的,这个区域叫做视锥体,当然正交投影后面再说。所谓的视锥体,是一个削掉尖头的椎体,我们叫做平截头体,如下图所示:
这里写图片描述

我们看到上面的三角形,以及额外添加的两条红线,那么这个梯形就是所谓的平截头体了。图中还告诉我们短红线是近平面、长红线是远平面、在平截头体外的区域都是不能被看到的。所以到这里你可以清楚的知道了,这个平截头体就是裁剪区域了。

文中还告诉我们,什么是被裁剪,也就是什么时候将超过区域外的点丢弃掉。在做透视除法之前,如果我们发现有的坐标是超过了-Wc到Wc之外的点都丢弃。

那么这里的透视除法又是什么鬼。Wc又是什么玩意。。。

总的来说,我们是把平截头体中的点映射到一个标准的立方体盒子中去。如下图所示:
这里写图片描述
那么如何把平截头体中的点映射到立方体中去呢?首先要把平截头体中的任意一个点映射到平截头体的近平面上去。

这里要注意一下上面两张图中的坐标系。左图是右手坐标系,而右图是左手坐标系。所以平截头体的近平面是-n到-f。
我们画一个自己的图,我觉得非常的清除。
这里写图片描述
上图中两个绿色的三角形是相似的。下面我们就来看看平截头体中的点(x,y,z)映射到近平面上之后的坐标是多少。
已知道OC’ = -n;OC = z;
三角形OB’C’相似于三角形OBC
OC’/OC = B’C’/BC,这里的BC就是点A的x轴坐标,即时x
-n/z = B’C’/x
这样就得到:B’C’ = -nx/z
同样的三角形OB’A’相似于三角形OBA
A’B’/AB = OB’/OB = OC’/OC
AB即是A点y轴。
所以:
A’B’/y = -n/z
所以A’B’ = -ny/z
所以有:
x’ = -nx/z
y’ = -ny/z
z’ = -n
也就是说,平截头体中的任意一点,最终通过相似三角形,映射到了近平面上的点即为(x’,y’,z’)。其中z’始终为-n,这个毫无悬念。然后此时得到的点的坐标叫什么呢?到这里我们会遇到这样的问题,裁剪空间、NDC空间、还有什么CVV空间。
首先给个全称:
CVV——Canonical View Volume, 规则观察体。
NDC——normalized device coordinates,规范化设备坐标。
Clip Space——裁剪空间。
走访各个博客,最终还是区分出这几个术语的不同。
CVV和NDC:规则观察体,无论是正交投影还是透视投影,最终我们都会将立方体(正交投影)或平截头体(透视投影)中的点,映射到一个立方体内(这个立方体的的x从-1到1,y从-1到1,而z可能是-1到1,也可以是0到1)。这个CVV也就是NDC空间。我们经常混淆的是CVV中的C,它不是clip的意思,而是canonical的意思。
Clip Space:并不是NDC空间,我们可以参考网址:
http://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrix-GPU-rendering-pipeline-clipping
中的这张图:
这里写图片描述
具体的还是要读者自己去看看这个网址中的教程,讲得非常好。在将摄像机坐标系中的点通过透视矩阵变换之后得到的点到底是什么?搞清楚这个就可以明确裁剪空间和NDC空间的区别了。答案是,得到的点是没有经过透视除法的点的,而是一个齐次坐标坐标空间的点,那么裁剪空间又是什么鬼呢?由图可见我们将得到的点,-Wc和Wc进行比较如果不在这个范围之内的就直接去除掉了,所以这就是裁剪。而不是等到透视除法(除以Wc)才去判断点的范围是否则-1到1。说到这里,我们就知道了裁剪空间是在NDC空间之前的一个空间,而且NDC空间是在透视除法之后得到的空间。NDC空间又是一个标准的立方体(x从-1到1,y从-1到1,z从-1到1,或者z从0到1)。标准的立方体又叫什么呢?对的,Canonical View Volume。
接着,我们这样问一个问题,为什么要映射到一个CVV立方体呢?或者NDC空间呢?答案是为了方便裁剪。而裁剪并不是一定要在CVV或者NDC判断,上面的介绍说过了,可以在透视矩阵作用后,不做透视除法就可以进行裁剪了。但总的来说,我们的点从平截头体中的映射到立方体呢?(透视矩阵之后,虽然还没有透视除法,但是依然是一个立方体),而立方体是很容易进行裁剪的,裁剪的线的算法可以参考:Cohen-Sutherland algorithm而裁剪多边形的算法可以参考Sutherland-Hodgman algorithm这两个算法以后我再去讲解。
裁剪空间可以参考网址:https://en.wikipedia.org/wiki/Clip_coordinates

到这里之后我们再去推导透视矩阵是怎么炼成的?为什么会有透视除法?
之前的那个图,我们再次给出:
这里写图片描述
黄色面,在scratchpixel网址(上面的学习网址)中叫做图片平面image plane. 平截头体中的任意一点,最终都会被映射到这个2D的平面上去。上面的已经分析了,通过三角形的相似,可以得到点A(x,y,z)映射到黄色平面上之后得到了A’(-nx/z,-ny/z,-n)。问题好像到这里已经能够告诉计算机去画一个3D的东西了,因为我们已经将3D的点映射到了2D的平面上了。但是我们有没有考虑裁剪呢?我们并没有考虑裁剪呀,那么考虑裁剪的话,是在这个平截头体中做的方便呢,还是在上面说的在立方体中做的方便呢?已经说过了,在立方体中做的方便。

为什么需要ndc空间?
当找寻这个知识点的时候,无意中发现了这个网址http://www.scratchapixel.com/ 写的真的是很好呀,非常的细致,解答了很多之前的疑惑。后面我们还会认真的研读这个网址所写的东西。现在呢?我还是真对目前所了解的继续写博客,后面随着认识的提高,会勘误之前出现的错误。
ndc空间是设备空间,不同的显示器会有不同的显示方式,那么我们不希望我们的程序真对不同的设备就不能正确运行了,所以做一次抽象。只有抽象出一个普适的坐标才能屏蔽各个设备的不同。

下面就来说一下什么是设备坐标、光栅空间坐标、分辨率、电影底片的分辨率,见下一节。只有明白这些概念,才能彻底的了解透视矩阵的推导。

http://www.66acg.com/?post=522
http://blog.csdn.net/popy007/article/details/1797121
http://blog.csdn.net/n5/article/details/9734905
http://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrix-GPU-rendering-pipeline-clipping
http://www.lxway.com/65981822.htm
http://blog.csdn.net/llwszjj/article/details/24842189
http://www.cnblogs.com/ojo-blogs/p/6754664.html
https://www.tomdalling.com/blog/modern-opengl/explaining-homogenous-coordinates-and-projective-geometry/

齐次坐标:
http://www.songho.ca/math/homogeneous/homogeneous.html

http://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/projection-stage

相关文章:

  • es
  • opengl从画三角形到画一个立方体(四)
  • opengl从画三角形到画一个立方体(五)
  • ZYNQ. GPIO
  • bzoj 3027 [Ceoi2004]Sweet——生成函数
  • 将光源信息应用到立方体(一)
  • unity包内的内容读取
  • 栈和局部变量操作 将常量压入栈的指令
  • 将光源信息应用到立方体(二)
  • c++总结
  • DNS劫持
  • reflect vector
  • 113007
  • parallax mapping
  • 京东JData算法大赛高潜用户购买意向预测——复现(并没有),提供数据集
  • hexo+github搭建个人博客
  • [译]Python中的类属性与实例属性的区别
  • Android 架构优化~MVP 架构改造
  • js中forEach回调同异步问题
  • maya建模与骨骼动画快速实现人工鱼
  • Protobuf3语言指南
  • quasar-framework cnodejs社区
  • session共享问题解决方案
  • spring boot 整合mybatis 无法输出sql的问题
  • vue2.0项目引入element-ui
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • windows下mongoDB的环境配置
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 给github项目添加CI badge
  • 面试总结JavaScript篇
  • 如何合理的规划jvm性能调优
  • 微服务入门【系列视频课程】
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • $(function(){})与(function($){....})(jQuery)的区别
  • (13):Silverlight 2 数据与通信之WebRequest
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (Matlab)使用竞争神经网络实现数据聚类
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (二开)Flink 修改源码拓展 SQL 语法
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (一)Linux+Windows下安装ffmpeg
  • (一)认识微服务
  • (转)ABI是什么
  • .Net IOC框架入门之一 Unity
  • .NET Remoting学习笔记(三)信道
  • .net(C#)中String.Format如何使用
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [APIO2015]巴厘岛的雕塑
  • [BUG] Authentication Error
  • [BZOJ2208][Jsoi2010]连通数
  • [CSS] 点击事件触发的动画
  • [GXYCTF2019]禁止套娃
  • [HNOI2006]鬼谷子的钱袋