@kibeo/loaders.gl-textures
Version:
Framework-independent loaders for compressed and super compressed (basis) textures
91 lines (74 loc) • 2.63 kB
JavaScript
import { loadCrunchModule } from './crunch-module-loader';
import { GL } from '../gl-constants';
import { assert } from '@kibeo/loaders.gl-loader-utils';
import { getDxt1LevelSize, getDxtXLevelSize } from './parse-dds';
import { extractMipmapImages } from '../utils/extract-mipmap-images';
const CRN_FORMAT = {
cCRNFmtInvalid: -1,
cCRNFmtDXT1: 0,
cCRNFmtDXT3: 1,
cCRNFmtDXT5: 2
};
const DXT_FORMAT_MAP = {};
DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT1] = {
pixelFormat: GL.COMPRESSED_RGB_S3TC_DXT1_EXT,
sizeFunction: getDxt1LevelSize
};
DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT3] = {
pixelFormat: GL.COMPRESSED_RGBA_S3TC_DXT3_EXT,
sizeFunction: getDxtXLevelSize
};
DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT5] = {
pixelFormat: GL.COMPRESSED_RGBA_S3TC_DXT5_EXT,
sizeFunction: getDxtXLevelSize
};
let cachedDstSize = 0;
let dst;
export async function parseCrunch(data, options) {
const crunchModule = await loadCrunchModule(options);
const srcSize = data.byteLength;
const bytes = new Uint8Array(data);
const src = crunchModule._malloc(srcSize);
arrayBufferCopy(bytes, crunchModule.HEAPU8, src, srcSize);
const format = crunchModule._crn_get_dxt_format(src, srcSize);
assert(Boolean(DXT_FORMAT_MAP[format]), 'Unsupported format');
const mipMapLevels = crunchModule._crn_get_levels(src, srcSize);
const width = crunchModule._crn_get_width(src, srcSize);
const height = crunchModule._crn_get_height(src, srcSize);
const sizeFunction = DXT_FORMAT_MAP[format].sizeFunction;
let dstSize = 0;
for (let i = 0; i < mipMapLevels; ++i) {
dstSize += sizeFunction(width >> i, height >> i);
}
if (cachedDstSize < dstSize) {
if (dst) {
crunchModule._free(dst);
}
dst = crunchModule._malloc(dstSize);
cachedDstSize = dstSize;
}
crunchModule._crn_decompress(src, srcSize, dst, dstSize, 0, mipMapLevels);
crunchModule._free(src);
const image = new Uint8Array(crunchModule.HEAPU8.buffer, dst, dstSize).slice();
return extractMipmapImages(image, {
mipMapLevels,
width,
height,
sizeFunction,
internalFormat: DXT_FORMAT_MAP[format].pixelFormat
});
}
function arrayBufferCopy(srcData, dstData, dstByteOffset, numBytes) {
let i;
const dst32Offset = dstByteOffset / 4;
const tail = numBytes % 4;
const src32 = new Uint32Array(srcData.buffer, 0, (numBytes - tail) / 4);
const dst32 = new Uint32Array(dstData.buffer);
for (i = 0; i < src32.length; i++) {
dst32[dst32Offset + i] = src32[i];
}
for (i = numBytes - tail; i < numBytes; i++) {
dstData[dstByteOffset + i] = srcData[i];
}
}
//# sourceMappingURL=parse-crunch.js.map