/src/away3d/lights/shadowmaps/DirectionalShadowMapper.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 196 lines · 161 code · 29 blank · 6 comment · 10 complexity · 91ad64aae505d55d65cff7424fd21a8c MD5 · raw file

  1. package away3d.lights.shadowmaps
  2. {
  3. import away3d.arcane;
  4. import away3d.cameras.Camera3D;
  5. import away3d.cameras.lenses.FreeMatrixLens;
  6. import away3d.containers.Scene3D;
  7. import away3d.core.math.Matrix3DUtils;
  8. import away3d.core.math.Plane3D;
  9. import away3d.core.render.DepthRenderer;
  10. import away3d.lights.DirectionalLight;
  11. import flash.display3D.textures.TextureBase;
  12. import flash.geom.Matrix3D;
  13. import flash.geom.Vector3D;
  14. use namespace arcane;
  15. public class DirectionalShadowMapper extends ShadowMapperBase
  16. {
  17. protected var _overallDepthCamera:Camera3D;
  18. protected var _localFrustum:Vector.<Number>;
  19. protected var _lightOffset:Number = 10000;
  20. protected var _matrix:Matrix3D;
  21. protected var _overallDepthLens:FreeMatrixLens;
  22. protected var _snap:Number = 64;
  23. protected var _cullPlanes:Vector.<Plane3D>;
  24. protected var _minZ:Number;
  25. protected var _maxZ:Number;
  26. public function DirectionalShadowMapper()
  27. {
  28. super();
  29. _cullPlanes = new Vector.<Plane3D>();
  30. _overallDepthLens = new FreeMatrixLens();
  31. _overallDepthCamera = new Camera3D(_overallDepthLens);
  32. _localFrustum = new Vector.<Number>(8*3);
  33. _matrix = new Matrix3D();
  34. }
  35. public function get snap():Number
  36. {
  37. return _snap;
  38. }
  39. public function set snap(value:Number):void
  40. {
  41. _snap = value;
  42. }
  43. public function get lightOffset():Number
  44. {
  45. return _lightOffset;
  46. }
  47. public function set lightOffset(value:Number):void
  48. {
  49. _lightOffset = value;
  50. }
  51. /**
  52. * Depth projection matrix that projects from scene space to depth map.
  53. */
  54. arcane function get depthProjection():Matrix3D
  55. {
  56. return _overallDepthCamera.viewProjection;
  57. }
  58. /**
  59. * Depth projection matrix that projects from scene space to depth map.
  60. */
  61. arcane function get depth():Number
  62. {
  63. return _maxZ - _minZ;
  64. }
  65. override protected function drawDepthMap(target:TextureBase, scene:Scene3D, renderer:DepthRenderer):void
  66. {
  67. _casterCollector.camera = _overallDepthCamera;
  68. _casterCollector.cullPlanes = _cullPlanes;
  69. _casterCollector.clear();
  70. scene.traversePartitions(_casterCollector);
  71. renderer.render(_casterCollector, target);
  72. _casterCollector.cleanUp();
  73. }
  74. protected function updateCullPlanes(viewCamera:Camera3D):void
  75. {
  76. var lightFrustumPlanes:Vector.<Plane3D> = _overallDepthCamera.frustumPlanes;
  77. var viewFrustumPlanes:Vector.<Plane3D> = viewCamera.frustumPlanes;
  78. _cullPlanes.length = 4;
  79. _cullPlanes[0] = lightFrustumPlanes[0];
  80. _cullPlanes[1] = lightFrustumPlanes[1];
  81. _cullPlanes[2] = lightFrustumPlanes[2];
  82. _cullPlanes[3] = lightFrustumPlanes[3];
  83. var dir:Vector3D = DirectionalLight(_light).sceneDirection;
  84. var dirX:Number = dir.x;
  85. var dirY:Number = dir.y;
  86. var dirZ:Number = dir.z;
  87. var j:int = 4;
  88. for (var i:int = 0; i < 6; ++i) {
  89. var plane:Plane3D = viewFrustumPlanes[i];
  90. if (plane.a*dirX + plane.b*dirY + plane.c*dirZ < 0)
  91. _cullPlanes[j++] = plane;
  92. }
  93. }
  94. override protected function updateDepthProjection(viewCamera:Camera3D):void
  95. {
  96. updateProjectionFromFrustumCorners(viewCamera, viewCamera.lens.frustumCorners, _matrix);
  97. _overallDepthLens.matrix = _matrix;
  98. updateCullPlanes(viewCamera);
  99. }
  100. protected function updateProjectionFromFrustumCorners(viewCamera:Camera3D, corners:Vector.<Number>, matrix:Matrix3D):void
  101. {
  102. var raw:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
  103. var dir:Vector3D;
  104. var x:Number, y:Number, z:Number;
  105. var minX:Number, minY:Number;
  106. var maxX:Number, maxY:Number;
  107. var i:uint;
  108. dir = DirectionalLight(_light).sceneDirection;
  109. _overallDepthCamera.transform = _light.sceneTransform;
  110. x = int((viewCamera.x - dir.x*_lightOffset)/_snap)*_snap;
  111. y = int((viewCamera.y - dir.y*_lightOffset)/_snap)*_snap;
  112. z = int((viewCamera.z - dir.z*_lightOffset)/_snap)*_snap;
  113. _overallDepthCamera.x = x;
  114. _overallDepthCamera.y = y;
  115. _overallDepthCamera.z = z;
  116. _matrix.copyFrom(_overallDepthCamera.inverseSceneTransform);
  117. _matrix.prepend(viewCamera.sceneTransform);
  118. _matrix.transformVectors(corners, _localFrustum);
  119. minX = maxX = _localFrustum[0];
  120. minY = maxY = _localFrustum[1];
  121. _maxZ = _localFrustum[2];
  122. i = 3;
  123. while (i < 24) {
  124. x = _localFrustum[i];
  125. y = _localFrustum[uint(i + 1)];
  126. z = _localFrustum[uint(i + 2)];
  127. if (x < minX)
  128. minX = x;
  129. if (x > maxX)
  130. maxX = x;
  131. if (y < minY)
  132. minY = y;
  133. if (y > maxY)
  134. maxY = y;
  135. if (z > _maxZ)
  136. _maxZ = z;
  137. i += 3;
  138. }
  139. _minZ = 1;
  140. var w:Number = maxX - minX;
  141. var h:Number = maxY - minY;
  142. var d:Number = 1/(_maxZ - _minZ);
  143. if (minX < 0)
  144. minX -= _snap; // because int() rounds up for < 0
  145. if (minY < 0)
  146. minY -= _snap;
  147. minX = int(minX/_snap)*_snap;
  148. minY = int(minY/_snap)*_snap;
  149. var snap2:Number = 2*_snap;
  150. w = int(w/snap2 + 2)*snap2;
  151. h = int(h/snap2 + 2)*snap2;
  152. maxX = minX + w;
  153. maxY = minY + h;
  154. w = 1/w;
  155. h = 1/h;
  156. raw[0] = 2*w;
  157. raw[5] = 2*h;
  158. raw[10] = d;
  159. raw[12] = -(maxX + minX)*w;
  160. raw[13] = -(maxY + minY)*h;
  161. raw[14] = -_minZ*d;
  162. raw[15] = 1;
  163. raw[1] = raw[2] = raw[3] = raw[4] = raw[6] = raw[7] = raw[8] = raw[9] = raw[11] = 0;
  164. matrix.copyRawDataFrom(raw);
  165. }
  166. }
  167. }