You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pixi.js复现ShaderToy着色器时遇循环初始化错误求助

用Pixi.js复现ShaderToy着色器的问题解决

1. 修复for循环语法错误

你遇到的'for' : Invalid init declaration错误,是因为GLSL ES 1.0(对应旧版Pixi.js常用的WebGL1环境)不允许在for循环的初始化部分单独使用赋值表达式(O *= 0.)。

原ShaderToy代码里的O*=0.是用来重置颜色变量,但你的代码已经在循环前将O初始化为vec4(0.0),可以直接移除循环初始化里的O *= 0.,修改后的循环如下:

for(; i < 12.; O += length(min(r.y/abs(F),r)) / 300.0*(cos(++t+i+vec4(0,1,2,0))*l+l)) {
    F *= mat2(cos(l*.2-i++*--t/1e2+vec4(0,33,11,0)));
}

如果后续代码需要保留重置逻辑,可将O *= 0.移到循环前面:

O *= 0.;
for(; i < 12.; O += length(min(r.y/abs(F),r)) / 300.0*(cos(++t+i+vec4(0,1,2,0))*l+l)) {
    F *= mat2(cos(l*.2-i++*--t/1e2+vec4(0,33,11,0)));
}

2. 关于fragCoord和fragColor的对应关系

ShaderToy里的fragCoord对应GLSL中的gl_FragCoord,fragColor对应gl_FragColor,你代码里的用法是正确的:

  • gl_FragCoord的原点在画布左下角,和ShaderToy的坐标系统一致;
  • 你代码中F += F - r等价于F = 2.0 * gl_FragCoord.xy - iResolution.xy,和原ShaderToy中(fragCoord - 0.5*iResolution)的逻辑类似,仅缩放比例不同,不影响语法正确性。

3. Pixi.js完整适配步骤

编写适配后的片段着色器

修改后的片段着色器(兼容GLSL ES 1.0):

precision mediump float;
uniform vec2 uResolution; // Pixi.js默认分辨率uniform
uniform float uTime; // Pixi.js默认时间uniform

void main(){
    vec4 O = vec4(0.0);
    vec2 F = gl_FragCoord.xy;
    vec2 r = uResolution.xy;
    float i = .3;
    float l = length(F += F - r) / r.y + i;
    float t = uTime;

    O *= 0.;
    for(; i < 12.; O += length(min(r.y/abs(F), r)) / 300.0 * (cos(++t + i + vec4(0,1,2,0)) * l + l)) {
        F *= mat2(cos(l*.2 - i++ * --t/1e2 + vec4(0,33,11,0)));
    }
    gl_FragColor = O;
}

在Pixi.js中应用着色器

通过创建Filter来应用自定义着色器:

import { Application, Filter, Sprite, Graphics } from 'pixi.js';

const app = new Application({ width: 800, height: 600 });
document.body.appendChild(app.view);

// 使用Pixi默认顶点着色器
const vertexShader = `
attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat3 projectionMatrix;
varying vec2 vTextureCoord;
void main(void) {
    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
    vTextureCoord = aTextureCoord;
}
`;

// 传入上面修改后的片段着色器代码
const customFilter = new Filter(vertexShader, fragmentShader);

// 创建全屏精灵承载滤镜
const sprite = Sprite.from(app.renderer.generateTexture(
    new Graphics().beginFill(0xffffff).drawRect(0, 0, 800, 600)
));
sprite.filters = [customFilter];
app.stage.addChild(sprite);

// 实时更新时间和分辨率uniform
app.ticker.add(() => {
    customFilter.uniforms.uTime = app.ticker.lastTime / 1000;
    customFilter.uniforms.uResolution = [app.screen.width, app.screen.height];
});

4. 版本相关说明

这个错误确实和旧版Pixi.js有关:

  • 旧版Pixi.js(v5及更早)默认使用WebGL1(GLSL ES 1.0),对for循环语法限制更严格,不允许在初始化部分使用非声明类表达式;
  • 新版Pixi.js(v6+)支持WebGL2(GLSL ES 3.0),语法限制更少,原ShaderToy的循环写法可直接使用。如果项目允许,升级到最新版Pixi.js也能解决该问题。

内容的提问来源于stack exchange,提问作者Stéphane Laurent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:47:49