texture.ts 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. import { serialize, SerializationHelper } from "../../Misc/decorators";
  2. import { Observable } from "../../Misc/observable";
  3. import { Tools } from "../../Misc/tools";
  4. import { Nullable } from "../../types";
  5. import { Scene } from "../../scene";
  6. import { Matrix, Vector3, Plane } from "../../Maths/math";
  7. import { BaseTexture } from "../../Materials/Textures/baseTexture";
  8. import { Constants } from "../../Engines/constants";
  9. import { _AlphaState } from "../../States/index";
  10. import { _TypeStore } from '../../Misc/typeStore';
  11. import { _DevTools } from '../../Misc/devTools';
  12. declare type CubeTexture = import("../../Materials/Textures/cubeTexture").CubeTexture;
  13. declare type MirrorTexture = import("../../Materials/Textures/mirrorTexture").MirrorTexture;
  14. declare type RenderTargetTexture = import("../../Materials/Textures/renderTargetTexture").RenderTargetTexture;
  15. /**
  16. * This represents a texture in babylon. It can be easily loaded from a network, base64 or html input.
  17. * @see http://doc.babylonjs.com/babylon101/materials#texture
  18. */
  19. export class Texture extends BaseTexture {
  20. /** @hidden */
  21. public static _CubeTextureParser = (jsonTexture: any, scene: Scene, rootUrl: string): CubeTexture => {
  22. throw _DevTools.WarnImport("CubeTexture");
  23. }
  24. /** @hidden */
  25. public static _CreateMirror = (name: string, renderTargetSize: number, scene: Scene, generateMipMaps: boolean): MirrorTexture => {
  26. throw _DevTools.WarnImport("MirrorTexture");
  27. }
  28. /** @hidden */
  29. public static _CreateRenderTargetTexture = (name: string, renderTargetSize: number, scene: Scene, generateMipMaps: boolean): RenderTargetTexture => {
  30. throw _DevTools.WarnImport("RenderTargetTexture");
  31. }
  32. /** nearest is mag = nearest and min = nearest and mip = linear */
  33. public static readonly NEAREST_SAMPLINGMODE = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
  34. /** nearest is mag = nearest and min = nearest and mip = linear */
  35. public static readonly NEAREST_NEAREST_MIPLINEAR = Constants.TEXTURE_NEAREST_NEAREST_MIPLINEAR; // nearest is mag = nearest and min = nearest and mip = linear
  36. /** Bilinear is mag = linear and min = linear and mip = nearest */
  37. public static readonly BILINEAR_SAMPLINGMODE = Constants.TEXTURE_BILINEAR_SAMPLINGMODE;
  38. /** Bilinear is mag = linear and min = linear and mip = nearest */
  39. public static readonly LINEAR_LINEAR_MIPNEAREST = Constants.TEXTURE_LINEAR_LINEAR_MIPNEAREST; // Bilinear is mag = linear and min = linear and mip = nearest
  40. /** Trilinear is mag = linear and min = linear and mip = linear */
  41. public static readonly TRILINEAR_SAMPLINGMODE = Constants.TEXTURE_TRILINEAR_SAMPLINGMODE;
  42. /** Trilinear is mag = linear and min = linear and mip = linear */
  43. public static readonly LINEAR_LINEAR_MIPLINEAR = Constants.TEXTURE_LINEAR_LINEAR_MIPLINEAR; // Trilinear is mag = linear and min = linear and mip = linear
  44. /** mag = nearest and min = nearest and mip = nearest */
  45. public static readonly NEAREST_NEAREST_MIPNEAREST = Constants.TEXTURE_NEAREST_NEAREST_MIPNEAREST;
  46. /** mag = nearest and min = linear and mip = nearest */
  47. public static readonly NEAREST_LINEAR_MIPNEAREST = Constants.TEXTURE_NEAREST_LINEAR_MIPNEAREST;
  48. /** mag = nearest and min = linear and mip = linear */
  49. public static readonly NEAREST_LINEAR_MIPLINEAR = Constants.TEXTURE_NEAREST_LINEAR_MIPLINEAR;
  50. /** mag = nearest and min = linear and mip = none */
  51. public static readonly NEAREST_LINEAR = Constants.TEXTURE_NEAREST_LINEAR;
  52. /** mag = nearest and min = nearest and mip = none */
  53. public static readonly NEAREST_NEAREST = Constants.TEXTURE_NEAREST_NEAREST;
  54. /** mag = linear and min = nearest and mip = nearest */
  55. public static readonly LINEAR_NEAREST_MIPNEAREST = Constants.TEXTURE_LINEAR_NEAREST_MIPNEAREST;
  56. /** mag = linear and min = nearest and mip = linear */
  57. public static readonly LINEAR_NEAREST_MIPLINEAR = Constants.TEXTURE_LINEAR_NEAREST_MIPLINEAR;
  58. /** mag = linear and min = linear and mip = none */
  59. public static readonly LINEAR_LINEAR = Constants.TEXTURE_LINEAR_LINEAR;
  60. /** mag = linear and min = nearest and mip = none */
  61. public static readonly LINEAR_NEAREST = Constants.TEXTURE_LINEAR_NEAREST;
  62. /** Explicit coordinates mode */
  63. public static readonly EXPLICIT_MODE = Constants.TEXTURE_EXPLICIT_MODE;
  64. /** Spherical coordinates mode */
  65. public static readonly SPHERICAL_MODE = Constants.TEXTURE_SPHERICAL_MODE;
  66. /** Planar coordinates mode */
  67. public static readonly PLANAR_MODE = Constants.TEXTURE_PLANAR_MODE;
  68. /** Cubic coordinates mode */
  69. public static readonly CUBIC_MODE = Constants.TEXTURE_CUBIC_MODE;
  70. /** Projection coordinates mode */
  71. public static readonly PROJECTION_MODE = Constants.TEXTURE_PROJECTION_MODE;
  72. /** Inverse Cubic coordinates mode */
  73. public static readonly SKYBOX_MODE = Constants.TEXTURE_SKYBOX_MODE;
  74. /** Inverse Cubic coordinates mode */
  75. public static readonly INVCUBIC_MODE = Constants.TEXTURE_INVCUBIC_MODE;
  76. /** Equirectangular coordinates mode */
  77. public static readonly EQUIRECTANGULAR_MODE = Constants.TEXTURE_EQUIRECTANGULAR_MODE;
  78. /** Equirectangular Fixed coordinates mode */
  79. public static readonly FIXED_EQUIRECTANGULAR_MODE = Constants.TEXTURE_FIXED_EQUIRECTANGULAR_MODE;
  80. /** Equirectangular Fixed Mirrored coordinates mode */
  81. public static readonly FIXED_EQUIRECTANGULAR_MIRRORED_MODE = Constants.TEXTURE_FIXED_EQUIRECTANGULAR_MIRRORED_MODE;
  82. /** Texture is not repeating outside of 0..1 UVs */
  83. public static readonly CLAMP_ADDRESSMODE = Constants.TEXTURE_CLAMP_ADDRESSMODE;
  84. /** Texture is repeating outside of 0..1 UVs */
  85. public static readonly WRAP_ADDRESSMODE = Constants.TEXTURE_WRAP_ADDRESSMODE;
  86. /** Texture is repeating and mirrored */
  87. public static readonly MIRROR_ADDRESSMODE = Constants.TEXTURE_MIRROR_ADDRESSMODE;
  88. /**
  89. * Gets or sets a boolean which defines if the texture url must be build from the serialized URL instead of just using the name and loading them side by side with the scene file
  90. */
  91. public static UseSerializedUrlIfAny = false;
  92. /**
  93. * Define the url of the texture.
  94. */
  95. @serialize()
  96. public url: Nullable<string>;
  97. /**
  98. * Define an offset on the texture to offset the u coordinates of the UVs
  99. * @see http://doc.babylonjs.com/how_to/more_materials#offsetting
  100. */
  101. @serialize()
  102. public uOffset = 0;
  103. /**
  104. * Define an offset on the texture to offset the v coordinates of the UVs
  105. * @see http://doc.babylonjs.com/how_to/more_materials#offsetting
  106. */
  107. @serialize()
  108. public vOffset = 0;
  109. /**
  110. * Define an offset on the texture to scale the u coordinates of the UVs
  111. * @see http://doc.babylonjs.com/how_to/more_materials#tiling
  112. */
  113. @serialize()
  114. public uScale = 1.0;
  115. /**
  116. * Define an offset on the texture to scale the v coordinates of the UVs
  117. * @see http://doc.babylonjs.com/how_to/more_materials#tiling
  118. */
  119. @serialize()
  120. public vScale = 1.0;
  121. /**
  122. * Define an offset on the texture to rotate around the u coordinates of the UVs
  123. * @see http://doc.babylonjs.com/how_to/more_materials
  124. */
  125. @serialize()
  126. public uAng = 0;
  127. /**
  128. * Define an offset on the texture to rotate around the v coordinates of the UVs
  129. * @see http://doc.babylonjs.com/how_to/more_materials
  130. */
  131. @serialize()
  132. public vAng = 0;
  133. /**
  134. * Define an offset on the texture to rotate around the w coordinates of the UVs (in case of 3d texture)
  135. * @see http://doc.babylonjs.com/how_to/more_materials
  136. */
  137. @serialize()
  138. public wAng = 0;
  139. /**
  140. * Defines the center of rotation (U)
  141. */
  142. @serialize()
  143. public uRotationCenter = 0.5;
  144. /**
  145. * Defines the center of rotation (V)
  146. */
  147. @serialize()
  148. public vRotationCenter = 0.5;
  149. /**
  150. * Defines the center of rotation (W)
  151. */
  152. @serialize()
  153. public wRotationCenter = 0.5;
  154. /**
  155. * Are mip maps generated for this texture or not.
  156. */
  157. get noMipmap(): boolean {
  158. return this._noMipmap;
  159. }
  160. private _noMipmap: boolean;
  161. /** @hidden */
  162. public _invertY: boolean;
  163. private _rowGenerationMatrix: Matrix;
  164. private _cachedTextureMatrix: Matrix;
  165. private _projectionModeMatrix: Matrix;
  166. private _t0: Vector3;
  167. private _t1: Vector3;
  168. private _t2: Vector3;
  169. private _cachedUOffset: number;
  170. private _cachedVOffset: number;
  171. private _cachedUScale: number;
  172. private _cachedVScale: number;
  173. private _cachedUAng: number;
  174. private _cachedVAng: number;
  175. private _cachedWAng: number;
  176. private _cachedProjectionMatrixId: number;
  177. private _cachedCoordinatesMode: number;
  178. /** @hidden */
  179. protected _initialSamplingMode = Texture.BILINEAR_SAMPLINGMODE;
  180. /** @hidden */
  181. public _buffer: Nullable<string | ArrayBuffer | HTMLImageElement | Blob>;
  182. private _deleteBuffer: boolean;
  183. protected _format: Nullable<number>;
  184. private _delayedOnLoad: Nullable<() => void>;
  185. private _delayedOnError: Nullable<() => void>;
  186. /**
  187. * Observable triggered once the texture has been loaded.
  188. */
  189. public onLoadObservable: Observable<Texture> = new Observable<Texture>();
  190. protected _isBlocking: boolean = true;
  191. /**
  192. * Is the texture preventing material to render while loading.
  193. * If false, a default texture will be used instead of the loading one during the preparation step.
  194. */
  195. public set isBlocking(value: boolean) {
  196. this._isBlocking = value;
  197. }
  198. @serialize()
  199. public get isBlocking(): boolean {
  200. return this._isBlocking;
  201. }
  202. /**
  203. * Get the current sampling mode associated with the texture.
  204. */
  205. public get samplingMode(): number {
  206. if (!this._texture) {
  207. return this._initialSamplingMode;
  208. }
  209. return this._texture.samplingMode;
  210. }
  211. /**
  212. * Gets a boolean indicating if the texture needs to be inverted on the y axis during loading
  213. */
  214. public get invertY(): boolean {
  215. return this._invertY;
  216. }
  217. /**
  218. * Instantiates a new texture.
  219. * This represents a texture in babylon. It can be easily loaded from a network, base64 or html input.
  220. * @see http://doc.babylonjs.com/babylon101/materials#texture
  221. * @param url define the url of the picture to load as a texture
  222. * @param scene define the scene the texture will belong to
  223. * @param noMipmap define if the texture will require mip maps or not
  224. * @param invertY define if the texture needs to be inverted on the y axis during loading
  225. * @param samplingMode define the sampling mode we want for the texture while fectching from it (Texture.NEAREST_SAMPLINGMODE...)
  226. * @param onLoad define a callback triggered when the texture has been loaded
  227. * @param onError define a callback triggered when an error occurred during the loading session
  228. * @param buffer define the buffer to load the texture from in case the texture is loaded from a buffer representation
  229. * @param deleteBuffer define if the buffer we are loading the texture from should be deleted after load
  230. * @param format define the format of the texture we are trying to load (Engine.TEXTUREFORMAT_RGBA...)
  231. */
  232. constructor(url: Nullable<string>, scene: Nullable<Scene>, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, buffer: Nullable<string | ArrayBuffer | HTMLImageElement | Blob> = null, deleteBuffer: boolean = false, format?: number) {
  233. super(scene);
  234. this.name = url || "";
  235. this.url = url;
  236. this._noMipmap = noMipmap;
  237. this._invertY = invertY;
  238. this._initialSamplingMode = samplingMode;
  239. this._buffer = buffer;
  240. this._deleteBuffer = deleteBuffer;
  241. if (format) {
  242. this._format = format;
  243. }
  244. scene = this.getScene();
  245. if (!scene) {
  246. return;
  247. }
  248. scene.getEngine().onBeforeTextureInitObservable.notifyObservers(this);
  249. let load = () => {
  250. if (this._texture && this._texture._invertVScale) {
  251. this.vScale = -1;
  252. }
  253. if (this.onLoadObservable.hasObservers()) {
  254. this.onLoadObservable.notifyObservers(this);
  255. }
  256. if (onLoad) {
  257. onLoad();
  258. }
  259. if (!this.isBlocking && scene) {
  260. scene.resetCachedMaterial();
  261. }
  262. };
  263. if (!this.url) {
  264. this._delayedOnLoad = load;
  265. this._delayedOnError = onError;
  266. return;
  267. }
  268. this._texture = this._getFromCache(this.url, noMipmap, samplingMode, invertY);
  269. if (!this._texture) {
  270. if (!scene.useDelayedTextureLoading) {
  271. this._texture = scene.getEngine().createTexture(this.url, noMipmap, invertY, scene, samplingMode, load, onError, this._buffer, undefined, this._format);
  272. if (deleteBuffer) {
  273. delete this._buffer;
  274. }
  275. } else {
  276. this.delayLoadState = Constants.DELAYLOADSTATE_NOTLOADED;
  277. this._delayedOnLoad = load;
  278. this._delayedOnError = onError;
  279. }
  280. } else {
  281. if (this._texture.isReady) {
  282. Tools.SetImmediate(() => load());
  283. } else {
  284. this._texture.onLoadedObservable.add(load);
  285. }
  286. }
  287. }
  288. /**
  289. * Update the url (and optional buffer) of this texture if url was null during construction.
  290. * @param url the url of the texture
  291. * @param buffer the buffer of the texture (defaults to null)
  292. * @param onLoad callback called when the texture is loaded (defaults to null)
  293. */
  294. public updateURL(url: string, buffer: Nullable<string | ArrayBuffer | HTMLImageElement | Blob> = null, onLoad?: () => void): void {
  295. if (this.url) {
  296. this.releaseInternalTexture();
  297. this.getScene()!.markAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag);
  298. }
  299. this.url = url;
  300. this._buffer = buffer;
  301. this.delayLoadState = Constants.DELAYLOADSTATE_NOTLOADED;
  302. if (onLoad) {
  303. this._delayedOnLoad = onLoad;
  304. }
  305. this.delayLoad();
  306. }
  307. /**
  308. * Finish the loading sequence of a texture flagged as delayed load.
  309. * @hidden
  310. */
  311. public delayLoad(): void {
  312. if (this.delayLoadState !== Constants.DELAYLOADSTATE_NOTLOADED) {
  313. return;
  314. }
  315. let scene = this.getScene();
  316. if (!scene) {
  317. return;
  318. }
  319. this.delayLoadState = Constants.DELAYLOADSTATE_LOADED;
  320. this._texture = this._getFromCache(this.url, this._noMipmap, this.samplingMode, this._invertY);
  321. if (!this._texture) {
  322. this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this.samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
  323. if (this._deleteBuffer) {
  324. delete this._buffer;
  325. }
  326. } else {
  327. if (this._delayedOnLoad) {
  328. if (this._texture.isReady) {
  329. Tools.SetImmediate(this._delayedOnLoad);
  330. } else {
  331. this._texture.onLoadedObservable.add(this._delayedOnLoad);
  332. }
  333. }
  334. }
  335. this._delayedOnLoad = null;
  336. this._delayedOnError = null;
  337. }
  338. private _prepareRowForTextureGeneration(x: number, y: number, z: number, t: Vector3): void {
  339. x *= this.uScale;
  340. y *= this.vScale;
  341. x -= this.uRotationCenter * this.uScale;
  342. y -= this.vRotationCenter * this.vScale;
  343. z -= this.wRotationCenter;
  344. Vector3.TransformCoordinatesFromFloatsToRef(x, y, z, this._rowGenerationMatrix, t);
  345. t.x += this.uRotationCenter * this.uScale + this.uOffset;
  346. t.y += this.vRotationCenter * this.vScale + this.vOffset;
  347. t.z += this.wRotationCenter;
  348. }
  349. /**
  350. * Get the current texture matrix which includes the requested offsetting, tiling and rotation components.
  351. * @returns the transform matrix of the texture.
  352. */
  353. public getTextureMatrix(): Matrix {
  354. if (
  355. this.uOffset === this._cachedUOffset &&
  356. this.vOffset === this._cachedVOffset &&
  357. this.uScale === this._cachedUScale &&
  358. this.vScale === this._cachedVScale &&
  359. this.uAng === this._cachedUAng &&
  360. this.vAng === this._cachedVAng &&
  361. this.wAng === this._cachedWAng) {
  362. return this._cachedTextureMatrix;
  363. }
  364. this._cachedUOffset = this.uOffset;
  365. this._cachedVOffset = this.vOffset;
  366. this._cachedUScale = this.uScale;
  367. this._cachedVScale = this.vScale;
  368. this._cachedUAng = this.uAng;
  369. this._cachedVAng = this.vAng;
  370. this._cachedWAng = this.wAng;
  371. if (!this._cachedTextureMatrix) {
  372. this._cachedTextureMatrix = Matrix.Zero();
  373. this._rowGenerationMatrix = new Matrix();
  374. this._t0 = Vector3.Zero();
  375. this._t1 = Vector3.Zero();
  376. this._t2 = Vector3.Zero();
  377. }
  378. Matrix.RotationYawPitchRollToRef(this.vAng, this.uAng, this.wAng, this._rowGenerationMatrix);
  379. this._prepareRowForTextureGeneration(0, 0, 0, this._t0);
  380. this._prepareRowForTextureGeneration(1.0, 0, 0, this._t1);
  381. this._prepareRowForTextureGeneration(0, 1.0, 0, this._t2);
  382. this._t1.subtractInPlace(this._t0);
  383. this._t2.subtractInPlace(this._t0);
  384. Matrix.FromValuesToRef(
  385. this._t1.x, this._t1.y, this._t1.z, 0.0,
  386. this._t2.x, this._t2.y, this._t2.z, 0.0,
  387. this._t0.x, this._t0.y, this._t0.z, 0.0,
  388. 0.0, 0.0, 0.0, 1.0,
  389. this._cachedTextureMatrix
  390. );
  391. let scene = this.getScene();
  392. if (!scene) {
  393. return this._cachedTextureMatrix;
  394. }
  395. scene.markAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag, (mat) => {
  396. return mat.hasTexture(this);
  397. });
  398. return this._cachedTextureMatrix;
  399. }
  400. /**
  401. * Get the current matrix used to apply reflection. This is useful to rotate an environment texture for instance.
  402. * @returns The reflection texture transform
  403. */
  404. public getReflectionTextureMatrix(): Matrix {
  405. let scene = this.getScene();
  406. if (!scene) {
  407. return this._cachedTextureMatrix;
  408. }
  409. if (
  410. this.uOffset === this._cachedUOffset &&
  411. this.vOffset === this._cachedVOffset &&
  412. this.uScale === this._cachedUScale &&
  413. this.vScale === this._cachedVScale &&
  414. this.coordinatesMode === this._cachedCoordinatesMode) {
  415. if (this.coordinatesMode === Texture.PROJECTION_MODE) {
  416. if (this._cachedProjectionMatrixId === scene.getProjectionMatrix().updateFlag) {
  417. return this._cachedTextureMatrix;
  418. }
  419. } else {
  420. return this._cachedTextureMatrix;
  421. }
  422. }
  423. if (!this._cachedTextureMatrix) {
  424. this._cachedTextureMatrix = Matrix.Zero();
  425. }
  426. if (!this._projectionModeMatrix) {
  427. this._projectionModeMatrix = Matrix.Zero();
  428. }
  429. this._cachedUOffset = this.uOffset;
  430. this._cachedVOffset = this.vOffset;
  431. this._cachedUScale = this.uScale;
  432. this._cachedVScale = this.vScale;
  433. this._cachedCoordinatesMode = this.coordinatesMode;
  434. switch (this.coordinatesMode) {
  435. case Texture.PLANAR_MODE:
  436. Matrix.IdentityToRef(this._cachedTextureMatrix);
  437. (<any>this._cachedTextureMatrix)[0] = this.uScale;
  438. (<any>this._cachedTextureMatrix)[5] = this.vScale;
  439. (<any>this._cachedTextureMatrix)[12] = this.uOffset;
  440. (<any>this._cachedTextureMatrix)[13] = this.vOffset;
  441. break;
  442. case Texture.PROJECTION_MODE:
  443. Matrix.FromValuesToRef(
  444. 0.5, 0.0, 0.0, 0.0,
  445. 0.0, -0.5, 0.0, 0.0,
  446. 0.0, 0.0, 0.0, 0.0,
  447. 0.5, 0.5, 1.0, 1.0,
  448. this._projectionModeMatrix
  449. );
  450. let projectionMatrix = scene.getProjectionMatrix();
  451. this._cachedProjectionMatrixId = projectionMatrix.updateFlag;
  452. projectionMatrix.multiplyToRef(this._projectionModeMatrix, this._cachedTextureMatrix);
  453. break;
  454. default:
  455. Matrix.IdentityToRef(this._cachedTextureMatrix);
  456. break;
  457. }
  458. scene.markAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag, (mat) => {
  459. return (mat.getActiveTextures().indexOf(this) !== -1);
  460. });
  461. return this._cachedTextureMatrix;
  462. }
  463. /**
  464. * Clones the texture.
  465. * @returns the cloned texture
  466. */
  467. public clone(): Texture {
  468. return SerializationHelper.Clone(() => {
  469. return new Texture(this._texture ? this._texture.url : null, this.getScene(), this._noMipmap, this._invertY, this.samplingMode);
  470. }, this);
  471. }
  472. /**
  473. * Serialize the texture to a JSON representation we can easily use in the resepective Parse function.
  474. * @returns The JSON representation of the texture
  475. */
  476. public serialize(): any {
  477. var serializationObject = super.serialize();
  478. if (typeof this._buffer === "string" && (this._buffer as string).substr(0, 5) === "data:") {
  479. serializationObject.base64String = this._buffer;
  480. serializationObject.name = serializationObject.name.replace("data:", "");
  481. }
  482. serializationObject.invertY = this._invertY;
  483. serializationObject.samplingMode = this.samplingMode;
  484. return serializationObject;
  485. }
  486. /**
  487. * Get the current class name of the texture useful for serialization or dynamic coding.
  488. * @returns "Texture"
  489. */
  490. public getClassName(): string {
  491. return "Texture";
  492. }
  493. /**
  494. * Dispose the texture and release its associated resources.
  495. */
  496. public dispose(): void {
  497. super.dispose();
  498. this.onLoadObservable.clear();
  499. this._delayedOnLoad = null;
  500. this._delayedOnError = null;
  501. }
  502. /**
  503. * Parse the JSON representation of a texture in order to recreate the texture in the given scene.
  504. * @param parsedTexture Define the JSON representation of the texture
  505. * @param scene Define the scene the parsed texture should be instantiated in
  506. * @param rootUrl Define the root url of the parsing sequence in the case of relative dependencies
  507. * @returns The parsed texture if successful
  508. */
  509. public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): Nullable<BaseTexture> {
  510. if (parsedTexture.customType) {
  511. var customTexture = Tools.Instantiate(parsedTexture.customType);
  512. // Update Sampling Mode
  513. var parsedCustomTexture: any = customTexture.Parse(parsedTexture, scene, rootUrl);
  514. if (parsedTexture.samplingMode && parsedCustomTexture.updateSamplingMode && parsedCustomTexture._samplingMode) {
  515. if (parsedCustomTexture._samplingMode !== parsedTexture.samplingMode) {
  516. parsedCustomTexture.updateSamplingMode(parsedTexture.samplingMode);
  517. }
  518. }
  519. return parsedCustomTexture;
  520. }
  521. if (parsedTexture.isCube && !parsedTexture.isRenderTarget) {
  522. return Texture._CubeTextureParser(parsedTexture, scene, rootUrl);
  523. }
  524. if (!parsedTexture.name && !parsedTexture.isRenderTarget) {
  525. return null;
  526. }
  527. var texture = SerializationHelper.Parse(() => {
  528. var generateMipMaps: boolean = true;
  529. if (parsedTexture.noMipmap) {
  530. generateMipMaps = false;
  531. }
  532. if (parsedTexture.mirrorPlane) {
  533. var mirrorTexture = Texture._CreateMirror(parsedTexture.name, parsedTexture.renderTargetSize, scene, generateMipMaps);
  534. mirrorTexture._waitingRenderList = parsedTexture.renderList;
  535. mirrorTexture.mirrorPlane = Plane.FromArray(parsedTexture.mirrorPlane);
  536. return mirrorTexture;
  537. } else if (parsedTexture.isRenderTarget) {
  538. let renderTargetTexture: Nullable<RenderTargetTexture> = null;
  539. if (parsedTexture.isCube) {
  540. // Search for an existing reflection probe (which contains a cube render target texture)
  541. if (scene.reflectionProbes) {
  542. for (var index = 0; index < scene.reflectionProbes.length; index++) {
  543. const probe = scene.reflectionProbes[index];
  544. if (probe.name === parsedTexture.name) {
  545. return probe.cubeTexture;
  546. }
  547. }
  548. }
  549. } else {
  550. renderTargetTexture = Texture._CreateRenderTargetTexture(parsedTexture.name, parsedTexture.renderTargetSize, scene, generateMipMaps);
  551. renderTargetTexture._waitingRenderList = parsedTexture.renderList;
  552. }
  553. return renderTargetTexture;
  554. } else {
  555. var texture: Texture;
  556. if (parsedTexture.base64String) {
  557. texture = Texture.CreateFromBase64String(parsedTexture.base64String, parsedTexture.name, scene, !generateMipMaps);
  558. } else {
  559. let url = rootUrl + parsedTexture.name;
  560. if (Texture.UseSerializedUrlIfAny && parsedTexture.url) {
  561. url = parsedTexture.url;
  562. }
  563. texture = new Texture(url, scene, !generateMipMaps, parsedTexture.invertY);
  564. }
  565. return texture;
  566. }
  567. }, parsedTexture, scene);
  568. // Update Sampling Mode
  569. if (parsedTexture.samplingMode) {
  570. var sampling: number = parsedTexture.samplingMode;
  571. if (texture && texture.samplingMode !== sampling) {
  572. texture.updateSamplingMode(sampling);
  573. }
  574. }
  575. // Animations
  576. if (texture && parsedTexture.animations) {
  577. for (var animationIndex = 0; animationIndex < parsedTexture.animations.length; animationIndex++) {
  578. var parsedAnimation = parsedTexture.animations[animationIndex];
  579. const internalClass = _TypeStore.GetClass("BABYLON.Animation");
  580. if (internalClass) {
  581. texture.animations.push(internalClass.Parse(parsedAnimation));
  582. }
  583. }
  584. }
  585. return texture;
  586. }
  587. /**
  588. * Creates a texture from its base 64 representation.
  589. * @param data Define the base64 payload without the data: prefix
  590. * @param name Define the name of the texture in the scene useful fo caching purpose for instance
  591. * @param scene Define the scene the texture should belong to
  592. * @param noMipmap Forces the texture to not create mip map information if true
  593. * @param invertY define if the texture needs to be inverted on the y axis during loading
  594. * @param samplingMode define the sampling mode we want for the texture while fectching from it (Texture.NEAREST_SAMPLINGMODE...)
  595. * @param onLoad define a callback triggered when the texture has been loaded
  596. * @param onError define a callback triggered when an error occurred during the loading session
  597. * @param format define the format of the texture we are trying to load (Engine.TEXTUREFORMAT_RGBA...)
  598. * @returns the created texture
  599. */
  600. public static CreateFromBase64String(data: string, name: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE,
  601. onLoad: Nullable<() => void> = null, onError: Nullable<() => void> = null, format: number = Constants.TEXTUREFORMAT_RGBA): Texture {
  602. return new Texture("data:" + name, scene, noMipmap, invertY, samplingMode, onLoad, onError, data, false, format);
  603. }
  604. /**
  605. * Creates a texture from its data: representation. (data: will be added in case only the payload has been passed in)
  606. * @param data Define the base64 payload without the data: prefix
  607. * @param name Define the name of the texture in the scene useful fo caching purpose for instance
  608. * @param buffer define the buffer to load the texture from in case the texture is loaded from a buffer representation
  609. * @param scene Define the scene the texture should belong to
  610. * @param deleteBuffer define if the buffer we are loading the texture from should be deleted after load
  611. * @param noMipmap Forces the texture to not create mip map information if true
  612. * @param invertY define if the texture needs to be inverted on the y axis during loading
  613. * @param samplingMode define the sampling mode we want for the texture while fectching from it (Texture.NEAREST_SAMPLINGMODE...)
  614. * @param onLoad define a callback triggered when the texture has been loaded
  615. * @param onError define a callback triggered when an error occurred during the loading session
  616. * @param format define the format of the texture we are trying to load (Engine.TEXTUREFORMAT_RGBA...)
  617. * @returns the created texture
  618. */
  619. public static LoadFromDataString(name: string, buffer: any, scene: Scene, deleteBuffer: boolean = false, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE,
  620. onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format: number = Constants.TEXTUREFORMAT_RGBA): Texture {
  621. if (name.substr(0, 5) !== "data:") {
  622. name = "data:" + name;
  623. }
  624. return new Texture(name, scene, noMipmap, invertY, samplingMode, onLoad, onError, buffer, deleteBuffer, format);
  625. }
  626. }
  627. // References the dependencies.
  628. SerializationHelper._TextureParser = Texture.Parse;