ThreeJS后处理怎么在开启/关闭的过程有淡入淡出的效果?

Number of views 50

我想将整个场景做灰度处理,因为我想把它作为基础效果对切换其它后处理效果时作为中间的过渡效果。应用灰度后处理时渲染效果是正确的,

var effectColorify,
    copyPass;

    effectColorify = new THREE.ShaderPass(THREE.ColorifyShader);
    effectColorify.uniforms['color'].value.setRGB(0.8, 0.8, 0.8); // Grayscale

    copyPass = new THREE.ShaderPass(THREE.CopyShader);
    copyPass.renderToScreen = true;

    this.composerGrayscale = new THREE.EffectComposer(this.engine.renderer);
    this.composerGrayscale.addPass(this.renderPass);
    this.composerGrayscale.addPass(effectColorify);
    this.composerGrayscale.addPass(copyPass);

但是没法做到淡入淡出,我想应该加个透明度调整的对应接口,但是具体怎么做我心里没底。

2 Answers

可以对着色器添加透明度调整的接口,具体定义如下:

// 50% scene-color, 50% shader-color.
effectColorify.uniforms['opacity'].value = 0.5; 

这是我对ColorifyShader调整后的着色器代码,你可以复制到ColorifyShader.js,默认的不透明度是1.0:

THREE.ColorifyShader = {
    uniforms: {
        "tDiffuse": { type: "t", value: null },
        "color":    { type: "c", value: new THREE.Color( 0xffffff ) },
        "opacity":  { type: "f", value: 1.0 }
    },
    vertexShader: [
        "varying vec2 vUv;",
        "void main() {",
            "vUv = uv;",
            "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0           );",
        "}"
    ].join("\n"),

    fragmentShader: [
        "uniform float opacity;",
        "uniform vec3 color;",
        "uniform sampler2D tDiffuse;",
        "varying vec2 vUv;",
        "void main() {",
            "vec4 texel = texture2D( tDiffuse, vUv );",
            "vec3 luma = vec3( 0.299, 0.587, 0.114 );",
            "float v = dot( texel.xyz, luma );",
            "vec3 finalColor = vec3(",
                "(opacity * v * color.x) + ((1.0 - opacity) * texel.x),",
                "(opacity * v * color.y) + ((1.0 - opacity) * texel.y),",
                "(opacity * v * color.z) + ((1.0 - opacity) * texel.z)",
            ");",
            "gl_FragColor = vec4( finalColor, texel.w );",
        "}"
    ].join("\n")
};

要在Three.js后处理中实现灰度效果的淡入淡出,可以通过在ShaderPass中添加一个控制透明度的uniform来实现。你可以使用一个介于0和1之间的值来控制灰度效果的强度,然后通过改变这个值来实现淡入淡出的效果。

首先,你需要修改你的着色器代码,以便能够控制灰度效果的透明度。你可以在现有的ColorifyShader基础上添加一个新的uniform,例如alpha,来控制灰度效果的透明度。

这里是一个简单的例子:

  1. 定义一个新的着色器,包含alpha透明度控制:

    THREE.ColorifyShaderWithAlpha = {
    uniforms: THREE.UniformsUtils.merge([
    THREE.ColorifyShader.uniforms,
    {
      alpha: { value: 1.0 } // 添加一个控制透明度的uniform
    }
    ]),
    vertexShader: THREE.ColorifyShader.vertexShader,
    fragmentShader: `
    uniform float alpha;
    void main() {
      vec4 color = texture2D(map, vUv);
      gl_FragColor = colorFilter(color);
      gl_FragColor.a *= alpha; // 应用透明度
    }
    `
    };
    
    1. 修改你的代码以使用新的着色器,并添加透明度控制: javascript var effectColorify, copyPass; effectColorify = new THREE.ShaderPass(THREE.ColorifyShaderWithAlpha); effectColorify.uniforms['color'].value.setRGB(0.8, 0.8, 0.8); // 灰度 effectColorify.uniforms['alpha'].value = 1.0; // 初始透明度为1 copyPass = new THREE.ShaderPass(THREE.CopyShader); copyPass.renderToScreen = true; this.composerGrayscale = new THREE.EffectComposer(this.engine.renderer); this.composerGrayscale.addPass(this.renderPass); this.composerGrayscale.addPass(effectColorify); this.composerGrayscale.addPass(copyPass); // 控制淡入淡出的函数 function fadeInOut(alpha) { effectColorify.uniforms['alpha'].value = alpha; this.composerGrayscale.render(); }
  2. 调用fadeInOut函数来实现淡入淡出效果: “`javascript // 淡入 for (let i = 0; i <= 1; i += 0.01) { fadeInOut(i); requestAnimationFrame(fadeInOut.bind(null, i)); }

// 或者淡出 for (let i = 1; i >= 0; i -= 0.01) { fadeInOut(i); requestAnimationFrame(fadeInOut.bind(null, i)); } “`

通过这种方式,你可以控制灰度效果的透明度,从而实现淡入淡出的效果。注意,这里的例子使用了简单的线性变化,你可以根据需要调整动画的速度或曲线。