WebGL是一套基于OpenGL ES的浏览器3D图形渲染接口,无需安装额外插件,仅通过JavaScript和HTML5的<canvas>元素就能调用GPU完成高性能3D图形绘制。它广泛应用于网页3D游戏、数据可视化、虚拟展厅等场景,是前端实现复杂3D效果的核心技术之一。

WebGL渲染的基础准备
要使用WebGL进行渲染,首先需要准备一个<canvas>元素作为渲染容器,然后获取WebGL上下文,这是所有WebGL操作的基础入口。
1. 创建画布与获取上下文
在HTML中先定义<canvas>元素,再通过JavaScript获取该元素的WebGL上下文:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>WebGL 3D渲染示例</title>
<style>
canvas {
border: 1px solid #ccc;
display: block;
margin: 20px auto;
}
</style>
</head>
<body>
<canvas id="glCanvas" width="800" height="600"></canvas>
<script src="main.js"></script>
</body>
</html>
对应的JavaScript获取上下文代码:
// 获取canvas元素
const canvas = document.getElementById('glCanvas');
// 获取WebGL上下文,兼容不同浏览器
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
if (!gl) {
console.error('当前浏览器不支持WebGL');
return;
}
2. 设置视口与清屏颜色
获取上下文后,需要先设置渲染视口范围,同时定义清空画布时使用的背景颜色:
// 设置视口为整个canvas区域 gl.viewport(0, 0, canvas.width, canvas.height); // 设置清屏颜色为深灰色,参数依次为RGBA,范围0-1 gl.clearColor(0.1, 0.1, 0.1, 1.0); // 清空颜色缓冲区 gl.clear(gl.COLOR_BUFFER_BIT);
WebGL着色器程序编写
WebGL采用可编程渲染管线,核心逻辑需要通过着色器实现,分为顶点着色器和片元着色器两部分,两者都需要用GLSL ES语言编写,再通过JavaScript编译、链接为可执行的程序。
1. 顶点着色器
顶点着色器负责处理每个顶点的位置、颜色等属性,这里我们先实现一个简单的顶点着色器,直接传递顶点位置:
// 顶点着色器GLSL代码
const vertexShaderSource = `
attribute vec4 aPosition;
void main() {
// 直接将顶点位置赋值给内置的输出变量gl_Position
gl_Position = aPosition;
// 设置顶点大小
gl_PointSize = 10.0;
}
`;
2. 片元着色器
片元着色器负责处理每个像素的颜色,这里设置绘制的图形为白色:
// 片元着色器GLSL代码
const fragmentShaderSource = `
precision mediump float;
void main() {
// 设置片元颜色为白色
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
3. 编译与链接着色器
编写完着色器代码后,需要通过JavaScript完成编译、链接为着色器程序的流程:
// 编译着色器的通用函数
function compileShader(gl, source, type) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
// 检查编译是否成功
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('着色器编译失败:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
// 编译顶点着色器和片元着色器
const vertexShader = compileShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
const fragmentShader = compileShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
// 创建着色器程序并链接
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
// 检查链接是否成功
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('着色器程序链接失败:', gl.getProgramInfoLog(program));
return;
}
// 使用当前着色器程序
gl.useProgram(program);
传递顶点数据并绘制3D图形
着色器程序准备完成后,需要把顶点数据传递给GPU,然后触发绘制命令。这里我们先绘制一个简单的三角形作为3D渲染的基础示例。
1. 创建顶点缓冲区并传递数据
需要把三角形的三个顶点位置数据存储到缓冲区对象中,再关联到着色器的属性变量:
// 三角形三个顶点的坐标,范围在-1到1之间(WebGL归一化坐标系)
const vertices = new Float32Array([
0.0, 0.5, 0.0, // 顶点1:上方
-0.5, -0.5, 0.0, // 顶点2:左下方
0.5, -0.5, 0.0 // 顶点3:右下方
]);
// 创建缓冲区对象
const vertexBuffer = gl.createBuffer();
// 绑定缓冲区到ARRAY_BUFFER目标
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// 向缓冲区写入顶点数据
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 获取着色器中aPosition属性的位置
const aPositionLocation = gl.getAttribLocation(program, 'aPosition');
// 告诉WebGL如何解析缓冲区中的数据
gl.vertexAttribPointer(aPositionLocation, 3, gl.FLOAT, false, 0, 0);
// 启用aPosition属性
gl.enableVertexAttribArray(aPositionLocation);
2. 执行绘制命令
所有准备完成后,调用绘制函数就能在画布上看到渲染结果:
// 清空画布 gl.clear(gl.COLOR_BUFFER_BIT); // 绘制三角形,参数依次为绘制模式、起始顶点索引、顶点数量 gl.drawArrays(gl.TRIANGLES, 0, 3);
3D变换基础
上面的示例是2D平面的三角形,要实现真正的3D效果,需要引入模型矩阵、视图矩阵、投影矩阵等变换,这里以简单的旋转变换为例,修改顶点着色器实现三角形绕Z轴旋转:
// 修改后的顶点着色器,增加旋转矩阵逻辑
const vertexShaderSource3D = `
attribute vec4 aPosition;
uniform float uRotationAngle; // 旋转角度,弧度制
void main() {
// 绕Z轴旋转矩阵
float cosA = cos(uRotationAngle);
float sinA = sin(uRotationAngle);
mat4 rotationMatrix = mat4(
cosA, sinA, 0.0, 0.0,
-sinA, cosA, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
// 顶点乘以旋转矩阵
gl_Position = rotationMatrix * aPosition;
gl_PointSize = 10.0;
}
`;
对应的JavaScript中传递旋转角度的逻辑:
// 获取uniform变量uRotationAngle的位置
const uRotationAngleLocation = gl.getUniformLocation(program, 'uRotationAngle');
let angle = 0;
// 动画循环函数
function animate() {
// 角度递增
angle += 0.01;
// 传递角度给着色器
gl.uniform1f(uRotationAngleLocation, angle);
// 清空画布
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);
// 请求下一帧动画
requestAnimationFrame(animate);
}
// 启动动画
animate();
常见问题与注意事项
- WebGL坐标系是归一化的,x、y、z轴范围都是-1到1,超出范围的图形会被裁剪。
- 着色器代码中的变量如果声明了但未使用,部分浏览器会报错,需要避免冗余变量。
- 缓冲区对象使用完成后可以调用
gl.deleteBuffer()释放资源,避免内存泄漏。 - 如果绘制黑色图形,大概率是片元着色器颜色设置错误或者未正确启用着色器程序。
WebGLJavaScript3D_graphics图形渲染修改时间:2026-07-08 20:24:39