- C++ 86.2%
- CMake 13.8%
The exact byte count is the whole punchline — surface it explicitly with a verifiable wc -c invocation rather than hiding it as '~1337 characters' in a subordinate clause. |
||
|---|---|---|
| docs | ||
| .gitignore | ||
| card.cc | ||
| card_explained.cc | ||
| CLAUDE.md | ||
| CMakeLists.txt | ||
| README.md | ||
card-raytracer
A study of Andrew Kensler's "business card raytracer" — a complete recursive path-tracer with soft shadows, depth of field, anti-aliasing, reflections, a checker floor, and a sky gradient, all crammed into a single C++ source file small enough to print on the back of a business card.
card.ccis exactly 1337 bytes. Yes, leet. Verify it yourself:$ wc -c card.cc 1337 card.ccThat is not a happy accident — Kensler golfed the source until it hit the magic number. Every typedef (
iforint,fforfloat), every operator-overload trick onstruct v, and every absent space exists to land on 1337.
The original code is preserved verbatim as card.cc. A
de-obfuscated, heavily-annotated rewrite lives in
card_explained.cc. Both produce the same image:
The spheres spell a · e · k, Andrew Kensler's initials, encoded as a
9-column bitmap in the G[] array of the original source.
Quick start
Requires a C++14 compiler, CMake ≥ 3.16, and (optionally) netpbm for
PPM → PNG conversion.
cmake -S . -B build
cmake --build build
# Render with the original (PPM, 786 KiB, ~6 s on a modern laptop)
./build/card > aek.ppm
# Or via the convenience target:
cmake --build build --target image # → build/aek.ppm
cmake --build build --target image_explained # → build/aek_explained.ppm
# View it (PPM is supported by most image viewers; or convert):
pnmtopng aek.ppm > aek.png
What's interesting about it
The whole renderer is built on operator overloading: a single struct v
provides + (add), * (scale), % (dot product), ^ (cross product), and
unary ! (normalise). Once those are in place, the entire rendering
pipeline — sphere intersections, reflection vectors, Phong shading,
checker-pattern tile lookup, camera basis construction — collapses into
just a handful of expressions.
Other tricks worth admiring:
- Soft shadows for free: the light position is jittered each call, so averaging 64 samples per pixel produces a real penumbra without any area-light formalism.
- Depth of field for free: the camera origin is also jittered across a 99-unit "lens" each sample, so points off the focal plane go blurry.
- Anti-aliasing for free: sub-pixel jitter on the ray direction.
The same 64-sample loop pays for all three at once.
A line-by-line walkthrough of the algorithm is the long-form
comments inside card_explained.cc.
Layout
.
├── card.cc # original, untouched — do not edit
├── card_explained.cc # de-obfuscated, documented rewrite
├── CMakeLists.txt
├── docs/
│ └── aek.png # published render
├── README.md
└── CLAUDE.md # working notes for AI assistance
Credits
- Original raytracer: Andrew Kensler ("aek").
- Excellent walkthrough that inspired this study: Fabien Sanglard, Decyphering The Business Card Raytracer.
Licence
The original card.cc is reproduced as-is from publicly published material
for educational purposes; credit and copyright belong to Andrew Kensler.
The supporting files in this repository (CMake, README, de-obfuscated
rewrite) are placed in the public domain by the repository author.
