basisTextureLoader.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { Nullable } from "../../../types";
  2. import { Engine } from "../../../Engines/engine";
  3. import { InternalTexture } from "../../../Materials/Textures/internalTexture";
  4. import { IInternalTextureLoader } from "../../../Materials/Textures/internalTextureLoader";
  5. import { _TimeToken } from "../../../Instrumentation/timeToken";
  6. import { _DepthCullingState, _StencilState, _AlphaState } from "../../../States/index";
  7. import { BasisTools } from "../../../Misc/basis";
  8. import { Texture } from '../texture';
  9. import { Tools } from '../../../Misc/tools';
  10. import { Scalar } from '../../../Maths/math.scalar';
  11. /**
  12. * Loader for .basis file format
  13. */
  14. export class _BasisTextureLoader implements IInternalTextureLoader {
  15. /**
  16. * Defines whether the loader supports cascade loading the different faces.
  17. */
  18. public readonly supportCascades = false;
  19. /**
  20. * This returns if the loader support the current file information.
  21. * @param extension defines the file extension of the file being loaded
  22. * @param textureFormatInUse defines the current compressed format in use iun the engine
  23. * @param fallback defines the fallback internal texture if any
  24. * @param isBase64 defines whether the texture is encoded as a base64
  25. * @param isBuffer defines whether the texture data are stored as a buffer
  26. * @returns true if the loader can load the specified file
  27. */
  28. public canLoad(extension: string, textureFormatInUse: Nullable<string>, fallback: Nullable<InternalTexture>, isBase64: boolean, isBuffer: boolean): boolean {
  29. return extension.indexOf(".basis") === 0;
  30. }
  31. /**
  32. * Transform the url before loading if required.
  33. * @param rootUrl the url of the texture
  34. * @param textureFormatInUse defines the current compressed format in use iun the engine
  35. * @returns the transformed texture
  36. */
  37. public transformUrl(rootUrl: string, textureFormatInUse: Nullable<string>): string {
  38. return rootUrl;
  39. }
  40. /**
  41. * Gets the fallback url in case the load fail. This can return null to allow the default fallback mecanism to work
  42. * @param rootUrl the url of the texture
  43. * @param textureFormatInUse defines the current compressed format in use iun the engine
  44. * @returns the fallback texture
  45. */
  46. public getFallbackTextureUrl(rootUrl: string, textureFormatInUse: Nullable<string>): Nullable<string> {
  47. return null;
  48. }
  49. /**
  50. * Uploads the cube texture data to the WebGl Texture. It has already been bound.
  51. * @param data contains the texture data
  52. * @param texture defines the BabylonJS internal texture
  53. * @param createPolynomials will be true if polynomials have been requested
  54. * @param onLoad defines the callback to trigger once the texture is ready
  55. * @param onError defines the callback to trigger in case of error
  56. */
  57. public loadCubeData(data: string | ArrayBuffer | (string | ArrayBuffer)[], texture: InternalTexture, createPolynomials: boolean, onLoad: Nullable<(data?: any) => void>, onError: Nullable<(message?: string, exception?: any) => void>): void {
  58. throw ".basis not supported in Cube.";
  59. }
  60. /**
  61. * Uploads the 2D texture data to the WebGl Texture. It has alreday been bound once in the callback.
  62. * @param data contains the texture data
  63. * @param texture defines the BabylonJS internal texture
  64. * @param callback defines the method to call once ready to upload
  65. */
  66. public loadData(data: ArrayBuffer, texture: InternalTexture,
  67. callback: (width: number, height: number, loadMipmap: boolean, isCompressed: boolean, done: () => void) => void): void {
  68. var caps = texture.getEngine().getCaps();
  69. var transcodeConfig = {
  70. supportedCompressionFormats: {
  71. etc1: caps.etc1 ? true : false,
  72. s3tc: caps.s3tc ? true : false,
  73. pvrtc: caps.pvrtc ? true : false,
  74. etc2: caps.etc2 ? true : false
  75. }
  76. };
  77. BasisTools.TranscodeAsync(data, transcodeConfig).then((result) => {
  78. var rootImage = result.fileInfo.images[0].levels[0];
  79. callback(rootImage.width, rootImage.height, false, true, () => {
  80. texture._invertVScale = texture.invertY;
  81. if (result.format === -1) {
  82. // No compatable compressed format found, fallback to RGB
  83. texture.type = Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5;
  84. texture.format = Engine.TEXTUREFORMAT_RGB;
  85. // Create non power of two texture
  86. let source = new InternalTexture(texture.getEngine(), InternalTexture.DATASOURCE_TEMP);
  87. source.type = Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5;
  88. source.format = Engine.TEXTUREFORMAT_RGB;
  89. // Fallback requires aligned width/height
  90. source.width = (rootImage.width + 3) & ~3;
  91. source.height = (rootImage.height + 3) & ~3;
  92. texture.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, source, true);
  93. texture.getEngine()._uploadDataToTextureDirectly(source, rootImage.transcodedPixels, 0, 0, Engine.TEXTUREFORMAT_RGB, true);
  94. // Resize to power of two
  95. source.getEngine()._rescaleTexture(source, texture, texture.getEngine().scenes[0], source.getEngine()._getInternalFormat(Engine.TEXTUREFORMAT_RGB), () => {
  96. source.getEngine()._releaseTexture(source);
  97. source.getEngine()._bindTextureDirectly(source.getEngine()._gl.TEXTURE_2D, texture, true);
  98. });
  99. }else {
  100. texture.width = rootImage.width;
  101. texture.height = rootImage.height;
  102. // Upload all mip levels in the file
  103. result.fileInfo.images[0].levels.forEach((level, index) => {
  104. texture.getEngine()._uploadCompressedDataToTextureDirectly(texture, BasisTools.GetInternalFormatFromBasisFormat(result.format!), level.width, level.height, level.transcodedPixels, 0, index);
  105. });
  106. if (texture.getEngine().webGLVersion < 2 && (Scalar.Log2(texture.width) % 1 !== 0 || Scalar.Log2(texture.height) % 1 !== 0)) {
  107. Tools.Warn("Loaded .basis texture width and height are not a power of two. Texture wrapping will be set to Texture.CLAMP_ADDRESSMODE as other modes are not supported with non power of two dimensions in webGL 1.");
  108. texture._cachedWrapU = Texture.CLAMP_ADDRESSMODE;
  109. texture._cachedWrapV = Texture.CLAMP_ADDRESSMODE;
  110. }
  111. }
  112. });
  113. });
  114. }
  115. }
  116. // Register the loader.
  117. Engine._TextureLoaders.push(new _BasisTextureLoader());