如何在 Pixi.js v7 中正确实现自定义滤镜的屏幕空间矩阵计算

pixi.js v7 已移除 `calculatenormalizedscreenspacematrix` 方法,需改用 `calc

ulatespritematrix` 配合滤镜坐标系适配,否则会抛出“is not a function”错误。

在 Pixi.js v7 中,滤镜系统进行了重构,旧版(v6 及之前)中用于归一化屏幕空间坐标的 filterManager.calculateNormalizedScreenSpaceMatrix() 已被彻底移除。该方法在 v7 的 FilterManager 实例上不再存在,直接调用会导致运行时错误:

// ❌ 错误:v7 中不存在此方法
filterManager.calculateNormalizedScreenSpaceMatrix(matrix);

✅ 正确做法是使用 filterManager.calculateSpriteMatrix() —— 它专为 v7 设计,可将纹理坐标映射到目标渲染区域,并自动处理滤镜区域(filterArea)、渲染目标尺寸及帧坐标关系。

以下是兼容 Pixi.js v7 的自定义滤镜完整写法示例:

import * as PIXI from 'pixi.js';

const fragShader = `
    precision mediump float;
    varying vec2 vTextureCoord;
    uniform sampler2D uSampler;
    uniform mat3 filterMatrix; // 接收变换矩阵

    void main() {
        // 将纹理坐标通过 filterMatrix 变换到归一化滤镜区域
        vec3 coord = vec3(vTextureCoord, 1.0);
        vec2 transformed = (filterMatrix * coord).xy;
        gl_FragColor = texture2D(uSampler, transformed);
    }
`;

const uniforms = {
    filterMatrix: new PIXI.Matrix(),
};

const myFilter = new PIXI.Filter(null, fragShader, uniforms);

myFilter.apply = function (filterManager, input, output, clear) {
    // ✅ v7 推荐:使用 calculateSpriteMatrix 替代已废弃方法
    const matrix = new PIXI.Matrix();
    filterManager.calculateSpriteMatrix(matrix, this); // 自动适配 filterArea 和 renderTarget

    this.uniforms.filterMatrix = matrix;
    filterManager.applyFilter(this, input, output, clear);
};

// 应用滤镜(例如添加到 Sprite)
const sprite = new PIXI.Sprite(texture);
sprite.filters = [myFilter];

⚠️ 注意事项:

  • calculateSpriteMatrix() 的第二个参数必须传入当前 Filter 实例(即 this),以便内部读取 filterArea 和 autoFit 等配置;
  • 若需手动控制坐标归一化逻辑(如实现 UV 偏移或缩放),可基于 matrix 进一步复合变换,但通常无需额外处理;
  • 确保你的 uniforms.filterMatrix 是 PIXI.Matrix 实例(而非普通数组),否则着色器中 mat3 类型无法正确解析;
  • v7 中 Filter.apply 的签名与 v6 一致,但底层 filterManager API 已不兼容,切勿混合使用旧文档示例。

总结:Pixi.js v7 强调语义化与一致性,calculateSpriteMatrix 不仅替代了旧函数功能,还统一了精灵、容器和滤镜间的坐标转换逻辑。升级项目时,请务必检查所有自定义滤镜中的 filterManager 调用,并以官方 v7 文档中的 FilterManager API 为准。