htmlthree.jsaframewebvrpost-processing

Implementing Three.js SSAOPass in AFrame


I was able to successfully integrate Threejs Effect composer in aframe as a component by exporting everything as THREE.Effectcomposer, THREE.SSAOPass etc. and adding the effect inside a aframe component and i tweaked the AFrame renderer to update the effects in the scene. OutlinePass from threejs worked fine in this code but SSAO is not working and i don't get any errors. Please someone help me figure out the problem. the code for SSAOPass looks like this

AFRAME.registerComponent('ssao', {

  init: function () {
    this.el.addEventListener('that', evt => this.onEnter());
    this.el.addEventListener('mouseleave', evt => this.onLeave());
    setTimeout(() => this.el.emit("that"), 2000);
  },
  onEnter: function () {
    const scene = this.el.sceneEl.object3D;
    const camera = this.el.sceneEl.camera;
    const renderer = this.el.sceneEl.renderer;
    const render = renderer.render;
    const composer = new THREE.EffectComposer(renderer);
    //let renderPass = new THREE.RenderPass(scene, camera);
    //let outlinePass = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    const ssaoPass = new THREE.SSAOPass( scene, camera, window.innerWidth, window.innerHeight );
    //composer.addPass(renderPass);
    //composer.addPass(outlinePass);
    ssaoPass.kernelRadius = 16;
        composer.addPass( ssaoPass );
    // let objects = [];
    // this.el.object3D.traverse(node => {
    //   if (!node.isMesh) return;
    //   objects.push(node);
    // });
    // outlinePass.selectedObjects = objects;
    // outlinePass.renderToScreen = true;
    // outlinePass.edgeStrength = this.data.strength;
    // outlinePass.edgeGlow = this.data.glow;
    // outlinePass.visibleEdgeColor.set(this.data.color);
    // HACK the AFRAME render method (a bit ugly)
    const clock = new THREE.Clock();
    this.originalRenderMethod = render;
    let calledByComposer = false;
        renderer.render = function () {
      if (calledByComposer) {
        render.apply(renderer, arguments);
      } else {
        calledByComposer = true;
        composer.render(clock.getDelta());
        calledByComposer = false;
      }
    };
  },
  onLeave: function () {
    this.el.sceneEl.renderer.render = this.originalRenderMethod;
  },
  remove: function () {
    this.onLeave();
  }
});

I have also created a glitch project which i am sharing here. Please feel free to join and collaborate in my project Edit link: https://glitch.com/edit/#!/accessible-torpid-partridge Site link:https://accessible-torpid-partridge.glitch.me

Thanks in advance


Solution

  • The code is correct, all you need is to tweak the exposed SSAOShader uniforms:
    SSAOPass.kernelRadius, SSAOPass.minDistance, SSAOPass.maxDistance - like in the Three.js example.

    Keep in mind - the scale in the example is huge, so the values will need to be different in a default aframe scene.

    It's a good idea to be able to dynamically update a component (via setAttribute() if you properly handle updates), so you can see what's going on in realtime. Something like I did here - SSAO in a-frame (also based on Don McCurdys gist.

    I've used some basic HTML elements, most threejs examples use dat.GUI - it is made for demo / debug tweaks.