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

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

  1. /**
  2. A **CubeTexture** specifies a cube texture map.
  3.  
  4. ## Overview
  5.  
  6. See {{#crossLink "Lights"}}{{/crossLink}} for an example of how to use CubeTextures for light and reflection mapping.
  7.  
  8. @class CubeTexture
  9. @module xeogl
  10. @submodule lighting
  11. @constructor
  12. @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.
  13. @param [cfg] {*} Configs
  14. @param [cfg.id] {String} Optional ID for this CubeTexture, unique among all components in the parent scene, generated automatically when omitted.
  15. @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this CubeTexture.
  16. @param [cfg.src=null] {Array of String} Paths to six image files to load into this CubeTexture.
  17. @param [cfg.flipY=false] {Boolean} Flips this CubeTexture's source data along its vertical axis when true.
  18. @param [cfg.encoding="linear"] {String} Encoding format. See the {{#crossLink "CubeTexture/encoding:property"}}{{/crossLink}} property for more info.
  19. @extends Component
  20. */
  21. import {Component} from '../component.js';
  22. import {State} from '../renderer/state.js';
  23. import {Texture2D} from '../renderer/texture2d.js';
  24. import {stats} from './../stats.js';
  25. import {componentClasses} from "./../componentClasses.js";
  26.  
  27. const type = "xeogl.CubeTexture";
  28.  
  29. function ensureImageSizePowerOfTwo(image) {
  30. if (!isPowerOfTwo(image.width) || !isPowerOfTwo(image.height)) {
  31. const canvas = document.createElement("canvas");
  32. canvas.width = nextHighestPowerOfTwo(image.width);
  33. canvas.height = nextHighestPowerOfTwo(image.height);
  34. const ctx = canvas.getContext("2d");
  35. ctx.drawImage(image,
  36. 0, 0, image.width, image.height,
  37. 0, 0, canvas.width, canvas.height);
  38. image = canvas;
  39. }
  40. return image;
  41. }
  42.  
  43. function isPowerOfTwo(x) {
  44. return (x & (x - 1)) === 0;
  45. }
  46.  
  47. function nextHighestPowerOfTwo(x) {
  48. --x;
  49. for (let i = 1; i < 32; i <<= 1) {
  50. x = x | x >> i;
  51. }
  52. return x + 1;
  53. }
  54.  
  55. class CubeTexture extends Component{
  56.  
  57. /**
  58. JavaScript class name for this Component.
  59.  
  60. For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.
  61.  
  62. @property type
  63. @type String
  64. @final
  65. */
  66. get type() {
  67. return type;
  68. }
  69.  
  70. init(cfg) {
  71.  
  72. super.init(cfg);
  73.  
  74. const gl = this.scene.canvas.gl;
  75.  
  76. this._state = new State({
  77. texture: new Texture2D(gl, gl.TEXTURE_CUBE_MAP),
  78. flipY: this._checkFlipY(cfg.minFilter),
  79. encoding: this._checkEncoding(cfg.encoding),
  80. minFilter: "linearMipmapLinear",
  81. magFilter: "linear",
  82. wrapS: "clampToEdge",
  83. wrapT: "clampToEdge",
  84. mipmaps: true
  85. });
  86.  
  87. this._src = cfg.src;
  88. this._images = [];
  89.  
  90. this._loadSrc(cfg.src);
  91.  
  92. stats.memory.textures++;
  93. }
  94.  
  95. _checkFlipY(value) {
  96. return !!value;
  97. }
  98.  
  99. _checkEncoding (value) {
  100. value = value || "linear";
  101. if (value !== "linear" && value !== "sRGB" && value !== "gamma") {
  102. this.error("Unsupported value for 'encoding': '" + value + "' - supported values are 'linear', 'sRGB', 'gamma'. Defaulting to 'linear'.");
  103. value = "linear";
  104. }
  105. return value;
  106. }
  107.  
  108. _webglContextRestored () {
  109. const gl = this.scene.canvas.gl;
  110. this._state.texture = null;
  111. // if (this._images.length > 0) {
  112. // this._state.texture = new xeogl.renderer.Texture2D(gl, gl.TEXTURE_CUBE_MAP);
  113. // this._state.texture.setImage(this._images, this._state);
  114. // this._state.texture.setProps(this._state);
  115. // } else
  116. if (this._src) {
  117. this._loadSrc(this._src);
  118. }
  119. }
  120.  
  121. _loadSrc (src) {
  122. const self = this;
  123. const gl = this.scene.canvas.gl;
  124. this._images = [];
  125. let loadFailed = false;
  126. let numLoaded = 0;
  127. for (let i = 0; i < src.length; i++) {
  128. const image = new Image();
  129. image.onload = (function () {
  130. let _image = image;
  131. const index = i;
  132. return function () {
  133. if (loadFailed) {
  134. return;
  135. }
  136. _image = ensureImageSizePowerOfTwo(_image);
  137. self._images[index] = _image;
  138. numLoaded++;
  139. if (numLoaded === 6) {
  140. let texture = self._state.texture;
  141. if (!texture) {
  142. texture = new Texture2D(gl, gl.TEXTURE_CUBE_MAP);
  143. self._state.texture = texture;
  144. }
  145. texture.setImage(self._images, self._state);
  146. texture.setProps(self._state);
  147. /**
  148. * Fired whenever this CubeTexture has loaded the
  149. * image files that its {{#crossLink "CubeTexture/src:property"}}{{/crossLink}} property currently points to.
  150. * @event loaded
  151. * @param value {HTML Image} The value of the {{#crossLink "CubeTexture/src:property"}}{{/crossLink}} property
  152. */
  153. self.fire("loaded", self._src);
  154. }
  155. };
  156. })();
  157. image.onerror = function () {
  158. loadFailed = true;
  159. };
  160. image.src = src[i];
  161. }
  162. }
  163.  
  164. destroy() {
  165. super.destroy();
  166. if (this._state.texture) {
  167. this._state.texture.destroy();
  168. }
  169. stats.memory.textures--;
  170. this._state.destroy();
  171. }
  172. }
  173.  
  174. componentClasses[type] = CubeTexture;
  175.  
  176. export {CubeTexture};