顶点数据经过模型变换、相机变换转换到观察空间,之后渲染系统引入视椎体的概念,并通过投影变换将视椎体转换到统一设备坐标系中,方便剪裁和后续窗口映射工作。
投影变换其实就是将不同对的视锥体映射到标准设备坐标的过程,投影变换过程中实际上并未实际计算顶点的NDC坐标,而是在后面齐次除法中进行,不过投影变换的整个过程与之息息相关,应该说是作为一个目标。
1 视锥体
一般而言,常用的视锥体有两种, 如下图所示。视锥体一般由6个剪裁平面决定,包括近剪裁面和远剪裁面
2 统一设备坐标系 NDC
可以理解为一个立方体,中心点在中间,x,y,z
方向的范围[−1,1](OpenGL中,在有些文档中描述为CVV,傻傻的分不清楚了,但是表达的意思是相同的),注意的是不同的API定义的NDC不尽相同,DirectX定义z范围为[0,1],本文主要使用OpenGl的NDC坐标范围,不过整个推导过程相同。
3 设定
- 转换过程推导以OpenGl为准,也就是采用右手坐标系,观察方向位沿Z轴负方向
-
涉及的符号为不带符号数,比如下文中近邻面z
4.平行投影
设观察空间中,视椎体的为[l,r]×[b,t]×[f,n]
,其中l<randb<tandf<n平行视椎体 和NDC都是立方体,所以可以通过平移T(t)和缩放S(s) 实现 , 其过程如下图所示
T(t)将视椎体中心移动到坐标系中心,平移矩阵如下:
S(s) 将平移后视椎体的(x,y,z)转换到[−1,1]区间,
所以转换矩阵
5.透视投影
透视投影的特征就是投影线都会经过视点,也就是摄像机中心,一般在计算中会将视椎体的近平面z=n
作为成像平面。投影矩阵可以直接通过投影关系以及视锥体和NDC区间的关系建立方程求教获得,可以参考Mathematics for 3D Game Programming and Computer Graphics 第五章 。不过这里采用另外一种方式,先将透视投影的视椎体转换为平面投影的视椎体,然后再利用平行投影的视椎体获得透视投影矩阵。
5.1 透视关系
假设空间中一点的坐标为P(px,py,pz)
5.2 深度关系
上述过程可以实现将空间中点转换到2D图像中,但点q(qx,qy,n)
的z 保持为n , 实际上z 应该保持[n,f]的区间,另一方面在光栅化过程中对1z进行插值,所以z的变换函数应该是1z的线性函数,假设z的变换函数为
http://www.kanxia.org/info/3393.html
由z
的区间映射关系[n,f]→[n,f]以得:计算可得:
也就是说转换函数为
5.3 透视视锥体转换到平行视锥体
通过上面的推导,透视投影视椎体转换为平行投影视椎体的过程可以表达为:
用齐次坐标表达以及转换过程:
结合平行投影转换矩阵,获得透视投影转换矩阵:
即:
总结
上文即笔者总结的透视变换的数学推导过程,毕业后第一次写这样的文章,无非是想把这个过程完全理清楚是怎么回事。之前看的时候感觉没什么问题啊,但是在写的时候还是遇到一些问题,比如:
- Canonical view volume(CVV) 与 Normalized device Coordinaate(NDC)的关系,参考了几本书中的描述,其实都有点混淆,包括RTR中也会同时出现这两个概念,不过最终还是没弄明白怎么个区分方法,暂且当做一个概念吧
- z
- 投影前后的计算公式,好几本书都是直接给出结论的,最后还是在Mathematics for 3D Game Programming and Computer Graphics中找到具体的流程,也可以参考另外一篇PPT
总之,本文会有很多描述不清晰或者弄错的地方,遇到的请帮忙指教。
1万+

被折叠的 条评论
为什么被折叠?



