【计算机图形学】GAMES101学习笔记(1):变换

这个专栏是有关GAMES101:现代计算机图形学入门课程的学习笔记。

课程主页

B站视频

主教材:S. Marschner, P. Shirley, et al., Fundamentals of Computer Graphics, 4th ed. Boca Raton, FL, USA: CRC Press, 2016.

在本专栏的每篇文章开头,将会列出这篇文章对应的GAMES101课程部分和主教材部分,以及主要参考资料,其中主教材(编号为[1])几乎在每篇文章中都会被引用。此外,GAMES101课程的课件也常常被引用(但没有被列出)。本专栏一般不会在文中被引用处注明所引用的资料编号。

因为作者水平有限,错漏之处在所难免,故真诚地欢迎读者提出批评意见和建议。


本篇内容对应GAMES101课程的Lecture 3-4、以及Lecture 5的开头,对应[1]的Chapter 5-7。本篇不整理有关线性代数基础知识(包括向量、矩阵的介绍等)的笔记。如有需要,可参考GAMES101课程的Lecture 2,以及[1]的Chapter 2。

本文主要参考资料:

[1] S. Marschner, P. Shirley, et al., Fundamentals of Computer Graphics, 4th ed. Boca Raton, FL, USA: CRC Press, 2016.

[2] 姚慕生, 吴泉水, 谢启鸿. 高等代数学 (第三版). 上海: 复旦大学出版社, 2014.


2D变换

我们引入齐次坐标(homogeneous coordinate),从而可将\mathbb{R}^2上的旋转(rotation)反射(reflection)缩放(scale)切变(shear)平移(translation)变换(x,y)^{\mathrm{T}}\mapsto (x',y')^{\mathrm{T}}统一写成

\begin{pmatrix} x'\\ y'\\ i \end{pmatrix}=\begin{pmatrix} a &b & t_x\\ c & d &t_y \\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} x\\ y\\ i \end{pmatrix}

的形式。其中,i \in \mathbb{Z}_{\ge0}i=0时表示向量(向量具有平移不变性),i>0时表示点(\frac{x}{i},\frac{y}{i},1)^{\mathrm{T}}。于是,在齐次坐标下,向量+向量=向量,点+向量=点,点-点=向量,而两个点相加得到它们的中点,三个点相加得到以它们为顶点的三角形的重心......等等。

具体来说,之所以要引入第三个维度,是因为平移不是线性变换,它不能写成\boldsymbol{x}\mapsto \boldsymbol{S}\boldsymbol{x}的形式(其中\boldsymbol{S}是二阶矩阵)。

我们以点的变换为例。

(1)绕原点逆时针旋转\theta角:\begin{pmatrix} \mathrm{cos}\theta & -\mathrm{sin}\theta & 0\\ \mathrm{sin}\theta & \mathrm{cos}\theta& 0\\ 0 & 0 & 1 \end{pmatrix}

容易发现这是一个行列式为1的正交矩阵。事实上,所有旋转矩阵都是行列式为1的正交阵,它的转置等于它的逆。例如在这里,绕原点顺时针旋转\theta角就等于该矩阵的逆即转置。

一般地,对于一个正交变换(其矩阵为正交矩阵),如果其行列式为1,则称之为旋转变换;如果其行列式为-1,则称之为反射变换

2D旋转变换的几何意义:我们知道旋转矩阵\boldsymbol{A}=(\boldsymbol{v}_1,\boldsymbol{v}_2)的列向量是\mathbb{R}^2的一组标准正交基,因此,\boldsymbol{A}表示分别将坐标轴\boldsymbol{v}_1\boldsymbol{v}_2旋转至x-轴和y-轴;

事实上,这个几何意义有助于帮助我们认清这样一个事实:旋转都是相对的。把几何对象绕原点旋转等价于将坐标轴按相反的方向旋转相同的角度。这实际上就是视图变换(view/camera transformation)的基本思想。

