|
@@ -118,178 +118,180 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
var light = _lights[ i ];
|
|
var light = _lights[ i ];
|
|
|
|
|
|
- if ( light.castShadow === false ) continue;
|
|
|
|
-
|
|
|
|
- var shadow = light.shadow;
|
|
|
|
- var shadowCamera = shadow.camera;
|
|
|
|
- var shadowMapSize = shadow.mapSize;
|
|
|
|
-
|
|
|
|
- if ( light instanceof THREE.PointLight ) {
|
|
|
|
-
|
|
|
|
- faceCount = 6;
|
|
|
|
- isPointLight = true;
|
|
|
|
-
|
|
|
|
- var vpWidth = shadowMapSize.x / 4.0;
|
|
|
|
- var vpHeight = shadowMapSize.y / 2.0;
|
|
|
|
-
|
|
|
|
- // These viewports map a cube-map onto a 2D texture with the
|
|
|
|
- // following orientation:
|
|
|
|
- //
|
|
|
|
- // xzXZ
|
|
|
|
- // y Y
|
|
|
|
- //
|
|
|
|
- // X - Positive x direction
|
|
|
|
- // x - Negative x direction
|
|
|
|
- // Y - Positive y direction
|
|
|
|
- // y - Negative y direction
|
|
|
|
- // Z - Positive z direction
|
|
|
|
- // z - Negative z direction
|
|
|
|
-
|
|
|
|
- // positive X
|
|
|
|
- cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
|
|
|
|
- // negative X
|
|
|
|
- cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
|
|
|
|
- // positive Z
|
|
|
|
- cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
|
|
|
|
- // negative Z
|
|
|
|
- cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
|
|
|
|
- // positive Y
|
|
|
|
- cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
|
|
|
|
- // negative Y
|
|
|
|
- cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
-
|
|
|
|
- faceCount = 1;
|
|
|
|
- isPointLight = false;
|
|
|
|
|
|
+ if ( light.castShadow === true ) {
|
|
|
|
+
|
|
|
|
+ var shadow = light.shadow;
|
|
|
|
+ var shadowCamera = shadow.camera;
|
|
|
|
+ var shadowMapSize = shadow.mapSize;
|
|
|
|
+
|
|
|
|
+ if ( light instanceof THREE.PointLight ) {
|
|
|
|
+
|
|
|
|
+ faceCount = 6;
|
|
|
|
+ isPointLight = true;
|
|
|
|
+
|
|
|
|
+ var vpWidth = shadowMapSize.x / 4.0;
|
|
|
|
+ var vpHeight = shadowMapSize.y / 2.0;
|
|
|
|
+
|
|
|
|
+ // These viewports map a cube-map onto a 2D texture with the
|
|
|
|
+ // following orientation:
|
|
|
|
+ //
|
|
|
|
+ // xzXZ
|
|
|
|
+ // y Y
|
|
|
|
+ //
|
|
|
|
+ // X - Positive x direction
|
|
|
|
+ // x - Negative x direction
|
|
|
|
+ // Y - Positive y direction
|
|
|
|
+ // y - Negative y direction
|
|
|
|
+ // Z - Positive z direction
|
|
|
|
+ // z - Negative z direction
|
|
|
|
+
|
|
|
|
+ // positive X
|
|
|
|
+ cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // negative X
|
|
|
|
+ cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // positive Z
|
|
|
|
+ cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // negative Z
|
|
|
|
+ cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // positive Y
|
|
|
|
+ cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
|
|
|
|
+ // negative Y
|
|
|
|
+ cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- if ( shadow.map === null ) {
|
|
|
|
|
|
+ faceCount = 1;
|
|
|
|
+ isPointLight = false;
|
|
|
|
|
|
- var shadowFilter = THREE.LinearFilter;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- if ( scope.type === THREE.PCFSoftShadowMap ) {
|
|
|
|
|
|
+ if ( shadow.map === null ) {
|
|
|
|
|
|
- shadowFilter = THREE.NearestFilter;
|
|
|
|
|
|
+ var shadowFilter = THREE.LinearFilter;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( scope.type === THREE.PCFSoftShadowMap ) {
|
|
|
|
|
|
- var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };
|
|
|
|
|
|
+ shadowFilter = THREE.NearestFilter;
|
|
|
|
|
|
- shadow.map = new THREE.WebGLRenderTarget( shadowMapSize.x, shadowMapSize.y, pars );
|
|
|
|
- shadow.matrix = new THREE.Matrix4();
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- //
|
|
|
|
|
|
+ var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };
|
|
|
|
|
|
- if ( light instanceof THREE.SpotLight ) {
|
|
|
|
|
|
+ shadow.map = new THREE.WebGLRenderTarget( shadowMapSize.x, shadowMapSize.y, pars );
|
|
|
|
+ shadow.matrix = new THREE.Matrix4();
|
|
|
|
|
|
- shadowCamera.aspect = shadowMapSize.x / shadowMapSize.y;
|
|
|
|
|
|
+ //
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( light instanceof THREE.SpotLight ) {
|
|
|
|
|
|
- shadowCamera.updateProjectionMatrix();
|
|
|
|
|
|
+ shadowCamera.aspect = shadowMapSize.x / shadowMapSize.y;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var shadowMap = shadow.map;
|
|
|
|
- var shadowMatrix = shadow.matrix;
|
|
|
|
|
|
+ shadowCamera.updateProjectionMatrix();
|
|
|
|
|
|
- _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
|
|
|
|
- shadowCamera.position.copy( _lightPositionWorld );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- _renderer.setRenderTarget( shadowMap );
|
|
|
|
- _renderer.clear();
|
|
|
|
|
|
+ var shadowMap = shadow.map;
|
|
|
|
+ var shadowMatrix = shadow.matrix;
|
|
|
|
|
|
- // render shadow map for each cube face (if omni-directional) or
|
|
|
|
- // run a single pass if not
|
|
|
|
|
|
+ _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
|
|
|
|
+ shadowCamera.position.copy( _lightPositionWorld );
|
|
|
|
|
|
- for ( var face = 0; face < faceCount; face ++ ) {
|
|
|
|
|
|
+ _renderer.setRenderTarget( shadowMap );
|
|
|
|
+ _renderer.clear();
|
|
|
|
|
|
- if ( isPointLight ) {
|
|
|
|
|
|
+ // render shadow map for each cube face (if omni-directional) or
|
|
|
|
+ // run a single pass if not
|
|
|
|
|
|
- _lookTarget.copy( shadowCamera.position );
|
|
|
|
- _lookTarget.add( cubeDirections[ face ] );
|
|
|
|
- shadowCamera.up.copy( cubeUps[ face ] );
|
|
|
|
- shadowCamera.lookAt( _lookTarget );
|
|
|
|
- var vpDimensions = cube2DViewPorts[ face ];
|
|
|
|
- _renderer.setViewport( vpDimensions.x, vpDimensions.y, vpDimensions.z, vpDimensions.w );
|
|
|
|
|
|
+ for ( var face = 0; face < faceCount; face ++ ) {
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ if ( isPointLight ) {
|
|
|
|
|
|
- _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
|
- shadowCamera.lookAt( _lookTarget );
|
|
|
|
|
|
+ _lookTarget.copy( shadowCamera.position );
|
|
|
|
+ _lookTarget.add( cubeDirections[ face ] );
|
|
|
|
+ shadowCamera.up.copy( cubeUps[ face ] );
|
|
|
|
+ shadowCamera.lookAt( _lookTarget );
|
|
|
|
+ var vpDimensions = cube2DViewPorts[ face ];
|
|
|
|
+ _renderer.setViewport( vpDimensions.x, vpDimensions.y, vpDimensions.z, vpDimensions.w );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
|
+ shadowCamera.lookAt( _lookTarget );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ shadowCamera.updateMatrixWorld();
|
|
|
|
+ shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
|
|
|
|
|
|
- shadowCamera.updateMatrixWorld();
|
|
|
|
- shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
|
|
|
|
|
|
+ // compute shadow matrix
|
|
|
|
|
|
- // 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.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.multiply( shadowCamera.projectionMatrix );
|
|
|
|
+ shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
|
|
|
|
|
|
- shadowMatrix.multiply( shadowCamera.projectionMatrix );
|
|
|
|
- shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
|
|
|
|
|
|
+ // update camera matrices and frustum
|
|
|
|
|
|
- // update camera matrices and frustum
|
|
|
|
|
|
+ _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
|
|
|
|
+ _frustum.setFromMatrix( _projScreenMatrix );
|
|
|
|
|
|
- _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
|
|
|
|
- _frustum.setFromMatrix( _projScreenMatrix );
|
|
|
|
|
|
+ // set object matrices & frustum culling
|
|
|
|
|
|
- // set object matrices & frustum culling
|
|
|
|
|
|
+ _renderList.length = 0;
|
|
|
|
|
|
- _renderList.length = 0;
|
|
|
|
|
|
+ projectObject( scene, shadowCamera );
|
|
|
|
|
|
- projectObject( scene, shadowCamera );
|
|
|
|
|
|
+ // render shadow map
|
|
|
|
+ // render regular objects
|
|
|
|
|
|
- // render shadow map
|
|
|
|
- // render regular objects
|
|
|
|
|
|
+ for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
|
|
|
|
|
|
- for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
|
|
|
|
|
|
+ var object = _renderList[ j ];
|
|
|
|
+ var geometry = _objects.update( object );
|
|
|
|
+ var material = object.material;
|
|
|
|
|
|
- var object = _renderList[ j ];
|
|
|
|
- var geometry = _objects.update( object );
|
|
|
|
- var material = object.material;
|
|
|
|
|
|
+ if ( material instanceof THREE.MeshFaceMaterial ) {
|
|
|
|
|
|
- if ( material instanceof THREE.MeshFaceMaterial ) {
|
|
|
|
|
|
+ var groups = geometry.groups;
|
|
|
|
+ var materials = material.materials;
|
|
|
|
|
|
- var groups = geometry.groups;
|
|
|
|
- var materials = material.materials;
|
|
|
|
|
|
+ for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
|
|
|
|
|
|
- for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
|
|
|
|
|
|
+ var group = groups[ k ];
|
|
|
|
+ var groupMaterial = materials[ group.materialIndex ];
|
|
|
|
|
|
- var group = groups[ k ];
|
|
|
|
- var groupMaterial = materials[ group.materialIndex ];
|
|
|
|
|
|
+ if ( groupMaterial.visible === true ) {
|
|
|
|
|
|
- if ( groupMaterial.visible === true ) {
|
|
|
|
|
|
+ var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld );
|
|
|
|
+ _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, group );
|
|
|
|
|
|
- var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld );
|
|
|
|
- _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, group );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld );
|
|
|
|
+ _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, null );
|
|
|
|
|
|
- var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld );
|
|
|
|
- _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, null );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ // We must call _renderer.resetGLState() at the end of each iteration of
|
|
|
|
+ // the light loop in order to force material updates for each light.
|
|
|
|
+ _renderer.resetGLState();
|
|
|
|
|
|
- //We must call _renderer.resetGLState() at the end of each iteration of
|
|
|
|
- // the light loop in order to force material updates for each light.
|
|
|
|
- _renderer.resetGLState();
|
|
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|