Project folder
Located in web folder
https://github.com/lighttransport/tinyusdz/tree/release/web
Use Emscripten to build WASM/JS module.
SharedArrayBuffer feature is not required.
WASM module is being built with no thread support by default, so works without SharedArrayBuffer feature. (e.g. static-site hosting service like Github Pages, where Cross-Origin isolation headers cannot be appended)
We have a plan to make TinyUSDZ multithreaded, and provide WASM build with SharedArrayBuffer feature.
FetchAssetResolver & EMAssetResolver
Since it is impossible or quite difficult to call JS fetch(or other async function) to do async file read from C++(synchronous),
we provide JavaScript/WASM specific FetchAssetResolver(JavaScript) and EMAssetResolver(C++).
How asset resolve in USD composition works
- First list up asset paths for each composition op(subLayer, references, payload)
- fetch asset(URI) and store it to memory
- Set asset binary to EMAssetResolver(C++).
- Use EMAssetResolver for AssetResolver in USD progressive composition(in C++).
- EMAssetResolver returns corresponding binary for given asset name.
Limitation
- File(asset) must be read into memory a priori. So it may fail to load larger USD file.
JS library
- TinyUSDZLoader.js : USD loader, extends Three.js Loader class. Internally it imports WASM module.
- TinyUSDZLoaderUtils.js : Material setup(also requires Three.js), etc.
- TinyUSDZComposer.js : USD composition utils. Depends 'TinyUSDZLoader.js'
memory64
You can use memory64 build of tinyusdz JS/WASM module.
function checkMemory64Support() {
try {
// Try creating a 64-bit memory
const memory = new WebAssembly.Memory({
initial: 1,
maximum: 65536,
index: 'i64' // This specifies 64-bit indexing
});
return true;
} catch (e) {
return false;
}
}
const loader = new TinyUSDZLoader();
const memory64 = checkMemory64Support();
await loader.init({useMemory64: memory64});
Max memory size is set to 8GB in 64bit build.
Memory limit feature on USD load.
JS/WASM supports memory limit feature to load USD(USDA or USDC). Assets(e.g. textures) are excluded in this limitation feature.
// limits up to 100MB(during USD data is parsed)
loader.setMaxMemoryLimitMB(100);
Currently, heap buffer consumes 10x ~ 20x of input USD file. (USD file data(or DataURI) itself, Parsed USD data, USD data in memory, Geom data for rasterizer, etc).
For example, 180 MB of suzanne-subd-lv6.usdc file,
https://github.com/lighttransport/tinyusdz-assets
JS engine(V8) consumes roughly 5 GB of heap buffer at max.
Three.js
Currently we only support Three.js for demo .
UsdPreviewSurface
UsdPreviewSurface parameters are directly mapped to Three.js's MeshPhysicalMaterial material.
| UsdPreviewSurface Parameter | three.js MeshPhysicalMaterial Property | Notes |
|---|---|---|
| diffuseColor | color | Both define the base color/albedo. |
| emissiveColor | emissive | For self-illumination. |
| roughness | roughness | Controls surface roughness. |
| metallic | metalness | Controls metallic appearance. |
| clearcoat | clearcoat | MeshPhysicalMaterial supports clearcoat. |
| clearcoatRoughness | clearcoatRoughness | MeshPhysicalMaterial supports clearcoatRoughness. |
| opacity | opacity | Set transparent = true if opacity < 1. |
| ior (indexOfRefraction) | ior | Supported by MeshPhysicalMaterial (three.js r125+). |
| normal | normalMap | For normal mapping. |
| occlusion | aoMap | Ambient occlusion. Texture only |
| displacement | displacementMap/ displacementScale | Displacement mapping. Texture only |
Note on displacement mapping
Mesh subdivision is not supported well. To make displacement mapping work nicely, Meshes must be tessellated finely before creating USD, or tesselate in JavaScript layer.
TODO
- Support specularWorkflow
- Support refraction(refractive transmission)
MaterialX
TODO
WASM binary size
as of 2025/Jun.
- 1.9 MB with
-Oz- 400 kb with zstd compression
- 6~7 MB with
-Oz+ ASYNCIFY- ASYNCIFY is not enabled since we made TinyUSDZ WASM module async-free
npm release(Developer only)
Need to manually invoke Github Actions for npm publish.
https://github.com/lighttransport/tinyusdz/actions/workflows/wasmPublish.yml
Edit version and run workflow.
CLI
example
$ curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/OWNER/REPO/actions/workflows/build-wasm.yml/dispatches \
-d '{"ref":"main","inputs":{"release_version":"v1.2.0"}}'