/home/lindsay/xeolabs/xeogl-next/xeogl/src/lighting/spotLight.js
API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/lighting/spotLight.js

  1. /**
  2. A **SpotLight** defines a positional light source that originates from a single point and eminates in a given direction,
  3. to illuminate {{#crossLink "Mesh"}}Meshes{{/crossLink}}.
  4.  
  5. ## Overview
  6.  
  7. * SpotLights have a position and direction.
  8. * SpotLights may be defined in either **World** or **View** coordinate space. When in World-space, their positions
  9. are relative to the World coordinate system, and will appear to move as the {{#crossLink "Camera"}}{{/crossLink}} moves.
  10. When in View-space, their positions are relative to the View coordinate system, and will behave as if fixed to the viewer's
  11. head as the {{#crossLink "Camera"}}{{/crossLink}} moves.
  12. * SpotLights have {{#crossLink "SpotLight/constantAttenuation:property"}}{{/crossLink}}, {{#crossLink "SpotLight/linearAttenuation:property"}}{{/crossLink}} and
  13. {{#crossLink "SpotLight/quadraticAttenuation:property"}}{{/crossLink}} factors, which indicate how their intensity attenuates over distance.
  14. * A SpotLight can also have a {{#crossLink "Shadow"}}{{/crossLink}} component, to configure it to cast a shadow.
  15. * {{#crossLink "AmbientLight"}}{{/crossLink}}, {{#crossLink "DirLight"}}{{/crossLink}},
  16. {{#crossLink "SpotLight"}}{{/crossLink}} and {{#crossLink "PointLight"}}{{/crossLink}} instances are registered by ID
  17. on {{#crossLink "Scene/lights:property"}}Scene#lights{{/crossLink}} for convenient access.
  18. ## Examples
  19.  
  20. TODO
  21.  
  22. ## Usage
  23.  
  24. In the example below we'll customize the default Scene's light sources, defining an AmbientLight and a couple of
  25. SpotLights, then create a Phong-shaded box mesh.
  26.  
  27. ````javascript
  28. new xeogl.AmbientLight({
  29. color: [0.8, 0.8, 0.8],
  30. intensity: 0.5
  31. });
  32.  
  33. new xeogl.SpotLight({
  34. pos: [0, 100, 100],
  35. dir: [0, -1, 0],
  36. color: [0.5, 0.7, 0.5],
  37. intensity: 1
  38. constantAttenuation: 0,
  39. linearAttenuation: 0,
  40. quadraticAttenuation: 0,
  41. space: "view"
  42. });
  43.  
  44. new xeogl.PointLight({
  45. pos: [0, 100, 100],
  46. dir: [0, -1, 0],
  47. color: [0.5, 0.7, 0.5],
  48. intensity: 1
  49. constantAttenuation: 0,
  50. linearAttenuation: 0,
  51. quadraticAttenuation: 0,
  52. space: "view"
  53. });
  54.  
  55. // Create box mesh
  56. new xeogl.Mesh({
  57. material: new xeogl.PhongMaterial({
  58. ambient: [0.5, 0.5, 0.5],
  59. diffuse: [1,0.3,0.3]
  60. }),
  61. geometry: new xeogl.BoxGeometry()
  62. });
  63. ````
  64.  
  65. @class SpotLight
  66. @module xeogl
  67. @submodule lighting
  68. @constructor
  69. @extends Component
  70. @param [owner] {Component} Owner component. When destroyed, the owner will destroy this component as well. Creates this component within the default {{#crossLink "Scene"}}{{/crossLink}} when omitted.
  71. @param [cfg] {*} The SpotLight configuration
  72. @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}}, generated automatically when omitted.
  73. @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this SpotLight.
  74. @param [cfg.pos=[ 1.0, 1.0, 1.0 ]] {Float32Array} Position, in either World or View space, depending on the value of the **space** parameter.
  75. @param [cfg.dir=[ 0.0, -1.0, 0.0 ]] {Float32Array} Direction in which this Spotlight is shining, in either World or View space, depending on the value of the **space** parameter.
  76. @param [cfg.color=[0.7, 0.7, 0.8 ]] {Float32Array} Color of this SpotLight.
  77. @param [cfg.intensity=1.0] {Number} Intensity of this SpotLight.
  78. @param [cfg.constantAttenuation=0] {Number} Constant attenuation factor.
  79. @param [cfg.linearAttenuation=0] {Number} Linear attenuation factor.
  80. @param [cfg.quadraticAttenuation=0] {Number} Quadratic attenuation factor.
  81. @param [cfg.space="view"] {String} The coordinate system this SpotLight is defined in - "view" or "world".
  82. @param [cfg.shadow=false] {Boolean} Flag which indicates if this SpotLight casts a shadow.
  83. */
  84.  
  85. import {Component} from '../component.js';
  86. import {State} from '../renderer/state.js';
  87. import {RenderBuffer} from '../renderer/renderBuffer.js';
  88. import {math} from '../math/math.js';
  89. import {componentClasses} from "./../componentClasses.js";
  90.  
  91. const type = "xeogl.SpotLight";
  92.  
  93. class SpotLight extends Component {
  94.  
  95. /**
  96. JavaScript class name for this Component.
  97.  
  98. For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.
  99.  
  100. @property type
  101. @type String
  102. @final
  103. */
  104. get type() {
  105. return type;
  106. }
  107.  
  108. init(cfg) {
  109.  
  110. super.init(cfg);
  111.  
  112. const self = this;
  113.  
  114. this._shadowRenderBuf = null;
  115. this._shadowViewMatrix = null;
  116. this._shadowProjMatrix = null;
  117. this._shadowViewMatrixDirty = true;
  118. this._shadowProjMatrixDirty = true;
  119.  
  120. this._state = new State({
  121. type: "spot",
  122. pos: math.vec3([1.0, 1.0, 1.0]),
  123. dir: math.vec3([0.0, -1.0, 0.0]),
  124. color: math.vec3([0.7, 0.7, 0.8]),
  125. intensity: 1.0,
  126. attenuation: [0.0, 0.0, 0.0],
  127. space: cfg.space || "view",
  128. shadow: false,
  129. shadowDirty: true,
  130.  
  131. getShadowViewMatrix: (function () {
  132. const look = math.vec3();
  133. const up = math.vec3([0, 1, 0]);
  134. return function () {
  135. if (self._shadowViewMatrixDirty) {
  136. if (!self._shadowViewMatrix) {
  137. self._shadowViewMatrix = math.identityMat4();
  138. }
  139. math.addVec3(self._state.pos, self._state.dir, look);
  140. math.lookAtMat4v(self._state.pos, look, up, self._shadowViewMatrix);
  141. self._shadowViewMatrixDirty = false;
  142. }
  143. return self._shadowViewMatrix;
  144. };
  145. })(),
  146.  
  147. getShadowProjMatrix: function () {
  148. if (self._shadowProjMatrixDirty) { // TODO: Set when canvas resizes
  149. if (!self._shadowProjMatrix) {
  150. self._shadowProjMatrix = math.identityMat4();
  151. }
  152. const canvas = self.scene.canvas.canvas;
  153. math.perspectiveMat4(60 * (Math.PI / 180.0), canvas.clientWidth / canvas.clientHeight, 0.1, 400.0, self._shadowProjMatrix);
  154. self._shadowProjMatrixDirty = false;
  155. }
  156. return self._shadowProjMatrix;
  157. },
  158.  
  159. getShadowRenderBuf: function () {
  160. if (!self._shadowRenderBuf) {
  161. self._shadowRenderBuf = new RenderBuffer(self.scene.canvas.canvas, self.scene.canvas.gl);
  162. }
  163. return self._shadowRenderBuf;
  164. }
  165. });
  166.  
  167. this.pos = cfg.pos;
  168. this.color = cfg.color;
  169. this.intensity = cfg.intensity;
  170. this.constantAttenuation = cfg.constantAttenuation;
  171. this.linearAttenuation = cfg.linearAttenuation;
  172. this.quadraticAttenuation = cfg.quadraticAttenuation;
  173. this.shadow = cfg.shadow;
  174. this.scene._lightCreated(this);
  175. }
  176.  
  177.  
  178. /**
  179. The position of this SpotLight.
  180.  
  181. This will be either World- or View-space, depending on the value of {{#crossLink "SpotLight/space:property"}}{{/crossLink}}.
  182.  
  183. @property pos
  184. @default [1.0, 1.0, 1.0]
  185. @type Array(Number)
  186. */
  187. set pos(value) {
  188. this._state.pos.set(value || [1.0, 1.0, 1.0]);
  189. this._shadowViewMatrixDirty = true;
  190. this._renderer.imageDirty();
  191. }
  192.  
  193. get pos() {
  194. return this._state.pos;
  195. }
  196.  
  197. /**
  198. The direction in which the light is shining.
  199.  
  200. @property dir
  201. @default [1.0, 1.0, 1.0]
  202. @type Float32Array
  203. */
  204. set dir(value) {
  205. this._state.dir.set(value || [1.0, 1.0, 1.0]);
  206. this._shadowViewMatrixDirty = true;
  207. this._renderer.imageDirty();
  208. }
  209.  
  210. get dir() {
  211. return this._state.dir;
  212. }
  213.  
  214. /**
  215. The color of this SpotLight.
  216.  
  217. @property color
  218. @default [0.7, 0.7, 0.8]
  219. @type Float32Array
  220. */
  221. set color(value) {
  222. this._state.color.set(value || [0.7, 0.7, 0.8]);
  223. this._renderer.imageDirty();
  224. }
  225.  
  226. get color() {
  227. return this._state.color;
  228. }
  229.  
  230. /**
  231. The intensity of this SpotLight.
  232.  
  233. Fires a {{#crossLink "SpotLight/intensity:event"}}{{/crossLink}} event on change.
  234.  
  235. @property intensity
  236. @default 1.0
  237. @type Number
  238. */
  239. set intensity(value) {
  240. value = value !== undefined ? value : 1.0;
  241. this._state.intensity = value;
  242. this._renderer.imageDirty();
  243. }
  244.  
  245. get intensity() {
  246. return this._state.intensity;
  247. }
  248.  
  249. /**
  250. The constant attenuation factor for this SpotLight.
  251.  
  252. @property constantAttenuation
  253. @default 0
  254. @type Number
  255. */
  256. set constantAttenuation(value) {
  257. this._state.attenuation[0] = value || 0.0;
  258. this._renderer.imageDirty();
  259. }
  260.  
  261. get constantAttenuation() {
  262. return this._state.attenuation[0];
  263. }
  264.  
  265. /**
  266. The linear attenuation factor for this SpotLight.
  267.  
  268. @property linearAttenuation
  269. @default 0
  270. @type Number
  271. */
  272. set linearAttenuation(value) {
  273. this._state.attenuation[1] = value || 0.0;
  274. this._renderer.imageDirty();
  275. }
  276.  
  277. get linearAttenuation() {
  278. return this._state.attenuation[1];
  279. }
  280.  
  281. /**
  282. The quadratic attenuation factor for this SpotLight.
  283.  
  284. @property quadraticAttenuation
  285. @default 0
  286. @type Number
  287. */
  288. set quadraticAttenuation(value) {
  289. this._state.attenuation[2] = value || 0.0;
  290. this._renderer.imageDirty();
  291. }
  292.  
  293. get quadraticAttenuation() {
  294. return this._state.attenuation[2];
  295. }
  296.  
  297. /**
  298. Flag which indicates if this SpotLight casts a shadow.
  299.  
  300. @property shadow
  301. @default false
  302. @type Boolean
  303. */
  304. set shadow(value) {
  305. value = !!value;
  306. if (this._state.shadow === value) {
  307. return;
  308. }
  309. this._state.shadow = value;
  310. this._shadowViewMatrixDirty = true;
  311. this._renderer.imageDirty();
  312. this.fire("dirty", true);
  313. }
  314.  
  315. get shadow() {
  316. return this._state.shadow;
  317. }
  318.  
  319. destroy() {
  320. super.destroy();
  321. this._state.destroy();
  322. if (this._shadowRenderBuf) {
  323. this._shadowRenderBuf.destroy();
  324. }
  325. this.scene._lightDestroyed(this);
  326.  
  327. }
  328. }
  329.  
  330. componentClasses[type] = SpotLight;
  331.  
  332. export{SpotLight};
  333.