فهرست منبع

Moved shadow map into separate plugin.

This is still pretty rough, will need to clean it more.
alteredq 14 سال پیش
والد
کامیت
c16ce4b26a
2فایلهای تغییر یافته به همراه303 افزوده شده و 0 حذف شده
  1. 59 0
      src/core/Frustum.js
  2. 244 0
      src/extras/plugins/ShadowMapPlugin.js

+ 59 - 0
src/core/Frustum.js

@@ -0,0 +1,59 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.Frustum = function ( ) {
+
+	this.planes = [
+
+		new THREE.Vector4(),
+		new THREE.Vector4(),
+		new THREE.Vector4(),
+		new THREE.Vector4(),
+		new THREE.Vector4(),
+		new THREE.Vector4()
+
+	];
+
+};
+
+THREE.Frustum.prototype.setFromMatrix = function ( m ) {
+
+	var i, plane,
+	planes = this.planes;
+
+	planes[ 0 ].set( m.n41 - m.n11, m.n42 - m.n12, m.n43 - m.n13, m.n44 - m.n14 );
+	planes[ 1 ].set( m.n41 + m.n11, m.n42 + m.n12, m.n43 + m.n13, m.n44 + m.n14 );
+	planes[ 2 ].set( m.n41 + m.n21, m.n42 + m.n22, m.n43 + m.n23, m.n44 + m.n24 );
+	planes[ 3 ].set( m.n41 - m.n21, m.n42 - m.n22, m.n43 - m.n23, m.n44 - m.n24 );
+	planes[ 4 ].set( m.n41 - m.n31, m.n42 - m.n32, m.n43 - m.n33, m.n44 - m.n34 );
+	planes[ 5 ].set( m.n41 + m.n31, m.n42 + m.n32, m.n43 + m.n33, m.n44 + m.n34 );
+
+	for ( i = 0; i < 6; i ++ ) {
+
+		plane = planes[ i ];
+		plane.divideScalar( Math.sqrt( plane.x * plane.x + plane.y * plane.y + plane.z * plane.z ) );
+
+	}
+
+};
+
+THREE.Frustum.prototype.contains = function ( object ) {
+
+	var distance,
+	planes = this.planes,
+	matrix = object.matrixWorld,
+	radius = - object.geometry.boundingSphere.radius * Math.max( object.scale.x, Math.max( object.scale.y, object.scale.z ) );
+
+	for ( var i = 0; i < 6; i ++ ) {
+
+		distance = planes[ i ].x * matrix.n14 + planes[ i ].y * matrix.n24 + planes[ i ].z * matrix.n34 + planes[ i ].w;
+		if ( distance <= radius ) return false;
+
+	}
+
+	return true;
+
+};
+

+ 244 - 0
src/extras/plugins/ShadowMapPlugin.js

