@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

function · import { atlasManifest } from "@threenative/assets"

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.

ts
function atlasManifest(result: IAtlasResult): string

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

ts
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

function · import { audioPass } from "@threenative/assets"

Conditions a game's audio and proves the conditioning did not destroy it.

ts
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

ts
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

function · import { censusDocument } from "@threenative/assets"

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.

ts
function censusDocument( model: string, document: Document, pageSize = 4_096, ): IContentCensus

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

sh
pnpm census:content public/assets

Good 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

function · import { compileAssets } from "@threenative/assets"

Compiles a project's source assets into content-addressed runtime files and a manifest.

ts
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

ts
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

function · import { dedupeMaterials } from "@threenative/assets"

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.

ts
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

sh
pnpm census:content public/assets

Good 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

function · import { formatAudioSizes } from "@threenative/assets"

Formats audio conditioning measurements for a build report.

ts
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

ts
const lines = formatAudioSizes(audioRows);

Good to know

  • an empty row list produces no report lines

formatHealthReport

function · import { formatHealthReport } from "@threenative/assets"

Formats asset health findings and their summary for human-readable output.

ts
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

ts
const lines = formatHealthReport(report);

Good to know

  • the returned lines describe findings; target enforcement happens in runHealthReport

formatModelSizes

function · import { formatModelSizes } from "@threenative/assets"

Formats model byte, geometry, and embedded-texture measurements for a build report.

ts
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

ts
const lines = formatModelSizes(modelRows);

Good to know

  • rows must use bytes before and after from the same compiled input

formatPassCosts

function · import { formatPassCosts } from "@threenative/assets"

Formats per-pass wall-clock costs for a build report.

ts
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

ts
const lines = formatPassCosts(result.passCosts);

Good to know

  • one row per pass in registry order, per-asset rows sorted by logical path

formatTextureSizes

function · import { formatTextureSizes } from "@threenative/assets"

Formats standalone texture byte measurements for a build report.

ts
function formatTextureSizes(rows: readonly ITextureSizeRow[]): readonly string[]

Use it to

  • inspect texture compression savings
  • print which codec a compiled texture uses

Example

ts
const lines = formatTextureSizes(textureRows);

Good to know

  • an empty row list produces no report lines

lightmapPass

function · import { lightmapPass } from "@threenative/assets"

Generates lightmap UVs and bakes a static GLB's lightmap atlas.

ts
function lightmapPass(options: ILightmapPassOptions): IAssetPass

Use it to

  • add baked static lighting to a model
  • generate TEXCOORD_1 data for a lightmapped scene

Example

ts
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

function · import { materialSignature } from "@threenative/assets"

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.

ts
function materialSignature(material: IMaterialState): string

Use it to

  • decide whether fewer objects is actually available in this content
  • report why a per-material merge collapsed nothing

Example

sh
pnpm census:content public/assets

Good 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

function · import { materialStateOf } from "@threenative/assets"

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.

ts
function materialStateOf(material: Material): IMaterialState

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

sh
pnpm census:content public/assets

Good 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

function · import { modelPass } from "@threenative/assets"

Optimizes self-contained GLB models through the configured geometry and embedded-texture passes.

ts
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

ts
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

function · import { packAtlas } from "@threenative/assets"

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.

ts
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

ts
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

function · import { parseAudioConfig } from "@threenative/assets"

Validates a game's declared assets.audio block, the one place its keys and ranges are checked.

ts
function parseAudioConfig(raw: unknown): IAudioPassOptions | undefined

Use it to

  • validate a threenative.config.ts audio block before compiling assets
  • ship audio exactly as committed without conditioning it

Example

ts
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

function · import { parsePng } from "@threenative/assets"

Reads dimensions and alpha metadata from a PNG signature and IHDR header.

ts
function parsePng(value: Buffer): IPngInfo | undefined

Use it to

  • inspect a PNG before choosing a texture codec
  • read source texture dimensions in an asset health check

Example

ts
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

function · import { resolveBasisTranscoder } from "@threenative/assets"

Finds Three.js's Basis Universal transcoder files for the runtime KTX2 loader.

ts
function resolveBasisTranscoder(cwd: string): IBasisTranscoder

Use it to

  • prepare compressed textures for runtime loading
  • copy the Basis transcoder into a compiled asset output

Example

ts
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

function · import { resolveSourceTexel } from "@threenative/assets"

Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.

ts
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

ts
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
  • resolveSourceTexel is the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself

rewriteUvs

function · import { rewriteUvs } from "@threenative/assets"

Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.

ts
function rewriteUvs(uv: Float32Array, transform: IAtlasTransform): Float32Array

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

ts
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
  • resolveSourceTexel is the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself

runHealthReport

function · import { runHealthReport } from "@threenative/assets"

Measures compiled assets and grades them against declared project targets.

ts
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

ts
const report = await runHealthReport(inputs, { maxTextureDimension: 2048 });

Good to know

  • a finding is fail-grade only when the corresponding project target was declared

texturePass

function · import { texturePass } from "@threenative/assets"

Encodes standalone textures as mipmapped KTX2/Basis assets for GPU storage.

ts
function texturePass(options: ITexturePassOptions =

Use it to

  • optimize textures for the GPU
  • compress PNG or JPEG files before runtime loading

Example

ts
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

function · import { totalCensus } from "@threenative/assets"

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.

ts
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

sh
pnpm census:content public/assets

Good 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

function · import { uvsTile } from "@threenative/assets"

Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.

ts
function uvsTile(uv: ArrayLike<number>): boolean

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

ts
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
  • resolveSourceTexel is the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself

watchAssets

function · import { watchAssets } from "@threenative/assets"

Watches an asset source directory and recompiles settled changes during development.

ts
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

ts
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

function · import { withAtlasTextures } from "@threenative/assets"

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.

ts
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

sh
pnpm census:content public/assets

Good 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

function · import { wrapTiles } from "@threenative/assets"

Move a mesh's UVs onto its atlas page, and decide from the geometry which meshes may not go.

ts
function wrapTiles(wrapS: number | undefined, wrapT: number | undefined): boolean

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

ts
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
  • resolveSourceTexel is the inverse, so a build can round-trip a texel instead of asserting the arithmetic against itself
View source on GitHub ↗