/src/extras/plugins/ShadowMapPlugin.js
JavaScript | 250 lines | 133 code | 106 blank | 11 comment | 37 complexity | 287f2b3b3cb0869b2611d4b6fbb2fea5 MD5 | raw file
Possible License(s): MIT, CC-BY-3.0, Apache-2.0
- /**
- * @author alteredq / http://alteredqualia.com/
- */
- THREE.ShadowMapPlugin = function ( ) {
- var _gl,
- _renderer,
- _depthMaterial, _depthMaterialMorph,
- _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 } );
- _depthMaterial._shadowPass = true;
- _depthMaterialMorph._shadowPass = true;
- };
- this.render = function ( scene, camera ) {
- if ( ! ( _renderer.shadowMapEnabled && _renderer.shadowMapAutoUpdate ) ) return;
- this.update( scene, camera );
- };
- this.update = function ( scene, camera ) {
- var i, il, j, jl,
- shadowMap, shadowMatrix, shadowCamera,
- program, buffer, material,
- webglObject, object, light,
- renderList,
- lights = scene.lights,
- fog = null;
- // set GL state for depth map
- _gl.clearColor( 1, 1, 1, 1 );
- _gl.disable( _gl.BLEND );
- if ( _renderer.shadowMapCullFrontFaces ) _gl.cullFace( _gl.FRONT );
- _renderer.setDepthTest( true );
- // render depth map
- for ( i = 0, il = lights.length; i < il; i ++ ) {
- light = lights[ i ];
- if ( ! light.castShadow ) continue;
- if ( ! light.shadowMap ) {
- var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
- light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
- light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
- light.shadowMatrix = new THREE.Matrix4();
- }
- if ( ! light.shadowCamera ) {
- if ( light instanceof THREE.SpotLight ) {
- light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
- } else if ( light instanceof THREE.DirectionalLight ) {
- light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );
- } else {
- console.error( "Unsupported light type for shadow" );
- continue;
- }
- scene.add( light.shadowCamera );
- if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
- }
- if ( light.shadowCameraVisible && ! light.cameraHelper ) {
- light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
- light.shadowCamera.add( light.cameraHelper );
- }
- shadowMap = light.shadowMap;
- shadowMatrix = light.shadowMatrix;
- shadowCamera = light.shadowCamera;
- shadowCamera.position.copy( light.matrixWorld.getPosition() );
- shadowCamera.lookAt( light.target.matrixWorld.getPosition() );
- shadowCamera.updateMatrixWorld();
- shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
- if ( light.cameraHelper ) light.cameraHelper.lines.visible = light.shadowCameraVisible;
- if ( light.shadowCameraVisible ) light.cameraHelper.update( light.shadowCamera );
- // compute shadow matrix
- shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
- 0.0, 0.5, 0.0, 0.5,
- 0.0, 0.0, 0.5, 0.5,
- 0.0, 0.0, 0.0, 1.0 );
- shadowMatrix.multiplySelf( shadowCamera.projectionMatrix );
- shadowMatrix.multiplySelf( shadowCamera.matrixWorldInverse );
- // render shadow map
- if ( ! shadowCamera._viewMatrixArray ) shadowCamera._viewMatrixArray = new Float32Array( 16 );
- shadowCamera.matrixWorldInverse.flattenToArray( shadowCamera._viewMatrixArray );
- if ( ! shadowCamera._projectionMatrixArray ) shadowCamera._projectionMatrixArray = new Float32Array( 16 );
- shadowCamera.projectionMatrix.flattenToArray( shadowCamera._projectionMatrixArray );
- _projScreenMatrix.multiply( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
- _frustum.setFromMatrix( _projScreenMatrix );
- _renderer.setRenderTarget( shadowMap );
- _renderer.clear();
- // set 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 && object.castShadow ) {
- if ( ! ( object instanceof THREE.Mesh ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
- object.matrixWorld.flattenToArray( object._objectMatrixArray );
- object._modelViewMatrix.multiplyToArray( shadowCamera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
- webglObject.render = true;
- }
- }
- }
- // render regular objects
- for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
- webglObject = renderList[ j ];
- if ( webglObject.render ) {
- object = webglObject.object;
- buffer = webglObject.buffer;
- _renderer.setObjectFaces( object );
- if ( object.customDepthMaterial ) {
- material = object.customDepthMaterial;
- } else if ( object.geometry.morphTargets.length ) {
- material = _depthMaterialMorph;
- } else {
- material = _depthMaterial;
- }
- if ( buffer instanceof THREE.BufferGeometry ) {
- _renderer.renderBufferDirect( shadowCamera, lights, fog, material, buffer, object );
- } else {
- _renderer.renderBuffer( shadowCamera, 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.castShadow ) {
- if( object.matrixAutoUpdate ) {
- object.matrixWorld.flattenToArray( object._objectMatrixArray );
- }
- object._modelViewMatrix.multiplyToArray( shadowCamera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
- _renderer.renderImmediateObject( shadowCamera, 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 );
- if ( _renderer.shadowMapCullFrontFaces ) _gl.cullFace( _gl.BACK );
- };
- };