@ibltools/ibla-loader
v0.2.0
Published
Parser-only TypeScript loader for .ibla assets.
Downloads
70
Maintainers
Readme
@ibltools/ibla-loader
@ibltools/ibla-loader is the parser-only TypeScript loader for .ibla assets.
This package exposes the public v1 parsing contract for applications and renderer-specific integrations.
The shared .ibla container contract is defined in the repository format specification:
https://github.com/shawn0326/ibl-baker/blob/main/docs/format-spec.md
Installation
npm install @ibltools/ibla-loaderUsage
import { parseIBLA } from "@ibltools/ibla-loader";
const parsed = parseIBLA(buffer);
console.log(parsed.manifest.faceCount, parsed.manifest.encoding);Scope
The TypeScript loader is parser-only in v1.
Its responsibility is limited to:
- parsing the
.iblacontainer - validating basic format structure while parsing
- exposing chunk payloads as encoded bytes with derived metadata
It does not:
- decode PNG payloads
- decode RGBD into HDR float data
- prepare WebGL or WebGPU upload objects
- create engine-specific runtime textures
Those concerns are left to the application or renderer integration layer.
For KTX2 assets produced by the CLI (--output-format ktx2), use the sibling
@ibltools/ktx2-loader package. This package does not handle .ktx2 files.
Core Model
One parsed .ibla file maps to one texture payload set.
faceCount = 1means a 2D texture withmipCountimagesfaceCount = 6means a cubemap withmipCount * 6images- chunk identity is reconstructed from deterministic ordering, not stored explicitly in the file
- chunk payload bytes remain encoded according to manifest metadata
In the current CLI workflow, .ibla is used for specular and irradiance outputs.
BRDF LUT is emitted as a direct .png and does not go through the .ibla loader.
Public API
export function parseIBLA(buffer: ArrayBuffer | Uint8Array): ParsedIBLAparseIBLA is a fail-fast API.
In v1 it throws IBLAParseError when the container is invalid or unsupported.
Public Types
export type FaceName = 'px' | 'nx' | 'py' | 'ny' | 'pz' | 'nz'
export type BakeQuality = 'low' | 'medium' | 'high'
export type IBLAParseErrorCode =
| 'INVALID_HEADER'
| 'UNSUPPORTED_VERSION'
| 'INVALID_MANIFEST'
| 'UNSUPPORTED_FACE_COUNT'
| 'INVALID_CUBEMAP_DIMENSIONS'
| 'INVALID_CHUNK_TABLE_LENGTH'
| 'CHUNK_RANGE_OUT_OF_BOUNDS'
export class IBLAParseError extends Error {
readonly code: IBLAParseErrorCode
}
export interface ParsedIBLA {
header: {
version: number
flags: number
}
manifest: {
generator: string
generatorVersion: string
encoding: 'rgbd-srgb' | 'srgb' | 'linear'
container: 'png'
width: number
height: number
mipCount: number
faceCount: 1 | 6
build: {
rotation: number
samples: number
quality: BakeQuality
sourceFormat: 'hdr' | 'exr' | 'png' | 'jpg' | 'jpeg' | 'unknown'
}
}
chunks: ParsedChunk[]
}
export interface ParsedChunk {
index: number
mipLevel: number
face: FaceName | null
width: number
height: number
byteOffset: number
byteLength: number
encodedBytes: Uint8Array
}parseIBLA(buffer) Semantics
parseIBLA must:
- validate header magic and version
- read manifest metadata
- reconstruct chunk identity from
mipCount,faceCount, and deterministic ordering - derive each chunk's
widthandheightfrom manifestwidth,height, andmipLevel - reconstruct
byteOffsetfrom chunk-tablebyteLengthprefix sums - expose each chunk as encoded bytes plus derived chunk metadata
parseIBLA must throw IBLAParseError when:
- the header is invalid
- the manifest is missing required fields
- the manifest contains unsupported enum values
faceCountis not supported by the format- cubemap dimensions are invalid for the format
- the chunk table length is inconsistent with manifest-declared topology
- chunk payload ranges exceed or do not exactly cover the binary section
Recommended v1 error-code mapping:
- invalid header bytes or magic ->
INVALID_HEADER - unsupported format version ->
UNSUPPORTED_VERSION - malformed JSON, missing required fields, or unsupported manifest enums ->
INVALID_MANIFEST - unsupported
faceCount->UNSUPPORTED_FACE_COUNT - invalid cubemap
width/heightrelationship ->INVALID_CUBEMAP_DIMENSIONS - inconsistent chunk-table byte length or entry count ->
INVALID_CHUNK_TABLE_LENGTH - payload byte ranges exceeding or not exactly covering the binary section ->
CHUNK_RANGE_OUT_OF_BOUNDS
Dimension derivation in v1:
For 2D textures:
chunkWidth = max(1, floor(width / 2^mipLevel))
chunkHeight = max(1, floor(height / 2^mipLevel))For cubemaps:
chunkWidth = chunkHeight = max(1, floor(width / 2^mipLevel))Equivalently, readers may use:
dimensionAtMip(base, mipLevel) = max(1, base >> mipLevel)Parser Output Contract
The parser output is intentionally still encoded.
That means:
- PNG chunks remain PNG bytes
manifest.encodingremains metadata, not a decode stepbuild.sourceFormatremains provenance metadata, not a parse input- no promise is made about returning upload-ready pixel buffers
Applications can build on top of ParsedIBLA to implement:
- PNG decode helpers
- RGBD-to-float conversion
- WebGL upload preparation
- WebGPU upload preparation
- engine-specific runtime adapters
Those higher-level helpers can derive texture topology directly from manifest metadata:
faceCount = 1means a 2D texture withmipCountimagesfaceCount = 6means a cubemap withmipCount * 6images- cubemap face order remains the fixed v1 sequence
px, nx, py, ny, pz, nz
Reference decode code for encoding = "rgbd-srgb":
vec3 decodeRgbdSrgb(vec4 encodedSample) {
vec3 linearRgb = sRGBToLinear(encodedSample.rgb);
return linearRgb / encodedSample.a;
}The exact helper name is not fixed. What matters for v1 is the decode contract:
- apply sRGB-to-linear conversion to sampled RGB
- keep alpha as the linear
Dvalue - reconstruct linear HDR values as
rgb / D
If a runtime uploads the payload into an sRGB texture format and relies on hardware sRGB sampling, the explicit sRGBToLinear(encodedSample.rgb) step can be omitted because the sampled RGB values are already linearized.
Reference consumption contract for the other v1 encodings:
srgb- after PNG decode, payload RGB data must be treated as sRGB color data
- higher-level helpers may keep the decoded bytes in sRGB form or convert them to linear values depending on their output contract
linear- after PNG decode, payload values must be treated as linear data
- higher-level helpers must not apply sRGB-to-linear conversion implicitly
Defaults and Constraints
- v1 only supports
.iblaparsing, not direct PNG/LUT handling - v1 only supports
encoding = rgbd-srgb | srgb | linear - v1 only supports
container = png - v1 only supports
build.quality = low | medium | high - v1 chunk ordering is
mipLevelascending, then fixed cubemap face order when applicable
