babylon.spotLight.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. module BABYLON {
  2. /**
  3. * A spot light is defined by a position, a direction, an angle, and an exponent.
  4. * These values define a cone of light starting from the position, emitting toward the direction.
  5. * The angle, in radians, defines the size (field of illumination) of the spotlight's conical beam,
  6. * and the exponent defines the speed of the decay of the light with distance (reach).
  7. * Documentation: https://doc.babylonjs.com/babylon101/lights
  8. */
  9. export class SpotLight extends ShadowLight {
  10. /*
  11. upVector , rightVector and direction will form the coordinate system for this spot light.
  12. These three vectors will be used as projection matrix when doing texture projection.
  13. Also we have the following rules always holds:
  14. direction cross up = right
  15. right cross dirction = up
  16. up cross right = forward
  17. light_near and light_far will control the range of the texture projection. If a plane is
  18. out of the range in spot light space, there is no texture projection.
  19. Warning:
  20. Change the angle of the Spotlight, direction of the SpotLight will not re-compute the
  21. projection matrix. Need to call computeTextureMatrix() to recompute manually. Add inheritance
  22. to the setting function of the 2 attributes will solve the problem.
  23. */
  24. private _angle: number;
  25. @serialize()
  26. /**
  27. * Gets the cone angle of the spot light in Radians.
  28. */
  29. public get angle(): number {
  30. return this._angle
  31. }
  32. /**
  33. * Sets the cone angle of the spot light in Radians.
  34. */
  35. public set angle(value: number) {
  36. this._angle = value;
  37. this.forceProjectionMatrixCompute();
  38. }
  39. private _shadowAngleScale: number;
  40. @serialize()
  41. /**
  42. * Allows scaling the angle of the light for shadow generation only.
  43. */
  44. public get shadowAngleScale(): number {
  45. return this._shadowAngleScale
  46. }
  47. /**
  48. * Allows scaling the angle of the light for shadow generation only.
  49. */
  50. public set shadowAngleScale(value: number) {
  51. this._shadowAngleScale = value;
  52. this.forceProjectionMatrixCompute();
  53. }
  54. /**
  55. * The light decay speed with the distance from the emission spot.
  56. */
  57. @serialize()
  58. public exponent: number;
  59. private _textureProjectionMatrix = Matrix.Zero();
  60. @serialize()
  61. /**
  62. * Allows reading the projecton texture
  63. */
  64. public get textureMatrix(): Matrix{
  65. return this._textureProjectionMatrix;
  66. }
  67. /**
  68. * Allows setting the value of projection texture
  69. */
  70. public set textureMatrix(value: Matrix) {
  71. this._textureProjectionMatrix = value;
  72. }
  73. protected _light_near :number;
  74. @serialize()
  75. /**
  76. * Gets the near clip of the Spotlight for texture projection.
  77. */
  78. public get light_near(): number {
  79. return this._light_near;
  80. }
  81. /**
  82. * Sets the near clip of the Spotlight for texture projection.
  83. */
  84. public set light_near(value: number) {
  85. this._light_near = value;
  86. this._computeTextureMatrix();
  87. }
  88. protected _light_far :number;
  89. /**
  90. * Gets the far clip of the Spotlight for texture projection.
  91. */
  92. @serialize()
  93. public get light_far(): number {
  94. return this._light_far;
  95. }
  96. /**
  97. * Sets the far clip of the Spotlight for texture projection.
  98. */
  99. public set light_far(value: number) {
  100. this._light_far = value;
  101. }
  102. @serializeAsTexture("projectedLightTexture")
  103. private _projectedLightTexture: Nullable<BaseTexture>;;
  104. /**
  105. * Gets the projection texture of the light.
  106. */
  107. public get projectedLightTexture(): Nullable<BaseTexture> {
  108. return this._projectedLightTexture;
  109. }
  110. /**
  111. * Sets the projection texture of the light.
  112. */
  113. public set projectedLightTexture(value: Nullable<BaseTexture>) {
  114. this._projectedLightTexture = value;
  115. this._light_far = 1000.0;
  116. this._light_near = 1e-6;
  117. this._computeTextureMatrix();
  118. }
  119. /**
  120. * Creates a SpotLight object in the scene. A spot light is a simply light oriented cone.
  121. * It can cast shadows.
  122. * Documentation : http://doc.babylonjs.com/tutorials/lights
  123. * @param name The light friendly name
  124. * @param position The position of the spot light in the scene
  125. * @param direction The direction of the light in the scene
  126. * @param angle The cone angle of the light in Radians
  127. * @param exponent The light decay speed with the distance from the emission spot
  128. * @param scene The scene the lights belongs to
  129. */
  130. constructor(name: string, position: Vector3, direction: Vector3, angle: number, exponent: number, scene: Scene) {
  131. super(name, scene);
  132. this.position = position;
  133. this.direction = direction;
  134. this.angle = angle;
  135. this.exponent = exponent;
  136. }
  137. /**
  138. * Returns the string "SpotLight".
  139. * @returns the class name
  140. */
  141. public getClassName(): string {
  142. return "SpotLight";
  143. }
  144. /**
  145. * Returns the integer 2.
  146. * @returns The light Type id as a constant defines in Light.LIGHTTYPEID_x
  147. */
  148. public getTypeID(): number {
  149. return Light.LIGHTTYPEID_SPOTLIGHT;
  150. }
  151. /**
  152. * Sets the passed matrix "matrix" as perspective projection matrix for the shadows and the passed view matrix with the fov equal to the SpotLight angle and and aspect ratio of 1.0.
  153. * Returns the SpotLight.
  154. */
  155. protected _setDefaultShadowProjectionMatrix(matrix: Matrix, viewMatrix: Matrix, renderList: Array<AbstractMesh>): void {
  156. var activeCamera = this.getScene().activeCamera;
  157. if (!activeCamera) {
  158. return;
  159. }
  160. this._shadowAngleScale = this._shadowAngleScale || 1;
  161. var angle = this._shadowAngleScale * this._angle;
  162. Matrix.PerspectiveFovLHToRef(angle, 1.0,
  163. this.getDepthMinZ(activeCamera), this.getDepthMaxZ(activeCamera), matrix);
  164. }
  165. /**
  166. * Main function for light texture projection matrix computing.
  167. */
  168. protected _computeTextureMatrix(): void {
  169. var viewLightMatrix = Matrix.Zero();
  170. Matrix.LookAtLHToRef(this.position, this.position.add(this.direction), Vector3.Up(), viewLightMatrix);
  171. var light_far = this.light_far;
  172. var light_near = this.light_near;
  173. var P = light_far / (light_far - light_near);
  174. var Q = - P * light_near;
  175. var S = 1.0 / Math.tan(this._angle / 2.0);
  176. var A = 1.0;
  177. var projectionLightMatrix = Matrix.Zero();
  178. Matrix.FromValuesToRef(S/A, 0.0, 0.0, 0.0,
  179. 0.0, S, 0.0, 0.0,
  180. 0.0, 0.0, P, 1.0,
  181. 0.0, 0.0, Q, 0.0, projectionLightMatrix);
  182. var scaleMatrix = Matrix.Zero();
  183. Matrix.FromValuesToRef(0.5, 0.0, 0.0, 0.0,
  184. 0.0, 0.5, 0.0, 0.0,
  185. 0.0, 0.0, 0.5, 0.0,
  186. 0.5, 0.5, 0.5, 1.0, scaleMatrix);
  187. this._textureProjectionMatrix.copyFrom(viewLightMatrix);
  188. this._textureProjectionMatrix.multiplyToRef(projectionLightMatrix, this._textureProjectionMatrix);
  189. this._textureProjectionMatrix.multiplyToRef(scaleMatrix, this._textureProjectionMatrix);
  190. }
  191. protected _buildUniformLayout(): void {
  192. this._uniformBuffer.addUniform("vLightData", 4);
  193. this._uniformBuffer.addUniform("vLightDiffuse", 4);
  194. this._uniformBuffer.addUniform("vLightSpecular", 3);
  195. this._uniformBuffer.addUniform("vLightDirection", 3);
  196. this._uniformBuffer.addUniform("shadowsInfo", 3);
  197. this._uniformBuffer.addUniform("depthValues", 2);
  198. this._uniformBuffer.create();
  199. }
  200. /**
  201. * Sets the passed Effect object with the SpotLight transfomed position (or position if not parented) and normalized direction.
  202. * @param effect The effect to update
  203. * @param lightIndex The index of the light in the effect to update
  204. * @returns The spot light
  205. */
  206. public transferToEffect(effect: Effect, lightIndex: string): SpotLight {
  207. var normalizeDirection;
  208. if (this.computeTransformedInformation()) {
  209. this._uniformBuffer.updateFloat4("vLightData",
  210. this.transformedPosition.x,
  211. this.transformedPosition.y,
  212. this.transformedPosition.z,
  213. this.exponent,
  214. lightIndex);
  215. normalizeDirection = Vector3.Normalize(this.transformedDirection);
  216. } else {
  217. this._uniformBuffer.updateFloat4("vLightData",
  218. this.position.x,
  219. this.position.y,
  220. this.position.z,
  221. this.exponent,
  222. lightIndex);
  223. normalizeDirection = Vector3.Normalize(this.direction);
  224. }
  225. this._uniformBuffer.updateFloat4("vLightDirection",
  226. normalizeDirection.x,
  227. normalizeDirection.y,
  228. normalizeDirection.z,
  229. Math.cos(this.angle * 0.5),
  230. lightIndex);
  231. effect.setMatrix("textureProjectionMatrix" + lightIndex, this._textureProjectionMatrix);
  232. if (this.projectedLightTexture){
  233. effect.setTexture("projectionLightSampler" + lightIndex, this.projectedLightTexture);
  234. }
  235. return this;
  236. }
  237. /**
  238. * Disposes the light and the associated resources.
  239. */
  240. public dispose() : void {
  241. super.dispose();
  242. if (this._projectedLightTexture){
  243. this._projectedLightTexture.dispose();
  244. }
  245. }
  246. }
  247. }