WebGL 矩阵相乘

799 阅读2分钟

源码:github.com/buglas/webg…

矩阵相乘可以实现复合变换,就比如先位移再旋转、先旋转在位移,或着连续位移。

接下来咱们先看一下两个矩阵是如何相乘的。

矩阵乘以矩阵的结果还是矩阵,我们可以通过矩阵库验证一下矩阵相乘的规律。

1.使用three.js的Matrix4 对象建立矩阵

const a=new Matrix4().set(
    0, 1, 2, 3,
    4, 5, 6, 7,
    8, 9, 10,11,
    12,13,14,15
)
const b=new Matrix4().set(
    0,  10, 20, 30,
    40, 50, 60, 70,
    80, 90, 100,110,
    120,130,140,150
)

注:set()方法里输入的矩阵是行主序的,但elements 输出的矩阵是列主序的。

const ca=a.elements
console.log(ca);

[
    0, 4, 8,  12, 
    1, 5, 9,  13, 
    2, 6, 10, 14, 
    3, 7, 11, 15
]
const cb=b.elements
console.log(cb);

[
    0,  40, 80, 120, 
    10, 50, 90, 130, 
    20, 60, 100, 140, 
    30, 70, 110, 150
]

2.让矩阵a乘以矩阵b

const c=a.multiply(b)
console.log(c.elements);

[
    560, 1520, 2480, 3440, 
    620, 1740, 2860, 3980, 
    680, 1960, 3240, 4520, 
    740, 2180, 3620, 5060
]

分析一下结果

560=0*0 +1*40+2*80 +3*120
620=0*10+1*50+2*90 +3*130
680=0*20+1*60+2*100+3*140
740=0*30+1*70+2*110+3*150

1520=4*0 +5*40+6*80 +7*120
1740=4*10+5*50+6*90 +7*130
……

到此,我们应该能总结出矩阵a乘以矩阵b规律,以列主序的ca、cb为例:

先遍历ca的每一列,再遍历cb的每一行,将ca的每一列乘以cb的每一行,按照列主序排列后得到的结果。

或者,先遍历ca的每一行,再遍历cb的每一列,将ca的每一行乘以cb的每一列,按照行主序排列后得到的结果。

我们验证一下后者:

const cc=[]
for(let y=0;y<16;y+=4){
    const [ax,ay,az,aw]=[ca[y],ca[y+1],ca[y+2],ca[y+3]]
    for (let x=0;x<4;x++){
        console.log(x);
        const [bx,by,bz,bw]=[cb[x],cb[x+4],cb[x+8],cb[x+12]]
        cc.push(ax*bx+ay*by+az*bz+aw*bw)
    }
}
console.log(cc);

[
    560, 1520, 2480, 3440, 
    620, 1740, 2860, 3980, 
    680, 1960, 3240, 4520, 
    740, 2180, 3620, 5060
]

其结果和矩阵库一致。

3.通过上面的规则可知,矩阵的乘法不满足结合律,即矩阵a乘以矩阵b不一定等于矩阵b乘以矩阵a。