Using KHR_texture_basisu with Internal KTX 2.0 in glTF

This article explains how the KHR_texture_basisu extension references internally stored KTX 2.0 (.ktx2) textures within glTF and GLB containers. It covers the structural relationship between textures, images, buffer views, and binary buffers, detailing how the extension overrides standard image references to point directly to embedded binary data.

Extension Overview

The KHR_texture_basisu extension allows glTF assets to use Basis Universal textures wrapped in the KTX 2.0 container format. When textures are embedded internally—such as in a self-contained .glb binary file or via base64 data in a .gltf file—the reference bypasses external URIs and targets internal binary buffer views.

Structure of Internal References

Referencing an internal KTX 2.0 file requires coordinating four primary sections of the glTF JSON: textures, images, bufferViews, and buffers.

  1. The Texture Object (textures) The standard glTF texture entry delegates the source to the KHR_texture_basisu extension object instead of relying solely on the primary source property:
"textures": [
  {
    "sampler": 0,
    "extensions": {
      "KHR_texture_basisu": {
        "source": 0
      }
    }
  }
]

The source index defined inside extensions.KHR_texture_basisu points to the corresponding entry in the top-level images array.

  1. The Image Object (images) For internal storage, the target image object omits the uri attribute. Instead, it defines a bufferView index and explicitly specifies the image/ktx2 MIME type:
"images": [
  {
    "bufferView": 1,
    "mimeType": "image/ktx2"
  }
]

The mimeType property is mandatory when using bufferView so that runtime loaders know to parse the raw byte stream as a KTX 2.0 container.

  1. The Buffer View (bufferViews) The bufferView identifies the exact location and byte length of the KTX 2.0 file inside the binary buffer:
"bufferViews": [
  {
    "buffer": 0,
    "byteOffset": 1024,
    "byteLength": 204800
  }
]

The payload bounded by byteOffset and byteLength must be the complete, valid binary data of the KTX 2.0 file, starting with the 12-byte KTX 2.0 file identifier («KTX 20»\r\n\x1A\n).

Extension Declaration

To ensure parsers correctly process the texture references, the extension must be declared in the root extensionsUsed array:

"extensionsUsed": [
  "KHR_texture_basisu"
]

If the asset does not provide fallback textures (such as standard PNG or JPEG images assigned to the default source field in textures), KHR_texture_basisu must also be included in the extensionsRequired array.