javascript three.js ssao

javascript - SSAO y escenas mĂșltiples en Three.JS



(0)

Estoy atascado en este problema y he estado trabajando en ello y buscándolo durante horas.

Intento renderizar mi escena, usando EffectComposer, para que mis objetos de fondo no tengan SSAO (en mi proyecto real, es una ciudad de procedimientos) y mis objetos en primer plano (que en mi proyecto real son dos edificios a los que quiero llamar y que tienen un material diferente) TENGA SSAO.

Como puede ver en el siguiente violín, el cubo azul (que es parte de la escena bg) está cubierto por el renderizado SSAO del cubo rojo (que está en la escena FG). Obviamente, este efecto no es deseable.

¿Cómo hago para que esto funcione correctamente?

¡Gracias!

-Adán

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(); }

Actualizar:

Traté de agregar el bgScene con un material de anulación de negro al renderizado de objetivo de profundidad, solo para ver si oscurecería el SSAO. http://jsfiddle.net/5d7Lk7eu/1/ - aunque es difícil de ver en este violín (pero puedo verlo en la escena de mi proyecto real) ... ¿qué representa en realidad la representación dentro de los objetos bgScene de una silueta de fgScene? , y ya no hace que el SSAO pase completamente sobre el bgScene. Entonces, siento que estoy más cerca, pero todavía estoy atascado.

Actualización 2: *

La siguiente imagen (donde se puede ver que la máscara de Marte se muestra a través de la Tierra) es quizás un ejemplo visual más claro del problema (aunque este no usa SSAO, pero creo que los dos problemas están relacionados):