Skip to content

Repository files navigation

f1-round2

A 124-second 4K film of a Formula 1 car, shot as one unbroken camera take with zero cuts — in which every polygon, every material and every sound is generated by code in this repository.

resolution    3840 x 2160
frame rate    24 fps
frames        2,978            (124.0833 s)
cuts          0
samples       512
grade         AgX, look None, exposure -3.628
renderer      Blender 5.2.0 LTS / Cycles / OptiX
render        3 rented RTX 5090s, 2026-08-09 -> 08-13, $132.57
triangles     17,707,774,735 evaluated per frame   (52.7 trillion across the film)
              138,073,595 unique, resident once -- instanced 128x

Those two triangle figures are different quantities and are not interchangeable; docs/SCALE.md defines all four of them, gives the source line for every number in this file, and records the one measurement disagreement that is still open.

The camera starts inside a showroom, flies through a wall as it is breached, out onto an access road, and away around a 3,675 m circuit — as a single continuous path through one continuous world. There is no cut to hide a transition behind, which is the constraint that produced most of what is in here.


Nothing was downloaded. Nothing was sampled. Nothing was generated by AI.

This is the second hard rule after the single take, and it is meant literally:

  • no downloaded or purchased 3D models — the car, the circuit, the grandstands, the barriers, the crowd, the debris are all built by Python here
  • no HDRIs — the sky is a node graph in world/build_sky.py
  • no photographic textures — every material is a procedural node graph
  • no sample libraries — the audio is synthesised from physical models in audio/; the engine note is a mode series, not a recording
  • no AI-generated images, video, audio or geometry anywhere in the pipeline

What that produced, by the numbers: a 3,675 m circuit; a vegetation library of 33.62 M base-library triangles over 1,432 unique meshes, placing 27,969 woody objects (24,646 woodland + 3,299 hedgerow + 24 avenue) alongside 38,847 shrubs and ~4.86 M ground-cover instances; ~45 individually-gated item modules; a crowd; and a soundtrack — all from scripts in this tree. Every one of those numbers has an entry behind it in docs/DEFECT-LOG-R2.md, usually because someone got it wrong first.

