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

如何复用three.js片元着色器输出实现正确的盒子模糊效果

问题根源

你当前的代码核心问题是blurv函数内采样的还是原始的uTexture纹理,并没有用到blurh输出的水平模糊结果——垂直方向采样的上下邻域像素都是原始图的像素,只有当前点用了水平模糊后的结果,所以最终看起来只有垂直模糊效果。


问题1:如何复用水平模糊的输出作为垂直模糊的输入

盒模糊的高效实现标准方案是双Pass渲染,单Pass内你无法拿到其他像素点的水平模糊结果,必须把第一步的水平模糊结果存为纹理,再做垂直模糊:

  1. Three.js侧准备两个帧缓冲:创建两个和画布尺寸一致的WebGLRenderTarget,用于存储中间渲染结果。
  2. 第一Pass水平模糊:用水平模糊着色器,输入原始纹理,把渲染结果写入第一个帧缓冲,此时这个帧缓冲的纹理就是全图水平模糊后的结果。
  3. 第二Pass垂直模糊:用垂直模糊着色器,输入第一Pass输出的纹理,把渲染结果写入第二个帧缓冲或者直接输出到屏幕,得到最终的完整盒模糊效果。

对应着色器可以简化为通用的单方向模糊实现,不需要同时写两个函数:

// 通用单方向模糊函数,dir为模糊方向:vec2(1.0, 0.0)水平,vec2(0.0, 1.0)垂直
void blur(in vec4 inColor, out vec4 outColor, int r, vec2 dir) {
    vec4 sum = vec4(0.0);
    float weight = 1.0 / float(r * 2 + 1);
    for(int i = -r; i <= r; i++) {
        vec2 offset = dir * float(i) / uResolution;
        vec2 sampleUv = clamp(vUv + offset, 0.0, 1.0);
        sum += texture2D(uTexture, sampleUv);
    }
    outColor = sum * weight;
}

// 水平模糊Pass的main:
void main() {
    int r = 200;
    blur(gl_FragColor, gl_FragColor, r, vec2(1.0, 0.0));
}

// 垂直模糊Pass的main:
void main() {
    int r = 200;
    blur(gl_FragColor, gl_FragColor, r, vec2(0.0, 1.0));
}

Three.js侧的核心调用逻辑参考:

const rt1 = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);
const rt2 = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);
// 第一Pass渲染到rt1
renderer.setRenderTarget(rt1);
renderer.render(blurScene, blurCamera);
// 把rt1的纹理传给垂直模糊的着色器
verticalBlurMaterial.uniforms.uTexture.value = rt1.texture;
// 第二Pass直接渲染到屏幕
renderer.setRenderTarget(null);
renderer.render(blurScene, blurCamera);

问题2:片元着色器如何存储变量供后续使用

分两种场景:

  • 同个片元内部使用:直接定义局部变量即可,比如vec4 tempBlurResult;,变量仅在当前片元的着色器执行周期内有效,只能供当前片元的后续代码读取。
  • 跨片元/跨Pass使用:必须通过WebGLRenderTarget把整帧的渲染结果存储为纹理,后续Pass的着色器采样这个纹理,就能拿到上一步所有片元的输出结果,这也是GPU做多步后处理的标准实现方式。

如果你的模糊半径很小,可以用单Pass直接采样周围r*r的像素实现盒模糊,不需要中间帧缓冲,但半径200的场景下双Pass的性能是单Pass的200倍,优先用双Pass方案。

内容的提问来源于stack exchange,提问作者jiopjina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 22:45:07