tiramisu

Public entrypoint for Tiramisu.

Most applications only need this module plus a handful of node-specific attribute modules such as tiramisu/camera, tiramisu/primitive, or tiramisu/material.

A minimal application looks like this:

import lustre
import lustre/attribute
import tiramisu
import tiramisu/camera
import tiramisu/renderer
import tiramisu/transform
import vec/vec3

pub fn main() -> Nil {
  let assert Ok(_) = tiramisu.register(tiramisu.builtin_extensions())
  let assert Ok(_) = lustre.start(lustre.element(view()), "#app", Nil)
  Nil
}

fn view() {
  tiramisu.renderer(
    "renderer",
    [attribute.width(800), attribute.height(480)],
    [
      tiramisu.scene("scene", [], [
        tiramisu.camera(
          "camera",
          [camera.active(True), transform.position(vec3.Vec3(0.0, 0.0, 6.0))],
          [],
        ),
      ]),
    ],
  )
}

Values

pub fn builtin_extensions() -> List(extension.Extension)

Get the built-in extensions shipped with Tiramisu.

Pass this to tiramisu.register/1 unless you are assembling a custom extension list yourself.

pub fn camera(
  id: String,
  attributes: List(attribute.Attribute(msg)),
  children: List(element.Element(msg)),
) -> element.Element(msg)

Create a camera node.

Cameras are part of the scene hierarchy, so they can be nested under other nodes and transformed like any other scene object.

pub fn empty(
  id: String,
  attributes: List(attribute.Attribute(msg)),
  children: List(element.Element(msg)),
) -> element.Element(msg)

Create an empty group node for hierarchy and shared transforms.

Use empty nodes to build scene structure without introducing visible geometry.

pub fn light(
  id: String,
  attributes: List(attribute.Attribute(msg)),
  children: List(element.Element(msg)),
) -> element.Element(msg)

Create a light node.

Lights affect the scene from their place in the scene hierarchy.

pub fn mesh(
  id: String,
  attributes: List(attribute.Attribute(msg)),
  children: List(element.Element(msg)),
) -> element.Element(msg)

Create an asset-backed mesh node.

Meshes load external assets through attributes such as attribute.src(...).

pub fn primitive(
  id: String,
  attributes: List(attribute.Attribute(msg)),
  children: List(element.Element(msg)),
) -> element.Element(msg)

Create a primitive mesh node.

Primitives create geometry directly from attributes such as primitive.box(...) or primitive.sphere(...).

pub fn register(
  extensions: List(extension.Extension),
) -> Result(Nil, lustre.Error)

Register Tiramisu’s custom elements with Lustre.

Most applications should call this once at startup with tiramisu.builtin_extensions().

If you are writing custom nodes or attribute extensions you can append them to the built-ins before calling register/1.

pub fn renderer(
  id: String,
  attributes: List(attribute.Attribute(msg)),
  children: List(element.Element(msg)),
) -> element.Element(msg)

Create a renderer host.

A renderer owns the canvas, render loop, and runtime state for exactly one nested tiramisu.scene.

In practice a renderer is the root of each independent 3D world on the page.

pub fn scene(
  id: String,
  attributes: List(attribute.Attribute(msg)),
  children: List(element.Element(msg)),
) -> element.Element(msg)

Create a scene root inside a renderer.

Scene children are Tiramisu nodes such as cameras, primitives, meshes, lights, and empties.

A renderer should contain exactly one scene root.

pub fn script() -> element.Element(a)

Inject the browser import map required by Tiramisu’s runtime script.

This helper is mainly useful for direct browser usage and examples. If your app already manages module resolution through a bundler or its own import map, you likely do not need it.

Search Document