PageRenderTime 38ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/extras/plugins/ShadowMapPlugin.js

http://github.com/mrdoob/three.js
JavaScript | 250 lines | 133 code | 106 blank | 11 comment | 37 complexity | 287f2b3b3cb0869b2611d4b6fbb2fea5 MD5 | raw file
Possible License(s): MIT, CC-BY-3.0, Apache-2.0
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. */
  4. THREE.ShadowMapPlugin = function ( ) {
  5. var _gl,
  6. _renderer,
  7. _depthMaterial, _depthMaterialMorph,
  8. _frustum = new THREE.Frustum(),
  9. _projScreenMatrix = new THREE.Matrix4();
  10. this.init = function ( renderer ) {
  11. _gl = renderer.context;
  12. _renderer = renderer;
  13. var depthShader = THREE.ShaderLib[ "depthRGBA" ];
  14. var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
  15. _depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
  16. _depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
  17. _depthMaterial._shadowPass = true;
  18. _depthMaterialMorph._shadowPass = true;
  19. };
  20. this.render = function ( scene, camera ) {
  21. if ( ! ( _renderer.shadowMapEnabled && _renderer.shadowMapAutoUpdate ) ) return;
  22. this.update( scene, camera );
  23. };
  24. this.update = function ( scene, camera ) {
  25. var i, il, j, jl,
  26. shadowMap, shadowMatrix, shadowCamera,
  27. program, buffer, material,
  28. webglObject, object, light,
  29. renderList,
  30. lights = scene.lights,
  31. fog = null;
  32. // set GL state for depth map
  33. _gl.clearColor( 1, 1, 1, 1 );
  34. _gl.disable( _gl.BLEND );
  35. if ( _renderer.shadowMapCullFrontFaces ) _gl.cullFace( _gl.FRONT );
  36. _renderer.setDepthTest( true );
  37. // render depth map
  38. for ( i = 0, il = lights.length; i < il; i ++ ) {
  39. light = lights[ i ];
  40. if ( ! light.castShadow ) continue;
  41. if ( ! light.shadowMap ) {
  42. var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
  43. light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
  44. light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
  45. light.shadowMatrix = new THREE.Matrix4();
  46. }
  47. if ( ! light.shadowCamera ) {
  48. if ( light instanceof THREE.SpotLight ) {
  49. light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
  50. } else if ( light instanceof THREE.DirectionalLight ) {
  51. light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );
  52. } else {
  53. console.error( "Unsupported light type for shadow" );
  54. continue;
  55. }
  56. scene.add( light.shadowCamera );
  57. if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
  58. }
  59. if ( light.shadowCameraVisible && ! light.cameraHelper ) {
  60. light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
  61. light.shadowCamera.add( light.cameraHelper );
  62. }
  63. shadowMap = light.shadowMap;
  64. shadowMatrix = light.shadowMatrix;
  65. shadowCamera = light.shadowCamera;
  66. shadowCamera.position.copy( light.matrixWorld.getPosition() );
  67. shadowCamera.lookAt( light.target.matrixWorld.getPosition() );
  68. shadowCamera.updateMatrixWorld();
  69. shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
  70. if ( light.cameraHelper ) light.cameraHelper.lines.visible = light.shadowCameraVisible;
  71. if ( light.shadowCameraVisible ) light.cameraHelper.update( light.shadowCamera );
  72. // compute shadow matrix
  73. shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
  74. 0.0, 0.5, 0.0, 0.5,
  75. 0.0, 0.0, 0.5, 0.5,
  76. 0.0, 0.0, 0.0, 1.0 );
  77. shadowMatrix.multiplySelf( shadowCamera.projectionMatrix );
  78. shadowMatrix.multiplySelf( shadowCamera.matrixWorldInverse );
  79. // render shadow map
  80. if ( ! shadowCamera._viewMatrixArray ) shadowCamera._viewMatrixArray = new Float32Array( 16 );
  81. shadowCamera.matrixWorldInverse.flattenToArray( shadowCamera._viewMatrixArray );
  82. if ( ! shadowCamera._projectionMatrixArray ) shadowCamera._projectionMatrixArray = new Float32Array( 16 );
  83. shadowCamera.projectionMatrix.flattenToArray( shadowCamera._projectionMatrixArray );
  84. _projScreenMatrix.multiply( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
  85. _frustum.setFromMatrix( _projScreenMatrix );
  86. _renderer.setRenderTarget( shadowMap );
  87. _renderer.clear();
  88. // set matrices & frustum culling
  89. renderList = scene.__webglObjects;
  90. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  91. webglObject = renderList[ j ];
  92. object = webglObject.object;
  93. webglObject.render = false;
  94. if ( object.visible && object.castShadow ) {
  95. if ( ! ( object instanceof THREE.Mesh ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
  96. object.matrixWorld.flattenToArray( object._objectMatrixArray );
  97. object._modelViewMatrix.multiplyToArray( shadowCamera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
  98. webglObject.render = true;
  99. }
  100. }
  101. }
  102. // render regular objects
  103. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  104. webglObject = renderList[ j ];
  105. if ( webglObject.render ) {
  106. object = webglObject.object;
  107. buffer = webglObject.buffer;
  108. _renderer.setObjectFaces( object );
  109. if ( object.customDepthMaterial ) {
  110. material = object.customDepthMaterial;
  111. } else if ( object.geometry.morphTargets.length ) {
  112. material = _depthMaterialMorph;
  113. } else {
  114. material = _depthMaterial;
  115. }
  116. if ( buffer instanceof THREE.BufferGeometry ) {
  117. _renderer.renderBufferDirect( shadowCamera, lights, fog, material, buffer, object );
  118. } else {
  119. _renderer.renderBuffer( shadowCamera, lights, fog, material, buffer, object );
  120. }
  121. }
  122. }
  123. // set matrices and render immediate objects
  124. renderList = scene.__webglObjectsImmediate;
  125. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  126. webglObject = renderList[ j ];
  127. object = webglObject.object;
  128. if ( object.visible && object.castShadow ) {
  129. if( object.matrixAutoUpdate ) {
  130. object.matrixWorld.flattenToArray( object._objectMatrixArray );
  131. }
  132. object._modelViewMatrix.multiplyToArray( shadowCamera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
  133. _renderer.renderImmediateObject( shadowCamera, lights, fog, _depthMaterial, object );
  134. }
  135. }
  136. }
  137. // restore GL state
  138. var clearColor = _renderer.getClearColor(),
  139. clearAlpha = _renderer.getClearAlpha();
  140. _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
  141. _gl.enable( _gl.BLEND );
  142. if ( _renderer.shadowMapCullFrontFaces ) _gl.cullFace( _gl.BACK );
  143. };
  144. };