three-stdlib
Version:
stand-alone library of threejs examples
1 lines • 9.16 kB
Source Map (JSON)
{"version":3,"file":"KTXLoader.cjs","sources":["../../src/loaders/KTXLoader.js"],"sourcesContent":["import { CompressedTextureLoader } from 'three'\n\n/**\n * for description see https://www.khronos.org/opengles/sdk/tools/KTX/\n * for file layout see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/\n *\n * ported from https://github.com/BabylonJS/Babylon.js/blob/master/src/Tools/babylon.khronosTextureContainer.ts\n */\n\nclass KTXLoader extends CompressedTextureLoader {\n constructor(manager) {\n super(manager)\n }\n\n parse(buffer, loadMipmaps) {\n const ktx = new KhronosTextureContainer(buffer, 1)\n\n return {\n mipmaps: ktx.mipmaps(loadMipmaps),\n width: ktx.pixelWidth,\n height: ktx.pixelHeight,\n format: ktx.glInternalFormat,\n isCubemap: ktx.numberOfFaces === 6,\n mipmapCount: ktx.numberOfMipmapLevels,\n }\n }\n}\n\nconst HEADER_LEN = 12 + 13 * 4 // identifier + header elements (not including key value meta-data pairs)\n// load types\nconst COMPRESSED_2D = 0 // uses a gl.compressedTexImage2D()\n//const COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()\n//const TEX_2D = 2; // uses a gl.texImage2D()\n//const TEX_3D = 3; // uses a gl.texImage3D()\n\nclass KhronosTextureContainer {\n /**\n * @param {ArrayBuffer} arrayBuffer- contents of the KTX container file\n * @param {number} facesExpected- should be either 1 or 6, based whether a cube texture or or\n * @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented\n * @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented\n */\n constructor(arrayBuffer, facesExpected /*, threeDExpected, textureArrayExpected */) {\n this.arrayBuffer = arrayBuffer\n\n // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:\n // '´', 'K', 'T', 'X', ' ', '1', '1', 'ª', '\\r', '\\n', '\\x1A', '\\n'\n // 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A\n const identifier = new Uint8Array(this.arrayBuffer, 0, 12)\n if (\n identifier[0] !== 0xab ||\n identifier[1] !== 0x4b ||\n identifier[2] !== 0x54 ||\n identifier[3] !== 0x58 ||\n identifier[4] !== 0x20 ||\n identifier[5] !== 0x31 ||\n identifier[6] !== 0x31 ||\n identifier[7] !== 0xbb ||\n identifier[8] !== 0x0d ||\n identifier[9] !== 0x0a ||\n identifier[10] !== 0x1a ||\n identifier[11] !== 0x0a\n ) {\n console.error('texture missing KTX identifier')\n return\n }\n\n // load the reset of the header in native 32 bit uint\n const dataSize = Uint32Array.BYTES_PER_ELEMENT\n const headerDataView = new DataView(this.arrayBuffer, 12, 13 * dataSize)\n const endianness = headerDataView.getUint32(0, true)\n const littleEndian = endianness === 0x04030201\n\n this.glType = headerDataView.getUint32(1 * dataSize, littleEndian) // must be 0 for compressed textures\n this.glTypeSize = headerDataView.getUint32(2 * dataSize, littleEndian) // must be 1 for compressed textures\n this.glFormat = headerDataView.getUint32(3 * dataSize, littleEndian) // must be 0 for compressed textures\n this.glInternalFormat = headerDataView.getUint32(4 * dataSize, littleEndian) // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)\n this.glBaseInternalFormat = headerDataView.getUint32(5 * dataSize, littleEndian) // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)\n this.pixelWidth = headerDataView.getUint32(6 * dataSize, littleEndian) // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)\n this.pixelHeight = headerDataView.getUint32(7 * dataSize, littleEndian) // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)\n this.pixelDepth = headerDataView.getUint32(8 * dataSize, littleEndian) // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)\n this.numberOfArrayElements = headerDataView.getUint32(9 * dataSize, littleEndian) // used for texture arrays\n this.numberOfFaces = headerDataView.getUint32(10 * dataSize, littleEndian) // used for cubemap textures, should either be 1 or 6\n this.numberOfMipmapLevels = headerDataView.getUint32(11 * dataSize, littleEndian) // number of levels; disregard possibility of 0 for compressed textures\n this.bytesOfKeyValueData = headerDataView.getUint32(12 * dataSize, littleEndian) // the amount of space after the header for meta-data\n\n // Make sure we have a compressed type. Not only reduces work, but probably better to let dev know they are not compressing.\n if (this.glType !== 0) {\n console.warn('only compressed formats currently supported')\n return\n } else {\n // value of zero is an indication to generate mipmaps @ runtime. Not usually allowed for compressed, so disregard.\n this.numberOfMipmapLevels = Math.max(1, this.numberOfMipmapLevels)\n }\n\n if (this.pixelHeight === 0 || this.pixelDepth !== 0) {\n console.warn('only 2D textures currently supported')\n return\n }\n\n if (this.numberOfArrayElements !== 0) {\n console.warn('texture arrays not currently supported')\n return\n }\n\n if (this.numberOfFaces !== facesExpected) {\n console.warn('number of faces expected' + facesExpected + ', but found ' + this.numberOfFaces)\n return\n }\n\n // we now have a completely validated file, so could use existence of loadType as success\n // would need to make this more elaborate & adjust checks above to support more than one load type\n this.loadType = COMPRESSED_2D\n }\n\n mipmaps(loadMipmaps) {\n const mipmaps = []\n\n // initialize width & height for level 1\n let dataOffset = HEADER_LEN + this.bytesOfKeyValueData\n let width = this.pixelWidth\n let height = this.pixelHeight\n const mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1\n\n for (let level = 0; level < mipmapCount; level++) {\n const imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0] // size per face, since not supporting array cubemaps\n dataOffset += 4 // size of the image + 4 for the imageSize field\n\n for (let face = 0; face < this.numberOfFaces; face++) {\n const byteArray = new Uint8Array(this.arrayBuffer, dataOffset, imageSize)\n\n mipmaps.push({ data: byteArray, width: width, height: height })\n\n dataOffset += imageSize\n dataOffset += 3 - ((imageSize + 3) % 4) // add padding for odd sized image\n }\n\n width = Math.max(1.0, width * 0.5)\n height = Math.max(1.0, height * 0.5)\n }\n\n return mipmaps\n }\n}\n\nexport { KTXLoader }\n"],"names":["CompressedTextureLoader"],"mappings":";;;AASA,MAAM,kBAAkBA,MAAAA,wBAAwB;AAAA,EAC9C,YAAY,SAAS;AACnB,UAAM,OAAO;AAAA,EACd;AAAA,EAED,MAAM,QAAQ,aAAa;AACzB,UAAM,MAAM,IAAI,wBAAwB,QAAQ,CAAC;AAEjD,WAAO;AAAA,MACL,SAAS,IAAI,QAAQ,WAAW;AAAA,MAChC,OAAO,IAAI;AAAA,MACX,QAAQ,IAAI;AAAA,MACZ,QAAQ,IAAI;AAAA,MACZ,WAAW,IAAI,kBAAkB;AAAA,MACjC,aAAa,IAAI;AAAA,IAClB;AAAA,EACF;AACH;AAEA,MAAM,aAAa,KAAK,KAAK;AAE7B,MAAM,gBAAgB;AAKtB,MAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5B,YAAY,aAAa,eAA2D;AAClF,SAAK,cAAc;AAKnB,UAAM,aAAa,IAAI,WAAW,KAAK,aAAa,GAAG,EAAE;AACzD,QACE,WAAW,CAAC,MAAM,OAClB,WAAW,CAAC,MAAM,MAClB,WAAW,CAAC,MAAM,MAClB,WAAW,CAAC,MAAM,MAClB,WAAW,CAAC,MAAM,MAClB,WAAW,CAAC,MAAM,MAClB,WAAW,CAAC,MAAM,MAClB,WAAW,CAAC,MAAM,OAClB,WAAW,CAAC,MAAM,MAClB,WAAW,CAAC,MAAM,MAClB,WAAW,EAAE,MAAM,MACnB,WAAW,EAAE,MAAM,IACnB;AACA,cAAQ,MAAM,gCAAgC;AAC9C;AAAA,IACD;AAGD,UAAM,WAAW,YAAY;AAC7B,UAAM,iBAAiB,IAAI,SAAS,KAAK,aAAa,IAAI,KAAK,QAAQ;AACvE,UAAM,aAAa,eAAe,UAAU,GAAG,IAAI;AACnD,UAAM,eAAe,eAAe;AAEpC,SAAK,SAAS,eAAe,UAAU,IAAI,UAAU,YAAY;AACjE,SAAK,aAAa,eAAe,UAAU,IAAI,UAAU,YAAY;AACrE,SAAK,WAAW,eAAe,UAAU,IAAI,UAAU,YAAY;AACnE,SAAK,mBAAmB,eAAe,UAAU,IAAI,UAAU,YAAY;AAC3E,SAAK,uBAAuB,eAAe,UAAU,IAAI,UAAU,YAAY;AAC/E,SAAK,aAAa,eAAe,UAAU,IAAI,UAAU,YAAY;AACrE,SAAK,cAAc,eAAe,UAAU,IAAI,UAAU,YAAY;AACtE,SAAK,aAAa,eAAe,UAAU,IAAI,UAAU,YAAY;AACrE,SAAK,wBAAwB,eAAe,UAAU,IAAI,UAAU,YAAY;AAChF,SAAK,gBAAgB,eAAe,UAAU,KAAK,UAAU,YAAY;AACzE,SAAK,uBAAuB,eAAe,UAAU,KAAK,UAAU,YAAY;AAChF,SAAK,sBAAsB,eAAe,UAAU,KAAK,UAAU,YAAY;AAG/E,QAAI,KAAK,WAAW,GAAG;AACrB,cAAQ,KAAK,6CAA6C;AAC1D;AAAA,IACN,OAAW;AAEL,WAAK,uBAAuB,KAAK,IAAI,GAAG,KAAK,oBAAoB;AAAA,IAClE;AAED,QAAI,KAAK,gBAAgB,KAAK,KAAK,eAAe,GAAG;AACnD,cAAQ,KAAK,sCAAsC;AACnD;AAAA,IACD;AAED,QAAI,KAAK,0BAA0B,GAAG;AACpC,cAAQ,KAAK,wCAAwC;AACrD;AAAA,IACD;AAED,QAAI,KAAK,kBAAkB,eAAe;AACxC,cAAQ,KAAK,6BAA6B,gBAAgB,iBAAiB,KAAK,aAAa;AAC7F;AAAA,IACD;AAID,SAAK,WAAW;AAAA,EACjB;AAAA,EAED,QAAQ,aAAa;AACnB,UAAM,UAAU,CAAE;AAGlB,QAAI,aAAa,aAAa,KAAK;AACnC,QAAI,QAAQ,KAAK;AACjB,QAAI,SAAS,KAAK;AAClB,UAAM,cAAc,cAAc,KAAK,uBAAuB;AAE9D,aAAS,QAAQ,GAAG,QAAQ,aAAa,SAAS;AAChD,YAAM,YAAY,IAAI,WAAW,KAAK,aAAa,YAAY,CAAC,EAAE,CAAC;AACnE,oBAAc;AAEd,eAAS,OAAO,GAAG,OAAO,KAAK,eAAe,QAAQ;AACpD,cAAM,YAAY,IAAI,WAAW,KAAK,aAAa,YAAY,SAAS;AAExE,gBAAQ,KAAK,EAAE,MAAM,WAAW,OAAc,QAAgB;AAE9D,sBAAc;AACd,sBAAc,KAAM,YAAY,KAAK;AAAA,MACtC;AAED,cAAQ,KAAK,IAAI,GAAK,QAAQ,GAAG;AACjC,eAAS,KAAK,IAAI,GAAK,SAAS,GAAG;AAAA,IACpC;AAED,WAAO;AAAA,EACR;AACH;;"}