Parcourir la source

KTX2 loader reworking

Popov72 il y a 5 ans
Parent
commit
c0709bf33b
1 fichiers modifiés avec 160 ajouts et 8 suppressions
  1. 160 8
      src/Misc/khronosTextureContainer2.ts

+ 160 - 8
src/Misc/khronosTextureContainer2.ts

@@ -1,8 +1,8 @@
 import { InternalTexture } from "../Materials/Textures/internalTexture";
 import { ThinEngine } from "../Engines/thinEngine";
 import { EngineCapabilities } from '../Engines/engineCapabilities';
-
-declare var LIBKTX: any;
+import { Tools } from './tools';
+import { DataReader } from './dataReader';
 
 /**
  * Class for loading KTX2 files
@@ -10,26 +10,178 @@ declare var LIBKTX: any;
  * @hidden
  */
 export class KhronosTextureContainer2 {
+    public static WasmModuleUASTC_ASTC = "/dist/preview release/basisTranscoder/uastc_astc.wasm";
+
     private static _ModulePromise: Promise<{ module: any }>;
     private static _TranscodeFormat: number;
 
+    private static readonly VK_FORMAT_UNDEFINED = 0x00;
+    private static readonly SupercompressionScheme_BasisLZ = 1;
+
+    private static readonly DFDModel = {
+        ETC1S: 163,
+        UASTC: 166,
+    };
+
+    private static readonly DFDChannel = {
+        ETC1S: {
+            RGB: 0,
+            RRR: 3,
+            GGG: 4,
+            AAA: 15,
+        },
+        UASTC: {
+            RGB: 0,
+            RGBA: 3,
+            RRR: 4,
+            RRRG: 5
+        },
+    };
+
     public constructor(engine: ThinEngine) {
         if (!KhronosTextureContainer2._ModulePromise) {
             KhronosTextureContainer2._ModulePromise = new Promise((resolve) => {
-                LIBKTX({preinitializedWebGLContext: engine._gl}).then((module: any) => {
-                    module.GL.makeContextCurrent(module.GL.registerContext(engine._gl, { majorVersion: engine._webGLVersion }));
-                    KhronosTextureContainer2._TranscodeFormat = this._determineTranscodeFormat(module.TranscodeTarget, engine.getCaps());
-                    resolve({ module: module });
+                Tools.LoadFileAsync(KhronosTextureContainer2.WasmModuleUASTC_ASTC).then((wasmBinary) => {
+                    resolve({ module: wasmBinary });
                 });
             });
         }
     }
 
+    private _parseData(data: ArrayBufferView) {
+        let offsetInFile = 12; // skip the header
+
+        // Get the header
+        const hdrReader = new DataReader().setBuffer(data, offsetInFile, 17 * 4);
+
+        const header = {
+            vkFormat:               hdrReader.readUint32(),
+            typeSize:               hdrReader.readUint32(),
+            pixelWidth:             hdrReader.readUint32(),
+            pixelHeight:            hdrReader.readUint32(),
+            pixelDepth:             hdrReader.readUint32(),
+            layerCount:             hdrReader.readUint32(),
+            faceCount:              hdrReader.readUint32(),
+            levelCount:             hdrReader.readUint32(),
+            supercompressionScheme: hdrReader.readUint32(),
+
+            dfdByteOffset: hdrReader.readUint32(),
+            dfdByteLength: hdrReader.readUint32(),
+            kvdByteOffset: hdrReader.readUint32(),
+            kvdByteLength: hdrReader.readUint32(),
+            sgdByteOffset: hdrReader.readUint64(),
+            sgdByteLength: hdrReader.readUint64(),
+        };
+
+        if (header.pixelDepth > 0) {
+            throw new Error(`Failed to upload - Only 2D textures are currently supported.`);
+        }
+
+        if (header.layerCount > 1) {
+            throw new Error(`Failed to upload - Array textures are not currently supported.`);
+        }
+
+        if (header.faceCount > 1) {
+            throw new Error(`Failed to upload - Cube textures are not currently supported.`);
+        }
+
+        console.log(header);
+
+        offsetInFile += hdrReader.byteOffset;
+
+        // Get the levels
+        let levelCount = Math.max(1, header.levelCount);
+
+        const levelReader = new DataReader().setBuffer(data, offsetInFile, levelCount * 3 * (2 * 4));
+
+        const levels: Array<{ byteOffset: number, byteLength: number, uncompressedByteLength: number }> = [];
+
+        while (levelCount--) {
+            levels.push({
+                byteOffset: levelReader.readUint64(),
+                byteLength: levelReader.readUint64(),
+                uncompressedByteLength: levelReader.readUint64()
+            });
+        }
+
+        offsetInFile += levelReader.byteOffset;
+
+        console.log(levels);
+
+        // Get the data format descriptor (DFD) blocks
+        const dfdReader = new DataReader().setBuffer(data, header.dfdByteOffset, header.dfdByteLength);
+
+        const dfdBlock = {
+            vendorId: dfdReader.skipBytes(4 /* skip totalSize */).readUint16(),
+            descriptorType: dfdReader.readUint16(),
+            versionNumber: dfdReader.readUint16(),
+            descriptorBlockSize: dfdReader.readUint16(),
+            colorModel: dfdReader.readUint8(),
+            colorPrimaries: dfdReader.readUint8(),
+            transferFunction: dfdReader.readUint8(),
+            flags: dfdReader.readUint8(),
+            texelBlockDimension: {
+                r: dfdReader.readUint8() + 1,
+                g: dfdReader.readUint8() + 1,
+                b: dfdReader.readUint8() + 1,
+                a: dfdReader.readUint8() + 1,
+            },
+            bytesPlane: [
+                dfdReader.readUint8(), /* bytesPlane0 */
+                dfdReader.readUint8(), /* bytesPlane1 */
+                dfdReader.readUint8(), /* bytesPlane2 */
+                dfdReader.readUint8(), /* bytesPlane3 */
+                dfdReader.readUint8(), /* bytesPlane4 */
+                dfdReader.readUint8(), /* bytesPlane5 */
+                dfdReader.readUint8(), /* bytesPlane6 */
+                dfdReader.readUint8()  /* bytesPlane7 */
+            ],
+            numSamples: 0,
+            samples: new Array<{ bitOffset: number, bitLength: number, channelType: number, samplePosition: number[], sampleLower: number, sampleUpper: number }>()
+        };
+
+        dfdBlock.numSamples = (dfdBlock.descriptorBlockSize - 24) / 16;
+
+        for (let i = 0; i < dfdBlock.numSamples; i++) {
+            dfdBlock.samples.push({
+                bitOffset: dfdReader.readUint16(),
+                bitLength: dfdReader.readUint8(),
+                channelType: dfdReader.readUint8(),
+                samplePosition: [
+                    dfdReader.readUint8(), /* samplePosition0 */
+                    dfdReader.readUint8(), /* samplePosition1 */
+                    dfdReader.readUint8(), /* samplePosition2 */
+                    dfdReader.readUint8()  /* samplePosition3 */
+                ],
+                sampleLower: dfdReader.readUint32(),
+                sampleUpper: dfdReader.readUint32()
+            });
+        }
+
+        console.log(dfdBlock);
+
+        if (header.vkFormat !== KhronosTextureContainer2.VK_FORMAT_UNDEFINED &&
+             !(header.supercompressionScheme === KhronosTextureContainer2.SupercompressionScheme_BasisLZ ||
+                dfdBlock.colorModel === KhronosTextureContainer2.DFDModel.UASTC)) {
+            throw new Error(`Failed to upload - Only Basis Universal supercompression is currently supported.`);
+        }
+
+        // Get the Supercompression Global Data (sgd)
+        const sgd: any = {};
+
+        if (header.sgdByteLength > 0) {
+            const sgdReader = new DataReader().setBuffer(data, header.sgdByteOffset, header.sgdByteLength);
+        }
+
+    }
+
     public uploadAsync(data: ArrayBufferView, internalTexture: InternalTexture): Promise<void> {
         return KhronosTextureContainer2._ModulePromise.then((moduleWrapper: any) => {
             const module = moduleWrapper.module;
 
-            const ktxTexture = new module.ktxTexture(data);
+            this._parseData(data);
+
+            /*const ktxTexture = new module.ktxTexture(data);
             try {
                 if (ktxTexture.needsTranscoding) {
                     ktxTexture.transcodeBasis(KhronosTextureContainer2._TranscodeFormat, 0);
@@ -51,7 +203,7 @@ export class KhronosTextureContainer2 {
             }
             finally {
                 ktxTexture.delete();
-            }
+            }*/
         });
     }