【问题标题】:How to reuse the three.js fragment shader output如何重用three.js片段着色器输出
【发布时间】:2021-08-22 05:14:05
【问题描述】:

我是 three.js 中的新 glsl 着色器,现在尝试在网格纹理上制作简单快速的模糊效果。这是我的片段着色器代码:

void blurh(in vec4 inh, out vec4 outh, int r) {
    for(int x = -r; x < r+1; x++) {
        float coordx = vUv[0] + float(x) / uResolution[0];
        coordx = max(0.0, min(1.0, coordx));
        inh += texture2D(uTexture, vec2 (coordx, vUv[1]));
    }
    outh = inh / float(r + r + 1);
}

void blurv(in vec4 inv, out vec4 outv, int r) {
    for(int y = -r; y < r+1; y++) {
        float coordy = vUv[1] + float(y) / uResolution[1];
        coordy = max(0.0, min(1.0, coordy));
        inv += texture2D(uTexture, vec2 (vUv[0], coordy));
    }
    outv = inv / float(r + r + 1);
}

void main() {
    int r = 200; // radius
    gl_FragColor = texture2D(uTexture, vUv);
    blurh(gl_FragColor, gl_FragColor, r);
    blurv(gl_FragColor, gl_FragColor, r);
}
输出结果: 它应该给我一个框模糊,但它只是在垂直方向上模糊。 似乎垂直模糊功能没有使用水平模糊结果作为输入。 所以第一个问题是,如何重用水平模糊函数输出作为垂直模糊函数的输入?其次,如何在片段着色器中存储/保存一些变量以供以后使用?

【问题讨论】:

    标签: javascript three.js glsl fragment-shader


    【解决方案1】:

    请注意,存储库已经提供了模糊着色器。所以你可以使用后处理管道来达到预期的效果:

    let camera, scene, composer;
    
    let mesh;
    
    init();
    animate();
    
    function init() {
    
      camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
      camera.position.z = 1;
    
      scene = new THREE.Scene();
    
      const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
      const material = new THREE.MeshNormalMaterial();
    
      mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
    
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);
    
      composer = new THREE.EffectComposer(renderer);
    
      const renderPass = new THREE.RenderPass(scene, camera);
      const effectHBlur = new THREE.ShaderPass(THREE.HorizontalBlurShader);
      const effectVBlur = new THREE.ShaderPass(THREE.VerticalBlurShader);
      effectHBlur.uniforms['h'].value = 1 / window.innerWidth;
      effectVBlur.uniforms['v'].value = 1 / window.innerHeight;
    
      composer.addPass(renderPass);
      composer.addPass(effectHBlur);
      composer.addPass(effectVBlur);
    
    }
    
    function animate() {
    
      requestAnimationFrame(animate);
    
      mesh.rotation.x += 0.01;
      mesh.rotation.y += 0.02;
    
      composer.render();
    
    }
    body {
          margin: 0;
    }
    <script src="https://cdn.jsdelivr.net/npm/three@0.129/build/three.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.129/examples/js/postprocessing/EffectComposer.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.129/examples/js/postprocessing/ShaderPass.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.129/examples/js/postprocessing/RenderPass.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.129/examples/js/shaders/HorizontalBlurShader.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.129/examples/js/shaders/VerticalBlurShader.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.129/examples/js/shaders/CopyShader.js"></script>

    如果您不想使用效果器,则必须使用普通渲染目标。含义:

    • 首先将场景渲染到渲染目标中(美丽通道)
    • 应用水平模糊并渲染到下一个渲染目标
    • 应用垂直模糊并渲染到屏幕

    所以你必须将你当前的着色器一分为二。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 2021-04-27
      相关资源
      最近更新 更多