選項
首頁首頁 Skill 其他 pixijs-custom-rendering

pixijs-custom-rendering

pixijs/pixijs pixijs/pixijs

在 PixiJS v8 中撰寫自訂著色器、統一變數、濾鏡或批次處理器時,請使用此技巧。內容涵蓋 Shader.from({gl, gpu, resources})、GlProgram/GpuProgram、帶有類型化統一變數(f32、vec2、mat4x4)的 UniformGroup、 UBO 模式、作為資源的紋理、透過 Filter.from 建立的自訂濾波器、GLSL ES 3.0 規範(in/out、finalColor、texture())、uBackTexture 採樣,以及用於嚴格 CSP 的 pixi.js/unsafe-eval,以及透過擴充功能建立的自訂批次處理器。 觸發條件:Shader、GlProgram、GpuProgram、UniformGroup、Batcher、Filter、Filter.from、GLSL、WGSL、UBO、uniform、自訂著色器、finalColor、uBackTexture、blendRequired、unsafe-eval。

...展開全部
177
更新時間 2026-08-11

自訂著色器會透過Shader.from({ gl, gpu, resources }) 將 GLSL 和 WGSL 程式綁定至場景物件。Uniform 變數存放在具型別的UniformGroups中,貼圖則作為獨立資源傳入,且同一個著色器可同時針對 WebGL 和 WebGPU 進行編譯。

快速入門

constuniforms =new UniformGroup({
  uTime: {value:0,type:"f32"},
});constshader =Shader.from({
  gl: {vertex: vertexSrc,fragment: fragmentSrc },
 resources: { uniforms },
});constgeometry =new MeshGeometry({
  positions:new Float32Array([0,0,100,0,100,100,0,100]),
 uvs:new Float32Array([0,0,1,0,1,1,0,1]),
 indices:new Uint32Array([0,1,2,0,2,3]),
});constmesh =new Mesh({ geometry, shader });
app.stage.addChild(mesh);app.ticker.add(() =>{
  shader.resources.uniforms.uniforms.uTime= performance.now() /1000;
});

相關技能: pixijs-filters(內建濾鏡)、pixijs-scene-mesh(自訂幾何體)、pixijs-performance(批次優化)、pixijs-migration-v8(從 v7 遷移著色器 API)。

核心模式

雙渲染器著色器(WebGL + WebGPU)

import{Shader,GlProgram,GpuProgram,UniformGroup}from "pixi.js";constglVertex =`...`;// GLSL 頂點(若需 WebGL2/GLSL ES 3.0,請自行寫入 `#version 300 es`)
constglFragment =`...`;// GLSL 片元
constwgslSource =`...`;// WGSL組合程式碼constshader =Shader.from({
  gl: {vertex: glVertex,fragment: glFragment },
 gpu: {
    // 入口點名稱可自訂;但必須 與您 WGSL 原始碼中的 @vertex / @fragment
    // 函式名稱 相符 。PixiJS 提供的範例使用
    // 'mainVert' / 'mainFrag',但 `main` 同樣有效。
   vertex: {entryPoint:"mainVert",source: wgslSource },
    fragment: {entryPoint:"mainFrag",source: wgslSource },
  },
 resources: {
    myUniforms:new UniformGroup({
      uColor: {value:new Float32Array([1,0,0,1]),type:"vec4"},
     uMatrix: {value:new Float32Array(16),type:"mat4x4 "},
    }),
  },
});

若僅提供 gl,則著色器僅適用於 WebGL;若僅提供gpu,則僅適用於 WebGPU。compatibleRenderers位元遮罩會自動設定。

GlProgram 不會自動注入#version 300 es。 若您自行撰寫#version 300 es,PixiJS 會保留該設定並將著色器視為 GLSL ES 3.0;否則,它會注入 WebGL1 相容巨集(在 varying 中使用 #define,在 texture 中使用#define texture2D),並以 WebGL1 風格的 GLSL 執行著色器。GlProgram會始終注入預設精確度(頂點為 highp,片段為mediump)以及程式名稱。對於 GLSL ES 3.0,請使用in/out取代attribute/varying,使用texture()取代texture2D(),並使用out vec4取代gl_FragColor。

將紋理視為資源

紋理屬於資源,而非統一變數。請分別傳入紋理的來源與樣式:

import{Shader,UniformGroup,Texture,Assets}from "pixi.js";consttexture =await Assets.load("myImage.png");constshader =Shader.from({
  gl: {vertex: vertSrc,fragment: fragSrc },
 resources: {
    uTexture: texture.source,
    uSampler: texture.source.style,
    myUniforms:new UniformGroup({
      uAlpha: {value:1.0,type:"f32"},
    }),
  },
});// 執行時替換貼圖
shader.resources.uTexture= otherTexture.source;

