Skip to content

Layers and compositing

Layers let you build a composition from independent render passes. Each layer has its own draw callback, grid, font, framebuffers, opacity, blend mode, filter sequences, and camera state. (ノ◕ヮ◕)ノ*:・゚✧

Access layers through t.layers, a TextmodeLayerManager.

Base layer

Every sketch has a base layer:

js
t.layers.base.draw(() => {
  t.background(0);
  t.char(".");
  t.charColor(120);
  t.rect(t.grid.cols, t.grid.rows);
});

Calling t.draw(...) is the common shorthand for drawing on the base layer.

Add a layer

Create user layers with t.layers.add():

js
const glow = t.layers.add({
  opacity: 0.75,
  blendMode: t.BLEND_SCREEN,
  fontSize: 8,
});

glow.draw(() => {
  t.clear();
  t.char("*");
  t.charColor(120, 220, 255);
  t.rotateZ(t.frameCount);
  t.rect(24, 12);
});

Layer options include:

  • visible
  • opacity
  • blendMode
  • offsetX and offsetY
  • rotationZ
  • fontSize
  • fontSource

Blend modes

blendMode() controls how a layer is composited over the result below it:

js
glow.blendMode(t.BLEND_ADDITIVE);

Use the LayerBlendMode values exposed through constants such as t.BLEND_NORMAL, t.BLEND_ADDITIVE, t.BLEND_MULTIPLY, t.BLEND_SCREEN, t.BLEND_OVERLAY, and t.BLEND_DIFFERENCE.

Opacity, visibility, and placement

js
glow.opacity(0.5);
glow.offset(20, 0);
glow.rotateZ(8);
glow.hide();
glow.show();

These layer transforms affect compositing placement, not the drawing coordinate system inside the layer.

Manage layer order

Use the layer manager to reorder or remove user layers:

js
t.layers.move(glow, 0);
t.layers.swap(layerA, layerB);
t.layers.remove(glow);
t.layers.clear();

The base layer is always present.

Layer-local resources

Layers can load their own fonts or tilesets:

js
const labelLayer = t.layers.add({ fontSize: 12 });

await labelLayer.loadFont("./fonts/label.woff");

Layer-local font loading lets one sketch mix different glyph systems without changing the base layer.

Filters on layers

Apply filters before a layer is composited (requires textmode.filters.js). Each layer has its own filter queue, and filters run in the order they are requested:

js
glow.filter("threshold", { cutoff: 0.5 });

Calls to layer.filter() made during a layer's draw() callback run after that layer is converted to ASCII. Calls made during layer.postDraw() run after the draw-time filter sequence and still before compositing:

js
glow.draw(() => {
  t.clear();
  t.char("*");
  t.rect(24, 10);
  glow.filter("grayscale");
});

glow.postDraw(() => {
  glow.filter("invert");
});

The invert filter runs after the layer has already been converted and passed through grayscale, but before glow is composited with other layers.

Apply global filters with t.filter() after all layers are composited. See Filters for the full filtering model.

Final draw

Use finalDraw() for final post-processing operations after layer compositing and before presentation:

js
t.finalDraw(() => {
  t.filter("grayscale");
});

Export layered sketches

Use Exporting to choose the right export model:

  • canvas exports capture the final composited result, including layers, opacity, blend modes, filters, and finalDraw();
  • TXT and SVG exports read one selected layer through the layer option;
  • JSON exports one selected layer by default, or the full descriptive layer stack with target: 'all'.