提交 c16ce4b2 编写于 作者: A alteredq

Moved shadow map into separate plugin.

This is still pretty rough, will need to clean it more.
上级 4be5880b
/**
* @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;
};
/**
* @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 ++;
}
}
};
};
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册