3D数学-裁剪空间与透视投影矩阵的推导

透视投影矩阵的变换本质,是将视锥体变换到裁剪空间

视锥体的具有六个面,近裁剪面,远裁剪面,左裁剪面,右裁剪面,上裁剪面,下裁剪面

所有超出视锥体的都会被舍弃,也就是被裁剪,我们之后的操作都是对视锥体内部进行计算

接下来我们来分析并解析,如何推导透视投影矩阵

注意:这里我们对于坐标的矢量使用的是行矢量,如果你使用的是列矢量,那么透视投影矩阵要进行转置

在之前的章节中,我们已经知道了:

将点p投影到z=d的平面上,通过相似三角形的比例关系,可以获得p'

p[x,y,z] --> p'[dx/z,dy/z,d]

我们使用齐次坐标理论去改变它

p'=[dx/z,dy/z,d]=[dx/z,dy/z,dz/z]=[x,y,z]/(z/d)

我们将这个分母放入w,那么四维齐次坐标将会是:[x,y,z,z/d],之后我们要将齐次坐标转化为三维坐标只需要将各个分量除以w即可。

实际上,d值表示焦距,即从投影平面到投影中心的距离,它的值并不重要,我们将其选择为最方便的值:1

投影在平面上的z值我们并不关心,之所以选择使用d=1,主要是原z值对于后续的计算仍然有作用,因此我们要保存它

这样以来,齐次坐标就变为了:[x,y,z,z]

此时,透视投影矩阵是这样的:

[1 0 0 0]
[0 1 0 0]
[0 0 1 1]
[0 0 0 0]

现在,我们考虑裁剪空间的坐标[-1,1],之前我们的计算仅仅考虑到了将点投影在平面上,但是这仍然不够。

因为,实际上,我们希望将视锥体内的坐标,转化为裁剪空间下的坐标,而裁剪空间是什么坐标?

裁剪空间下的坐标,x[-1,1] y[-1,1] z[-1,1],因此,上述的透视投影矩阵还不够全面,不仅如此,我们还需要考虑到x,y的缩放,以及将z的值映射到[-1,1]的范围内。

现在,我们用一些字母参数重新描述透视投影矩阵

[zoomx 0      0 0]
[0     zoomy 0 0]
[0     0     a 1]
[0     0     b 0]

现在我们来解释一下这些字母参数

zoomxzoomy分别表示x轴与y轴的缩放(根据相机的缩放控制),这很容易理解

ab,用于将z值映射到[-1,1]

我们首先计算通过该矩阵变换后的齐次坐标

[x,y,z,1][zoomx 0      0 0] = [zoomx*x,zoomy*y,az+b,z][0   zoomy 0 0][0     0     a 1][0     0     b 0]

变换后的齐次坐标为:[zoomx*x,zoomy*y,az+b,z]

将齐次坐标转化为普通坐标:[zoom*x/z,zoomy*y/z,(az+b)/z,1]

之前我们说明了,我们要将视锥体中的点转换到裁剪空间中。现在先处理z值,将其映射到[-1,1]

我们定义从原点到近裁剪平面的距离为n,从原点到远裁剪平面的距离为f

我们可以列出方程:

(az+b)/z = -1 , z = n
(az+b)/z =  1 , z = f

我们可以求出ab的值

a = (n+f)/(f-n);
b = -2nf/(f-n);

现在我们已经求出第一版的透视投影矩阵了,即

[zoomx 0      0           0]
[0     zoomy 0           0]
[0     0     (n+f)/(f-n) 1]
[0     0     -2nf/(f-n)  0]

我们还没有将xy映射到[-1,1]的范围内

这里我们首先介绍一种数学方法

简单的线性插值

这是在图形学中普遍使用的基本技巧,我们在很多地方都会用到,比如2D位图的放大、缩小,Tweening变换,以及我们即将看到的透视投影变换等等。基本思想是:给一个x属于[a, b],找到y属于[c, d],使得xa的距离比上ab长度所得到的比例,等于yc的距离比上cd长度所得到的比例,用数学表达式描述很容易理解:

(x - a)/(b - a)=(y - c)/(d - c)

这样,从a到b的每一个点都与c到d上的唯一一个点对应。有一个x,就可以求得一个y。

