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

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

小孔成像
图片到底是怎么形成的?如下图所示:
这里写图片描述
如上图所示,坐标真实的蜡烛,透过红色面板上的点,最终形成一个倒立的蜡烛。我们可以自己做一个图看看,利用相似三角形的原理,即可看到成像的规律。
这里写图片描述
如上图所示,如果投影面与小孔面距离比较近,那么蜡烛投影之后得到了一个比较小的投影结果;如果投影面距离小孔明比较大,那么投影后,发现投影之后,得到了一个比较大的结果。自然,如果是投影面距离小孔面和小孔面距离蜡烛相等,那么投影的结果为等比。

小孔成像与我们的透视有什么关系呢?为什么我们把投影面移动到了摄像机的前面呢?
透视的图如下:
这里写图片描述
如上图所示,左图中,真实的蜡烛,透过小孔得到了倒立的绿色的蜡烛,而红色的蜡烛为绿色的蜡烛的再次倒立就为正确的投影了。而我们的眼睛就是小孔,所以我们可以把右图中的视锥体平移到小孔的右侧,以确保得到正立的投影。

下面我们来讲下什么是透视除法。
我们前面讲过将视锥体中的物体通过相似三角形的知识,把它映射到近平面上去。这个坐标的转换过程如下:
这里写图片描述
上图中,我们视锥体中的P点,经过相似三角形的知识,得到了P’点,我们看到了P’点的x和y坐标分别是-xn/z,以及-yn/z,而z坐标用于是-n。
我们来解释一下,为什么这里有一个负号,因为在opengl中采用的是右手坐标系,而摄像机的整朝向是指向z的负方向的。这里的P点的(x,y,z)都是带有符号的,而n的这个距离是近平面的距离,这里是正值,而又因为我们经常讲摄像机放在原点处,所以近平面的距离应该为-n,而远平面自然是-f了。这样才不会导致,在映射平面上之后,得到一张x和y左右颠倒的图。
ok,到这里,我们解释了为什么把小孔成像中的投影面移到了右侧,以及小孔在透视中就相当于人的眼睛或者是摄像机。那么我们有没有发现,到这里我们已经解决了,透视的变换了。答案为是的。但是也不是的。
所谓的是,其实透视到这里的确结束了,我们仅仅需要的就是相似三角形的知识,把每个点都除以-n就得到了透视这是的平面上的点了。而近平面上的点的z坐标都是-n。
说没有结束,是因为我们这里还要做一个映射。
在讲到映射之前,我们先来看看近平面相当于什么?近平面就是小孔成像中的投影面,你可以把它理解为就是画布或者电影的那个幕布。那么一个幕布是有大小的,这里我们的近平面就是那个幕布,那么近平面也是有大小的,比如我们限定它的大小在x(l,r),以及y(b,t),可以是一个正方形,也可以是一个矩形。
所以上一步中,通过相似三角形变换之后得到的近平面上的点为:
l<=-xn/z<=r
b<=-yn/z<=t
问题到这里,也就加了一个限定的范围而已,似乎和最后的透视矩阵没有半毛钱关系。对的,你的感觉是正确的。到这里的确没有透视矩阵的影子。

接下来就是引入一个设备坐标的知识了。
上面的幕布的大小,可以任意的改变,你可以是一个矩形、可以是正方形,也就是长宽不定。
那么我们这个和我们的屏幕分别率有什么关系呢?比如说我们的幕布大小为800*600,你可以用800*600的像素填充,也可以用1600*1200的像素填充,很显然,用后者填充的更加清晰。所以这就是幕布的尺寸和分辨率大小的区别了。
那么我们的幕布是就是近平面,你可以将近平面设计成任意的宽高比。
到这里我们依然没有引入-1到1的ndc空间,是的,非常牵强,非常困难。

再来回顾一下,我们知道了近平面的大小、知道了近平面的z,就可以通过相似三角形得到视锥体中的点在近平面山的对应坐标。下面的问题是,如何将这个坐标画到屏幕上去,而且要应用到不同的分辨率的屏幕下。

我们可以反推一个东西,这里引入光栅坐标系外文中叫raster space。raster space的坐标系如下所示:
这里写图片描述
右侧的Raster Space和Screen Space有一个明显的区别就是y轴是反着来的。而NDC空间硬生生的设置为了-1到1的范围。之所以有负号,是因为和Canvas Space中的lt、tb的符号相同,因为我们的透视到画布上的点的xy是有正负的。

ok,我们的目标现在明确了,就是左边Canvas Space一路将点映射到Raster Space中去。只有得到了Raster Space中的点的坐标,我们的图像才能最终的显示出来。

