ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

PixiJS 过滤器(Filters)完全指南:内置滤镜、高级混合模式与自定义着色器

PixiJS 过滤器(Filters)完全指南:内置滤镜、高级混合模式与自定义着色器 PixiJS 过滤器Filters完全指南内置滤镜、高级混合模式与自定义着色器【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs过滤器Filters是 PixiJS 后处理体系的核心它们能对任意显示对象及其子树施加模糊、颜色调整、噪点、置换扭曲乃至完全自定义的着色器效果。本文以 filters.md 为骨架结合 src/filters 目录下的真实源码与 examples 中的示例系统讲解五种内置过滤器、21 种高级混合模式、两种自定义过滤器写法以及渲染管线的底层原理。读完本文你将能够在自己的 PixiJS 应用中直接套用所有示例代码并写出可同时运行于 WebGL 与 WebGPU 的 GLSL/WGSL 过滤器。过滤器是什么对显示对象施加后处理在 PixiJS 中过滤器Filter是对显示对象渲染结果的一次后处理先把对象渲染到离屏纹理再用过滤器的着色器程序把该纹理处理一遍后画回主帧缓冲。任何继承自Container的对象Sprite、Graphics、Text 等都可以通过filters属性挂载过滤器。import { Assets, Sprite, BlurFilter, NoiseFilter } from pixi.js; const texture await Assets.load(photo.png); const sprite new Sprite(texture); // 单个过滤器 sprite.filters new BlurFilter({ strength: 8 }); // 多个过滤器按顺序依次应用 sprite.filters [ new BlurFilter({ strength: 8 }), new NoiseFilter({ noise: 0.5 }), ];[!NOTE]过滤器顺序很重要。它们按数组顺序依次执行每个过滤器处理的是上一个过滤器的输出结果因此顺序不同最终效果也不同。在源码层面Filter 类 继承自Shader并维护一份Filter.defaultOptions作为所有过滤器的默认配置blendMode: normal、resolution: 1、padding: 0、antialias: off、blendRequired: false、clipToViewport: true。构造过滤器时传入的选项会与默认值合并。内置过滤器一览PixiJS 内置了五个开箱即用的过滤器全部位于 src/filters/defaults 目录过滤器用途AlphaFilter施加统一的透明度BlurFilter高斯模糊ColorMatrixFilter通过 5x4 矩阵做颜色变换DisplacementFilter使用置换贴图纹理扭曲图像NoiseFilter添加随机噪点营造颗粒质感AlphaFilter透明度import { AlphaFilter } from pixi.js; sprite.filters new AlphaFilter({ alpha: 0.5 });alpha取值范围 0完全透明到 1完全不透明。从源码看AlphaFilter 的defaultOptions.alpha为1滤镜运行时会把它写入名为uAlpha的 uniform并且暴露了可读写的alpha属性供运行时动态修改。值得注意的使用建议写在源码注释中当需要对整个显示对象树施加统一透明度时优先使用AlphaFilter而非Container.alpha。因为Container.alpha是逐元素逐层相乘的多个半透明子元素叠加时会出现视觉上的重叠加深而AlphaFilter是在整棵树渲染完成后统一施加 alpha表现更符合直觉。同时它还能免费获得所有过滤器共有的能力——例如为滤镜指定blendMode让整棵树与背景混合、或在容器上设置filterArea做裁剪。BlurFilter高斯模糊import { BlurFilter } from pixi.js; sprite.filters new BlurFilter({ strength: 8, // 模糊强度默认 8 quality: 4, // 模糊趟数默认 4 kernelSize: 5, // 内核尺寸默认 5 });也可以只对单轴模糊用strengthX/strengthY分别控制水平与垂直方向的强度适合制作运动模糊或方向性光晕。从实现看BlurFilter 内部并不直接做二维模糊而是组合了两个单方向的 BlurFilterPass水平一趟 垂直一趟利用高斯模糊的可分离性把 O(n²) 的卷积拆成两次 O(n) 卷积大幅降低开销。apply方法中两个方向都非零时会从TexturePool申请一张同尺寸临时纹理先水平模糊到临时纹理再垂直模糊到输出最后归还纹理。关于各参数的源码细节strength同时设置 X/Y 强度读取时若strengthX ! strengthY会抛出异常见 BlurFilter.ts#L289-L297。旧版 API 的blur/blurX/blurY属性自 8.3.0 起已废弃请改用strength系列。kernelSize决定卷积核精度可选值限定为5、7、9、11、13、15奇数数值越大精度越高、开销也越大见 BlurFilter.ts#L76-L79。quality对应模糊趟数越高越平滑但越慢。repeatEdgePixels置为true时会对边缘像素做 clamp钳制采样避免模糊把透明边缘卷进来此时padding自动归零见 BlurFilter.ts#L261-L271。legacy选项默认false用于恢复 v8 之前的旧模糊趟行为强度按趟数均匀分摊而非优化的折半方案并会禁用 WebGPU 的按趟 UBO 批处理一般无需开启。仓库示例 examples/filters_blur.ts 展示了真实用法创建两个BlurFilter实例分别挂到两个精灵上然后在app.ticker中用Math.cos/Math.sin驱动模糊强度做呼吸式动画const blurFilter1 new BlurFilter(); const blurFilter2 new BlurFilter(); littleDudes.filters [blurFilter1]; littleRobot.filters [blurFilter2]; app.ticker.add(() { count 0.005; blurFilter1.blur 20 * Math.cos(count); // 注意8.3 起建议改为 strength blurFilter2.blur 20 * Math.sin(count); });ColorMatrixFilter颜色变换import { ColorMatrixFilter } from pixi.js; const colorMatrix new ColorMatrixFilter(); colorMatrix.brightness(0.5, false); colorMatrix.contrast(0.8, false); colorMatrix.saturate(1.2, true); // true 与当前矩阵相乘累积效果 sprite.filters colorMatrix;ColorMatrixFilter用一张5x4 矩阵20 个元素对每个像素的 RGBA 做线性变换类型定义见 ColorMatrixFilter.ts#L19。所有便捷方法的第二个参数multiply控制合并方式false表示用新矩阵替换当前矩阵true表示新矩阵与当前矩阵相乘从而把多次颜色调整累积起来内部由_multiply实现 4 行 x 5 列的手写矩阵乘法见 ColorMatrixFilter.ts#L141-L172。可用预设方法均带multiply参数brightness、contrast、saturate、desaturate、greyscale别名grayscale、blackAndWhite、hue、negative、sepia、technicolor、polaroid、toBGR、kodachrome、browni、vintage、colorTone、night、predator、lsd、reset。此外还有tint(color, multiply)方法接受任意 ColorSource如0xff0000或green适合做整体染色。所有颜色调整都可以在运行时连续调用、动态切换例如实现昼夜过渡白天 → 夜晚滤镜。DisplacementFilter置换贴图import { Sprite, DisplacementFilter } from pixi.js; const displacementSprite Sprite.from(displacement-map.png); sprite.filters new DisplacementFilter({ sprite: displacementSprite, scale: 20, });DisplacementFilter用一张 Sprite 的纹理作为置换贴图贴图中每个像素的红色通道决定水平位移量绿色通道决定垂直位移量。scale既可以是单个数字均匀缩放也可以传入{ x, y }形式的PointData分别控制两个方向见 DisplacementFilter.ts#L50-L63默认值20。源码中有几个值得注意的实现细节DisplacementFilter.ts构造时传入的sprite会被自动设为renderable falseL174-L176即贴图精灵本身不会被渲染出来只作为数据源因此你完全可以把它加到舞台上并移动/旋转它来驱动动画效果每次apply时通过filterManager.calculateSpriteMatrix计算贴图矩阵并从sprite.worldTransform提取旋转分量写入uRotationL186-L216保证贴图跟随精灵的变换缩放值通过filter.scale.x/filter.scale.y可随时读写。典型的应用场景包括水波涟漪、热浪扭曲、动态过渡转场。仓库示例 examples/filters_displacement.ts 与 examples/filters_displacement_interactive.ts 可作参考对应贴图资源位于 examples/assets/pixi-filters 和 examples/assets/pond。NoiseFilter噪点import { NoiseFilter } from pixi.js; sprite.filters new NoiseFilter({ noise: 0.5, // 噪点强度默认 0.5 seed: Math.random(), // 随机种子默认 Math.random() });noise控制噪点强度0.1 细微颗粒、0.5 中等、1.0 最强seed决定噪点图案——相同 seed 产生完全一致的噪点图案适合做可复现的胶片颗粒或静态雪花效果。两者在运行时均可通过filter.noise、filter.seed属性动态调整见 NoiseFilter.ts#L165-L202。高级混合模式除了五种过滤器PixiJS 还通过独立导入提供高级混合模式。与过滤器不同它们不是直接应用的后处理滤镜而是注册到容器上的混合模式blendMode由渲染管线在混合阶段生效import pixi.js/advanced-blend-modes; sprite.blendMode color-burn;导入后即可使用以下 21 种混合模式字符串 → 实现类混合模式字符串类colorColorBlendcolor-burnColorBurnBlendcolor-dodgeColorDodgeBlenddarkenDarkenBlenddifferenceDifferenceBlenddivideDivideBlendexclusionExclusionBlendhard-lightHardLightBlendhard-mixHardMixBlendlightenLightenBlendlinear-burnLinearBurnBlendlinear-dodgeLinearDodgeBlendlinear-lightLinearLightBlendluminosityLuminosityBlendnegationNegationBlendoverlayOverlayBlendpin-lightPinLightBlendsaturationSaturationBlendsoft-lightSoftLightBlendsubtractSubtractBlendvivid-lightVividLightBlend从源码看导入pixi.js/advanced-blend-modes实际执行的是 init.ts把上述 21 个混合类通过extensions.add(...)注册进扩展系统随后渲染器就能识别对应的混合模式字符串。高 DPI 渲染器上的分辨率问题高级混合模式需要采样当前渲染目标来把源像素与目标像素背景做混合。与其他过滤器一样它们创建时使用Filter.defaultOptions其默认resolution为1为了性能。如果你的渲染器使用了非1的分辨率例如高 DPI 屏且高级混合模式出现被裁剪、被缩放、或只部分生效的现象请在创建使用高级混合模式的过滤器或显示对象之前选择继承渲染目标分辨率import { Filter } from pixi.js; import pixi.js/advanced-blend-modes; Filter.defaultOptions.resolution inherit; sprite.blendMode overlay;inherit使过滤器按当前渲染目标的分辨率渲染能提升这类对分辨率敏感的混合效果的真实度代价是相比默认值1会增加显存占用与运行时开销。自定义过滤器内置过滤器不够用时可以用 GLSL 着色器编写自己的过滤器。PixiJS v8 采用GLSL ES 3.0 风格用in/out代替attribute/varying用texture()代替texture2D。使用Filter.from()推荐快速上手最简方式通常只需提供片元着色器顶点着色器由 PixiJS 提供默认实现负责顶点位置计算传undefined或省略即可使用默认顶点着色器。下面的例子用片元着色器做一个反色效果const simpleFilter Filter.from({ gl: { fragment: in vec2 vTextureCoord; out vec4 finalColor; uniform sampler2D uTexture; void main(void) { vec4 color texture(uTexture, vTextureCoord); finalColor vec4(1.0 - color.rgb, color.a); // 反色 } , }, resources: {}, });从实现看Filter.from会调用GlProgram.from/GpuProgram.from把着色器源码编译成程序再包一层Filter见 Filter.ts#L261-L283。若需要同时完全控制顶点与片元着色器可以写一个水波滤镜——片元着色器按正弦波横向偏移采样坐标uTime随时间递增形成波动动画import { Filter } from pixi.js; const waveFilter Filter.from({ gl: { vertex: in vec2 aPosition; out vec2 vTextureCoord; uniform vec4 uInputSize; uniform vec4 uOutputFrame; uniform vec4 uOutputTexture; vec4 filterVertexPosition(void) { vec2 position aPosition * uOutputFrame.zw uOutputFrame.xy; position.x position.x * (2.0 / uOutputTexture.x) - 1.0; position.y position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z; return vec4(position, 0.0, 1.0); } vec2 filterTextureCoord(void) { return aPosition * (uOutputFrame.zw * uInputSize.zw); } void main(void) { gl_Position filterVertexPosition(); vTextureCoord filterTextureCoord(); } , fragment: in vec2 vTextureCoord; out vec4 finalColor; uniform sampler2D uTexture; uniform float uWaveAmplitude; uniform float uWaveFrequency; uniform float uTime; void main(void) { vec2 coord vTextureCoord; coord.x sin(coord.y * uWaveFrequency uTime) * uWaveAmplitude; finalColor texture(uTexture, coord); } , }, resources: { waveUniforms: { uWaveAmplitude: { value: 0.05, type: f32 }, uWaveFrequency: { value: 10.0, type: f32 }, uTime: { value: 0.0, type: f32 }, }, }, }); sprite.filters [waveFilter]; app.ticker.add((ticker) { waveFilter.resources.waveUniforms.uniforms.uTime 0.1 * ticker.deltaTime; });这段代码中resources里的 uniform 会在渲染时自动绑定无需手动上传。注意gl_Position filterVertexPosition()与vTextureCoord filterTextureCoord()是默认顶点着色器的标准套路对应文档中的着色器约定一节。使用new Filter()配合预编译程序需要更高控制力时可以自己构造GlProgram/GpuProgram再传入Filter构造函数import { Filter, GlProgram } from pixi.js; const glProgram new GlProgram({ vertex: vertexSrc, fragment: fragmentSrc }); const filter new Filter({ glProgram, resources: { timeUniforms: { uTime: { value: 0.0, type: f32 }, }, }, });着色器编写约定片元着色器使用out vec4 finalColor;输出颜色不是gl_FragColor采样纹理使用texture()不是texture2D默认顶点着色器提供filterVertexPosition()与filterTextureCoord()辅助函数处理输出帧定位自定义顶点着色器时可直接复用resources中声明的 uniform 可通过filter.resources.组名.uniforms.uniform名在 JS 侧读写如动画循环里更新uTime。[!NOTE] 为了同时支持 WebGL 与 WebGPU 双渲染器请同时提供glProgramGLSL与gpuProgramWGSL。仅提供一个时过滤器在缺少对应程序的那个渲染器上会被跳过、按原样渲染。仓库中内置过滤器均为双实现例如 BlurFilterPass 同时通过generateBlurGlProgramGLSL与generateBlurProgramWGSL生成两个程序。更多示例见 examples/mesh_multipass_shader_effects 与 examples/filters_custom-shader_glsl后者含 custom.frag / custom.vert 可对照。过滤器基础选项所有过滤器无论内置还是自定义都接受以下基础选项定义于 FilterOptions 接口选项类型默认值说明blendModestringnormal过滤器输出使用的混合模式resolutionnumber \| inherit1渲染分辨率越低性能越好、质量越低paddingnumber0过滤器区域外扩的像素数模糊等会向外扩散的效果需要 padding 防止裁切antialiasFilterAntialias \| booleanoff抗锯齿模式on/off/inherit布尔值会被转换为 on/off见 Filter.ts#L200-L208blendRequiredbooleanfalse是否需要在着色器中读取背景像素开启后着色器需声明uBackTextureuniformclipToViewportbooleantrue是否将过滤器纹理裁剪到视口范围内其中antialias的三种取值语义on强制抗锯齿、off默认关闭、inherit跟随渲染目标设置。resolution的inherit见上文高 DPI 场景。渲染管线视角过滤器底层做了什么为了写出高性能的过滤器代码理解底层流程很有必要。Filter 类的源码注释 完整描述了挂载过滤器后渲染器实际执行的步骤打断当前批次break the current batch用getGlobalBounds递归遍历所有子对象测量目标的大小从纹理池获取2 的幂或屏幕尺寸的纹理把目标对象渲染到该纹理离屏渲染再用过滤器的着色器程序把该纹理作为 quad渲染回主帧缓冲。某些过滤器如模糊需要多趟处理性能开销会进一步放大。注释中还特别强调了两点经验瓶颈通常不是着色器本身的复杂度而是频繁的帧缓冲与着色器切换一个过滤器作用于一个含大量对象的容器远快于大量对象各自挂过滤器。性能优化实践限制过滤区域默认每帧 PixiJS 都根据对象边界计算过滤区域。手动设置sprite.filterArea为固定Rectangle可跳过该计算并缩小处理范围。共享过滤器实例同一个过滤器实例可以挂到多个对象上避免重复创建与重复上传资源。用不到就移除sprite.filters null可完全跳过过滤处理。调节质量降低BlurFilter的quality可减少趟数、显著提速。优先使用图集/烘焙对静态效果应把效果烘焙进纹理而不是运行时用过滤器。import { Rectangle, BlurFilter } from pixi.js; // 把过滤处理限制在 200x200 区域内 sprite.filterArea new Rectangle(0, 0, 200, 200); // 在多个精灵之间共享同一个模糊实例 const sharedBlur new BlurFilter({ strength: 4 }); sprite1.filters [sharedBlur]; sprite2.filters [sharedBlur];相关源码与延伸阅读想继续深入可在当前仓库中查看以下入口Filter 基类与 FilterOptions过滤器选项、Filter.from、默认行为FilterSystem过滤器的渲染调度系统五个内置过滤器Alpha、Blur、ColorMatrix、Displacement、Noise 各自的实现与默认值高级混合模式21 种混合模式的类实现与注册逻辑 init.tsBlurFilter 相关测试、ColorMatrixFilter 测试验证各参数行为与渲染结果可运行示例examples/filters_blur.ts、examples/filters_color-matrix.ts、examples/filters_displacement.ts、examples/filters_displacement_interactive.ts、examples/filters_custom-shader_glsl【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表