babylon.directionalLight.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /// <reference path="babylon.light.ts" />
  2. module BABYLON {
  3. export class DirectionalLight extends ShadowLight {
  4. private _shadowFrustumSize = 0;
  5. /**
  6. * Fix frustum size for the shadow generation. This is disabled if the value is 0.
  7. */
  8. @serialize()
  9. public get shadowFrustumSize(): number {
  10. return this._shadowFrustumSize
  11. }
  12. /**
  13. * Specifies a fix frustum size for the shadow generation.
  14. */
  15. public set shadowFrustumSize(value: number) {
  16. this._shadowFrustumSize = value;
  17. this.forceProjectionMatrixCompute();
  18. }
  19. private _shadowOrthoScale = 0.5;
  20. @serialize()
  21. public get shadowOrthoScale(): number {
  22. return this._shadowOrthoScale
  23. }
  24. public set shadowOrthoScale(value: number) {
  25. this._shadowOrthoScale = value;
  26. this.forceProjectionMatrixCompute();
  27. }
  28. @serialize()
  29. public autoUpdateExtends = true;
  30. // Cache
  31. private _orthoLeft = Number.MAX_VALUE;
  32. private _orthoRight = Number.MIN_VALUE;
  33. private _orthoTop = Number.MIN_VALUE;
  34. private _orthoBottom = Number.MAX_VALUE;
  35. /**
  36. * Creates a DirectionalLight object in the scene, oriented towards the passed direction (Vector3).
  37. * The directional light is emitted from everywhere in the given direction.
  38. * It can cast shawdows.
  39. * Documentation : http://doc.babylonjs.com/tutorials/lights
  40. */
  41. constructor(name: string, direction: Vector3, scene: Scene) {
  42. super(name, scene);
  43. this.position = direction.scale(-1.0);
  44. this.direction = direction;
  45. }
  46. /**
  47. * Returns the string "DirectionalLight".
  48. */
  49. public getClassName(): string {
  50. return "DirectionalLight";
  51. }
  52. /**
  53. * Returns the integer 1.
  54. */
  55. public getTypeID(): number {
  56. return Light.LIGHTTYPEID_DIRECTIONALLIGHT;
  57. }
  58. /**
  59. * Sets the passed matrix "matrix" as projection matrix for the shadows cast by the light according to the passed view matrix.
  60. * Returns the DirectionalLight Shadow projection matrix.
  61. */
  62. protected _setDefaultShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void {
  63. if (this.shadowFrustumSize > 0) {
  64. this._setDefaultFixedFrustumShadowProjectionMatrix(matrix, viewMatrix);
  65. }
  66. else {
  67. this._setDefaultAutoExtendShadowProjectionMatrix(matrix, viewMatrix, renderList);
  68. }
  69. }
  70. /**
  71. * Sets the passed matrix "matrix" as fixed frustum projection matrix for the shadows cast by the light according to the passed view matrix.
  72. * Returns the DirectionalLight Shadow projection matrix.
  73. */
  74. protected _setDefaultFixedFrustumShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix): void {
  75. var activeCamera = this.getScene().activeCamera;
  76. Matrix.OrthoLHToRef(this.shadowFrustumSize, this.shadowFrustumSize,
  77. this.shadowMinZ !== undefined ? this.shadowMinZ : activeCamera.minZ, this.shadowMaxZ !== undefined ? this.shadowMaxZ : activeCamera.maxZ, matrix);
  78. }
  79. /**
  80. * Sets the passed matrix "matrix" as auto extend projection matrix for the shadows cast by the light according to the passed view matrix.
  81. * Returns the DirectionalLight Shadow projection matrix.
  82. */
  83. protected _setDefaultAutoExtendShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void {
  84. var activeCamera = this.getScene().activeCamera;
  85. // Check extends
  86. if (this.autoUpdateExtends || this._orthoLeft === Number.MAX_VALUE) {
  87. var tempVector3 = Vector3.Zero();
  88. this._orthoLeft = Number.MAX_VALUE;
  89. this._orthoRight = Number.MIN_VALUE;
  90. this._orthoTop = Number.MIN_VALUE;
  91. this._orthoBottom = Number.MAX_VALUE;
  92. for (var meshIndex = 0; meshIndex < renderList.length; meshIndex++) {
  93. var mesh = renderList[meshIndex];
  94. if (!mesh) {
  95. continue;
  96. }
  97. var boundingInfo = mesh.getBoundingInfo();
  98. if (!boundingInfo) {
  99. continue;
  100. }
  101. var boundingBox = boundingInfo.boundingBox;
  102. for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {
  103. Vector3.TransformCoordinatesToRef(boundingBox.vectorsWorld[index], viewMatrix, tempVector3);
  104. if (tempVector3.x < this._orthoLeft)
  105. this._orthoLeft = tempVector3.x;
  106. if (tempVector3.y < this._orthoBottom)
  107. this._orthoBottom = tempVector3.y;
  108. if (tempVector3.x > this._orthoRight)
  109. this._orthoRight = tempVector3.x;
  110. if (tempVector3.y > this._orthoTop)
  111. this._orthoTop = tempVector3.y;
  112. }
  113. }
  114. }
  115. var xOffset = this._orthoRight - this._orthoLeft;
  116. var yOffset = this._orthoTop - this._orthoBottom;
  117. Matrix.OrthoOffCenterLHToRef(this._orthoLeft - xOffset * this.shadowOrthoScale, this._orthoRight + xOffset * this.shadowOrthoScale,
  118. this._orthoBottom - yOffset * this.shadowOrthoScale, this._orthoTop + yOffset * this.shadowOrthoScale,
  119. this.shadowMinZ !== undefined ? this.shadowMinZ : activeCamera.minZ, this.shadowMaxZ !== undefined ? this.shadowMaxZ : activeCamera.maxZ, matrix);
  120. }
  121. protected _buildUniformLayout(): void {
  122. this._uniformBuffer.addUniform("vLightData", 4);
  123. this._uniformBuffer.addUniform("vLightDiffuse", 4);
  124. this._uniformBuffer.addUniform("vLightSpecular", 3);
  125. this._uniformBuffer.addUniform("shadowsInfo", 3);
  126. this._uniformBuffer.addUniform("depthValues", 2);
  127. this._uniformBuffer.create();
  128. }
  129. /**
  130. * Sets the passed Effect object with the DirectionalLight transformed position (or position if not parented) and the passed name.
  131. * Returns the DirectionalLight.
  132. */
  133. public transferToEffect(effect: Effect, lightIndex: string): DirectionalLight {
  134. if (this.computeTransformedInformation()) {
  135. this._uniformBuffer.updateFloat4("vLightData", this.transformedDirection.x, this.transformedDirection.y, this.transformedDirection.z, 1, lightIndex);
  136. return this;
  137. }
  138. this._uniformBuffer.updateFloat4("vLightData", this.direction.x, this.direction.y, this.direction.z, 1, lightIndex);
  139. return this;
  140. }
  141. /**
  142. * Gets the minZ used for shadow according to both the scene and the light.
  143. *
  144. * Values are fixed on directional lights as it relies on an ortho projection hence the need to convert being
  145. * -1 and 1 to 0 and 1 doing (depth + min) / (min + max) -> (depth + 1) / (1 + 1) -> (depth * 0.5) + 0.5.
  146. * @param activeCamera
  147. */
  148. public getDepthMinZ(activeCamera: Camera): number {
  149. return 1;
  150. }
  151. /**
  152. * Gets the maxZ used for shadow according to both the scene and the light.
  153. *
  154. * Values are fixed on directional lights as it relies on an ortho projection hence the need to convert being
  155. * -1 and 1 to 0 and 1 doing (depth + min) / (min + max) -> (depth + 1) / (1 + 1) -> (depth * 0.5) + 0.5.
  156. * @param activeCamera
  157. */
  158. public getDepthMaxZ(activeCamera: Camera): number {
  159. return 1;
  160. }
  161. }
  162. }