mirror of
https://github.com/wahyd4/three.js.git
synced 2026-08-09 04:56:01 +10:00
Moved shadow map into separate plugin.
This is still pretty rough, will need to clean it more.
This commit is contained in:
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
@@ -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 ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user