八、矩阵

200 阅读1分钟

上节我们学习了平移、旋转、缩放这三种基础的图形变换公式,这些公式可以分别通过矩阵来实现,具体推导逻辑可详查资料,此处不做赘述。

一、矩阵介绍

矩阵 * 矢量 = 新矩阵

\left[
 \begin{matrix}
   x'' \\
   y'' \\
   z'' \\
  \end{matrix}
  \right] = \left[
 \begin{matrix}
   a & b & c\\
   d & e & f\\
   g & h & i\\
  \end{matrix}
  \right] \left[
 \begin{matrix}
   x \\
   y \\
   z \\
  \end{matrix}
  \right]
x'' = ax + by + cz
y'' = dx + ey + fz
z'' = gx + hy + iz

(1)矩阵乘法不符合交换律 A*B != B*A
(2)只有矩阵的列数=矢量的行数,才能相乘

二、常用矩阵

旋转矩阵

\left[
 \begin{matrix}
   x'' \\
   y'' \\
   z'' \\
  \end{matrix}
  \right] = \left[
 \begin{matrix}
   cosB & -sinB & 0\\
   sinB & cosB & 0\\
   0 & 0 & 1\\
  \end{matrix}
  \right] \left[
 \begin{matrix}
   x \\
   y \\
   z \\
  \end{matrix}
  \right]

4x4旋转矩阵

\left[
 \begin{matrix}
   x'' \\
   y'' \\
   z'' \\
   1 \\
  \end{matrix}
  \right] = \left[
 \begin{matrix}
   cosB & -sinB & 0 & 0\\
   sinB & cosB & 0 & 0\\
   0 & 0 & 1 & 0\\
   0 & 0 & 0 & 1\\
  \end{matrix}
  \right] \left[
 \begin{matrix}
   x \\
   y \\
   z \\
   1 \\
  \end{matrix}
  \right]

平移矩阵

\left[
 \begin{matrix}
   x'' \\
   y'' \\
   z'' \\
   1 \\
  \end{matrix}
  \right] = \left[
 \begin{matrix}
   1 & 0 & 0 & Tx\\
   0 & 1 & 0 & Ty\\
   0 & 0 & 1 & Tz\\
   0 & 0 & 0 & 1\\
  \end{matrix}
  \right] \left[
 \begin{matrix}
   x \\
   y \\
   z \\
   1 \\
  \end{matrix}
  \right]

缩放矩阵

\left[
 \begin{matrix}
   x'' \\
   y'' \\
   z'' \\
   1 \\
  \end{matrix}
  \right] = \left[
 \begin{matrix}
   Sx & 0 & 0 & 0\\
   0 & Sy & 0 & 0\\
   0 & 0 & Sz & 0\\
   0 & 0 & 0 & 1\\
  \end{matrix}
  \right] \left[
 \begin{matrix}
   x \\
   y \\
   z \\
   1 \\
  \end{matrix}
  \right]

三、关键代码

var VSHADER_SOURCE =
    'attribute vec4 a_Position;\n' +
    #mat4 表示 4x4矩阵类型
    'uniform mat4 u_xformMatrix;\n' +
    'void main() {\n' +
    '  gl_Position = u_xformMatrix * a_Position;\n' +
    '}\n';
    
var ANGLE = 90.0;

function main() {
    ···
    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        console.log('Failed to intialize shaders.');
        return;
    }
    var n = initVertexBuffers(gl);
    var radian = Math.PI * ANGLE / 180.0; 
    var cosB = Math.cos(radian), sinB = Math.sin(radian);
    #列主序
    var xformMatrix = new Float32Array([
        cosB, sinB, 0.0, 0.0,
        -sinB, cosB, 0.0, 0.0,
        0.0,  0.0, 1.0, 0.0,
        0.0,  0.0, 0.0, 1.0
    ]);


    #u_xformMatrix
    var u_xformMatrix = gl.getUniformLocation(gl.program, 'u_xformMatrix');
    #将旋转矩阵传输给顶点着色器
    gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, n);
}

内置方法说明

1、 gl.uniformMatrix4fv(location, transpose, array)

将array表示的4x4矩阵分配给由location指向的uniform变量

参数

(1) location 存储位置
(2) transpose WebGL中为false,表示是否转置矩阵(WebGL中未实现该方法)
(1) array 类型化数组 4x4矩阵列主序存储在其中

(1)gl.uniformMatrix4fv()中的'v'表示可向着色器传输多个数据值
(2)js中未提供表示矩阵的类型,所以用类型化数组Float32Array表示矩阵,矩阵是二维的,数组是一维的; 在数组中存储矩阵元素有两种方式:列主序和行主序; 在WebGL和OpenGL中采用列主序。