Undefined Symbol screenshot

Released at Nova 2020, 4KB Executable Graphics (a single 4KB executable file generates this image, with no external data) with help from Lia-Sae.

Download on Demozoo

The challenge: Rendering realistic cloth

I was thinking a lot about materials before I started this, particularly how texture isn’t really a thing when you look close enough: there’s only geometry and material. Texture is how we perceive fine surface details.

It follows, then, that realistic rendering should use ultra-detailed geometry, not textures.

I decided to try it, by rendering cloth 🤦‍♀️

Breakdown

To give the scene some scale, I had to show cloth up close. That ended up being difficult - how to show it nicely and give it scale? I decided to make tiny cloth flags and carpet, and use Lego to give it a sense of scale.

I started with the lighting. The ambient light has a blue tint and the main light yellow to indicate daytime / sunlight. To provide a visual cue that we’re indoors I added some shadows across the scene, perhaps the wooden frame between window panes.

Lighting setup

Getting the lighting right is important - without the main (sun) light, the scene looks drab and flat.

Lighting setup

Apart from that the scene is quite simple - carpet, 2 flags, some lego blocks.

Cloth rendering

Here’s how the cloth works:

Zoomed cloth

Zoomed cloth

Zoomed cloth

Zoomed cloth

It’s literally just modelled down to fibre level 🙃 With path tracing this is actually viable - with many samples per pixel aliasing is not an issue, and because light bounces around within the threads the lighting and colour is realistic.

Generating this as a mesh clearly isn’t viable, so this is rendered as a raymarched SDF (signed distance field). In fact only 2 single fibres are drawn - they’re repeated, twisted around themselves to form threads, mirrored and twisted again to form ‘string’ (Lia-Sae will probably tell me that’s the wrong term ;) then repeated and woven together to form cloth.

This is how it works in cross-section:

The importance of light bounces

Each time the ray bounces, it transmits colour from the surface. This means if a ray bounces multiple times within the cloth, it both increases the brightness of the cloth and also the richness of the colour.

This turns out to be critical:

Effect of light bounces
5 bounces per sample

Effect of light bounces
15 bounces per sample

The downside

Of course there’s a catch: rendering geometry this fine is expensive. I optimised this to hell, and it’s still very slow - especially when many light bounces are needed. I think in the end the release version only manages ~12 samples per pixel on my GPU (a Vega 56), which is why it’s a bit noisy…