Coding with Balls

May 10, 2016


Filed under: Uncategorized — codingwithballs @ 19:12

A couple of people have asked about the effects in Dataskull so I figured I’d post this (originally from an email right after the demo compo).

And just to remind you what it’s all about: Dataskull is a demo for “high-end Amigas” (AGA, 68060 CPU at 50MHz or above) which was released at last years Assembly in Helsinki (where it ended up 3rd in the Amiga compo).

This was a fairly quick project done in about a week (right after the much more time-consuming Korreks) because I didn’t want to show up at Assembly without a demo when they had their first dedicated Amiga compo since 1999 (and because my friend Wrec deserved a birthday greeting!)

The main effect was based on some old ideas and unfinished code I’d wanted to pick up again and its main purpose was to look massive and voxel’ish.

The tech

It’s actually just z-sorted point sprites with a lot of hacking. 🙂 (Note: these aren’t Amiga hardware sprites, but “CPU sprites” plotted into a chunky buffer).

Offline processing

I started with volume data from a CT scan of a skull which I downsampled and thresholded to a more manageable size, storing the resulting points (those with high enough density) as regular 3d coords.
Since this was still far too much data for the poor A1200 I then did optimistic (lossy) view-dependent pre-culling to bring it down to a manageable number of sprites. This was basically just brute-forced by rendering the object from a lot of different angles and then removing the points that didn’t contribute enough to the final image (because they were too small, occluded by other sprites, or not visible in enough frames).

The final skull object used in the demo consists of just 1909 3D points (the cluster of spheres is 1828 points).


The points were transformed in 3D, z-sorted (cheaper than a z-/span- buffer due to the slow memory, small sprites and relatively high penalty of conditionals) and rendered with basic depth shading (and 2D screenspace clipping) into a 160 x 96 pixels buffer (1/4 size of the final screen).

This was then used as the source for various combinations of 2 post-processing effects which produced the final 320 x 192 screen buffer.
The noise filter does edge detection on the z-shaded sprite buffer and spawns 2D dots which move pseudo-randomly out from the edges.
The voronoi filter just uses precalculated look-up tables to draw voronoi cells that are colored based on the contents of the 160 x 96 sprite buffer. (In other words, it’s just basic “tunnel effect tables”.) There are 8 different tables for different amounts of cells (“voronoi resolution”, if you will). Each buffer is 320 x 192 x 16bits.

And while all of this runs at ~16FPS (every third frame) on an A1200 with a 50MHz 68060 CPU we adjust the hardware color registers from the vblank interrupt at 50 FPS to add instant coolness and give an illusion of higher effect frame rate (at the risk of triggering some photosensitive epilepsy).

I also switched between 2 different sprite renderers throughout the demo to balance performance against the zoom level of the object: One slightly faster version that just plotted fixed-size squares, and one slower but better looking version that plotted circular(‘ish) shapes at different sizes.

Highest voronoi resolution - sprite size adjusted to match object size

Highest voronoi resolution – sprite size adjusted to match the on-screen size of the object

Too small sprites causing ugly gaps - Increase sprite size or apply aggressive post-processing!

Too small sprites causing ugly gaps – Increase sprite size or apply aggressive post-processing!

Lowest voronoi resolution - ok sprite size

Lowest voronoi resolution – ok sprite size

A couple of weeks after the compo I also did some work on a final version of the demo. The intro part has been improved quite a bit, but I never got around to fixing the sync and post-proc for the main part. I’ll see if I manage to get it out at some point.

Blog at