PixiJS 渲染引擎
概述
PixiJS 是一款轻量级、高性能的 2D 渲染引擎,基于 WebGL 和 WebGPU 技术构建。它将底层图形 API 的复杂性封装成简洁易用的 JavaScript 接口,使开发者能够快速创建交互式 2D 图形、动画和游戏。PixiJS 支持精灵(Sprite)、图形(Graphics)、文本(Text)、粒子系统、滤镜与混合模式等丰富功能,是目前最流行的 2D Web 渲染库之一。
WebGL 渲染管线基础
要理解 PixiJS 的工作原理,需要先了解 WebGL 渲染管线。WebGL 是基于 OpenGL ES 2.0 的浏览器图形 API,其渲染管线分为以下几个阶段:
顶点着色器
顶点着色器(Vertex Shader)负责处理每个顶点的数据。它接收顶点位置、颜色、法线等属性,执行坐标变换(如模型-视图-投影变换),最终输出裁剪空间坐标。典型的顶点着色器代码如下:
attribute vec2 aVertexPosition;
uniform mat3 projectionMatrix;
void main() {
gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
}PixiJS 内部维护了一套默认着色器(基于 PIXI.Shader),开发者通常无需手动编写 GLSL 代码。
片元着色器
片元着色器(Fragment Shader)决定每个像素的最终颜色。它接收从顶点着色器插值而来的数据,执行光照计算、纹理采样、颜色混合等操作:
varying vec4 vColor;
uniform sampler2D uSampler;
varying vec2 vTextureCoord;
void main() {
gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;
}帧缓冲
帧缓冲(Framebuffer)是 WebGL 用于离屏渲染的机制。PixiJS 在实现滤镜和混合模式时,会频繁使用帧缓冲进行中间渲染,再将结果绘制到主画布上。每个 PIXI.Filter 本质上就是一个帧缓冲渲染管线。
核心 API
Application
PIXI.Application 是 PixiJS 应用的入口,它封装了渲染器、舞台、Ticker 和 DOM 挂载:
const app = new PIXI.Application({
width: 800,
height: 600,
backgroundColor: 0x0a0a1a,
antialias: true,
resolution: window.devicePixelRatio || 1
});
document.body.appendChild(app.view);app.view 是 <canvas> 元素,需要手动添加到 DOM 中。app.ticker 提供游戏循环,每帧自动调用注册的回调函数。
Sprite
Sprite(精灵)是 PixiJS 中最常用的显示对象,用于渲染纹理(Texture)。纹理可以来自图片、Canvas 或者 RenderTexture:
// 从图片创建纹理
const texture = PIXI.Texture.from('path/to/image.png');
const sprite = new PIXI.Sprite(texture);
sprite.x = 100;
sprite.y = 200;
sprite.anchor.set(0.5); // 中心锚点
sprite.scale.set(2);
sprite.rotation = Math.PI / 4;
app.stage.addChild(sprite);Graphics
Graphics 提供程序化绘制几何图形的能力,无需外部图片资源:
const graphics = new PIXI.Graphics();
graphics.beginFill(0xff6b6b, 0.8);
graphics.drawRoundedRect(0, 0, 100, 60, 8);
graphics.endFill();
graphics.lineStyle(2, 0xffffff, 0.5);
graphics.drawCircle(200, 30, 25);Graphics 在绘制复杂形状时会产生大量顶点,如果需要在动画中频繁更新,建议使用 PIXI.Mesh 或更新几何体而非重新绘制。
Text
Text 用于渲染文本,支持位图文本和系统文本两种模式:
const text = new PIXI.Text('Hello PixiJS', {
fontFamily: 'Arial',
fontSize: 32,
fill: 0xffffff,
stroke: 0x000000,
strokeThickness: 2,
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowBlur: 4,
dropShadowDistance: 2,
});位图文本(BitmapText)性能更高,适合大量动态文本场景。
容器与层级管理
PIXI.Container 是显示对象的容器,可以包含 Sprite、Graphics、Text 等其他显示对象。容器自身也是一个显示对象,支持嵌套结构:
const container = new PIXI.Container();
container.x = 400;
container.y = 300;
const child = new PIXI.Sprite(texture);
container.addChild(child);
app.stage.addChild(container);层级顺序由 addChild 的添加顺序决定,后添加的显示在上层。可以通过 addChildAt、setChildIndex、swapChildren 等方法调整层级。容器的变换属性(position、rotation、scale)会传递给所有子对象,形成一个场景图。
滤镜与混合模式
滤镜
PixiJS v7 使用 PIXI.Filter 实现滤镜效果。内置滤镜位于 @pixi/filter-* 系列包中。开发者也可以编写自定义滤镜:
// 使用内置模糊滤镜(需安装 @pixi/filter-blur)
const blurFilter = new PIXI.BlurFilter();
blurFilter.blur = 4;
sprite.filters = [blurFilter];
// 多个滤镜叠加
sprite.filters = [
new PIXI.ColorMatrixFilter(),
new PIXI.BlurFilter()
];自定义滤镜需要编写 GLSL 着色器代码:
const fragSrc = `
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
void main() {
vec4 color = texture2D(uSampler, vTextureCoord);
gl_FragColor = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b, color.a);
}
`;
const invertFilter = new PIXI.Filter(null, fragSrc);混合模式
PixiJS 支持标准的 WebGL 混合模式,通过 blendMode 属性设置:
sprite.blendMode = PIXI.BLEND_MODES.ADD; // 叠加混合
sprite.blendMode = PIXI.BLEND_MODES.MULTIPLY; // 正片叠底
sprite.blendMode = PIXI.BLEND_MODES.SCREEN; // 滤色常用的混合模式包括:
NORMAL:默认,源覆盖目标ADD:颜色值相加,适合粒子发光效果MULTIPLY:正片叠底,适合阴影SCREEN:滤色,适合高光
粒子系统实现
PixiJS 实现粒子系统有多种策略,以下是两种常见方案:
基于 Graphics 的简单粒子
适合粒子数量不多(几千个以内)的场景。每个粒子是一个 Graphics 对象,在主循环中更新位置、透明度等属性。
基于 ParticleContainer 的优化粒子
PIXI.ParticleContainer 是专门为大量粒子优化的容器,牺牲了部分显示对象功能(如独立旋转、锚点)来换取性能提升:
const particleContainer = new PIXI.ParticleContainer(10000, {
scale: true,
position: true,
rotation: false,
uvs: false,
alpha: true
});
// 添加精灵作为粒子
for (let i = 0; i < 5000; i++) {
const particle = PIXI.Sprite.from('particle.png');
particle.x = Math.random() * 800;
particle.y = Math.random() * 600;
particleContainer.addChild(particle);
}
app.stage.addChild(particleContainer);性能对比
| 方案 | 粒子数量上限 | 功能完整性 | 内存占用 |
|---|---|---|---|
| Graphics 粒子 | ~3000 | 高 | 高 |
| Sprite + Container | ~5000 | 高 | 中 |
| ParticleContainer | ~50000 | 低 | 低 |
| 自定义 Mesh | ~100000 | 最低 | 最低 |
对于烟花、爆炸、星云等需要数千到数万粒子的效果,推荐使用 ParticleContainer 或自定义 Mesh。
性能调优策略
减少绘制调用
PixiJS 的渲染性能瓶颈通常在于绘制调用(Draw Call)数量。优化策略包括:
- 纹理图集(Texture Atlas):将多个小图合并为一张大图,减少纹理切换次数
- 批处理(Batching):PixiJS 自动将使用相同纹理和混合模式的显示对象合并为一次绘制调用
- 避免频繁调用 Graphics:静态图形使用 RenderTexture 缓存为纹理
渲染配置优化
const app = new PIXI.Application({
powerPreference: 'high-performance', // 优先使用独立 GPU
antialias: false, // 关闭抗锯齿以提升性能
resolution: Math.min(devicePixelRatio, 2), // 限制最大分辨率
backgroundColor: 0x000000,
});Ticker 优化
- 合理控制 Ticker 的 FPS:
app.ticker.maxFPS = 60 - 不在 Ticker 回调中执行耗时同步操作
- 使用对象池(Object Pool)复用粒子对象,避免频繁创建和销毁
内存管理
- 不再使用的纹理调用
texture.destroy(true) - 移除显示对象后调用
displayObject.destroy({ children: true, texture: true }) - 使用
PIXI.utils.destroyTextureCache()清理纹理缓存
实际案例:粒子烟花秀
下面是一个基于 PixiJS v7 的交互式烟花秀 Demo,展示了粒子系统、容器管理和 Ticker 动画的综合应用:
总结
PixiJS 通过封装 WebGL 的复杂性,让 2D 图形开发变得直观高效。掌握其核心渲染管线、显示对象体系、容器层级管理、滤镜与混合模式、粒子系统以及性能调优策略,是构建高质量交互式图形应用的关键。从简单的数据可视化到复杂的游戏开发,PixiJS 都能提供出色的开发体验和运行时性能。