資源是一個扁平的鍵值對映表。鍵名必須與著色器原始碼中的 uniform/binding 名稱相符。

資源也可以是普通的物件(會自動封裝為UniformGroup):

constshader =Shader.from({
  gl: {vertex: vertSrc,fragment: fragSrc },
 resources: {
    myUniforms: {
      uTime: {value:0,type:"f32"},
    },
  },
});

UBO 模式(Uniform Buffer Objects)

UBO 模式會將統一變數打包到單一 GPU 緩衝區中。WebGPU 必須使用此模式;WebGL 則為選用(WebGL2+)。

import{UniformGroup}from "pixi.js";constubo =new UniformGroup(
  {
    uProjection: {value:new Float32Array(16),type:"mat4x4"},
   uAlpha: {value:1.0,type:"f32"},
  },
  {ubo:true,isStatic:true},
);// 當 isStatic 為 true 時,必須手動呼叫 update()
ubo.uniforms.uAlpha=0.5;
ubo.update();

UBO 規則:

  • 僅支援基於f32和i32的資料型別(不支援u32)。矩陣僅限浮點數。
  • 取樣器/紋理無法放入 UBO 中。
  • 資源中的 UniformGroup 名稱必須與著色器中的 UBO 區塊名稱完全一致。
  • 結構與順序必須與著色器佈局完全一致。
  • UBO 同步機制在底層使用新的 Function 函式。在嚴格 CSP 環境(無unsafe-eval)中,請於啟動時導入pixi.js/unsafe-eval一次,以切換至備用同步路徑;若未導入,基於 UBO 的著色器(以及 WebGPU)將在首次使用時拋出錯誤。

自訂濾鏡

Filter.from({ gl, resources })為簡寫形式。僅需傳入片段著色器;PixiJS 會提供預設的頂點著色器來處理輸出幀的定位。

import{Filter}from "pixi.js";constfilter =Filter.from({
  gl: {
    fragment:`
            in vec2 vTextureCoord;
            out vec4 finalColor;
            uniform sampler2D uTexture;
            uniform float uStrength;            void main(void) {
                vec4 color = texture(uTexture, vTextureCoord);
                finalColor = mix(color, vec4(1.0 - color.rgb, color.a), uStrength);
            }
        `,
  },
  resources: {
    filterUniforms: {
      uStrength: {value:0.5,type:"f32"},
    },
  },
});filter.resources.filterUniforms.uniforms.uStrength=1.0;

若要使用自訂頂點著色器,請使用new Filter({ glProgram: new GlProgram({ vertex, fragment }), resources })。

Filter 著色器規範(GLSL ES 3.0)
  • 使用 `vec2 vTextureCoord;`取代 `varying vec2 vTextureCoord;`
  • 使用out vec4 finalColor;取代gl_FragColor
  • 使用texture(uTexture, uv)取代texture2D(uTexture, uv)
  • 預設頂點著色器會公開uInputSize、uOutputFrame、uOutputTexture以及輔助函式filterVertexPosition()/filterTextureCoord()
對濾鏡後方的渲染目標進行取樣

將blendRequired 設為 true,並在片元著色器中採樣uBackTexture。PixiJS 會在執行濾波器之前,將目標像素複製到該 uniform 中:

constblendFilter =Filter.from({
  gl: {fragment: blendFragSrc },
  resources: {uniforms: {uAmount: {value:0.5,type:"f32"} } },
  blendRequired:true,
});

僅在需要時才啟用 `blendRequired`;此設定會強制每幀進行一次額外的 GPU 複製。

執行階段更新統一變數

// 透過 resources 存取 UniformGroup
shader.resources.myUniforms.uniforms.uTime= performance.now() /1000;// 對於 isStatic 類型的 UBO,變更值後請呼叫 update()
shader.resources.myUniforms.update();

Uniform 類型參考

請參閱references/uniform-types.md,以查看支援類型的完整表格、其 WGSL/GLSL 對應格式以及值格式。

自訂批次處理器(基於擴充功能)

Batcher抽象類別可實現專用渲染的自訂批次處理。請繼承此類別,並透過擴充功能進行註冊:

