|
@@ -13,36 +13,48 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
_min = new THREE.Vector3(),
|
|
|
_max = new THREE.Vector3(),
|
|
|
|
|
|
- _matrixPosition = new THREE.Vector3(),
|
|
|
+ _lookTarget = new THREE.Vector3(),
|
|
|
+ _lightPosition = new THREE.Vector3(),
|
|
|
|
|
|
_renderList = [];
|
|
|
|
|
|
+ var _depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
|
|
|
+ _distanceMaterial, _distanceMaterialMorph, _distanceMaterialSkin, _distanceMaterialMorphSkin;
|
|
|
+
|
|
|
+ var cubeDirections = [new THREE.Vector3(1,0,0), new THREE.Vector3(-1,0,0), new THREE.Vector3(0,1,0),
|
|
|
+ new THREE.Vector3(0,-1,0), new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,-1)];
|
|
|
+
|
|
|
+ var cubeUps = [new THREE.Vector3(0,-1,0), new THREE.Vector3(0,-1,0), new THREE.Vector3(0,0,1),
|
|
|
+ new THREE.Vector3(0,0,-1), new THREE.Vector3(0,-1,0), new THREE.Vector3(0,-1,0)];
|
|
|
+
|
|
|
+ var _vector4 = new THREE.Vector4();
|
|
|
+
|
|
|
// init
|
|
|
|
|
|
var depthShader = THREE.ShaderLib[ "depthRGBA" ];
|
|
|
var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
|
|
|
|
|
|
- var _depthMaterial = new THREE.ShaderMaterial( {
|
|
|
+ _depthMaterial = new THREE.ShaderMaterial( {
|
|
|
uniforms: depthUniforms,
|
|
|
vertexShader: depthShader.vertexShader,
|
|
|
fragmentShader: depthShader.fragmentShader
|
|
|
} );
|
|
|
|
|
|
- var _depthMaterialMorph = new THREE.ShaderMaterial( {
|
|
|
+ _depthMaterialMorph = new THREE.ShaderMaterial( {
|
|
|
uniforms: depthUniforms,
|
|
|
vertexShader: depthShader.vertexShader,
|
|
|
fragmentShader: depthShader.fragmentShader,
|
|
|
morphTargets: true
|
|
|
} );
|
|
|
|
|
|
- var _depthMaterialSkin = new THREE.ShaderMaterial( {
|
|
|
+ _depthMaterialSkin = new THREE.ShaderMaterial( {
|
|
|
uniforms: depthUniforms,
|
|
|
vertexShader: depthShader.vertexShader,
|
|
|
fragmentShader: depthShader.fragmentShader,
|
|
|
skinning: true
|
|
|
} );
|
|
|
|
|
|
- var _depthMaterialMorphSkin = new THREE.ShaderMaterial( {
|
|
|
+ _depthMaterialMorphSkin = new THREE.ShaderMaterial( {
|
|
|
uniforms: depthUniforms,
|
|
|
vertexShader: depthShader.vertexShader,
|
|
|
fragmentShader: depthShader.fragmentShader,
|
|
@@ -55,6 +67,43 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
_depthMaterialSkin._shadowPass = true;
|
|
|
_depthMaterialMorphSkin._shadowPass = true;
|
|
|
|
|
|
+
|
|
|
+ var distanceShader = THREE.ShaderLib[ "distanceRGBA" ];
|
|
|
+ var distanceUniforms = THREE.UniformsUtils.clone( distanceShader.uniforms );
|
|
|
+
|
|
|
+ _distanceMaterial = new THREE.ShaderMaterial( {
|
|
|
+ uniforms: distanceUniforms,
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
+ fragmentShader: distanceShader.fragmentShader
|
|
|
+ } );
|
|
|
+
|
|
|
+ _distanceMaterialMorph = new THREE.ShaderMaterial( {
|
|
|
+ uniforms: distanceUniforms,
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
+ fragmentShader: distanceShader.fragmentShader,
|
|
|
+ morphTargets: true
|
|
|
+ } );
|
|
|
+
|
|
|
+ _distanceMaterialSkin = new THREE.ShaderMaterial( {
|
|
|
+ uniforms: distanceUniforms,
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
+ fragmentShader: distanceShader.fragmentShader,
|
|
|
+ skinning: true
|
|
|
+ } );
|
|
|
+
|
|
|
+ _distanceMaterialMorphSkin = new THREE.ShaderMaterial( {
|
|
|
+ uniforms: distanceUniforms,
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
+ fragmentShader: distanceShader.fragmentShader,
|
|
|
+ morphTargets: true,
|
|
|
+ skinning: true
|
|
|
+ } );
|
|
|
+
|
|
|
+ _distanceMaterial._shadowPass = true;
|
|
|
+ _distanceMaterialMorph._shadowPass = true;
|
|
|
+ _distanceMaterialSkin._shadowPass = true;
|
|
|
+ _distanceMaterialMorphSkin._shadowPass = true;
|
|
|
+
|
|
|
//
|
|
|
|
|
|
var scope = this;
|
|
@@ -69,6 +118,8 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
this.render = function ( scene ) {
|
|
|
|
|
|
+ var faceCount, isCube;
|
|
|
+
|
|
|
if ( scope.enabled === false ) return;
|
|
|
if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
|
|
|
|
|
@@ -98,6 +149,14 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
var light = _lights[ i ];
|
|
|
|
|
|
+ if ( light instanceof THREE.PointLight ) {
|
|
|
+ faceCount = 6;
|
|
|
+ isCube = true;
|
|
|
+ } else {
|
|
|
+ faceCount = 1;
|
|
|
+ isCube = false;
|
|
|
+ }
|
|
|
+
|
|
|
if ( ! light.castShadow ) continue;
|
|
|
|
|
|
if ( ! light.shadowMap ) {
|
|
@@ -112,8 +171,13 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };
|
|
|
|
|
|
- light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
|
|
|
- light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
|
|
|
+ if ( isCube ) {
|
|
|
+ light.shadowMap = new THREE.WebGLRenderTargetCube( light.shadowMapWidth, light.shadowMapWidth, pars );
|
|
|
+ light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapWidth );
|
|
|
+ } else {
|
|
|
+ light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
|
|
|
+ light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
|
|
|
+ }
|
|
|
|
|
|
light.shadowMatrix = new THREE.Matrix4();
|
|
|
|
|
@@ -131,8 +195,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- console.error( "THREE.ShadowMapPlugin: Unsupported light type for shadow", light );
|
|
|
- continue;
|
|
|
+ light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -153,83 +216,97 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
var shadowMatrix = light.shadowMatrix;
|
|
|
var shadowCamera = light.shadowCamera;
|
|
|
|
|
|
- //
|
|
|
+ _lightPosition.setFromMatrixPosition( light.matrixWorld );
|
|
|
+ shadowCamera.position.copy(_lightPosition);
|
|
|
+
|
|
|
+ // render shadow map for each cube face (if omni-directional) or
|
|
|
+ // run a single pass if not
|
|
|
|
|
|
- shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
|
|
|
- _matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
- shadowCamera.lookAt( _matrixPosition );
|
|
|
- shadowCamera.updateMatrixWorld();
|
|
|
+ for(var face = 0; face < faceCount; face ++){
|
|
|
+
|
|
|
+ if( isCube){
|
|
|
+ _lookTarget.copy(shadowCamera.position);
|
|
|
+ _lookTarget.add(cubeDirections[face]);
|
|
|
+ shadowCamera.up.copy(cubeUps[face]);
|
|
|
+ shadowCamera.lookAt(_lookTarget);
|
|
|
+ } else {
|
|
|
+ _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
+ shadowCamera.lookAt( _lookTarget);
|
|
|
+ }
|
|
|
|
|
|
- shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
|
|
|
+ shadowCamera.updateMatrixWorld();
|
|
|
+ shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
|
|
|
|
|
|
- //
|
|
|
+ if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
|
|
|
+ if ( light.shadowCameraVisible ) light.cameraHelper.update();
|
|
|
|
|
|
- if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
|
|
|
- if ( light.shadowCameraVisible ) light.cameraHelper.update();
|
|
|
+ // 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 );
|
|
|
+ // render shadow map
|
|
|
|
|
|
- // render shadow map
|
|
|
+ if(isCube){
|
|
|
+ shadowMap.activeCubeFace = face;
|
|
|
+ }
|
|
|
|
|
|
- _renderer.setRenderTarget( shadowMap );
|
|
|
- _renderer.clear();
|
|
|
+ _renderer.setRenderTarget( shadowMap );
|
|
|
+ _renderer.clear();
|
|
|
|
|
|
- // set object matrices & frustum culling
|
|
|
+ // set object matrices & frustum culling
|
|
|
|
|
|
- _renderList.length = 0;
|
|
|
+ _renderList.length = 0;
|
|
|
|
|
|
- projectObject( scene, shadowCamera );
|
|
|
+ projectObject( scene, shadowCamera );
|
|
|
|
|
|
+ // render regular objects
|
|
|
|
|
|
- // 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, isCube, _lightPosition);
|
|
|
+ _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial , object, group );
|
|
|
|
|
|
- _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, groupMaterial ), object, group );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
+ } else {
|
|
|
+ var depthMaterial = getDepthMaterial( object, material, isCube, _lightPosition);
|
|
|
+ _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, null );
|
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
-
|
|
|
- _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, material ), object, null );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
// restore GL state
|
|
@@ -252,43 +329,67 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
};
|
|
|
|
|
|
- function getDepthMaterial( object, material ) {
|
|
|
+ function getDepthMaterial( object, material, isCube, lightPosition) {
|
|
|
|
|
|
var geometry = object.geometry;
|
|
|
|
|
|
var useMorphing = geometry.morphTargets !== undefined && geometry.morphTargets.length > 0 && material.morphTargets;
|
|
|
var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
|
|
|
|
|
|
- var depthMaterial;
|
|
|
+ var newMaterial;
|
|
|
+
|
|
|
+ var depthMaterial = _depthMaterial;
|
|
|
+ var depthMaterialMorph = _depthMaterialMorph;
|
|
|
+ var depthMaterialSkin = _depthMaterialSkin;
|
|
|
+ var depthMaterialMorphSkin = _depthMaterialMorphSkin;
|
|
|
|
|
|
- if ( object.customDepthMaterial ) {
|
|
|
+ if ( isCube ){
|
|
|
+ depthMaterial = _distanceMaterial;
|
|
|
+ depthMaterialMorph = _distanceMaterialMorph;
|
|
|
+ depthMaterialSkin = _distanceMaterialSkin;
|
|
|
+ depthMaterialMorphSkin = _distanceMaterialMorphSkin;
|
|
|
+ }
|
|
|
|
|
|
- depthMaterial = object.customDepthMaterial;
|
|
|
+ if ( object.customDepthMaterial || object.customDistanceMaterial) {
|
|
|
+
|
|
|
+ if( isCube ){
|
|
|
+ newMaterial = object.customDistanceMaterial;
|
|
|
+ } else {
|
|
|
+ newMaterial = object.customDepthMaterial;
|
|
|
+ }
|
|
|
|
|
|
} else if ( useSkinning ) {
|
|
|
|
|
|
- depthMaterial = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
|
|
|
+ newMaterial = useMorphing ? depthMaterialMorphSkin : depthMaterialSkin;
|
|
|
|
|
|
} else if ( useMorphing ) {
|
|
|
|
|
|
- depthMaterial = _depthMaterialMorph;
|
|
|
+ newMaterial = depthMaterialMorph;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- depthMaterial = _depthMaterial;
|
|
|
+ newMaterial = depthMaterial;
|
|
|
|
|
|
}
|
|
|
|
|
|
- depthMaterial.visible = material.visible;
|
|
|
- depthMaterial.wireframe = material.wireframe;
|
|
|
- depthMaterial.wireframeLinewidth = material.wireframeLinewidth;
|
|
|
+ newMaterial.visible = material.visible;
|
|
|
+ newMaterial.wireframe = material.wireframe;
|
|
|
+ newMaterial.wireframeLinewidth = material.wireframeLinewidth;
|
|
|
|
|
|
- return depthMaterial;
|
|
|
+ if ( isCube ){
|
|
|
+ if(newMaterial.uniforms.lightPos)
|
|
|
+ {
|
|
|
+ newMaterial.uniforms.lightPos.value.copy(lightPosition);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return newMaterial;
|
|
|
|
|
|
}
|
|
|
|
|
|
function projectObject( object, camera ) {
|
|
|
|
|
|
+
|
|
|
if ( object.visible === false ) return;
|
|
|
|
|
|
if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
|
|
@@ -298,7 +399,6 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
var material = object.material;
|
|
|
|
|
|
if ( material.visible === true ) {
|
|
|
-
|
|
|
object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
|
|
|
_renderList.push( object );
|
|
|
|