/** * @author alteredq / http://alteredqualia.com/ */ THREE.DepthPassPlugin = function () { this.enabled = false; this.renderTarget = null; var _gl, _renderer, _lights, _webglObjects, _webglObjectsImmediate, _depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin, _frustum = new THREE.Frustum(), _projScreenMatrix = new THREE.Matrix4(), _renderList = []; this.init = function ( renderer, lights, webglObjects, webglObjectsImmediate ) { _gl = renderer.context; _renderer = renderer; _lights = lights; _webglObjects = webglObjects; _webglObjectsImmediate = webglObjectsImmediate; 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.state.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.length = 0; projectObject(scene, scene, camera); // render regular objects var objectMaterial, useMorphing, useSkinning; for ( j = 0, jl = _renderList.length; j < jl; j ++ ) { webglObject = _renderList[ j ]; object = webglObject.object; buffer = webglObject.buffer; // todo: create proper depth material for particles if ( object instanceof THREE.PointCloud && ! object.customDepthMaterial ) continue; objectMaterial = getObjectMaterial( object ); if ( objectMaterial ) _renderer.setMaterialFaces( object.material ); useMorphing = object.geometry.morphTargets !== undefined && 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, _lights, fog, material, buffer, object ); } else { _renderer.renderBuffer( camera, _lights, fog, material, buffer, object ); } } // set matrices and render immediate objects for ( j = 0, jl = _webglObjectsImmediate.length; j < jl; j ++ ) { webglObject = _webglObjectsImmediate[ j ]; object = webglObject.object; if ( object.visible ) { object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); _renderer.renderImmediateObject( camera, _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 ); }; function projectObject(scene, object,camera) { if ( object.visible ) { var webglObjects = _webglObjects[object.id]; if (webglObjects && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) { for (var i = 0, l = webglObjects.length; i < l; i ++) { var webglObject = webglObjects[i]; object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); _renderList.push(webglObject); } } for (var i = 0, l = object.children.length; i < l; i ++) { projectObject(scene, object.children[i], camera); } } } // 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; }; };