---
title: "Skia · generative art"
description: "A random space, drawn until it casts a shadow. Generative art plate #31 by Theodore Vorillas, drawn live in your browser from its code."
url: "https://vorillaz.com/lab/skia"
---

![](https://vorillaz.com/_astro/skia.Cb49Q9xu_ZRlRXX.webp)

fig. #31 · rendered live in your browser from the code below

# #31 skia

A random space, drawn until it casts a shadow.

- date

  2026.10.13

- tags

  generative-art · javascript · webgl

A tall cube of random space, filled the way a drawing fills a page. Sheaves of hairline planes stand in it, each one rectangle repeated and nudged a little further along. Hundreds of walks follow a field of sines and turn back at its walls, so the tangle takes the shape of the room it is in. Cords swell and thin through it, and a few loops get out. Slabs stand upright or bristle out of a dense core, specks scatter around them, and a handful of orange threads wind through everything. The hairlines are laid down at partial strength, so where they crowd the drawing goes dark on its own.

Play it and it turns. Every so often it comes down from the top and another space builds up from the floor. Switch the ground to paper to draw it in black on white.

## The walls

```javascript title="skia.js"
// steer gently into the field; a wall turns the walk back into the room
for (let i = 1; i < n; i++) {
  dir = normalize(mix(dir, normalize(flow(p)), steer));
  p = p + dir * step;
  for (const a of [x, y, z]) if (abs(p[a]) > box[a]) {
    p[a] = sign(p[a]) * (2 * box[a] - abs(p[a]));
    dir[a] = -dir[a];
  }
}
```

## The sheaves

```javascript title="skia.js"
// one rectangle, repeated, each copy nudged further along its normal
for (let c = 0; c < copies; c++, depth += step) {
  const jitter = 1 + random(-1, 1) * 0.04;
  outline(plane(normal, depth), half * jitter);
}
```

## The ink

```glsl title="skia.frag"
// solids take a faceted light; hairlines are ink at partial strength,
// so where they crowd, the drawing darkens by itself
if (solid) colour = tone * (0.68 + 0.42 * light) + 0.1 * light * light;
else alpha = (1.0 - fade) * (1.0 - haze);
if (born > grow) discard; // built from the floor up
```

## References

- [Flow Fields](https://www.tylerxhobbs.com/words/flow-fields) by Tyler Hobbs, on walking curves through a field of angles
- [Reticulárea](https://en.wikipedia.org/wiki/Gego) by Gego, drawing with lines in the room instead of on the page
- [Incomplete Open Cubes](https://en.wikipedia.org/wiki/Sol_LeWitt) by Sol LeWitt, the cube as a frame to be left unfinished
- [Alpha compositing](https://en.wikipedia.org/wiki/Alpha_compositing), Porter and Duff’s over operator, which darkens where the hairlines crowd
- [Parallel transport frames](https://github.com/thi-ng/geom/blob/feature/no-org/src/thi/ng/geom/ptf.cljc), from thi.ng/geom, carrying the cords along their walks
