跳到正文
Carol's Blog
返回

计算机图形学-变换

概述

用来记录计算机图形学中关于变换的相关知识,内容并不详尽,只记录了我认为比较重要的内容。

齐次坐标与仿射变换

对二维空间中的向量(x,y)(x, y) 加入第三维的值 ww,即可表示齐次坐标(需要归一化,同除以ww):

可以满足以下的操作:

用齐次坐标表示二维仿射变换

仿射变换 = 线性变换(缩放/镜像/旋转等) + 平移(非线性变换)

(xy1)=(abtxcdty001)(xy1) \begin{pmatrix} x^\prime \\ y^\prime \\ 1 \end{pmatrix} = \begin{pmatrix} a & b & t_x \\ c & d & t_y \\ 0 & 0 & 1 \end{pmatrix} \cdot \begin{pmatrix} x \\ y \\ 1 \end{pmatrix}

表示先进行线性变换,再平移

其中三种重要的变换为:

变换的组合

先平移后旋转:

先旋转后平移:

因为矩阵乘法不满足交换律,多种变换组合起来时从右向左运算

因为矩阵满足结合律,n个变换矩阵可以先做乘法,最后组合起来时维数不变。

变换的分解

因为旋转矩阵默认绕原点旋转,如果我们需要表示一个绕任意点旋转的变换,则需要用到矩阵的分解。

表示为:

T(c)R(α)T(c)T(c) \cdot R(\alpha) \cdot T(-c)

三维变换中的旋转

沿三个坐标轴旋转:

需要注意的是Ry(α)R_y(\alpha)sinα\sin \alpha的正负比较特殊,是因为在右手坐标系下,Z轴 ×\times X轴 = Y轴,而不是X轴 ×\times Z轴。

对于任意三维旋转,使用欧拉角来表示:

Rxyz(α,β,γ)=Rx(α)Ry(β)Rz(γ)R_{xyz}(\alpha, \beta, \gamma) = R_x(\alpha)R_y(\beta)R_z(\gamma)

对应的角度分别叫做:roll,pitch,yaw

沿着任意方向轴旋转(过原点)

方向向量为n\vec n,单位矩阵II

R(n,α)=cos(α)I+(1cos(α))nn+sin(α)(0nznynz0nxnynx0)R(\vec n, \alpha) = \cos(\alpha)I + (1 - \cos(\alpha))\vec n \vec n^\top + \sin(\alpha) \begin{pmatrix} 0 & -\vec n_z & \vec n_y \\ \vec n_z & 0 & -\vec n_x \\ -\vec n_y & \vec n_x & 0 \end{pmatrix}

四元数

用于解决万向节死锁,有利于旋转与旋转之间的角度差值。

观测变换 Viewing trans

包括模型变换视图/相机变换以及投影变换

也称作MVP(Model-View-Projection)变换

模型变换 Model trans

用于定义物体与物体之间的位置关系。

视图/相机变换 View/Camera trans

定义相机的位置:

下面为了表示方便,用 xgx_g 来表示 g\vec g 在X轴的分量,其他同理。

将相机的位置固定(标准位置):相机放在原点,朝Z轴负方向看,上方为Y轴

MviewM_{view}计算:

  1. e\vec e平移到原点

    Tview=(100xe010ye001ze0001)T_{view} = \begin{pmatrix} 1 & 0 & 0 & -x_e \\ 0 & 1 & 0 & -y_e \\ 0 & 0 & 1 & -z_e \\ 0 & 0 & 0 & 1 \end{pmatrix}
  2. g\vec g旋转到-Z,将t\vec t旋转到Y,将g×t\vec g \times \vec t旋转到X

    该旋转矩阵定义为 RviewR_{view}RviewR_{view} 不好直接求值,可以利用旋转的正交矩阵特性: Rview1=RviewR_{view}^{-1} = R_{view}^\top

    求得:

    Rview1=(xg^×t^xtxgyg^×t^ytygzg^×t^ztzg)R_{view}^{-1} = \begin{pmatrix} x_{\hat g \times \hat t} & x_t & x_{-g} \\ y_{\hat g \times \hat t} & y_t & y_{-g} \\ z_{\hat g \times \hat t} & z_t & z_{-g} \end{pmatrix}

    可以验证:

    Rview1(100)=(xg^×t^yg^×t^zg^×t^)R_{view}^{-1} \cdot \begin{pmatrix}1\\0\\0\end{pmatrix} = \begin{pmatrix}x_{\hat g \times \hat t} \\ y_{\hat g \times \hat t} \\ z_{\hat g \times \hat t} \end{pmatrix}

    即可将X轴的单位向量变换成 g^×t^\hat g \times \hat t的方向。

    也可以理解成 Rview1R_{view}^{- 1} 的三个列向量分别是在就坐标系下表示的新坐标系的基向量。

    由于正交矩阵的性质:

    Rview=(Rview1)=(xg^×t^yg^×t^zg^×t^0xtytzt0xgygzg00001)R_{view} = (R_{view}^{-1})^\top = \begin{pmatrix} x_{\hat g \times \hat t} & y_{\hat g \times \hat t} & z_{\hat g \times \hat t} & 0 \\ x_t & y_t & z_t & 0 \\ x_g & y_g & z_g & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}

