[Greg] implemented a simple ray tracer for Arduino as a fun exercise and a way to benchmark the processor. He started out with the Moller-Trumbore algorithm, a common ray-tracing algorithm that calculates the intersection of a ray with a triangular plane without doing any pre-calculation of the planes. His code supports one static light and one static camera, which is enough to render a simple scene.
[Greg] started out with a small scene composed of a few polygons, but just finished up a scene with 505 vertices, 901 faces, and reflective surfaces (shown above). He made the above render on his PC emulator, but estimates that it would take just over 4 days to render on the Arduino. [Greg]’s project supports multiple bounces of light, which differentiates his ray tracer from some we’ve covered before (and which explains why it takes so long to render).
The ray tracer is implemented entirely with double-precision floats. This translates to a ton of software float emulation instructions, since the Arduino doesn’t have a floating-point unit. While this ray tracer can’t render anything near real-time graphics due to the slowness of the microcontroller, it’s still a great proof of concept.
The title image for this post was rendered on a modern PC, taking 263 seconds to complete. The same scene, at 64×64 resolution, was rendered on the Arduino, taking 4008 seconds to complete. That render is below.
Cutting a few corners the ATmega328 can do this:
https://www.youtube.com/watch?v=9ryBeJAs2I0
casting and tracing are two similar but different things
Yep. Raycasting can be done in constant time assuming a fixed screen size, while raytracing is PSPACE-hard.
Ray casting is not constant time. You are casting through some 2D
“The ray tracer is implemented entirely with double-precision floats. ”
Unfortunately, the arduino (based on avr-gcc) doesn’t support double precision floats. It accepts them syntactically, but converts them all to single precision
I initially thought of this:
unsigned char cowboyDouble[8];
But after looking at the source, no such craziness. :(
200+ seconds on a modern PC? i could do path tracing in that time XP
200 seconds on a modern pc is extremly slow, seeing how fairlight did it realtime (with a ton more detailed geometry) at 60fps in 2013
https://www.youtube.com/watch?v=i8hSZGTXTx8
The article states though that the large render, while done on the PC, was computed in an emulator, which could explain the slowdown
I don’t want to be mean, but I would have expected something more exciting than a suboptimal (doubles on an 8 bit MCU?) implementation of a standard algorithm. This somehow lacks the “hack” and the hack…
Also, triangles are not very suitable for raytracing. He could have easily built his scene from planes and spheres and get a massive speed up by reducing the number of intersections to calculated.
Don’t worry, the avrcc compiler doesn’t do doubles, it only does floats (it accepts ‘double’ in the source code but it uses ‘float’ to implement them).
Anyway; it sounds like you’ve just seen a glove hit the floor. We expect you to pick it up and post your riposte on here real soon…
Yes, I realized this a split second after I hit “post comment” :)
Lets see, I coded my last raytracer a couple of years ago…
What about the Arduino Due? I would think that would handle the double precision floats, at least.
Ummm, you’re missing the point. The correct way to ‘improve’ this hack is to use a Tiny85, not a Due.
Now, do it on an fpga :D
Probably slower than on a PC.
As the article clearly states this is to benchmark the Arduino against other platforms, if the goal is simply to draw 3d scenes then of course there are much faster ways to do it. Wolf3D-type engines can run on much less than this, I wrote a simple engine for the Arduino-based Gamebuino a while back (see https://www.youtube.com/watch?v=4m-Nj2IkDpo) and the bottlenecks in that demo were entirely due to the display, the 328p itself is surprisingly capable.
well, this is what 7MHz M68K can do
http://www.youtube.com/watch?v=-sAZWWbY4n4
Neat!
My two favorite raytracers are still that one written in C# as a single LINQ query, and the insane IOCC entry http://www.ioccc.org/2013/hou/hint.html
I wonder what kind of bounding a limits he used. Stop calculating after the X’th refraction/reflection. Y distance is ‘infinite’. Invisible bounding spheres around complex shapes.
Maybe Russian roulette for bounces…
Can you paralellise a number of Arduinos and render small bits of a big image?