Two thousand seven hundred rays around a circle, each stopping at a randomly chosen depth, with a disc punched out of the middle.
Rays with random depth
The corona is 2,700 straight rays swept once round a circle. Every ray starts at the
same outer radius and ends at a depth read out of a table:
var stopSize = _size - stops[i / 5];
var innerX = (float)(Math.Sin(angle) * stopSize);
The outer end is on a circle. The inner end is not, and that is the whole
composition: what looks like an irregular fringe is 2,700 line segments of the same
kind, differing only in where they stop.
A sixth of the sweep. The rays are placed in angle order, and the inner boundary is
already visibly stepped rather than smooth.
Five rays to a step
var numStops = (int)Math.Ceiling(72 * Density);
…
var stopSize = _size - stops[i / 5];
There are 2,700 rays but only 540 stop values, and the index is i / 5 — integer
division. So each stop value serves five consecutive rays.
That is why the inner edge is a series of flat plateaux rather than a noise field.
Five rays at the same depth make a visible facet; the next five jump somewhere else
entirely, because the values are independent uniform draws with no smoothing between
them. The fringe is blocky by construction, and the block size is exactly five rays
— two thirds of a degree.
Two fifths. The five-ray plateaux are unmistakable now.
Seven tenths. 540 independent depths, each occupying two thirds of a degree.
The geometry is inside out
Two details in the arithmetic are worth reading carefully, because they are the
reverse of what the names suggest.
var _size = OuterScale - Size; // 36 − 190 = −154
OuterScale is 36 and Size is 190, so _size is negative. The stop radius is
then −154 − stops[…], with stops uniform in [0, 190) — giving inner radii from
−154 down to −344.
A negative radius flips the point through the origin. So the “inner” end of each ray
is on the far side of the circle from its “outer” end, and every ray is a chord
passing through the middle rather than a spoke pointing at it. The corona is a dense
crossing of long lines, not a starburst — which is why the middle needs covering.
The whole sweep, before the disc. All 2,700 rays cross the centre, and the disc that
will hide them is not there yet.
The disc is an eraser
using var fillPaint = new SKPaint { Color = Background, Style = SKPaintStyle.Fill };
canvas.DrawCircle(centerX, centerY, DiscRadius, fillPaint);
canvas.DrawCircle(centerX, centerY, DiscRadius, outlinePaint);
The disc is drawn in the background colour and filled. It is not a shape in the
composition; it is a hole punched through it, hiding the tangle where every ray
crosses every other. Then a one-pixel outline in the foreground colour gives the hole
an edge, which is what turns it from an absence into a disc.
Everything the eye reads as the disc is that single fill.
What can move
Everything above is the piece at its defaults, but the knobs the variants turn
are structural, not just cosmetic:
Sweep — the corona need not close. Less than 1 draws a fan that stops
mid-air, and the terminator between ink and paper is a straight line through
the centre.DiscShiftX / DiscShiftY — the disc need not sit on the centre. Off centre
it eclipses only part of the tangle, and the crossing rays spill out past its
far side.Disc2Radius — a second disc, punched the same way on its own spot: a
companion in transit across the disc’s rim, erasing a bite of corona and
outline as it goes.HaloRadius — one stroked ring around the disc, drawn over the rays, turning
the hole into a target.Accent / AccentEvery — a second ink for whole five-ray groups, so the
fringe is interleaved with wedges of another colour instead of one uniform
field.
Each variant still gets the whole progression: its stages sweep its own
fraction of the circle, so Daybreak’s plates build a fan, not a full corona.
Seven variants
| Rendering | What it changes | Ink |
|---|
| Lunar Cyan | The archetype: full sweep, centred disc, default everything | #00FFFF on #000000 |
| Eclipse Pink | Disc shifted off centre, so the corona spills past one side | #FF1493 on #1a1a2e |
| Solar Gold | A small companion disc grazing the rim, mid-transit | #FFD700 on #0a0a0a |
| Silver Halo | A stroked ring around the disc, like a winter halo | #D9DFE6 on #030303 |
| Daybreak | Half a sweep: the corona fans upward from a dark horizon | #F4EBD8 on #131A33 |
| Ember | Gold wedges interleaved in the red fringe, one group in four | #F04E23 + #FFD166 on #0C0806 |
| Snow Moon | Sparse, long rays behind a much larger disc | #CFE0F0 on #05070D |
Density controls both counts at once — rays as 360 × Density, stops as
72 × Density — so the five-to-one ratio between them is fixed and the fringe’s
block size in degrees is the same whatever the density. Raising it adds rays and
facets in proportion, making the corona denser without making the fringe finer.
Using the frame
Every rendering is drawn larger than the raw arithmetic would have it, by one
knob: Scale, which multiplies every distance about the canvas centre. The
presets set it so the longest rays finish a few pixels inside the canvas edge —
the corona uses the frame as its outer boundary instead of floating inside it.
The one place the darkness is deliberate is Daybreak’s lower half: the horizon
is the composition, and the empty indigo below the cut stays empty on purpose.
Whitespace is kept only where it is part of the picture.
Scale is a homothety — the stop table is generated from the seed exactly as
before, and the same seed stream draws the same corona, larger.
Hung on a wall
The piece ships one museum presentation: a gallery plate,
museum-lunar-cyan, that hangs the lead the way a gallery would — a wall, a
mat with a window, a frame around the mat, and a soft drop shadow lifting the
frame off the wall. The artwork is contain-fitted into the window and clipped
at the mat edge, like a print behind glass.
The treatment is a presentation layer, not a new family of renderings: it
wraps the finished drawing and adds nothing to the rule itself, and there is
deliberately no framed copy of every preset — one plate, the way one work
hangs on one wall. Mat, frame and shadow are fractions of the shorter side,
so the treatment scales with the plate, and the presentation composes the
finished drawing without touching the generative geometry.
Determinism
One Random is created per draw, seeded from the preset, and consumed once per
stop up front to fill the stop table before any ray is placed. Nothing else is
random. The generator is System.Random, which the project’s determinism policy
flags as not guaranteed stable across .NET versions.