@loaders.gl/textures
Version:
Framework-independent loaders for compressed and super compressed (basis) textures
1,358 lines (1,337 loc) • 54.9 kB
JavaScript
"use strict";
(() => {
// ../loader-utils/src/lib/env-utils/assert.ts
function assert(condition, message) {
if (!condition) {
throw new Error(message || "loader assertion failed.");
}
}
// ../loader-utils/src/lib/module-utils/js-module-utils.ts
function registerJSModules(modules) {
globalThis.loaders ||= {};
globalThis.loaders.modules ||= {};
Object.assign(globalThis.loaders.modules, modules);
}
function getJSModuleOrNull(name) {
const module = globalThis.loaders?.modules?.[name];
return module || null;
}
// ../worker-utils/src/lib/env-utils/version.ts
function getVersion() {
if (!globalThis._loadersgl_?.version) {
globalThis._loadersgl_ = globalThis._loadersgl_ || {};
if (false) {
console.warn(
"loaders.gl: The __VERSION__ variable is not injected using babel plugin. Latest unstable workers would be fetched from the CDN."
);
globalThis._loadersgl_.version = NPM_TAG;
} else {
globalThis._loadersgl_.version = "4.3.2";
}
}
return globalThis._loadersgl_.version;
}
var VERSION = getVersion();
// ../worker-utils/src/lib/env-utils/assert.ts
function assert2(condition, message) {
if (!condition) {
throw new Error(message || "loaders.gl assertion failed.");
}
}
// ../worker-utils/src/lib/env-utils/globals.ts
var globals = {
self: typeof self !== "undefined" && self,
window: typeof window !== "undefined" && window,
global: typeof global !== "undefined" && global,
document: typeof document !== "undefined" && document
};
var self_ = globals.self || globals.window || globals.global || {};
var window_ = globals.window || globals.self || globals.global || {};
var global_ = globals.global || globals.self || globals.window || {};
var document_ = globals.document || {};
var isBrowser = (
// @ts-ignore process.browser
typeof process !== "object" || String(process) !== "[object process]" || process.browser
);
var isWorker = typeof importScripts === "function";
var isMobile = typeof window !== "undefined" && typeof window.orientation !== "undefined";
var matches = typeof process !== "undefined" && process.version && /v([0-9]*)/.exec(process.version);
var nodeVersion = matches && parseFloat(matches[1]) || 0;
// ../worker-utils/src/lib/node/worker_threads-browser.ts
var parentPort = null;
// ../worker-utils/src/lib/worker-utils/get-transfer-list.ts
function getTransferList(object, recursive = true, transfers) {
const transfersSet = transfers || /* @__PURE__ */ new Set();
if (!object) {
} else if (isTransferable(object)) {
transfersSet.add(object);
} else if (isTransferable(object.buffer)) {
transfersSet.add(object.buffer);
} else if (ArrayBuffer.isView(object)) {
} else if (recursive && typeof object === "object") {
for (const key in object) {
getTransferList(object[key], recursive, transfersSet);
}
}
return transfers === void 0 ? Array.from(transfersSet) : [];
}
function isTransferable(object) {
if (!object) {
return false;
}
if (object instanceof ArrayBuffer) {
return true;
}
if (typeof MessagePort !== "undefined" && object instanceof MessagePort) {
return true;
}
if (typeof ImageBitmap !== "undefined" && object instanceof ImageBitmap) {
return true;
}
if (typeof OffscreenCanvas !== "undefined" && object instanceof OffscreenCanvas) {
return true;
}
return false;
}
// ../worker-utils/src/lib/worker-farm/worker-body.ts
async function getParentPort() {
return parentPort;
}
var onMessageWrapperMap = /* @__PURE__ */ new Map();
var WorkerBody = class {
/** Check that we are actually in a worker thread */
static async inWorkerThread() {
return typeof self !== "undefined" || Boolean(await getParentPort());
}
/*
* (type: WorkerMessageType, payload: WorkerMessagePayload) => any
*/
static set onmessage(onMessage) {
async function handleMessage(message) {
const parentPort2 = await getParentPort();
const { type, payload } = parentPort2 ? message : message.data;
onMessage(type, payload);
}
getParentPort().then((parentPort2) => {
if (parentPort2) {
parentPort2.on("message", (message) => {
handleMessage(message);
});
parentPort2.on("exit", () => console.debug("Node worker closing"));
} else {
globalThis.onmessage = handleMessage;
}
});
}
static async addEventListener(onMessage) {
let onMessageWrapper = onMessageWrapperMap.get(onMessage);
if (!onMessageWrapper) {
onMessageWrapper = async (message) => {
if (!isKnownMessage(message)) {
return;
}
const parentPort3 = await getParentPort();
const { type, payload } = parentPort3 ? message : message.data;
onMessage(type, payload);
};
}
const parentPort2 = await getParentPort();
if (parentPort2) {
console.error("not implemented");
} else {
globalThis.addEventListener("message", onMessageWrapper);
}
}
static async removeEventListener(onMessage) {
const onMessageWrapper = onMessageWrapperMap.get(onMessage);
onMessageWrapperMap.delete(onMessage);
const parentPort2 = await getParentPort();
if (parentPort2) {
console.error("not implemented");
} else {
globalThis.removeEventListener("message", onMessageWrapper);
}
}
/**
* Send a message from a worker to creating thread (main thread)
* @param type
* @param payload
*/
static async postMessage(type, payload) {
const data = { source: "loaders.gl", type, payload };
const transferList = getTransferList(payload);
const parentPort2 = await getParentPort();
if (parentPort2) {
parentPort2.postMessage(data, transferList);
} else {
globalThis.postMessage(data, transferList);
}
}
};
function isKnownMessage(message) {
const { type, data } = message;
return type === "message" && data && typeof data.source === "string" && data.source.startsWith("loaders.gl");
}
// ../worker-utils/src/lib/library-utils/library-utils.ts
var loadLibraryPromises = {};
async function loadLibrary(libraryUrl, moduleName = null, options = {}, libraryName = null) {
if (moduleName) {
libraryUrl = getLibraryUrl(libraryUrl, moduleName, options, libraryName);
}
loadLibraryPromises[libraryUrl] = // eslint-disable-next-line @typescript-eslint/no-misused-promises
loadLibraryPromises[libraryUrl] || loadLibraryFromFile(libraryUrl);
return await loadLibraryPromises[libraryUrl];
}
function getLibraryUrl(library, moduleName, options = {}, libraryName = null) {
if (!options.useLocalLibraries && library.startsWith("http")) {
return library;
}
libraryName = libraryName || library;
const modules = options.modules || {};
if (modules[libraryName]) {
return modules[libraryName];
}
if (!isBrowser) {
return `modules/${moduleName}/dist/libs/${libraryName}`;
}
if (options.CDN) {
assert2(options.CDN.startsWith("http"));
return `${options.CDN}/${moduleName}@${VERSION}/dist/libs/${libraryName}`;
}
if (isWorker) {
return `../src/libs/${libraryName}`;
}
return `modules/${moduleName}/src/libs/${libraryName}`;
}
async function loadLibraryFromFile(libraryUrl) {
if (libraryUrl.endsWith("wasm")) {
return await loadAsArrayBuffer(libraryUrl);
}
if (!isBrowser) {
try {
const { requireFromFile } = globalThis.loaders || {};
return await requireFromFile?.(libraryUrl);
} catch (error) {
console.error(error);
return null;
}
}
if (isWorker) {
return importScripts(libraryUrl);
}
const scriptSource = await loadAsText(libraryUrl);
return loadLibraryFromString(scriptSource, libraryUrl);
}
function loadLibraryFromString(scriptSource, id) {
if (!isBrowser) {
const { requireFromString } = globalThis.loaders || {};
return requireFromString?.(scriptSource, id);
}
if (isWorker) {
eval.call(globalThis, scriptSource);
return null;
}
const script = document.createElement("script");
script.id = id;
try {
script.appendChild(document.createTextNode(scriptSource));
} catch (e) {
script.text = scriptSource;
}
document.body.appendChild(script);
return null;
}
async function loadAsArrayBuffer(url) {
const { readFileAsArrayBuffer } = globalThis.loaders || {};
if (isBrowser || !readFileAsArrayBuffer || url.startsWith("http")) {
const response = await fetch(url);
return await response.arrayBuffer();
}
return await readFileAsArrayBuffer(url);
}
async function loadAsText(url) {
const { readFileAsText } = globalThis.loaders || {};
if (isBrowser || !readFileAsText || url.startsWith("http")) {
const response = await fetch(url);
return await response.text();
}
return await readFileAsText(url);
}
// ../loader-utils/src/lib/worker-loader-utils/create-loader-worker.ts
var requestId = 0;
async function createLoaderWorker(loader) {
if (!await WorkerBody.inWorkerThread()) {
return;
}
WorkerBody.onmessage = async (type, payload) => {
switch (type) {
case "process":
try {
const { input, options = {}, context = {} } = payload;
const result = await parseData({
loader,
arrayBuffer: input,
options,
// @ts-expect-error fetch missing
context: {
...context,
_parse: parseOnMainThread
}
});
WorkerBody.postMessage("done", { result });
} catch (error) {
const message = error instanceof Error ? error.message : "";
WorkerBody.postMessage("error", { error: message });
}
break;
default:
}
};
}
function parseOnMainThread(arrayBuffer, loader, options, context) {
return new Promise((resolve, reject) => {
const id = requestId++;
const onMessage = (type, payload2) => {
if (payload2.id !== id) {
return;
}
switch (type) {
case "done":
WorkerBody.removeEventListener(onMessage);
resolve(payload2.result);
break;
case "error":
WorkerBody.removeEventListener(onMessage);
reject(payload2.error);
break;
default:
}
};
WorkerBody.addEventListener(onMessage);
const payload = { id, input: arrayBuffer, options };
WorkerBody.postMessage("process", payload);
});
}
async function parseData({
loader,
arrayBuffer,
options,
context
}) {
let data;
let parser;
if (loader.parseSync || loader.parse) {
data = arrayBuffer;
parser = loader.parseSync || loader.parse;
} else if (loader.parseTextSync) {
const textDecoder = new TextDecoder();
data = textDecoder.decode(arrayBuffer);
parser = loader.parseTextSync;
} else {
throw new Error(`Could not load data with ${loader.name} loader`);
}
options = {
...options,
modules: loader && loader.options && loader.options.modules || {},
worker: false
};
return await parser(data, { ...options }, context, loader);
}
// src/lib/utils/version.ts
var VERSION2 = true ? "4.3.2" : "latest";
// ../../node_modules/ktx-parse/dist/ktx-parse.modern.js
var KHR_SUPERCOMPRESSION_NONE = 0;
var KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT = 0;
var KHR_DF_VENDORID_KHRONOS = 0;
var KHR_DF_VERSION = 2;
var KHR_DF_MODEL_UNSPECIFIED = 0;
var KHR_DF_FLAG_ALPHA_STRAIGHT = 0;
var KHR_DF_TRANSFER_SRGB = 2;
var KHR_DF_PRIMARIES_BT709 = 1;
var KHR_DF_SAMPLE_DATATYPE_SIGNED = 64;
var VK_FORMAT_UNDEFINED = 0;
var KTX2Container = class {
constructor() {
this.vkFormat = VK_FORMAT_UNDEFINED;
this.typeSize = 1;
this.pixelWidth = 0;
this.pixelHeight = 0;
this.pixelDepth = 0;
this.layerCount = 0;
this.faceCount = 1;
this.supercompressionScheme = KHR_SUPERCOMPRESSION_NONE;
this.levels = [];
this.dataFormatDescriptor = [{
vendorId: KHR_DF_VENDORID_KHRONOS,
descriptorType: KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,
descriptorBlockSize: 0,
versionNumber: KHR_DF_VERSION,
colorModel: KHR_DF_MODEL_UNSPECIFIED,
colorPrimaries: KHR_DF_PRIMARIES_BT709,
transferFunction: KHR_DF_TRANSFER_SRGB,
flags: KHR_DF_FLAG_ALPHA_STRAIGHT,
texelBlockDimension: [0, 0, 0, 0],
bytesPlane: [0, 0, 0, 0, 0, 0, 0, 0],
samples: []
}];
this.keyValue = {};
this.globalData = null;
}
};
var BufferReader = class {
constructor(data, byteOffset, byteLength, littleEndian) {
this._dataView = void 0;
this._littleEndian = void 0;
this._offset = void 0;
this._dataView = new DataView(data.buffer, data.byteOffset + byteOffset, byteLength);
this._littleEndian = littleEndian;
this._offset = 0;
}
_nextUint8() {
const value = this._dataView.getUint8(this._offset);
this._offset += 1;
return value;
}
_nextUint16() {
const value = this._dataView.getUint16(this._offset, this._littleEndian);
this._offset += 2;
return value;
}
_nextUint32() {
const value = this._dataView.getUint32(this._offset, this._littleEndian);
this._offset += 4;
return value;
}
_nextUint64() {
const left = this._dataView.getUint32(this._offset, this._littleEndian);
const right = this._dataView.getUint32(this._offset + 4, this._littleEndian);
const value = left + 2 ** 32 * right;
this._offset += 8;
return value;
}
_nextInt32() {
const value = this._dataView.getInt32(this._offset, this._littleEndian);
this._offset += 4;
return value;
}
_nextUint8Array(len) {
const value = new Uint8Array(this._dataView.buffer, this._dataView.byteOffset + this._offset, len);
this._offset += len;
return value;
}
_skip(bytes) {
this._offset += bytes;
return this;
}
_scan(maxByteLength, term = 0) {
const byteOffset = this._offset;
let byteLength = 0;
while (this._dataView.getUint8(this._offset) !== term && byteLength < maxByteLength) {
byteLength++;
this._offset++;
}
if (byteLength < maxByteLength)
this._offset++;
return new Uint8Array(this._dataView.buffer, this._dataView.byteOffset + byteOffset, byteLength);
}
};
var NUL = new Uint8Array([0]);
var KTX2_ID = [
// '´', 'K', 'T', 'X', '2', '0', 'ª', '\r', '\n', '\x1A', '\n'
171,
75,
84,
88,
32,
50,
48,
187,
13,
10,
26,
10
];
function decodeText(buffer) {
return new TextDecoder().decode(buffer);
}
function read(data) {
const id = new Uint8Array(data.buffer, data.byteOffset, KTX2_ID.length);
if (id[0] !== KTX2_ID[0] || // '´'
id[1] !== KTX2_ID[1] || // 'K'
id[2] !== KTX2_ID[2] || // 'T'
id[3] !== KTX2_ID[3] || // 'X'
id[4] !== KTX2_ID[4] || // ' '
id[5] !== KTX2_ID[5] || // '2'
id[6] !== KTX2_ID[6] || // '0'
id[7] !== KTX2_ID[7] || // 'ª'
id[8] !== KTX2_ID[8] || // '\r'
id[9] !== KTX2_ID[9] || // '\n'
id[10] !== KTX2_ID[10] || // '\x1A'
id[11] !== KTX2_ID[11]) {
throw new Error("Missing KTX 2.0 identifier.");
}
const container = new KTX2Container();
const headerByteLength = 17 * Uint32Array.BYTES_PER_ELEMENT;
const headerReader = new BufferReader(data, KTX2_ID.length, headerByteLength, true);
container.vkFormat = headerReader._nextUint32();
container.typeSize = headerReader._nextUint32();
container.pixelWidth = headerReader._nextUint32();
container.pixelHeight = headerReader._nextUint32();
container.pixelDepth = headerReader._nextUint32();
container.layerCount = headerReader._nextUint32();
container.faceCount = headerReader._nextUint32();
const levelCount = headerReader._nextUint32();
container.supercompressionScheme = headerReader._nextUint32();
const dfdByteOffset = headerReader._nextUint32();
const dfdByteLength = headerReader._nextUint32();
const kvdByteOffset = headerReader._nextUint32();
const kvdByteLength = headerReader._nextUint32();
const sgdByteOffset = headerReader._nextUint64();
const sgdByteLength = headerReader._nextUint64();
const levelByteLength = levelCount * 3 * 8;
const levelReader = new BufferReader(data, KTX2_ID.length + headerByteLength, levelByteLength, true);
for (let i = 0; i < levelCount; i++) {
container.levels.push({
levelData: new Uint8Array(data.buffer, data.byteOffset + levelReader._nextUint64(), levelReader._nextUint64()),
uncompressedByteLength: levelReader._nextUint64()
});
}
const dfdReader = new BufferReader(data, dfdByteOffset, dfdByteLength, true);
const dfd = {
vendorId: dfdReader._skip(
4
/* totalSize */
)._nextUint16(),
descriptorType: dfdReader._nextUint16(),
versionNumber: dfdReader._nextUint16(),
descriptorBlockSize: dfdReader._nextUint16(),
colorModel: dfdReader._nextUint8(),
colorPrimaries: dfdReader._nextUint8(),
transferFunction: dfdReader._nextUint8(),
flags: dfdReader._nextUint8(),
texelBlockDimension: [dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8()],
bytesPlane: [dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8()],
samples: []
};
const sampleStart = 6;
const sampleWords = 4;
const numSamples = (dfd.descriptorBlockSize / 4 - sampleStart) / sampleWords;
for (let i = 0; i < numSamples; i++) {
const sample = {
bitOffset: dfdReader._nextUint16(),
bitLength: dfdReader._nextUint8(),
channelType: dfdReader._nextUint8(),
samplePosition: [dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8(), dfdReader._nextUint8()],
sampleLower: -Infinity,
sampleUpper: Infinity
};
if (sample.channelType & KHR_DF_SAMPLE_DATATYPE_SIGNED) {
sample.sampleLower = dfdReader._nextInt32();
sample.sampleUpper = dfdReader._nextInt32();
} else {
sample.sampleLower = dfdReader._nextUint32();
sample.sampleUpper = dfdReader._nextUint32();
}
dfd.samples[i] = sample;
}
container.dataFormatDescriptor.length = 0;
container.dataFormatDescriptor.push(dfd);
const kvdReader = new BufferReader(data, kvdByteOffset, kvdByteLength, true);
while (kvdReader._offset < kvdByteLength) {
const keyValueByteLength = kvdReader._nextUint32();
const keyData = kvdReader._scan(keyValueByteLength);
const key = decodeText(keyData);
container.keyValue[key] = kvdReader._nextUint8Array(keyValueByteLength - keyData.byteLength - 1);
if (key.match(/^ktx/i)) {
const text = decodeText(container.keyValue[key]);
container.keyValue[key] = text.substring(0, text.lastIndexOf("\0"));
}
const kvPadding = keyValueByteLength % 4 ? 4 - keyValueByteLength % 4 : 0;
kvdReader._skip(kvPadding);
}
if (sgdByteLength <= 0)
return container;
const sgdReader = new BufferReader(data, sgdByteOffset, sgdByteLength, true);
const endpointCount = sgdReader._nextUint16();
const selectorCount = sgdReader._nextUint16();
const endpointsByteLength = sgdReader._nextUint32();
const selectorsByteLength = sgdReader._nextUint32();
const tablesByteLength = sgdReader._nextUint32();
const extendedByteLength = sgdReader._nextUint32();
const imageDescs = [];
for (let i = 0; i < levelCount; i++) {
imageDescs.push({
imageFlags: sgdReader._nextUint32(),
rgbSliceByteOffset: sgdReader._nextUint32(),
rgbSliceByteLength: sgdReader._nextUint32(),
alphaSliceByteOffset: sgdReader._nextUint32(),
alphaSliceByteLength: sgdReader._nextUint32()
});
}
const endpointsByteOffset = sgdByteOffset + sgdReader._offset;
const selectorsByteOffset = endpointsByteOffset + endpointsByteLength;
const tablesByteOffset = selectorsByteOffset + selectorsByteLength;
const extendedByteOffset = tablesByteOffset + tablesByteLength;
const endpointsData = new Uint8Array(data.buffer, data.byteOffset + endpointsByteOffset, endpointsByteLength);
const selectorsData = new Uint8Array(data.buffer, data.byteOffset + selectorsByteOffset, selectorsByteLength);
const tablesData = new Uint8Array(data.buffer, data.byteOffset + tablesByteOffset, tablesByteLength);
const extendedData = new Uint8Array(data.buffer, data.byteOffset + extendedByteOffset, extendedByteLength);
container.globalData = {
endpointCount,
selectorCount,
imageDescs,
endpointsData,
selectorsData,
tablesData,
extendedData
};
return container;
}
// src/lib/utils/extract-mipmap-images.ts
function extractMipmapImages(data, options) {
const images = new Array(options.mipMapLevels);
let levelWidth = options.width;
let levelHeight = options.height;
let offset = 0;
for (let i = 0; i < options.mipMapLevels; ++i) {
const levelSize = getLevelSize(options, levelWidth, levelHeight, data, i);
const levelData = getLevelData(data, i, offset, levelSize);
images[i] = {
compressed: true,
format: options.internalFormat,
data: levelData,
width: levelWidth,
height: levelHeight,
levelSize
};
levelWidth = Math.max(1, levelWidth >> 1);
levelHeight = Math.max(1, levelHeight >> 1);
offset += levelSize;
}
return images;
}
function getLevelData(data, index, offset, levelSize) {
if (!Array.isArray(data)) {
return new Uint8Array(data.buffer, data.byteOffset + offset, levelSize);
}
return data[index].levelData;
}
function getLevelSize(options, levelWidth, levelHeight, data, index) {
if (!Array.isArray(data)) {
return options.sizeFunction(levelWidth, levelHeight);
}
return options.sizeFunction(data[index]);
}
// src/lib/gl-extensions.ts
var GL_EXTENSIONS_CONSTANTS = {
// WEBGL_compressed_texture_s3tc
COMPRESSED_RGB_S3TC_DXT1_EXT: 33776,
COMPRESSED_RGBA_S3TC_DXT1_EXT: 33777,
COMPRESSED_RGBA_S3TC_DXT3_EXT: 33778,
COMPRESSED_RGBA_S3TC_DXT5_EXT: 33779,
// WEBGL_compressed_texture_es3
COMPRESSED_R11_EAC: 37488,
COMPRESSED_SIGNED_R11_EAC: 37489,
COMPRESSED_RG11_EAC: 37490,
COMPRESSED_SIGNED_RG11_EAC: 37491,
COMPRESSED_RGB8_ETC2: 37492,
COMPRESSED_RGBA8_ETC2_EAC: 37493,
COMPRESSED_SRGB8_ETC2: 37494,
COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 37495,
COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 37496,
COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 37497,
// WEBGL_compressed_texture_pvrtc
COMPRESSED_RGB_PVRTC_4BPPV1_IMG: 35840,
COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: 35842,
COMPRESSED_RGB_PVRTC_2BPPV1_IMG: 35841,
COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: 35843,
// WEBGL_compressed_texture_etc1
COMPRESSED_RGB_ETC1_WEBGL: 36196,
// WEBGL_compressed_texture_atc
COMPRESSED_RGB_ATC_WEBGL: 35986,
COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL: 35987,
COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL: 34798,
// WEBGL_compressed_texture_astc
COMPRESSED_RGBA_ASTC_4X4_KHR: 37808,
COMPRESSED_RGBA_ASTC_5X4_KHR: 37809,
COMPRESSED_RGBA_ASTC_5X5_KHR: 37810,
COMPRESSED_RGBA_ASTC_6X5_KHR: 37811,
COMPRESSED_RGBA_ASTC_6X6_KHR: 37812,
COMPRESSED_RGBA_ASTC_8X5_KHR: 37813,
COMPRESSED_RGBA_ASTC_8X6_KHR: 37814,
COMPRESSED_RGBA_ASTC_8X8_KHR: 37815,
COMPRESSED_RGBA_ASTC_10X5_KHR: 37816,
COMPRESSED_RGBA_ASTC_10X6_KHR: 37817,
COMPRESSED_RGBA_ASTC_10X8_KHR: 37818,
COMPRESSED_RGBA_ASTC_10X10_KHR: 37819,
COMPRESSED_RGBA_ASTC_12X10_KHR: 37820,
COMPRESSED_RGBA_ASTC_12X12_KHR: 37821,
COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR: 37840,
COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR: 37841,
COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR: 37842,
COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR: 37843,
COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR: 37844,
COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR: 37845,
COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR: 37846,
COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR: 37847,
COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR: 37848,
COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR: 37849,
COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR: 37850,
COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR: 37851,
COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR: 37852,
COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR: 37853,
// EXT_texture_compression_rgtc
COMPRESSED_RED_RGTC1_EXT: 36283,
COMPRESSED_SIGNED_RED_RGTC1_EXT: 36284,
COMPRESSED_RED_GREEN_RGTC2_EXT: 36285,
COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 36286,
// WEBGL_compressed_texture_s3tc_srgb
COMPRESSED_SRGB_S3TC_DXT1_EXT: 35916,
COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 35917,
COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 35918,
COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 35919
};
// src/lib/utils/ktx-format-helper.ts
var VULKAN_TO_WEBGL_FORMAT_MAP = {
131: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT,
132: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB_S3TC_DXT1_EXT,
133: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT1_EXT,
134: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
135: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT3_EXT,
136: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
137: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT,
138: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
139: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RED_RGTC1_EXT,
140: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SIGNED_RED_RGTC1_EXT,
141: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RED_GREEN_RGTC2_EXT,
142: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT,
147: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB8_ETC2,
148: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ETC2,
149: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
150: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
151: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA8_ETC2_EAC,
152: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
153: GL_EXTENSIONS_CONSTANTS.COMPRESSED_R11_EAC,
154: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SIGNED_R11_EAC,
155: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RG11_EAC,
156: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SIGNED_RG11_EAC,
// @ts-ignore
157: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_4x4_KHR,
// @ts-ignore
158: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
// @ts-ignore
159: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_5x4_KHR,
// @ts-ignore
160: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR,
// @ts-ignore
161: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_5x5_KHR,
// @ts-ignore
162: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
// @ts-ignore
163: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_6x5_KHR,
// @ts-ignore
164: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
// @ts-ignore
165: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_6x6_KHR,
// @ts-ignore
166: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
// @ts-ignore
167: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8x5_KHR,
// @ts-ignore
168: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
// @ts-ignore
169: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8x6_KHR,
// @ts-ignore
170: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
// @ts-ignore
171: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8x8_KHR,
// @ts-ignore
172: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
// @ts-ignore
173: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x5_KHR,
// @ts-ignore
174: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
// @ts-ignore
175: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x6_KHR,
// @ts-ignore
176: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
// @ts-ignore
177: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x8_KHR,
// @ts-ignore
178: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
// @ts-ignore
179: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x10_KHR,
// @ts-ignore
180: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
// @ts-ignore
181: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_12x10_KHR,
// @ts-ignore
182: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
// @ts-ignore
183: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_12x12_KHR,
// @ts-ignore
184: GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
1000054e3: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,
1000054001: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
// @ts-ignore
1000066e3: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_4x4_KHR,
// @ts-ignore
1000066001: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_5x4_KHR,
// @ts-ignore
1000066002: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_5x5_KHR,
// @ts-ignore
1000066003: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_6x5_KHR,
// @ts-ignore
1000066004: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_6x6_KHR,
// @ts-ignore
1000066005: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8x5_KHR,
// @ts-ignore
1000066006: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8x6_KHR,
// @ts-ignore
1000066007: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8x8_KHR,
// @ts-ignore
1000066008: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x5_KHR,
// @ts-ignore
1000066009: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x6_KHR,
// @ts-ignore
1000066010: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x8_KHR,
// @ts-ignore
1000066011: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10x10_KHR,
// @ts-ignore
1000066012: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_12x10_KHR,
// @ts-ignore
1000066013: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_12x12_KHR
};
function mapVkFormatToWebGL(vkFormat) {
return VULKAN_TO_WEBGL_FORMAT_MAP[vkFormat];
}
// src/lib/parsers/parse-ktx.ts
var KTX2_ID2 = [
// '´', 'K', 'T', 'X', '2', '0', 'ª', '\r', '\n', '\x1A', '\n'
171,
75,
84,
88,
32,
50,
48,
187,
13,
10,
26,
10
];
function isKTX(data) {
const id = new Uint8Array(data);
const notKTX = id.byteLength < KTX2_ID2.length || id[0] !== KTX2_ID2[0] || // '´'
id[1] !== KTX2_ID2[1] || // 'K'
id[2] !== KTX2_ID2[2] || // 'T'
id[3] !== KTX2_ID2[3] || // 'X'
id[4] !== KTX2_ID2[4] || // ' '
id[5] !== KTX2_ID2[5] || // '2'
id[6] !== KTX2_ID2[6] || // '0'
id[7] !== KTX2_ID2[7] || // 'ª'
id[8] !== KTX2_ID2[8] || // '\r'
id[9] !== KTX2_ID2[9] || // '\n'
id[10] !== KTX2_ID2[10] || // '\x1A'
id[11] !== KTX2_ID2[11];
return !notKTX;
}
function parseKTX(arrayBuffer) {
const uint8Array = new Uint8Array(arrayBuffer);
const ktx = read(uint8Array);
const mipMapLevels = Math.max(1, ktx.levels.length);
const width = ktx.pixelWidth;
const height = ktx.pixelHeight;
const internalFormat = mapVkFormatToWebGL(ktx.vkFormat);
return extractMipmapImages(ktx.levels, {
mipMapLevels,
width,
height,
sizeFunction: (level) => level.uncompressedByteLength,
internalFormat
});
}
// src/lib/parsers/parse-dds.ts
var DDS_CONSTANTS = {
MAGIC_NUMBER: 542327876,
HEADER_LENGTH: 31,
MAGIC_NUMBER_INDEX: 0,
HEADER_SIZE_INDEX: 1,
HEADER_FLAGS_INDEX: 2,
HEADER_HEIGHT_INDEX: 3,
HEADER_WIDTH_INDEX: 4,
MIPMAPCOUNT_INDEX: 7,
HEADER_PF_FLAGS_INDEX: 20,
HEADER_PF_FOURCC_INDEX: 21,
DDSD_MIPMAPCOUNT: 131072,
DDPF_FOURCC: 4
};
var DDS_PIXEL_FORMATS = {
DXT1: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT,
DXT3: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT3_EXT,
DXT5: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT,
"ATC ": GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_ATC_WEBGL,
ATCA: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL,
ATCI: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL
};
var getATCLevelSize = getDxt1LevelSize;
var getATCALevelSize = getDxtXLevelSize;
var getATCILevelSize = getDxtXLevelSize;
var DDS_SIZE_FUNCTIONS = {
DXT1: getDxt1LevelSize,
DXT3: getDxtXLevelSize,
DXT5: getDxtXLevelSize,
"ATC ": getATCLevelSize,
ATCA: getATCALevelSize,
ATCI: getATCILevelSize
};
function isDDS(data) {
const header = new Uint32Array(data, 0, DDS_CONSTANTS.HEADER_LENGTH);
const magic = header[DDS_CONSTANTS.MAGIC_NUMBER_INDEX];
return magic === DDS_CONSTANTS.MAGIC_NUMBER;
}
function parseDDS(data) {
const header = new Int32Array(data, 0, DDS_CONSTANTS.HEADER_LENGTH);
const pixelFormatNumber = header[DDS_CONSTANTS.HEADER_PF_FOURCC_INDEX];
assert(
Boolean(header[DDS_CONSTANTS.HEADER_PF_FLAGS_INDEX] & DDS_CONSTANTS.DDPF_FOURCC),
"DDS: Unsupported format, must contain a FourCC code"
);
const fourCC = int32ToFourCC(pixelFormatNumber);
const internalFormat = DDS_PIXEL_FORMATS[fourCC];
const sizeFunction = DDS_SIZE_FUNCTIONS[fourCC];
assert(internalFormat && sizeFunction, `DDS: Unknown pixel format ${pixelFormatNumber}`);
let mipMapLevels = 1;
if (header[DDS_CONSTANTS.HEADER_FLAGS_INDEX] & DDS_CONSTANTS.DDSD_MIPMAPCOUNT) {
mipMapLevels = Math.max(1, header[DDS_CONSTANTS.MIPMAPCOUNT_INDEX]);
}
const width = header[DDS_CONSTANTS.HEADER_WIDTH_INDEX];
const height = header[DDS_CONSTANTS.HEADER_HEIGHT_INDEX];
const dataOffset = header[DDS_CONSTANTS.HEADER_SIZE_INDEX] + 4;
const image = new Uint8Array(data, dataOffset);
return extractMipmapImages(image, {
mipMapLevels,
width,
height,
sizeFunction,
internalFormat
});
}
function getDxt1LevelSize(width, height) {
return (width + 3 >> 2) * (height + 3 >> 2) * 8;
}
function getDxtXLevelSize(width, height) {
return (width + 3 >> 2) * (height + 3 >> 2) * 16;
}
function int32ToFourCC(value) {
return String.fromCharCode(
value & 255,
value >> 8 & 255,
value >> 16 & 255,
value >> 24 & 255
);
}
// src/lib/parsers/parse-pvr.ts
var PVR_CONSTANTS = {
MAGIC_NUMBER: 55727696,
MAGIC_NUMBER_EXTRA: 1347834371,
HEADER_LENGTH: 13,
HEADER_SIZE: 52,
MAGIC_NUMBER_INDEX: 0,
PIXEL_FORMAT_INDEX: 2,
COLOUR_SPACE_INDEX: 4,
HEIGHT_INDEX: 6,
WIDTH_INDEX: 7,
MIPMAPCOUNT_INDEX: 11,
METADATA_SIZE_INDEX: 12
};
var PVR_PIXEL_FORMATS = {
0: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_PVRTC_2BPPV1_IMG],
1: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG],
2: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_PVRTC_4BPPV1_IMG],
3: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG],
6: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_ETC1_WEBGL],
7: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT],
9: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT3_EXT],
11: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT],
22: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB8_ETC2],
23: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA8_ETC2_EAC],
24: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2],
25: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_R11_EAC],
26: [GL_EXTENSIONS_CONSTANTS.COMPRESSED_RG11_EAC],
27: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_4X4_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR
],
28: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_5X4_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR
],
29: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_5X5_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR
],
30: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_6X5_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR
],
31: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_6X6_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR
],
32: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8X5_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR
],
33: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8X6_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR
],
34: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_8X8_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR
],
35: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10X5_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR
],
36: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10X6_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR
],
37: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10X8_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR
],
38: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_10X10_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR
],
39: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_12X10_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR
],
40: [
GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_12X12_KHR,
GL_EXTENSIONS_CONSTANTS.COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR
]
};
var PVR_SIZE_FUNCTIONS = {
0: pvrtc2bppSize,
1: pvrtc2bppSize,
2: pvrtc4bppSize,
3: pvrtc4bppSize,
6: dxtEtcSmallSize,
7: dxtEtcSmallSize,
9: dxtEtcAstcBigSize,
11: dxtEtcAstcBigSize,
22: dxtEtcSmallSize,
23: dxtEtcAstcBigSize,
24: dxtEtcSmallSize,
25: dxtEtcSmallSize,
26: dxtEtcAstcBigSize,
27: dxtEtcAstcBigSize,
28: atc5x4Size,
29: atc5x5Size,
30: atc6x5Size,
31: atc6x6Size,
32: atc8x5Size,
33: atc8x6Size,
34: atc8x8Size,
35: atc10x5Size,
36: atc10x6Size,
37: atc10x8Size,
38: atc10x10Size,
39: atc12x10Size,
40: atc12x12Size
};
function isPVR(data) {
const header = new Uint32Array(data, 0, PVR_CONSTANTS.HEADER_LENGTH);
const version = header[PVR_CONSTANTS.MAGIC_NUMBER_INDEX];
return version === PVR_CONSTANTS.MAGIC_NUMBER || version === PVR_CONSTANTS.MAGIC_NUMBER_EXTRA;
}
function parsePVR(data) {
const header = new Uint32Array(data, 0, PVR_CONSTANTS.HEADER_LENGTH);
const pvrFormat = header[PVR_CONSTANTS.PIXEL_FORMAT_INDEX];
const colourSpace = header[PVR_CONSTANTS.COLOUR_SPACE_INDEX];
const pixelFormats = PVR_PIXEL_FORMATS[pvrFormat] || [];
const internalFormat = pixelFormats.length > 1 && colourSpace ? pixelFormats[1] : pixelFormats[0];
const sizeFunction = PVR_SIZE_FUNCTIONS[pvrFormat];
const mipMapLevels = header[PVR_CONSTANTS.MIPMAPCOUNT_INDEX];
const width = header[PVR_CONSTANTS.WIDTH_INDEX];
const height = header[PVR_CONSTANTS.HEIGHT_INDEX];
const dataOffset = PVR_CONSTANTS.HEADER_SIZE + header[PVR_CONSTANTS.METADATA_SIZE_INDEX];
const image = new Uint8Array(data, dataOffset);
return extractMipmapImages(image, {
mipMapLevels,
width,
height,
sizeFunction,
internalFormat
});
}
function pvrtc2bppSize(width, height) {
width = Math.max(width, 16);
height = Math.max(height, 8);
return width * height / 4;
}
function pvrtc4bppSize(width, height) {
width = Math.max(width, 8);
height = Math.max(height, 8);
return width * height / 2;
}
function dxtEtcSmallSize(width, height) {
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
}
function dxtEtcAstcBigSize(width, height) {
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
}
function atc5x4Size(width, height) {
return Math.floor((width + 4) / 5) * Math.floor((height + 3) / 4) * 16;
}
function atc5x5Size(width, height) {
return Math.floor((width + 4) / 5) * Math.floor((height + 4) / 5) * 16;
}
function atc6x5Size(width, height) {
return Math.floor((width + 5) / 6) * Math.floor((height + 4) / 5) * 16;
}
function atc6x6Size(width, height) {
return Math.floor((width + 5) / 6) * Math.floor((height + 5) / 6) * 16;
}
function atc8x5Size(width, height) {
return Math.floor((width + 7) / 8) * Math.floor((height + 4) / 5) * 16;
}
function atc8x6Size(width, height) {
return Math.floor((width + 7) / 8) * Math.floor((height + 5) / 6) * 16;
}
function atc8x8Size(width, height) {
return Math.floor((width + 7) / 8) * Math.floor((height + 7) / 8) * 16;
}
function atc10x5Size(width, height) {
return Math.floor((width + 9) / 10) * Math.floor((height + 4) / 5) * 16;
}
function atc10x6Size(width, height) {
return Math.floor((width + 9) / 10) * Math.floor((height + 5) / 6) * 16;
}
function atc10x8Size(width, height) {
return Math.floor((width + 9) / 10) * Math.floor((height + 7) / 8) * 16;
}
function atc10x10Size(width, height) {
return Math.floor((width + 9) / 10) * Math.floor((height + 9) / 10) * 16;
}
function atc12x10Size(width, height) {
return Math.floor((width + 11) / 12) * Math.floor((height + 9) / 10) * 16;
}
function atc12x12Size(width, height) {
return Math.floor((width + 11) / 12) * Math.floor((height + 11) / 12) * 16;
}
// src/lib/parsers/parse-compressed-texture.ts
function parseCompressedTexture(data) {
if (isKTX(data)) {
return parseKTX(data);
}
if (isDDS(data)) {
return parseDDS(data);
}
if (isPVR(data)) {
return parsePVR(data);
}
throw new Error("Texture container format not recognized");
}
// src/lib/parsers/basis-module-loader.ts
var BASIS_EXTERNAL_LIBRARIES = {
/** Basis transcoder, javascript wrapper part */
TRANSCODER: "basis_transcoder.js",
/** Basis transcoder, compiled web assembly part */
TRANSCODER_WASM: "basis_transcoder.wasm",
/** Basis encoder, javascript wrapper part */
ENCODER: "basis_encoder.js",
/** Basis encoder, compiled web assembly part */
ENCODER_WASM: "basis_encoder.wasm"
};
var loadBasisTranscoderPromise;
async function loadBasisTranscoderModule(options) {
registerJSModules(options.modules);
const basis = getJSModuleOrNull("basis");
if (basis) {
return basis;
}
loadBasisTranscoderPromise ||= loadBasisTranscoder(options);
return await loadBasisTranscoderPromise;
}
async function loadBasisTranscoder(options) {
let BASIS = null;
let wasmBinary = null;
[BASIS, wasmBinary] = await Promise.all([
await loadLibrary(BASIS_EXTERNAL_LIBRARIES.TRANSCODER, "textures", options),
await loadLibrary(BASIS_EXTERNAL_LIBRARIES.TRANSCODER_WASM, "textures", options)
]);
BASIS = BASIS || globalThis.BASIS;
return await initializeBasisTranscoderModule(BASIS, wasmBinary);
}
function initializeBasisTranscoderModule(BasisModule, wasmBinary) {
const options = {};
if (wasmBinary) {
options.wasmBinary = wasmBinary;
}
return new Promise((resolve) => {
BasisModule(options).then((module) => {
const { BasisFile, initializeBasis } = module;
initializeBasis();
resolve({ BasisFile });
});
});
}
var loadBasisEncoderPromise;
async function loadBasisEncoderModule(options) {
const modules = options.modules || {};
if (modules.basisEncoder) {
return modules.basisEncoder;
}
loadBasisEncoderPromise = loadBasisEncoderPromise || loadBasisEncoder(options);
return await loadBasisEncoderPromise;
}
async function loadBasisEncoder(options) {
let BASIS_ENCODER = null;
let wasmBinary = null;
[BASIS_ENCODER, wasmBinary] = await Promise.all([
await loadLibrary(BASIS_EXTERNAL_LIBRARIES.ENCODER, "textures", options),
await loadLibrary(BASIS_EXTERNAL_LIBRARIES.ENCODER_WASM, "textures", options)
]);
BASIS_ENCODER = BASIS_ENCODER || globalThis.BASIS;
return await initializeBasisEncoderModule(BASIS_ENCODER, wasmBinary);
}
function initializeBasisEncoderModule(BasisEncoderModule, wasmBinary) {
const options = {};
if (wasmBinary) {
options.wasmBinary = wasmBinary;
}
return new Promise((resolve) => {
BasisEncoderModule(options).then((module) => {
const { BasisFile, KTX2File, initializeBasis, BasisEncoder } = module;
initializeBasis();
resolve({ BasisFile, KTX2File, BasisEncoder });
});
});
}
// src/lib/utils/texture-formats.ts
var BROWSER_PREFIXES = ["", "WEBKIT_", "MOZ_"];
var WEBGL_EXTENSIONS = {
/* eslint-disable camelcase */
WEBGL_compressed_texture_s3tc: "dxt",
WEBGL_compressed_texture_s3tc_srgb: "dxt-srgb",
WEBGL_compressed_texture_etc1: "etc1",
WEBGL_compressed_texture_etc: "etc2",
WEBGL_compressed_texture_pvrtc: "pvrtc",
WEBGL_compressed_texture_atc: "atc",
WEBGL_compressed_texture_astc: "astc",
EXT_texture_compression_rgtc: "rgtc"
/* eslint-enable camelcase */
};
var formats = null;
function getSupportedGPUTextureFormats(gl) {
if (!formats) {
gl = gl || getWebGLContext() || void 0;
formats = /* @__PURE__ */ new Set();
for (const prefix of BROWSER_PREFIXES) {
for (const extension in WEBGL_EXTENSIONS) {
if (gl && gl.getExtension(`${prefix}${extension}`)) {
const gpuTextureFormat = WEBGL_EXTENSIONS[extension];
formats.add(gpuTextureFormat);
}
}
}
}
return formats;
}
function getWebGLContext() {
try {
const canvas = document.createElement("canvas");
return canvas.getContext("webgl");
} catch (error) {
return null;
}
}
// src/lib/parsers/parse-basis.ts
var OutputFormat = {
etc1: {
basisFormat: 0,
compressed: true,
format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_ETC1_WEBGL
},
etc2: { basisFormat: 1, compressed: true },
bc1: {
basisFormat: 2,
compressed: true,
format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT
},
bc3: {
basisFormat: 3,
compressed: true,
format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT
},
bc4: { basisFormat: 4, compressed: true },
bc5: { basisFormat: 5, compressed: true },
"bc7-m6-opaque-only": { basisFormat: 6, compressed: true },
"bc7-m5": { basisFormat: 7, compressed: true },
"pvrtc1-4-rgb": {
basisFormat: 8,
compressed: true,
format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
},
"pvrtc1-4-rgba": {
basisFormat: 9,
compressed: true,
format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
},
"astc-4x4": {
basisFormat: 10,
compressed: true,
format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_4X4_KHR
},
"atc-rgb": { basisFormat: 11, compressed: true },
"atc-rgba-interpolated-alpha": { basisFormat: 12, compressed: true },
rgba32: { basisFormat: 13, compressed: false },
rgb565: { basisFormat: 14, compressed: false },
bgr565: { basisFormat: 15, compressed: false },
rgba4444: { basisFormat: 16, compressed: false }
};
async function parseBasis(data, options) {
if (options.basis.containerFormat === "auto") {
if (isKTX(data)) {
const fileConstructors = await loadBasisEncoderModule(options);
return parseKTX2File(fileConstructors.KTX2File, data, options);
}
const { BasisFile } = await loadBasisTranscoderModule(options);
return parseBasisFile(BasisFile, data, options);
}
switch (options.basis.module) {
case "encoder":
const fileConstructors = await loadBasisEncoderModule(options);
switch (options.basis.containerFormat) {
case "ktx2":
return parseKTX2File(fileConstructors.KTX2File, data, options);
case "basis":
default:
return parseBasisFile(fileConstructors.BasisFile, data, options);
}
case "transcoder":
default:
const { BasisFile } = await loadBasisTranscoderModule(options);
return parseBasisFile(BasisFile, data, options);
}
}
function parseBasisFile(BasisFile, data, options) {
const basisFile = new BasisFile(new Uint8Array(data));
try {
if (!basisFile.startTranscoding()) {
throw new Error("Failed to start basis transcoding");
}
const imageCount = basisFile.getNumImages();
const images = [];
for (let imageIndex = 0; imageIndex < imageCount; imageIndex++) {
const levelsCount = basisFile.getNumLevels(imageIndex);
const levels = [];
for (let levelIndex = 0; levelIndex < levelsCount; levelIndex++) {
levels.push(transco