(Those are the shipped world's figures, measured from render/world/assembly/r2/assembly15_build.json. This paragraph previously read "33.26 M … 26,641 trees", which was assembly5-era — the same superseded-terrain chain docs/SCALE.md §9 is about. docs/README.md:173 still quotes the old pair while describing a historical document; that instance is left as written.)

The only thing carried in from the previous round is a 2.4 MB build recipe under round1_source/ (see its PROVENANCE.md) — deliberately the recipe and not the 288 MB artefact it produces.


Start here

if you have read
five minutes, and no interest in films docs/BROKEN-INSTRUMENTS.md — twenty-six cases of a check that passed while the thing it guarded was broken. Written for a reader who knows nothing about this project.
ten minutes docs/READING-LIST.md — sixty entries out of ~1,300, each with a line on why it is worth opening. There is a ten-minute list at the top.
an afternoon docs/README.md — how the engineering log is organised, which documents are live and which are historical, and a glossary.
to know how big this thing is docs/SCALE.md — the film in measured triangles: the four definitions, the four census layers, the per-module breakdown, the render settings and the GPU bill. Every figure with its source line.
to find one specific thing docs/INDEX.md — every file in docs/, one line each.
twenty seconds and a terminal Run something, below.

The most unusual thing in this repository

Not the film. docs/BROKEN-INSTRUMENTS.md — a catalogue of this project's own checks that reported success while the thing they guarded was broken. One failure, found twenty-six times, in subsystems that share no code and were written weeks apart:

A guard, gate, metric or report returned the same answer whether the defect it existed to catch was present or absent.

Three of the cases, to show the shape:

  • A limiter reported 0.124 dB of gain reduction while removing about 22 dB (§IV.1). The measurement was taken correctly and then overwritten by the code's own arithmetic four lines later. The project read −0.124, declared the limiter innocent, and went looking elsewhere.
  • A quality gate whose best possible score was silence (§II.1). Every gate in the audio suite was relative — ratios, spans, correlations — so digital silence scored perfectly on all of them. A tuning loop walked downhill towards a better score and arrived: the delivered passage measured 26.4 dB SPL with 0 of 29 third-octave bands above the threshold of hearing. It was caught by a listener, not by an instrument.
  • A gate suite that passed a two-second block of audio tiled 16.5 times (§I.1). Eight gates, all green, ALL_PASS = True, on 33 seconds of literal loop. Three of the eight never opened the file.

The document is grouped by mechanism rather than by subsystem, because the mechanism is the transferable part, and it ends with a Corrections section retracting two claims that had circulated in this project as folklore and did not survive being checked against their sources.

Most repositories do not ship this. This one leads with it: an append-only log of ~1,300 numbered entries that records what was tried, what was measured, and what turned out to be wrong — including entries that retract their own author's published findings, and one that retracts a retraction.


Run something in twenty seconds

Nothing here needs the film, the render farm or the 545 GB of gitignored artefacts. There are 45 item modules under world/items/, and 27 of them carry a selftest — which is the interesting part, because it builds the geometry, measures it, and prints what it measured rather than a green tick.

blender -b -noaudio -P world/items/armco_post.py -- --selftest

About 20 seconds on a laptop, no GPU required. It builds 3,236 crash-barrier posts and then argues with them:

   3236 distinct post specifications over 3236 posts; 0 exact duplicates
   naive [tangent, normal, up]: 1685 of 3236 records are LEFT-handed (det = -1)
   `_world_frame`:              det min 1.000000 max 1.000000; 0 left-handed
   LOD0:  69547 tris/post   edge p10  0.687 mm =  0.99 px
   SELFTEST PASSED

Twenty-seven of the 45 item modules carry --selftest. All 27 were run on 2026-08-18 and the results are in docs/QUICKSTART.md, untidied: 20 pass, 5 fail, and 2 are neither. The failures are the useful rows — each is a disagreement with a manifest or another module, stated in metres or in slots, which is more informative than a pass. And one module runs its selftest, exits 0, and prints nothing at all: no checks ran. That is this repository's founding defect, found live while writing the page that describes it.


How the world is built

The world is assembled, not modelled. Each module owns a slice of the scene and knows nothing about the others except through a contract:

world/world_contract.py ownership rules — who is allowed to create what
world/build_terrain.py, build_surface.py ground, sward, asphalt and its relief
world/build_architecture.py, build_barriers.py showroom, pit buildings, armco, catch fence
world/build_dressing.py, build_nearband.py scatter and the detail band nearest camera
world/build_sky.py, showroom_lighting.py, film_exposure.py light and grade
world/items/ ~45 individually-gated item modules (trees, masts, seating, …)
world/build_items.py places items, and refuses to run on any item lacking an accepted gate verdict
sim/ the breach: fracture, debris, ride pose, contact
audio/ engine, chain, glass and master — synthesised, never sampled

Assembly runs every module into one scene and saves a single .blend:

blender -b -noaudio -P render/world/assembly/r2/assemble.py -- --out assembly.blend

render/world/assembly/r2/SHIPPING.md records which assembly is the shipping world and why it was promoted. That file matters more than it looks: the film build appends the car and props onto a prebuilt world and does not rebuild it, so a landed change to a world module reaches no frame until assemble.py is run again. The staleness warning it prints is not a refusal.

How it is rendered, and what that costs

Never straight to 4K. docs/RENDER-LADDER.md sets out the rule and the reason: stills and sequences catch different defect classes. A 4K still shows you a material reading as plastic; only a sequence shows flicker, popping shadows, sim jitter, camera-path kinks, speed-ramp stutter, or a seam where two machines rendered adjacent ranges. So work climbs the ladder — 720p and 1080p sequences, stripped to frames and inspected — and 4K is the last rung, not the first.

The master itself was not rendered locally, and could not have been:

full 4K master three rented RTX 5090s, launched 2026-08-09 ~04:30Z, 2,978/2,978 frames on disk 2026-08-13 05:45Z — about 97 h wall clock against a projection of ~84 h — for $132.57 against a $150 ceiling
one 4K frame minutes, not seconds; a local 8 GB card cannot hold one in a single pass
rung 1 (1280×720, 64 spp) cheap enough to iterate on, and explicitly not able to adjudicate a delivery-spec question
an item selftest ~20–60 s, CPU only

Frame ranges were dispatched to the rented GPUs by the broker in the companion repository, vast-render — it rents instances on vast.ai, ships the assembled .blend, renders ranges, fetches frames, verifies them and tears the fleet down. If you intend to reproduce the film rather than read about it, you need that repository and a funded vast.ai account. docs/MASTER-RUNBOOK.md is the record of the run — what had to be true, what it cost, and what was checked at each retirement.

Nothing here makes a 4K master cheap. This repository does not include the rendered frames or the delivered master; both are far too large and are regenerable from what is here.

The gates, and what "verified" means

The recurring failure this project kept finding is not a bad render. It is a check that passes without having measured anything. Several things follow from that, and they are the actual engineering content of the repository:

  • Gate verdicts are records, not artefacts. render/items/*/gate.json is the verdict of the run that accepted the geometry that shipped. Re-running the gate cannot restore it; it can only produce a different verdict with the same filename. That is why 33 of them are tracked here while everything else under render/ is ignored.
  • A gate must be able to fail. The battery under render/world/assembly/r2/ ships control scenes alongside the probes, so a probe that would pass anything is caught by a control it should have rejected.
  • Measuring the film against itself proves nothing. Several gates passed worlds that were days behind their own generators, because every one of them measured the built scene rather than the sources it came from.
  • A convention is not a rule. The 11.25 GB delivery master sat untracked with nothing but "never git add -A" protecting it, until an ignore rule replaced the convention.

tools/ holds ~250 single-purpose probes and A/B rigs written for individual defects. They are kept rather than deleted because the measurement is the evidence for the fix.

The defect log

docs/DEFECT-LOG-R2.md is the largest thing in this repository and the reason it is worth publishing. 67,640 lines, 1,316 entry headings, 1,295 distinct numbered entries (R2-001R2-4255), written as the work happened. (Measured 2026-08-18; the log is append-only and grows.)

It is not a changelog. Each entry records what was believed, what was measured, and what the measurement turned out to mean — including the many cases where the first diagnosis was wrong and the entry says so. The genuinely instructive entries are the ones where a fix that was verified turned out not to be in the shipped output at all, where a gate was found to have never run on the world that renders, and where a resource limit was found wearing the costume of a verdict about the work.

Do not start at line 1. Start with docs/READING-LIST.md.

The commit history reads the same way, and deliberately: commit subjects state the finding, not the file that changed.

Related documents: docs/MASTER-PLAN.md (the plan), docs/THE-BRIEF-ROUND2.md (the original brief and its laws), docs/MASTER-RUNBOOK.md (the master render), watch/INDEX.md (what was reviewed and what was concluded).

Prerequisites, honestly

  • Blender 5.2.0 LTS. Not "5.x" — the project pins this version and the broker installs exactly it on rented instances, because a scene must be rendered by the build that assembled it.
  • Python 3.14 for the standalone tools in tools/. Scripts run inside Blender use Blender's own interpreter, not this one.
  • numpy, scipy, soundfile for the audio modules, in whichever interpreter runs them. There is no requirements.txt and no packaging; nothing here is installable as a package and everything is run as a script.
  • An NVIDIA GPU for Cycles/OptiX if you want pictures. Selftests and the audio synthesis do not need one.
  • ffmpeg for encoding, if you want a video rather than frames.

Things a fresh clone will not do

Stated plainly rather than discovered later:

  • Paths assume the repository sits at ~/f1-round2. 135 Python files and 64 shell scripts used to carry the author's absolute home directory. They now use os.path.expanduser("~/f1-round2/…") in Python and $HOME/f1-round2/… in shell, so a clone into ~/f1-round2 runs unchanged and a clone anywhere else does not. There is still no configuration layer; there is now a convention, and it is one line to see: grep -rn 'expanduser("~/f1-round2' tools/. Records under docs/, render/ and audio/out/ quote the same paths repo-relative, which is what you want when reading a verdict.
  • The rendered outputs are not here. render/, work/, world/ bakes and watch/ are gitignored — several hundred gigabytes of blends, frames, caches and the delivered master. The repository is source and reasoning only.
  • Some tooling is not committed. A number of one-off probes under tools/, sim/ and world/items/, and ten docs/STAGING-*.md files, exist on the authoring machine and are not in the repository. Of the entry IDs in those staging files, all but one (R2-1661) were already merged into docs/DEFECT-LOG-R2.md, so the loss is one entry rather than ten files' worth — measured, not assumed.
  • Some selftests fail here. See docs/QUICKSTART.md for which, and why that is left visible rather than tidied away.

What is tracked, and why any of this is in git at all

The .gitignore is heavily commented and those comments are load-bearing — read them before simplifying anything. The short version is in its header: version control was added on 2026-08-03 after an edit truncated a 1,655-line reference document to 538 lines with no backup and no way to recover it. The lost sections are still lost.

So the rule is: track the source and the reasoning; do not track the artefacts. Everything large and regenerable is ignored. Where real, hand-written source turned out to be sitting inside an ignored directory — the gate battery in render/, the film bar's two measurement probes in work/, the item gate verdicts — it is re-included one directory at a time, and each of those blocks carries the incident that motivated it.

Contributing

See CONTRIBUTING.md. The short version: the append-only log is the house style, corrections are appended rather than applied in place, and a change that fixes a defect should say how the fix was measured.

There is one thing to do before your first commit — set a noreply git identity:

git config user.email 'ID+username@users.noreply.github.com'
git config user.name  'Your Name'

This is local configuration only, and it changes nothing already committed. The existing history carries personal addresses on most of its ~640 commits (git rev-list --count HEAD). Rewriting it is a live option and is the owner's decision: measured against this repository's object store, the documentation cites 83 distinct commit SHAs in 218 places, all of which a rewrite would de-reference. (An earlier figure of "~4,100 SHAs" circulated in this repository and was wrong — 4,100 is the scale of the R2-NNNN entry-ID citations, which a history rewrite does not touch at all. The correction is recorded in docs/PUBLICATION-AUDIT.md §6.)

Before publishing, re-run tools/publication/sanitise_docs.py. Its README says why "once, and then trusted" is not good enough for a corpus that is still moving.

Licence

Three kinds of work live here and they are licensed differently. LICENSE is the authority; this is the summary.

Code GPL-3.0-or-laterworld/, tools/, sim/, audio/, render/, anim/, telemetry/, work/, round1_source/, and every .py / .sh / build-input .json wherever it sits
Documentation CC BY-SA 4.0docs/, README.md, round2_inventory.md, watch/*.md, and the .md files beside the modules they describe. Full text in LICENSE-DOCS.
The film and its audio all rights reserved, not licensed for reusewatch/*.mov, watch/*.mp4, the rendered frames, the masters under audio/out/. They are gitignored and are not published with this repository.

Why GPL and not something permissive. Not a preference. Blender is GPL, and the Blender Foundation's stated position is that publicly distributed scripts using the bpy API are derivative works of Blender and must be GPL-compatible. Nearly everything here is bpy code. Worth being precise about the strength of the claim: this is the Foundation's stated interpretation, not settled case law — it is adopted because it is the conservative reading, and because being wrong in the other direction is the more expensive mistake.

Why the film is called out separately. So that nobody infers a grant from silence. A licence file that covered "everything in the repository" would be read, wrongly, as covering the film if a copy ever travelled alongside it. Renders you make by running this code are yours.

Individual source files do not carry per-file licence headers. LICENSE section 1 names the covered directories and file types explicitly, and is the authority for any file that does not say otherwise.

The owner can change any of this before publishing. These licences were applied so the repository would not go public in the no-licence, therefore all-rights-reserved default that makes public code unusable. After the first public copy the position is asymmetric: future versions can be relicensed, copies already released cannot be recalled.

About

A 124-second 4K film of an F1 car in one unbroken take, where every model, material and sound is generated by code — no downloaded assets, no HDRIs, no photo textures, nothing AI-generated. Ships its own engineering log: ~1,300 entries recording what was measured and what turned out to be wrong.

Topics

Resources

Code of conduct

Contributing

Stars

16 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages