GTAO Pass not making any effect on my 3D model

I’m trying to apply a GTAO pass on my three js scene but nothing seems to happen when I add it.
And even when I try to change the value.

I have use this example : three.js examples

And here is my code :

textureLoader = new THREE.TextureLoader();

    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    // document.body.appendChild( renderer.domElement );
    // use ref as a mount point of the Three.js scene instead of the document.body
    refContainer.current && refContainer.current.appendChild( renderer.domElement );

    const pmremGenerator = new THREE.PMREMGenerator( renderer );

    scene = new THREE.Scene();
    scene.environment = pmremGenerator.fromScene( new RoomEnvironment( renderer ), 0.04 ).texture;

    const camera = new THREE.PerspectiveCamera( 22, window.innerWidth / window.innerHeight, 0.1, 20 );
    camera.position.set( 3.62, 2.734, 3.408 );

    const controls = new OrbitControls( camera, renderer.domElement );
    controls.target.set( 0, 0, 0 );
    controls.update();
    controls.enablePan = false;
    controls.enableDamping = true;
    controls.maxPolarAngle = Math.PI;
    controls.minDistance = 1;
    controls.maxDistance = 5;

    const dirLight1 = new THREE.DirectionalLight( 0xffddcc, 3 );
    dirLight1.position.set( 1, 0.75, 0.5 );
    scene.add( dirLight1 );

    const dirLight2 = new THREE.DirectionalLight( 0xccccff, 3 );
    dirLight2.position.set( - 1, 0.75, - 0.5 );
    scene.add( dirLight2 );

    const pointLight = new THREE.PointLight( 0xff0000, Math.PI, 100, 0 );
    pointLight.position.set( -10, -10, -1 );
    scene.add( pointLight );

    const ambientLight = new THREE.AmbientLight( 0xff0000, 1 );
    scene.add( ambientLight );

    const spotLight = new THREE.SpotLight( 0xff0000, Math.PI, 0, 0.15, 1, 0 );
    spotLight.position.set( 10, 10, 10 );
    scene.add( spotLight );

    // add ambiant occlusion effect
    // based on this : https://threejs.org/examples/?q=ambient#webgl_postprocessing_gtao
    let composer = new EffectComposer( renderer );

    const width = window.innerWidth;
    const height = window.innerHeight;

    const gtaoPass = new GTAOPass( scene, camera, width, height );
    gtaoPass.output = GTAOPass.OUTPUT.Denoise;
    composer.addPass( gtaoPass );

    // Init gui
    const gui = new GUI();

    gui.add( gtaoPass, 'output', {
        'Default': GTAOPass.OUTPUT.Default,
        'Diffuse': GTAOPass.OUTPUT.Diffuse,
        'AO Only': GTAOPass.OUTPUT.AO,
        'AO Only + Denoise': GTAOPass.OUTPUT.Denoise,
        'Depth': GTAOPass.OUTPUT.Depth,
        'Normal': GTAOPass.OUTPUT.Normal
    } ).onChange( function ( value ) {
        console.log("ON CHANGE")
        console.log("change gtaoPass: " + value)
        gtaoPass.output = value;

    } );

    const aoParameters = {
        radius: 0.25,
        distanceExponent: 1.,
        thickness: 1.,
        scale: 1.,
        samples: 16,
        distanceFallOff: 1.,
        screenSpaceRadius: false,
    };
    
    const pdParameters = {
        lumaPhi: 10.,
        depthPhi: 2.,
        normalPhi: 3.,
        radius: 0.,
        radiusExponent: 1.,
        rings: 2.,
        samples: 16,
    };

    gtaoPass.updateGtaoMaterial( aoParameters );
    gtaoPass.updatePdMaterial( pdParameters );
    gui.add( gtaoPass, 'blendIntensity' ).min( 0 ).max( 1 ).step( 0.01 );
    gui.add( aoParameters, 'radius' ).min( 0.01 ).max( 1 ).step( 0.01 ).onChange( () => gtaoPass.updateGtaoMaterial( aoParameters ) );
    gui.add( aoParameters, 'distanceExponent' ).min( 1 ).max( 4 ).step( 0.01 ).onChange( () => gtaoPass.updateGtaoMaterial( aoParameters ) );
    gui.add( aoParameters, 'thickness' ).min( 0.01 ).max( 10 ).step( 0.01 ).onChange( () => gtaoPass.updateGtaoMaterial( aoParameters ) );
    gui.add( aoParameters, 'distanceFallOff' ).min( 0 ).max( 1 ).step( 0.01 ).onChange( () => gtaoPass.updateGtaoMaterial( aoParameters ) );
    gui.add( aoParameters, 'scale' ).min( 0.01 ).max( 2.0 ).step( 0.01 ).onChange( () => gtaoPass.updateGtaoMaterial( aoParameters ) );
    gui.add( aoParameters, 'samples' ).min( 2 ).max( 32 ).step( 1 ).onChange( () => gtaoPass.updateGtaoMaterial( aoParameters ) );
    gui.add( aoParameters, 'screenSpaceRadius' ).onChange( () => gtaoPass.updateGtaoMaterial( aoParameters ) );
    gui.add( pdParameters, 'lumaPhi' ).min( 0 ).max( 20 ).step( 0.01 ).onChange( () => gtaoPass.updatePdMaterial( pdParameters ) );
    gui.add( pdParameters, 'depthPhi' ).min( 0.01 ).max( 20 ).step( 0.01 ).onChange( () => gtaoPass.updatePdMaterial( pdParameters ) );
    gui.add( pdParameters, 'normalPhi' ).min( 0.01 ).max( 20 ).step( 0.01 ).onChange( () => gtaoPass.updatePdMaterial( pdParameters ) );
    gui.add( pdParameters, 'radius' ).min( 0 ).max( 32 ).step( 1 ).onChange( () => gtaoPass.updatePdMaterial( pdParameters ) );
    gui.add( pdParameters, 'radiusExponent' ).min( 0.1 ).max( 4. ).step( 0.1 ).onChange( () => gtaoPass.updatePdMaterial( pdParameters ) );
    gui.add( pdParameters, 'rings' ).min( 1 ).max( 16 ).step( 0.125 ).onChange( () => gtaoPass.updatePdMaterial( pdParameters ) );
    gui.add( pdParameters, 'samples' ).min( 2 ).max( 32 ).step( 1 ).onChange( () => gtaoPass.updatePdMaterial( pdParameters ) );
	
	window.addEventListener( 'resize', onWindowResize );
	
	const loader = new GLTFLoader();
	
	        loader.load( 'pahtTo3DModel.glb', function ( gltf ) {

            
            const box = new THREE.Box3().setFromObject( scene );
            gtaoPass.setSceneClipBox( box );
			
	}

I wonder where is the issue, is it caused by the lighting of the scene, is it caused by the material used on the object ?

Someone can give me a clue please ?

Thanks in advance :slight_smile:

I don’t see your render loop in there…

Did you properly switch out renderer.render with composer.render?

2 Likes

Hi here is my render loop :

    var animate = function () {
      requestAnimationFrame(animate);
 
      renderer.render(scene, camera);
    };

No I did not use composer.render !

It certainly explains why it does not work!
I am going to test it and let you know if it solves evything.

Thanks for your help :slight_smile:

With composer.render(scene, camera) I finally see the effect.

However I only see something when output is set to “AO Only”, if I put “Default”, I don’t see my model with his texture map on it, everything is white.

with AO only:

with Default:

Contrary to this example when the color map is shown when output is set to “Default”.
https://threejs.org/examples/webgl_postprocessing_gtao.html

Do you have any idea why ?

When I use renderer.render() instead I get a view of my 3D model with all color maps applied.

1 Like

I’m guessing all these lights might be blowing out the scene?

can you comment out all the above and try one ambient light?

  const ambientLight = new THREE.AmbientLight( 'white', 1 );
  scene.add( ambientLight );

Under many scenarios you only want a couple lights… a directional, maybe an ambient, and an environment map. You can have more, but they have to have their values chosen pretty carefully, and lights aren’t cheap, so the less you can get away with, the better your thing will perform.

Thank you so much for helping me on this subject!

I found the reason why I did not see anything when selecting “Default” output for the gtaoPass.

In my composer I just have added the gtaoPass :

const gtaoPass = new GTAOPass( scene, camera, width, height ); gtaoPass.output = GTAOPass.OUTPUT.Denoise; composer.addPass( gtaoPass );
But I also need to add the RenderPass and the OutputPass to it:

`
const renderPass = new RenderPass( scene, camera );
composer.addPass( renderPass );

const gtaoPass = new GTAOPass( scene, camera, width, height );
gtaoPass.output = GTAOPass.OUTPUT.Denoise;
composer.addPass( gtaoPass );

const outputPass = new OutputPass();
composer.addPass( outputPass );

`
And now it’s working:

I did not understand how the composer was working but with this documentation I now understand why it wasn’t working:

https://threejs.org/docs/#manual/en/introduction/How-to-use-post-processing

The RenderPass is normally placed at the beginning of the chain in order to provide the rendered scene as an input for the next post-processing step.

OutputPass is usually the last pass in the chain which performs sRGB color space conversion and optional tone mapping.

Have a nice day and thanks again :).

1 Like

Awesome! Glad you figured it out!

1 Like