babylon.cubeTexture.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. module BABYLON {
  2. export class CubeTexture extends BaseTexture {
  3. public url: string;
  4. public coordinatesMode = Texture.CUBIC_MODE;
  5. /**
  6. * Gets or sets the center of the bounding box associated with the cube texture
  7. * It must define where the camera used to render the texture was set
  8. */
  9. public boundingBoxPosition = Vector3.Zero();
  10. private _boundingBoxSize: Vector3;
  11. /**
  12. * Gets or sets the size of the bounding box associated with the cube texture
  13. * When defined, the cubemap will switch to local mode
  14. * @see https://community.arm.com/graphics/b/blog/posts/reflections-based-on-local-cubemaps-in-unity
  15. * @example https://www.babylonjs-playground.com/#RNASML
  16. */
  17. public set boundingBoxSize(value: Vector3) {
  18. if (this._boundingBoxSize && this._boundingBoxSize.equals(value)) {
  19. return;
  20. }
  21. this._boundingBoxSize = value;
  22. let scene = this.getScene();
  23. if (scene) {
  24. scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag);
  25. }
  26. }
  27. public get boundingBoxSize(): Vector3 {
  28. return this._boundingBoxSize;
  29. }
  30. @serialize("rotationY")
  31. protected _rotationY: number = 0;
  32. /**
  33. * Sets texture matrix rotation angle around Y axis in radians.
  34. */
  35. public set rotationY(value: number) {
  36. this._rotationY = value;
  37. this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
  38. }
  39. /**
  40. * Gets texture matrix rotation angle around Y axis radians.
  41. */
  42. public get rotationY(): number {
  43. return this._rotationY;
  44. }
  45. private _noMipmap: boolean;
  46. private _files: string[];
  47. private _extensions: string[];
  48. private _textureMatrix: Matrix;
  49. private _format: number;
  50. private _createPolynomials: boolean;
  51. /** @hidden */
  52. public readonly _prefiltered: boolean = false;
  53. public static CreateFromImages(files: string[], scene: Scene, noMipmap?: boolean) {
  54. let rootUrlKey = "";
  55. files.forEach(url => rootUrlKey += url);
  56. return new CubeTexture(rootUrlKey, scene, null, noMipmap, files);
  57. }
  58. /**
  59. * Creates and return a texture created from prefilterd data by tools like IBL Baker or Lys.
  60. * @param url defines the url of the prefiltered texture
  61. * @param scene defines the scene the texture is attached to
  62. * @param forcedExtension defines the extension of the file if different from the url
  63. * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
  64. * @return the prefiltered texture
  65. */
  66. public static CreateFromPrefilteredData(url: string, scene: Scene, forcedExtension: any = null, createPolynomials: boolean = true) {
  67. return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension, createPolynomials);
  68. }
  69. /**
  70. * Creates a cube texture to use with reflection for instance. It can be based upon dds or six images as well
  71. * as prefiltered data.
  72. * @param rootUrl defines the url of the texture or the root name of the six images
  73. * @param scene defines the scene the texture is attached to
  74. * @param extensions defines the suffixes add to the picture name in case six images are in use like _px.jpg...
  75. * @param noMipmap defines if mipmaps should be created or not
  76. * @param files defines the six files to load for the different faces
  77. * @param onLoad defines a callback triggered at the end of the file load if no errors occured
  78. * @param onError defines a callback triggered in case of error during load
  79. * @param format defines the internal format to use for the texture once loaded
  80. * @param prefiltered defines whether or not the texture is created from prefiltered data
  81. * @param forcedExtension defines the extensions to use (force a special type of file to load) in case it is different from the file name
  82. * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
  83. * @return the cube texture
  84. */
  85. constructor(rootUrl: string, scene: Scene, extensions: Nullable<string[]> = null, noMipmap: boolean = false, files: Nullable<string[]> = null,
  86. onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format: number = Engine.TEXTUREFORMAT_RGBA, prefiltered = false,
  87. forcedExtension: any = null, createPolynomials: boolean = false) {
  88. super(scene);
  89. this.name = rootUrl;
  90. this.url = rootUrl;
  91. this._noMipmap = noMipmap;
  92. this.hasAlpha = false;
  93. this._format = format;
  94. this._prefiltered = prefiltered;
  95. this.isCube = true;
  96. this._textureMatrix = Matrix.Identity();
  97. this._createPolynomials = createPolynomials;
  98. if (prefiltered) {
  99. this.gammaSpace = false;
  100. }
  101. if (!rootUrl && !files) {
  102. return;
  103. }
  104. this._texture = this._getFromCache(rootUrl, noMipmap);
  105. const lastDot = rootUrl.lastIndexOf(".");
  106. const extension = forcedExtension ? forcedExtension : (lastDot > -1 ? rootUrl.substring(lastDot).toLowerCase() : "");
  107. const isDDS = (extension === ".dds");
  108. const isEnv = (extension === ".env");
  109. if (isEnv) {
  110. this.gammaSpace = false;
  111. }
  112. if (!files) {
  113. if (!isEnv && !isDDS && !extensions) {
  114. extensions = ["_px.jpg", "_py.jpg", "_pz.jpg", "_nx.jpg", "_ny.jpg", "_nz.jpg"];
  115. }
  116. files = [];
  117. if (extensions) {
  118. for (var index = 0; index < extensions.length; index++) {
  119. files.push(rootUrl + extensions[index]);
  120. }
  121. }
  122. }
  123. this._files = files;
  124. if (!this._texture) {
  125. if (!scene.useDelayedTextureLoading) {
  126. if (prefiltered) {
  127. this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, this.lodGenerationScale, this.lodGenerationOffset, onLoad, onError, format, forcedExtension, this._createPolynomials);
  128. }
  129. else {
  130. this._texture = scene.getEngine().createCubeTexture(rootUrl, scene, files, noMipmap, onLoad, onError, this._format, forcedExtension);
  131. }
  132. } else {
  133. this.delayLoadState = Engine.DELAYLOADSTATE_NOTLOADED;
  134. }
  135. } else if (onLoad) {
  136. if (this._texture.isReady) {
  137. Tools.SetImmediate(() => onLoad());
  138. } else {
  139. this._texture.onLoadedObservable.add(onLoad);
  140. }
  141. }
  142. }
  143. // Methods
  144. public delayLoad(): void {
  145. if (this.delayLoadState !== Engine.DELAYLOADSTATE_NOTLOADED) {
  146. return;
  147. }
  148. let scene = this.getScene();
  149. if (!scene) {
  150. return;
  151. }
  152. this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
  153. this._texture = this._getFromCache(this.url, this._noMipmap);
  154. if (!this._texture) {
  155. if (this._prefiltered) {
  156. this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format, undefined, this._createPolynomials);
  157. }
  158. else {
  159. this._texture = scene.getEngine().createCubeTexture(this.url, scene, this._files, this._noMipmap, undefined, undefined, this._format);
  160. }
  161. }
  162. }
  163. public getReflectionTextureMatrix(): Matrix {
  164. return this._textureMatrix;
  165. }
  166. public setReflectionTextureMatrix(value: Matrix): void {
  167. this._textureMatrix = value;
  168. }
  169. public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): CubeTexture {
  170. var texture = SerializationHelper.Parse(() => {
  171. var prefiltered:boolean = false;
  172. if (parsedTexture.prefiltered) {
  173. prefiltered = parsedTexture.prefiltered;
  174. }
  175. return new CubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.extensions, false, null, null, null, undefined, prefiltered);
  176. }, parsedTexture, scene);
  177. // Local Cubemaps
  178. if (parsedTexture.boundingBoxPosition) {
  179. texture.boundingBoxPosition = Vector3.FromArray(parsedTexture.boundingBoxPosition);
  180. }
  181. if (parsedTexture.boundingBoxSize) {
  182. texture.boundingBoxSize = Vector3.FromArray(parsedTexture.boundingBoxSize);
  183. }
  184. // Animations
  185. if (parsedTexture.animations) {
  186. for (var animationIndex = 0; animationIndex < parsedTexture.animations.length; animationIndex++) {
  187. var parsedAnimation = parsedTexture.animations[animationIndex];
  188. texture.animations.push(Animation.Parse(parsedAnimation));
  189. }
  190. }
  191. return texture;
  192. }
  193. public clone(): CubeTexture {
  194. return SerializationHelper.Clone(() => {
  195. let scene = this.getScene();
  196. if (!scene) {
  197. return this;
  198. }
  199. return new CubeTexture(this.url, scene, this._extensions, this._noMipmap, this._files);
  200. }, this);
  201. }
  202. }
  203. }