nanoraster
0.7.1

Render multiple views

Declare an ordered plan of identified camera views — with per-view size and format overrides — and render it in one call from one GLB.

Open Markdown

Render several outputs of one model in one call, the plan call. The results keep the IDs and the order you declared, as the tutorial does for its contact sheet. One call parses and uploads the GLB once, shares the GPU device across every view, and schedules the whole set together. A loop of single renders never can.

1. Declare the views as a tuple

Each view needs a unique id. Its optional self-contained camera defaults to the fitted three-quarter view. axes marks each orientation.

import { directionFromOrbit, renderImages } from 'nanoraster';import { readFile } from 'node:fs/promises';const glb = Uint8Array.from(await readFile('model.glb'));const images = await renderImages(glb, {  format: 'webp',  width: 640,  height: 480,  axes: true,  views: [    { id: 'iso' },    {      id: 'front',      camera: {        framing: 'fit',        direction: directionFromOrbit({ azimuth: 90, elevation: 0 }),      },    },  ],});

Rendering…

advanced · direction XYZ

2. Read the results positionally or by ID

The result is a tuple, not a map: position and length match the input.

const [iso, front] = images;

console.log(iso.id); // 'iso'
console.log(front.file.name); // 'render-front.webp'

TypeScript types iso.id as 'iso' rather than string, but only while the options object is inferred as const.

3. Ladder sizes and formats with per-view overrides

A view is more than a camera. You can override width, height, format, and quality per entry; each defaults to the shared value. One call turns one subject into a card, a social image, and a print asset.

const [card, og, print] = await renderImages(glb, {
  format: 'webp',
  width: 768,
  height: 576,
  views: [
    { id: 'card' },
    { id: 'og', width: 1536, height: 804 },
    { id: 'print', width: 1536, height: 804, format: 'png' },
  ],
});

console.log(og.file.name); // 'render-og.webp'
console.log(print.file.mimeType); // 'image/png'

Each entry's filename and MIME type follow its own resolved format. TypeScript narrows print.file.mimeType to 'image/png', while card and og stay 'image/webp'. Overrides pass the same validation as the shared values: a per-view quality: 1 on WebP still means lossless, and annotated views still need 192 pixels each way.

4. Preserve literal types across a variable

When you assign the options to a variable, TypeScript widens the literals and loses the IDs. as const satisfies RenderImagesOptions prevents that. as const keeps every literal, and satisfies still rejects misspelled or misplaced keys. Both act at compile time and add nothing to the bundle.

import { renderImages, type RenderImagesOptions } from 'nanoraster';

const options = {
  format: 'webp',
  views: [{ id: 'iso' }, { id: 'top', camera: { framing: 'fit', direction: [0, 1, 0], up: [0, 0, 1] } }],
} as const satisfies RenderImagesOptions;

const images = await renderImages(glb, options);

Variations

One image only. Use renderImage. The plan call requires a non-empty tuple and returns a tuple even for one view, under the same exactness rules.

Labels per view. Give an entry a label and that view is labelled. Omit it and the view is not. See Format and annotate.

Shared and per-view settings. axes, scaleBar, background, lighting, surfaces, lines, and sections apply to the whole request. A view may set visiblePrimitives to draw and fit a different subject while sharing one parsed GLB. Omit it to inherit the shared selection. Per-view selection with sections is unsupported. camera, label, and the four output fields also vary per view. There is no shared partial camera or inheritance order.

Renders spread over time. The plan call shares the device across views within one call; createRenderer shares it across calls over time. They compose: a warm renderer accepts the same plan calls. Either way, when you can write the full list of images, send it as one call rather than a loop. Only the renderer can schedule work it can see.

Stage timings. timings: true attaches stage and resource data to results.timings. presentationBuilds is 1 for the plan; see RenderTimings.

On this page