Assets
Images, vectors and 3D models you have uploaded can be drawn from a script: a bitmap or SVG as a texture on any primitive, a model as geometry.
context 3d
render {
draw::cube(texture: asset::bitmap(id: "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d"))
}
Referring to an asset
| Call | What it names |
|---|---|
asset::bitmap(id: "<id>") | A PNG, JPEG or WebP upload |
asset::vector(id: "<id>") | An SVG upload |
asset::model(id: "<id>") | A GLB (binary glTF) upload |
The id is the asset’s identifier from your library, and the id: label is
required — every argument in the language is named, and a bare string here
would be the sole exception. asset::bitmap("a1b2c3d4-…") does not parse.
The library’s Insert button and Copy reference both write the correct form, so there is rarely a need to type one out.
The id must be a literal string. asset::bitmap(id: my_variable) is not valid,
and this is deliberate rather than an oversight. Visamp works out which visuals
use which asset by reading your source, and that is what makes it possible to
tell you when an asset you rely on has gone away. A computed id could not be
read that way, so the guarantee would be lost for everybody.
An asset:: expression is a reference, not a picture. It does nothing on its
own — pass it to a draw call.
Textures
texture: is accepted by every 3D draw:: call and takes a bitmap or
vector reference.
context 3d
render {
light::ambient(color: color::rgb(r: 0.6, g: 0.6, b: 0.6))
draw::sphere(radius: 1.5, texture: asset::bitmap(id: "a1b2c3d4-…"))
}
The texture modulates the shape’s colour rather than replacing it, so everything else still works the way you would expect:
// Tinted red, half transparent, still textured.
draw::cube(
texture: asset::bitmap(id: "a1b2c3d4-…"),
color: color::rgb(r: 1.0, g: 0.2, b: 0.2),
opacity: 0.5
)
Passing a color of white — the default — leaves the image untouched.
How each primitive is wrapped
| Primitive | Mapping |
|---|---|
cube | Each face gets the whole image |
sphere | Equirectangular: u around, v pole to pole |
plane | The whole image across the surface |
cylinder | Around the side; the caps are mapped radially from their centre |
cone | Around the side; the base radially |
torus | u around the ring, v around the tube |
sprite | The whole image on the quad |
point_cloud | The whole image on each point |
mesh, model | Whatever the geometry’s own coordinates say |
A draw::mesh without uvs samples the image’s top-left corner, which shows as
a flat colour rather than an error.
Images larger than 2048 pixels on their longest side are scaled down before being sent to the graphics card. An 8192×8192 texture would cost 256 MB of video memory, which is more than the whole visual is likely to have.
Models
draw::model draws an uploaded GLB. It takes the same position, rotation,
colour, shading and texture arguments as any other 3D primitive.
context 3d
render {
transform::rotate_y(deg: $TIME_SEC * 30.0)
draw::model(asset: asset::model(id: "f0e1d2c3-…"))
}
The whole model is loaded as one piece of geometry, with each part placed where
the file says it goes. Any textures the model file carries internally are not
applied — pass one with texture: if you want it textured.
Only .glb is accepted. A .gltf file normally points at separate texture and
buffer files sitting next to it, and Visamp has no way to store or keep track of
those, so a model has to be exported as a single self-contained file.
Point models (engine 2.5.0)
GLBs can contain POINTS geometry as well as triangles. Render these with
draw::point_cloud(model: asset::model(id: "…")). Point-only models have no
surfaces for draw::model to draw. Triangle models can also be drawn as points,
using each primitive’s source positions without expanding its triangle indices.
Point primitives preserve their draw order, including indexed points. Node transforms are applied once during loading, in scene order. The decoder does not sort, merge, centre or rescale vertices. This matters for animations that walk between neighbouring points. See point fields for source-position access, per-point size and sprites.
Upload admission uses the same geometry decoder as playback. Positions must be
finite floating-point VEC3 values in the embedded binary buffer. Sparse
accessors and external buffers are unsupported. Models must contain renderable
points or triangles, at most 1,000,000 point positions and 65,536 triangle
vertices. Triangle indices are limited to 6,000,000. Bounds, transforms, attribute
counts and node hierarchies are checked before an asset becomes ready.
Loading and missing assets
The Visamp host resolves and preloads referenced assets before activating the script. Cached assets can be reused when you return to a visual. While loading, the player shows a loading state; a failed or unavailable asset shows a retryable error instead of rendering an incomplete visual. Upload completion alone is not enough: the asset must be ready and readable by the current viewer.
The engine itself never fetches URLs or bypasses permissions. Custom hosts must
supply decoded assets and implement their own readiness gate. Some low-level
mesh/point calls have missing-asset fallbacks; effect::displace requires its
bitmap and reports a located runtime error if it has not been supplied.
Access
- Your uploads are private by default and only you can use them.
- Making one public lets anybody use it, including in exported video.
- Referencing an asset you cannot read does not give you access to it. The host reports it as unavailable.
- A public visual cannot reference a private asset. Publishing one is refused, and names the assets that need making public first.
Forks work exactly as you would expect and need no special handling. A fork keeps the source, so it keeps the references. Whether they load is decided for whoever is watching: a fork of a visual using a public asset works for everyone, and a fork can never reach a private one.
If an asset a published visual relies on is removed, the host reports the dependency as unavailable until it can be resolved.
Formats and limits
| Kind | Accepted | Maximum size |
|---|---|---|
| Bitmap | .png, .jpg, .jpeg, .webp | 20 MB, 8192×8192 pixels |
| Vector | .svg | 2 MB |
| Model | .glb | 60 MB |
An account can store 300 assets totalling 1 GB.
SVGs are checked on upload and refused if they contain scripts, event handlers, or references to anything outside the file itself — an uploaded vector has to stand alone. If an SVG is rejected, exporting it as a plain shape drawing from your editor usually resolves it.