pixijs-custom-rendering
Use this skill when writing custom shaders, uniforms, filters, or batchers in PixiJS v8. Covers Shader.from({gl, gpu, resources}), GlProgram/GpuProgram, UniformGroup with typed uniforms (f32, vec2, mat4x4), UBO mode, textures as resources, custom Filter via Filter.from, GLSL ES 3.0 conventions (in/out, finalColor, texture()), uBackTexture sampling, pixi.js/unsafe-eval for strict CSP, custom Batcher via extensions. Triggers on: Shader, GlProgram, GpuProgram, UniformGroup, Batcher, Filter, Filter.
Security Assessment
About pixijs-custom-rendering
This skill covers writing custom shaders, uniforms, filters, and batchers in PixiJS v8. Custom shaders bind GLSL and WGSL programs to scene objects via Shader.from({ gl, gpu, resources }), with uniforms held in typed UniformGroups, textures passed as separate resources, and a single shader able to target both WebGL and WebGPU. It triggers on terms including Shader, GlProgram, GpuProgram, UniformGroup, Batcher, Filter.from, GLSL, WGSL, UBO, finalColor, uBackTexture, blendRequired, and unsafe-eval. A typical quick start pairs a UniformGroup (for example a uTime f32 uniform) with a MeshGeometry and a Mesh, updating the uniform each frame through shader.resources.uniforms.uniforms.
For dual-renderer shaders, providing gl alone targets WebGL only, gpu alone targets WebGPU only, and the compatibleRenderers bitmask is set automatically; WGSL entry-point names are arbitrary but must match the @vertex and @fragment function names. GlProgram does not auto-inject #version 300 es: if you write it yourself PixiJS preserves it and treats the source as GLSL ES 3.0, otherwise it injects WebGL1 compatibility macros. GlProgram always injects a default precision (highp vertex, mediump fragment) and the program name. GLSL ES 3.0 conventions use in/out instead of attribute/varying, texture() instead of texture2D(), and an out vec4 instead of gl_FragColor. Textures are resources rather than uniforms, with the texture's source and style passed separately under keys that match the shader binding names, and resources may also be plain objects that are auto-wrapped into UniformGroups.
UBO mode packs uniforms into a single GPU buffer (required for WebGPU, optional on WebGL2+) and supports only f32 and i32 based types with no samplers, requires an exact name and layout match with the shader, and uses new Function internally, so strict-CSP environments must import pixi.js/unsafe-eval once at startup or UBO-backed shaders will throw. Custom filters use Filter.from({ gl, resources }) as shorthand, taking only a fragment shader while PixiJS supplies a default vertex shader exposing uInputSize, uOutputFrame, uOutputTexture and the filterVertexPosition/filterTextureCoord helpers; a custom vertex shader requires the full Filter constructor with a GlProgram. Sampling the render target behind a filter requires blendRequired: true and reading uBackTexture, which forces an extra GPU copy each frame and should be enabled only when needed. The skill also introduces extending the abstract Batcher class and registering it via extensions for specialized batching, and points to references/uniform-types.md for the complete supported-type table.
FAQ
How do I make a shader work on both WebGL and WebGPU?
Provide both gl and gpu sources to Shader.from. Supplying gl alone targets WebGL only and gpu alone targets WebGPU only; the compatibleRenderers bitmask is set automatically. For WGSL, the entryPoint names are arbitrary but must match your @vertex and @fragment function names.
Does GlProgram add #version 300 es for me?
No. GlProgram does not auto-inject #version 300 es. If you write it yourself PixiJS preserves it and treats the shader as GLSL ES 3.0; otherwise it injects WebGL1 compatibility macros. It always injects a default precision (highp vertex, mediump fragment) and the program name.
How are textures passed to a custom shader?
Textures are resources, not uniforms. Pass the texture's source and style separately (for example texture.source and texture.source.style) under keys that match the binding names in the shader, and you can swap the texture at runtime by reassigning shader.resources.<key>.
What are the constraints of UBO mode?
UBO mode is required for WebGPU and optional on WebGL2+. It supports only f32 and i32 based types (no u32, matrices are float-only), cannot hold samplers or textures, and the UniformGroup name and layout must exactly match the shader's UBO block. It uses new Function internally, so strict-CSP environments must import pixi.js/unsafe-eval once at startup.
How do I sample the render target behind a filter?
Set blendRequired: true on the filter and sample uBackTexture in the fragment shader; PixiJS copies the destination pixels into that uniform before running the filter. Enable it only when needed, since it forces an extra GPU copy every frame.
Install pixijs-custom-rendering
Quick Setup:
- Copy the skill folder to
.claude/skills/ - Claude will automatically detect and use the skill
Repository
pixijs/pixijs-skills