(2)x坐标变为原来的p倍,y坐标变为原来的q倍:\begin{pmatrix} p & 0 & 0\\ 0 & q&0 \\ 0 & 0& 1 \end{pmatrix}

(3)以x轴为对称轴的反射:\begin{pmatrix} 1 & 0 & 0\\ 0 & -1 &0 \\ 0 & 0& 1 \end{pmatrix};以y轴为对称轴的反射:\begin{pmatrix} -1 & 0 & 0\\ 0 & 1 &0 \\ 0 & 0& 1 \end{pmatrix}

(4)x方向上的切变:\begin{pmatrix} 1 & a & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix};y方向上的切变:\begin{pmatrix} 1 & 0 & 0 \\ a & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix}

(5)平移:\begin{pmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{pmatrix}

变换的合成与分解

对列向量的变换遵循从右向左的运算顺序:变换\boldsymbol{x}'=\boldsymbol{R}\boldsymbol{S}\boldsymbol{x}是先进行变换\boldsymbol{x}\mapsto \boldsymbol{S}\boldsymbol{x},再进行变换\boldsymbol{x}\mapsto \boldsymbol{R}\boldsymbol{x}。因为矩阵乘法不满足交换律,所以变换的顺序很重要。

对于\mathbb{R}^2上的仿射变换

\begin{pmatrix} x'\\ y'\\ i \end{pmatrix}=\begin{pmatrix} a &b & t_x\\ c & d &t_y \\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} x\\ y\\ i \end{pmatrix}

它是先进行线性变换,再进行平移变换:

\begin{pmatrix} a & b & t_x\\ c & d & t_y\\ 0 & 0 & 1 \end{pmatrix}=\begin{pmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} a & b & 0\\ c & d & 0\\ 0 & 0 & 1 \end{pmatrix}

例如,绕点(1,2)逆时针旋转30°,需要先平移回原点、再绕原点逆时针旋转30°、再平移回点(1,2)。变换矩阵为

\begin{pmatrix} 1 & 0 & 1 \\ 0 & 1 & 2\\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} \frac{\sqrt{3}}{2} & -\frac{1}{2} & 0 \\ \frac{1}{2} & \frac{\sqrt{3}}{2} & 0\\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} 1 & 0 & -1 \\ 0 & 1 & -2\\ 0 & 0 & 1 \end{pmatrix}= \begin{pmatrix} \frac{\sqrt{3}}{2} & -\frac{1}{2} & 2-\frac{\sqrt{3}}{2} \\ \frac{1}{2} & \frac{\sqrt{3}}{2} & \frac{3}{2}-\sqrt{3}\\ 0 & 0 & 1 \end{pmatrix}

关于变换的合成与分解,我们有如下定理:

(1)(实对称矩阵的特征值分解)任何一个实对称矩阵\boldsymbol{A}都可以写成如下形式:

\boldsymbol{A}=\boldsymbol{Q}\boldsymbol{D}\boldsymbol{Q}^{\mathrm{T}}

其中,\boldsymbol{Q}是正交矩阵,\boldsymbol{D}是对角阵,对角线上的元素为\boldsymbol{A}的特征值(均为实数)。

因为所有行列式为1的正交矩阵都可以通过对其一个列向量乘以-1使之变为行列式为1的正交矩阵(而\boldsymbol{A}的分解式不变),故几何上看,这说明\mathbb{R}^n上的任何一个“对称”线性变换都可以分解为先进行一个旋转变换,再进行一个缩放变换,最后进行之前那个旋转变换的逆变换;

(2)(实矩阵的奇异值分解)我们在这里只讨论\boldsymbol{A}n阶实方阵的情况,定理的一般陈述可参见任何一本高等代数书,例如[2]。

任何一个n阶实方阵\boldsymbol{A}都可以写成如下形式:

\boldsymbol{A}=\boldsymbol{U}\boldsymbol{S}\boldsymbol{V}^{\mathrm{T}}

其中,\boldsymbol{U}\boldsymbol{V}是正交矩阵(未必相同),\boldsymbol{S}是对角阵,对角线上的元素为\boldsymbol{A}的所有奇异值。

