UNPKG

@pixi/compressed-textures

Version:

Loaders for compressed texture file formats

110 lines (109 loc) 4.87 kB
import { INTERNAL_FORMAT_TO_BYTES_PER_PIXEL } from "../const.mjs"; import { BlobResource } from "./BlobResource.mjs"; class CompressedTextureResource extends BlobResource { /** * @param source - the buffer/URL holding the compressed texture data * @param options * @param {PIXI.INTERNAL_FORMATS} options.format - the compression format * @param {number} options.width - the image width in pixels. * @param {number} options.height - the image height in pixels. * @param {number} [options.level=1] - the mipmap levels stored in the compressed texture, including level 0. * @param {number} [options.levelBuffers] - the buffers for each mipmap level. `CompressedTextureResource` can allows you * to pass `null` for `source`, for cases where each level is stored in non-contiguous memory. */ constructor(source, options) { super(source, options), this.format = options.format, this.levels = options.levels || 1, this._width = options.width, this._height = options.height, this._extension = CompressedTextureResource._formatToExtension(this.format), (options.levelBuffers || this.buffer) && (this._levelBuffers = options.levelBuffers || CompressedTextureResource._createLevelBuffers( source instanceof Uint8Array ? source : this.buffer.uint8View, this.format, this.levels, 4, 4, // PVRTC has 8x4 blocks in 2bpp mode this.width, this.height )); } /** * @override * @param renderer - A reference to the current renderer * @param _texture - the texture * @param _glTexture - texture instance for this webgl context */ upload(renderer, _texture, _glTexture) { const gl = renderer.gl; if (!renderer.context.extensions[this._extension]) throw new Error(`${this._extension} textures are not supported on the current machine`); if (!this._levelBuffers) return !1; gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); for (let i = 0, j = this.levels; i < j; i++) { const { levelID, levelWidth, levelHeight, levelBuffer } = this._levelBuffers[i]; gl.compressedTexImage2D(gl.TEXTURE_2D, levelID, this.format, levelWidth, levelHeight, 0, levelBuffer); } return !0; } /** @protected */ onBlobLoaded() { this._levelBuffers = CompressedTextureResource._createLevelBuffers( this.buffer.uint8View, this.format, this.levels, 4, 4, // PVRTC has 8x4 blocks in 2bpp mode this.width, this.height ); } /** * Returns the key (to ContextSystem#extensions) for the WebGL extension supporting the compression format * @private * @param format - the compression format to get the extension for. */ static _formatToExtension(format) { if (format >= 33776 && format <= 33779) return "s3tc"; if (format >= 35916 && format <= 35919) return "s3tc_sRGB"; if (format >= 37488 && format <= 37497) return "etc"; if (format >= 35840 && format <= 35843) return "pvrtc"; if (format === 36196) return "etc1"; if (format === 35986 || format === 35987 || format === 34798) return "atc"; if (format >= 36492 && format <= 36495) return "bptc"; if (format === 37808) return "astc"; throw new Error(`Invalid (compressed) texture format given: ${format}`); } /** * Pre-creates buffer views for each mipmap level * @private * @param buffer - * @param format - compression formats * @param levels - mipmap levels * @param blockWidth - * @param blockHeight - * @param imageWidth - width of the image in pixels * @param imageHeight - height of the image in pixels */ static _createLevelBuffers(buffer, format, levels, blockWidth, blockHeight, imageWidth, imageHeight) { const buffers = new Array(levels); let offset = buffer.byteOffset, levelWidth = imageWidth, levelHeight = imageHeight, alignedLevelWidth = levelWidth + blockWidth - 1 & ~(blockWidth - 1), alignedLevelHeight = levelHeight + blockHeight - 1 & ~(blockHeight - 1), levelSize = alignedLevelWidth * alignedLevelHeight * INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[format]; for (let i = 0; i < levels; i++) buffers[i] = { levelID: i, levelWidth: levels > 1 ? levelWidth : alignedLevelWidth, levelHeight: levels > 1 ? levelHeight : alignedLevelHeight, levelBuffer: new Uint8Array(buffer.buffer, offset, levelSize) }, offset += levelSize, levelWidth = levelWidth >> 1 || 1, levelHeight = levelHeight >> 1 || 1, alignedLevelWidth = levelWidth + blockWidth - 1 & ~(blockWidth - 1), alignedLevelHeight = levelHeight + blockHeight - 1 & ~(blockHeight - 1), levelSize = alignedLevelWidth * alignedLevelHeight * INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[format]; return buffers; } } export { CompressedTextureResource }; //# sourceMappingURL=CompressedTextureResource.mjs.map