WebGL (Web Graphics Library) 是一种JavaScript API,用于在网页中渲染高性能的2D和3D图形。它基于OpenGL ES 2.0,可以在兼容的浏览器中运行,无需安装任何插件。WebGL为网页开发者提供了强大的工具来创建复杂的图形和动画,使网页应用更具交互性和视觉吸引力。本文将介绍WebGL的基础知识,并带你逐步创建一个简单的3D场景。
WebGL的基本概念
- 上下文 (Context): WebGL的所有操作都在一个WebGL上下文中进行。这个上下文由HTML5的
<canvas>
元素创建。 - 着色器 (Shaders): WebGL使用GLSL (OpenGL Shading Language) 编写的着色器程序来进行图形的渲染。主要有两种着色器:顶点着色器和片段着色器。
- 顶点着色器:负责处理每个顶点的位置。
- 片段着色器:负责处理每个像素的颜色。
WebGL开发的基本步骤
- 创建Canvas元素并获取WebGL上下文
- 定义并编译着色器程序
- 创建缓冲区并传入顶点数据
- 设置视口并清除背景
- 绘制图形
示例:创建一个简单的3D立方体
以下是一个使用WebGL创建3D立方体的基本示例:
1. 创建HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebGL 3D Cube</title>
<style>
canvas { width: 100%; height: 100%; }
</style>
</head>
<body>
<canvas id="glCanvas"></canvas>
<script src="app.js"></script>
</body>
</html>
2. 编写JavaScript文件 (app.js)
// 获取Canvas元素并初始化WebGL上下文
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
if (!gl) {
console.log('WebGL not supported, falling back on experimental-webgl');
gl = canvas.getContext('experimental-webgl');
}
if (!gl) {
alert('Your browser does not support WebGL');
}
// 定义顶点着色器
const vertexShaderSource = `
attribute vec4 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
}
`;
// 定义片段着色器
const fragmentShaderSource = `
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); // 白色
}
`;
// 创建并编译着色器
function loadShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
// 创建着色器程序并链接
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.log('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram));
}
// 获取属性和统一变量的位置
const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
},
uniformLocations: {
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
},
};
// 定义立方体的顶点数据
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,
];
// 创建缓冲区并传入数据
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
// 设置视口并清除背景
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0.0, 0.0, 0.0, 1.0); // 黑色
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// 启用深度测试
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
// 使用着色器程序
gl.useProgram(programInfo.program);
// 设置投影矩阵和模型视图矩阵
const fieldOfView = 45 * Math.PI / 180; // 弧度
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar);
const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]); // 将立方体移动到视口中
// 绑定缓冲区并传递数据
{
const numComponents = 3;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
}
// 使用统一变量传递矩阵
gl.uniformMatrix4fv(
programInfo.uniformLocations.projectionMatrix,
false,
projectionMatrix);
gl.uniformMatrix4fv(
programInfo.uniformLocations.modelViewMatrix,
false,
modelViewMatrix);
// 绘制立方体
{
const offset = 0;
const vertexCount = 8;
gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
}
总结
以上示例展示了如何使用WebGL创建一个简单的3D立方体。通过学习WebGL的基础知识和实践,你可以创建更复杂和互动的图形应用。WebGL是一个强大而灵活的工具,为网页开发带来了前所未有的图形处理能力。希望本文对你理解WebGL开发有所帮助。