因为所有负奇异值都可以通过该奇异值乘以-1、\boldsymbol{U}(或\boldsymbol{V})对应的奇异向量乘以-1使之变为正数,故我们认为\boldsymbol{A}的所有奇异值,即\boldsymbol{S}对角线上的所有元素,均为非负数。但此时不能再保证\boldsymbol{U}\boldsymbol{V}的行列式均为1。如果不希望\boldsymbol{U}\boldsymbol{V}是反射变换(最多只有一个是反射变换),可以将一个奇异值乘以-1,反射矩阵对应的奇异向量乘以-1,即可将反射变为旋转。当\boldsymbol{A}的所有奇异值均为正数时,几何上看,这说明\mathbb{R}^n上的任何一个可逆线性变换都可以分解为先进行一个旋转变换,再进行一个缩放变换(可能包含了一个坐标轴方向反转,即反射),最后进行另一个旋转变换。

可见奇异值分解是特征值分解的推广:当\boldsymbol{A}是实对称阵且特征值都不是负数时,\boldsymbol{A}的特征值分解和奇异值分解相同。

奇异值的定义:

\boldsymbol{A}m\times n实矩阵,如果存在非负实数\sigma以及n维非零实列向量\boldsymbol{\alpha}m维非零实列向量\boldsymbol{\beta},使

\boldsymbol{A}\boldsymbol{\alpha}=\sigma\boldsymbol{\beta}并且\boldsymbol{A}^{\mathrm{T}}\boldsymbol{\beta}=\sigma\boldsymbol{\alpha}

则称\sigma\boldsymbol{A}奇异值\boldsymbol{\alpha}\boldsymbol{\beta}分别称为\boldsymbol{A}的关于\sigma右奇异向量左奇异向量

在奇异值分解\boldsymbol{A}=\boldsymbol{U}\boldsymbol{S}\boldsymbol{V}^{\mathrm{T}}中,\boldsymbol{U}\boldsymbol{V}的列向量分别是\boldsymbol{A}的关于对应奇异值的左、右奇异向量。

3D变换

这里仅给出有关旋转的部分,其他变换易由2D变换推广得。注意此处的坐标系都是右手系,即满足\boldsymbol{x}\times \boldsymbol{y}=\boldsymbol{z}的空间直角坐标系:

绕x-轴(逆时针,从+x向-x望去)旋转:\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \mathrm{cos}\alpha & -\mathrm{sin}\alpha & 0\\ 0 & \mathrm{sin}\alpha & \mathrm{cos}\alpha & 0\\ 0 & 0 & 0 & 1 \end{pmatrix}

绕y-轴(逆时针,从+y向-y望去)旋转:\begin{pmatrix} \mathrm{cos}\alpha & 0 & \mathrm{sin}\alpha & 0 \\ 0 & 1 & 0& 0\\ -\mathrm{sin}\alpha & 0 & \mathrm{cos}\alpha & 0\\ 0 & 0 & 0 & 1 \end{pmatrix}

绕z-轴(逆时针,从+z向-z望去)旋转:\begin{pmatrix} \mathrm{cos}\alpha & -\mathrm{sin}\alpha & 0 & 0 \\ \mathrm{sin}\alpha & \mathrm{cos}\alpha & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{pmatrix}

注意:这里绕y-轴旋转的部分是\begin{pmatrix} \mathrm{cos}\alpha & \mathrm{sin}\alpha\\ -\mathrm{sin}\alpha & \mathrm{cos}\alpha \end{pmatrix}而非\begin{pmatrix} \mathrm{cos}\alpha & -\mathrm{sin}\alpha\\ \mathrm{sin}\alpha & \mathrm{cos}\alpha \end{pmatrix},这可以从\boldsymbol{x}\times \boldsymbol{y}=\boldsymbol{z}\boldsymbol{y}\times \boldsymbol{z}=\boldsymbol{x}\boldsymbol{z}\times \boldsymbol{x}=\boldsymbol{y}理解。

