Skip to content

(data …)

Defines embedded data for buffer initialization. Supports compile-time shape generators, inline float arrays, WASM (WebAssembly) generated data, and external image files.

; Shape generator (compile-time mesh generation)
(data :name cubeVerts (cube :format [position4 color4 uv2]))
; Inline float array
(data :name weights :float32 [1.0 2.0 3.0])
; WASM-generated data
(data :name curve (wasm-data :file "gen.wasm" :func make :returns "array<f32,360>"))
; External image file
(data :name logoFile :file "path/to/file.png" :mime "image/png")
Key Type Required Default Description
:name symbol Yes - Unique data name
generator sub-form positional form No* - (cube …), (plane …), … or (wasm-data …)
:float32 array No* - Inline float array data
:file string No* - Image file path, relative to the source document
:mime string No application/octet-stream MIME type stored with the :file bytes

*One byte source, three spellings. A (data …) carries at most one positional generator sub-form; a second one is a positional_too_many error rather than a silently ignored form. If more than one spelling is present the generator wins, then :file, then :float32; a (data …) with none of them is an empty entry of zero bytes.

Generate vertex data at compile time instead of writing arrays manually. A shape is a positional sub-form inside (data …). Shape generators produce triangle lists with the specified vertex attributes.

Available shapes: cube, plane, sphere, torus, truncated-cone, cylinder, teapot, dragon. Each accepts a :format list, plus generator-specific parameters:

Key Type Default Applies to
:segments number 24 sphere (longitude)
:rings number 12 sphere (latitude)
:radius number 1.0 sphere, torus (major radius), cylinder
:thickness number 0.24 torus (minor radius)
:radial-subdivisions number 24 torus, truncated-cone, cylinder
:body-subdivisions number 12 torus
:vertical-subdivisions number 1 truncated-cone, cylinder
:bottom-radius number 1.0 truncated-cone (a cylinder takes :radius for both ends)
:top-radius number 0.0 truncated-cone
:height number 1.0 truncated-cone, cylinder
:top-cap / :bottom-cap boolean true truncated-cone, cylinder
:faceted boolean false flat normals, one per triangle

A subdivision count outside its generatable range is a compile error naming the key and the range: no generated mesh may exceed 65536 indices.

Generates a cube centered at the origin, vertices at ±1. Produces 36 vertices (6 faces × 2 triangles × 3 vertices), deindexed.

(data :name cubeVertices (cube :format [position4 color4 uv2]))

Generates a single 1×1 quad on the XY plane, facing +Z. Produces 6 vertices (2 triangles), deindexed.

(data :name planeVertices (plane :format [position3 uv2]))

Generates a UV sphere. Extra parameters (:segments, :rings) tune the tessellation:

(data :name sphereVertices (sphere :format [position3 normal3] :segments 24 :rings 12))

The teapot and dragon generators produce an indexed mesh: vertex data plus an index companion. Source a vertex buffer from the shape and an index buffer with :index-of:

(data :name teapotMesh (teapot :format [position3 normal3]))
(buffer :name vertexBuffer :usage [vertex] :data teapotMesh)
(buffer :name indexBuffer :index-of teapotMesh :usage [index])

The :format array specifies which attributes to generate for each vertex:

Specifier Type Size Description
position3 vec3f 12 bytes XYZ position
position4 vec4f 16 bytes XYZW position (w=1)
normal3 vec3f 12 bytes Surface normal
color3 vec3f 12 bytes RGB vertex color
color4 vec4f 16 bytes RGBA vertex color
uv2 vec2f 8 bytes Texture coordinates

Vertex stride is the sum of all attribute sizes. For [position4 color4 uv2]:

  • position4: 16 bytes
  • color4: 16 bytes
  • uv2: 8 bytes
  • Total stride: 40 bytes

Type: array of numbers

Inline float values, written directly:

(data :name vertices :float32 [
0.0 0.5 1.0 0.0 0.0
-0.5 -0.5 0.0 1.0 0.0
0.5 -0.5 0.0 0.0 1.0
])

:float32 takes a literal list only; there is no repeat-or-fill generator. For computed values, use a (wasm-data …) generator (below) to produce the bytes at compile time, or a compute init pass (see (init …)) to fill the buffer on the GPU.

A (wasm-data …) sub-form calls a WASM function once at buffer-create time; its returned bytes fill the buffer.

(data :name curve (wasm-data :file "gen.wasm" :func makeCurve :returns "array<f32,360>"))
Key Type Required Description
:file string Yes WASM file path, relative to the source document
:func symbol Yes Exported function to call
:returns string Yes Return type, turned into a byte count (array<f32,360> is 1440, mat4x4 is 64, vec4 is 16, f32 is 4)

Modules are deduplicated by path, and are read at compile time, so an unreadable :file is an error that names the path.

Type: string

Path to an image file, relative to the source document. It is embedded in the PNGB payload (the compiled bytecode) at compile time as [mime_len][mime][bytes], and decoded at runtime by an (image-bitmap …):

(data :name imageFile :file "textures/diffuse.png" :mime "image/png")
(data :name cubeVertices (cube :format [position4 color4 uv2]))
(buffer :name vertexBuffer
:usage [vertex]
:data cubeVertices)
(render-pipeline :name cubeRenderer :layout auto
(vertex :module shader :entry vs
(vertex-buffer :array-stride 40
(attribute :shader-location 0 :offset 0 :format float32x4)
(attribute :shader-location 1 :offset 16 :format float32x4)
(attribute :shader-location 2 :offset 32 :format float32x2)))
(fragment :module shader :entry fs
(target :format preferred-canvas-format)))
(data :name triangleVerts :float32 [
0.0 0.5 1 0 0
-0.5 -0.5 0 1 0
0.5 -0.5 0 0 1
])
(buffer :name vertexBuffer
:usage [vertex]
:data triangleVerts)
(data :name textureData :file "assets/logo.png" :mime "image/png")
(image-bitmap :name logo :data textureData)

A buffer with :data takes its size from the data, so no byte count is written beside it:

(data :name vertexData (cube :format [position4 color4 uv2]))
(buffer :name verts ; sized by the data it is filled from
:usage [vertex]
:data vertexData)

Size calculation:

  • Shape generators: vertex_count × stride (e.g. a cube with position4+color4+uv2 = 36 × 40 = 1440 bytes)
  • Inline :float32 arrays: element_count × 4 bytes
  • (wasm-data …): the byte count its :returns type spells

A numeric :size beside :data is legal and over-allocates on purpose; a :size smaller than the data is a compile error. A (data …) name is not accepted in :size itself, which takes a number, an expression, or a (define …) constant.

Rule Error
A name is declared once, across every form kind duplicate_cross_ref_target, or duplicate name 'x': already declared as a (data …) at line N
At most one generator sub-form positional_too_many
The sub-form head is one of the nine generators not_head_member
:format entries are position3, position4, normal3, color3, color4 or uv2 not_member
A generator’s subdivision counts are in range (sphere …) :segments 0 is outside the generatable range 3..4096
:file must be readable at compile time cannot read 'assets/logo.png': FileNotFound (located on the (data …) form; the path is resolved against the document’s directory)

The rows with a code are schema checks; the rows with a message are compiler checks, and they report the line the form is written on.