基础-矩阵
基本变换矩阵(transformation matrix)
旋转矩阵
3X3 版本:
4X4 版本:
平移矩阵
缩放矩阵
WebGL中的矩阵
在 webgl 中,矩阵是列主序的, 也就是说,一个旋转矩阵应当如下. 此外, webgl 着色器内部内置了矩阵的运算, 以便为图形计算提供便利
//注意. WebGL中矩阵是列主序的
let 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
]);

魔法矩阵: 逆转置矩阵
对顶点进行变换的矩阵称为模型矩阵. 如何计算变换之后的法向量呢, 只要将变换之前的法向量乘以模型矩阵的 逆转置矩阵(inverse transpose mastrix) 即可.
逆转置矩阵, 就是逆矩阵的转置. 逆矩阵的意思是 M*R=E, 其中矩阵 R 就是矩阵 M 的逆, 或者说 M 和 R 互逆.
Matrix4 对象提供了便捷的方法来完成上述任务:
假如模型矩阵存储在modelMatrix对象中, 下面这段代码将会计算它的逆转置矩阵, 并将其存储在normalMatrix对象中:
Matrix4 normalMatrix=new Matrix4();
//计算模型矩阵
...
//根据模型矩阵计算用来变换法向量的矩阵
normalMatrix.setInverseOf(modelMatrix);
normalMatrix.transpose();
下面来看看示例程序, 该程序使立方体绕 z 轴顺时针旋转 90 度, 然后沿 y 轴平移 0.9 个单位, 并且处于平行光和环境光的照射下.
// LightedTranslatedRotatedCube.js (c) 2012 matsuda
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'attribute vec4 a_Normal;\n' +
'uniform mat4 u_MvpMatrix;\n' +
'uniform mat4 u_NormalMatrix;\n' + //用来变换法向量的矩阵
'uniform vec3 u_LightColor;\n' + //光的颜色
'uniform vec3 u_LightDirection;\n' + //归一化的世界坐标
'uniform vec3 u_AmbientLight;\n' + // 环境光颜色
'varying vec4 v_Color;\n' +
'void main() {\n' +
' gl_Position = u_MvpMatrix * a_Position;\n' +
// 计算变换后的法向量并归一化
' vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' +
// 计算光线方向和法向量的点击
' float nDotL = max(dot(u_LightDirection, normal), 0.0);\n' +
//计算漫反射光的颜色
' vec3 diffuse = u_LightColor * a_Color.rgb * nDotL;\n' +
// 计算环境光产生的反射光的颜色
' vec3 ambient = u_AmbientLight * a_Color.rgb;\n' +
// 将以上两个相加作为最终的颜色
' v_Color = vec4(diffuse + ambient, a_Color.a);\n' +
'}\n';
...
function main() {
...
// 获取unifrom等变量的地址
var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
...
// 计算模型矩阵
modelMatrix.setTranslate(0, 0.9, 0); // 沿Y轴平移
modelMatrix.rotate(90, 0, 0, 1); // 绕Z轴旋转
// 计算模型视图投影矩阵
mvpMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);
mvpMatrix.lookAt(3, 3, 7, 0, 0, 0, 0, 1, 0);
mvpMatrix.multiply(modelMatrix);
// 将模型视图投影矩阵传给u_MvpMatrix变量
gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
//根据模型矩阵计算用来变换法向量的矩阵
normalMatrix.setInverseOf(modelMatrix);
normalMatrix.transpose();
//将用来变换法向量的矩阵传给u_NormalMatrix
gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);
...
}
顶点着色器的流程与前面的程序类型, 区别在于, 本例根据前述的规则先用模型矩阵的逆转置矩阵对a_Normal进行了变换, 再赋值给normal, 而不是直接赋值.