ShadowMapPlugin.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. */
  4. THREE.ShadowMapPlugin = function ( ) {
  5. var _gl, _renderer,
  6. _depthMaterial, _depthMaterialMorph,
  7. _cameraLight,
  8. _frustum = new THREE.Frustum(),
  9. _projScreenMatrix = new THREE.Matrix4();
  10. this.shadowMatrix = [];
  11. this.shadowMap = [];
  12. this.init = function ( renderer ) {
  13. _gl = renderer.context;
  14. _renderer = renderer;
  15. var depthShader = THREE.ShaderLib[ "depthRGBA" ];
  16. var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
  17. _depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
  18. _depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
  19. _depthMaterial._shadowPass = true;
  20. _depthMaterialMorph._shadowPass = true;
  21. };
  22. this.render = function ( scene, camera ) {
  23. if ( ! ( _renderer.shadowMapEnabled && _renderer.shadowMapAutoUpdate ) ) return;
  24. this.update( scene, camera );
  25. };
  26. this.update = function ( scene, camera ) {
  27. var i, il, j, jl,
  28. shadowMap, shadowMatrix,
  29. program, buffer, material,
  30. webglObject, object, light,
  31. renderList,
  32. shadowIndex = 0,
  33. lights = scene.lights,
  34. fog = null;
  35. if ( ! _cameraLight ) {
  36. _cameraLight = new THREE.PerspectiveCamera( _renderer.shadowCameraFov, _renderer.shadowMapWidth / _renderer.shadowMapHeight, _renderer.shadowCameraNear, _renderer.shadowCameraFar );
  37. }
  38. for ( i = 0, il = lights.length; i < il; i ++ ) {
  39. light = lights[ i ];
  40. if ( light.castShadow && light instanceof THREE.SpotLight ) {
  41. if ( ! this.shadowMap[ shadowIndex ] ) {
  42. var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
  43. this.shadowMap[ shadowIndex ] = new THREE.WebGLRenderTarget( _renderer.shadowMapWidth, _renderer.shadowMapHeight, pars );
  44. this.shadowMatrix[ shadowIndex ] = new THREE.Matrix4();
  45. }
  46. shadowMap = this.shadowMap[ shadowIndex ];
  47. shadowMatrix = this.shadowMatrix[ shadowIndex ];
  48. _cameraLight.position.copy( light.position );
  49. _cameraLight.lookAt( light.target.position );
  50. if ( _cameraLight.parent == null ) {
  51. console.warn( "Camera is not on the Scene. Adding it..." );
  52. scene.add( _cameraLight );
  53. if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
  54. }
  55. _cameraLight.matrixWorldInverse.getInverse( _cameraLight.matrixWorld );
  56. // compute shadow matrix
  57. shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
  58. 0.0, 0.5, 0.0, 0.5,
  59. 0.0, 0.0, 0.5, 0.5,
  60. 0.0, 0.0, 0.0, 1.0 );
  61. shadowMatrix.multiplySelf( _cameraLight.projectionMatrix );
  62. shadowMatrix.multiplySelf( _cameraLight.matrixWorldInverse );
  63. // render shadow map
  64. if ( ! _cameraLight._viewMatrixArray ) _cameraLight._viewMatrixArray = new Float32Array( 16 );
  65. _cameraLight.matrixWorldInverse.flattenToArray( _cameraLight._viewMatrixArray );
  66. if ( ! _cameraLight._projectionMatrixArray ) _cameraLight._projectionMatrixArray = new Float32Array( 16 );
  67. _cameraLight.projectionMatrix.flattenToArray( _cameraLight._projectionMatrixArray );
  68. _projScreenMatrix.multiply( _cameraLight.projectionMatrix, _cameraLight.matrixWorldInverse );
  69. _frustum.setFromMatrix( _projScreenMatrix );
  70. _renderer.setRenderTarget( shadowMap );
  71. // using arbitrary clear color in depth pass
  72. // creates variance in shadows
  73. _gl.clearColor( 1, 0, 1, 1 );
  74. //_gl.clearColor( 0, 0, 0, 1 );
  75. _renderer.clear();
  76. var clearColor = _renderer.getClearColor(),
  77. clearAlpha = _renderer.getClearAlpha();
  78. _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
  79. // set matrices & frustum culling
  80. renderList = scene.__webglObjects;
  81. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  82. webglObject = renderList[ j ];
  83. object = webglObject.object;
  84. webglObject.render = false;
  85. if ( object.visible && object.castShadow ) {
  86. if ( ! ( object instanceof THREE.Mesh ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
  87. object.matrixWorld.flattenToArray( object._objectMatrixArray );
  88. object._modelViewMatrix.multiplyToArray( _cameraLight.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
  89. webglObject.render = true;
  90. }
  91. }
  92. }
  93. // render regular objects
  94. _renderer.setDepthTest( true );
  95. _renderer.setBlending( THREE.NormalBlending ); // maybe blending should be just disabled?
  96. //_gl.cullFace( _gl.FRONT );
  97. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  98. webglObject = renderList[ j ];
  99. if ( webglObject.render ) {
  100. object = webglObject.object;
  101. buffer = webglObject.buffer;
  102. _renderer.setObjectFaces( object );
  103. if ( object.customDepthMaterial ) {
  104. material = object.customDepthMaterial;
  105. } else if ( object.geometry.morphTargets.length ) {
  106. material = _depthMaterialMorph;
  107. } else {
  108. material = _depthMaterial;
  109. }
  110. _renderer.renderBuffer( _cameraLight, lights, fog, material, buffer, object );
  111. }
  112. }
  113. // set matrices and render immediate objects
  114. renderList = scene.__webglObjectsImmediate;
  115. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  116. webglObject = renderList[ j ];
  117. object = webglObject.object;
  118. if ( object.visible && object.castShadow ) {
  119. if( object.matrixAutoUpdate ) {
  120. object.matrixWorld.flattenToArray( object._objectMatrixArray );
  121. }
  122. object._modelViewMatrix.multiplyToArray( _cameraLight.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
  123. _renderer.renderImmediateObject( _cameraLight, lights, fog, _depthMaterial, object );
  124. }
  125. }
  126. //_gl.cullFace( _gl.BACK );
  127. shadowIndex ++;
  128. }
  129. }
  130. };
  131. };