/** * @author alteredq / http://alteredqualia.com/ */ THREE.DepthPassPlugin = function () { this.enabled = false; this.renderTarget = null; var _gl, _renderer, _depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin, _frustum = new THREE.Frustum(), _projScreenMatrix = new THREE.Matrix4(); this.init = function ( renderer ) { _gl = renderer.context; _renderer = renderer; var depthShader = THREE.ShaderLib[ "depthRGBA" ]; var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms ); _depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } ); _depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } ); _depthMaterialSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, skinning: true } ); _depthMaterialMorphSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true, skinning: true } ); _depthMaterial._shadowPass = true; _depthMaterialMorph._shadowPass = true; _depthMaterialSkin._shadowPass = true; _depthMaterialMorphSkin._shadowPass = true; }; this.render = function ( scene, camera ) { if ( ! this.enabled ) return; this.update( scene, camera ); }; this.update = function ( scene, camera ) { var i, il, j, jl, n, program, buffer, material, webglObject, object, light, renderList, fog = null; // set GL state for depth map _gl.clearColor( 1, 1, 1, 1 ); _gl.disable( _gl.BLEND ); _renderer.setDepthTest( true ); // update scene if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); // update camera matrices and frustum camera.matrixWorldInverse.getInverse( camera.matrixWorld ); _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); _frustum.setFromMatrix( _projScreenMatrix ); // render depth map _renderer.setRenderTarget( this.renderTarget ); _renderer.clear(); // set object matrices & frustum culling renderList = scene.__webglObjects; for ( j = 0, jl = renderList.length; j < jl; j ++ ) { webglObject = renderList[ j ]; object = webglObject.object; webglObject.render = false; if ( object.visible ) { if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.intersectsObject( object ) ) { object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); webglObject.render = true; } } } // render regular objects var objectMaterial, useMorphing, useSkinning; for ( j = 0, jl = renderList.length; j < jl; j ++ ) { webglObject = renderList[ j ]; if ( webglObject.render ) { object = webglObject.object; buffer = webglObject.buffer; // todo: create proper depth material for particles if ( object instanceof THREE.ParticleSystem && !object.customDepthMaterial ) continue; objectMaterial = getObjectMaterial( object ); if ( objectMaterial ) _renderer.setMaterialFaces( object.material ); useMorphing = object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets; useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning; if ( object.customDepthMaterial ) { material = object.customDepthMaterial; } else if ( useSkinning ) { material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin; } else if ( useMorphing ) { material = _depthMaterialMorph; } else { material = _depthMaterial; } if ( buffer instanceof THREE.BufferGeometry ) { _renderer.renderBufferDirect( camera, scene.__lights, fog, material, buffer, object ); } else { _renderer.renderBuffer( camera, scene.__lights, fog, material, buffer, object ); } } } // set matrices and render immediate objects renderList = scene.__webglObjectsImmediate; for ( j = 0, jl = renderList.length; j < jl; j ++ ) { webglObject = renderList[ j ]; object = webglObject.object; if ( object.visible ) { object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); _renderer.renderImmediateObject( camera, scene.__lights, fog, _depthMaterial, object ); } } // restore GL state var clearColor = _renderer.getClearColor(), clearAlpha = _renderer.getClearAlpha(); _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha ); _gl.enable( _gl.BLEND ); }; // For the moment just ignore objects that have multiple materials with different animation methods // Only the first material will be taken into account for deciding which depth material to use function getObjectMaterial( object ) { return object.material instanceof THREE.MeshFaceMaterial ? object.material.materials[ 0 ] : object.material; }; };