几何意义:设\boldsymbol{R}_{uvw}=(\boldsymbol{u},\boldsymbol{v},\boldsymbol{w})是一个三阶旋转矩阵,则其列向量构成\mathbb{R}^3的一组标准正交基。我们有

\boldsymbol{R}_{uvw}\boldsymbol{x}=\boldsymbol{u}\boldsymbol{R}_{uvw}\boldsymbol{y}=\boldsymbol{v}\boldsymbol{R}_{uvw}\boldsymbol{z}=\boldsymbol{w}

\boldsymbol{R}_{uvw}把x、y、z-轴分别旋转至u、v、w-轴。则\boldsymbol{R}_{uvw}^{\mathrm{T}}=\boldsymbol{R}_{uvw}^{-1}=\begin{pmatrix} \boldsymbol{u}^{\mathrm{T}}\\\boldsymbol{v}^{\mathrm{T}} \\ \boldsymbol{w}^{\mathrm{T}} \end{pmatrix}把u、v、w-轴分别旋转至x、y、z-轴。

关于3D旋转变换的分解,我们有如下定理:

任何一个3D旋转变换均可分解为绕x-轴、绕y-轴和绕z-轴的旋转变换的合成。即

\boldsymbol{R}_{xyz}(\alpha,\beta,\gamma)=\boldsymbol{R}_x(\alpha)\boldsymbol{R}_y(\beta)\boldsymbol{R}_z(\gamma)

参见百度百科:欧拉角

绕任意过原点的轴(用向量\boldsymbol{n}表示)逆时针(从+n向-n望去)旋转\alpha角,旋转矩阵为

\boldsymbol{R}(\boldsymbol{n},\alpha)=\mathrm{cos}(\alpha) \boldsymbol{I}_3+(1-\mathrm{cos}(\alpha))\boldsymbol{n}\boldsymbol{n}^{\mathrm{T}}+\mathrm{sin}(\alpha) \begin{pmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \end{pmatrix}

显式地写出即

\boldsymbol{R}(\boldsymbol{n},\alpha)\boldsymbol{x}=\mathrm{cos}(\alpha) \boldsymbol{x}+(1-\mathrm{cos}(\alpha))\boldsymbol{n}\boldsymbol{n}^{\mathrm{T}}\boldsymbol{x}+\mathrm{sin}(\alpha) \boldsymbol{n}\times \boldsymbol{x}

对于不绕过原点的轴\overrightarrow{AB}的旋转,可以仿照2D旋转那样,先平移回原点(使A来到O的位置),再绕过原点的轴旋转,最后平移回去(使O来到原来A的位置)。

观测变换

观测变换(viewing transformation)分为视图变换(view/camera transformation)投影变换(projection transformation)视口变换(viewport transformation)。本篇文章主要讲述视图变换和投影变换(有关视口变换的内容见下一篇文章),它们和模型变换model transformation,即对空间中的模型的变换)一起,简称MVP。

视图变换

要想在计算机的屏幕上显示出某个3D场景从某个方向看过去的图像,至少要具备两个要素:(1)模型,即被观察的事物。它们在空间中的位置可以用数学方式描述;(2)相机,即看物体的视角,包括一块用于接受光线的“接收区域”(可认为是相机的“镜头”。注意,“接收区域”跟下一篇中出现的计算机的“屏幕”还有所区别,光打在相机的镜头上但还没显示在计算机的屏幕上。事实上,从接收区域到屏幕的变换即视口变换)。

我们来从数学上定义相机。

相机有三个参数,分别用三个向量表示,这三个向量唯一确定一个相机。它们分别是:

(1)位置(position),使用向量\boldsymbol{e}表示;

(2)视角朝向(look-at/gaze direction),表示相机朝哪里看,使用方向向量\hat{\boldsymbol{g}}表示;

当我们只在意向量的方向、不在意其大小时,我们可以使用模长为1的方向向量表示某个方向。任意一个非零向量可以通过单位化转化为该方向的方向向量:

