关于 filters-and-postfx
面向 Phaser 4 开发者的滤镜与后期特效技能指南,介绍 WebGL 上的对象和摄像机滤镜、内部与外部处理及常见效果配置。
主要功能
- 01为游戏对象启用滤镜
- 02配置摄像机滤镜
- 03区分内部与外部滤镜
- 04按顺序组合多种效果
- 05使用遮罩与转场效果
适用场景
- 01为角色添加发光或模糊
- 02对摄像机画面进行调色
- 03制作遮罩与显露转场
- 04组合滤镜实现自定义合成
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ phaserjs/ phaser --skill filters-and-postfx安装后在 Claude Code 中输入/filters-and-postfx确认已加载。
详细介绍
Phaser 4 滤镜与后期特效
快速开始
为精灵添加辉光效果:
// In your Scene's create() method:
const sprite = this.add.sprite(400, 300, 'player');
// Step 1: Enable the filter system on the game object (WebGL only)
sprite.enableFilters();
// Step 2: Add filters via .filters.internal or .filters.external
sprite.filters.internal.addGlow(0xff00ff, 4, 0, 1);
为相机添加模糊:
// Cameras have filters enabled by default - no enableFilters() needed
const camera = this.cameras.main;
camera.filters.internal.addBlur(0, 2, 2, 1);
核心概念
v4 中滤镜的工作方式
滤镜是基于 GPU 的后期处理效果,在对象或相机渲染到纹理后应用。每个滤镜都会对该纹理运行一次着色器通道,生成最终的视觉输出。滤镜仅支持 WebGL。
带滤镜的相机的渲染管线:
- 对象渲染到与相机尺寸相同的纹理。
- 内部滤镜处理该纹理,在对象/相机局部空间中应用效果。
- 纹理绘制到与上下文尺寸相同的纹理,应用相机变换(位置、旋转、缩放)。
- 外部滤镜处理该上下文纹理,在屏幕空间中应用效果。
- 最终纹理合成到输出中。
内部滤镜与外部滤镜
每个 FilterList 都暴露两个子列表:filters.internal 和 filters.external。这一区别控制滤镜相对于相机/对象变换的运行时机:
- 内部——在相机变换之前应用。效果在对象的局部坐标空间中运行。对旋转对象施加水平模糊时,模糊会随对象一起旋转。内部滤镜仅覆盖对象/相机区域,因此开销更低。
- 外部——在相机变换之后应用。效果在屏幕空间中运行。对旋转对象施加水平模糊时,在屏幕上始终水平模糊。外部滤镜是全屏的,开销更高。
尽可能使用内部滤镜以获得更好的性能。
FilterList
FilterList(Phaser.GameObjects.Components.FilterList)是存放滤镜控制器的容器。它提供:
add(filter, index)——在可选索引处添加 Controller 实例remove(filter, forceDestroy)——移除并销毁滤镜clear()——移除并销毁所有滤镜getActive()——返回所有active === true的滤镜list——Controller 的原始数组(可安全重排序)- 便捷工厂方法:
addBlur()、addGlow()、addMask()等。
滤镜控制器
每个滤镜都是 Phaser.Filters.Controller 的子类。常见 Controller 属性:
| 属性 | 类型 | 描述 |
|---|---|---|
active | boolean | 在不移除滤镜的情况下开启/关闭它 |
camera | Camera | 拥有此滤镜的相机 |
renderNode | string | 着色器的渲染节点 ID |
paddingOverride | Rectangle | 覆盖自动内边距计算 |
ignoreDestroy | boolean | 如果为 true,则当其 FilterList 被销毁时滤镜仍保留(用于复用) |
关键方法:setActive(bool)、setPaddingOverride(left, top, right, bottom)、getPadding()、destroy()。
在游戏对象上启用滤镜
相机默认可用滤镜。游戏对象则不行——必须先调用 enableFilters():
const sprite = this.add.sprite(400, 300, 'hero');
sprite.enableFilters();
// Now sprite.filters is available
sprite.filters.internal.addGlow();
sprite.filters.external.addVignette();
enableFilters() 会在游戏对象上创建一个内部 filterCamera,负责将对象渲染到纹理以供滤镜处理。它返回 this 以支持链式调用。
启用后游戏对象上的相关属性:
| 属性 | 默认值 | 描述 |
|---|---|---|
filterCamera | null -> Camera | 用于滤镜渲染的内部相机 |
filters | null -> {internal, external} | 访问 FilterList 对 |
renderFilters | true | 所有滤镜渲染的总开关 |
filtersAutoFocus | true | 自动调整相机以跟随对象 |
filtersFocusContext | false | 聚焦于渲染上下文而非对象边界 |
filtersForceComposite | false | 即使没有活动滤镜也始终绘制到帧缓冲 |
maxFilterSize | null -> Vector2 | 滤镜帧缓冲的最大纹理尺寸 |
使用 willRenderFilters() 检查是否有任何活动滤镜会实际渲染。
常见模式
为游戏对象添加滤镜
const sprite = this.add.sprite(400, 300, 'enemy');
sprite.enableFilters();
// Add a glow
const glow = sprite.filters.internal.addGlow(0x00ff00, 4);
// Modify at runtime
glow.outerStrength = 8;
glow.color = 0xff0000;
// Temporarily disable
glow.setActive(false);
// Remove and destroy
sprite.filters.internal.remove(glow);
相机滤镜
const camera = this.cameras.main;
// Internal: effect in camera-local space
const blur = camera.filters.internal.addBlur(0, 2, 2, 1);
// External: effect in screen space
const vignette = camera.filters.external.addVignette(0.5, 0.5, 0.5, 0.5);
// Color grading via ColorMatrix
const cm = camera.filters.internal.addColorMatrix();
cm.colorMatrix.sepia();
串联多个滤镜
滤镜按列表顺序执行。每个滤镜接收前一个滤镜的输出:
const cam = this.cameras.main;
// First: apply color grading
const cm = cam.filters.internal.addColorMatrix();
cm.colorMatrix.brightness(0.2);
// Second: apply blur to the color-graded result
cam.filters.internal.addBlur(1, 2, 2, 1);
// Third: add a vignette on top
cam.filters.external.addVignette(0.5, 0.5, 0.5, 0.8);
通过滤镜实现遮罩
v4 中的遮罩以滤镜形式实现。它们使用纹理或游戏对象的 alpha 通道来控制可见性:
// Mask with a static texture
sprite.enableFilters();
sprite.filters.internal.addMask('maskTexture');
// Mask with a game object (renders to DynamicTexture automatically)
const maskShape = this.add.circle(0, 0, 100, 0xffffff);
sprite.enableFilters();
const mask = sprite.filters.internal.addMask(maskShape);
// Invert the mask
mask.invert = true;
// Control auto-updating for game object masks
mask.autoUpdate = true; // default: re-renders each frame
mask.needsUpdate = true; // force a one-time update
// Use a specific camera for viewing the mask object
sprite.filters.external.addMask(maskShape, false, this.cameras.main);
内部遮罩匹配被过滤的对象。外部遮罩匹配相机上下文。使用 viewCamera 参数来控制由哪个相机渲染遮罩游戏对象。
擦除 / 揭示过渡
const camera = this.cameras.main;
const wipe = camera.filters.external.addWipe(0.1, 0, 0);
// Animate via tween
this.tweens.add({
targets: wipe,
progress: 1,
duration: 2000,
ease: 'Linear'
});
// Direction helpers
wipe.setLeftToRight();
wipe.setTopToBottom();
wipe.setRevealEffect(); // reveal mode
wipe.setWipeEffect(); // wipe mode
// Wipe to another texture (for scene transitions)
wipe.setTexture('nextSceneCapture');
ParallelFilters(自定义泛光与合成)
ParallelFilters 将输入拆分为两条路径,分别独立处理,然后混合结果。这取代了 v3 中专用的 Bloom 滤镜:
const camera = this.cameras.main;
const pf = camera.filters.internal.addParallelFilters();
// Top path: threshold bright areas, then blur them
pf.top.addThreshold(0.5, 1);
pf.top.addBlur();
// Configure the blend (how top combines onto bottom)
pf.blend.blendMode = Phaser.BlendModes.ADD;
pf.blend.amount = 0.5;
// Bottom path: left empty = uses original input
使用 CaptureFrame 实现场景级效果
CaptureFrame 会在其出现在显示列表中的位置捕获当前渲染状态。在它之前渲染的对象会被捕获;在它之后渲染的对象则不会:
// Requires composite mode on the camera
this.cameras.main.setForceComposite(true);
// Objects rendered before CaptureFrame are captured
const bg = this.add.image(400, 300, 'background');
// Create the capture point
const capture = this.add.captureFrame('myCapture');
// Display the captured texture with filters applied
const display = this.add.image(400, 300, 'myCapture');
display.enableFilters();
display.filters.internal.addBlur(0, 4, 4, 2);
所有内置滤镜
| 滤镜 | 添加方法 | 描述 |
|---|---|---|
| Barrel | addBarrel(amount) | 挤压/膨胀变形。amount=1 为中性。 |
| Blend | addBlend(texture, blendMode, amount, color) | 使用混合模式混合另一个纹理。支持标准 WebGL 中没有的模式。 |
| Blocky | addBlocky(config) | 保留原始颜色的像素化(无混合)。最好在不使用抗锯齿时使用。 |
| Blur | addBlur(quality, x, y, strength, color, steps) | 高斯模糊。质量:0=低,1=中,2=高。 |
| Bokeh | addBokeh(radius, amount, contrast) | 景深散景模糊效果。 |
| ColorMatrix | addColorMatrix() | 通过矩阵进行颜色操作。访问 .colorMatrix 可实现棕褐色、灰度、亮度、色相等效果。 |
| CombineColorMatrix | addCombineColorMatrix(texture) | 通过颜色矩阵合并两个纹理的通道。适用于 alpha 传递。 |
| Displacement | addDisplacement(texture, x, y) | 使用位移贴图纹理进行像素位移。值为非常小的浮点数(例如 0.005)。 |
| Glow | addGlow(color, outerStrength, innerStrength, scale, knockout, quality, distance) | 边缘周围的发光光晕。支持内发光/外发光和挖空模式。 |
| GradientMap | addGradientMap(config) | 基于亮度使用 ColorRamp 重新着色图像。 |
| ImageLight | addImageLight(config) | 使用全景环境贴图和法线贴图进行基于图像的照明。 |
| Key | addKey(config) | 色度键:移除或隔离特定颜色。配置:{ color, threshold, feather, isolate }。 |
| Mask | addMask(mask, invert, viewCamera, viewTransform, scaleFactor) | 通过纹理或游戏对象进行 Alpha 遮罩。 |
| NormalTools | addNormalTools(config) | 操作法线贴图:旋转、调整朝向强度、输出灰度朝向数据。 |
| PanoramaBlur | addPanoramaBlur(config) | 用于全景图像的球面校正模糊。与 ImageLight 配合使用。非常慢。 |
| ParallelFilters | addParallelFilters() | 将输入拆分为两条滤镜路径,混合结果。用于自定义泛光。 |
| Pixelate | addPixelate(amount) | 马赛克/像素化效果。像素大小 = 2 + amount。会混合颜色(与 Blocky 不同)。 |
| Quantize | addQuantize(config) | 减少调色板。支持 RGBA/HSVA 模式、gamma、偏移、抖动。 |
| Sampler | addSampler(callback, region) | 从渲染中提取像素数据。不会改变图像。开销较大。 |
| Shadow | addShadow(x, y, decay, power, color, samples, intensity) | 带偏移、衰减和颜色的投影阴影。 |
| Threshold | addThreshold(edge1, edge2, invert) | 逐通道二值阈值。边缘可以是数组以进行逐通道控制。 |
| TiltShift | addTiltShift(radius, amount, contrast, blurX, blurY, strength) | 微缩/移轴效果(内部使用 Bokeh)。 |
| Vignette | addVignette(x, y, radius, strength, color, blendMode) | 边缘变暗/着色。支持 NORMAL、ADD、MULTIPLY、SCREEN 混合模式。 |
| Wipe | addWipe(wipeWidth, direction, axis, reveal, wipeTexture) | 擦除/显现过渡。通过 tween 动画化 progress。 |
API 快速参考
启用和访问滤镜
// Game objects: must enable first
gameObject.enableFilters();
gameObject.filters.internal.addBlur();
gameObject.filters.external.addGlow();
// Cameras: filters available immediately
camera.filters.internal.addBlur();
camera.filters.external.addGlow();
FilterList 方法
const list = camera.filters.internal;
list.addBlur(); // Factory method (one per filter type)
list.add(controllerInstance); // Add a pre-built controller
list.add(controller, 2); // Insert at index 2
list.remove(controller); // Remove and destroy
list.clear(); // Remove and destroy all
list.getActive(); // Get all active controllers
list.list; // Raw array (reorder safely)
控制器通用 API
controller.active = false; // Disable without removing
controller.setActive(true); // Enable (returns this)
controller.setPaddingOverride(10, 10, 10, 10); // Override padding
controller.setPaddingOverride(null); // Clear override
controller.ignoreDestroy = true; // Survive FilterList.destroy()
controller.destroy(); // Manual cleanup
Mask 滤镜 API
const mask = list.addMask('texKey'); // From texture key
const mask = list.addMask(gameObject); // From game object
mask.invert = true; // Invert mask
mask.autoUpdate = false; // Stop auto-updating GO masks
mask.needsUpdate = true; // Force one update
mask.setTexture('newKey'); // Change texture source
mask.setGameObject(newGO); // Change GO source
mask.viewCamera = otherCamera; // Camera for GO rendering
mask.viewTransform = 'local'; // 'local' or 'world'
mask.scaleFactor = 0.5; // Scale mask texture size
ColorMatrix 预设
const cm = list.addColorMatrix();
cm.colorMatrix.sepia();
cm.colorMatrix.grayscale(1);
cm.colorMatrix.brightness(0.3);
cm.colorMatrix.hue(90);
cm.colorMatrix.saturate(-0.5);
cm.colorMatrix.contrast(0.3);
cm.colorMatrix.blackWhite();
cm.colorMatrix.negative();
cm.colorMatrix.desaturate();
cm.colorMatrix.night(0.5);
cm.colorMatrix.lsd();
cm.colorMatrix.brown();
cm.colorMatrix.vintagePinhole();
cm.colorMatrix.kodachrome();
cm.colorMatrix.technicolor();
cm.colorMatrix.polaroid();
cm.colorMatrix.shiftToBGR();
注意事项
-
仅限 WebGL -- 滤镜在 Canvas 渲染器中无效。如果 WebGL 不可用,
enableFilters()会提前返回。 -
游戏对象需要调用 enableFilters() -- 摄像机默认具有滤镜。精灵、图像、容器及其他游戏对象在访问
filters之前需要调用enableFilters()。 -
性能开销 -- 每个带有活动滤镜的对象都会产生额外的绘制调用(基础渲染一次,外加每个活动滤镜一次)。请谨慎使用,并尽早进行性能测试。
-
内部与外部滤镜的区别很重要 -- 内部滤镜开销更低(大小与对象区域一致)。外部滤镜是全屏的。应随对象旋转的模糊必须使用内部滤镜;应保持屏幕对齐的模糊必须使用外部滤镜。
-
滤镜顺序很重要 -- 滤镜按列表顺序依次应用。一个滤镜的输出会作为下一个滤镜的输入。
-
Glow 的 quality 和 distance 不可变 -- Glow 滤镜的
quality和distance在创建后无法更改。如需更改,请销毁并重新创建该滤镜。 -
CaptureFrame 需要 forceComposite -- 摄像机必须设置
setForceComposite(true),或以其他方式渲染到帧缓冲区,CaptureFrame 才能正常工作。 -
为扩展效果添加内边距 -- Blur、Glow 和 Shadow 等滤镜可以自动计算内边距以扩展渲染纹理。如有需要,可用
setPaddingOverride()覆盖。传入null可清除覆盖。在摄像机上使用时,请用camera.getPaddingWrapper(x)在图像边缘之外渲染更多世界内容。 -
控制器复用 -- 默认情况下,控制器会在其 FilterList 被销毁时一并销毁。设置
ignoreDestroy = true可在多个对象间复用控制器,但你必须手动管理其生命周期。与外部滤镜配合使用效果最佳。 -
遮罩游戏对象渲染 -- 当使用游戏对象作为遮罩源时,它每帧都会被渲染到一个 DynamicTexture(如果
autoUpdate为 true)。将autoUpdate = false并配合needsUpdate = true进行一次性更新,以提升静态遮罩的性能。 -
没有 Bloom 滤镜 -- v4 没有专用的 Bloom 滤镜。请改用 ParallelFilters 配合 Threshold + Blur + ADD 混合(参见常见模式),或使用
Phaser.Actions.AddEffectBloom自动完成该过程。
v4 相较于 v3 的变化
| v3 (FX) | v4 (Filters) | 说明 |
|---|---|---|
gameObject.preFX / gameObject.postFX | gameObject.filters.internal / gameObject.filters.external | preFX/postFX 被内部/外部滤镜列表取代 |
camera.postFX | camera.filters.internal / camera.filters.external | 摄像机现在同时拥有内部和外部列表 |
FX.addBloom() | 使用 ParallelFilters + Threshold + Blur | 没有专用 Bloom 滤镜;用 ParallelFilters 或 Phaser.Actions.AddEffectBloom 构建 |
FX.addCircle() | 使用 Vignette 或 Mask | Circle 效果已移除;请使用带半径的 Vignette 或圆形 Mask,或用 Phaser.Actions.AddMaskShape 自动完成 |
FX.addGradient() | 使用 Gradient GameObject + Quantize | 新的 Gradient GameObject 可渲染渐变;Quantize 可按需添加色阶 |
Glow 的 quality 原为 0-1 的小数 | Glow 的 quality 现为整数(默认 10) | 随机采样取代了线采样;值越低质量越高 |
camera.setMask() | camera.filters.internal.addMask() | 遮罩现在是一种滤镜,而非独立系统 |
gameObject.setMask() | gameObject.filters.internal.addMask() | 同样统一的滤镜系统 |
| FX 控制器 | Phaser.Filters.Controller 子类 | 模式相同:返回的控制器对象带有可变属性 |
| -- | 游戏对象需要调用 enableFilters() | 游戏对象新增了显式的启用步骤 |
| -- | Blocky、Quantize、Key、Blend、CombineColorMatrix、ImageLight、NormalTools、PanoramaBlur、ParallelFilters、Sampler | v4 中新增的滤镜 |
源文件映射
| 文件 | 描述 |
|---|---|
src/gameobjects/components/Filters.js | 为游戏对象添加 enableFilters()、filterCamera、filters 的 Mixin |
src/gameobjects/components/FilterList.js | 包含所有 add*() 工厂方法的 FilterList 类 |
src/filters/Controller.js | 所有滤镜的基础 Controller 类 |
src/filters/Barrel.js | 桶形畸变滤镜 |
src/filters/Blend.js | 纹理混合滤镜 |
src/filters/Blocky.js | 保留颜色的像素化滤镜 |
src/filters/Blur.js | 高斯模糊滤镜 |
src/filters/Bokeh.js | 散景 / 移轴滤镜 |
src/filters/ColorMatrix.js | 颜色矩阵滤镜(棕褐色、灰度等) |
src/filters/CombineColorMatrix.js | 双纹理通道合并滤镜 |
src/filters/Displacement.js | 置换贴图滤镜 |
src/filters/Glow.js | 发光/描边滤镜 |
src/filters/GradientMap.js | 渐变映射重新着色滤镜 |
src/filters/ImageLight.js | 基于图像的照明滤镜 |
src/filters/Key.js | 色度键滤镜 |
src/filters/Mask.js | Alpha 遮罩滤镜(纹理或游戏对象) |
src/filters/NormalTools.js | 法线贴图操作滤镜 |
src/filters/PanoramaBlur.js | 球形全景模糊滤镜 |
src/filters/ParallelFilters.js | 带混合的并行滤镜路径 |
src/filters/Pixelate.js | 像素化滤镜 |
src/filters/Quantize.js | 颜色量化滤镜 |
src/filters/Sampler.js | 像素采样/回读滤镜 |
src/filters/Shadow.js | 投影滤镜 |
src/filters/Threshold.js | 阈值滤镜 |
src/filters/Vignette.js | 暗角滤镜 |
src/filters/Wipe.js | 擦除/揭示过渡滤镜 |
src/gameobjects/captureframe/CaptureFrame.js | 用于场景级捕获的 CaptureFrame 游戏对象 |
相关:sprites-and-images.md、cameras.md、v4-new-features.md