Real-Time-Rendering 矩阵的其他变换及投影矩阵(三)

        接下来我们讨论矩阵的平移、投影变换,在计算机图形学中这两种变换也及其常用。

一、4x4矩阵

        在讨论位移矩阵前,我们需要引出4x4矩阵的相关概念。

        4D向量有4个分量,前三个是标准的x、y、z分量,第四个是w,有时称为齐次坐标。

        我们可以把齐次坐标理解为更高维度的抽象。比如2D坐标系中一个点在2D的扩展坐标齐次坐标中将有无数的点对应。他的形式为(x,y,w)。对于不在w=1平面的点,我们可以通过将x、y除以w来将这个点投影到w=1的平面。所以2D坐标系中的齐次坐标(x,y,w)其实映射的实际2D点为(x/w,y/w)。3D坐标系同理。

        为什么引入4x4矩阵,第一个原因是因为方便的记法,在平移矩阵中将会讨论。第二个原因是因为w的映射性质。

二、平移矩阵

        在上一章中我们讨论的都是用3x3矩阵表示的线性变换,不包含平移。因为矩阵乘法的性质,零向量总是变化成零向量。显然无法描述分量加、减这样的平移操作。而4x4矩阵提供了数学上的技巧帮我们做到这一点。

        暂时假设w总是等于1,那么,标准3D向量[x,y,z]对应的4D向量为[x,y,z,1]。任意3x3变换矩阵在4D中表示为:

        \begin{bmatrix} m_{11} & m_{12} &m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} &m_{32} & m_{33} \end{bmatrix} => \begin{bmatrix} m_{11} & m_{12} &m_{13} & 0 \\ m_{21} & m_{22} & m_{23}& 0 \\ m_{31} &m_{32} & m_{33} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

        \begin{bmatrix} m_{11} & m_{12} &m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} &m_{32} & m_{33} \end{bmatrix} \begin{bmatrix} x\\ y\\ z \end{bmatrix} = \begin{bmatrix} xm_{11} + ym_{12} + zm_{13}\\ xm_{21} + ym_{22} + zm_{23}\\ xm_{31} + ym_{32} + zm_{33} \end{bmatrix}

        \begin{bmatrix} m_{11} & m_{12} &m_{13}&0 \\ m_{21} & m_{22} & m_{23} &0\\ m_{31} &m_{32} & m_{33}&0 \\ 0 &0 & 0&1\end{bmatrix} \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} = \begin{bmatrix} xm_{11} + ym_{12} + zm_{13} + 0 * 1\\ xm_{21} + ym_{22} + zm_{23} + 0 * 1\\ xm_{31} + ym_{32} + zm_{33} + 0 * 1\\ 1 \end{bmatrix}

        可以发现中间的3x3矩阵依然可以代表线性变换改变向量的x、y、z分量,如果我们想屏蔽线性变换只需中间的3x3方阵改变为单元矩阵即可。而现在x、y、z分量同时被4x4矩阵的第四列所影响(如果矩阵以行为主,则是第四行)。只是因为我们都设为0,所以他并没有向量带来实际变换,但他却有加减的特性,利用此数学技巧我们可以利用矩阵的第四列实现向量的平移变换。

        \begin{bmatrix} 1 & 0 & 0 & \triangle x\\ 0 & 1 & 0 & \triangle y\\ 0 & 0 & 1 &\triangle z\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} = \begin{bmatrix} x + \triangle x\\ y + \triangle y\\ z + \triangle z\\ 1 \end{bmatrix}

        当中间的3x3方阵包含一个线性变换时,外面包裹上位移矩阵的第4列,即实现了诸如y = ax + b形式的映射,我们称其为仿射变换。

        之前我们将列向量的w总是设为1,现在我们设为0,很容易发现位移矩阵的第四列失去了作用。换句话说,列向量的w可以开关平移矩阵。所以在计算变换时,向量如果代表一个点,说明他具有3D坐标系中的具体位置,我们应该把w设为1。如果向量就是作为向量,只具有方向的含义,我们应将w设为0,屏蔽无用的位置偏移的信息。

        在上一章中我们所做的线性操作要求任意轴都经过原点。现在我们有了位移矩阵就可以获得不经过原点的任意轴的仿射变换。我们可以将向量先平移至原点,在做线性变换,再将向量反向平移回去。即可实现向量对任意轴的变幻了。

        \mathbf{T} = \begin{bmatrix} 1 & 0 & 0 & -\mathbf{p_{x}} \\ 0 & 1 & 0 &-\mathbf{p_{y}} \\ 0 & 0 & 0 &-\mathbf{p_{z}} \\ 0 & 0 & 1 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{I }& -\mathbf{p}\\ 0 & 1 \end{bmatrix}

        \mathbf{R}_{4x4} = \begin{bmatrix} r_{11} & r_{12} & r_{13} & 0\\ r_{21} & r_{22} & r_{23} & 0\\ r_{31} & r_{32} & r_{33} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{R}_{3x3} & \mathbf{0}\\ 0 & 1 \end{bmatrix}

        \mathbf{T}^{-1} = \begin{bmatrix} 1 & 0 & 0 & \mathbf{p_{x}} \\ 0 & 1 & 0 &\mathbf{p_{y}} \\ 0 & 0 & 0 &\mathbf{p_{z}} \\ 0 & 0 & 1 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{I }&\mathbf{p}\\ 0 & 1 \end{bmatrix}

        \mathbf{T}\mathbf{R}_{4x4}\mathbf{T}^{-1} = \begin{bmatrix} \mathbf{I} & -\mathbf{p}\\ 0 & 1 \end{bmatrix} \begin{bmatrix} \mathbf{R}_{3x3} & \mathbf{0}\\ 0 & 1 \end{bmatrix} \begin{bmatrix} \mathbf{I} & \mathbf{p}\\ 0 & 1 \end{bmatrix} = \begin{bmatrix} \mathbf{R}_{3x3} & \mathbf{R}_{3x3}(-\mathbf{p}) + \mathbf{p}\\ 0 & 1 \end{bmatrix}

