internalTexture.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. import { Observable } from "../../Misc/observable";
  2. import { Nullable, int } from "../../types";
  3. import { SphericalPolynomial } from "../../Maths/sphericalPolynomial";
  4. import { RenderTargetCreationOptions } from "../../Materials/Textures/renderTargetCreationOptions";
  5. import { _TimeToken } from "../../Instrumentation/timeToken";
  6. import { _DepthCullingState, _StencilState, _AlphaState } from "../../States/index";
  7. import { Constants } from "../../Engines/constants";
  8. import { _DevTools } from '../../Misc/devTools';
  9. declare type Engine = import("../../Engines/engine").Engine;
  10. declare type BaseTexture = import("../../Materials/Textures/baseTexture").BaseTexture;
  11. /**
  12. * Class used to store data associated with WebGL texture data for the engine
  13. * This class should not be used directly
  14. */
  15. export class InternalTexture {
  16. /** hidden */
  17. public static _UpdateRGBDAsync = (internalTexture: InternalTexture, data: ArrayBufferView[][], sphericalPolynomial: Nullable<SphericalPolynomial>, lodScale: number, lodOffset: number): Promise<void> => {
  18. throw _DevTools.WarnImport("environmentTextureTools");
  19. }
  20. /**
  21. * The source of the texture data is unknown
  22. */
  23. public static DATASOURCE_UNKNOWN = 0;
  24. /**
  25. * Texture data comes from an URL
  26. */
  27. public static DATASOURCE_URL = 1;
  28. /**
  29. * Texture data is only used for temporary storage
  30. */
  31. public static DATASOURCE_TEMP = 2;
  32. /**
  33. * Texture data comes from raw data (ArrayBuffer)
  34. */
  35. public static DATASOURCE_RAW = 3;
  36. /**
  37. * Texture content is dynamic (video or dynamic texture)
  38. */
  39. public static DATASOURCE_DYNAMIC = 4;
  40. /**
  41. * Texture content is generated by rendering to it
  42. */
  43. public static DATASOURCE_RENDERTARGET = 5;
  44. /**
  45. * Texture content is part of a multi render target process
  46. */
  47. public static DATASOURCE_MULTIRENDERTARGET = 6;
  48. /**
  49. * Texture data comes from a cube data file
  50. */
  51. public static DATASOURCE_CUBE = 7;
  52. /**
  53. * Texture data comes from a raw cube data
  54. */
  55. public static DATASOURCE_CUBERAW = 8;
  56. /**
  57. * Texture data come from a prefiltered cube data file
  58. */
  59. public static DATASOURCE_CUBEPREFILTERED = 9;
  60. /**
  61. * Texture content is raw 3D data
  62. */
  63. public static DATASOURCE_RAW3D = 10;
  64. /**
  65. * Texture content is a depth texture
  66. */
  67. public static DATASOURCE_DEPTHTEXTURE = 11;
  68. /**
  69. * Texture data comes from a raw cube data encoded with RGBD
  70. */
  71. public static DATASOURCE_CUBERAW_RGBD = 12;
  72. /**
  73. * Defines if the texture is ready
  74. */
  75. public isReady: boolean = false;
  76. /**
  77. * Defines if the texture is a cube texture
  78. */
  79. public isCube: boolean = false;
  80. /**
  81. * Defines if the texture contains 3D data
  82. */
  83. public is3D: boolean = false;
  84. /**
  85. * Defines if the texture contains multiview data
  86. */
  87. public isMultiview: boolean = false;
  88. /**
  89. * Gets the URL used to load this texture
  90. */
  91. public url: string = "";
  92. /**
  93. * Gets the sampling mode of the texture
  94. */
  95. public samplingMode: number = -1;
  96. /**
  97. * Gets a boolean indicating if the texture needs mipmaps generation
  98. */
  99. public generateMipMaps: boolean = false;
  100. /**
  101. * Gets the number of samples used by the texture (WebGL2+ only)
  102. */
  103. public samples: number = 0;
  104. /**
  105. * Gets the type of the texture (int, float...)
  106. */
  107. public type: number = -1;
  108. /**
  109. * Gets the format of the texture (RGB, RGBA...)
  110. */
  111. public format: number = -1;
  112. /**
  113. * Observable called when the texture is loaded
  114. */
  115. public onLoadedObservable = new Observable<InternalTexture>();
  116. /**
  117. * Gets the width of the texture
  118. */
  119. public width: number = 0;
  120. /**
  121. * Gets the height of the texture
  122. */
  123. public height: number = 0;
  124. /**
  125. * Gets the depth of the texture
  126. */
  127. public depth: number = 0;
  128. /**
  129. * Gets the initial width of the texture (It could be rescaled if the current system does not support non power of two textures)
  130. */
  131. public baseWidth: number = 0;
  132. /**
  133. * Gets the initial height of the texture (It could be rescaled if the current system does not support non power of two textures)
  134. */
  135. public baseHeight: number = 0;
  136. /**
  137. * Gets the initial depth of the texture (It could be rescaled if the current system does not support non power of two textures)
  138. */
  139. public baseDepth: number = 0;
  140. /**
  141. * Gets a boolean indicating if the texture is inverted on Y axis
  142. */
  143. public invertY: boolean = false;
  144. // Private
  145. /** @hidden */
  146. public _invertVScale = false;
  147. /** @hidden */
  148. public _associatedChannel = -1;
  149. /** @hidden */
  150. public _dataSource = InternalTexture.DATASOURCE_UNKNOWN;
  151. /** @hidden */
  152. public _buffer: Nullable<string | ArrayBuffer | HTMLImageElement | Blob> = null;
  153. /** @hidden */
  154. public _bufferView: Nullable<ArrayBufferView> = null;
  155. /** @hidden */
  156. public _bufferViewArray: Nullable<ArrayBufferView[]> = null;
  157. /** @hidden */
  158. public _bufferViewArrayArray: Nullable<ArrayBufferView[][]> = null;
  159. /** @hidden */
  160. public _size: number = 0;
  161. /** @hidden */
  162. public _extension: string = "";
  163. /** @hidden */
  164. public _files: Nullable<string[]> = null;
  165. /** @hidden */
  166. public _workingCanvas: Nullable<HTMLCanvasElement> = null;
  167. /** @hidden */
  168. public _workingContext: Nullable<CanvasRenderingContext2D> = null;
  169. /** @hidden */
  170. public _framebuffer: Nullable<WebGLFramebuffer> = null;
  171. /** @hidden */
  172. public _depthStencilBuffer: Nullable<WebGLRenderbuffer> = null;
  173. /** @hidden */
  174. public _MSAAFramebuffer: Nullable<WebGLFramebuffer> = null;
  175. /** @hidden */
  176. public _MSAARenderBuffer: Nullable<WebGLRenderbuffer> = null;
  177. /** @hidden */
  178. public _attachments: Nullable<number[]> = null;
  179. /** @hidden */
  180. public _cachedCoordinatesMode: Nullable<number> = null;
  181. /** @hidden */
  182. public _cachedWrapU: Nullable<number> = null;
  183. /** @hidden */
  184. public _cachedWrapV: Nullable<number> = null;
  185. /** @hidden */
  186. public _cachedWrapR: Nullable<number> = null;
  187. /** @hidden */
  188. public _cachedAnisotropicFilteringLevel: Nullable<number> = null;
  189. /** @hidden */
  190. public _isDisabled: boolean = false;
  191. /** @hidden */
  192. public _compression: Nullable<string> = null;
  193. /** @hidden */
  194. public _generateStencilBuffer: boolean = false;
  195. /** @hidden */
  196. public _generateDepthBuffer: boolean = false;
  197. /** @hidden */
  198. public _comparisonFunction: number = 0;
  199. /** @hidden */
  200. public _sphericalPolynomial: Nullable<SphericalPolynomial> = null;
  201. /** @hidden */
  202. public _lodGenerationScale: number = 0;
  203. /** @hidden */
  204. public _lodGenerationOffset: number = 0;
  205. // Multiview
  206. /** @hidden */
  207. public _colorTextureArray: Nullable<WebGLTexture> = null;
  208. /** @hidden */
  209. public _depthStencilTextureArray: Nullable<WebGLTexture> = null;
  210. // The following three fields helps sharing generated fixed LODs for texture filtering
  211. // In environment not supporting the textureLOD extension like EDGE. They are for internal use only.
  212. // They are at the level of the gl texture to benefit from the cache.
  213. /** @hidden */
  214. public _lodTextureHigh: Nullable<BaseTexture> = null;
  215. /** @hidden */
  216. public _lodTextureMid: Nullable<BaseTexture> = null;
  217. /** @hidden */
  218. public _lodTextureLow: Nullable<BaseTexture> = null;
  219. /** @hidden */
  220. public _isRGBD: boolean = false;
  221. /** @hidden */
  222. public _webGLTexture: Nullable<WebGLTexture> = null;
  223. /** @hidden */
  224. public _references: number = 1;
  225. private _engine: Engine;
  226. /**
  227. * Gets the Engine the texture belongs to.
  228. * @returns The babylon engine
  229. */
  230. public getEngine(): Engine {
  231. return this._engine;
  232. }
  233. /**
  234. * Gets the data source type of the texture (can be one of the InternalTexture.DATASOURCE_XXXX)
  235. */
  236. public get dataSource(): number {
  237. return this._dataSource;
  238. }
  239. /**
  240. * Creates a new InternalTexture
  241. * @param engine defines the engine to use
  242. * @param dataSource defines the type of data that will be used
  243. * @param delayAllocation if the texture allocation should be delayed (default: false)
  244. */
  245. constructor(engine: Engine, dataSource: number, delayAllocation = false) {
  246. this._engine = engine;
  247. this._dataSource = dataSource;
  248. if (!delayAllocation) {
  249. this._webGLTexture = engine._createTexture();
  250. }
  251. }
  252. /**
  253. * Increments the number of references (ie. the number of Texture that point to it)
  254. */
  255. public incrementReferences(): void {
  256. this._references++;
  257. }
  258. /**
  259. * Change the size of the texture (not the size of the content)
  260. * @param width defines the new width
  261. * @param height defines the new height
  262. * @param depth defines the new depth (1 by default)
  263. */
  264. public updateSize(width: int, height: int, depth: int = 1): void {
  265. this.width = width;
  266. this.height = height;
  267. this.depth = depth;
  268. this.baseWidth = width;
  269. this.baseHeight = height;
  270. this.baseDepth = depth;
  271. this._size = width * height * depth;
  272. }
  273. /** @hidden */
  274. public _rebuild(): void {
  275. var proxy: InternalTexture;
  276. this.isReady = false;
  277. this._cachedCoordinatesMode = null;
  278. this._cachedWrapU = null;
  279. this._cachedWrapV = null;
  280. this._cachedAnisotropicFilteringLevel = null;
  281. switch (this._dataSource) {
  282. case InternalTexture.DATASOURCE_TEMP:
  283. return;
  284. case InternalTexture.DATASOURCE_URL:
  285. proxy = this._engine.createTexture(this.url, !this.generateMipMaps, this.invertY, null, this.samplingMode, () => {
  286. proxy._swapAndDie(this);
  287. this.isReady = true;
  288. }, null, this._buffer, undefined, this.format);
  289. return;
  290. case InternalTexture.DATASOURCE_RAW:
  291. proxy = this._engine.createRawTexture(this._bufferView, this.baseWidth, this.baseHeight, this.format, this.generateMipMaps,
  292. this.invertY, this.samplingMode, this._compression);
  293. proxy._swapAndDie(this);
  294. this.isReady = true;
  295. return;
  296. case InternalTexture.DATASOURCE_RAW3D:
  297. proxy = this._engine.createRawTexture3D(this._bufferView, this.baseWidth, this.baseHeight, this.baseDepth, this.format, this.generateMipMaps,
  298. this.invertY, this.samplingMode, this._compression);
  299. proxy._swapAndDie(this);
  300. this.isReady = true;
  301. return;
  302. case InternalTexture.DATASOURCE_DYNAMIC:
  303. proxy = this._engine.createDynamicTexture(this.baseWidth, this.baseHeight, this.generateMipMaps, this.samplingMode);
  304. proxy._swapAndDie(this);
  305. this._engine.updateDynamicTexture(this, this._engine.getRenderingCanvas()!, this.invertY, undefined, undefined, true);
  306. // The engine will make sure to update content so no need to flag it as isReady = true
  307. return;
  308. case InternalTexture.DATASOURCE_RENDERTARGET:
  309. let options = new RenderTargetCreationOptions();
  310. options.generateDepthBuffer = this._generateDepthBuffer;
  311. options.generateMipMaps = this.generateMipMaps;
  312. options.generateStencilBuffer = this._generateStencilBuffer;
  313. options.samplingMode = this.samplingMode;
  314. options.type = this.type;
  315. if (this.isCube) {
  316. proxy = this._engine.createRenderTargetCubeTexture(this.width, options);
  317. } else {
  318. let size = {
  319. width: this.width,
  320. height: this.height
  321. };
  322. proxy = this._engine.createRenderTargetTexture(size, options);
  323. }
  324. proxy._swapAndDie(this);
  325. this.isReady = true;
  326. return;
  327. case InternalTexture.DATASOURCE_DEPTHTEXTURE:
  328. let depthTextureOptions = {
  329. bilinearFiltering: this.samplingMode !== Constants.TEXTURE_BILINEAR_SAMPLINGMODE,
  330. comparisonFunction: this._comparisonFunction,
  331. generateStencil: this._generateStencilBuffer,
  332. isCube: this.isCube
  333. };
  334. proxy = this._engine.createDepthStencilTexture({ width: this.width, height: this.height }, depthTextureOptions);
  335. proxy._swapAndDie(this);
  336. this.isReady = true;
  337. return;
  338. case InternalTexture.DATASOURCE_CUBE:
  339. proxy = this._engine.createCubeTexture(this.url, null, this._files, !this.generateMipMaps, () => {
  340. proxy._swapAndDie(this);
  341. this.isReady = true;
  342. }, null, this.format, this._extension);
  343. return;
  344. case InternalTexture.DATASOURCE_CUBERAW:
  345. proxy = this._engine.createRawCubeTexture(this._bufferViewArray!, this.width, this.format, this.type, this.generateMipMaps, this.invertY, this.samplingMode, this._compression);
  346. proxy._swapAndDie(this);
  347. this.isReady = true;
  348. return;
  349. case InternalTexture.DATASOURCE_CUBERAW_RGBD:
  350. proxy = this._engine.createRawCubeTexture(null, this.width, this.format, this.type, this.generateMipMaps, this.invertY, this.samplingMode, this._compression);
  351. InternalTexture._UpdateRGBDAsync(proxy, this._bufferViewArrayArray!, this._sphericalPolynomial, this._lodGenerationScale, this._lodGenerationOffset).then(() => {
  352. proxy._swapAndDie(this);
  353. this.isReady = true;
  354. });
  355. return;
  356. case InternalTexture.DATASOURCE_CUBEPREFILTERED:
  357. proxy = this._engine.createPrefilteredCubeTexture(this.url, null, this._lodGenerationScale, this._lodGenerationOffset, (proxy) => {
  358. if (proxy) {
  359. proxy._swapAndDie(this);
  360. }
  361. this.isReady = true;
  362. }, null, this.format, this._extension);
  363. proxy._sphericalPolynomial = this._sphericalPolynomial;
  364. return;
  365. }
  366. }
  367. /** @hidden */
  368. public _swapAndDie(target: InternalTexture): void {
  369. target._webGLTexture = this._webGLTexture;
  370. target._isRGBD = this._isRGBD;
  371. if (this._framebuffer) {
  372. target._framebuffer = this._framebuffer;
  373. }
  374. if (this._depthStencilBuffer) {
  375. target._depthStencilBuffer = this._depthStencilBuffer;
  376. }
  377. if (this._lodTextureHigh) {
  378. if (target._lodTextureHigh) {
  379. target._lodTextureHigh.dispose();
  380. }
  381. target._lodTextureHigh = this._lodTextureHigh;
  382. }
  383. if (this._lodTextureMid) {
  384. if (target._lodTextureMid) {
  385. target._lodTextureMid.dispose();
  386. }
  387. target._lodTextureMid = this._lodTextureMid;
  388. }
  389. if (this._lodTextureLow) {
  390. if (target._lodTextureLow) {
  391. target._lodTextureLow.dispose();
  392. }
  393. target._lodTextureLow = this._lodTextureLow;
  394. }
  395. let cache = this._engine.getLoadedTexturesCache();
  396. var index = cache.indexOf(this);
  397. if (index !== -1) {
  398. cache.splice(index, 1);
  399. }
  400. }
  401. /**
  402. * Dispose the current allocated resources
  403. */
  404. public dispose(): void {
  405. if (!this._webGLTexture) {
  406. return;
  407. }
  408. this._references--;
  409. if (this._references === 0) {
  410. this._engine._releaseTexture(this);
  411. this._webGLTexture = null;
  412. }
  413. }
  414. }