import{Batcher, extensions,ExtensionType}from "pixi.js";
import type{
  BatcherOptions,
  BatchableMeshElement,
  BatchableQuadElement,
  Geometry,
  Shader,
}from "pixi.js";class MyBatcher extends Batcher{
 public staticextension = {
    type: [ExtensionType.Batcher],
    name:"my-batcher",
  };  publicname ="my-batcher";
 protectedvertexSize =6;// 每個頂點的浮點數數量
  public geometry:Geometry;
  public shader:Shader;  constructor(options:BatcherOptions) {
    super(options);
    // 初始化幾何體與著色器
  }  public packAttributes(
    element:BatchableMeshElement,
    float32View:Float32Array,
    uint32View:Uint32Array,
    index:number,
    textureId:number,
  ):void{
   // 將網格頂點屬性封裝至批次緩衝區
  }  public packQuadAttributes(
    element:BatchableQuadElement,
    float32View:Float32Array,
    uint32View:Uint32Array,
    index:number,
    textureId:number,
  ):void{
   // 將四邊形頂點屬性封裝至批次緩衝區
  }
}extensions.add(MyBatcher);

元素透過batcherName 來引用批次處理器。BatchableElement介面要求以下參數:batcherName、texture、blendMode、indexSize、attributeSize、topology 以及packAsQuad。

常見錯誤

[關鍵] 舊版 Shader.from(vertex, fragment, uniforms) 建構子

錯誤示例:

constshader =Shader.from(vertex, fragment, {uTime:1});

正確寫法:

constshader =Shader.from({
  gl: { vertex, fragment },
  resources: {
    uniforms:new UniformGroup({
      uTime: {value:1,type:"f32"},
    }),
  },
});

v8 要求在gl/gpu程式與資源中使用選項物件。位置式 API 已被移除。

[嚴重] UniformGroup 未標註資料型別

錯誤:

new UniformGroup({uTime:1});

正確寫法:

new UniformGroup({uTime: {value:1,type:"f32"} });

每個 uniform 都必須明確指定{ value, type }對。若省略類型,將導致執行時錯誤:「不支援未定義的 uniform 類型。」

[高] 包含不支援類型或結構錯誤的 UBO

UBO 模式支援基於f32和i32的類型(標量與向量)。u32不在受支援的UniformGroup類型清單中,將引發錯誤。矩陣僅限浮點數(mat* )。取樣器無法放置於 UBO 中。

結構體名稱與欄位順序必須與著色器的 UBO 宣告完全一致。若不符,將導致渲染結果混亂,且不會顯示錯誤訊息。

[HIGH] 將紋理放入 UniformGroup

錯誤示例:

new UniformGroup({
  uTexture: {value: texture,type:"f32"},
});

正確:

constshader =Shader.from({
  gl: { vertex, fragment },
  resources: {
   uTexture: texture.source,
    uSampler: texture.source.style,
    myUniforms:new UniformGroup({
      uAlpha: {value:1.0,type:"f32"},
    }),
  },
});

紋理屬於資源,而非統一變數。請將texture.source(TextureSource)和texture.source.style(TextureStyle)作為頂層資源項目傳入。

API 參考

在 GitHub 上查看

Custom shaders bind GLSL and WGSL programs to scene objects via Shader.from({ gl, gpu, resources }). Uniforms live in typed UniformGroups, textures are passed as separate resources, and the same shader can target both WebGL and WebGPU.

Quick Start

const uniforms = new UniformGroup({
  uTime: { value: 0, type: "f32" },
});const shader = Shader.from({
  gl: { vertex: vertexSrc, fragment: fragmentSrc },
  resources: { uniforms },
});const geometry = new MeshGeometry({
  positions: new Float32Array([0, 0, 100, 0, 100, 100, 0, 100]),
  uvs: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
  indices: new Uint32Array([0, 1, 2, 0, 2, 3]),
});const mesh = new Mesh({ geometry, shader });
app.stage.addChild(mesh);app.ticker.add(() => {
  shader.resources.uniforms.uniforms.uTime = performance.now() / 1000;
});

Related skills: pixijs-filters (built-in filters), pixijs-scene-mesh (custom geometry), pixijs-performance (batch optimization), pixijs-migration-v8 (shader API migration from v7).

Core Patterns

Dual-renderer shader (WebGL + WebGPU)

