baseTexture.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. import { __decorate } from "../../tslib.es6.js";
  2. import { serialize, serializeAsTexture } from "../../Misc/decorators.js";
  3. import { Observable } from "../../Misc/observable.js";
  4. import { Matrix } from "../../Maths/math.vector.js";
  5. import { EngineStore } from "../../Engines/engineStore.js";
  6. import { RandomGUID } from "../../Misc/guid.js";
  7. import "../../Misc/fileTools.js";
  8. import { ThinTexture } from "./thinTexture.js";
  9. import { SerializationHelper } from "../../Misc/decorators.serialization.js";
  10. /**
  11. * Base class of all the textures in babylon.
  12. * It groups all the common properties the materials, post process, lights... might need
  13. * in order to make a correct use of the texture.
  14. */
  15. export class BaseTexture extends ThinTexture {
  16. /**
  17. * Define if the texture is having a usable alpha value (can be use for transparency or glossiness for instance).
  18. */
  19. set hasAlpha(value) {
  20. if (this._hasAlpha === value) {
  21. return;
  22. }
  23. this._hasAlpha = value;
  24. if (this._scene) {
  25. this._scene.markAllMaterialsAsDirty(1, (mat) => {
  26. return mat.hasTexture(this);
  27. });
  28. }
  29. }
  30. get hasAlpha() {
  31. return this._hasAlpha;
  32. }
  33. /**
  34. * Defines if the alpha value should be determined via the rgb values.
  35. * If true the luminance of the pixel might be used to find the corresponding alpha value.
  36. */
  37. set getAlphaFromRGB(value) {
  38. if (this._getAlphaFromRGB === value) {
  39. return;
  40. }
  41. this._getAlphaFromRGB = value;
  42. if (this._scene) {
  43. this._scene.markAllMaterialsAsDirty(1, (mat) => {
  44. return mat.hasTexture(this);
  45. });
  46. }
  47. }
  48. get getAlphaFromRGB() {
  49. return this._getAlphaFromRGB;
  50. }
  51. /**
  52. * Define the UV channel to use starting from 0 and defaulting to 0.
  53. * This is part of the texture as textures usually maps to one uv set.
  54. */
  55. set coordinatesIndex(value) {
  56. if (this._coordinatesIndex === value) {
  57. return;
  58. }
  59. this._coordinatesIndex = value;
  60. if (this._scene) {
  61. this._scene.markAllMaterialsAsDirty(1, (mat) => {
  62. return mat.hasTexture(this);
  63. });
  64. }
  65. }
  66. get coordinatesIndex() {
  67. return this._coordinatesIndex;
  68. }
  69. /**
  70. * How a texture is mapped.
  71. *
  72. * | Value | Type | Description |
  73. * | ----- | ----------------------------------- | ----------- |
  74. * | 0 | EXPLICIT_MODE | |
  75. * | 1 | SPHERICAL_MODE | |
  76. * | 2 | PLANAR_MODE | |
  77. * | 3 | CUBIC_MODE | |
  78. * | 4 | PROJECTION_MODE | |
  79. * | 5 | SKYBOX_MODE | |
  80. * | 6 | INVCUBIC_MODE | |
  81. * | 7 | EQUIRECTANGULAR_MODE | |
  82. * | 8 | FIXED_EQUIRECTANGULAR_MODE | |
  83. * | 9 | FIXED_EQUIRECTANGULAR_MIRRORED_MODE | |
  84. */
  85. set coordinatesMode(value) {
  86. if (this._coordinatesMode === value) {
  87. return;
  88. }
  89. this._coordinatesMode = value;
  90. if (this._scene) {
  91. this._scene.markAllMaterialsAsDirty(1, (mat) => {
  92. return mat.hasTexture(this);
  93. });
  94. }
  95. }
  96. get coordinatesMode() {
  97. return this._coordinatesMode;
  98. }
  99. /**
  100. * | Value | Type | Description |
  101. * | ----- | ------------------ | ----------- |
  102. * | 0 | CLAMP_ADDRESSMODE | |
  103. * | 1 | WRAP_ADDRESSMODE | |
  104. * | 2 | MIRROR_ADDRESSMODE | |
  105. */
  106. get wrapU() {
  107. return this._wrapU;
  108. }
  109. set wrapU(value) {
  110. this._wrapU = value;
  111. }
  112. /**
  113. * | Value | Type | Description |
  114. * | ----- | ------------------ | ----------- |
  115. * | 0 | CLAMP_ADDRESSMODE | |
  116. * | 1 | WRAP_ADDRESSMODE | |
  117. * | 2 | MIRROR_ADDRESSMODE | |
  118. */
  119. get wrapV() {
  120. return this._wrapV;
  121. }
  122. set wrapV(value) {
  123. this._wrapV = value;
  124. }
  125. /**
  126. * Define if the texture is a cube texture or if false a 2d texture.
  127. */
  128. get isCube() {
  129. if (!this._texture) {
  130. return this._isCube;
  131. }
  132. return this._texture.isCube;
  133. }
  134. // eslint-disable-next-line @typescript-eslint/naming-convention
  135. set isCube(value) {
  136. if (!this._texture) {
  137. this._isCube = value;
  138. }
  139. else {
  140. this._texture.isCube = value;
  141. }
  142. }
  143. /**
  144. * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
  145. */
  146. get is3D() {
  147. if (!this._texture) {
  148. return false;
  149. }
  150. return this._texture.is3D;
  151. }
  152. // eslint-disable-next-line @typescript-eslint/naming-convention
  153. set is3D(value) {
  154. if (!this._texture) {
  155. return;
  156. }
  157. this._texture.is3D = value;
  158. }
  159. /**
  160. * Define if the texture is a 2d array texture (webgl 2) or if false a 2d texture.
  161. */
  162. get is2DArray() {
  163. if (!this._texture) {
  164. return false;
  165. }
  166. return this._texture.is2DArray;
  167. }
  168. // eslint-disable-next-line @typescript-eslint/naming-convention
  169. set is2DArray(value) {
  170. if (!this._texture) {
  171. return;
  172. }
  173. this._texture.is2DArray = value;
  174. }
  175. /**
  176. * Define if the texture contains data in gamma space (most of the png/jpg aside bump).
  177. * HDR texture are usually stored in linear space.
  178. * This only impacts the PBR and Background materials
  179. */
  180. get gammaSpace() {
  181. if (!this._texture) {
  182. return this._gammaSpace;
  183. }
  184. else {
  185. if (this._texture._gammaSpace === null) {
  186. this._texture._gammaSpace = this._gammaSpace;
  187. }
  188. }
  189. return this._texture._gammaSpace && !this._texture._useSRGBBuffer;
  190. }
  191. set gammaSpace(gamma) {
  192. if (!this._texture) {
  193. if (this._gammaSpace === gamma) {
  194. return;
  195. }
  196. this._gammaSpace = gamma;
  197. }
  198. else {
  199. if (this._texture._gammaSpace === gamma) {
  200. return;
  201. }
  202. this._texture._gammaSpace = gamma;
  203. }
  204. this.getScene()?.markAllMaterialsAsDirty(1, (mat) => {
  205. return mat.hasTexture(this);
  206. });
  207. }
  208. /**
  209. * Gets or sets whether or not the texture contains RGBD data.
  210. */
  211. get isRGBD() {
  212. return this._texture != null && this._texture._isRGBD;
  213. }
  214. set isRGBD(value) {
  215. if (value === this.isRGBD) {
  216. return;
  217. }
  218. if (this._texture) {
  219. this._texture._isRGBD = value;
  220. }
  221. this.getScene()?.markAllMaterialsAsDirty(1, (mat) => {
  222. return mat.hasTexture(this);
  223. });
  224. }
  225. /**
  226. * Are mip maps generated for this texture or not.
  227. */
  228. get noMipmap() {
  229. return false;
  230. }
  231. /**
  232. * With prefiltered texture, defined the offset used during the prefiltering steps.
  233. */
  234. get lodGenerationOffset() {
  235. if (this._texture) {
  236. return this._texture._lodGenerationOffset;
  237. }
  238. return 0.0;
  239. }
  240. set lodGenerationOffset(value) {
  241. if (this._texture) {
  242. this._texture._lodGenerationOffset = value;
  243. }
  244. }
  245. /**
  246. * With prefiltered texture, defined the scale used during the prefiltering steps.
  247. */
  248. get lodGenerationScale() {
  249. if (this._texture) {
  250. return this._texture._lodGenerationScale;
  251. }
  252. return 0.0;
  253. }
  254. set lodGenerationScale(value) {
  255. if (this._texture) {
  256. this._texture._lodGenerationScale = value;
  257. }
  258. }
  259. /**
  260. * With prefiltered texture, defined if the specular generation is based on a linear ramp.
  261. * By default we are using a log2 of the linear roughness helping to keep a better resolution for
  262. * average roughness values.
  263. */
  264. get linearSpecularLOD() {
  265. if (this._texture) {
  266. return this._texture._linearSpecularLOD;
  267. }
  268. return false;
  269. }
  270. set linearSpecularLOD(value) {
  271. if (this._texture) {
  272. this._texture._linearSpecularLOD = value;
  273. }
  274. }
  275. /**
  276. * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
  277. * You can set the irradiance texture to rely on a texture instead of the spherical approach.
  278. * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
  279. */
  280. get irradianceTexture() {
  281. if (this._texture) {
  282. return this._texture._irradianceTexture;
  283. }
  284. return null;
  285. }
  286. set irradianceTexture(value) {
  287. if (this._texture) {
  288. this._texture._irradianceTexture = value;
  289. }
  290. }
  291. /**
  292. * Define the unique id of the texture in the scene.
  293. */
  294. get uid() {
  295. if (!this._uid) {
  296. this._uid = RandomGUID();
  297. }
  298. return this._uid;
  299. }
  300. /**
  301. * Return a string representation of the texture.
  302. * @returns the texture as a string
  303. */
  304. toString() {
  305. return this.name;
  306. }
  307. /**
  308. * Get the class name of the texture.
  309. * @returns "BaseTexture"
  310. */
  311. getClassName() {
  312. return "BaseTexture";
  313. }
  314. /**
  315. * Callback triggered when the texture has been disposed.
  316. * Kept for back compatibility, you can use the onDisposeObservable instead.
  317. */
  318. set onDispose(callback) {
  319. if (this._onDisposeObserver) {
  320. this.onDisposeObservable.remove(this._onDisposeObserver);
  321. }
  322. this._onDisposeObserver = this.onDisposeObservable.add(callback);
  323. }
  324. /**
  325. * Define if the texture is preventing a material to render or not.
  326. * If not and the texture is not ready, the engine will use a default black texture instead.
  327. */
  328. get isBlocking() {
  329. return true;
  330. }
  331. /**
  332. * Was there any loading error?
  333. */
  334. get loadingError() {
  335. return this._loadingError;
  336. }
  337. /**
  338. * If a loading error occurred this object will be populated with information about the error.
  339. */
  340. get errorObject() {
  341. return this._errorObject;
  342. }
  343. /**
  344. * Instantiates a new BaseTexture.
  345. * Base class of all the textures in babylon.
  346. * It groups all the common properties the materials, post process, lights... might need
  347. * in order to make a correct use of the texture.
  348. * @param sceneOrEngine Define the scene or engine the texture belongs to
  349. * @param internalTexture Define the internal texture associated with the texture
  350. */
  351. constructor(sceneOrEngine, internalTexture = null) {
  352. super(null);
  353. /**
  354. * Gets or sets an object used to store user defined information.
  355. */
  356. this.metadata = null;
  357. /**
  358. * For internal use only. Please do not use.
  359. */
  360. this.reservedDataStore = null;
  361. this._hasAlpha = false;
  362. this._getAlphaFromRGB = false;
  363. /**
  364. * Intensity or strength of the texture.
  365. * It is commonly used by materials to fine tune the intensity of the texture
  366. */
  367. this.level = 1;
  368. this._coordinatesIndex = 0;
  369. /**
  370. * Gets or sets a boolean indicating that the texture should try to reduce shader code if there is no UV manipulation.
  371. * (ie. when texture.getTextureMatrix().isIdentityAs3x2() returns true)
  372. */
  373. this.optimizeUVAllocation = true;
  374. this._coordinatesMode = 0;
  375. /**
  376. * | Value | Type | Description |
  377. * | ----- | ------------------ | ----------- |
  378. * | 0 | CLAMP_ADDRESSMODE | |
  379. * | 1 | WRAP_ADDRESSMODE | |
  380. * | 2 | MIRROR_ADDRESSMODE | |
  381. */
  382. this.wrapR = 1;
  383. /**
  384. * With compliant hardware and browser (supporting anisotropic filtering)
  385. * this defines the level of anisotropic filtering in the texture.
  386. * The higher the better but the slower. This defaults to 4 as it seems to be the best tradeoff.
  387. */
  388. this.anisotropicFilteringLevel = BaseTexture.DEFAULT_ANISOTROPIC_FILTERING_LEVEL;
  389. /** @internal */
  390. this._isCube = false;
  391. /** @internal */
  392. this._gammaSpace = true;
  393. /**
  394. * Is Z inverted in the texture (useful in a cube texture).
  395. */
  396. this.invertZ = false;
  397. /**
  398. * @internal
  399. */
  400. this.lodLevelInAlpha = false;
  401. /**
  402. * Define if the texture is a render target.
  403. */
  404. this.isRenderTarget = false;
  405. /** @internal */
  406. this._prefiltered = false;
  407. /** @internal */
  408. this._forceSerialize = false;
  409. /**
  410. * Define the list of animation attached to the texture.
  411. */
  412. this.animations = [];
  413. /**
  414. * An event triggered when the texture is disposed.
  415. */
  416. this.onDisposeObservable = new Observable();
  417. this._onDisposeObserver = null;
  418. this._scene = null;
  419. /** @internal */
  420. this._uid = null;
  421. /** @internal */
  422. this._parentContainer = null;
  423. this._loadingError = false;
  424. if (sceneOrEngine) {
  425. if (BaseTexture._IsScene(sceneOrEngine)) {
  426. this._scene = sceneOrEngine;
  427. }
  428. else {
  429. this._engine = sceneOrEngine;
  430. }
  431. }
  432. else {
  433. this._scene = EngineStore.LastCreatedScene;
  434. }
  435. if (this._scene) {
  436. this.uniqueId = this._scene.getUniqueId();
  437. this._scene.addTexture(this);
  438. this._engine = this._scene.getEngine();
  439. }
  440. this._texture = internalTexture;
  441. this._uid = null;
  442. }
  443. /**
  444. * Get the scene the texture belongs to.
  445. * @returns the scene or null if undefined
  446. */
  447. getScene() {
  448. return this._scene;
  449. }
  450. /** @internal */
  451. _getEngine() {
  452. return this._engine;
  453. }
  454. /**
  455. * Get the texture transform matrix used to offset tile the texture for instance.
  456. * @returns the transformation matrix
  457. */
  458. getTextureMatrix() {
  459. return Matrix.IdentityReadOnly;
  460. }
  461. /**
  462. * Get the texture reflection matrix used to rotate/transform the reflection.
  463. * @returns the reflection matrix
  464. */
  465. getReflectionTextureMatrix() {
  466. return Matrix.IdentityReadOnly;
  467. }
  468. /**
  469. * Gets a suitable rotate/transform matrix when the texture is used for refraction.
  470. * There's a separate function from getReflectionTextureMatrix because refraction requires a special configuration of the matrix in right-handed mode.
  471. * @returns The refraction matrix
  472. */
  473. getRefractionTextureMatrix() {
  474. return this.getReflectionTextureMatrix();
  475. }
  476. /**
  477. * Get if the texture is ready to be consumed (either it is ready or it is not blocking)
  478. * @returns true if ready, not blocking or if there was an error loading the texture
  479. */
  480. isReadyOrNotBlocking() {
  481. return !this.isBlocking || this.isReady() || this.loadingError;
  482. }
  483. /**
  484. * Scales the texture if is `canRescale()`
  485. * @param ratio the resize factor we want to use to rescale
  486. */
  487. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  488. scale(ratio) { }
  489. /**
  490. * Get if the texture can rescale.
  491. */
  492. get canRescale() {
  493. return false;
  494. }
  495. /**
  496. * @internal
  497. */
  498. _getFromCache(url, noMipmap, sampling, invertY, useSRGBBuffer, isCube) {
  499. const engine = this._getEngine();
  500. if (!engine) {
  501. return null;
  502. }
  503. const correctedUseSRGBBuffer = engine._getUseSRGBBuffer(!!useSRGBBuffer, noMipmap);
  504. const texturesCache = engine.getLoadedTexturesCache();
  505. for (let index = 0; index < texturesCache.length; index++) {
  506. const texturesCacheEntry = texturesCache[index];
  507. if (useSRGBBuffer === undefined || correctedUseSRGBBuffer === texturesCacheEntry._useSRGBBuffer) {
  508. if (invertY === undefined || invertY === texturesCacheEntry.invertY) {
  509. if (texturesCacheEntry.url === url && texturesCacheEntry.generateMipMaps === !noMipmap) {
  510. if (!sampling || sampling === texturesCacheEntry.samplingMode) {
  511. if (isCube === undefined || isCube === texturesCacheEntry.isCube) {
  512. texturesCacheEntry.incrementReferences();
  513. return texturesCacheEntry;
  514. }
  515. }
  516. }
  517. }
  518. }
  519. }
  520. return null;
  521. }
  522. /** @internal */
  523. _rebuild(_fromContextLost = false) { }
  524. /**
  525. * Clones the texture.
  526. * @returns the cloned texture
  527. */
  528. clone() {
  529. return null;
  530. }
  531. /**
  532. * Get the texture underlying type (INT, FLOAT...)
  533. */
  534. get textureType() {
  535. if (!this._texture) {
  536. return 0;
  537. }
  538. return this._texture.type !== undefined ? this._texture.type : 0;
  539. }
  540. /**
  541. * Get the texture underlying format (RGB, RGBA...)
  542. */
  543. get textureFormat() {
  544. if (!this._texture) {
  545. return 5;
  546. }
  547. return this._texture.format !== undefined ? this._texture.format : 5;
  548. }
  549. /**
  550. * Indicates that textures need to be re-calculated for all materials
  551. */
  552. _markAllSubMeshesAsTexturesDirty() {
  553. const scene = this.getScene();
  554. if (!scene) {
  555. return;
  556. }
  557. scene.markAllMaterialsAsDirty(1);
  558. }
  559. /**
  560. * Reads the pixels stored in the webgl texture and returns them as an ArrayBuffer.
  561. * This will returns an RGBA array buffer containing either in values (0-255) or
  562. * float values (0-1) depending of the underlying buffer type.
  563. * @param faceIndex defines the face of the texture to read (in case of cube texture)
  564. * @param level defines the LOD level of the texture to read (in case of Mip Maps)
  565. * @param buffer defines a user defined buffer to fill with data (can be null)
  566. * @param flushRenderer true to flush the renderer from the pending commands before reading the pixels
  567. * @param noDataConversion false to convert the data to Uint8Array (if texture type is UNSIGNED_BYTE) or to Float32Array (if texture type is anything but UNSIGNED_BYTE). If true, the type of the generated buffer (if buffer==null) will depend on the type of the texture
  568. * @param x defines the region x coordinates to start reading from (default to 0)
  569. * @param y defines the region y coordinates to start reading from (default to 0)
  570. * @param width defines the region width to read from (default to the texture size at level)
  571. * @param height defines the region width to read from (default to the texture size at level)
  572. * @returns The Array buffer promise containing the pixels data.
  573. */
  574. readPixels(faceIndex = 0, level = 0, buffer = null, flushRenderer = true, noDataConversion = false, x = 0, y = 0, width = Number.MAX_VALUE, height = Number.MAX_VALUE) {
  575. if (!this._texture) {
  576. return null;
  577. }
  578. const engine = this._getEngine();
  579. if (!engine) {
  580. return null;
  581. }
  582. const size = this.getSize();
  583. let maxWidth = size.width;
  584. let maxHeight = size.height;
  585. if (level !== 0) {
  586. maxWidth = maxWidth / Math.pow(2, level);
  587. maxHeight = maxHeight / Math.pow(2, level);
  588. maxWidth = Math.round(maxWidth);
  589. maxHeight = Math.round(maxHeight);
  590. }
  591. width = Math.min(maxWidth, width);
  592. height = Math.min(maxHeight, height);
  593. try {
  594. if (this._texture.isCube) {
  595. return engine._readTexturePixels(this._texture, width, height, faceIndex, level, buffer, flushRenderer, noDataConversion, x, y);
  596. }
  597. return engine._readTexturePixels(this._texture, width, height, -1, level, buffer, flushRenderer, noDataConversion, x, y);
  598. }
  599. catch (e) {
  600. return null;
  601. }
  602. }
  603. /**
  604. * @internal
  605. */
  606. _readPixelsSync(faceIndex = 0, level = 0, buffer = null, flushRenderer = true, noDataConversion = false) {
  607. if (!this._texture) {
  608. return null;
  609. }
  610. const size = this.getSize();
  611. let width = size.width;
  612. let height = size.height;
  613. const engine = this._getEngine();
  614. if (!engine) {
  615. return null;
  616. }
  617. if (level != 0) {
  618. width = width / Math.pow(2, level);
  619. height = height / Math.pow(2, level);
  620. width = Math.round(width);
  621. height = Math.round(height);
  622. }
  623. try {
  624. if (this._texture.isCube) {
  625. return engine._readTexturePixelsSync(this._texture, width, height, faceIndex, level, buffer, flushRenderer, noDataConversion);
  626. }
  627. return engine._readTexturePixelsSync(this._texture, width, height, -1, level, buffer, flushRenderer, noDataConversion);
  628. }
  629. catch (e) {
  630. return null;
  631. }
  632. }
  633. /** @internal */
  634. get _lodTextureHigh() {
  635. if (this._texture) {
  636. return this._texture._lodTextureHigh;
  637. }
  638. return null;
  639. }
  640. /** @internal */
  641. get _lodTextureMid() {
  642. if (this._texture) {
  643. return this._texture._lodTextureMid;
  644. }
  645. return null;
  646. }
  647. /** @internal */
  648. get _lodTextureLow() {
  649. if (this._texture) {
  650. return this._texture._lodTextureLow;
  651. }
  652. return null;
  653. }
  654. /**
  655. * Dispose the texture and release its associated resources.
  656. */
  657. dispose() {
  658. if (this._scene) {
  659. // Animations
  660. if (this._scene.stopAnimation) {
  661. this._scene.stopAnimation(this);
  662. }
  663. // Remove from scene
  664. this._scene.removePendingData(this);
  665. const index = this._scene.textures.indexOf(this);
  666. if (index >= 0) {
  667. this._scene.textures.splice(index, 1);
  668. }
  669. this._scene.onTextureRemovedObservable.notifyObservers(this);
  670. this._scene = null;
  671. if (this._parentContainer) {
  672. const index = this._parentContainer.textures.indexOf(this);
  673. if (index > -1) {
  674. this._parentContainer.textures.splice(index, 1);
  675. }
  676. this._parentContainer = null;
  677. }
  678. }
  679. // Callback
  680. this.onDisposeObservable.notifyObservers(this);
  681. this.onDisposeObservable.clear();
  682. this.metadata = null;
  683. super.dispose();
  684. }
  685. /**
  686. * Serialize the texture into a JSON representation that can be parsed later on.
  687. * @param allowEmptyName True to force serialization even if name is empty. Default: false
  688. * @returns the JSON representation of the texture
  689. */
  690. serialize(allowEmptyName = false) {
  691. if (!this.name && !allowEmptyName) {
  692. return null;
  693. }
  694. const serializationObject = SerializationHelper.Serialize(this);
  695. // Animations
  696. SerializationHelper.AppendSerializedAnimations(this, serializationObject);
  697. return serializationObject;
  698. }
  699. /**
  700. * Helper function to be called back once a list of texture contains only ready textures.
  701. * @param textures Define the list of textures to wait for
  702. * @param callback Define the callback triggered once the entire list will be ready
  703. */
  704. static WhenAllReady(textures, callback) {
  705. let numRemaining = textures.length;
  706. if (numRemaining === 0) {
  707. callback();
  708. return;
  709. }
  710. for (let i = 0; i < textures.length; i++) {
  711. const texture = textures[i];
  712. if (texture.isReady()) {
  713. if (--numRemaining === 0) {
  714. callback();
  715. }
  716. }
  717. else {
  718. const onLoadObservable = texture.onLoadObservable;
  719. if (onLoadObservable) {
  720. onLoadObservable.addOnce(() => {
  721. if (--numRemaining === 0) {
  722. callback();
  723. }
  724. });
  725. }
  726. else {
  727. if (--numRemaining === 0) {
  728. callback();
  729. }
  730. }
  731. }
  732. }
  733. }
  734. static _IsScene(sceneOrEngine) {
  735. return sceneOrEngine.getClassName() === "Scene";
  736. }
  737. }
  738. /**
  739. * Default anisotropic filtering level for the application.
  740. * It is set to 4 as a good tradeoff between perf and quality.
  741. */
  742. BaseTexture.DEFAULT_ANISOTROPIC_FILTERING_LEVEL = 4;
  743. __decorate([
  744. serialize()
  745. ], BaseTexture.prototype, "uniqueId", void 0);
  746. __decorate([
  747. serialize()
  748. ], BaseTexture.prototype, "name", void 0);
  749. __decorate([
  750. serialize()
  751. ], BaseTexture.prototype, "metadata", void 0);
  752. __decorate([
  753. serialize("hasAlpha")
  754. ], BaseTexture.prototype, "_hasAlpha", void 0);
  755. __decorate([
  756. serialize("getAlphaFromRGB")
  757. ], BaseTexture.prototype, "_getAlphaFromRGB", void 0);
  758. __decorate([
  759. serialize()
  760. ], BaseTexture.prototype, "level", void 0);
  761. __decorate([
  762. serialize("coordinatesIndex")
  763. ], BaseTexture.prototype, "_coordinatesIndex", void 0);
  764. __decorate([
  765. serialize()
  766. ], BaseTexture.prototype, "optimizeUVAllocation", void 0);
  767. __decorate([
  768. serialize("coordinatesMode")
  769. ], BaseTexture.prototype, "_coordinatesMode", void 0);
  770. __decorate([
  771. serialize()
  772. ], BaseTexture.prototype, "wrapU", null);
  773. __decorate([
  774. serialize()
  775. ], BaseTexture.prototype, "wrapV", null);
  776. __decorate([
  777. serialize()
  778. ], BaseTexture.prototype, "wrapR", void 0);
  779. __decorate([
  780. serialize()
  781. ], BaseTexture.prototype, "anisotropicFilteringLevel", void 0);
  782. __decorate([
  783. serialize()
  784. ], BaseTexture.prototype, "isCube", null);
  785. __decorate([
  786. serialize()
  787. ], BaseTexture.prototype, "is3D", null);
  788. __decorate([
  789. serialize()
  790. ], BaseTexture.prototype, "is2DArray", null);
  791. __decorate([
  792. serialize()
  793. ], BaseTexture.prototype, "gammaSpace", null);
  794. __decorate([
  795. serialize()
  796. ], BaseTexture.prototype, "invertZ", void 0);
  797. __decorate([
  798. serialize()
  799. ], BaseTexture.prototype, "lodLevelInAlpha", void 0);
  800. __decorate([
  801. serialize()
  802. ], BaseTexture.prototype, "lodGenerationOffset", null);
  803. __decorate([
  804. serialize()
  805. ], BaseTexture.prototype, "lodGenerationScale", null);
  806. __decorate([
  807. serialize()
  808. ], BaseTexture.prototype, "linearSpecularLOD", null);
  809. __decorate([
  810. serializeAsTexture()
  811. ], BaseTexture.prototype, "irradianceTexture", null);
  812. __decorate([
  813. serialize()
  814. ], BaseTexture.prototype, "isRenderTarget", void 0);
  815. //# sourceMappingURL=baseTexture.js.map