此外,如果x不在[a, b]内,比如x < a或者x > b,则得到的y也是符合y < c或者y > d,比例仍然不变,插值同样适用。

现在我们使用这种方法将xy映射到[-1,1]范围内

我们再次强调我们获得的齐次坐标:[zoomx*x,zoomy*y,az+b,z],我们暂时忽略zoomxzoomy

(x/z - left)/(right - left) = (x' - (-1))/(1- (-1))
(y/z - bottom)/(top - bottom) = (y' - (-1))/(1- (-1))

我们计算出x'y'

x' = (2x / z)/(right - left) - (right + left)/(right - left)
y' = (2y / z)/(top - bottom) - (top + bottom)/(top - bottom)

我们将重新z乘回去,获得齐次坐标下的xy

x' = (2x)/(right - left) - (right + left)/(right - left)*z
y' = (2y)/(top - bottom) - (top + bottom)/(top - bottom)*z

我们将其写到矩阵里,最终我们就可以获得完整的透视投影矩阵了

[(2)/(right - left)  0                     (right + left)/(right - left)           0]
[0                   (2)/(top - bottom)   (top + bottom)/(top - bottom)           0]
[0                   0                    (n+f)/(f-n)                             1]
[0                   0                    -2nf/(f-n)                              0]

我们将上面这个矩阵称为M(这里其实还不完整,记得把zoomxzoomy乘回去)

最终从视锥体变换到裁剪空间的表示式

[x,y,z,1] M = [x',y',az+b,z]

转化为普通三维坐标

[x'/z,y'/z,(az+b)/z,1]

我们在将相机缩放参数加回去,就是完整的裁剪空间坐标

[zoomx*x'/z,zoomy*y'/z,(az+b)/z,1]

当然,在根据不同约定下,ab的值会有所不同,例如在DirectX风格的约定下,z[0,1]那么我们之前的计算就会有所不同,矩阵当然也有所不同。在OpenGL下,由于使用的是列矢量进行计算,因此相对于我们这里的矩阵,要进行转置

我们之前讨论的都是透视投影矩阵,对于正交投影矩阵其实很简单,就是最后一列的变化

[0,0,1,0]–>[0,0,0,1],正交投影矩阵不需要根据距离的大小进行缩放。

屏幕空间

我们已经将视锥体裁剪到裁剪空间下了,那么最后我们需要将裁剪空间投影到屏幕空间,屏幕空间当然是2维空间。

首先就是进行标准化齐次除法,也就是除以w(OpenGL中将此结果称为归一化设备坐标),其实就是将之前的齐次坐标转化为普通三维坐标,我们之前已经做过了。

然后就是缩放xy坐标,以映射到输出窗口上。

输出窗口如下:

裁剪空间的坐标中xy是[-1,1],但是输出窗口的坐标系和这不太一样,他的原点通常位于左上角。

而我们的窗口原点则为[winPosx,winPosy][0,0]则是屏幕的原点,因为我们的窗口并不一定覆盖整个屏幕设备

我们的画面是在窗口中的,也就是图中较小的框框内。

裁剪空间的齐次坐标:[x,y,z,w]

首先进行齐次除法

x' = x/w
y' = y/w

然后我们要将这个坐标映射到我们屏幕中窗口的坐标中

screenx = (x'*winResx)/2+winCenterx
screeny = -(y'*winResy)/2+winCentery

完整的写法

screenx = (x*winResx)/2w+winCenterx
screeny = -(y*winResy)/2w+winCentery

那么我们会有疑问,z有什么用?它被存储在深度缓冲,并用于深度测试。这一点有一定基础的读者应该容易理解。

另外w值也还有作用,在光栅化阶段,还需要用到它。

3D数学-裁剪空间与透视投影矩阵的推导相关推荐

  1. 3D数学之透视投影矩阵的推导

    视锥体 如图,近截面与远截面之间构成的这个四棱台就是视锥体,而透视投影矩阵的任务就是把位于视锥体内的物体的顶点X,Y,Z坐标映射到[-1,1]范围.这就相当于把这个四棱台扭曲变形成一个立方体.这个立方 ...

  2. Unity中的3D数学—02向量与矩阵

    1.向量 1.1 向量的运算 运算 公式 矢量和标量的乘/除法 k v = ( k v x , k v y , k v z ) k\mathbf{v}=(kv_x,kv_y,kv_z) kv=(kvx ...

  3. webgl学习之路(三)——透视投影矩阵的推导过程

    关于透视投影矩阵的讲解,网上有不少教程,但是有一点大家基本上都没有讲清楚:就是z轴坐标(这里的Z轴相当于景深)的推导过程,基本上是一笔带过. 下面先从头开始讲推导过程,再慢慢说Z轴的推导过程. 透视投 ...

  4. 【转载+补充】“最简单的” 相机透视投影矩阵推导与解析

    原文链接 作者:大其心宏其量扩其识 链接:https://www.jianshu.com/p/09fef48e7b0f 来源:简书 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. ...

  5. 透视矩阵的推导(最直观、最深入、最还原,看完请点赞。)

    由参数l,r,b,t,n,f定义的透视投影矩阵的推导困惑了我差不多一个多礼拜,这几天几乎是天天都在思考这个问题,昨天晚上3点多钟我突然醒了,然后我又开始想这个问题,结果终于让我给想通了,于是我赶紧起床 ...

  6. Cesium 透视投影矩阵推导

    一.透视投影 透视投影是3D固定流水线的重要组成部分,是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume)中,待裁剪完毕后进行透视除法的行为.在算 ...

  7. 图形学中透视投影矩阵推导

    透视投影矩阵是图形学一道重要的坎,他是将世界空间转到屏幕空间,再将屏幕放进裁剪空间ndc映射 我们从侧视图看 我们的已知条件 1.aspect:屏幕宽高比 2.n:近截面z轴坐标 3.f :远截面z轴 ...

  8. 【OpenGL】透视投影矩阵推导

    项目场景: 系统:ubuntu glad + glfw + opengl3.3 复习games101MVP变换,在使用OpenGL检验推导透视投影矩阵时,发现得出结果的Z坐标与把不符合目标预期.可以看 ...

  9. 3D数学读书笔记——矩阵基础番外篇之线性变换

    本系列文章由birdlove1987编写.转载请注明出处. 文章链接:http://blog.csdn.net/zhurui_idea/article/details/25102425 前面有一篇文章 ...

最新文章

  1. leetcode-102 二叉树的层次遍历
  2. 在GitHub上管理项目
  3. 关于request取中文字符串变?的解决办法
  4. 构建高可用LVS + keepalived+httpd和双主模型的keepalived方案
  5. oracle rac应急_ORACLE紧急情况检查应急预案
  6. C++经典面试题(最全,面中率最高)
  7. flask项目开发中,遇到http 413错误
  8. linux怎么看是否安装kde桌面,ubuntu 7上安装kde桌面
  9. JSTL标签库中fmt标签,日期,数字的格式化
  10. 理论与实践:如何从Hadoop迁移到MaxCompute
  11. MATLAB学习——矩阵
  12. mysql创建临时表 分页_Mysql 如何创建一张临时表
  13. 全新玖五社区系统整站源码
  14. Arcgis Server 10.4.1 搭建集群环境
  15. python自动化办公 51cto_聊聊 Python 办公自动化之一 Excel
  16. 理想的正方形 HAOI2007(二维RMQ)
  17. 5款Mac极速下载工具推荐和下载
  18. matlab实现图像直方图
  19. 实验五:大数据可视化工具-NodeXL
  20. Roundcube开启用户自助更改密码功能

热门文章

  1. 给移动硬盘分区(一个给mac的时间机器使用,一个用于windows和mac系统之间使用)----记录一次mac系统 用磁盘工具抹掉移动硬盘进度条卡死问题
  2. 写给设计新人的小指导
  3. 图解IFRS9 金融工具(1)总体介绍
  4. Linux虚拟机联网设置详细教程
  5. VMware workstation虚拟机联网的方法
  6. 不要抱怨电脑网速慢,只能怪自己不会调快网速
  7. Jenkins钩子实现代码提交/合并时自动部署
  8. 禁用戴尔inspiron 5447的触摸板
  9. 谈一谈|创新创业训练营结业思考分享
  10. matlab血糖预测,一种基于VMD-PACF-BP模型的动态血糖在线预测方法与流程