@@ -0,0 +1,244 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.ShadowMapPlugin = function ( ) {
+
+	var _gl, _renderer,
+
+	_depthMaterial, _depthMaterialMorph,
+
+	_cameraLight,
+
+	_frustum = new THREE.Frustum(),
+
+	_projScreenMatrix = new THREE.Matrix4();
+
+	this.shadowMatrix = [];
+	this.shadowMap = [];
+
+	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,
+		program, buffer, material,
+		webglObject, object, light,
+
+		shadowIndex = 0,
+
+		lights = scene.lights,
+		fog = null;
+
+		if ( ! _cameraLight ) {
+
+			_cameraLight = new THREE.PerspectiveCamera( _renderer.shadowCameraFov, _renderer.shadowMapWidth / _renderer.shadowMapHeight, _renderer.shadowCameraNear, _renderer.shadowCameraFar );
+
+		}
+
+		for ( i = 0, il = lights.length; i < il; i ++ ) {
+
+			light = lights[ i ];
+
+			if ( light.castShadow && light instanceof THREE.SpotLight ) {
+
+				if ( ! this.shadowMap[ shadowIndex ] ) {
+
+					var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
+
+					this.shadowMap[ shadowIndex ] = new THREE.WebGLRenderTarget( _renderer.shadowMapWidth, _renderer.shadowMapHeight, pars );
+					this.shadowMatrix[ shadowIndex ] = new THREE.Matrix4();
+
+				}
+
+				shadowMap = this.shadowMap[ shadowIndex ];
+				shadowMatrix = this.shadowMatrix[ shadowIndex ];
+
+				_cameraLight.position.copy( light.position );
+				_cameraLight.lookAt( light.target.position );
+
+				if ( _cameraLight.parent == null ) {
+
+					console.warn( "Camera is not on the Scene. Adding it..." );
+					scene.add( _cameraLight );
+
+					if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
+
+				}
+
+				_cameraLight.matrixWorldInverse.getInverse( _cameraLight.matrixWorld );
+
+				// 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( _cameraLight.projectionMatrix );
+				shadowMatrix.multiplySelf( _cameraLight.matrixWorldInverse );
+
+				// render shadow map
+
+				if ( ! _cameraLight._viewMatrixArray ) _cameraLight._viewMatrixArray = new Float32Array( 16 );
+				_cameraLight.matrixWorldInverse.flattenToArray( _cameraLight._viewMatrixArray );
+
+				if ( ! _cameraLight._projectionMatrixArray ) _cameraLight._projectionMatrixArray = new Float32Array( 16 );
+				_cameraLight.projectionMatrix.flattenToArray( _cameraLight._projectionMatrixArray );
+
+				_projScreenMatrix.multiply( _cameraLight.projectionMatrix, _cameraLight.matrixWorldInverse );
+				_frustum.setFromMatrix( _projScreenMatrix );
+
+				_renderer.setRenderTarget( shadowMap );
+
+				// using arbitrary clear color in depth pass
+				// creates variance in shadows
+
+				_gl.clearColor( 1, 0, 1, 1 );
+				//_gl.clearColor( 0, 0, 0, 1 );
+
+				_renderer.clear();
+
+				var clearColor = _renderer.getClearColor(),
+					clearAlpha = _renderer.getClearAlpha();
+
+				_gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
+
+				// set matrices & frustum culling
+
+				jl = scene.__webglObjects.length;
+
+				for ( j = 0; j < jl; j ++ ) {
+
+					webglObject = scene.__webglObjects[ 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( _cameraLight.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
+
+							webglObject.render = true;
+
+						}
+
+					}
+
+				}
+
+				// render regular objects
+
+				_renderer.setDepthTest( true );
+				_renderer.setBlending( THREE.NormalBlending ); // maybe blending should be just disabled?
+
+				//_gl.cullFace( _gl.FRONT );
+
+				for ( j = 0; j < jl; j ++ ) {
+
+					webglObject = scene.__webglObjects[ 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;
+
+						}
+
+						_renderer.renderBuffer( _cameraLight, lights, fog, material, buffer, object );
+
+					}
+
+				}
+
+				// set matrices and render immediate objects
+
+				jl = scene.__webglObjectsImmediate.length;
+
+				for ( j = 0; j < jl; j ++ ) {
+
+					webglObject = scene.__webglObjectsImmediate[ j ];
+					object = webglObject.object;
+
+					if ( object.visible && object.castShadow ) {
+
+						_currentGeometryGroupHash = -1;
+
+						if( object.matrixAutoUpdate ) {
+
+							object.matrixWorld.flattenToArray( object._objectMatrixArray );
+
+						}
+
+						object._modelViewMatrix.multiplyToArray( _cameraLight.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
+
+						_renderer.setObjectFaces( object );
+
+						program = _renderer.setProgram( _cameraLight, lights, fog, _depthMaterial, object );
+
+						if ( object.immediateRenderCallback ) {
+
+							object.immediateRenderCallback( program, _gl, _frustum );
+
+						} else {
+
+							object.render( function( object ) { _renderer.renderBufferImmediate( object, program, _depthMaterial.shading ); } );
+
+						}
+
+					}
+
+				}
+
+				//_gl.cullFace( _gl.BACK );
+
+				shadowIndex ++;
+
+			}
+
+		}
+
+	};
+
+};

粤ICP备19079148号