上一节中,我们提到了好多的空间,那么本节重点讲述的是透视空间,之前的博文中也讲到透视矩阵的推导、视图矩阵的推导,这些都讲过,但是每次涉及到坐标的变换,这些又是那么的重要,所以经常的捡起来回忆回忆还是很有意思的,每当你用一行代码搞定坐标转换的时候,如果心里感到阵阵的轻松,仿佛里面的细节你都一清二楚,那么这个时候,你才真正的掌握坐标转换。
下面就是参考的网址中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

opengl从画三角形到画一个立方体(三)相关推荐

  1. 前端怎么画三角形_css画出三角形和梯形

    用CSS画三角形 ​ 我们都知道在html中,想要画出圆形,椭圆,矩形,都很简单,但是常见的三角形,梯形如何用纯css画出却较麻烦,许多时候都是直接用三角形的图片.本文将介绍如何用纯css画出三角形和 ...

  2. vue3.0 + typescript openlayers实现地图标点、移动、画线、显示范围、测量长度、测量面积、画三角形、画正方形、画圆、线选、画笔、清除测量、清除、地图上展示弹窗等功能

    vue3.0 + typescript openlayers实现地图标点.移动.画线.显示范围.测量长度.测量面积.画三角形.画正方形.画圆.线选.画笔.清除测量.清除地图所有等功能 由于最近项目中用 ...

  3. Web前端笔记-two.js画三角形及画tip含tip旋转

    程序运行截图如下: 旋转下: 代码如下: import * as Two from "JS/two"; import * as $ from "JS/jquery&quo ...

  4. Android studio 继承view 画笔画圆、画方形、画三角形、画扇形、画椭圆

    MainActivity public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(B ...

  5. OpenGL画三角形

    目录 OpenGL窗口 OpenGL三角形 OpenGL画圆 OpenGL窗口 [代码总览] glfw初始化.配置.创建窗口 glad初始化 渲染循环,检测输入并给窗口涂颜色 清理操作 // 渲染循环 ...

  6. 前端怎么画三角形_用CSS画一个三角形

    作者 | 李银城 三角形的场景很常见,打开一个页面可以看到各种各样的三角形: 由于div一般是四边形,要画个三角形并不是那么直观.你可以贴一张png,但是这种办法有点low,或者是用svg的形式,但是 ...

  7. h5画三角形_如何利用css或html5画出一个三角形?两种不同的制作三角形方法(代码实例)...

    我们在平时的前端开发的时候,有时候是需要一些小图形来丰富一下页面效果,比如:下拉列表的倒三角图形.那么这样的一个三角形是如何制作出来的,本章给大家介绍如何利用css或html画出一个三角形?两种不同的 ...

  8. OpenGL画三角形 圆 五角星 菱形

    不开心,想玩,当家的不许我玩,还说你要玩就玩,那我不管你了,哭哭TAT 用OPenGL原有的画三角形,正方形,点的函数来作图. 画圆是用化曲为直的思想,把圆分为很多分,越分的多越细,越像圆. 画菱形和 ...

  9. css3画一个三角形,css3 画三角形

    /*箭头向上*/ .arrow-up { width:0; height:0; border-left:20px solid transparent; border-right:20px solid ...

最新文章

  1. CUDA 8的混合精度编程
  2. 学习笔记-Redis设计与实现-跳跃表
  3. 工业用微型计算机(19)-指令系统(14)
  4. 深入理解 JVM Class文件格式(八)
  5. centos7.4编译mysql5.6,centos7编译安装mysql5.6
  6. atoi函数_每日一道 LeetCode (50):字符串转换整数 (atoi)
  7. 2023年中国AI论文影响力超越美国?
  8. 补习系列(2)-springboot mime类型处理
  9. HCIE-Security Day13:防火墙双机热备实验(一)防火墙直路部署,上下行连接交换机
  10. RAID (HP)双循环
  11. 14.19 InnoDB and MySQL Replication InnoDB 和MySQL 复制:
  12. archlinux配置Xfce+fcitx5中文输入法
  13. 在VMware16中安装 Win10操作系统
  14. 如何辩证看待技术与业务的关系
  15. git rebase详解(图解+最简单示例,一次就懂)
  16. 脑肠轴必读综述 | 肠道菌群是如何影响人的情绪疾病呢?(一)
  17. 有限元剖网格之Gmsh安装与使用入门
  18. 软件项目管理第一章---项目管理概念
  19. python描述回文素数_回文素数-随心随性无为而为-51CTO博客
  20. 分析函数入门sum...over(partition by xxx order by yyy rows between zzz)

热门文章

  1. linux进入docker容器
  2. 芯片量产测试常用“黑话”
  3. 2018银行数据中心建设及云计算发展论坛
  4. ldap 服务器性能调优,监控OpenLDAP服务器性能指南.pdf
  5. 云服务器搭建mc服务器小记
  6. 刚学完python自动化系列文章,就接了一单任务
  7. css字体溢出省略号处理(3种)
  8. linux递归修改文件权限
  9. Windows下的socket编程
  10. jupyter import包失败