\hat{\boldsymbol{x}}=\dfrac{\boldsymbol{x}}{|\boldsymbol{x}|}

(3)向上方向(up direction),表示相机接收区域的上方向,总是与视角朝向垂直,使用方向向量\hat{\boldsymbol{t}}表示。

因此,我们可以建立一个以相机所在位置为原点,\hat{\boldsymbol{e}}\hat{\boldsymbol{t}}-\hat{\boldsymbol{g}}(使用-\hat{\boldsymbol{g}}是约定俗成的:我们规定相机总是看向-z方向,见下)为轴的空间直角坐标系,称为相机空间(camera space)。相机的三个参数组成一个右手系,满足\hat{\boldsymbol{e}}\times\hat{\boldsymbol{t}}=-\hat{\boldsymbol{g}}

这里有一个问题:当相机原本就在原点,即\boldsymbol{e}=\mathbf{0}时,我们无法定义\hat{\boldsymbol{e}}。因此,我们统一定义\hat{\boldsymbol{e}}=\hat{\boldsymbol{g}}\times \hat{\boldsymbol{t}}

相应地,各物体(包括相机)原本的所处的空间(由原本的原点和坐标轴建立的空间直角坐标系)被称为世界空间(world space)。要想知道相机能“看到”什么,第一步需要计算处于世界空间的各物体的世界坐标在相机空间中的相机坐标

根据上面的推导,一个重要的观察是:当我们想要知道相机的三个参数发生变化后看到的图像会发生什么变化,我们无需“旋转”相机,而是反方向“旋转”物体,因为二者是等价的。

从世界坐标到相机坐标的坐标变换可以分解为先进行一个平移变换,再进行一个旋转变换。

先考虑平移变换:它将\boldsymbol{e}对应的点平移至原点,对应的矩阵是

\boldsymbol{T}=\begin{pmatrix} 1 & 0 & 0 & -x_e\\ 0 & 1 & 0 & -y_e\\ 0 & 0 & 1 & -z_e\\ 0 & 0 & 0 & 1 \end{pmatrix}

再考虑旋转变换:它将e、t、(-g)-轴分别旋转至x、y、z-轴(即将e、t、g-轴分别旋转至x、y、(-z)-轴),对应的矩阵是

\boldsymbol{R}=\begin{pmatrix} x_{\hat{g} \times \hat{t}} & y_{\hat{g} \times \hat{t}} & z_{\hat{g} \times \hat{t}} & 0 \\ x_{\hat{t}} & y_{\hat{t}} & z_{\hat{t}} & 0 \\ x_{-\hat{g}} & y_{-\hat{g}} & z_{-\hat{g}} & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}

因此,视图变换矩阵\boldsymbol{M}_{view}=\boldsymbol{R}\boldsymbol{T}

投影变换

投影变换是3D至2D的变换,分为正交投影(orthographic projection)透视投影(perspective projection)。其中,透视投影假设相机作为一个点在有限远处,物体发出至相机的光线会聚于相机这一点(这使得平行线看起来相交);正交投影假设相机在无限远处,或者接收区域与物体的距离远小于接收区域与相机的距离,物体发出至相机的光线平行,即垂直(正交)投影到接收区域上。因此,正交投影可认为是透视距离当\frac{d_{object- screen}}{d_{object-camera}}\to 0时的近似。

正交投影

一般地,我们想把空间中的长方体(cuboid)[l,r]\times[b,t]\times[f,n] [这里l代表左,r代表右,b代表底,t代表顶,f代表远,n代表近。需要注意的是因为相机朝向-z方向,而我们假设立方体上每一点z坐标都小于0(这样才能被相机“看到”),故靠近相机的表面的z坐标n反而更大,即f<n<0] 中的物体作正交投影到接收区域(位于xy-平面的某个区域,为方便之后的计算,一般取为[-1,1]^2)上,需要先把[l,r]\times[b,t]\times[f,n]中的点进行坐标变换到标准立方体(canonical cube)[-1,1]^3中,然后再取x、y坐标(当然,你无需在最后将物体的z坐标赋为0,而是保留z坐标,因为其揭示了物体之间的遮挡关系,仍有重要作用。见下一篇文章“深度缓存”一节)。

