SSAO и несколько сцен в Three.JS

Я застрял в этой проблеме и работаю над ней и исследую ее в течение нескольких часов.

Я пытаюсь визуализировать свою сцену, используя 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, но я полагаю, что эти две проблемы связаны):

пример вопроса

0 ответов

Другие вопросы по тегам