@threenative/assets API
Every public function and class in @threenative/assets. Content-addressed asset compile step for ThreeNative games.
On this page
Generated from the engine's capability manifest: 27 functions. Each entry is the exported signature, what it is for, and a working example. Start with the package overview.
atlasManifest
Pack texture sources into deterministic atlas pages and answer each source's UV transform, so a build can stop giving every material a private texture.
function atlasManifest(result: IAtlasResult): stringUse it to
- a merge found nothing to collapse because each imported part owns its own texture
- cut the material count of an imported model pack at build time
Example
const { pages, transforms, excluded } = packAtlas(sources, { pageSize: 4096, padding: 4 });Good to know
- deterministic by construction: the packing order is derived from the sources, never from directory order, so a rebuild places every source at the same pixel
- a source the scene samples outside [0, 1] is excluded and reported, never clamped onto a shared page
- page bounds hold regardless of input order; padding keeps a mip tap from reaching the next source
audioPass
Conditions a game's audio and proves the conditioning did not destroy it.
function audioPass(options: IAudioPassOptions =Use it to
- make an ambience bed loop without an audible click
- halve what a positional sound effect costs a device's memory
- stop an audio asset shipping silent on desktop, Android and iOS
Example
const pass = audioPass({ overrides: [{ glob: "audio/*-bed.ogg", loop: true }] });Good to know
- a clip declared a loop has its seam measured on the decoded output bytes and fails the build when it exceeds the threshold; the assertion cannot be declared away
- which clips loop, which are positional, and what a clip is for are declared per glob and never inferred from a filename
- sources must be RIFF/WAVE or Ogg Vorbis, which is exactly what every native target decodes; an MP3 fails the bake
censusDocument
Census one glTF document, or a directory of them: the merge buckets a scene has now, and the buckets it would have once its atlasable textures shared pages.
function censusDocument( model: string, document: Document, pageSize = 4_096, ): IContentCensusUse it to
- find out whether "fewer objects" is available in this content before promising it
- explain why a per-material merge collapsed nothing
Example
pnpm census:content public/assetsGood to know
- reads geometry and materials only: no GPU, no runtime, no game
- a texture whose size the document does not state is reported excluded, never assumed square
- a model the reader cannot open is named, never skipped silently
compileAssets
Compiles a project's source assets into content-addressed runtime files and a manifest.
async function compileAssets( options: IAssetCompileOptions =Use it to
- compile game assets before a web or native build
- optimize textures for the GPU
- produce a manifest for runtime asset loading
Example
const result = await compileAssets({ source: "assets", output: "public" });Good to know
- source and output directories must be disjoint; a pass failure stops the build with the asset path
dedupeMaterials
Collapse materials that became identical once their textures shared an atlas page, and count the buckets a merge would find — before and after — so the promise can be checked rather than made.
function dedupeMaterials(materials: readonly IMaterialState[]):Use it to
- decide whether fewer objects is actually available in this content
- report why a per-material merge collapsed nothing
Example
pnpm census:content public/assetsGood to know
- the signature ignores the material name, which is what made every imported part a singleton, and keeps materials apart on any field it does not understand
- the census reads geometry and materials only: no GPU, no runtime, no game
formatAudioSizes
Formats audio conditioning measurements for a build report.
function formatAudioSizes(rows: readonly IAudioRow[]): readonly string[]Use it to
- see what audio conditioning did to a clip's wire and decoded size
- read the loop seam and cross-fade a build measured
Example
const lines = formatAudioSizes(audioRows);Good to know
- an empty row list produces no report lines
formatHealthReport
Formats asset health findings and their summary for human-readable output.
function formatHealthReport(report: IAssetHealthReport): readonly string[]Use it to
- print asset size, license, and target findings after compilation
- show why an asset health check is warning or failing
Example
const lines = formatHealthReport(report);Good to know
- the returned lines describe findings; target enforcement happens in runHealthReport
formatModelSizes
Formats model byte, geometry, and embedded-texture measurements for a build report.
function formatModelSizes(rows: readonly IModelSizeRow[]): readonly string[]Use it to
- inspect how model optimization changed file and GPU sizes
- print model compression results after an asset build
Example
const lines = formatModelSizes(modelRows);Good to know
- rows must use bytes before and after from the same compiled input
formatPassCosts
Formats per-pass wall-clock costs for a build report.
function formatPassCosts(rows: readonly IPassCostRow[]): readonly string[]Use it to
- see which asset pass owns the wall clock after a bake
- compare pass costs between two builds before optimizing the pipeline
Example
const lines = formatPassCosts(result.passCosts);Good to know
- one row per pass in registry order, per-asset rows sorted by logical path
formatTextureSizes
Formats standalone texture byte measurements for a build report.
function formatTextureSizes(rows: readonly ITextureSizeRow[]): readonly string[]Use it to
- inspect texture compression savings
- print which codec a compiled texture uses
Example
const lines = formatTextureSizes(textureRows);Good to know
- an empty row list produces no report lines
lightmapPass
Generates lightmap UVs and bakes a static GLB's lightmap atlas.
function lightmapPass(options: ILightmapPassOptions): IAssetPassUse it to
- add baked static lighting to a model
- generate TEXCOORD_1 data for a lightmapped scene
Example
const pass = lightmapPass({ atlasSize: 1024, padding: 2 });Good to know
- the input must be a static self-contained GLB with at least one punctual light
materialSignature
Collapse materials that became identical once their textures shared an atlas page, and count the buckets a merge would find — before and after — so the promise can be checked rather than made.
function materialSignature(material: IMaterialState): stringUse it to
- decide whether fewer objects is actually available in this content
- report why a per-material merge collapsed nothing
Example
pnpm census:content public/assetsGood to know
- the signature ignores the material name, which is what made every imported part a singleton, and keeps materials apart on any field it does not understand
- the census reads geometry and materials only: no GPU, no runtime, no game
materialStateOf
Census one glTF document, or a directory of them: the merge buckets a scene has now, and the buckets it would have once its atlasable textures shared pages.
function materialStateOf(material: Material): IMaterialStateUse it to
- find out whether "fewer objects" is available in this content before promising it
- explain why a per-material merge collapsed nothing
Example
pnpm census:content public/assetsGood to know
- reads geometry and materials only: no GPU, no runtime, no game
- a texture whose size the document does not state is reported excluded, never assumed square
- a model the reader cannot open is named, never skipped silently
modelPass
Optimizes self-contained GLB models through the configured geometry and embedded-texture passes.
function modelPass(options: IModelPassOptions =Use it to
- reduce a model's download and GPU footprint
- optimize a GLB before shipping it with a game
Example
const pass = modelPass({ simplify: { ratio: 0.5 } });Good to know
- the pass self-verifies reachable geometry, animation, bounds, and embedded texture bindings before returning output
packAtlas
Pack texture sources into deterministic atlas pages and answer each source's UV transform, so a build can stop giving every material a private texture.
function packAtlas( sources: readonly IAtlasSource[], options: IAtlasOptions =Use it to
- a merge found nothing to collapse because each imported part owns its own texture
- cut the material count of an imported model pack at build time
Example
const { pages, transforms, excluded } = packAtlas(sources, { pageSize: 4096, padding: 4 });Good to know
- deterministic by construction: the packing order is derived from the sources, never from directory order, so a rebuild places every source at the same pixel
- a source the scene samples outside [0, 1] is excluded and reported, never clamped onto a shared page
- page bounds hold regardless of input order; padding keeps a mip tap from reaching the next source
parseAudioConfig
Validates a game's declared assets.audio block, the one place its keys and ranges are checked.
function parseAudioConfig(raw: unknown): IAudioPassOptions | undefinedUse it to
- validate a threenative.config.ts audio block before compiling assets
- ship audio exactly as committed without conditioning it
Example
const options = parseAudioConfig({ overrides: [{ glob: "audio/*.ogg", conditioning: "none" }] });Good to know
- returns undefined for
"none", which drops the audio pass; an absent block returns the defaults - throws TN_ASSETS_CONFIG_INVALID or TN_ASSETS_CONFIG_UNKNOWN_KEY rather than dropping a key it does not know
parsePng
Reads dimensions and alpha metadata from a PNG signature and IHDR header.
function parsePng(value: Buffer): IPngInfo | undefinedUse it to
- inspect a PNG before choosing a texture codec
- read source texture dimensions in an asset health check
Example
const png = parsePng(bytes); if (png !== undefined) console.log(png.width, png.height);Good to know
- non-PNG or truncated bytes return undefined instead of being treated as a valid image
resolveBasisTranscoder
Finds Three.js's Basis Universal transcoder files for the runtime KTX2 loader.
function resolveBasisTranscoder(cwd: string): IBasisTranscoderUse it to
- prepare compressed textures for runtime loading
- copy the Basis transcoder into a compiled asset output
Example
const transcoder = resolveBasisTranscoder(process.cwd());Good to know
- the supplied working directory must resolve both basis_transcoder.js and basis_transcoder.wasm from its Three.js installation
resolveSourceTexel
Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.
function resolveSourceTexel( atlasUv: readonly [number, number], transform: IAtlasTransform, source:Use it to
- rewrite a model's texture coordinates after packing its images into an atlas
- tell a surface that tiles from one that merely has a repeating sampler
Example
if (!uvsTile(uv)) rewriteUvs(uv, transforms.get(source)!);Good to know
- a surface is tiling when its own UVs leave [0, 1]; glTF's default wrap is REPEAT, so the sampler alone excludes almost everything and is the wrong test
- the rewrite is in place, and a buffer that does not hold pairs throws rather than rewriting half a coordinate
resolveSourceTexelis the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself
rewriteUvs
Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.
function rewriteUvs(uv: Float32Array, transform: IAtlasTransform): Float32ArrayUse it to
- rewrite a model's texture coordinates after packing its images into an atlas
- tell a surface that tiles from one that merely has a repeating sampler
Example
if (!uvsTile(uv)) rewriteUvs(uv, transforms.get(source)!);Good to know
- a surface is tiling when its own UVs leave [0, 1]; glTF's default wrap is REPEAT, so the sampler alone excludes almost everything and is the wrong test
- the rewrite is in place, and a buffer that does not hold pairs throws rather than rewriting half a coordinate
resolveSourceTexelis the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself
runHealthReport
Measures compiled assets and grades them against declared project targets.
async function runHealthReport( inputs: readonly IAssetHealthInput[], targets: IAssetTargets =Use it to
- check asset dimensions, triangles, materials, and licenses
- enforce asset budgets during a build
Example
const report = await runHealthReport(inputs, { maxTextureDimension: 2048 });Good to know
- a finding is fail-grade only when the corresponding project target was declared
texturePass
Encodes standalone textures as mipmapped KTX2/Basis assets for GPU storage.
function texturePass(options: ITexturePassOptions =Use it to
- optimize textures for the GPU
- compress PNG or JPEG files before runtime loading
Example
const pass = texturePass({ quality: 150 });Good to know
- compressed source width and height must each be divisible by 4; automatic cooking retains an unaligned source unchanged and reports block-size, while an explicit compression codec override fails
- every compressed source width and height must be divisible by 4 because BC7, BC1, ETC2, and ASTC 4x4 use 4x4 blocks; WebGPU rejects an unaligned texture at draw time
- automatic cooking retains an unaligned source unchanged and reports block-size; an explicit compression codec override fails, while codec "none" remains available
totalCensus
Census one glTF document, or a directory of them: the merge buckets a scene has now, and the buckets it would have once its atlasable textures shared pages.
function totalCensus(entries: readonly IContentCensus[]): Omit<IContentCensus, "model">Use it to
- find out whether "fewer objects" is available in this content before promising it
- explain why a per-material merge collapsed nothing
Example
pnpm census:content public/assetsGood to know
- reads geometry and materials only: no GPU, no runtime, no game
- a texture whose size the document does not state is reported excluded, never assumed square
- a model the reader cannot open is named, never skipped silently
uvsTile
Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.
function uvsTile(uv: ArrayLike<number>): booleanUse it to
- rewrite a model's texture coordinates after packing its images into an atlas
- tell a surface that tiles from one that merely has a repeating sampler
Example
if (!uvsTile(uv)) rewriteUvs(uv, transforms.get(source)!);Good to know
- a surface is tiling when its own UVs leave [0, 1]; glTF's default wrap is REPEAT, so the sampler alone excludes almost everything and is the wrong test
- the rewrite is in place, and a buffer that does not hold pairs throws rather than rewriting half a coordinate
resolveSourceTexelis the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself
watchAssets
Watches an asset source directory and recompiles settled changes during development.
function watchAssets(options: IAssetWatchOptions =Use it to
- recompile a changed texture without restarting the dev server
- see asset pipeline failures as files are saved
Example
const watcher = watchAssets({ cwd: process.cwd() });Good to know
- call close on the returned handle; initial and burst failures are reported without stopping the dev server
withAtlasTextures
Collapse materials that became identical once their textures shared an atlas page, and count the buckets a merge would find — before and after — so the promise can be checked rather than made.
function withAtlasTextures( materials: readonly IMaterialState[], pageOf: (texture: string) => string | undefined, ): IMaterialState[]Use it to
- decide whether fewer objects is actually available in this content
- report why a per-material merge collapsed nothing
Example
pnpm census:content public/assetsGood to know
- the signature ignores the material name, which is what made every imported part a singleton, and keeps materials apart on any field it does not understand
- the census reads geometry and materials only: no GPU, no runtime, no game
wrapTiles
Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.
function wrapTiles(wrapS: number | undefined, wrapT: number | undefined): booleanUse it to
- rewrite a model's texture coordinates after packing its images into an atlas
- tell a surface that tiles from one that merely has a repeating sampler
Example
if (!uvsTile(uv)) rewriteUvs(uv, transforms.get(source)!);Good to know
- a surface is tiling when its own UVs leave [0, 1]; glTF's default wrap is REPEAT, so the sampler alone excludes almost everything and is the wrong test
- the rewrite is in place, and a buffer that does not hold pairs throws rather than rewriting half a coordinate
resolveSourceTexelis the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself