实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)

4 变换

    • 变换(transform)
    • 1 基础变换
    • 2 特殊的矩阵变换和操作
      • 欧拉变换(euler transform)
      • 绕任意轴进行旋转
    • 3 四元数
      • 数学背景
      • 四元数变换
      • 球面线性插值
      • 表示一个方向旋转到另一个方向

变换(transform)

变换是对例如点和向量这类实体进行转换的某种操作,对于计算机图形学的实践者来说这是极为重要的一项内容。通过变换,程序员可以对对象移动位置、放缩尺寸,对模型光源相机附加动画效果。
线性变换(linear transform) 是一种完成向量加法和数乘的操作,设操作表示为f ,其性质如下公式所示。

在这里插入图片描述
典型的线性变换包括旋转和尺寸放缩,对于三维空间中的线性变换,我们可以使用3*3的矩阵与向量乘法运算获得变换结果。对于平移,我们使用一个固定的向量与原始向量相加获得平移结果,例如完成向(7,3,2)平移我们需要使用如下的变换实现。
在这里插入图片描述
按之前的定义,平移变换f显然不是线性变换,无法用3×3矩阵表示,为了统一变换的形式,我们将平移和线性变换统一为仿射变换(affine transform),仿射变换使用4×4矩阵来表示。为了与仿射变换对应,我们将点和向量扩展为4维,定义点的第四维为1、向量的第4维为0(如此满足点的差为两点间向量,点与向量和为点)。下面介绍的内容中我们使用列向量(其他使用行向量的图形库对应的变换矩阵恰好都是本篇给出的矩阵的转置),那么向量扩展后写为:点 v=(vx,vy,vz,1)T 向量 v=(vx,vy,vz,0)T。所有的平移、旋转、放缩镜像、错切都是仿射变换的一种。仿射变换最显著的特征就是变换结果会保持原始的平行性质(即之前平行的两条线,在变换后一定仍然平行)。
对于图形学程序员,完成变换往往是通过提供的接口函数实现。但了解函数背后的变换矩阵如何工作进而可以提升代码质量(比如有些变换是由正交矩阵完成,正交阵的逆可以直接通过求转置完成),所以这一部分内容的学习有着重要意义。

1 基础变换

