Shortest Ray Tracer

December 19, 2006

In 1992, Brad Grantham and I challenged each other to write the shortest ray tracer possible. The program should take a set of sphere coordinates and radii on the command line, and output an ASCII rendering of the scene:

% ray x1 y1 z1 r1 [x2 y2 z2 r2 ...]
            

For example:

% ray  0 0 0 15  -15 2 15 5  10 -10 10 5
...........................................................................
...........................................................................
...........................................................................
...........................................................................
...............................#########====::.............................
............................@@@@########=====:::-..........................
..........................@@@@@########======:::--.........##=.............
.........................@@@@#########======::::---....#@@@@###==:.........
........................#############======:::::---..=##@@#####==::........
.......................############=======:::::----..=#######===::-........
.......................##########=======::::::----...=========:::-.........
.......................#######=========::::::----....-::::::::--...........
.......................=============:::::::-----........----...............
.......................==========::::::::-----.............................
........................:====::::::::::-----...............................
......................###==:::::::::------.................................
....................@@###==:--.--------....................................
...................#####==::-...---........................................
...................=##==:::-...............................................
....................:::::--................................................
......................--...................................................
...........................................................................
            

The program with the shortest source code, measured in characters, would win. (Details: 80 characters per line maximum; the only compile switch is -lm for the math library; use .-:=#@ for the brightness of a pixel.) I spent an entire Wednesday on it, failing a statistics mid-term as a result.

In the end, my version was one character shorter than Brad's. Luckily, he kept them in his vast email archives. Here's mine:

#define s atoi(*b++)
float sqrt(),A,B,i,o,w=-22,_,h,r,d,e,f;main(L,c,b)char**c,**b;{for(;w<22;w+=2){
for(o=-39;++o<37;){b=c+1,h=0,i=9;while(*b)d=s,e=s,f=50-s,r=s,A=2500+o*o+w*w,B=f
*50-e*w-d*o,(_=B*B-A*(f*f+d*d+e*e-r*r))>0&&(_=(B-sqrt(_))/A,_<i&&(h=(f-_*(50+o+
w)-d-e)/r,i=_));putchar("......-:=#@"[(int)(h*3)+5]);}puts("");}}
            

This was Brad's:

l;float*T,sqrt(),s[80],x,y=6,X,Y,Z,d,*S=s,A,B,C;main(c,v)char**v;{while(*++v)*
S++=atoi(*v);for(;y>-6;y-=.6,puts(""))for(x=-8;x<8;x+=.22,putchar("...-:=#@"[l]
))for(d=9e9,l=0,T=s;T<S;T++)X=*T++,Y=*T++,Z=*T+++9,A=x*x+y*y+81,B=x*X+y*Y+9*Z,C
=B*B-A*(X*X+Y*Y+Z*Z-*T**T),C>0&&(B-=sqrt(C),B<d?l=(X-Y+Z-(d=B)/A*(x-y+9))*2/
*T+4:0);}
            

(The original specs weren't precise on where the eyepoint should be, so Brad put his at the origin and I put mine recessed from the origin.) Brad has since found two characters to remove, so in these versions Brad's is one character shorter than mine (326 to 327).

It's a worthwhile exercise to try to write one of these. You learn a lot about C. Start with a normal program and keep shortening it. If you don't have that much time, then just try to shorten one of the above two programs. You'll probably find a lot of ideas that, when tried, either make the program longer or crash it.

~ See all projects ~