7.1 观察变换(Viewing Transformations)
观察变换是指将 3D 的物体映射到 2D 的过程。这是一个复杂的过程,我们将他拆解成几个过程:
- 摄像机变换(camera transformation)或者 眼睛变换(eye transformation):在场景内的物体摆放好之后,将摄像机拜访到场景的原点,这是一个刚体变换,只跟旋转和平移有关,不会产生形变或者缩放。过程完成后为 相机空间(camera space)。
-
投影变换(projection transformation):将相机视野映射到
的立方体中。叫做 规则观察体(canonical view volume) 或者 标准视景体(我就叫它 标准视图体积 了),也有的将过程完成后的空间叫做 裁剪空间(clip space) 或者 标准化设备坐标(normalized device coordinates)。
-
视口变换(viewport transformation) 或者 窗口变换(windowing transformation):将上面的立方体映射到屏幕像素空间。过程结束之后叫做 屏幕空间(screen space) 或者 像素坐标(pixel coordinates)。
(注意:有的 API 的 Viewing Transformations 只是单纯指这里的 camera transformation)
先从视口变换开始讲起,比如现在物体都已经在裁剪空间了,如下图(右手系),我们需要将 映射到屏幕最左边,将
映射到屏幕最右侧,将
映射到屏幕的最底部,将
映射到屏幕的最顶部。也就是从上往下看,顺着
的方向。

我们约定屏幕空间坐标:

所以假设我们的屏幕有


正交视图体积(orthographic view volume)跟标准标准视图体积类似,但它不是 ,而是
,如图:

字母代表的意思和所在轴如下所示:

我们观察的时候,其实是顺着

将正交视图体积变成标准视图体积的矩阵如下:

推导过程如图(上面的

所以要将正交视图体积中的点映射屏幕上,整个过程就是:

汇编代码为:

介绍完了视口变化,正交投影变换(其实还有透视投影变换,后面会说),再前面就是摄像机变换。下图中 是一组正交基,我们的眼睛(摄像机)在
的位置,看向
的方向,
是我们头顶的方向。

通过

如下图所示,我们的目标就是把物体都转换到

现在我们需要把

在这里写成:

我写一下完整过程:

总之

代码跟上面差不多,多乘了一个。

7.2 投影变换(Projective Transformations)
如图所示,相机的观测点还是在 点,目光像
看去,
是
应该在屏幕上的长度,用相似三角形可以得到
,这里有一个乘法,所以我们不能够像上面一样再多乘一个矩阵来保持算法不变,就完成投影变换。

回顾一下,没有其次坐标之前,我们可以完成这样的计算:

再引进其次坐标之后,多了平移,可以加上一个常数:

现在我们可以再进一步,把齐次坐标的最下面一行充分利用起来,让它不再一直是

但是这样有一个限制,也就是对于每个分量,他们的分母都是相同的:

实现这种变换的矩阵写成这样:

当我们需要在笛卡尔坐标系中运用到变换后的点的时候,将

这个过程就叫做 投影变换(projective transformation) 或者 单应性矩阵(homography)。
举个例子,这个矩阵

把下图的标准矩阵进行了透视投影。

对于

再将其

~ 代表 相等 的意思,也就是说

下面是一个二维的齐次坐标,

这样我们就可以进行任意次变换,而不用担心 的值,甚至在某一瞬间
也是可以的,我们只需要在真正需要读出这个点的值的时候才将每个分量除
就可以了。
7.3 透视投影(Perspective Projection)

还是看这个图,里面的

因为对于齐次坐标来说,同时乘常量没有关系,所以 ~ 两边的坐标我们看成是相等的,能够看出是满足

上述矩阵对视椎体的作用如下面两个图所示,保证了在


的逆矩阵是:

当然我们也可以让它的形式变得好看一点:

当把透视投影变成正交投影的样子之后就可以用正交投影的矩阵来完成后面的操作了:

其中

透视投影的整个观察变换代码如下:


除了多乘了一个矩阵之外,还要除
在 OpenGL 中,透视投影矩阵写法跟我们差不多:

还有一些地方,会把
7.5 视场角(FOV)

有时候我们会觉得

如果像素是正方形的,并且分辨率是定的,那么

最后有一个视场角的概念,可以看图,公式如下:

所以只需要屏幕分辨率、视场角、
网友评论