这一节介绍最为基础的变换,是后续小节和本书后续内容的必要背景知识。

  • 平移(translation)
    平移矩阵使用符号T,表示为:
    实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第1张图片
    对于点v = (x,y,z,1)T,通过T·v,得到v’ = (x+tx,y+ty,z+tz,1)。而对于向量,由于第四维为0,使用T乘向量后会得到向量本身,这符合向量只有方向没有位置属性的特点。T-1(t) = T(-t) ,即移动向量t取相反数就可以得到平移矩阵T的逆矩阵。

  • 旋转(Rotation)
    旋转可以让点或者向量绕任意穿过原点的轴进行旋转。绕x、y、z轴旋转的的矩阵是最基础的旋转矩阵,公式如下。
    实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第2张图片
    通过三个基础旋转的组合我们能得到所有旋转变换的结果。关于Φ角的方向根据右手系定义,大拇指指向坐标轴正向,其余四指握住坐标轴的方向即为Φ的正向(例如Rz 从x轴正向(1,0,0)+90度应该到y轴正向(0,1,0))。观察公式,我们发现旋转矩阵只有在左上3x3子阵中有所差别,最后一列一排都是固定的0或1;此外三种矩阵的迹(主对角线之和)都为2+cos(Φ);都是正交阵。
    之前给的定义中提到旋转只能表示绕过原点的轴进行旋转的变换。如果要绕未过原点的轴进行旋转时,可行的表示为平移-旋转-平移的组合变换。实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第3张图片图中将旋转中心(眼睛)移动到原点后再进行旋转,完成旋转后将旋转中心移动回到原位。
    关于旋转还有很多的实现方法和策略,我们在之后再详细描述。

  • 尺度缩放(scale)
    在某个轴的方向上进行尺度缩放,可以让模型变大缩小。
    实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第4张图片
    当sx = sy = sz时,称为均匀(uniform)的缩放。当三个轴的系数有一个或者三个为负数时,得到的缩放矩阵是一种反射矩阵(reflection matrix) ,而只有两个系数为负数时例如-1,那么相当于旋转180度并不是反射。此外反射矩阵和旋转矩阵相乘得到的还是一个反射矩阵(reflection matrix) ,我们应当注意进行反射后,三角形的法向方向会发生改变,这有可能在疏忽的情况下导致错误的光线和背面剖除(都是依据法向量而实现的内容)。
    和旋转的定义类似,缩放有方向只能为坐标轴的限制。为了能在任意方向进行缩放,一种可行的方案是进行旋转-缩放-旋转的组合变换。

  • 错切(Shearing)
    错切可以完成形状的变形、扭曲。一共定义有六种错切:在这里插入图片描述其中包含两个参数,第一个表示发生变化的轴坐标,第二个表示该坐标越远离原点扭曲距离越大。看图实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第5张图片
    如图所示,第一个参数是x,意味着错切变换只会改变x坐标,各点不会再y、z方向上有任何变化;第二个参数是z,那么z绝对值越大的x扭曲幅度越大、z等于零的点保持不动、z小于0扭曲方向是x的负方向(图里没画)。变换输入s衡量扭曲程度,对应图中的点每多一个单位z坐标,x就要多移动s距离。
    了解了定义后再观察错切矩阵的形式。
    实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第6张图片以第一个参数对应行号第二个参数对应列号,在该位置填入输入的s参数。可以看出左上3x3中,除了对角线上表示缩放的位置以外,剩下的6个空位就对应于六种错切的输入参数了。

  • 级联变换(Concatenation of Transforms)
    前面提到的4种变换是最为基本的变换方法,在实际应用中我们需求的变换就有可能是多个变换的组合,称为级联变换。关于级联变换我们先要明确它的不可交换性,下图给出了缩放与旋转相组合的例子:
    实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第7张图片很显然旋转和缩放的顺序会影响到变换结果。
    此外当我们意识到某种级联变换要多次进行时,我们可以考虑预先把级联变换的矩阵计算出来,把对每个物体都要进行多次基础变换替换为对每个物体进行一次级联变换。如此减少矩阵乘法次数提高效率。

  • 刚体变换(The Rigid-Body Transform)
    只有平移和旋转的级联变换称为刚体变换。容易看出刚体变换只改变物体的位置方向,不会改变物体的形状。任意刚体变换可以被定义为先进行旋转再进行平移的级联变换,如此可以方便的给出刚体变换的变换矩阵(若反之平移的效果会被旋转所影响)。
    实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第8张图片

  • 法线变换(normal transform)
    之前提到的变换可以作用于点、向量、三角形或者任意几何体,而且变换的矩阵可以同样的作用于切线上得到几何体变换后的切线方向。但是同样的变换矩阵不能用于法向量。如图所示。实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第9张图片图中的三角形(侧视图所以看着是条线)法向量标识为蓝色。我们对图形沿x缩小一半,假如我们用同样的变换施加到法向量,可以看到法向量也在x方向缩小,那势必导致法向量不再与三角形垂直。所以用什么方法才能得到如图3一样正确的结果呢?
    书中直接给出结论:使用变换矩阵伴随的转置;传统上也可以用变换矩阵逆的转置。后者与前者系数不同(相差一个变换矩阵的行列式),但是方向是相同的。后者的一个缺点是会在变换矩阵不可逆时出错。

  • 简单介绍图形学中逆矩阵的求法
    1、已知基础变换的参数时,设计带有反向变换的参数的矩阵就是原始变换矩阵的逆。比如平移中参数设定为x正向5单位,它的逆就为x负向5单位对应的变换矩阵;错切变换参数s的变换矩阵对应逆矩阵就为错切变换中设置参数为1/s。
    2、正交阵取转置为它的逆,这个在旋转矩阵中最明显。
    3、如果没有上述信息,邻接矩阵求逆、格莱姆法则(Cramer’s rule)、LU分解、 高斯消元法(Gaussian elimination)都是可以选择的方法。书中建议在计算机编程实现的情况下前两种方案比较简便(理由是判断分支“if”少)。

2 特殊的矩阵变换和操作

这一小节将会深入旋转的方法,首先根据上一节给出的三种基础旋转方式,通过组合形成任意一个旋转;之后再给出围绕任意一个轴进行旋转的方法。

欧拉变换(euler transform)

实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第10张图片欧拉角是由围绕三个轴的旋转组合而成,我们先对各轴方向以及对应旋转的名称进行定义。在本书中,设定默认视角方向为-z,head(就是yaw)旋转围绕y轴进行,命名设定为上图所示。
可行的欧拉变换顺序一共有24种(使用三个轴的是全排列6个,用两个轴的是6个,一共12个,又分为场景坐标系为中心外旋和以物体为中心的内旋,一共12x2=24种),书中选取最为常见的旋转顺序:
在这里插入图片描述欧拉变换简单容易被描述,但是它不容易完成插值任务,对于两个不同的欧拉变换矩阵,它们表示的变换可能是同一个旋转,这时插值过程应该是保持静止的,可显然不同的矩阵进行简单的插值一定导致插值过程中角度是变化的。
最后欧拉角还存在万向锁(gimbal lock) ,万向锁是在某种旋转方式导致一个旋转自由度丢失的情况。举个最简单的例子,当我们使用xyz的旋转顺序,先绕x旋转若干角度,再绕y轴旋转90度,这个时候x和z轴处于重合状态,这意味着开始时对x轴的变化已经体现在z轴的变化中,此时z轴的变化可以被舍弃掉。

