SSAO和Three.JS中的多个场景

时间:2014-09-17 21:25:02

标签: javascript three.js ssao

我一直坚持这个问题,并且已经开始研究并研究它几个小时了。

我正在尝试使用EffectComposer渲染我的场景,以便我的背景对象没有SSAO(在我的真实项目中,它是一个程序城市)和我的前景对象(在我的真实项目中是两个建筑物我想要呼唤,并且有不同的材料)请有SSAO。

正如您在下面的小提琴中看到的那样,蓝色立方体(它是bg场景的一部分)被红色立方体的SSAO渲染(在FG场景中)覆盖。显然,这种效果是不可取的。

如何使其正常工作?

谢谢!

- 亚当


http://jsfiddle.net/Lbddvnsp/1/

var renderTargetParameters, renderTarget, renderBackground, renderModel, clearMask, renderMask, depthMaterial, depthTarget, composer;
var container, camera, bgScene, fgScene, renderer;

init();
initSSAO();
addObjects();
animate();

function initSSAO() {

    // Depth

    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;

    // Post-processing

    // create a custom render target with a stencil buffer
    // the stencil buffer allows for masking to take place
    renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: true };
    renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, renderTargetParameters );
    composer = new THREE.EffectComposer( renderer, renderTarget );

    // add both foreground and background rendering to the composer
    renderBackground = new THREE.RenderPass( bgScene, camera );
    renderModel = new THREE.RenderPass( fgScene, camera );
    // set clear to false while rendering the model to preserve buffer data
    // the information in the stencil buffer is used for the masking pass
    renderModel.clear = false;

    clearMask = new THREE.ClearMaskPass();
    renderMask = new THREE.MaskPass( fgScene, camera );

    depthTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat } );

    var ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
    ssaoPass.uniforms[ 'tDepth' ].value = depthTarget;
    ssaoPass.uniforms[ 'size' ].value.set( window.innerWidth, window.innerHeight );
    ssaoPass.uniforms[ 'cameraNear' ].value = camera.near;
    ssaoPass.uniforms[ 'cameraFar' ].value = camera.far;
    ssaoPass.uniforms[ 'aoClamp' ].value = 0.4;
    //ssaoPass.renderToScreen = true;

    // fast aproximate anti-alising
    var fxaaPass = new THREE.ShaderPass( THREE.FXAAShader );
    fxaaPass.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
    fxaaPass.renderToScreen = true;

    composer.addPass( renderBackground );
    composer.addPass( renderModel );
    composer.addPass( renderMask );
    composer.addPass( ssaoPass );
    composer.addPass( clearMask );
    composer.addPass( fxaaPass );
}

var cube;

function addObjects() {

    // Floor (background scene)
    var floorGeom = new THREE.PlaneGeometry(1000, 1000, 4, 4);
    var floorMat = new THREE.MeshPhongMaterial({color: 0xff0000});

    var floor = new THREE.Mesh(floorGeom, floorMat);
    floor.position.y = -120;
    floor.rotation.x = - 90 * Math.PI / 180;

    bgScene.add(floor);

    var cubeGeom = new THREE.CubeGeometry(100, 100, 100);
    var cubeMat = new THREE.MeshPhongMaterial({color: 0x0000ff});

    var cube2 = new THREE.Mesh(cubeGeom, cubeMat);
    cube2.position.x = 300;

    bgScene.add(cube2)

     // SSAO Objects (foreground scene)
    var cubeGeom = new THREE.CubeGeometry(200, 200, 200);
    var cubeMat = new THREE.MeshLambertMaterial({color: 0x00ff00});

    cube = new THREE.Mesh(cubeGeom, cubeMat);
    cube.rotation.x = - 90 * Math.PI / 180;

    fgScene.add(cube);

}

function init() {

    // Container

    container = document.createElement( 'div' );
    document.body.appendChild( container );

    // Scene 

    bgScene = new THREE.Scene();
    fgScene = new THREE.Scene();

    // Camera

    camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 40000 );
    camera.position.x = 2000;
    camera.position.y = 1000;
    camera.position.z = -1000;

    fgScene.add(camera);

    camera.lookAt( fgScene.position );

    // Lights
    // Screwed around with settings of all lights to get a similar feel to the deferred example

    var ambientLight = new THREE.AmbientLight( 0x404040 );
    ambientLight.color.setHSL( 0.1, 0.1, 0.4 );
    fgScene.add( ambientLight );
    bgScene.add(ambientLight.clone());

    var directionalLight = new THREE.DirectionalLight( 0xffffff );
    directionalLight.color.setHSL( 0.1, 0.1, 0.5 );
    directionalLight.position.x = 1000;
    directionalLight.position.y = 1000;
    directionalLight.position.z = 750;
    directionalLight.position.normalize();
    fgScene.add( directionalLight );
    bgScene.add(directionalLight.clone());

    var directionalLight2 = new THREE.DirectionalLight( 0x808080 );
    directionalLight2.color.setHSL( 0.1, 0.1, 0.45 );
    directionalLight2.position.x = - 1000;
    directionalLight2.position.y = 1000;
    directionalLight2.position.z = - 750;
    directionalLight2.position.normalize();
    fgScene.add( directionalLight2 );
    bgScene.add(directionalLight2.clone());

    var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.65 );
    hemiLight.color.setHSL( 0.6, 0.35, 0.7 );
    hemiLight.groundColor.setHSL( 0.095, 0.5, 0.6 );
    hemiLight.position.set( 0, 600, 0 );
    fgScene.add( hemiLight );
    bgScene.add(hemiLight.clone());

    // Renderer

    renderer = new THREE.WebGLRenderer({
        antialias: false
    });
    renderer.autoClear = false;
    renderer.setSize( window.innerWidth, window.innerHeight );

    // Gamma settings make things look 'nicer' for some reason
    renderer.gammaInput = true;
    renderer.gammaOutput = true;

    //renderer.physicallyBasedShading = true;

    container.appendChild(renderer.domElement);

}

function render() {

    renderer.clear();
    //renderer.render( bgScene, camera );

    //renderer.clear( false, true, false );

    //camera.position.x += 1;
    camera.lookAt( cube.position );

    fgScene.overrideMaterial = depthMaterial;
    // set force clear to true here so the depth buffer is not preserved
    renderer.render( fgScene, camera, depthTarget, true );    
    fgScene.overrideMaterial = null;

    composer.render();

}

function animate() {

    window.requestAnimationFrame( animate );

    render();

}

更新

我尝试使用黑色覆盖材料添加bgScene到深度目标渲染,只是为了看它是否会遮挡SSAO。 http://jsfiddle.net/5d7Lk7eu/1/ - 尽管在这个小提琴中很难看到(但我可以在我真实的项目场景中看到它)......实际上在bgScene对象中渲染的是fgScene的一个轮廓,它不再渲染SSAO完全通过bgScene。所以,我觉得我离我更近了,但我仍然被困住了。


更新2:*

下图(你可以看到火星面具通过地球显示)可能是一个更清晰的问题视觉例子(尽管这个没有使用SSAO,但我相信这两个问题是相关的):< / p>

example of issue

0 个答案:

没有答案