三、正交矩阵

        上述混合变换时我们用到了逆矩阵,逆矩阵很好的变现了变换的逆操作,但根据第一篇矩阵的文章所述,求矩阵的逆将带来大量的运算。这里引入一种新的矩阵,正交矩阵。一个矩阵M,当且仅当矩阵M和其转置矩阵乘积等于单位矩阵。则说矩阵M正交。

        \mathbf{M}正交=d正交 <=> \mathbf{M}\mathbf{M}^{T} = \mathbf{I}

        根据矩阵第一章逆的相关定义,若矩阵乘他的逆等于单元矩阵,那么他的转置等于他的逆。

        所以如果该矩阵是正交的,那么我们在求他的逆矩阵时只需获得他的转置矩阵即可。显然转置的计算量远小于求逆的过程。

        若一个矩阵是正交的,他满足一下条件:

        1.矩阵的每一列都是单位向量。

        2.矩阵的所有列互相垂直。

        显然之前所述的旋转与镜像矩阵都是正交的。并且若一个矩阵正交,那么他的转置矩阵也正交。在计算逆矩阵中,显然如果我们知道该矩阵是正交矩阵时,直接获取其转置矩阵性能最佳。但若我们不知道他是否是正交矩阵时,先判断矩阵是否正交和直接计算矩阵逆耗费时间相同。若矩阵本来并不正交,我们只会浪费更多的计算时间。

        因为我们在矩阵的计算过程中矩阵的每一位的精度都可能超过了计算机能存储的精度。所以矩阵在浮点运算的过程中可能会累计误差,称为矩阵爬行。当我们认为一个矩阵是正交矩阵时,他可能因为外部的数据损坏或运算中的误差积累变得并不那么正交。所以有时我们需要做矩阵正交化的操作。

        施密特正交化是线性代数中标准的矩阵正交化算法。原理即每一列(行)都减去它投影于已处理过的列(行)的部分。显然得到的三个向量互相垂直。这三个向量称为3D向量空间的三个正交基。若将正交基标准化。则称为规范正交基(在线性代数中如此称呼,在3D数学基础:图形与游戏开发一书中称为标准正交基)。

        现在我们有一个3x3的矩阵,我们从矩阵中获取每一列分别记作r1,r2,r3。则求正交基的过程如下:

        \mathbf{r}_{1}^{'} <= \mathbf{r}_{1}

        \mathbf{r}_{2}^{'} <= \mathbf{r}_{2} - (\mathbf{r}_{2}*\mathbf{r}_{1}^{'}/\mathbf{r}_{1}^{'} * \mathbf{r}_{1}^{'}) \mathbf{r}_{1}^{'}

        \mathbf{r}_{3}^{'} <= \mathbf{r}_{3} - (\mathbf{r}_{3}*\mathbf{r}_{1}^{'}/\mathbf{r}_{1}^{'} * \mathbf{r}_{1}^{'}) \mathbf{r}_{1}^{'} - (\mathbf{r}_{3}*\mathbf{r}_{2}^{'}/\mathbf{r}_{2}^{'} * \mathbf{r}_{2}^{'}) \mathbf{r}_{2}^{'}

        然后将得到的三个向量标准化即可得到规范正交基。

        可以发现如果这么做正交化会出现因为选择第一个基向量的顺序的不同导致不同的结果。3D数学基础:图形与游戏开发一书中提出一个优化方法,选择一个小的因子k,每次都将一个向量减去对其余所有向量的投影,但都只减少k倍。如此迭代多次。得到的基向量会越来越正交化,但可能并不完全正交。

        \mathbf{r}_{1}^{'} <= \mathbf{r}_{1} - k(\mathbf{r}_{1}*\mathbf{r}_{2}/\mathbf{r}_{2} * \mathbf{r}_{2}) \mathbf{r}_{2} - (\mathbf{r}_{1}*\mathbf{r}_{3}/\mathbf{r}_{3} * \mathbf{r}_{3}) \mathbf{r}_{3}

        \mathbf{r}_{2}^{'} <= \mathbf{r}_{2} - k(\mathbf{r}_{2}*\mathbf{r}_{1}/\mathbf{r}_{1} * \mathbf{r}_{1}) \mathbf{r}_{1} - (\mathbf{r}_{2}*\mathbf{r}_{3}/\mathbf{r}_{3} * \mathbf{r}_{3}) \mathbf{r}_{3}

        \mathbf{r}_{3}^{'} <= \mathbf{r}_{3} - k(\mathbf{r}_{3}*\mathbf{r}_{1}/\mathbf{r}_{1} * \mathbf{r}_{1}) \mathbf{r}_{1} - (\mathbf{r}_{3}*\mathbf{r}_{2}/\mathbf{r}_{2} * \mathbf{r}_{2}) \mathbf{r}_{2}

        要得到完美的结果,需要选择适当的因子k,并迭代足够次数(如10次),接着标准化即可。

四、正交投影

        一般来说,投影意味着降维操作。可以将某个方向上用零作为缩放因子。这样所有点被拉伸到平面(3D)或线(2D)中。

        如果在2D中向坐标轴投影或者在3D中向两个坐标轴形成的平面投影。我们只需将剩下的一个维度设为0即可,即上述的缩放因子设为0。得到如下矩阵:

        \mathbf{P_{x}} = \mathbf{S}(\begin{bmatrix} 0 & 1 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 1 &0 \\ 0 & 0 \end{bmatrix}

        \mathbf{P_{y}} = \mathbf{S}(\begin{bmatrix} 1 & 0 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 0 &0 \\ 0 & 1 \end{bmatrix}

        \mathbf{P_{xy}} = \mathbf{S}(\begin{bmatrix} 0 &0 & 1 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 1 &0&0 \\ 0 & 1&0\\ 0 & 0&0 \end{bmatrix}

        \mathbf{P_{xz}} = \mathbf{S}(\begin{bmatrix} 0 &1 & 0 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 1 &0&0 \\ 0 & 0&0\\ 0 & 0&1 \end{bmatrix}

        \mathbf{P_{yz}} = \mathbf{S}(\begin{bmatrix} 0 &0 & 1 \end{bmatrix}^{T}, 0) = \begin{bmatrix} 0 &0&0 \\ 0 & 1&0\\ 0 & 0&1 \end{bmatrix}

        向任意直线或平面投影,位移部分用上述方法即可获取,现在我们关注经过原点的直线或平面的投影。

        上一章中获得的对任意经过原点的直线或平面的缩放矩阵,将缩放因子设为0即可获得。将0带入缩放矩阵很容易得到:

        \mathbf{P}(\mathbf{n}) = \mathbf{S}(\mathbf{n},0) = \begin{bmatrix} 1 + (0 - 1)\mathbf{n}_{x}^{2} & (0 - 1)\mathbf{n}_{x}\mathbf{n}_{y}\\ (0 - 1)\mathbf{n}_{x}\mathbf{n}_{y} & 1 + (0 - 1)\mathbf{n}_{y}^{2} \end{bmatrix} = \begin{bmatrix} 1 -\mathbf{n}_{x}^{2} & -\mathbf{n}_{x}\mathbf{n}_{y}\\ -\mathbf{n}_{x}\mathbf{n}_{y} & 1 -\mathbf{n}_{y}^{2} \end{bmatrix}

        \mathbf{P}(\mathbf{n}) = \mathbf{S}(\mathbf{n},0) = \begin{bmatrix} 1 -\mathbf{n}_{x}^{2} & -\mathbf{n}_{x}\mathbf{n}_{y}& -\mathbf{n}_{x}\mathbf{n}_{z}\\ -\mathbf{n}_{x}\mathbf{n}_{y} & 1 -\mathbf{n}_{y}^{2} & -\mathbf{n}_{z}\mathbf{n}_{y}\\ -\mathbf{n}_{x}\mathbf{n}_{z} & -\mathbf{n}_{y}\mathbf{n}_{z} & 1 -\mathbf{n}_{z}^{2} \end{bmatrix}

五、透视投影

        之前我们说引入齐次坐标作为4D向量的第四个分量的第二个原因是w可以为其他坐标做除以w的操作。这个性质在透视投影中得到运用。

        之前的平行投影之所以成为平行投影是因为投影线互相平行。而3D中透视投影的投影线不在平行,且会相交于一点,该点成为投影中心。

        透视投影是人类视觉系统的模型,充分显示出小孔成像的几何特性。小孔成像

        而图形接口如OpenGL中的投影矩阵与小孔成像相比只是在光透过小孔前就会成像。且一般都会投影到摄像机的z = 近裁剪面形成的平行于xy平面的面上。如下图所示。

投影图示

        我们现在将点P投影到P'。设P点的z分量为z。投影面的z分量即P'点的z分量为d。投影公式为:

        \mathbf{P} = \begin{bmatrix} x\\ y\\ z \end{bmatrix} => \mathbf{P{}'} = \begin{bmatrix} x{}'\\ y{}'\\ z{}' \end{bmatrix} = \begin{bmatrix} dx/z\\ dy/z\\ d \end{bmatrix}

        \mathbf{P}{}' = \begin{bmatrix} dx/z\\ dy/z\\ dz/z \end{bmatrix} = \begin{bmatrix} x\\ y\\ z \end{bmatrix}/(z/d)

        我们将P'转换为带有w的4D坐标即\begin{bmatrix} x & y & z & z/d \end{bmatrix}^{T}。是的4D坐标中x、y、z坐标分别除以w等于前面的3D坐标的x、y、z。

        所以我们需要构造一个4x4矩阵完成上述映射。矩阵如下:

        \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 1/d & 0 \end{bmatrix} \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} = \begin{bmatrix} x\\ y\\ z\\ z/d \end{bmatrix}

        当然真正使用的投影矩阵比这个复杂的多,比如unity中将摄像机坐标系下的点变换为投影坐标系下的点所使用的矩阵。在下一章中我们会详细讲述。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSDN是国内IT技术社区的一家知名平台,为广大IT从业人员提供了丰富的技术资源和交流平台。其中关于real-time graphics rendering engine(实时图形渲染引擎)的相关内容也是很多人关注和讨论的。 实时图形渲染引擎是一种计算机程序,主要用于在实时应用中实现图形渲染的高度效率和精确度。它能够将图像渲染成高质量的视觉效果,常见的应用场景包括游戏开发、虚拟现实和增强现实等。 在CSDNreal-time graphics rendering engine领域,有着丰富的技术资料和教程供开发者学习和参考。从基础入门到深入探究各种领域的技术细节,都能在CSDN找到相关的文章和博客。通过阅读这些资料,开发者们可以掌握实时图形渲染引擎的原理与应用,快速入门,并能够在实际项目中运用所学。 同时,在CSDNreal-time graphics rendering engine社区中,开发者们还可以相互交流、分享心得和技术难题。通过这种交流合作,可以加深理解和提高解决问题的能力。不少关于实时图形渲染引擎的优化技巧、最佳实践和案例等都得到了广泛探讨和分享,有助于开发者不断提升自己的技术水平。 总之,CSDN作为一个包含众多IT技术内容的平台,提供了real-time graphics rendering engine方面的丰富资源。它为开发者们提供了学习、交流和分享的机会,对于想要深入研究和应用实时图形渲染引擎的人来说,是一个不可多得的宝藏。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值