|
@@ -3,6 +3,113 @@ import { ThinEngine } from "../Engines/thinEngine";
|
|
|
import { EngineCapabilities } from '../Engines/engineCapabilities';
|
|
|
import { Tools } from './tools';
|
|
|
import { DataReader } from './dataReader';
|
|
|
+import { Constants } from '../Engines/constants';
|
|
|
+
|
|
|
+const enum supercompressionScheme {
|
|
|
+ BasisLZ = 1,
|
|
|
+ ZStandard = 2
|
|
|
+}
|
|
|
+
|
|
|
+const enum dfdModel {
|
|
|
+ ETC1S = 163, /* not supported yet */
|
|
|
+ UASTC = 166
|
|
|
+}
|
|
|
+
|
|
|
+const enum textureFormat {
|
|
|
+ ETC1S,
|
|
|
+ UASTC4x4
|
|
|
+}
|
|
|
+
|
|
|
+const enum dfdChannel_ETC1S {
|
|
|
+ RGB = 0,
|
|
|
+ RRR = 3,
|
|
|
+ GGG = 4,
|
|
|
+ AAA = 15
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+const enum dfdChannel_UASTC {
|
|
|
+ RGB = 0,
|
|
|
+ RGBA = 3,
|
|
|
+ RRR = 4,
|
|
|
+ RRRG = 5
|
|
|
+}
|
|
|
+
|
|
|
+interface IKTX2_Header {
|
|
|
+ vkFormat: number;
|
|
|
+ typeSize: number;
|
|
|
+ pixelWidth: number;
|
|
|
+ pixelHeight: number;
|
|
|
+ pixelDepth: number;
|
|
|
+ layerCount: number;
|
|
|
+ faceCount: number;
|
|
|
+ levelCount: number;
|
|
|
+ supercompressionScheme: number;
|
|
|
+ dfdByteOffset: number;
|
|
|
+ dfdByteLength: number;
|
|
|
+ kvdByteOffset: number;
|
|
|
+ kvdByteLength: number;
|
|
|
+ sgdByteOffset: number;
|
|
|
+ sgdByteLength: number;
|
|
|
+}
|
|
|
+
|
|
|
+interface IKTX2_Level {
|
|
|
+ byteOffset: number;
|
|
|
+ byteLength: number;
|
|
|
+ uncompressedByteLength: number;
|
|
|
+}
|
|
|
+
|
|
|
+interface IKTX2_Sample {
|
|
|
+ bitOffset: number;
|
|
|
+ bitLength: number;
|
|
|
+ channelType: number;
|
|
|
+ channelFlags: number;
|
|
|
+ samplePosition: number[];
|
|
|
+ sampleLower: number;
|
|
|
+ sampleUpper: number;
|
|
|
+}
|
|
|
+
|
|
|
+interface IKTX2_DFD {
|
|
|
+ vendorId: number;
|
|
|
+ descriptorType: number;
|
|
|
+ versionNumber: number;
|
|
|
+ descriptorBlockSize: number;
|
|
|
+ colorModel: number;
|
|
|
+ colorPrimaries: number;
|
|
|
+ transferFunction: number;
|
|
|
+ flags: number;
|
|
|
+ texelBlockDimension: {
|
|
|
+ x: number;
|
|
|
+ y: number;
|
|
|
+ z: number;
|
|
|
+ w: number;
|
|
|
+ };
|
|
|
+ bytesPlane: Array<number>;
|
|
|
+ numSamples: number;
|
|
|
+ samples: Array<IKTX2_Sample>;
|
|
|
+}
|
|
|
+
|
|
|
+interface IKTX2_ImageDesc {
|
|
|
+ imageFlags: number;
|
|
|
+ rgbSliceByteOffset: number;
|
|
|
+ rgbSliceByteLength: number;
|
|
|
+ alphaSliceByteOffset: number;
|
|
|
+ alphaSliceByteLength: number;
|
|
|
+}
|
|
|
+
|
|
|
+interface IKTX2_SupercompressionGlobalData {
|
|
|
+ endpointCount?: number;
|
|
|
+ selectorCount?: number;
|
|
|
+ endpointsByteLength?: number;
|
|
|
+ selectorsByteLength?: number;
|
|
|
+ tablesByteLength?: number;
|
|
|
+ extendedByteLength?: number;
|
|
|
+ imageDescs?: Array<IKTX2_ImageDesc>;
|
|
|
+ endpointsData?: Uint8Array;
|
|
|
+ selectorsData?: Uint8Array;
|
|
|
+ tablesData?: Uint8Array;
|
|
|
+ extendedData?: Uint8Array;
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* Class for loading KTX2 files
|
|
@@ -10,51 +117,48 @@ import { DataReader } from './dataReader';
|
|
|
* @hidden
|
|
|
*/
|
|
|
export class KhronosTextureContainer2 {
|
|
|
- public static WasmModuleUASTC_ASTC = "/dist/preview release/basisTranscoder/uastc_astc.wasm";
|
|
|
+ public static WasmModules = {
|
|
|
+ "uastc_astc" : "/dist/preview release/basisTranscoder/uastc_astc.wasm",
|
|
|
+ "uastc_bc7" : "/dist/preview release/basisTranscoder/uastc_bc7.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 _engine: ThinEngine;
|
|
|
|
|
|
- private static readonly DFDChannel = {
|
|
|
- ETC1S: {
|
|
|
- RGB: 0,
|
|
|
- RRR: 3,
|
|
|
- GGG: 4,
|
|
|
- AAA: 15,
|
|
|
- },
|
|
|
- UASTC: {
|
|
|
- RGB: 0,
|
|
|
- RGBA: 3,
|
|
|
- RRR: 4,
|
|
|
- RRRG: 5
|
|
|
- },
|
|
|
- };
|
|
|
+ private _data: ArrayBufferView;
|
|
|
+ private _header: IKTX2_Header;
|
|
|
+ private _levels: Array<IKTX2_Level>;
|
|
|
+ private _dfdBlock: IKTX2_DFD;
|
|
|
+ private _sgd: IKTX2_SupercompressionGlobalData;
|
|
|
|
|
|
public constructor(engine: ThinEngine) {
|
|
|
+ this._engine = engine;
|
|
|
+
|
|
|
if (!KhronosTextureContainer2._ModulePromise) {
|
|
|
KhronosTextureContainer2._ModulePromise = new Promise((resolve) => {
|
|
|
- Tools.LoadFileAsync(KhronosTextureContainer2.WasmModuleUASTC_ASTC).then((wasmBinary) => {
|
|
|
+ Tools.LoadFileAsync(KhronosTextureContainer2.WasmModules.uastc_bc7).then((wasmBinary) => {
|
|
|
resolve({ module: wasmBinary });
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private _parseData(data: ArrayBufferView) {
|
|
|
+ /**
|
|
|
+ * Based on https://github.com/mrdoob/three.js/blob/dfb5c23ce126ec845e4aa240599915fef5375797/examples/jsm/loaders/KTX2Loader.js
|
|
|
+ */
|
|
|
+ private _parseData() {
|
|
|
let offsetInFile = 12; // skip the header
|
|
|
|
|
|
- // Get the header
|
|
|
- const hdrReader = new DataReader().setBuffer(data, offsetInFile, 17 * 4);
|
|
|
+ /**
|
|
|
+ * Get the header
|
|
|
+ */
|
|
|
+ const hdrReader = new DataReader().setBuffer(this._data, offsetInFile, 17 * 4);
|
|
|
|
|
|
- const header = {
|
|
|
+ const header = this._header = {
|
|
|
vkFormat: hdrReader.readUint32(),
|
|
|
typeSize: hdrReader.readUint32(),
|
|
|
pixelWidth: hdrReader.readUint32(),
|
|
@@ -65,12 +169,12 @@ export class KhronosTextureContainer2 {
|
|
|
levelCount: hdrReader.readUint32(),
|
|
|
supercompressionScheme: hdrReader.readUint32(),
|
|
|
|
|
|
- dfdByteOffset: hdrReader.readUint32(),
|
|
|
- dfdByteLength: hdrReader.readUint32(),
|
|
|
- kvdByteOffset: hdrReader.readUint32(),
|
|
|
- kvdByteLength: hdrReader.readUint32(),
|
|
|
- sgdByteOffset: hdrReader.readUint64(),
|
|
|
- sgdByteLength: hdrReader.readUint64(),
|
|
|
+ dfdByteOffset: hdrReader.readUint32(),
|
|
|
+ dfdByteLength: hdrReader.readUint32(),
|
|
|
+ kvdByteOffset: hdrReader.readUint32(),
|
|
|
+ kvdByteLength: hdrReader.readUint32(),
|
|
|
+ sgdByteOffset: hdrReader.readUint64(),
|
|
|
+ sgdByteLength: hdrReader.readUint64(),
|
|
|
};
|
|
|
|
|
|
if (header.pixelDepth > 0) {
|
|
@@ -89,18 +193,20 @@ export class KhronosTextureContainer2 {
|
|
|
|
|
|
offsetInFile += hdrReader.byteOffset;
|
|
|
|
|
|
- // Get the levels
|
|
|
+ /**
|
|
|
+ * Get the levels
|
|
|
+ */
|
|
|
let levelCount = Math.max(1, header.levelCount);
|
|
|
|
|
|
- const levelReader = new DataReader().setBuffer(data, offsetInFile, levelCount * 3 * (2 * 4));
|
|
|
+ const levelReader = new DataReader().setBuffer(this._data, offsetInFile, levelCount * 3 * (2 * 4));
|
|
|
|
|
|
- const levels: Array<{ byteOffset: number, byteLength: number, uncompressedByteLength: number }> = [];
|
|
|
+ const levels: Array<IKTX2_Level> = this._levels = [];
|
|
|
|
|
|
while (levelCount--) {
|
|
|
levels.push({
|
|
|
byteOffset: levelReader.readUint64(),
|
|
|
byteLength: levelReader.readUint64(),
|
|
|
- uncompressedByteLength: levelReader.readUint64()
|
|
|
+ uncompressedByteLength: levelReader.readUint64(),
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -108,10 +214,12 @@ export class KhronosTextureContainer2 {
|
|
|
|
|
|
console.log(levels);
|
|
|
|
|
|
- // Get the data format descriptor (DFD) blocks
|
|
|
- const dfdReader = new DataReader().setBuffer(data, header.dfdByteOffset, header.dfdByteLength);
|
|
|
+ /**
|
|
|
+ * Get the data format descriptor (DFD) blocks
|
|
|
+ */
|
|
|
+ const dfdReader = new DataReader().setBuffer(this._data, header.dfdByteOffset, header.dfdByteLength);
|
|
|
|
|
|
- const dfdBlock = {
|
|
|
+ const dfdBlock = this._dfdBlock = {
|
|
|
vendorId: dfdReader.skipBytes(4 /* skip totalSize */).readUint16(),
|
|
|
descriptorType: dfdReader.readUint16(),
|
|
|
versionNumber: dfdReader.readUint16(),
|
|
@@ -121,10 +229,10 @@ export class KhronosTextureContainer2 {
|
|
|
transferFunction: dfdReader.readUint8(),
|
|
|
flags: dfdReader.readUint8(),
|
|
|
texelBlockDimension: {
|
|
|
- r: dfdReader.readUint8() + 1,
|
|
|
- g: dfdReader.readUint8() + 1,
|
|
|
- b: dfdReader.readUint8() + 1,
|
|
|
- a: dfdReader.readUint8() + 1,
|
|
|
+ x: dfdReader.readUint8() + 1,
|
|
|
+ y: dfdReader.readUint8() + 1,
|
|
|
+ z: dfdReader.readUint8() + 1,
|
|
|
+ w: dfdReader.readUint8() + 1,
|
|
|
},
|
|
|
bytesPlane: [
|
|
|
dfdReader.readUint8(), /* bytesPlane0 */
|
|
@@ -134,52 +242,238 @@ export class KhronosTextureContainer2 {
|
|
|
dfdReader.readUint8(), /* bytesPlane4 */
|
|
|
dfdReader.readUint8(), /* bytesPlane5 */
|
|
|
dfdReader.readUint8(), /* bytesPlane6 */
|
|
|
- dfdReader.readUint8() /* bytesPlane7 */
|
|
|
+ dfdReader.readUint8(), /* bytesPlane7 */
|
|
|
],
|
|
|
numSamples: 0,
|
|
|
- samples: new Array<{ bitOffset: number, bitLength: number, channelType: number, samplePosition: number[], sampleLower: number, sampleUpper: number }>()
|
|
|
+ samples: new Array<IKTX2_Sample>(),
|
|
|
};
|
|
|
|
|
|
dfdBlock.numSamples = (dfdBlock.descriptorBlockSize - 24) / 16;
|
|
|
|
|
|
for (let i = 0; i < dfdBlock.numSamples; i++) {
|
|
|
- dfdBlock.samples.push({
|
|
|
+ const sample = {
|
|
|
bitOffset: dfdReader.readUint16(),
|
|
|
- bitLength: dfdReader.readUint8(),
|
|
|
+ bitLength: dfdReader.readUint8() + 1,
|
|
|
channelType: dfdReader.readUint8(),
|
|
|
+ channelFlags: 0,
|
|
|
samplePosition: [
|
|
|
dfdReader.readUint8(), /* samplePosition0 */
|
|
|
dfdReader.readUint8(), /* samplePosition1 */
|
|
|
dfdReader.readUint8(), /* samplePosition2 */
|
|
|
- dfdReader.readUint8() /* samplePosition3 */
|
|
|
+ dfdReader.readUint8(), /* samplePosition3 */
|
|
|
],
|
|
|
sampleLower: dfdReader.readUint32(),
|
|
|
- sampleUpper: dfdReader.readUint32()
|
|
|
- });
|
|
|
+ sampleUpper: dfdReader.readUint32(),
|
|
|
+ };
|
|
|
+
|
|
|
+ sample.channelFlags = (sample.channelType & 0xF0) >> 4;
|
|
|
+ sample.channelType = sample.channelType & 0x0F;
|
|
|
+
|
|
|
+ dfdBlock.samples.push(sample);
|
|
|
}
|
|
|
|
|
|
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.`);
|
|
|
+ if (dfdBlock.colorModel !== dfdModel.UASTC) {
|
|
|
+ throw new Error(`Failed to upload - Only UASTC color model files are currently supported.`);
|
|
|
}
|
|
|
|
|
|
- // Get the Supercompression Global Data (sgd)
|
|
|
- const sgd: any = {};
|
|
|
+ /*if (header.vkFormat !== KhronosTextureContainer2.VK_FORMAT_UNDEFINED &&
|
|
|
+ !(header.supercompressionScheme === supercompressionScheme.BasisLZ ||
|
|
|
+ dfdBlock.colorModel === dfdModel.UASTC)) {
|
|
|
+ throw new Error(`Failed to upload - Only Basis Universal supercompression is currently supported.`);
|
|
|
+ }*/
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the Supercompression Global Data (sgd)
|
|
|
+ */
|
|
|
+ const sgd: IKTX2_SupercompressionGlobalData = this._sgd = {};
|
|
|
|
|
|
if (header.sgdByteLength > 0) {
|
|
|
- const sgdReader = new DataReader().setBuffer(data, header.sgdByteOffset, header.sgdByteLength);
|
|
|
+ const sgdReader = new DataReader().setBuffer(this._data, header.sgdByteOffset, header.sgdByteLength);
|
|
|
+
|
|
|
+ sgd.endpointCount = sgdReader.readUint16();
|
|
|
+ sgd.selectorCount = sgdReader.readUint16();
|
|
|
+ sgd.endpointsByteLength = sgdReader.readUint32();
|
|
|
+ sgd.selectorsByteLength = sgdReader.readUint32();
|
|
|
+ sgd.tablesByteLength = sgdReader.readUint32();
|
|
|
+ sgd.extendedByteLength = sgdReader.readUint32();
|
|
|
+ sgd.imageDescs = [];
|
|
|
+
|
|
|
+ for (let i = 0; i < header.levelCount; i ++) {
|
|
|
+ sgd.imageDescs.push({
|
|
|
+ imageFlags: sgdReader.readUint32(),
|
|
|
+ rgbSliceByteOffset: sgdReader.readUint32(),
|
|
|
+ rgbSliceByteLength: sgdReader.readUint32(),
|
|
|
+ alphaSliceByteOffset: sgdReader.readUint32(),
|
|
|
+ alphaSliceByteLength: sgdReader.readUint32(),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ const endpointsByteOffset = header.sgdByteOffset + sgdReader.byteOffset;
|
|
|
+ const selectorsByteOffset = endpointsByteOffset + sgd.endpointsByteLength;
|
|
|
+ const tablesByteOffset = selectorsByteOffset + sgd.selectorsByteLength;
|
|
|
+ const extendedByteOffset = tablesByteOffset + sgd.tablesByteLength;
|
|
|
+
|
|
|
+ sgd.endpointsData = new Uint8Array(this._data.buffer, endpointsByteOffset, sgd.endpointsByteLength);
|
|
|
+ sgd.selectorsData = new Uint8Array(this._data.buffer, selectorsByteOffset, sgd.selectorsByteLength);
|
|
|
+ sgd.tablesData = new Uint8Array(this._data.buffer, tablesByteOffset, sgd.tablesByteLength);
|
|
|
+ sgd.extendedData = new Uint8Array(this._data.buffer, extendedByteOffset, sgd.extendedByteLength);
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(sgd);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private get textureFormat(): textureFormat {
|
|
|
+ return this._dfdBlock.colorModel === dfdModel.UASTC ? textureFormat.UASTC4x4 : textureFormat.ETC1S;
|
|
|
+ }
|
|
|
+
|
|
|
+ private get hasAlpha(): boolean {
|
|
|
+ const tformat = this.textureFormat;
|
|
|
+
|
|
|
+ switch (tformat) {
|
|
|
+ case textureFormat.ETC1S:
|
|
|
+ return this._dfdBlock.numSamples === 2 && (this._dfdBlock.samples[0].channelType === dfdChannel_ETC1S.AAA || this._dfdBlock.samples[1].channelType === dfdChannel_ETC1S.AAA);
|
|
|
+ case textureFormat.UASTC4x4:
|
|
|
+ return this._dfdBlock.samples[0].channelType === dfdChannel_UASTC.RGBA;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private async _initMipmaps(internalTexture: InternalTexture) {
|
|
|
+
|
|
|
+ /*await this.zstd.init();
|
|
|
+
|
|
|
+ var TranscodeTarget = this.basisModule.TranscodeTarget;
|
|
|
+ var TextureFormat = this.basisModule.TextureFormat;
|
|
|
+ var ImageInfo = this.basisModule.ImageInfo;*/
|
|
|
+
|
|
|
+ var mipmaps = [];
|
|
|
+ var width = this._header.pixelWidth;
|
|
|
+ var height = this._header.pixelHeight;
|
|
|
+ var texFormat = this.textureFormat;
|
|
|
+ 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;
|
|
|
+
|
|
|
+ } else if (config.dxtSupported) {
|
|
|
+
|
|
|
+ targetFormat = hasAlpha ? TranscodeTarget.BC3_RGBA : TranscodeTarget.BC1_RGB;
|
|
|
+ this.transcodedFormat = hasAlpha ? RGBA_S3TC_DXT5_Format : RGB_S3TC_DXT1_Format;
|
|
|
+
|
|
|
+ } else if (config.pvrtcSupported && pvrtcTranscodable) {
|
|
|
+
|
|
|
+ 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 levelByteLength = this._levels[level].byteLength;
|
|
|
+
|
|
|
+ for (var imageIndex = 0; imageIndex < numImagesInLevel; imageIndex ++) {
|
|
|
+ if (texFormat === textureFormat.UASTC4x4) {
|
|
|
+ // UASTC
|
|
|
+ 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 compressedData = new Uint8Array(this._data.buffer, this._levels[level].byteOffset + imageOffsetInLevel, levelByteLength);
|
|
|
+
|
|
|
+ textureView.set(compressedData);
|
|
|
+
|
|
|
+ const transcoder = (
|
|
|
+ await WebAssembly.instantiateStreaming(
|
|
|
+ fetch(KhronosTextureContainer2.WasmModules.uastc_bc7),
|
|
|
+ { env: { memory: memory } }
|
|
|
+ )
|
|
|
+ ).instance.exports;
|
|
|
+
|
|
|
+ if ((transcoder as any).transcode(nBlocks) === 0) {
|
|
|
+ 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);
|
|
|
+
|
|
|
+ internalTexture.isReady = true;
|
|
|
+ } else {
|
|
|
+ console.log("no...");
|
|
|
+ }
|
|
|
+
|
|
|
+ /*if (this._header.supercompressionScheme === supercompressionScheme.ZStandard) {
|
|
|
+ encodedData = this.zstd.decode(encodedData, levelUncompressedByteLength);
|
|
|
+ }*/
|
|
|
+
|
|
|
+ //result = transcoder.transcodeImage(targetFormat, encodedData, imageInfo, 0, hasAlpha, isVideo);
|
|
|
+ //mipmaps.push({ data: levelData, width: levelWidth, height: levelHeight });
|
|
|
+ }
|
|
|
+
|
|
|
+ imageOffsetInLevel += levelByteLength;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ //this.mipmaps = mipmaps;
|
|
|
}
|
|
|
|
|
|
public uploadAsync(data: ArrayBufferView, internalTexture: InternalTexture): Promise<void> {
|
|
|
+ this._data = data;
|
|
|
return KhronosTextureContainer2._ModulePromise.then((moduleWrapper: any) => {
|
|
|
const module = moduleWrapper.module;
|
|
|
|
|
|
- this._parseData(data);
|
|
|
+ this._parseData();
|
|
|
+ this._initMipmaps(internalTexture);
|
|
|
|
|
|
/*const ktxTexture = new module.ktxTexture(data);
|
|
|
try {
|