绕任意轴进行旋转

之前提到的都是绕x、y、z轴进行旋转的例子。如果需要描述绕任意轴进行旋转,是一定能够通过欧拉角表示的,但表示方法显然不够直观,下面给出一种较为直观的方法。
假设我们要绕r(设r为单位长度向量)旋转α度。第一步要将r旋转到x正向,这一步的变换矩阵设为M;第二步使用绕x旋转的矩阵 Rx 将模型旋转α;第三步使用M的逆还原回r所在位置。流程如图所示:
实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第11张图片在图中可以看到我们又根据r的方向设置了s、t两个轴,这是我们创建矩阵M的步骤之一。创建M的过程十分简单,首先第一步根据r设置方向s(s、t是等价的先设置s只是语义上的区别)。显然和r垂直的向量不是唯一的,我们要选取精度最大的一个,避免选择的s坐标存在接近0而不是0的数值。实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第12张图片
公式的三种情况对应于r的坐标最小值是xyz的三种情形,我们要让s坐标中出现的是r中最大的两个坐标,随后再对s进行单位化。第二步,叉积计算t,注意这里由于s、r都设置为单位化向量,t的计算结果长度是1。
在这里插入图片描述
计算出rst后,M矩阵写为(使用基准向量拼接一个想要的变换矩阵是一种常见的技巧):在这里插入图片描述这样我们的公式可以写作:
在这里插入图片描述


  • 除了上述方法,由Goldman提出了一次完成旋转的矩阵公式:实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第13张图片式子中r为单位旋转轴,Ф为旋转角度,书中略去证明的方法。

3 四元数

数学背景

四元数由一个由虚数组成的三维向量和一个实数组成,对应的一个实数称为实部,虚数向量称为虚部。在粗体字体上加一个^,四元数和向量粗体进行区分。
在这里插入图片描述
四元数的乘法使用满足分配律的计算方法,但是四元数乘法是不可交换的。
实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第14张图片
四元数除了乘法还包含了多种运算,下面介绍与旋转表示相关的运算定义。

  • 共轭
    即虚部向量系数取相反数
    在这里插入图片描述
  • 求模
    作为四维向量的二范数
    在这里插入图片描述
  • 求逆
    在这里插入图片描述
    这一公式是借助于共轭和原四元数的乘积为模的平方推导而定义出来的
    在这里插入图片描述

四元数变换

我们变换操作使用的四元数是四元数集合的子集,是长度为一的单位四元数(unit quaternions)。首先我们简单的将点或向量写成4维的形式p=(px,py,pz,pw);接着设一个单位四元数表示为
在这里插入图片描述
其中uq 为单位向量,最后通过公式
在这里插入图片描述
来表示绕轴uq旋转角度2×Ф的结果。
实时渲染(RealTimeRendering-4thEdition)笔记——4变换(上)_第15张图片
我们注意到对于单位四元数,由于模为1,推出逆和共轭是相同的。

感性思考:四元数是四维空间运算,一次四元数乘法得到的结果不在向量或点最初的三维空间中(w不为1或0),所以只进行一次四元数乘法完成旋转是不可行的,只能通过取旋转角度的一半,进行两次旋转才能得到正确结果

球面线性插值

之前提到了对欧拉角进行插值是不可行的,四元数最出色的特点就是它可以简单的完成插值任务,在应用中实现动画效果。slerp球面线性插值(spherical linear interpolation) 的缩写,他表示插值过程将会在球面大圆(great circle) 中的一段(称为大圆弧great arc)完成。
在这里插入图片描述
公式中t在[0,1]之间,t=0时插值结果为q,t=1时插值结果为r。直觉上不使用的正弦函数直接使用(1-t)和t也可以完成插值,不过这样获得的结果是在球的弦上进行的线性插值,这会导致旋转过程先变快再变慢。

表示一个方向旋转到另一个方向

实际应用中我们会使用四元数表示将空间中一个向量旋转到另一个向量的位置的变换。假设起始向量为s目的向量为t,旋转角度2×Ф。首先第一步要对s、t进行单位化;二者叉乘可以表示旋转轴,用二者内积可以表示夹角2×Ф的余弦值;
在这里插入图片描述
最后通过半角公式推出公式:
在这里插入图片描述
注意到当e为-1,也就是s和t方向恰好相反为180度时,分母为零,此时是没有定义的。

你可能感兴趣的:(实时渲染笔记,计算机图形学)