Render for LLMs
Size, encode, and annotate renders for multimodal models — pixel-based billing, lossless input, and the annotations that carry spatial context.
A render sent to a multimodal model faces different constraints than one sent to a person. The provider bills the model by the pixel. The model reads compression artifacts as if they were geometry, and it cannot infer orientation or physical size from shading alone.
1. Bytes are free, pixels are billed
The major vision APIs convert an image to tokens from its pixel dimensions alone. The encoded file size never enters the bill. A 5 KB lossy WebP and a 30 KB lossless WebP of the same 768×432 render cost identical tokens on every provider below.
| Provider | Image tokens | Reference |
|---|---|---|
| OpenAI | ⌈width/32⌉ × ⌈height/32⌉ patches | Images and vision |
| Anthropic | ⌈width/28⌉ × ⌈height/28⌉ visual tokens | Vision |
| Gemini | fixed per-image budget, set by media resolution | Image understanding |
The documented base formulas apply to images small enough to skip
provider-side resizing. Some models add multipliers, or detail and
resolution settings, that scale the result; the linked pages carry the
per-model rules. Under them, the default 768×432 render costs
336 patches on OpenAI and 448 visual tokens on Anthropic. Width and height
are the only cost lever the renderer controls. Halve both and the bill
roughly quarters; shrink the file and nothing changes.
2. Send lossless input
Because bytes are free, lossy compression can only lose information the model
might need. WebP's default quality of 1 encodes lossless, so an explicit
format: 'webp' with no quality sends the model exactly the rendered
pixels. Anthropic's vision guidance warns that lossy artifacts can degrade
model performance while they save nothing on tokens. Use
lossy WebP, quality below 1, only when upload
latency matters more than fidelity.
3. Annotate for spatial reasoning
A model that reads a render has no camera, no ruler, and no filename. The three annotations put that context into the pixels:
axesdraws a camera-aware XYZ indicator, so the model knows which way the part is oriented.scaleBardraws physical size in model units; without it a gearbox and a wristwatch gear read identically.labelnames the subject or view, so a multi-image prompt stays attributable. The renderer draws the label only when you set it.
import { renderImage } from 'nanoraster';const image = await renderImage(glb, { format: 'webp', background: '#101418', axes: true, scaleBar: true, label: 'gear',});Rendering…
Annotated output needs at least 192 pixels on both axes. The mechanics of each overlay live in Format and annotate. For the strongest spatial evidence, send several labelled orthogonal views from one batch call. The shared label and axes let the model reconcile the views into one part.
Work with raw pixels
Return the RGBA frame instead of an encoded file, for pixel diffs, video frames and texture uploads with no image decoder in the loop.
Light the subject
Replace the studio preset with a rig of your own, render from the environment alone, or fix a light to the model instead of the camera.