文章目录
前言正射投影透视投影总结前言
在webgl中,三维空间中的所有物体不是会都被绘制出来,只有当它在可视范围内时,才会进行绘制。因为不在可视范围中的物体即使绘制也不会在屏幕上显示。除了水平和垂直范围内的限制,WebGL还限制观察者的可视深度,即"能够看多远"。水平视角、垂直视角、可视深度,三者定义了可视空间。常用的可线空间分为两种:
由正射投影(orthographic projection)产生的长方体状可视空间由透视投影(perspective projection)产生的锥体状可视空间
正射投影
经过正射投影后,场景中的物体大小尺寸都不会改变,即
物体大小与其所在的位置没有关系
,如下图所示:物体投影线与投影面保持垂直
正射投影的可视空间如下。其中前后两个面分别称近裁剪面和远裁剪面,处于可视空间外的物体不会被渲染到屏幕上。
正射投影要做的事情就是将可视空间的坐标转换至 [-1, 1]的立方体空间中
。下面我们来进行正射投影矩阵的推导,假设进行投影转换前坐标为(x,y,z),正射投影转换后坐标为(x‘,y’,z‘),left、right、top、bottom分别简写为l、r、t、b,近裁剪面near和原裁剪面far分别简写为n,f:
x => x’
y => y’
z => z’
由于z方向实际是指向屏幕内的(左手坐标系),因此最终的表达式为z的系数需要乘以-1
将投影矩阵转换为表达式形式:
将:
x’ = 2x / (r-l) - (r+l) / r-ly’ = 2y / (t-b) - (t+b) / t-bz’ = -2z / (f-n) - (f+n) / f-nw’ = 1
代入得正射投影矩阵👇
透视投影
与正射投影不同,透视投影符合人眼的实际效果:物体的形状与物体所处的位置有关,
近处的物体大、远处的东西小
,这样效果赋予了照片深度感,或称透视感。
如下图所示,由于近裁剪面的存在,透视投影实际是一个被裁切了一块的锥体,也就是一个梯状空间。
透视投影变换矩阵分为两步:首先,将锥体空间转换到矩形空间
,这里参考了这篇文章:链接。之后,按照正射投影原则将其投影至[-1,1]的立方空间内
锥体空间 => 长方体空间
现在我们的目的是将锥体空间内坐标为(x,y,z)的 P 投影至由红色近平面构成的
长方体可视空间
中,图中的 P‘ 为在长方体空间中的坐标(x’, y’, z’)
首先考虑 x 和 y坐标:
上图为从x轴方向看向yz平面,很容易由相似三角形得:
也就是说
-代表第三行未知,接下来是关键的一步,按照webgl中齐次坐标
的概念(x,y,z,1)与(kx,ky,kz,k)是等价的
。
将上个式子的右侧增加一项1,则:
转化为矩阵运算的形式就是:
只观察第三行:假设它们系数为a b c d
当P’位于远平面,上式中右侧x y 的系数为 f:ax + by -cf +d = f * f当P’位于近平面(上式):ax + by -cn +d = n * n
可得 a = b = 0, c= n+f, d=nf,推导证明新的z坐标的值与其原x y 坐标没有关系
,梯形空间转向长方体空间的转换矩阵为:
透视投影矩阵
在进行一次正射投影即可得最终的透视矩阵
结果为👇
由于透视投影中没有直接给出top、bottom、left、right,因此需要使用视角α和宽高比aspect表示:
t = n * tan(α/2)b = -tr = n * aspect * tan(α/2)l = -r
最终的正射投影矩阵👇