Polyfork BrowseKits

What a parametric asset costs

Every asset here is a small program rather than a frozen mesh, which raises a fair question: is that slower than loading a GLB? These are the measured answers, on this catalogue, with the script that produced them in the repo.

Does varying the knobs cost more?

No. This is the number most people expect to go the other way.

AssetTrianglesSame shape, 25× Different shape every callKnob varied
Street lamp 422 0.79 ms 0.61 ms tallness
Toy rocket 618 2.48 ms 2.27 ms tallness
Windmill 1,811 4.56 ms 4.11 ms tallness
Convertible 60s 4,784 10.36 ms 9.78 ms stretch
Asking for a different shape is free.

The factory runs the same code whatever the values are, so a configurator offering a hundred variants costs exactly what one offering a single shape costs. Only the number of calls matters.

Does it run every frame?

No. It runs when a parameter changes, and never otherwise.

Page stateWindowRebuildsWhat is happening
Loaded, untouched5 s0 render loop running, factory idle
Slider in motion2.5 s42 one rebuild per frame, by design
Slider released5 s0 back to idle immediately
A static scene has no ongoing cost from the module.

Once built, drawing it is identical to drawing a GLB: the same geometry and the same single material are already on the GPU. The build cost is paid per change, not per frame.

Module or GLB?

Same thing on screen. The difference is what you pay upfront and what you can still change.

AssetModulegzippedGLB gzippedBuild cost
Street lamp 11.1 KB 4.1 KB 45.7 KB 6.3 KB 0.79 ms
Toy rocket 11.3 KB 4.0 KB 66.3 KB 7.9 KB 2.48 ms
Windmill 25.2 KB 8.4 KB 194.2 KB 26.6 KB 4.56 ms
Convertible 60s 24.8 KB 7.7 KB 365.4 KB 32.5 KB 10.36 ms

Module sizes are the comment-stripped copies actually served, gzipped as your server would send them. The module came out smaller on the wire for every asset measured here and produces any variant; the GLB needs no build step and opens in Unity, Godot and Blender. Neither is faster to render.

The one real trap: copies

Calling the factory once per copy is the mistake that actually costs you.

20 copies of Convertible 60s CPUDistinct geometriesWhy
createAsset() per copy 199.20 ms 40 every copy uploaded to the GPU separately
.clone() from one build 3.30 ms 2 buffers shared, uploaded once
60× cheaper, and 20× less GPU memory.

Build once and clone(), or use THREE.InstancedMesh for many copies of one shape. This is the only case where the factory can genuinely hurt.

A whole scene in one draw call

Every asset in the catalogue uses one vertex-coloured material and no textures, which means any set of them collapses into a single geometry.

SceneAssetsMeshesTriangles Merge timeDraw calls after
cottage, tree, well, barrel, fence, lamp 6 10 4,712 0.40 ms 1
import { mergeAssets } from 'https://polyfork.dev/cdn/merge.mjs';

const { merged, dynamic } = mergeAssets([cottage, tree, well]);
scene.add(merged);                  // one draw call, static
dynamic.forEach(d => scene.add(d)); // wheels, doors, still animatable

Position everything before merging: world transforms are baked in. Rig-declared parts come back separately so they can still move.

The cost that surprised us

When a slider does rebuild every frame, the geometry was never the expensive part.

Per rebuild, counted in the browserBeforeAfter
Shader program links1 0
Shader compiles2 0

three.js reference-counts a compiled GPU program against the materials using it. Dispose the last material holding a program and the program is deleted, so the next rebuild has to compile and link again, and a link is a synchronous stall inside the driver. Keeping one material instance per distinct configuration removed it entirely. If you drive a knob live: dispose geometry, reuse materials.

The rules, short

  1. Shape never changes at runtime?Use the GLB. There is nothing to gain from the factory.
  2. Static scene of several assets?Build each once, then mergeAssets. One draw call for the lot.
  3. Many copies of one asset?Build once, then clone() or InstancedMesh. Never call the factory in a loop.
  4. A handful of fixed variants?Build each once at load and swap between them. Do not rebuild to switch.
  5. A live slider?The only case that justifies rebuilding per frame. Reuse materials, and budget roughly 10.36 ms a frame for something convertible 60s-sized.

Measured 2026-07-28 on node v22.22.1, three r185. median of 25 calls per asset, after 8 warm-up calls, single core. CPU figures come from tools/bench.mjs in the repo; the shader counts were taken in a real browser by patching the WebGL context, and the idle-rebuild counts by watching the scene graph across animation frames. Absolute milliseconds depend on your hardware, so treat the ratios as the durable part.

How remixable assets work Use it from an agent Browse the catalog
Polyfork

Sign in

One account for your purchases and downloads.

Continue with Google
or

No password needed: the link signs you in directly.