WebGL 2026-05-28 12 min read 6100 Reads
打破DOM的局限:用 WebGL 2.0 在网页端操控十万粒子
前端界面的终点不止于 DOM 节点。当你要渲染一万个、十万个独立粒子,并让它们根据鼠标的引力和排斥力实时移动时,常规的 DOM 元素甚至普通的 2D Canvas 上下文都会瞬间卡死。
这时候,我们需要请出浏览器底层的超级引擎:WebGL 2.0。
1. 为什么 DOM 会卡死?
DOM(文档对象模型)在设计之初是为了承载结构化的文本和多媒体内容。每个 DOM 节点都带着极其厚重的内存开销(包括样式计算、布局、图层合并、事件监听器等)。 而 WebGL 则是直接与操作系统的显卡驱动进行对话。在 WebGL 中,没有所谓的“标签”或“卡片”,有的只是顶点(Vertices)、像素着色器(Fragment Shaders)和在内存中流动的浮点数数组。
2. GPU 物理模拟的核心思路:在着色器中运行算法
在传统的 CPU 渲染中,我们通过 requestAnimationFrame 循环,遍历一个包含十万个 JavaScript 对象的数组,在每一次循环中计算它们的新坐标:
// ❌ 传统做法:在 CPU 中循环计算,十万粒子会导致极大的主线程阻塞
particles.forEach(p => {
p.x += p.vx;
p.y += p.vy;
});
而高效的 WebGL 做法,是将粒子所有的初始坐标、速度、加速度打包成二进制缓冲区(VBO - Vertex Buffer Object),一次性灌入 GPU 的显存中。 接着,通过 Vertex Shader(顶点着色器) 直接在 GPU 核心中并行计算每个粒子的新位置。如果一块显卡有 2048 个着色内核,那它就能同时计算 2048 个粒子的位置,计算效率将获得成百上千倍的提升。
3. 着色器代码极简窥探
以下是实现“鼠标排斥力”的顶点着色器伪代码:
#version 300 es
in vec2 a_position;
in vec2 a_velocity;
uniform vec2 u_mouse;
uniform float u_time;
out vec4 v_color;
void main() {
vec2 pos = a_position;
// 计算粒子到鼠标的距离
float dist = distance(pos, u_mouse);
if (dist < 0.2) {
// 计算排斥力向量
vec2 dir = normalize(pos - u_mouse);
float force = (0.2 - dist) * 1.5;
pos += dir * force;
}
gl_Position = vec4(pos, 0.0, 1.0);
gl_PointSize = 2.0;
}
4. 极致视觉的克制表达
在极简风格的网站中,千万不要把粒子背景做得花哨繁杂。最优雅的呈现应当是:
- 单色微调:粒子颜色与背景色保持极近的层次关系。例如背景是
#0a0a0a,粒子可以设计为半透明的rgba(255,255,255, 0.08),只有在鼠标靠近时,它才亮起为rgba(255,255,255, 0.35)。 - 隐藏连线:仅在粒子相距极近时绘制一条细如发丝的半透明连线,呈现出如同神经元网格或宇宙尘埃般的隐约质感。
这种在克制中藏着磅礴力量的设计,正是高端工程师最爱展示的“低调的前端炫技”。
#WebGL#GPU Physics#Performance#Canvas