Tiny Raytracer

I love ray tracers. Their combination of a simple algorithm and stunning results are hard to beat.

I’ve written several ray tracers over the years, but this time I decided to write the smallest possible one I could write. My current version is 959 bytes of Javascript, and I’m sure it’s still possible to shave off a few more bytes. Note that the size includes a simple scene definition.

Here’s the full source code:

var m=600,w=[m,[0,-m,0],9,9,0,m,2,1,[0,0,3],9,0,0,m,3,1,[-2,1,4],0,9,0,9,4,1,[2,1,4],0,0,9,m,5],A=2,B=[8,[2,2,0]],D=Math,E=D.sqrt,F=D.max,G=0,H=document.getElementById("c"),I=H.getContext("2d"),J=I.getImageData(0,0,m,m),K=J.data;H.width=H.height=m;function O(p,g){return p[0]*g[0]+p[1]*g[1]+p[2]*g[2]}function P(p,g,z){return[p[0]-g[0]*z,p[1]-g[1]*z,p[2]-g[2]*z]}function Q(p,g,z,C){t=m;for(v=q=0;r=w[q++];q+=6)if(j=P(p,w[q],1),a=2*O(g,g),b=-2*O(j,g),d=E(b*b-2*a*(O(j,j)-r*r)))for(e=2;e--;d=-d)f=(b-d)/a,z<f&&f<C&&f<t&&(v=q,t=f);return v}function R(p,g,z,C){if(!(s=Q(p,g,z,m)))return 0;N=P(X=P(p,g,-t),w[s],1);n=O(N,N);i=A;for(l=0;u=B[l++];)k=O(N,L=P(B[l++],X,1)),i+=u*!Q(X,L,1/m,1)*(F(0,k/E(O(L,L)*n))+F(0,D.pow(O(M=P(L,N,2*k/n),g)/E(O(M,M)*O(g,g)),w[s+4])));p=w[s+c]*i*2.8;z=w[s+5]/9;return C--?R(X,P(g,N,2*O(N,g)/n),1/m,C)*z+p*(1-z):p}for(y=h=m/2;y-- >-h;)for(x=-h;x++<h;){for(c=0;4>++c;)K[G++]=R([0,1,0],[x/m,y/m,1],1,2);K[G++]=255}I.putImageData(J,0,0);

And here’s the output:

The code above was generated by Google’s Closure Compiler. The original, fully commented source code can be found here. Note that the goal here was to make the source code as small as possible, not clarity; so even the original code before minification is a horrible mess. This doesn’t do justice to the elegance and simplicity of proper raytracer code; I’m writing a book to right this wrong.

It should run in any reasonable browser that supports the CANVAS tag and has a good Javascript interpreter. Here’s a live demo.

If you’re interested in the theory of raytracers, you may be interested in my textbook, Computer Graphics from scratch.