Status
Active development
Role
Sole author
Built with
C11, Software rendering, Audio synthesis, Win32 threads
Licence
MIT
Source
github.com/fkkarakurt/demoscene
Website
www.youtube.com/@fkkarakurt
Updated

Every frame and every audio sample in this project is computed. There are no textures, no samples, no meshes, no stock footage and no engine underneath it — the repository contains 53 files of C and nothing else, and what comes out is a film with a soundtrack.

That constraint is not nostalgia. It is what makes the code worth reading: nothing can be hidden behind an asset, so every artefact on screen and every rough edge in the audio has a cause that is somewhere in the arithmetic and can be found.

What is in itPermalink to “What is in it”

PartWhat it is
engine/The shared renderer and synthesiser: HDR framebuffer, stroke font, post chain, noise, thread pool, oscillators, filters, WAV and video sinks.
demos/01-coldstart/COLD START — two minutes, nine scenes, landscape. A timeline, a soundtrack and a set of raymarched scenes.
demos/02-runtime/RUNTIME — thirty seconds, vertical. The subject is the renderer: the picture is shown being computed, in the order the thread pool walks it.
demos/03-liftoff/LIFTOFF — thirty seconds, vertical. A launch to orbit, flown by an integrated trajectory rather than by keyframes.
tools/A smoke test, a font sheet renderer and the channel-art renderer. Built on the engine, part of no demo.

The size, counted with the command the repository states so anyone can reproduce it:

FilesLinesCode
engine/182,7151,998
demos/01-coldstart/132,3131,563
demos/02-runtime/71,404935
demos/03-liftoff/123,0671,906
tools/3713517
Total5310,2126,919

Third-party libraries: none. The engine links libc and Win32, and nothing else.

The two ideas the engine is built onPermalink to “The two ideas the engine is built on”

Everything is in linear light. The framebuffer holds three unclamped floats per pixel. Values above 1.0 are normal and wanted — they are what gives bloom something to bloom from and the tone mapper something to roll off. Tone mapping and sRGB encoding happen once, at the very end, in dm_fb_resolve. Anything that averages, blurs or downsamples gamma-encoded pixels darkens every edge it touches, which is the mistake behind most washed-out software bloom.

A scene is a pure function of time. No state carries from one frame to the next, so the renderer can jump straight to any timestamp. That is what makes a contact sheet of a whole two-minute demo possible in one command, and it is what guarantees that a preview and a final render show exactly the same picture.

Rendering is offline, on purposePermalink to “Rendering is offline, on purpose”

A frame that takes three seconds to compute still plays back at 60 fps. Giving up real-time buys motion blur by supersampling in time, high anti-aliasing counts, and effects that would never fit in a 16-millisecond budget. What it costs is a render measured in hours, which is why the renderer uses every core the machine has and why the scenes are sphere-traced distance fields rather than anything requiring a scene graph.

The soundtrack is generated the same way and by the same rules: oscillators, filters, envelopes and a reverb, rendered to a float buffer and written as a WAV. Band-limiting the oscillators is the single change that separates a synthesiser that sounds like an instrument from one that sounds broken.

Building itPermalink to “Building it”

.\build.ps1                 # builds demos/01-coldstart
.\build.ps1 -Tool smoke     # builds tools/smoke.c
.\build.ps1 -Debug          # -O0 -g, no fast math

gcc (MinGW-w64) and PowerShell. There is no makefile: three dozen translation units rebuild in about two seconds, so a dependency graph would cost more than it saves.

Three honest notesPermalink to “Three honest notes”

It is a Windows project as it stands, and does not have to be. The rendering and synthesis code is portable C11. Two files touch the platform: dm_job.c uses Win32 threads and dm_video.c pipes to ffmpeg. A pthreads and popen port of those two files is the whole job.

ffmpeg is not part of the picture. It packs finished RGB frames into an H.264 file, the same role the compiler plays for the source. Remove it and the renderer emits a numbered PPM sequence instead — larger, identical.

The release build uses -ffast-math, and a solver never should. These are different programs with different contracts. A renderer is judged by the pixels a viewer sees, where a reassociated sum that moves the last bits of a float changes nothing observable; a geotechnical solver is judged by whether two runs agree exactly, and there reassociation is a defect. The one place the distinction bites is NaN handling — the framebuffer resolve detects NaNs that leak out of scene code, so the build passes -fno-finite-math-only to keep that check meaningful.

Where the demos arePermalink to “Where the demos are”

The finished videos are on the KORMOS channel; the code that produced every frame of them is in the repository, under MIT.

← Back to all projects, or read the writing that comes out of them.