playcanvas
Version:
PlayCanvas WebGL game engine
131 lines (128 loc) • 5.19 kB
JavaScript
import { Debug } from '../../../core/debug.js';
import { ReadStream } from '../../../core/read-stream.js';
import { pixelFormatLinearToGamma, ADDRESS_CLAMP_TO_EDGE, ADDRESS_REPEAT, TEXHINT_ASSET } from '../../../platform/graphics/constants.js';
import { Texture } from '../../../platform/graphics/texture.js';
import { Asset } from '../../asset/asset.js';
import { basisTranscode } from '../../handlers/basis.js';
import { TextureParser } from './texture.js';
function _extends() {
_extends = Object.assign || function(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i];
for(var key in source){
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
var KHRConstants = {
KHR_DF_MODEL_UASTC: 166
};
/**
* Texture parser for ktx2 files.
*/ class Ktx2Parser extends TextureParser {
load(url, callback, asset) {
Asset.fetchArrayBuffer(url.load, (err, result)=>{
if (err) {
callback(err, result);
} else {
this.parse(result, url, callback, asset);
}
}, asset, this.maxRetries);
}
open(url, data, device, textureOptions) {
if (textureOptions === void 0) textureOptions = {};
var format = textureOptions.srgb ? pixelFormatLinearToGamma(data.format) : data.format;
var texture = new Texture(device, _extends({
name: url,
profilerHint: TEXHINT_ASSET,
addressU: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,
addressV: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,
width: data.width,
height: data.height,
format: format,
cubemap: data.cubemap,
levels: data.levels
}, textureOptions));
texture.upload();
return texture;
}
parse(arraybuffer, url, callback, asset) {
var rs = new ReadStream(arraybuffer);
// check magic header bits: '«', 'K', 'T', 'X', ' ', '2', '0', '»', '\r', '\n', '\x1A', '\n'\
var magic = [
rs.readU32be(),
rs.readU32be(),
rs.readU32be()
];
if (magic[0] !== 0xAB4B5458 || magic[1] !== 0x203230BB || magic[2] !== 0x0D0A1A0A) {
Debug.warn('Invalid definition header found in KTX2 file. Expected 0xAB4B5458, 0x203131BB, 0x0D0A1A0A');
return null;
}
// unpack header
var header = {
vkFormat: rs.readU32(),
typeSize: rs.readU32(),
pixelWidth: rs.readU32(),
pixelHeight: rs.readU32(),
pixelDepth: rs.readU32(),
layerCount: rs.readU32(),
faceCount: rs.readU32(),
levelCount: rs.readU32(),
supercompressionScheme: rs.readU32()
};
// unpack index
var index = {
dfdByteOffset: rs.readU32(),
dfdByteLength: rs.readU32(),
kvdByteOffset: rs.readU32(),
kvdByteLength: rs.readU32(),
sgdByteOffset: rs.readU64(),
sgdByteLength: rs.readU64()
};
// unpack levels
var levels = [];
for(var i = 0; i < Math.max(1, header.levelCount); ++i){
levels.push({
byteOffset: rs.readU64(),
byteLength: rs.readU64(),
uncompressedByteLength: rs.readU64()
});
}
// unpack data format descriptor
var dfdTotalSize = rs.readU32();
if (dfdTotalSize !== index.kvdByteOffset - index.dfdByteOffset) {
Debug.warn('Invalid file data encountered.');
return null;
}
rs.skip(8);
var colorModel = rs.readU8();
rs.skip(index.dfdByteLength - 9);
// skip key/value pairs
rs.skip(index.kvdByteLength);
if (header.supercompressionScheme === 1 || colorModel === KHRConstants.KHR_DF_MODEL_UASTC) {
var _asset_file_variants_basis, _asset_file_variants, _asset_file;
// assume for now all super compressed images are basis
var basisModuleFound = basisTranscode(this.device, url.load, arraybuffer, callback, {
isGGGR: ((asset == null ? void 0 : (_asset_file = asset.file) == null ? void 0 : (_asset_file_variants = _asset_file.variants) == null ? void 0 : (_asset_file_variants_basis = _asset_file_variants.basis) == null ? void 0 : _asset_file_variants_basis.opt) & 8) !== 0,
isKTX2: true
});
if (!basisModuleFound) {
callback("Basis module not found. Asset [" + asset.name + "](" + asset.getFileUrl() + ") basis texture variant will not be loaded.");
}
} else {
// TODO: load non-supercompressed formats
callback('unsupported KTX2 pixel format');
}
}
constructor(registry, device){
super();
this.maxRetries = 0;
this.device = device;
}
}
export { Ktx2Parser };