返回
WebGL矩阵操纵指南:释放图形学的真实潜力
前端
2023-11-11 14:31:03
WebGL矩阵简介
WebGL中的矩阵是一个用于表示空间变换的数学对象,它可以物体的位移、旋转和缩放。矩阵通常由一个由16个数字排列成的4x4方阵表示,其中前3列对应于x、y和z轴的基向量,而第4列对应于平移向量。
变换矩阵
变换矩阵用于将物体从一个位置移动到另一个位置。变换矩阵可以分为三种类型:平移、旋转和缩放。
- 平移矩阵 :平移矩阵用于将物体沿x、y或z轴移动一定距离。
- 旋转矩阵 :旋转矩阵用于将物体绕x、y或z轴旋转一定角度。
- 缩放矩阵 :缩放矩阵用于将物体沿x、y或z轴缩放一定比例。
实例代码:使用变换矩阵创建3D立方体
// 创建一个 WebGL 上下文
const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl');
// 创建一个 WebGL 程序
const vertexShaderSource = `
attribute vec3 a_position;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_projectionMatrix;
void main() {
gl_Position = u_projectionMatrix * u_modelViewMatrix * vec4(a_position, 1.0);
}
`;
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
// 告诉 WebGL 使用这个程序
gl.useProgram(program);
// 创建一个缓冲区对象来存储顶点数据
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
// 获取 attribute 变量的存储位置
const positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
// 创建一个uniform变量来存储模型视图矩阵
const modelViewMatrixLocation = gl.getUniformLocation(program, "u_modelViewMatrix");
// 创建一个模型视图矩阵
const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [0.0, 0.0, -3.0]);
// 将模型视图矩阵传递给uniform变量
gl.uniformMatrix4fv(modelViewMatrixLocation, false, modelViewMatrix);
// 创建一个 uniform 变量来存储投影矩阵
const projectionMatrixLocation = gl.getUniformLocation(program, "u_projectionMatrix");
// 创建一个投影矩阵
const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45 * (Math.PI / 180), canvas.width / canvas.height, 0.1, 100.0);
// 将投影矩阵传递给 uniform 变量
gl.uniformMatrix4fv(projectionMatrixLocation, false, projectionMatrix);
// 清空画布
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// 绘制立方体
gl.drawArrays(gl.TRIANGLES, 0, 36);
透视矩阵
透视矩阵用于将3D空间投影到2D屏幕上。透视矩阵可以分为两种类型:正交投影和透视投影。
- 正交投影 :正交投影将3D空间中的对象投影到一个平面上,无论对象离相机有多远,它们的大小都不会改变。
- 透视投影 :透视投影将3D空间中的对象投影到一个透视平面上,离相机越近的对象看起来越大,离相机越远的对象看起来越小。
实例代码:使用透视矩阵创建3D场景
// 创建一个 WebGL 上下文
const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl');
// 创建一个 WebGL 程序
const vertexShaderSource = `
attribute vec3 a_position;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_projectionMatrix;
void main() {
gl_Position = u_projectionMatrix * u_modelViewMatrix * vec4(a_position, 1.0);
}
`;
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
// 告诉 WebGL 使用这个程序
gl.useProgram(program);
// 创建一个缓冲区对象来存储顶点数据
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,