返回
WebGL图形变换轻松学,掌握矩阵,纵横3D世界
前端
2023-10-31 17:29:15
序言
大家好,我是广州小井,上一节我们初步认识了矩阵的数学基础,但我们还不知道学来干嘛?那这一节我们马不停蹄的来应用矩阵进行实战!
矩阵在WebGL中的作用
在WebGL中,矩阵主要用于对物体进行变换,包括平移、旋转和缩放。通过矩阵变换,我们可以轻松实现物体在3D世界中的移动、旋转和缩放效果。
平移矩阵
平移矩阵用于将物体在X、Y和Z轴上进行平移。平移矩阵的数学形式为:
[1 0 0 x]
[0 1 0 y]
[0 0 1 z]
[0 0 0 1]
其中,x、y和z是物体在X、Y和Z轴上的平移距离。
旋转矩阵
旋转矩阵用于将物体绕X、Y和Z轴进行旋转。旋转矩阵的数学形式为:
[cosθ 0 sinθ 0]
[0 1 0 0]
[-sinθ 0 cosθ 0]
[0 0 0 1]
其中,θ是物体绕X轴旋转的角度,φ是物体绕Y轴旋转的角度,ω是物体绕Z轴旋转的角度。
缩放矩阵
缩放矩阵用于将物体在X、Y和Z轴上进行缩放。缩放矩阵的数学形式为:
[sx 0 0 0]
[0 sy 0 0]
[0 0 sz 0]
[0 0 0 1]
其中,sx、sy和sz是物体在X、Y和Z轴上的缩放比例。
应用实例
现在,我们已经了解了平移矩阵、旋转矩阵和缩放矩阵的基本知识,接下来,我们来看看如何将它们应用到WebGL中。
首先,我们需要创建一个WebGL上下文,然后加载顶点着色器和片段着色器。接着,我们需要创建一个缓冲区对象来存储顶点数据,并创建一个纹理对象来存储纹理数据。最后,我们需要编写JavaScript代码来控制矩阵变换,并将其应用到物体上。
// 创建WebGL上下文
const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');
// 加载顶点着色器和片段着色器
const vertexShaderSource = `
attribute vec3 position;
attribute vec2 texcoord;
varying vec2 vTexcoord;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
void main() {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
vTexcoord = texcoord;
}
`;
const fragmentShaderSource = `
precision mediump float;
varying vec2 vTexcoord;
uniform sampler2D texture;
void main() {
gl_FragColor = texture2D(texture, vTexcoord);
}
`;
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);
// 获取属性位置
const positionAttributeLocation = gl.getAttribLocation(program, 'position');
const texcoordAttributeLocation = gl.getAttribLocation(program, 'texcoord');
// 获取uniform位置
const modelMatrixUniformLocation = gl.getUniformLocation(program, 'modelMatrix');
const viewMatrixUniformLocation = gl.getUniformLocation(program, 'viewMatrix');
const projectionMatrixUniformLocation = gl.getUniformLocation(program, 'projectionMatrix');
// 创建缓冲区对象
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0
]), gl.STATIC_DRAW);
const texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.5, 1.0
]), gl.STATIC_DRAW);
// 创建纹理对象
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
255, 0, 0, 255
]));
// 设置视口
gl.viewport(0, 0, canvas.width, canvas.height);
// 清除颜色缓冲区
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// 启用顶点属性
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(texcoordAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.vertexAttribPointer(texcoordAttributeLocation, 2, gl.FLOAT, false, 0, 0);
// 激活程序对象
gl.useProgram(program);
// 设置uniform值
const modelMatrix = new Float32Array([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
]);
gl.uniformMatrix4fv(modelMatrixUniformLocation, false, modelMatrix);
const viewMatrix = new Float32Array([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
]);
gl.uniformMatrix4fv(viewMatrixUniformLocation, false, viewMatrix);
const projectionMatrix = new Float32Array([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
]);
gl.uniformMatrix4fv(projectionMatrixUniformLocation, false, projectionMatrix);
// 绑定纹理
gl.bindTexture(gl.TEXTURE_2D, texture);
// 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);
这段代码首先创建了一个WebGL上下文,然后加载顶点着色器和片段着色器。接着,它创建了一个缓冲区对象来存储顶点数据,并创建一个纹理对象来存储纹理数据。最后,它编写了JavaScript代码来控制矩阵变换,并将其应用到物体上。
结语
通过矩阵变换,我们可以轻松实现物体在3D世界中的移动、旋转和缩放