Skip to content

Sprite

A billboarded sprite: a textured quad placed in the 3D world that faces the camera, tinted and alpha-blended, and depth-sorted back-to-front so overlapping sprites composite correctly. Ideal for particles, icons, foliage, and 2D-in-3D characters (Lexicon’s stone tiles use these).

Build a sprite from a Texture, set its style once, then drawAt a world position each frame. The engine computes the camera-facing corners and the draw order for you.

Returns: Sprite

Parameters:

  • texture (Texture) — The image to draw.
import "engine" for Texture, Sprite
var tex = Texture.load("textures/spark.png")
var spark = Sprite.new(tex)
  • size = (Num) — World-space height; the width follows the texture’s aspect ratio.
  • color = (List) — Tint [r, g, b, a] (0..1), multiplied with the texture. Default white.
  • billboard = (Num) — Facing mode:
    • 0 spherical (default) — fully faces the camera.
    • 1 cylindrical — locked to world up (Y); rotates only horizontally (upright characters/trees).
    • 2 flat — fixed in the world XY plane, no camera facing.
spark.size = 1.5
spark.color = [1.0, 0.8, 0.3, 0.9]
spark.billboard = 0

Draw the sprite this frame, centered at the world position (x, y, z). Requires the view/projection to be set (see Graphics); sprites are drawn after opaque geometry, depth-tested against it, and sorted among themselves back-to-front.

// In Game.draw(), after setting the camera matrices:
for (p in positions) {
spark.drawAt(p.x, p.y, p.z)
}
import "engine" for Graphics, Window, Texture, Sprite, Scene
class Game {
construct new() { _tex = null; _cam = null; _s = null }
init() {
_tex = Texture.load("textures/circle.png")
var scene = Scene.new()
_cam = scene.addCamera()
var n = scene.addNode("cam")
n.setPosition(0, 0.6, 6)
n.lookAt(0, 0, 0)
_cam.setNode(n)
_s = Sprite.new(_tex)
_s.size = 2.0
}
draw() {
Graphics.setViewProjectionEnabled(true)
var aspect = Window.getWidth() / Window.getHeight()
Graphics.setViewMatrix(_cam.getViewMatrix())
Graphics.setProjectionMatrix(_cam.getProjectionMatrix(aspect))
_s.color = [1, 0.5, 0.5, 0.95]
_s.drawAt(-0.5, 0, -2) // farther from the camera
_s.color = [0.5, 0.7, 1, 0.95]
_s.drawAt(0.5, 0, 1) // nearer — ends up on top
}
quit() {}
}

Draw order does not decide occlusion. The renderer sorts each frame’s sprites back-to-front by view-space depth before drawing, so the nearer sprite covers the farther one regardless of the order you call drawAt in.

See Sprite Demo (apps/sprite_demo) for a depth-sorted cascade, and Graphics for the camera setup.