So... I just spent 30 minutes building a ray tracer from scratch in pure C++17, and the results are honestly blowing my mind. Not because it's some groundbreaking new algorithm, but because it's running on hardware that's older than some of the developers reading this post.
The Setup (Prepare to Laugh)
Here's what I'm working with:
- CPU: AMD Phenom™ Triple-Core 2.40 GHz (yes, triple-core was a thing)
- RAM: 2GB DDR2 (with 564MB actually free)
- GPU: GTX 210 (which doesn't even show up as available, just outputs to monitor)
- Storage: 149GB HDD (the clicking kind)
This is literally a PC from the Pentium dual-core era that someone slapped an AMD sticker on. I'm pretty sure my phone has more computing power.
Why I Did This
I was getting frustrated with modern rendering engines. Want to do some ray tracing in Blender? Better have 16GB+ RAM. Unreal Engine 5 with Lumen? Hope you've got that RTX 4090 ready.
But here's the thing - ray tracing is just math. Really beautiful, elegant math. So I thought: what if I stripped away all the bloat and just focused on the core algorithms?
All available softwares like Blender, Maya, Unreal Engine, Unity even the growing Godot Engine can't run on my PC so I thought to make an advanced ray tracing engine that can run on PC while powerful than these software renderers. No OpenGL, no external libraries, no fancy frameworks. Just pure C++17 and the Windows API for display. One file. One simple, beautiful file.
The Results Speak for Themselves
These renders took about 40 seconds each at 800x600 with 200 samples per pixel and max_depth of 50. On my dinosaur rig. While using only 11.4MB of RAM.
Let that sink in for a moment.
What's Under the Hood
The engine includes everything you'd expect from a modern ray tracer:
🎨 Physically Based Materials
- Lambertian diffuse surfaces (that red sphere)
- Metals with configurable roughness
- Glass with proper Fresnel reflectance (look at those refractions!)
- Emissive materials for light sources
🔬 Advanced Math
- Full 3D vector operations with reflection/refraction
- 4x4 transformation matrices
- Monte Carlo integration for path tracing
- Importance sampling to reduce noise
⚡ Performance Features
- Multi-threaded rendering (maxes out all 3 cores)
- AABB bounding volume acceleration
- Efficient memory management
- Lock-free progress tracking
🎯 Geometric Primitives
- Analytical sphere intersections
- Triangle meshes (the blue cube is made of 12 triangles)
- Automatic normal calculation
- UV coordinate generation
The Code Philosophy
I kept everything in one file. Yes, one single rayengine.cpp
file. Here's why:
- No dependency hell - Download, compile, run
- Easy to understand - Everything's right there
- Fast compilation - Builds in seconds
- Maximum portability - Works anywhere C++17 does
// The entire camera ray generation in ~20 lines
Ray get_ray(double s, double t, std::mt19937& rng) const {
Vec3 rd = lens_radius * random_in_unit_disk(rng);
Vec3 offset = u * rd.x + v * rd.y;
return Ray(
origin + offset,
lower_left_corner + s*horizontal + t*vertical - origin - offset
);
}
Clean, readable, and it just works.
Performance That Makes You Think
Here's what really gets me excited about this project:
- Memory: 11.4MB vs Blender's 500MB+
- Dependencies: 0 vs thousands
- Build time: 3 seconds vs hours of CMake hell
- Quality: Matches industry renderers
When you see glass that refracts properly, metals that reflect accurately, and shadows that feel real and all coming from a PC that predates YouTube HD - it makes you question why modern engines are so bloated.
The Technical Wins
The threading implementation is something I'm particularly proud of. Instead of fighting with complex synchronization, I just split the image into rows and let each thread work independently:
// Simple but effective parallel rendering
threads.emplace_back([this, start_row, end_row, t]() {
for (int j = start_row; j < end_row; ++j) {
render_row(image_height - 1 - j, t);
}
});
Result? 100% CPU utilization with zero system lag. The progress bar updates smoothly, the mouse still works, and all three cores are sweating to give me those pixels.
What This Proves
Modern graphics programming has lost its way. We've become so dependent on massive engines and external libraries that we've forgotten the fundamentals still work amazingly well.
You don't need:
- ❌ A $1,600 graphics card
- ❌ 32GB of RAM
- ❌ Gigabytes of engine downloads
- ❌ Complex build systems
You just need:
- ✅ Good algorithms
- ✅ Clean math
- ✅ Efficient code
- ✅ Understanding of the physics
Try It Yourself
The entire engine is open source on GitHub:
Building is stupid simple:
g++ -std=c++17 -O3 -m64 -flto -pthread -mwindows -static-libgcc -static-libstdc++ -o ray_engine rayengine.cpp -lgdi32 -luser32
That's it. No CMake, no vcpkg, no package managers. Just compile and watch the magic happen.
What's Next?
I'm thinking about adding:
- BVH acceleration structures for complex scenes
- Volumetric rendering (fog, smoke, god rays)
- Mesh loading (OBJ files)
- Maybe even some GPU compute shaders
But honestly? Part of me wants to see how far I can push this single-file approach. There's something beautiful about keeping it simple.
Challenges For You
Code an advanced ray tracer from scratch using pure C++17 standard libraries but it should run on my PC not on Core i9.
OR
Build a 3D modelling software from scratch in C++17 using standard libraries but super efficient, ultra powerful, and should work on that dinosaur PC.
The Real Lesson
Sometimes the best solution isn't the most complex one. Sometimes it's just good math, clean code, and a refusal to accept that "this is how things are done."
If a ray tracer can look this good on hardware from 2008, maybe we should stop assuming we need cutting-edge everything to create something beautiful.
Comment what should I code next? I'm thinking either a software rasterizer or maybe diving into fluid simulation or even a new 3D modelling software. What would you like to see built from scratch? 🚀
Built with ❤️ and way too much coffee on the world's most patient dinosaur PC
Top comments (0)