createBasisTexture = data => {
const basisFile = new BasisFile(new Uint8Array(data));
function cleanup() {
basisFile.close();
basisFile.delete();
}
const width = basisFile.getImageWidth(0, 0);
const height = basisFile.getImageHeight(0, 0);
const images = basisFile.getNumImages();
const levels = basisFile.getNumLevels(0);
const has_alpha = basisFile.getHasAlpha();
if (!width || !height || !images || !levels) {
cleanup();
throw new Error('Invalid .basis file');
}
let format;
if (SUPPORTS.astc) {
format = BASIS_FORMAT.ASTC_4x4;
} else if (SUPPORTS.bc7) {
format = BASIS_FORMAT.BC7;
} else if (SUPPORTS.dxt) {
format = has_alpha ? BASIS_FORMAT.BC3 : BASIS_FORMAT.BC1;
} else if (SUPPORTS.pvrtc) {
format = has_alpha ? BASIS_FORMAT.PVRTC1_4_RGBA : BASIS_FORMAT.PVRTC1_4_RGB;
if (((width & (width - 1)) != 0) || ((height & (height - 1)) != 0))
console.warn('ERROR: PVRTC1 requires square power of 2 textures');
if (width != height)
console.warn('ERROR: PVRTC1 requires square power of 2 textures');
} else if (SUPPORTS.etc) {
format = BASIS_FORMAT.ETC1;
} else {
format = BASIS_FORMAT.RGB565;
}
if (!basisFile.startTranscoding()) {
cleanup();
throw new Error('startTranscoding failed');
}
const dstSize = basisFile.getImageTranscodedSizeInBytes(0, 0, format);
const dst = new Uint8Array(dstSize);
if (!basisFile.transcodeImage(dst, 0, 0, format, 0, 0)) {
cleanup();
throw new Error('transcodeImage failed');
}
cleanup();
const alignedWidth = (width + 3) & ~3;
const alignedHeight = (height + 3) & ~3;
let tex;
if (format === BASIS_FORMAT.ASTC_4x4) {
tex = createCompressedTexture(dst, alignedWidth, alignedHeight, COMPRESSED.RGBA_ASTC_4x4_KHR);
} else if (format == BASIS_FORMAT.BC3) {
tex = createCompressedTexture(dst, alignedWidth, alignedHeight, COMPRESSED.RGBA_S3TC_DXT5_EXT);
} else if (format == BASIS_FORMAT.BC1) {
tex = createCompressedTexture(dst, alignedWidth, alignedHeight, COMPRESSED.RGB_S3TC_DXT1_EXT);
} else if (format == BASIS_FORMAT.BC7) {
tex = createCompressedTexture(dst, alignedWidth, alignedHeight, COMPRESSED.RGBA_BPTC_UNORM);
} else if (format === BASIS_FORMAT.ETC1) {
tex = createCompressedTexture(dst, alignedWidth, alignedHeight, COMPRESSED.RGB_ETC1_WEBGL);
} else if (format === BASIS_FORMAT.PVRTC1_4_RGB) {
tex = createCompressedTexture(dst, alignedWidth, alignedHeight, COMPRESSED.RGB_PVRTC_4BPPV1_IMG);
} else if (format === BASIS_FORMAT.PVRTC1_4_RGBA) {
tex = createCompressedTexture(dst, alignedWidth, alignedHeight, COMPRESSED.RGBA_PVRTC_4BPPV1_IMG);
} else {
const dstTex = new Uint16Array(width * height);
let pix = 0;
for (let y = 0; y < height; y++)
for (let x = 0; x < width; x++, pix++)
dstTex[pix] = dst[2 * pix + 0] | (dst[2 * pix + 1] << 8);
tex = createRgb565Texture(dstTex, width, height);
}
return tex;
}