Przeglądaj źródła

Transcoding UASTC to BC7 now works

Popov72 5 lat temu
rodzic
commit
2bd36d4781
1 zmienionych plików z 84 dodań i 66 usunięć
  1. 84 66
      src/Misc/khronosTextureContainer2.ts

+ 84 - 66
src/Misc/khronosTextureContainer2.ts

@@ -4,6 +4,14 @@ import { EngineCapabilities } from '../Engines/engineCapabilities';
 import { Tools } from './tools';
 import { DataReader } from './dataReader';
 import { Constants } from '../Engines/constants';
+import { Nullable } from '../types';
+
+declare var MSC_TRANSCODER: any;
+
+const RGB_S3TC_DXT1_Format = 33776;
+const RGBA_S3TC_DXT5_Format = 33779;
+
+const COMPRESSED_RGBA_BPTC_UNORM_EXT = 36492;
 
 const enum supercompressionScheme {
     BasisLZ = 1,
@@ -135,6 +143,8 @@ export class KhronosTextureContainer2 {
     private _dfdBlock: IKTX2_DFD;
     private _sgd: IKTX2_SupercompressionGlobalData;
 
+    private _mscBasisTranscoder: Promise<any>;
+
     public constructor(engine: ThinEngine) {
         this._engine = engine;
 
@@ -147,6 +157,23 @@ export class KhronosTextureContainer2 {
         }
     }
 
+    private _mscBasisModule: any;
+
+    private _getMSCBasisTranscoder() {
+        if (this._mscBasisTranscoder) {
+            return this._mscBasisTranscoder;
+        }
+
+        this._mscBasisTranscoder = new Promise((resolve) => {
+            MSC_TRANSCODER().then((basisModule: any) => {
+                basisModule.initTranscoders();
+                this._mscBasisModule = basisModule;
+                resolve();
+            });
+        });
+
+        return this._mscBasisTranscoder;
+    }
     /**
      * Based on https://github.com/mrdoob/three.js/blob/dfb5c23ce126ec845e4aa240599915fef5375797/examples/jsm/loaders/KTX2Loader.js
      */
@@ -321,7 +348,7 @@ export class KhronosTextureContainer2 {
             sgd.extendedData = new Uint8Array(this._data.buffer, extendedByteOffset, sgd.extendedByteLength);
         }
 
-        console.log(sgd);
+        console.log("sgd", sgd);
 
     }
 
@@ -344,11 +371,15 @@ export class KhronosTextureContainer2 {
 
     private async _initMipmaps(internalTexture: InternalTexture) {
 
-        /*await this.zstd.init();
+        await this._getMSCBasisTranscoder();
+
+        const basisModule = this._mscBasisModule;
+
+        const TranscodeTarget: any = basisModule.TranscodeTarget;
+        const TextureFormat: any = basisModule.TextureFormat;
+        const ImageInfo: any = basisModule.ImageInfo;
 
-        var TranscodeTarget = this.basisModule.TranscodeTarget;
-        var TextureFormat = this.basisModule.TextureFormat;
-        var ImageInfo = this.basisModule.ImageInfo;*/
+        /*await this.zstd.init();*/
 
         var mipmaps = [];
         var width = this._header.pixelWidth;
@@ -357,95 +388,82 @@ export class KhronosTextureContainer2 {
         var hasAlpha = this.hasAlpha;
         var isVideo = false;
 
-        /*var targetFormat;
-
-        if (config.astcSupported) {
-
-            targetFormat = TranscodeTarget.ASTC_4x4_RGBA;
-            this.transcodedFormat = RGBA_ASTC_4x4_Format;
-
-        } else if (config.bptcSupported && texFormat === TextureFormat.UASTC4x4) {
-
-            targetFormat = TranscodeTarget.BC7_M5_RGBA;
-            this.transcodedFormat = RGBA_BPTC_Format;
+        var BasisLzEtc1sImageTranscoder = basisModule.BasisLzEtc1sImageTranscoder;
+        var UastcImageTranscoder = basisModule.UastcImageTranscoder;
 
-        } else if (config.dxtSupported) {
+        var transcoder = texFormat === textureFormat.UASTC4x4 ? new UastcImageTranscoder() : new BasisLzEtc1sImageTranscoder();
 
-            targetFormat = hasAlpha ? TranscodeTarget.BC3_RGBA : TranscodeTarget.BC1_RGB;
-            this.transcodedFormat = hasAlpha ? RGBA_S3TC_DXT5_Format : RGB_S3TC_DXT1_Format;
+        let targetFormat = hasAlpha ? TranscodeTarget.BC7_RGBA : TranscodeTarget.BC1_RGB;
+        //let transcodedFormat = hasAlpha ? RGBA_S3TC_DXT5_Format : RGB_S3TC_DXT1_Format;
+        let transcodedFormat = COMPRESSED_RGBA_BPTC_UNORM_EXT;
 
-        } else if (config.pvrtcSupported && pvrtcTranscodable) {
+        const useMSCTranscoder = false;
 
-            targetFormat = hasAlpha ? TranscodeTarget.PVRTC1_4_RGBA : TranscodeTarget.PVRTC1_4_RGB;
-            this.transcodedFormat = hasAlpha ? RGBA_PVRTC_4BPPV1_Format : RGB_PVRTC_4BPPV1_Format;
-
-        } else if (config.etc2Supported) {
-
-            targetFormat = hasAlpha ? TranscodeTarget.ETC2_RGBA : TranscodeTarget.ETC1_RGB
-            this.transcodedFormat = hasAlpha ? RGBA_ETC2_EAC_Format : RGB_ETC2_Format;
-
-        } else if (config.etc1Supported) {
-
-            targetFormat = TranscodeTarget.ETC1_RGB;
-            this.transcodedFormat = RGB_ETC1_Format;
-
-        } else {
-
-            console.warn('THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.');
-
-            targetFormat = TranscodeTarget.RGBA32;
-            this.transcodedFormat = RGBAFormat;
-
-        }
-
-        if (! this.basisModule.isFormatSupported(targetFormat, texFormat)) {
-
-            throw new Error('THREE.KTX2Loader: Selected texture format not supported by current transcoder build.');
-
-        }
-*/
         for (var level = 0; level < this._header.levelCount; level ++) {
             var levelWidth = width / Math.pow(2, level);
             var levelHeight = height / Math.pow(2, level);
 
             var numImagesInLevel = 1; // TODO(donmccurdy): Support cubemaps, arrays and 3D.
             var imageOffsetInLevel = 0;
+            var imageInfo = new ImageInfo(texFormat, levelWidth, levelHeight, level);
             var levelByteLength = this._levels[level].byteLength;
+            var levelUncompressedByteLength = this._levels[level].uncompressedByteLength;
 
             for (var imageIndex = 0; imageIndex < numImagesInLevel; imageIndex ++) {
                 if (texFormat === textureFormat.UASTC4x4) {
                     // UASTC
-                    const nBlocks = ((levelWidth + 3) >> 2) * ((levelHeight + 3) >> 2);
+                    let textureData: Nullable<Uint8Array> = null;
+                    if (useMSCTranscoder) {
+                        imageInfo.flags = 0;
+                        imageInfo.rgbByteOffset = 0;
+                        imageInfo.rgbByteLength = levelUncompressedByteLength;
+                        imageInfo.alphaByteOffset = 0;
+                        imageInfo.alphaByteLength = 0;
+
+                        let encodedData = new Uint8Array(this._data.buffer, this._levels[level].byteOffset + imageOffsetInLevel, levelByteLength);
+
+                        if (this._header.supercompressionScheme === supercompressionScheme.ZStandard) {
+                            //encodedData = this.zstd.decode( encodedData, levelUncompressedByteLength );
+                        }
+
+                        const result: any = transcoder.transcodeImage(targetFormat, encodedData, imageInfo, 0, hasAlpha, isVideo);
+
+                        if (result) {
+                            textureData = result.transcodedImage.get_typed_memory_view().slice();
+                            result.transcodedImage.delete();
+                        }
+                    } else {
+                        const nBlocks = ((levelWidth + 3) >> 2) * ((levelHeight + 3) >> 2);
 
-                    const texMemoryPages = (nBlocks * 16 + 65535) >> 16;
-                    const memory = new WebAssembly.Memory({ initial: texMemoryPages + 1 });
-                    const textureView = new Uint8Array(memory.buffer, 65536, nBlocks * 16);
+                        const texMemoryPages = (nBlocks * 16 + 65535) >> 16;
+                        const memory = new WebAssembly.Memory({ initial: texMemoryPages + 1 });
+                        const textureView = new Uint8Array(memory.buffer, 65536, nBlocks * 16);
 
-                    const compressedData = new Uint8Array(this._data.buffer, this._levels[level].byteOffset + imageOffsetInLevel, levelByteLength);
+                        const encodedData = new Uint8Array(this._data.buffer, this._levels[level].byteOffset + imageOffsetInLevel, levelByteLength);
 
-                    textureView.set(compressedData);
+                        textureView.set(encodedData);
 
-                    const transcoder = (
-                        await WebAssembly.instantiateStreaming(
-                            fetch(KhronosTextureContainer2.WasmModules.uastc_bc7),
-                            { env: { memory: memory } }
-                        )
-                    ).instance.exports;
+                        const transcoder = (
+                            await WebAssembly.instantiateStreaming(
+                                fetch(KhronosTextureContainer2.WasmModules.uastc_bc7),
+                                { env: { memory: memory } }
+                            )
+                        ).instance.exports;
 
-                    if ((transcoder as any).transcode(nBlocks) === 0) {
+                        if ((transcoder as any).transcode(nBlocks) === 0) {
+                            textureData = textureView;
+                        }
+                    }
+                    if (textureData) {
                         console.log("yes!");
 
                         internalTexture.width = internalTexture.baseWidth = levelWidth;
                         internalTexture.height = internalTexture.baseHeight = levelHeight;
                         internalTexture.generateMipMaps = false;
-                        internalTexture.type = Constants.TEXTURETYPE_UNSIGNED_BYTE;
-                        internalTexture.format = 0x83F3;
                         internalTexture.invertY = false;
 
-(window as any).tt = internalTexture;
-
                         this._engine._bindTextureDirectly(this._engine._gl.TEXTURE_2D, internalTexture);
-                        this._engine._uploadCompressedDataToTextureDirectly(internalTexture, 0x83F3, levelWidth, levelHeight, textureView, 0, 0);
+                        this._engine._uploadCompressedDataToTextureDirectly(internalTexture, transcodedFormat, levelWidth, levelHeight, textureData, 0, 0);
 
                         internalTexture.isReady = true;
                     } else {