Fbo

Drawing offscreen into an Fbo and reusing it as a texture.

Fbo

Fbo(width=0, height=0, format=TextureFormat.RGBA8)

An offscreen image to draw into, then draw or sample.

Draw into it in a with fbo: block, then show it with draw or use texture anywhere a Texture goes. Drawing into an Fbo and drawing it to the screen in the same frame just works, in the order you wrote it.

fbo = kiln.Fbo(200, 200)          # in setup
with fbo:                          # in draw (or update, or setup)
    kiln.clear(0)
    kiln.circle(100, 100, 80)
fbo.draw(0, 0)
fbo.draw(200, 0, 100, 100)         # reuse it, scaled

Inside the Fbo, the origin is its top-left corner, y points down and one unit is one of its pixels, whatever the window’s pixel ratio: a 200 x 200 Fbo is 200 x 200 pixels on any display, and read returns exactly that. draw defaults to its size in points, so on a 2x display it is magnified like a Texture; allocate it at twice the size and draw it at half size for Retina-crisp results.

An Fbo keeps its pixels until you clear them: the automatic background clears only the window. clear, background and clear_alpha inside with fbo: apply to the Fbo, in order with your draws; a new Fbo starts transparent black.

Blended drawing stores premultiplied colour (colour times alpha) in the Fbo, which is what blending computes. Kiln knows, so a semi-transparent shape drawn into a transparent Fbo looks the same once the Fbo is drawn as drawn directly, and read of an RGBA8 Fbo returns straight alpha, ready for a PNG. Float Fbos read back their stored, premultiplied values. For data rather than pictures (simulations), keep alpha at 255 or draw with Blend.REPLACE, which stores and copies values unchanged on the GPU. Reading an RGBA8 Fbo back always un-premultiplies, so to read four independent 8-bit values per pixel keep alpha at 255, or use a float Fbo, which reads back exactly what it stores.

Drawing an Fbo into itself raises ValueError: GPUs can’t read and write one image at once. For feedback effects use two Fbos and swap them each frame (ping-pong). The same goes for binding its texture to a Mesh drawn into it.

Its texture takes filter and wrap like any Texture (NEAREST for crisp pixels, REPEAT to tile with draw(source=) or mesh texture coordinates), but not mipmaps, which raise ValueError. Inside with fbo:, Image.grab_screen and kiln.save_screen read the Fbo rather than the window, in its pixels.

Parameters

Name Type Description Default
width int Width in pixels; with height, allocates right away. 0
height int Height in pixels. 0
format TextureFormat | TextureFormatValue How the pixels are stored. RGBA16F and RGBA32F keep values outside 0-1 (glow accumulation, simulations). TextureFormat.RGBA8

Attributes

Name Type Description
width Width in pixels, 0 until allocated and after release.
height Height in pixels, like width.
format The TextureFormat.

Methods

Name Description
allocate Creates (or recreates) the Fbo’s image, transparent black.
clear Clears the Fbo’s pixels, in order with the draws around it.
draw Draws the Fbo’s pixels as a textured quad.
read Returns the Fbo’s pixels, top row first.
release Frees the Fbo’s image.

allocate

Fbo.allocate(width, height, format=TextureFormat.RGBA8)

Creates (or recreates) the Fbo’s image, transparent black.

Parameters
Name Type Description Default
width int Width in pixels, at least 1. required
height int Height in pixels, at least 1. required
format TextureFormat | TextureFormatValue How the pixels are stored. TextureFormat.RGBA8
Raises
Name Type Description
ValueError A size below 1.
RuntimeError No App is running, or the Fbo is being drawn into.

clear

Fbo.clear(r=0, g=None, b=None, a=None)

Clears the Fbo’s pixels, in order with the draws around it.

Takes the arguments of kiln.clear, so fbo.clear() clears to transparent black and fbo.clear(255, 0, 0) to opaque red. Works inside with fbo: or outside it.

Parameters
Name Type Description Default
r float Red (0-255), or the gray level when g and b are omitted, or an iterable (r, g, b[, a]). 0
g float | None Green, or the alpha of clear(gray, alpha). None
b float | None Blue. None
a float | None Alpha, as in kiln.clear. None
Raises
Name Type Description
RuntimeError The Fbo is not allocated, or no App is running.

draw

Fbo.draw(x, y, w=None, h=None)

Draws the Fbo’s pixels as a textured quad.

It draws like Texture.draw: tinted by the current tint, placed by RectMode and the anchor set on texture, and transformed; w and h default to the Fbo’s size, in points. A negative w or h mirrors it (x becomes its right edge).

Parameters
Name Type Description Default
x float Left (or centre) x. required
y float Top (or centre) y. required
w float | None Drawn width. Negative mirrors left to right. None
h float | None Drawn height. Negative mirrors top to bottom. None
Raises
Name Type Description
ValueError The Fbo is the one being drawn into (a feedback loop).
RuntimeError No App is running, or the Fbo’s window has closed.

read

Fbo.read()

Returns the Fbo’s pixels, top row first.

Draws into the Fbo made earlier in the frame are rendered first.

Returns
Name Type Description
np.ndarray An (height, width, 4) RGBA array: uint8 (0-255) for RGBA8,
np.ndarray straight alpha (the stored premultiplied colour divided by its
np.ndarray alpha, as a PNG wants it); float32 for the float formats, the
np.ndarray stored values as they are (premultiplied where drawn blended),
np.ndarray values outside 0-1 kept. If the Fbo isn’t allocated, a warning
np.ndarray and an empty (0, 0, 4) uint8 array, as for a Texture (drawing it
np.ndarray warns and draws nothing too).
Raises
Name Type Description
RuntimeError No App is running, or the Fbo’s window has closed.

release

Fbo.release()

Frees the Fbo’s image.

Draws made earlier in the frame that use it are kept. Like a Texture’s, the image goes back to a pool, with its pipelines, for the next Fbo of exactly the same size and format, so an Fbo of the same size created every frame costs no new GPU objects. An Fbo of a new size every frame costs a new image and new pipelines each time (the pool keeps a few, and warns about the churn): keep one Fbo of a fixed size instead. Fbos are also released when garbage collected, and with their window. The Fbo can be allocated again afterwards.

Raises
Name Type Description
RuntimeError The Fbo is being drawn into (inside with fbo:).