坐标变换分为两步:

(1)平移变换:把长方体的中心(\frac{r+l}{2},\frac{t+b}{2},\frac{n+f}{2})^{\mathrm{T}}平移到原点,对应的矩阵是

\boldsymbol{T}=\begin{pmatrix} 1 & 0 & 0 & -\frac{r+l}{2}\\ 0 & 1 & 0 & -\frac{t+b}{2}\\ 0 & 0 & 1 & -\frac{n+f}{2}\\ 0 & 0 & 0 & 1 \end{pmatrix}

(2)缩放变换:把长方体的长宽高均缩放为2,对应的矩阵是

\boldsymbol{S}=\begin{pmatrix} \frac{2}{r-l} & 0 & 0 & 0\\ 0 & \frac{2}{t-b} & 0 & 0\\ 0 & 0 & \frac{2}{n-f} & 0\\ 0 & 0 & 0 & 1 \end{pmatrix}

因此,正交投影矩阵

\boldsymbol{M}_{ortho}=\boldsymbol{S}\boldsymbol{T}=\begin{pmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l}\\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b}\\ 0 & 0 & \frac{2}{n-f} & -\frac{n+f}{n-f}\\ 0 & 0 & 0 & 1 \end{pmatrix}

透视投影

透视投影本质上是要把截锥(frustum)内的物体投影到接收区域[-1,1]^2上。设截锥的近表面的x、y坐标范围为[l,r]\times [b,t],z坐标为n;远表面的z坐标为f。

透视投影分为两步:

(1)将截锥变为长方体:将截锥中的点进行坐标变换到的一个长方体中;

(2)正交投影:将长方体中的点作正交投影到[-1,1]^2上。

第二步前面已经讨论过,因此以下只讨论第一步。为方便,我们假设截锥内点的z坐标均乘以-1从而大于0,此时n<f。

我们还假设从截锥到长方体的变换满足如下条件:z=n的点(即在近表面上的点)经变换后坐标保持不变;z=f的点(即在远表面上的点)经变换后z坐标保持不变,仍为f。由此可见长方体为[l,r]\times[b,t]\times[n,f]

首先来看x、y坐标的变换。由相似三角形的关系知x'=\frac{n}{z}xy'=\frac{n}{z}y

但是这样的关系式中,z处于分母的位置,所以关于z不是线性的。我们需要把这个表示化为线性的形式。回忆齐次坐标的定义,我们这样操作:

\begin{pmatrix} x\\ y\\ z\\ 1 \end{pmatrix}\to\begin{pmatrix} \frac{n}{z}x\\ \frac{n}{z}y\\ z'\\ 1 \end{pmatrix}=\begin{pmatrix} nx\\ ny\\ zz'\\ z \end{pmatrix}

于是,我们可以确定变化矩阵的第1、2、4行(注意到变换是线性的,所以变换矩阵本身不包含变量x、y、z):

