Skip to content

Framebuffers

Framebuffers let you render offscreen and use the result later. They are useful for multi-pass effects, feedback loops, cached render passes, readback, and shader workflows. (@_@)

Create them with createFramebuffer().

Create a framebuffer

js
let fb;

t.setup(() => {
  fb = t.createFramebuffer({
    width: t.grid.cols,
    height: t.grid.rows,
  });
});

Framebuffer width and height are in grid cells. If width or height is omitted from the options object, that dimension uses the current textmode grid size.

Render offscreen

Use begin() and end():

js
t.draw(() => {
  fb.begin();
  t.clear();
  t.char("A");
  t.charColor(255, 120, 80);
  t.rect(20, 10);
  fb.end();

  t.background(0);
  t.rotateZ(t.frameCount);
  t.image(fb);
});

Everything between begin() and end() renders into the framebuffer instead of the active layer.

Draw a framebuffer

Framebuffers can be drawn with image():

js
t.image(fb);
t.image(fb, 40, 20);

The optional width and height scale the framebuffer result in grid cells.

Multi-pass rendering

Use multiple framebuffers when one pass should feed another:

js
fbA.begin();
t.clear();
t.char("*");
t.rect(20, 10);
fbA.end();

fbB.begin();
t.shader(waveShader);
t.setUniform("u_source", fbA.textures[0]);
t.image(fbA);
t.shader(null);
fbB.end();

t.image(fbB);

For feedback effects, ping-pong between two framebuffers so the current frame can sample the previous result.

Read and resize

readPixels() reads framebuffer data when you need CPU-side inspection or export support:

js
const pixels = fb.readPixels();

resize() updates framebuffer dimensions:

js
fb.resize(t.grid.cols, t.grid.rows);

Call dispose() when a manually created framebuffer is no longer needed.