texture.ts 31 KB

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