aframe icon indicating copy to clipboard operation
aframe copied to clipboard

how to use EffectComposer/UnrealBloomPass in Aframe

Open JetsomMa opened this issue 4 years ago • 2 comments

Description:

i write the threejs code in vue + Aframe, but it`s not work and no error

mounted(){
    this.sceneElement = document.querySelector("a-scene");

    if (this.sceneElement.hasLoaded) {
      this.senceLoaded2();
    } else {
      this.sceneElement.addEventListener('loaded', this.senceLoaded2);
    }
},
method:{
    senceLoaded2 () {
      var params = {
        exposure: 1.5,
        bloomStrength: 100,
        bloomThreshold: 0,
        bloomRadius: 0.8
      }

      let renderer = this.sceneElement.renderer

      let camera = this.sceneElement.camera
      let scene = this.sceneElement.object3D

      // 添加渲染场景到渲染器
      var renderScene = new window.THREE.RenderPass(scene, camera);

      let bloomPass = new window.THREE.UnrealBloomPass(new window.THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
      bloomPass.renderToScreen = true;
      bloomPass.threshold = params.bloomThreshold;
      bloomPass.strength = params.bloomStrength;
      bloomPass.radius = params.bloomRadius;

      let composer = new window.THREE.EffectComposer(renderer);
      composer.setSize(window.innerWidth, window.innerHeight);
      composer.addPass(renderScene);
      composer.addPass(bloomPass);

      window.AFRAME.effectComposer = composer

      // 创建Bloom的Material
      let meshMaterialBloom = new window.THREE.MeshBasicMaterial({
        color: "blue",
        transparent: false,
        opacity: 1
      });

      var geometryBloom = new window.THREE.BoxGeometry(10, 10, 10);
      var cubeBloom = new window.THREE.Mesh(geometryBloom, meshMaterialBloom);
      // 设置到第二通道
      cubeBloom.layers.enable(1);
      scene.add(cubeBloom);
    },
}

i so rewrited Aframe/core/sence/a-sence.js[function render] on my location, code as

/**
     * The render loop.
     *
     * Updates animations.
     * Updates behaviors.
     * Renders with request animation frame.
     */
    render: {
      value: function (time, frame) {
        var renderer = this.renderer;

        this.frame = frame;
        this.delta = this.clock.getDelta();
        this.time = this.clock.elapsedTime * 1000;

        if (this.isPlaying) { this.tick(this.time, this.delta * 1000); }
        var savedBackground = null;
        if (this.is('ar-mode')) {
          // In AR mode, don't render the default background. Hide it, then
          // restore it again after rendering.
          savedBackground = this.object3D.background;
          this.object3D.background = null;
        }

        + if(window.AFRAME.effectComposer){
        + renderer.clear();
        +  this.camera.layers.set(window.AFRAME.BLOOM_SCENE);
        +  window.AFRAME.effectComposer.render(this.delta);
        +  renderer.clearDepth();
        +  this.camera.layers.set(window.AFRAME.ENTIRE_SCENE);
        +  renderer.render(this.object3D, this.camera);
        }
        
        -  renderer.render(this.object3D, this.camera);
        if (savedBackground) {
          this.object3D.background = savedBackground;
        }
      },
      writable: true
    }

my copy example1: https://wow.techbrood.com/fiddle/54961

my copy example2: https://blog.csdn.net/qq_39503511/article/details/111029877

need help !

  • A-Frame Version: 1.2.0
  • Platform / Device: vue/mac pro
  • Reproducible Code Snippet or URL:

JetsomMa avatar Jul 31 '21 20:07 JetsomMa

英语不太好,我就直接写中文了,

以上问题我已经解决,希望对有需要的人有帮助

经过多天研读源码,加上看threejs范例,最终花了五天时间找到了方案【之前没怎么做过这方面底层】 现在有一个建议提给Aframe官方:我们对WebGLRenderer的封装太过死板了,虽然有onBeforeRender和onAfterRender这两个函数,但是不足以支撑我们的特殊场景

1、在我们需要做多通道渲染时候,每个通道都会调用renderer.render(),如果我们想依靠onBeforeRender和onAfterRender解决这一问题,这会导致递归,造成栈溢出,而且a-sence.js中render()的renderer.render(this.object3D, this.camera);调用会冗余 2、如果我们通过修改源码禁用a-sence.js中的play()的renderer.setAnimationLoop(this.render);然后自己去控制render调用,这样看似能解决我们的问题,但是如果项目中有自己写的shader,且自己的shader有法线方向扩散的特效等类似功能,这些功能又会失效,并非一个合理的解决办法

【最终解决方案:核心代码】 1、修改a-sence.js中render()

// 马少杰兼容添加---注意:此方案的引入致使renderer的onBeforeRender和onAfterRender这两个钩子函数已不可再使用,因为bloomComposer和finalComposer的render()都会默认调用renderer.render(),从而引发递归,造成栈溢出
        if (renderer.bloomComposer && renderer.finalComposer) {
          // 复制需要晕光的纹理涂层
          this.object3D.traverse(this.darkenNonBloomed);
          renderer.bloomComposer.render();
          this.object3D.traverse(this.restoreMaterial);
          // 晕光纹理和原图合并渲染
          renderer.finalComposer.render();
        } else {
          renderer.render(this.object3D, this.camera);
        }
        // 马少杰兼容添加--结束

        // 马少杰修改前原版代码
        // renderer.render(this.object3D, this.camera);

2、在自己项目中声明你自己需要的Composer,挂载到renderer对象

_ 强烈呼吁:希望Aframe官网能开一个回调,能够重构renderer.render()地方的执行代码,这样我们就可以在不修改Aframe源码的基础上支持各种threejs的Composer引用了 _

关键的副作用-注意:此方案的引入致使renderer的onBeforeRender和onAfterRender这两个钩子函数已不可再使用,因为bloomComposer和finalComposer的render()都会默认调用renderer.render(),从而引发递归,造成栈溢出

如有码友有类似问题需要解决,可以详询我:wechat/QQ:1215458034

JetsomMa avatar Aug 05 '21 03:08 JetsomMa

Post processing still depends on pending THREE work mrdoob/three.js#18846

dmarcos avatar Aug 09 '21 05:08 dmarcos