engine.rawTexture.ts 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. import { Nullable } from "../../types";
  2. import { Engine } from "../../Engines/engine";
  3. import { _TimeToken } from "../../Instrumentation/timeToken";
  4. import { InternalTexture } from '../../Materials/Textures/internalTexture';
  5. import { Logger } from '../../Misc/logger';
  6. import { Tools } from '../../Misc/tools';
  7. import { Scene } from '../../scene';
  8. import { WebRequest } from '../../Misc/webRequest';
  9. import { Constants } from '../constants';
  10. declare module "../../Engines/engine" {
  11. export interface Engine {
  12. /**
  13. * Creates a raw texture
  14. * @param data defines the data to store in the texture
  15. * @param width defines the width of the texture
  16. * @param height defines the height of the texture
  17. * @param format defines the format of the data
  18. * @param generateMipMaps defines if the engine should generate the mip levels
  19. * @param invertY defines if data must be stored with Y axis inverted
  20. * @param samplingMode defines the required sampling mode (Texture.NEAREST_SAMPLINGMODE by default)
  21. * @param compression defines the compression used (null by default)
  22. * @param type defines the type fo the data (Engine.TEXTURETYPE_UNSIGNED_INT by default)
  23. * @returns the raw texture inside an InternalTexture
  24. */
  25. createRawTexture(data: Nullable<ArrayBufferView>, width: number, height: number, format: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: Nullable<string>, type: number): InternalTexture;
  26. /**
  27. * Update a raw texture
  28. * @param texture defines the texture to update
  29. * @param data defines the data to store in the texture
  30. * @param format defines the format of the data
  31. * @param invertY defines if data must be stored with Y axis inverted
  32. */
  33. updateRawTexture(texture: Nullable<InternalTexture>, data: Nullable<ArrayBufferView>, format: number, invertY: boolean): void;
  34. /**
  35. * Update a raw texture
  36. * @param texture defines the texture to update
  37. * @param data defines the data to store in the texture
  38. * @param format defines the format of the data
  39. * @param invertY defines if data must be stored with Y axis inverted
  40. * @param compression defines the compression used (null by default)
  41. * @param type defines the type fo the data (Engine.TEXTURETYPE_UNSIGNED_INT by default)
  42. */
  43. updateRawTexture(texture: Nullable<InternalTexture>, data: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string>, type: number): void;
  44. /**
  45. * Creates a new raw cube texture
  46. * @param data defines the array of data to use to create each face
  47. * @param size defines the size of the textures
  48. * @param format defines the format of the data
  49. * @param type defines the type of the data (like Engine.TEXTURETYPE_UNSIGNED_INT)
  50. * @param generateMipMaps defines if the engine should generate the mip levels
  51. * @param invertY defines if data must be stored with Y axis inverted
  52. * @param samplingMode defines the required sampling mode (like Texture.NEAREST_SAMPLINGMODE)
  53. * @param compression defines the compression used (null by default)
  54. * @returns the cube texture as an InternalTexture
  55. */
  56. createRawCubeTexture(data: Nullable<ArrayBufferView[]>, size: number, format: number, type: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: Nullable<string>): InternalTexture;
  57. /**
  58. * Update a raw cube texture
  59. * @param texture defines the texture to udpdate
  60. * @param data defines the data to store
  61. * @param format defines the data format
  62. * @param type defines the type fo the data (Engine.TEXTURETYPE_UNSIGNED_INT by default)
  63. * @param invertY defines if data must be stored with Y axis inverted
  64. */
  65. updateRawCubeTexture(texture: InternalTexture, data: ArrayBufferView[], format: number, type: number, invertY: boolean): void;
  66. /**
  67. * Update a raw cube texture
  68. * @param texture defines the texture to udpdate
  69. * @param data defines the data to store
  70. * @param format defines the data format
  71. * @param type defines the type fo the data (Engine.TEXTURETYPE_UNSIGNED_INT by default)
  72. * @param invertY defines if data must be stored with Y axis inverted
  73. * @param compression defines the compression used (null by default)
  74. */
  75. updateRawCubeTexture(texture: InternalTexture, data: ArrayBufferView[], format: number, type: number, invertY: boolean, compression: Nullable<string>): void;
  76. /**
  77. * Update a raw cube texture
  78. * @param texture defines the texture to udpdate
  79. * @param data defines the data to store
  80. * @param format defines the data format
  81. * @param type defines the type fo the data (Engine.TEXTURETYPE_UNSIGNED_INT by default)
  82. * @param invertY defines if data must be stored with Y axis inverted
  83. * @param compression defines the compression used (null by default)
  84. * @param level defines which level of the texture to update
  85. */
  86. updateRawCubeTexture(texture: InternalTexture, data: ArrayBufferView[], format: number, type: number, invertY: boolean, compression: Nullable<string>, level: number): void;
  87. /**
  88. * Creates a new raw cube texture from a specified url
  89. * @param url defines the url where the data is located
  90. * @param scene defines the current scene
  91. * @param size defines the size of the textures
  92. * @param format defines the format of the data
  93. * @param type defines the type fo the data (like Engine.TEXTURETYPE_UNSIGNED_INT)
  94. * @param noMipmap defines if the engine should avoid generating the mip levels
  95. * @param callback defines a callback used to extract texture data from loaded data
  96. * @param mipmapGenerator defines to provide an optional tool to generate mip levels
  97. * @param onLoad defines a callback called when texture is loaded
  98. * @param onError defines a callback called if there is an error
  99. * @returns the cube texture as an InternalTexture
  100. */
  101. createRawCubeTextureFromUrl(url: string, scene: Scene, size: number, format: number, type: number, noMipmap: boolean,
  102. callback: (ArrayBuffer: ArrayBuffer) => Nullable<ArrayBufferView[]>,
  103. mipmapGenerator: Nullable<((faces: ArrayBufferView[]) => ArrayBufferView[][])>,
  104. onLoad: Nullable<() => void>,
  105. onError: Nullable<(message?: string, exception?: any) => void>): InternalTexture;
  106. /**
  107. * Creates a new raw cube texture from a specified url
  108. * @param url defines the url where the data is located
  109. * @param scene defines the current scene
  110. * @param size defines the size of the textures
  111. * @param format defines the format of the data
  112. * @param type defines the type fo the data (like Engine.TEXTURETYPE_UNSIGNED_INT)
  113. * @param noMipmap defines if the engine should avoid generating the mip levels
  114. * @param callback defines a callback used to extract texture data from loaded data
  115. * @param mipmapGenerator defines to provide an optional tool to generate mip levels
  116. * @param onLoad defines a callback called when texture is loaded
  117. * @param onError defines a callback called if there is an error
  118. * @param samplingMode defines the required sampling mode (like Texture.NEAREST_SAMPLINGMODE)
  119. * @param invertY defines if data must be stored with Y axis inverted
  120. * @returns the cube texture as an InternalTexture
  121. */
  122. createRawCubeTextureFromUrl(url: string, scene: Scene, size: number, format: number, type: number, noMipmap: boolean,
  123. callback: (ArrayBuffer: ArrayBuffer) => Nullable<ArrayBufferView[]>,
  124. mipmapGenerator: Nullable<((faces: ArrayBufferView[]) => ArrayBufferView[][])>,
  125. onLoad: Nullable<() => void>,
  126. onError: Nullable<(message?: string, exception?: any) => void>,
  127. samplingMode: number,
  128. invertY: boolean): InternalTexture;
  129. /**
  130. * Creates a new raw 3D texture
  131. * @param data defines the data used to create the texture
  132. * @param width defines the width of the texture
  133. * @param height defines the height of the texture
  134. * @param depth defines the depth of the texture
  135. * @param format defines the format of the texture
  136. * @param generateMipMaps defines if the engine must generate mip levels
  137. * @param invertY defines if data must be stored with Y axis inverted
  138. * @param samplingMode defines the required sampling mode (like Texture.NEAREST_SAMPLINGMODE)
  139. * @param compression defines the compressed used (can be null)
  140. * @param textureType defines the compressed used (can be null)
  141. * @returns a new raw 3D texture (stored in an InternalTexture)
  142. */
  143. createRawTexture3D(data: Nullable<ArrayBufferView>, width: number, height: number, depth: number, format: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: Nullable<string>, textureType: number): InternalTexture;
  144. /**
  145. * Update a raw 3D texture
  146. * @param texture defines the texture to update
  147. * @param data defines the data to store
  148. * @param format defines the data format
  149. * @param invertY defines if data must be stored with Y axis inverted
  150. */
  151. updateRawTexture3D(texture: InternalTexture, data: Nullable<ArrayBufferView>, format: number, invertY: boolean): void;
  152. /**
  153. * Update a raw 3D texture
  154. * @param texture defines the texture to update
  155. * @param data defines the data to store
  156. * @param format defines the data format
  157. * @param invertY defines if data must be stored with Y axis inverted
  158. * @param compression defines the used compression (can be null)
  159. * @param textureType defines the texture Type (Engine.TEXTURETYPE_UNSIGNED_INT, Engine.TEXTURETYPE_FLOAT...)
  160. */
  161. updateRawTexture3D(texture: InternalTexture, data: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string>, textureType: number): void;
  162. }
  163. }
  164. Engine.prototype.updateRawTexture = function(texture: Nullable<InternalTexture>, data: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string> = null, type: number = Constants.TEXTURETYPE_UNSIGNED_INT): void {
  165. if (!texture) {
  166. return;
  167. }
  168. // Babylon's internalSizedFomat but gl's texImage2D internalFormat
  169. var internalSizedFomat = this._getRGBABufferInternalSizedFormat(type, format);
  170. // Babylon's internalFormat but gl's texImage2D format
  171. var internalFormat = this._getInternalFormat(format);
  172. var textureType = this._getWebGLTextureType(type);
  173. this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
  174. this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
  175. if (!this._doNotHandleContextLost) {
  176. texture._bufferView = data;
  177. texture.format = format;
  178. texture.type = type;
  179. texture.invertY = invertY;
  180. texture._compression = compression;
  181. }
  182. if (texture.width % 4 !== 0) {
  183. this._gl.pixelStorei(this._gl.UNPACK_ALIGNMENT, 1);
  184. }
  185. if (compression && data) {
  186. this._gl.compressedTexImage2D(this._gl.TEXTURE_2D, 0, (<any>this.getCaps().s3tc)[compression], texture.width, texture.height, 0, <DataView>data);
  187. } else {
  188. this._gl.texImage2D(this._gl.TEXTURE_2D, 0, internalSizedFomat, texture.width, texture.height, 0, internalFormat, textureType, data);
  189. }
  190. if (texture.generateMipMaps) {
  191. this._gl.generateMipmap(this._gl.TEXTURE_2D);
  192. }
  193. this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
  194. // this.resetTextureCache();
  195. texture.isReady = true;
  196. };
  197. Engine.prototype.createRawTexture = function(data: Nullable<ArrayBufferView>, width: number, height: number, format: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: Nullable<string> = null, type: number = Constants.TEXTURETYPE_UNSIGNED_INT): InternalTexture {
  198. var texture = new InternalTexture(this, InternalTexture.DATASOURCE_RAW);
  199. texture.baseWidth = width;
  200. texture.baseHeight = height;
  201. texture.width = width;
  202. texture.height = height;
  203. texture.format = format;
  204. texture.generateMipMaps = generateMipMaps;
  205. texture.samplingMode = samplingMode;
  206. texture.invertY = invertY;
  207. texture._compression = compression;
  208. texture.type = type;
  209. if (!this._doNotHandleContextLost) {
  210. texture._bufferView = data;
  211. }
  212. this.updateRawTexture(texture, data, format, invertY, compression, type);
  213. this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
  214. // Filters
  215. var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
  216. this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
  217. this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
  218. if (generateMipMaps) {
  219. this._gl.generateMipmap(this._gl.TEXTURE_2D);
  220. }
  221. this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
  222. this._internalTexturesCache.push(texture);
  223. return texture;
  224. };
  225. Engine.prototype.createRawCubeTexture = function(data: Nullable<ArrayBufferView[]>, size: number, format: number, type: number,
  226. generateMipMaps: boolean, invertY: boolean, samplingMode: number,
  227. compression: Nullable<string> = null): InternalTexture {
  228. var gl = this._gl;
  229. var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBERAW);
  230. texture.isCube = true;
  231. texture.format = format;
  232. texture.type = type;
  233. if (!this._doNotHandleContextLost) {
  234. texture._bufferViewArray = data;
  235. }
  236. var textureType = this._getWebGLTextureType(type);
  237. var internalFormat = this._getInternalFormat(format);
  238. if (internalFormat === gl.RGB) {
  239. internalFormat = gl.RGBA;
  240. }
  241. // Mipmap generation needs a sized internal format that is both color-renderable and texture-filterable
  242. if (textureType === gl.FLOAT && !this._caps.textureFloatLinearFiltering) {
  243. generateMipMaps = false;
  244. samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
  245. Logger.Warn("Float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
  246. }
  247. else if (textureType === this._gl.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
  248. generateMipMaps = false;
  249. samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
  250. Logger.Warn("Half float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
  251. }
  252. else if (textureType === gl.FLOAT && !this._caps.textureFloatRender) {
  253. generateMipMaps = false;
  254. Logger.Warn("Render to float textures is not supported. Mipmap generation forced to false.");
  255. }
  256. else if (textureType === gl.HALF_FLOAT && !this._caps.colorBufferFloat) {
  257. generateMipMaps = false;
  258. Logger.Warn("Render to half float textures is not supported. Mipmap generation forced to false.");
  259. }
  260. var width = size;
  261. var height = width;
  262. texture.width = width;
  263. texture.height = height;
  264. // Double check on POT to generate Mips.
  265. var isPot = !this.needPOTTextures || (Tools.IsExponentOfTwo(texture.width) && Tools.IsExponentOfTwo(texture.height));
  266. if (!isPot) {
  267. generateMipMaps = false;
  268. }
  269. // Upload data if needed. The texture won't be ready until then.
  270. if (data) {
  271. this.updateRawCubeTexture(texture, data, format, type, invertY, compression);
  272. }
  273. this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture, true);
  274. // Filters
  275. if (data && generateMipMaps) {
  276. this._gl.generateMipmap(this._gl.TEXTURE_CUBE_MAP);
  277. }
  278. var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
  279. gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
  280. gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
  281. gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  282. gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  283. this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
  284. texture.generateMipMaps = generateMipMaps;
  285. return texture;
  286. };
  287. Engine.prototype.updateRawCubeTexture = function(texture: InternalTexture, data: ArrayBufferView[], format: number, type: number, invertY: boolean, compression: Nullable<string> = null, level: number = 0): void {
  288. texture._bufferViewArray = data;
  289. texture.format = format;
  290. texture.type = type;
  291. texture.invertY = invertY;
  292. texture._compression = compression;
  293. var gl = this._gl;
  294. var textureType = this._getWebGLTextureType(type);
  295. var internalFormat = this._getInternalFormat(format);
  296. var internalSizedFomat = this._getRGBABufferInternalSizedFormat(type);
  297. var needConversion = false;
  298. if (internalFormat === gl.RGB) {
  299. internalFormat = gl.RGBA;
  300. needConversion = true;
  301. }
  302. this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
  303. this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
  304. if (texture.width % 4 !== 0) {
  305. gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
  306. }
  307. // Data are known to be in +X +Y +Z -X -Y -Z
  308. for (let faceIndex = 0; faceIndex < 6; faceIndex++) {
  309. let faceData = data[faceIndex];
  310. if (compression) {
  311. gl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, (<any>(this.getCaps().s3tc))[compression], texture.width, texture.height, 0, <DataView>faceData);
  312. } else {
  313. if (needConversion) {
  314. faceData = this._convertRGBtoRGBATextureData(faceData, texture.width, texture.height, type);
  315. }
  316. gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, internalSizedFomat, texture.width, texture.height, 0, internalFormat, textureType, faceData);
  317. }
  318. }
  319. var isPot = !this.needPOTTextures || (Tools.IsExponentOfTwo(texture.width) && Tools.IsExponentOfTwo(texture.height));
  320. if (isPot && texture.generateMipMaps && level === 0) {
  321. this._gl.generateMipmap(this._gl.TEXTURE_CUBE_MAP);
  322. }
  323. this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
  324. // this.resetTextureCache();
  325. texture.isReady = true;
  326. };
  327. Engine.prototype.createRawCubeTextureFromUrl = function(url: string, scene: Scene, size: number, format: number, type: number, noMipmap: boolean,
  328. callback: (ArrayBuffer: ArrayBuffer) => Nullable<ArrayBufferView[]>,
  329. mipmapGenerator: Nullable<((faces: ArrayBufferView[]) => ArrayBufferView[][])>,
  330. onLoad: Nullable<() => void> = null,
  331. onError: Nullable<(message?: string, exception?: any) => void> = null,
  332. samplingMode: number = Constants.TEXTURE_TRILINEAR_SAMPLINGMODE,
  333. invertY: boolean = false): InternalTexture {
  334. var gl = this._gl;
  335. var texture = this.createRawCubeTexture(null, size, format, type, !noMipmap, invertY, samplingMode);
  336. scene._addPendingData(texture);
  337. texture.url = url;
  338. this._internalTexturesCache.push(texture);
  339. var onerror = (request?: WebRequest, exception?: any) => {
  340. scene._removePendingData(texture);
  341. if (onError && request) {
  342. onError(request.status + " " + request.statusText, exception);
  343. }
  344. };
  345. var internalCallback = (data: any) => {
  346. var width = texture.width;
  347. var faceDataArrays = callback(data);
  348. if (!faceDataArrays) {
  349. return;
  350. }
  351. if (mipmapGenerator) {
  352. var textureType = this._getWebGLTextureType(type);
  353. var internalFormat = this._getInternalFormat(format);
  354. var internalSizedFomat = this._getRGBABufferInternalSizedFormat(type);
  355. var needConversion = false;
  356. if (internalFormat === gl.RGB) {
  357. internalFormat = gl.RGBA;
  358. needConversion = true;
  359. }
  360. this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
  361. this._unpackFlipY(false);
  362. var mipData = mipmapGenerator(faceDataArrays);
  363. for (var level = 0; level < mipData.length; level++) {
  364. var mipSize = width >> level;
  365. for (var faceIndex = 0; faceIndex < 6; faceIndex++) {
  366. let mipFaceData = mipData[level][faceIndex];
  367. if (needConversion) {
  368. mipFaceData = this._convertRGBtoRGBATextureData(mipFaceData, mipSize, mipSize, type);
  369. }
  370. gl.texImage2D(faceIndex, level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipFaceData);
  371. }
  372. }
  373. this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
  374. }
  375. else {
  376. this.updateRawCubeTexture(texture, faceDataArrays, format, type, invertY);
  377. }
  378. texture.isReady = true;
  379. // this.resetTextureCache();
  380. scene._removePendingData(texture);
  381. if (onLoad) {
  382. onLoad();
  383. }
  384. };
  385. this._loadFile(url, (data) => {
  386. internalCallback(data);
  387. }, undefined, scene.offlineProvider, true, onerror);
  388. return texture;
  389. };
  390. Engine.prototype.createRawTexture3D = function(data: Nullable<ArrayBufferView>, width: number, height: number, depth: number, format: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: Nullable<string> = null, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT): InternalTexture {
  391. var texture = new InternalTexture(this, InternalTexture.DATASOURCE_RAW3D);
  392. texture.baseWidth = width;
  393. texture.baseHeight = height;
  394. texture.baseDepth = depth;
  395. texture.width = width;
  396. texture.height = height;
  397. texture.depth = depth;
  398. texture.format = format;
  399. texture.type = textureType;
  400. texture.generateMipMaps = generateMipMaps;
  401. texture.samplingMode = samplingMode;
  402. texture.is3D = true;
  403. if (!this._doNotHandleContextLost) {
  404. texture._bufferView = data;
  405. }
  406. this.updateRawTexture3D(texture, data, format, invertY, compression, textureType);
  407. this._bindTextureDirectly(this._gl.TEXTURE_3D, texture, true);
  408. // Filters
  409. var filters = this._getSamplingParameters(samplingMode, generateMipMaps);
  410. this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
  411. this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MIN_FILTER, filters.min);
  412. if (generateMipMaps) {
  413. this._gl.generateMipmap(this._gl.TEXTURE_3D);
  414. }
  415. this._bindTextureDirectly(this._gl.TEXTURE_3D, null);
  416. this._internalTexturesCache.push(texture);
  417. return texture;
  418. };
  419. Engine.prototype.updateRawTexture3D = function(texture: InternalTexture, data: Nullable<ArrayBufferView>, format: number, invertY: boolean, compression: Nullable<string> = null, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT): void {
  420. var internalType = this._getWebGLTextureType(textureType);
  421. var internalFormat = this._getInternalFormat(format);
  422. var internalSizedFomat = this._getRGBABufferInternalSizedFormat(textureType, format);
  423. this._bindTextureDirectly(this._gl.TEXTURE_3D, texture, true);
  424. this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
  425. if (!this._doNotHandleContextLost) {
  426. texture._bufferView = data;
  427. texture.format = format;
  428. texture.invertY = invertY;
  429. texture._compression = compression;
  430. }
  431. if (texture.width % 4 !== 0) {
  432. this._gl.pixelStorei(this._gl.UNPACK_ALIGNMENT, 1);
  433. }
  434. if (compression && data) {
  435. this._gl.compressedTexImage3D(this._gl.TEXTURE_3D, 0, (<any>this.getCaps().s3tc)[compression], texture.width, texture.height, texture.depth, 0, data);
  436. } else {
  437. this._gl.texImage3D(this._gl.TEXTURE_3D, 0, internalSizedFomat, texture.width, texture.height, texture.depth, 0, internalFormat, internalType, data);
  438. }
  439. if (texture.generateMipMaps) {
  440. this._gl.generateMipmap(this._gl.TEXTURE_3D);
  441. }
  442. this._bindTextureDirectly(this._gl.TEXTURE_3D, null);
  443. // this.resetTextureCache();
  444. texture.isReady = true;
  445. };