所以视图变换的矩阵可以表示为:

Mview=RviewTviewM_{view}=R_{view}T_{view}

注意是先平移再旋转。

投影变换 Projection trans

在计算机图形学中,投影是从三维空间向二维空间的变换(不可逆,因为缺失了一个维度的信息)

一般认为投影变换有两种:正交投影(Orthographic projection)透视投影(Perspective projection)

有以下性质:

正交投影 Orthographic projection

简单可以理解为将Z轴去除掉,就可以得到一个二维的平面

在计算机图形学中,更标准的做法是将物体的 轴对齐包围盒(Axis Align Bounding Box,简称AABB) 变换到 标准立方体(Canonical Cube,即[1,1]3[-1, 1]^3),具体经过两步:

AABB变量定义:

  • X轴的最小值ll(left),X轴的最大值rr(right)
  • Y轴的最小值bb(bottom),Y轴的最大值tt(top)
  • Z轴的最小值ff(far),Z轴的最大值nn(near)
  1. 将AABB的中心平移至原点
  2. 将AABB缩放至标准立方体(边长为2)

即可得出:

Mortho=(2rl00002tb00002nf00001)(100r+l2010t+b2001n+f20001)M_{ortho} = \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} \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}

暂时不考虑旋转,且映射到标准立方体的过程中会导致物体被拉伸或缩放,后续还会进行视口变换。

透视投影 Perspective projection

透视投影的成像空间是一个 视锥(Frustum) 我习惯叫六面台体,而正交投影的成像空间是长方体。

而正交投影我们已经能理解并推导出变换矩阵,那就可以将透视投影的成像空间(六面台体)变化成正交投影的成像空间(长方体),再进行正交投影,这样不就是一次透视投影吗。

考虑人在远处可以看到更多的物体,但最后成像必然都是与近处物体在同一二维平面(视网膜)上,且远处物体会变小(被压缩了),相当于人眼进行透视投影的时候也是将远处的空间压缩到与近处相同,即长方体成像空间。所以将透视投影分成两步:压缩成像空间和正交投影是合理的。

现在关注如何 压缩/变换成像空间,在计算机图形学中可以做以下假设:

  1. 最近平面(成像平面)上的所有点经过透视投影 不变
  2. 最远平面上的所有点的Z值在变换成像空间后 不变
  3. 最远平面上的中心点的坐标在变换成像空间后 不变

可以将变换成像空间定义为矩阵:MpoM_{p\to o}

从X轴负方向看Y-Z平面:

从原点(相机)出发,近平面的点 (x,y,z)(x^\prime, y^\prime, z^\prime) 与成像空间内任意一点 (x,y,z)(x, y, z) 在同一直线上,在经过MpoM_{p\to o}变换后这两个点应该x和y都相同。即 MpoM_{p\to o} 应该使:

