OpenGL ES 入门 -- 变换

522 阅读6分钟

如果不想安逸的被淘汰,那就奋不顾身的去努力

OpenGL ES 入门 -- 绘制图形

OpenGL ES 入门 -- 渲染图片

变换

通过前两章,我们大致的可以绘制一个简单的矩形或者渲染一张图片,对我而言这似乎很有意思,如果想要变得更有意思,我们得稍微了解一点数学相关的知识-矩阵,使用多个矩阵对象可以很好的变换一个物体,为了深入了解变换,在我们讨论矩阵之前了解一下向量,这篇文章的目的是为了让你拥有将来最需要的基础数学背景知识,如果你对向量、矩阵很熟悉,这章可以忽略,如果你觉得这章十分困难,请尽可能的尝试去理解它们,以后需要的时候回过头来复习这些概念,理论知识比较枯燥,加油~

向量

向量最基本的定义就是一个方向,或者说向量有一个方向(Direction)和大小(或长度),由于向量表示的是方向,起始于何处并不会改变它的值,所以我们可以理解向量v和向量w是相等的,尽管他们的起点不相同,例如:

用公式表达通常是这样的:

由于向量是一个方向,所以有些时候会很难形象地将它们用位置(Position)表示出来。为了让其更为直观,我们通常设定这个方向的原点为(0, 0, 0),然后指向一个方向,对应一个点,使其变为位置向量(Position Vector)(你也可以把起点设置为其他的点,然后说:这个向量从这个点起始指向另一个点)。比如说位置向量(3, 5)在图像中的起点会是(0, 0),并会指向(3, 5)。我们可以使用向量在2D或3D空间中表示方向与位置, 和普通数字一样,我们也可以用向量进行多种运算。

向量和标量运算

标量(Scalar)只是一个数字(或者说是仅有一个分量的向量)。当把一个向量加/减/乘/除一个标量,我们可以简单的把向量的每个分量分别进行该运算。对于加法来说会像这样:

向量加减

向量的加法可以被定义为是分量的相加,即将一个向量中的每一个分量加上另一个向量的对应分量:

减法同加法相似~

向量相乘

两个向量相乘可以分为两种情况:一个是点乘,记做向量v * k;一个是叉乘,记做向量v x k。

点乘

两个向量的点乘等于它们的数乘结果乘以两个向量之间夹角的余弦值,我们来看一下公式:其中||v¯||表示向量v¯的长度,

它们之间的夹角记作θ。为什么这很有用?想象如果v¯和k¯都是单位向量,它们的长度会等于1。这样公式会有效简化成:

现在点积只定义了两个向量的夹角。你也许记得90度的余弦值是0,0度的余弦值是1。使用点乘可以很容易测试两个向量是否正交(Orthogonal)或平行(正交意味着两个向量互为直角),点乘是通过将对应分量逐个相乘,然后再把所得积相加来计算的。两个单位向量的点乘会像是这样:

叉乘

叉乘只在3D空间中有定义,它需要两个不平行向量作为输入,生成一个正交于两个输入向量的第三个向量。如果输入的两个向量也是正交的,那么叉乘之后将会产生3个互相正交的向量,接下来的学习过程中会非常有用,下面你会看到两个正交向量A和B叉积:

矩阵加减

矩阵和标量之间的加减乘除定义如下:

矩阵与矩阵之间的加减就是两个矩阵对应元素的加减运算,所以总体的规则和与标量运算是差不多的,我们看看两个2×2矩阵是怎样相加的:

矩阵相乘

矩阵乘法基本上意味着遵照规定好的法则进行相乘,当然,相乘还有一些限制:

  • 1、只有当左侧矩阵的列数与右侧矩阵的行数相等,两个矩阵才能相乘。
  • 2、矩阵相乘不遵守交换律,也就是说A * B != B * A

我们先看一个两个2×2矩阵相乘的例子:

如果刚开始不理解,我们用一个更大的例子来尝试理解。试着使用颜色来寻找规律。如果用笔计算,我相信你很快就能掌握它们。

可以看出矩阵相乘非常的繁琐,所以我们一般都通过封装好的变换函数来实现图形变换,但是理解里面的实现,还是很有必要的,而且很乐意自己动手实现。

矩阵和向量相乘

目前为止,我们已经了解了向量和矩阵,我们可以用向量来表示位置、表示颜色、甚至是纹理坐标,我们可以试着将向量理解成 N x 1 向量,N表示向量分量的个数,如果你仔细思考一下就会明白,如果我们有一个M x N的矩阵,就能用这个矩阵乘以我们N x 1的向量,因为这个矩阵的列数等于向量的行数,所以他们就能相乘。

但是我们为什么这么关心矩阵是否能乘以一个向量呢?因为我们可以用某个变换矩阵乘以我们的向量就能变换这个向量,就比如说我们刚提到的位置、颜色甚至纹理坐标,这将会引出很多有趣的例子。

缩放

位移

X,Y,Z轴旋转

任意轴旋转(Rx,Ry,Rz)

利用矩阵旋转很可能会引发万向节死锁,有关于这个问题后面我们再讨论。

矩阵的组合

使用矩阵我们可以把多个变换组合到一个矩阵中,生成一个组合矩阵。假设我们有一个顶点(x, y, z),我们希望将其缩放2倍,然后位移(1, 2, 3)个单位。我们需要一个位移和缩放矩阵来完成这些变换。结果的变换矩阵看起来像这样:

需要注意的是,当矩阵相乘时是不满足乘法交换律的,这意味着他们的顺序很重要,建议在组合矩阵时,先进行缩放操作,然后是旋转,最后才是位移,否则它们会(消极地)互相影响。比如,如果你先位移再缩放,位移的向量也会同样被缩放(译注:比如向某方向移动2米,2米也许会被缩放成1米)!,最后结果变换矩阵如下:

向量先缩放两倍,然后位移了(1,2,3)个单位。

实践

现在为止我们已经理解了变换背后的理论知识,需要我们动手去实践,实现自己的变换函数,也可以使用GLM(OpenGL Mathematics),专门为OpenGL打造的数学库,接下来我们可以运用起来去实现更多有意思的场景。

Demo下载地址,欢迎交流