\boldsymbol{M}_{persp\to ortho}=\begin{pmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ A & B & C & D\\ 0 & 0 & 1 & 0 \end{pmatrix}

其中A、B、C、D是未知数。现在来确定第三行。我们应用之前的假设:

(1)z=n的点经变换后坐标保持不变:\forall \, (x,y,n,1)^{\mathrm{T}}满足(x,y)\in [l,r]\times [b,t]z=z'=n,从而

\begin{pmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ A & B & C & D\\ 0 & 0 & 1 & 0 \end{pmatrix}\begin{pmatrix} x\\ y\\ n\\ 1 \end{pmatrix}=\begin{pmatrix} nx\\ ny\\ Ax+By+Cn+D\\ n \end{pmatrix}=\begin{pmatrix} nx\\ ny\\ n^2\\ n \end{pmatrix}

Ax+By+Cn+D=n^2恒成立。因为x、y是变量,故只能有A=B=0Cn+D=n^2

(2)z=f的点经变换后z坐标保持不变:\forall \, (x,y,f,1)^{\mathrm{T}}在远平面上,z=z'=f,从而

\begin{pmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & C & D\\ 0 & 0 & 1 & 0 \end{pmatrix}\begin{pmatrix} x\\ y\\ f\\ 1 \end{pmatrix}=\begin{pmatrix} nx\\ ny\\ Cf+D\\ 1 \end{pmatrix}=\begin{pmatrix} nx\\ ny\\ f^2\\ f \end{pmatrix}

Cf+D=f^2

联立Cn+D=n^2Cf+D=f^2,得C=n+fD=-nf。故

\boldsymbol{M}_{persp\to ortho}=\begin{pmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{pmatrix}

\begin{pmatrix} x\\ y\\ z\\ 1 \end{pmatrix}\to\begin{pmatrix} nx\\ ny\\ (n+f)z-nf\\ z \end{pmatrix}=\begin{pmatrix} \frac{n}{z}x\\ \frac{n}{z}y\\ n+f-\frac{nf}{z}\\ 1 \end{pmatrix}

从而

\boldsymbol{M}_{persp}=\boldsymbol{M}_{ortho}\boldsymbol{M}_{persp \to ortho}=\begin{pmatrix} \frac{2n}{r-l} & 0 & -\frac{r+l}{r-l} & 0 \\ 0 & \frac{2n}{t-b} & -\frac{t+b}{t-b} & 0 \\ 0 & 0 & \frac{n+f}{n-f} & -\frac{2nf}{n-f} \\ 0 & 0 & 1 & 0 \end{pmatrix}

至此,变换矩阵\boldsymbol{M}_{persp\to ortho}推导完毕。我们来研究这个变换对点的z坐标的影响。首先如果z=n或f,则经变换后z坐标保持不变。如果n<z<f,则

z'-z=n+f-\dfrac{nf}{z}-z=-\dfrac{(z-n)(z-f)}{z}>0

z'>z。因此,这种情况下点经变换后z坐标增大,即向远表面靠近。不过,z'关于z是单调递增的,即若原先z_1>z_2,则变换后仍有z_1'>z_2',也就是说该变换保持遮挡关系不变。同样地,最后无需额外把所有物体的z坐标变为0,而是保留其。见下一篇文章“深度缓存”一节。

本篇文章的最后,我们给出一个表示截锥的简易方法。首先,显然表示一个截锥至少需要近表面和远表面的z坐标n、f。

现在我们不妨假设截锥的中轴(即近表面和远表面中点的连线)位于z轴上(否则只需经过一个平移变换即可将中轴移到z轴上),此时截锥关于z轴对称,从而近表面的顶点x、y坐标满足l=-r、b=-t。易知对于同一个相机视野所形成的锥体(姑且称之为视锥),对任意平面z=z_0z_0<0),它截该锥体所形成的矩形总是相似的,即它的宽除以它的高是一个定值,我们称这个定值为宽高比(aspect ratio)aspect,则有aspect=\frac{width}{height};此外,相机所在位置(原点)与该矩形上下两边的中点连线所形成的夹角(即相机看向这两点的张角)也是定值,我们称之为垂直视野Vertical Field of View,简称fovY)。类似地,还可定义水平视野,二者是相通的。在宽高比确定的情况下,知道其中一者即可知道另一者。

特别地,因为我们知道一个截锥是视锥被近平面z=n和远平面z=f所截的部分(即位于两平面之间的部分),而透视投影把截锥的远表面变得和近表面全等,因此考虑使用近表面的参数描述宽高比和垂直视野。我们有

\mathrm{tan}\dfrac{fovY}{2}=\dfrac{t}{|n|}aspect=\dfrac{r}{t}

于是,我们使用aspect与fovY唯一确定了一个视锥;使用n、f、aspect与fovY唯一确定了一个中轴位于z轴上的截锥。

  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值