问题
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