{y=nzyx=nzx\begin{cases} y^\prime = \frac{n}{z} y \\[2ex] x^\prime = \frac{n}{z} x \end{cases}

因为只假设了远近两平面的点的Z坐标不变,而成像空间内其他的点(即上述的坐标 (x,y,z)(x, y, z) )的Z坐标不知道应该怎么变化,所以对以上的变化规则可写成表达式:

Mpo(4×4)(xyz1)=(nx/zny/zunknown1)=×z(nxnyunknownz)M_{p \to o}^{(4\times 4)}\begin{pmatrix} x\\y\\z\\1\end{pmatrix} =\begin{pmatrix} nx/z \\ ny/z \\ \rm{unknown} \\ 1 \end{pmatrix} \overset {\times z}{=} \begin{pmatrix} nx \\ ny \\ \rm{unknown} \\ z \end{pmatrix}

这里利用了齐次坐标的性质,齐次坐标使用时需要归一化,最后一项永远会是1

可以分析得:

Mpo=(n0000n00????0010)M_{p \to o} = \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ ? & ? & ? & ? \\ 0 & 0 & 1 & 0\end{pmatrix}

同时,根据我们之前的假设,最近平面上的点 (x,y,n,1)(x, y, n, 1) 变化前后是不变的,可得:

Mpo(4×4)(xyn1)=(n0000n00ABCD0010)(xyn1)==(nxnyn2n)M_{p\to o}^{(4\times 4)} \begin{pmatrix} x \\ y \\ n \\ 1 \end{pmatrix} = \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 \\ n^2 \\ n \end{pmatrix}

其中ABCD为未知量

针对Mpo(4×4)M_{p\to o}^{(4\times 4)}的第三个行向量 (A,B,C,D)(A, B, C, D) 可以列出:

(A,B,C,D)(xyn1)==n2(A, B, C, D)\begin{pmatrix} x \\ y \\ n \\ 1 \end{pmatrix} == n^2

分析可得,n2n^2是一个常量,与AABB有关,与取的任意点 (x,y,z,1)(x, y, z, 1) 无关,所以 A=0A = 0B=0B = 0CCDD 不好判断,即可列出等式:

Cn+B=n2Cn + B = n^2

同理,最远平面上的所有点(x,y,f,1)(x, y, f, 1)变化前后Z轴上的值不变,即可列出:

Cf+B=f2Cf+B=f^2

省略了过程:

Mpo(4×4)(xyf1)=(n0000n0000CD0010)(xyf1)==(nxnyf2f)M_{p\to o}^{(4\times 4)} \begin{pmatrix} x \\ y \\ f \\ 1 \end{pmatrix} = \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 \\ f^2 \\ f \end{pmatrix}

列方程可解:

{Cn+B=n2Cf+B=f2{C=n+fD=nf\begin{cases} Cn + B = n^2 \\[2ex] Cf + B = f^2 \end{cases} \Longrightarrow \begin{cases} C = n + f \\[2ex] D = -nf \end{cases}

可得:

Mpo=(n0000n0000n+fnf0010)M_{p\to o} = \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n + f & -nf \\ 0 & 0 & 1 & 0\end{pmatrix}

综上可得,投影变换可以写为:

Mpersp=MorthoMpo=(2rl00r+l202tb0t+b2002nfn+f20001)(n0000n0000n+fnf0010)M_{persp} = M_{ortho}M_{p \to o} = \begin{pmatrix} \frac{2}{r - l} & 0 & 0 & -\frac{r + l}{2} \\ 0 & \frac{2}{t - b} & 0 & -\frac{t + b}{2} \\ 0 & 0 & \frac{2}{n - f} & -\frac{n + f}{2} \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n + f & -nf \\ 0 & 0 & 1 & 0 \end{pmatrix}

思考:成像空间中的任意一点经过 MpoM_{p \to o} 变换后Z轴的分量如何变化?

对于任意一点 (x,y,z,1)(x,y ,z,1) ,经过变换:

(n0000n0000n+fnf0010)(xyz1)=(nxny(n+f)znfz)=(nx/zny/zn+fnf/z1)\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} = \begin{pmatrix} nx \\ ny\\ (n + f)z - nf \\ z \end{pmatrix} = \begin{pmatrix} nx /z \\ ny/z \\ n + f - nf/z \\ 1 \end{pmatrix}

关于n和f的意义是Z轴上的坐标,此时 f<nf < n ,下面的函数中可以看做是近远平面到相机的距离,此时 n<fn < f ,此种改变并不会影响上述推导。

f(z)=nf/z+n+ff(z) = -nf /z +n + f 是变换前后Z轴分量的映射关系,可以看出是关于z的反比例函数的变形,可以验证 f(n)=nf(n)=nf(f)=ff(f)=f ,故可以画出函数图像:

可以看出当 n<z<fn < z < f 时,f(z)<g(z)f(z) < g(z) ,故在进行压缩成像空间时,六面台体内的点被挤向了远处

我个人对这种现象的看法是:在六面台体的成像空间中,单位空间的信息量是相同的,在经过 MpoM_{p \to o} 变换后六面台体的后部被挤压导致形成的长方体成像空间中的单位空间信息密度更大,所以整体上空间中的点更靠后集中。

总结

本篇记录了计算机图形学中关于坐标变换的部分内容,主要参考了GAMES101

我文章里的内容并不全面,可能后续会补充内容。


分享这篇文章:
通过邮件分享这篇文章

分享到微信

微信对普通网页没有开放通用直连分享协议。更稳妥的方式是复制链接、扫码打开,或在支持的设备上调用系统分享。

上一篇
[LEGACY] 脚本化备份hexo项目&部署博客
下一篇
sourcemod插件开发记录