首先来补充一个知识,就是映射的知识。
这里写图片描述
直线AB上的任意一点P,都能在-1到1上找到一个对应的点P’。下面我们通过不等式的变换来确定这个点到底是什么表示方式。
l<=-xn/z<=r,这里l一定小于r
两边同时减去l得到:
0<=-xn/z-l<=r-l
两边同时乘以2得到:
0<=2*(-xn/z-l)<=2(r-l)
两边同时减去r-l得到:
-(r-l)<=-2xn/z - (r-l)<=r-l
两边同时除以r-l得到:
-1<=-2xn/z(r-l) - (r+l)/(r-l) <= r-l
到这里,我们把中间的点叫做x’,此x’就是最后映射到-1到1上的点了。
我们写的好看一点,用下图所示:
这里写图片描述
上图中,我们z坐标出现在了分母中,这个不太好写成最后的矩阵形式,为啥呢?因为矩阵通过乘以某些点的坐标x或者y或者z,这种线性的形式,所以我们需要将坟墓中的z去掉,而如果我们将不等式的两边同时乘以z,我们就会得到如下等式:
这里写图片描述
ok,我们看到了新得到x”为-2nx/(r-l) - (r+l)z/(r-l)。
同理,老是同理,我们同样可以得到y”的表示为:
这里写图片描述
我们写成矩阵形式得到:
这里写图片描述
下面,来看看z的映射是怎么回事。我们知道近平面上的点的z都是-n,而到这一步,其他的网址中,一般会这么说,z即深度的映射有别于x和y的映射,z即平截头体中的点的z,在范围-n到-f之间,而我们需要把这其中的z映射到-1到1或者-到1之间,并且这个z与x和y的是无关系的,所以我们需要寻找两个系数,使得其满足:
z”=Az+B
也就是此时,矩阵变乘以向量变为如下形式:
这里写图片描述
然后此时,我们知道当z=-n的时候,-A-B/-n=-1;而当z=-f的时候,-A-B/-f = 1。
此时我们有如下的方程组:
这里写图片描述
将上面得到的A和B代入矩阵,可以得到:
这里写图片描述
我们的矩阵最后写成这样的形式:
这里写图片描述
此时,我们知道,齐次空间的点,其第四维一定为1,所以我们的矩阵:
这里写图片描述

最终我们就得到了透视矩阵的形式为:
这里写图片描述
到这里,我们就一步一步的展示了透视矩阵的推导过程,并且我们知道了,其实透视矩阵乘以点的坐标,其实并没有把点映射到-1到1的范围内,而此时只有在透视除法之后才是映射到了-1到1的空间内,才最终得到了-1到1空间内的点。儿透视除法是什么,是的,是把3D空间的点,投射到近平面的步骤,上面的相似三角形不要忘记了,那里需要一个除以z的步骤的哦,综上,就是透视的基本原理了。

相关文章:

  • opengl从画三角形到画一个立方体(五)
  • ZYNQ. GPIO
  • bzoj 3027 [Ceoi2004]Sweet——生成函数
  • 将光源信息应用到立方体(一)
  • unity包内的内容读取
  • 栈和局部变量操作 将常量压入栈的指令
  • 将光源信息应用到立方体(二)
  • c++总结
  • DNS劫持
  • reflect vector
  • 113007
  • parallax mapping
  • 京东JData算法大赛高潜用户购买意向预测——复现(并没有),提供数据集
  • java 规范
  • 判定你的java应用是否正常(是否内存、线程泄漏)的一个简单方法
  • [译] React v16.8: 含有Hooks的版本
  • 0x05 Python数据分析,Anaconda八斩刀
  • ECMAScript6(0):ES6简明参考手册
  • gops —— Go 程序诊断分析工具
  • HashMap ConcurrentHashMap
  • Hibernate【inverse和cascade属性】知识要点
  • Java编程基础24——递归练习
  • Joomla 2.x, 3.x useful code cheatsheet
  • Object.assign方法不能实现深复制
  • Promise初体验
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Redis 懒删除(lazy free)简史
  • spring学习第二天
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 读懂package.json -- 依赖管理
  • 如何用vue打造一个移动端音乐播放器
  • 如何在GitHub上创建个人博客
  • 昨天1024程序员节,我故意写了个死循环~
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • ​油烟净化器电源安全,保障健康餐饮生活
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (06)Hive——正则表达式
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (推荐)叮当——中文语音对话机器人
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (转)h264中avc和flv数据的解析
  • (转载)(官方)UE4--图像编程----着色器开发
  • (转载)深入super,看Python如何解决钻石继承难题
  • .CSS-hover 的解释
  • .NET NPOI导出Excel详解
  • .net 流——流的类型体系简单介绍
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .NET值类型变量“活”在哪?
  • @Autowired和@Resource装配
  • [.net]官方水晶报表的使用以演示下载