import { Shader, GlProgram, GpuProgram, UniformGroup } from "pixi.js";const glVertex = `...`; // GLSL vertex (write `#version 300 es` yourself if you want WebGL2/GLSL ES 3.0)
const glFragment = `...`; // GLSL fragment
const wgslSource = `...`; // WGSL combinedconst shader = Shader.from({
  gl: { vertex: glVertex, fragment: glFragment },
  gpu: {
    // entryPoint names are arbitrary; they must match the @vertex / @fragment
    // function names in your WGSL source. PixiJS ships examples using
    // 'mainVert' / 'mainFrag' but `main` is equally valid.
    vertex: { entryPoint: "mainVert", source: wgslSource },
    fragment: { entryPoint: "mainFrag", source: wgslSource },
  },
  resources: {
    myUniforms: new UniformGroup({
      uColor: { value: new Float32Array([1, 0, 0, 1]), type: "vec4<f32>" },
      uMatrix: { value: new Float32Array(16), type: "mat4x4<f32>" },
    }),
  },
});

If only gl is provided, the shader works with WebGL only. If only gpu is provided, it works with WebGPU only. The compatibleRenderers bitmask is set automatically.

GlProgram does not auto-inject #version 300 es. If you write #version 300 es yourself, PixiJS preserves it and treats the shader as GLSL ES 3.0; otherwise it injects WebGL1 compat macros (#define in varying, #define texture texture2D) and runs the shader as WebGL1-style GLSL. GlProgram always injects a default precision (highp vertex, mediump fragment) and the program name. For GLSL ES 3.0, use in/out instead of attribute/varying, texture() instead of texture2D(), and an out vec4 instead of gl_FragColor.

Textures as resources

Textures are resources, not uniforms. Pass the texture's source and style separately:

import { Shader, UniformGroup, Texture, Assets } from "pixi.js";const texture = await Assets.load("myImage.png");const shader = Shader.from({
  gl: { vertex: vertSrc, fragment: fragSrc },
  resources: {
    uTexture: texture.source,
    uSampler: texture.source.style,
    myUniforms: new UniformGroup({
      uAlpha: { value: 1.0, type: "f32" },
    }),
  },
});// Swap texture at runtime
shader.resources.uTexture = otherTexture.source;

Resources are a flat key-value map. The key must match the uniform/binding name in the shader source.

Resources can also be plain objects (auto-wrapped into UniformGroup):

const shader = Shader.from({
  gl: { vertex: vertSrc, fragment: fragSrc },
  resources: {
    myUniforms: {
      uTime: { value: 0, type: "f32" },
    },
  },
});

UBO mode (Uniform Buffer Objects)

UBO mode packs uniforms into a single GPU buffer. Required for WebGPU; optional (WebGL2+) for WebGL.

import { UniformGroup } from "pixi.js";const ubo = new UniformGroup(
  {
    uProjection: { value: new Float32Array(16), type: "mat4x4<f32>" },
    uAlpha: { value: 1.0, type: "f32" },
  },
  { ubo: true, isStatic: true },
);// Must call update() manually when isStatic is true
ubo.uniforms.uAlpha = 0.5;
ubo.update();

UBO rules:

  • Only f32 and i32 based types are supported (no u32). Matrices are float-only.
  • Samplers/textures cannot go in a UBO.
  • The UniformGroup name in resources must exactly match the UBO block name in the shader.
  • Structure and order must exactly match the shader layout.
  • UBO sync uses new Function under the hood. In strict-CSP environments (no unsafe-eval), import pixi.js/unsafe-eval once at startup to swap in the fallback sync path; without it, UBO-backed shaders (and therefore WebGPU) will throw on first use.

Custom filter

Filter.from({ gl, resources }) is the shorthand. Pass only a fragment shader; PixiJS supplies a default vertex shader that handles output frame positioning.

import { Filter } from "pixi.js";const filter = Filter.from({
  gl: {
    fragment: `
            in vec2 vTextureCoord;
            out vec4 finalColor;
            uniform sampler2D uTexture;
            uniform float uStrength;            void main(void) {
                vec4 color = texture(uTexture, vTextureCoord);
                finalColor = mix(color, vec4(1.0 - color.rgb, color.a), uStrength);
            }
        `,
  },
  resources: {
    filterUniforms: {
      uStrength: { value: 0.5, type: "f32" },
    },
  },
});filter.resources.filterUniforms.uniforms.uStrength = 1.0;

For a custom vertex shader, use new Filter({ glProgram: new GlProgram({ vertex, fragment }), resources }).

Filter shader conventions (GLSL ES 3.0)
  • in vec2 vTextureCoord; instead of varying vec2 vTextureCoord;
  • out vec4 finalColor; instead of gl_FragColor
  • texture(uTexture, uv) instead of texture2D(uTexture, uv)
  • The default vertex shader exposes uInputSize, uOutputFrame, uOutputTexture and helpers filterVertexPosition() / filterTextureCoord()
Sampling the render target behind the filter

