ThreeJS SSAO with SSAA

吃可爱长大的小学妹 提交于 2019-12-22 01:02:34

问题


i'd like to integrate the SSAO-Shader (Screen Space Ambient Occlusion) into my antialiasing render stack (Super Sampling Anti-Aliasing). The AA is necessary for high-quality rendering, the default antialiasing delivered by my gpu isn't always sufficient. Now i've already integrated SSAO into the usual render process, but my new goal is to combine both techniques.

For this, i've set up a fiddle. The first EffectComposer renders the scene onto a renderTarget with twice the resolution of the canvas. From this, i'd like to use the depthTarget for SSAO. The final step is to draw the rendered image to a plane with the size of the canvas, which results in downsampling, so we have the antialiasing effect.

Link to the fiddle: SSAO+SSAA

The stack is set up like this:

function initManualAntiAliasing2(width, height, wStepMax, hStepMax) {

    var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };

    // render image with double size
    var rw1 = wStepMax * width;
    var rh1 = hStepMax * height;
    var myRenderTarget1 = new THREE.WebGLRenderTarget( rw1, rh1, parameters );
    var myRenderTargetSSAO = new THREE.WebGLRenderTarget( rw1, rh1, parameters );

    composer = new THREE.EffectComposer( renderer, myRenderTarget1 );
    var renderPass = new THREE.RenderPass(scene, camera);
    composer.addPass(renderPass);

    var renderSceneSSAO = new THREE.TexturePass(composer.renderTarget2);

    composerSSAO = new THREE.EffectComposer( renderer, myRenderTargetSSAO );
    composerSSAO.addPass(renderSceneSSAO);


    var depthShader = THREE.ShaderLib[ "depthRGBA" ];
    var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );

    depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
    depthMaterial.blending = THREE.NoBlending;

    var parametersDepth = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };

    myRenderTargetDepth = new THREE.WebGLRenderTarget( rw1, rh1, parametersDepth );

    ssaoEffect = new THREE.ShaderPass( THREE.SSAOShader );
    ssaoEffect.uniforms[ 'tDepth' ].value = myRenderTargetDepth;
    ssaoEffect.uniforms[ 'size' ].value.set( rw1, rh1 );
    ssaoEffect.uniforms[ 'cameraNear' ].value = camera.near;
    ssaoEffect.uniforms[ 'cameraFar' ].value = camera.far;
    ssaoEffect.uniforms[ 'aoClamp' ].value = 0.4;
    ssaoEffect.uniforms[ 'lumInfluence' ].value = 0.4;
    ssaoEffect.uniforms[ 'onlyAO' ].value = 1; // debug: when ssao shader works, we will definitely see it with this option
    ssaoEffect.renderToScreen = true;
    composerSSAO.addPass( ssaoEffect );

    var renderScene1 = new THREE.TexturePass(composer.renderTarget2);

    // sample down to screen size
    composer1 = new THREE.EffectComposer(renderer);
    composer1.addPass(renderScene1);

    var renderScene2 = new THREE.TexturePass(composer1.renderTarget2);

    var effectCopy = new THREE.ShaderPass( THREE.CopyShader );
    effectCopy.renderToScreen = true;
    composer1.addPass(effectCopy);
}

The render function is set up like this:

function renderAA2() {
    renderer.autoClear = false;
    renderer.clear();
    scene.overrideMaterial = myRenderTargetDepth;
    composer.render();
    composerSSAO.render();
    scene.overrideMaterial = null;
    composer1.render();
}

I have not found a similar situation, so my question: how to set up the whole stack, so that ssao is used.

Greetings, Thomas


回答1:


If anyone is still looking for a solution i succeed in combine the SSAO pass with the MSAA pass by using the two examples available on three.js website.

Here is how the code appears:

function initPostprocessing() {
    // Setup render pass
    var renderPass = new THREE.RenderPass( scene, camera );
    effectComposer = new THREE.EffectComposer( renderer );

    // Setup depth pass
    depthMaterial = new THREE.MeshDepthMaterial();
    depthMaterial.depthPacking = THREE.RGBADepthPacking;
    depthMaterial.blending = THREE.NoBlending;

    var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter,format: THREE.RGBAFormat, stencilBuffer: false };
    depthRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );

    // Setup Anti Aliasing pass
    msaaRenderPass = new THREE.ManualMSAARenderPass( scene, camera );
    msaaRenderPass.unbiased = false;
    msaaRenderPass.sampleLevel = 2;

    // Setup Ambient Occlusion pass
    ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
    ssaoPass.renderToScreen = true;
    ssaoPass.uniforms[ 'tDepth' ].value = depthRenderTarget.texture;
    ssaoPass.uniforms[ 'size' ].value.set( window.innerWidth, window.innerHeight );
    ssaoPass.uniforms[ 'cameraNear' ].value = camera.near;
    ssaoPass.uniforms[ 'cameraFar' ].value = camera.far;
    ssaoPass.uniforms[ 'onlyAO' ].value = false;
    ssaoPass.uniforms[ 'aoClamp' ].value = 1.0;
    ssaoPass.uniforms[ 'lumInfluence' ].value = 0.7;

    effectComposer.addPass( renderPass );
    effectComposer.addPass( msaaRenderPass );
    effectComposer.addPass( ssaoPass );
}
function updatePostprocessing() {
    scene.overrideMaterial = depthMaterial;
    renderer.render( scene, camera, depthRenderTarget, true );
    scene.overrideMaterial = null;
    effectComposer.render();
}

The two examples mixed in this code are:

https://threejs.org/examples/?q=post#webgl_postprocessing_msaa

https://threejs.org/examples/?q=post#webgl_postprocessing_ssao

I hope it could help somebody else 'cause it took me hours to solve this problem.



来源:https://stackoverflow.com/questions/35205339/threejs-ssao-with-ssaa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!