Set blendRequired: true and sample uBackTexture in the fragment shader. PixiJS copies the destination pixels into that uniform before running the filter:

const blendFilter = Filter.from({
  gl: { fragment: blendFragSrc },
  resources: { uniforms: { uAmount: { value: 0.5, type: "f32" } } },
  blendRequired: true,
});

Only enable blendRequired when you need it; it forces an extra GPU copy every frame.

Updating uniforms at runtime

// Access the UniformGroup via resources
shader.resources.myUniforms.uniforms.uTime = performance.now() / 1000;// For isStatic UBOs, call update() after changing values
shader.resources.myUniforms.update();

Uniform type reference

See references/uniform-types.md for the complete table of supported types, their WGSL/GLSL equivalents, and value formats.

Custom Batcher (extension-based)

The Batcher abstract class enables custom batching for specialized rendering. Subclass it and register via extensions:

import { Batcher, extensions, ExtensionType } from "pixi.js";
import type {
  BatcherOptions,
  BatchableMeshElement,
  BatchableQuadElement,
  Geometry,
  Shader,
} from "pixi.js";class MyBatcher extends Batcher {
  public static extension = {
    type: [ExtensionType.Batcher],
    name: "my-batcher",
  };  public name = "my-batcher";
  protected vertexSize = 6; // floats per vertex
  public geometry: Geometry;
  public shader: Shader;  constructor(options: BatcherOptions) {
    super(options);
    // Initialize geometry and shader
  }  public packAttributes(
    element: BatchableMeshElement,
    float32View: Float32Array,
    uint32View: Uint32Array,
    index: number,
    textureId: number,
  ): void {
    // Pack mesh vertex attributes into the batch buffer
  }  public packQuadAttributes(
    element: BatchableQuadElement,
    float32View: Float32Array,
    uint32View: Uint32Array,
    index: number,
    textureId: number,
  ): void {
    // Pack quad vertex attributes into the batch buffer
  }
}extensions.add(MyBatcher);

Elements reference the batcher by batcherName. The BatchableElement interface requires: batcherName, texture, blendMode, indexSize, attributeSize, topology, and packAsQuad.

Common Mistakes

[CRITICAL] Old Shader.from(vertex, fragment, uniforms) constructor

Wrong:

const shader = Shader.from(vertex, fragment, { uTime: 1 });

Correct:

const shader = Shader.from({
  gl: { vertex, fragment },
  resources: {
    uniforms: new UniformGroup({
      uTime: { value: 1, type: "f32" },
    }),
  },
});

v8 requires an options object with gl/gpu programs and resources. The positional API was removed.

[CRITICAL] UniformGroup without type annotation

Wrong:

new UniformGroup({ uTime: 1 });

Correct:

new UniformGroup({ uTime: { value: 1, type: "f32" } });

Every uniform requires an explicit { value, type } pair. Omitting the type causes a runtime error: "Uniform type undefined is not supported."

[HIGH] UBO with unsupported types or wrong structure

UBO mode supports f32 and i32 based types (scalars and vectors). u32 is not in the supported UniformGroup type list and will throw. Matrices are float-only (mat*<f32>). Samplers cannot be placed in UBOs.

The struct name and field order must exactly match the shader's UBO declaration. Mismatches produce garbled rendering with no error.

[HIGH] Putting textures in UniformGroup

Wrong:

new UniformGroup({
  uTexture: { value: texture, type: "f32" },
});

Correct:

const shader = Shader.from({
  gl: { vertex, fragment },
  resources: {
    uTexture: texture.source,
    uSampler: texture.source.style,
    myUniforms: new UniformGroup({
      uAlpha: { value: 1.0, type: "f32" },
    }),
  },
});

Textures are resources, not uniforms. Pass texture.source (TextureSource) and texture.source.style (TextureStyle) as top-level resource entries.

API Reference

所有檔案

2 個檔案

安裝 pixijs-custom-rendering

請下載並將技能檔案解壓縮至您的 .claude/skills/ 目錄中。

下載 ZIP

複製儲存庫並將技能檔案複製到您的專案中。

git clone https://github.com/pixijs/pixijs/tree/dev/skills/pixijs-custom-rendering # Copy the skill folder to .claude/skills/ or .codex/skills/

複製 複製
快速設定: 將技能資料夾複製到 .claude/skills/,Claude 會自動偵測並使用該技能
儲存庫 pixijs/pixijs

相關技能

v4-new-features
更新時間 2026-08-04
pixijs-application
更新時間 2026-08-04
multica-creating-agents
更新時間 2026-08-12
agent-project-board-sync
更新時間 2026-08-03
OR