
Recursive raytracer in 35 lines of JavaScript - ggambetta
http://jsfiddle.net/vz5aZ/2/
======
Taylorious
This is very cool. Interestingly it was generated by Google's Closure
compiler. The author has the full source with excellent comments on his site.

link:
[http://www.gabrielgambetta.com/tiny_raytracer.html](http://www.gabrielgambetta.com/tiny_raytracer.html)

~~~
10098
from his site:

> Their combination of a simple algorithm and stunning results are hard to
> beat.

that's exactly what fascinates me about raytracing. It's pretty
straightforward, you literally emulate the light bouncing around, but given
enough resources the results can be surprisingly good-looking.

~~~
maggit
For interest, the method of literally emulating light bouncing around seems to
be called Photon tracing
([http://en.wikipedia.org/wiki/Photon_tracing](http://en.wikipedia.org/wiki/Photon_tracing)).
It creates realistic renderings of just about anything if you can afford the
time to render it. Rendering times are prohibitively high, though, because
this rendering method emulates lots of photons that never hit the sensor.

Ray tracing, although very powerful, has some limitations because it goes the
other way: It casts rays from the sensor into the scene.

~~~
ohwp
This is where path tracing steps in. Bi-directional path tracing combines both
photon tracing and ray tracing.
[http://en.wikipedia.org/wiki/Path_tracing](http://en.wikipedia.org/wiki/Path_tracing)

~~~
logicallee
could you elaborate on where the symmetry breaks down?

From your comment and another one here, it seems to be the case that actually
some of the photons that don't hit the sensor still affect the image (either
that, or you can't get back to the source starting at the sensor for some of
the photons). In other words, if a light source emits a trillion photons
everywhere in the room, and your sensor (the idealized camera) catches ten
million photons, then it's not strictly equivalent to trace back the ten
million maths to the light source, and ignore the ones that didn't make it to
the idealized camera.

If it were equivalent, you wouldn't need "photon tracing and ray tracing" or
bidirectionality.

But I'm struggling at where the symmetry breaks down, since it seems that
tracing a path back from the sensor along the same angles should produce the
same result as tracing it forward from the light source - for the photons that
directly or indirectly (after a certain number of bounces or passing through
the materials) make it to the idealized camera.

But the ones that _don 't_ make it to the idealized camera - how can they
still affect the frame? Or (equivalently), when is it the case that you can
trace it forward to the camera but not backward from the camera?

Why do you need bidirectionality? Where does the symmetry break down?

~~~
zeidrich
When you do photon tracing, you begin with beams of known intensity,
wavelength, direction because you are aware of the light source. That combines
with everything else that hits the sensor to give the image.

When you do ray tracing, you don't immediately know if 10 million photons were
captured. You know how many rays you are going to send based on the resolution
of the image. This also means there's issues with say light coming from narrow
apertures because you limit yourself to a finite number of rays.

If you use photon tracing and a light source sends 10 million photons and
70,000 are absorbed that's 70,000 data points to define the image which may be
plotted on a 200x200 canvas. If you use ray tracing with a 200x200 canvas you
will have the same size of image, but only get 40,000 samples. Even if you
expand the size of the canvas, there may be some photons which can reach the
camera but whose path the ray tracer can't reach.

For instance, say some photons hit the camera at pixel x-coordinates 10.0003
to 10.0005 through a fine aperture.

This will illuminate the camera in a photon tracing simulation. The ray tracer
will not capture that photon unless its resolution were 10,000 times higher.
The ray tracer will trace back from 10, 11. It can't do every intermediary
step. The photon tracer can account for those circumstances.

------
bemmu
Replace first line with this to get rid of jaggies with "supersampling" :)

var w = 1000;c.style.width = '500px';

~~~
d55
Also, increase the last int in line 34 to get deeper reflections.

------
ohwp
If you like this, maybe you also like this Path Tracer written in 99 lines of
C++:

[http://www.kevinbeason.com/smallpt/](http://www.kevinbeason.com/smallpt/) (+
source code and explanation)

~~~
reirob
Thanks for sharing this. Especially on the page there is a presentation as
well as several ports of this same program to other languages like OCaml,
Haskell and JavaScript. Interesting to see that the OCaml version is on par
with the C++ version performance wise, but is 47% shorter. However the Haskell
version is not shorter and 4.5 times slower?

------
onion2k
Impressive not only from a "ooo-that's-clever" perspective, but it's also
readable, tweakable code. Many of these tiny JS toys aren't things you can
really do anything with; this example is a great basis for learning.

~~~
ggambetta
Glad you liked it. It should be _far_ more readable, though; the constraint
here was code size in bytes, so even the non-minified code
([http://gabrielgambetta.com/tiny_raytracer_full.js](http://gabrielgambetta.com/tiny_raytracer_full.js))
is quite hacky (especially with the global vars, the horrible "tImageData"
hack, the assignments within if conditions, putting all the sphere data in a
flat array and playing with the indices,...)

------
thenomad
Along similar lines and (arguably) even cooler: full-on path tracing in WebGL
using a GLSL shader:

[http://madebyevan.com/webgl-path-tracing/](http://madebyevan.com/webgl-path-
tracing/)

~~~
hrjet
That has been optimised further by this guy here:
[http://mmmovania.blogspot.in/2011/11/snapshot-from-my-
latest...](http://mmmovania.blogspot.in/2011/11/snapshot-from-my-latest-glsl-
path.html)

------
lignuist
Those [anything] in [n] lines of JavaScript pieces are a great way to dive
into the code in order to learn. It is usually much easier to read through 30
lines than through 3000 lines. So it probably not very important that these
projects are not finished products.

~~~
CmonDev
You should try Perl - it's even less readable.

~~~
lignuist
I'm not looking for a language that is hard to read.

The great thing about such demos is, that everyone is able to read and run it
within minutes.

~~~
CmonDev
Yeah, readability is definitely an objective when you are trying to cram into
~30 lines.

~~~
lignuist
Try to read 30 lines of Brainfuck if you are a fan of unreadable languages. :)

[http://en.wikipedia.org/wiki/Brainfuck](http://en.wikipedia.org/wiki/Brainfuck)

------
cocoflunchy
I'm currently trying to write a raytracer in Python (I know, I know) but I'm
already at like 200 lines and no reflections, refraction, shadows or light
sources :(

But I won't quit! If you're interested, I'm already proud of what I have :)
[http://i.imgur.com/8wwSsab.png](http://i.imgur.com/8wwSsab.png)

------
kitsune_
Computers have become fast, I remember rendering a scene like this in PovRay
in the mid-90's and it took hours.

------
be5invis
I've got an interesting performance measurement:

On Chrome 31, it takes 3307 ms to render the image and on IE11 it takes only
2320 milliseconds.

So am I in the matrix?

------
filipedeschamps
Amazing job.

This is one of the coolest points of Javascript IMHO: you can see the result
and interact with it directly in your browser. Right here you will find
someone tweaking the code for supersampling, and you can apply it yourself and
see the result without hassle.

This generates an uncontrollable and very positive propagation effect.

------
cobrausn
Impressive, especially since it is still fairly readable. On the other end of
the spectrum, I give you raytracing on the back of a business card, in C++.

[http://fabiensanglard.net/rayTracing_back_of_business_card/](http://fabiensanglard.net/rayTracing_back_of_business_card/)

~~~
ggambetta
Not quite "the other end" \- the code I posted can be reduced to 960 bytes:
[http://gabrielgambetta.com/tiny_raytracer.html](http://gabrielgambetta.com/tiny_raytracer.html)

------
jcutrell
This is absolutely fantastic. Really impressive work with the material itself.

~~~
10098
pretty sure it's using standard blinn-phong shading. however, with the added
shadows and reflections it becomes much more interesting, doesn't it? :)

~~~
ggambetta
Right, just diffuse + specular with different coefficients. Nothing fancy
about the materials.

~~~
jcutrell
Makes sense - I'm not super familiar with how to make that happen in JS, so
it's all new to me. :)

------
vittore
Guys if you have links to other tiny things in js like that, of about 30 lines
of code or less, please send me links.
[http://30lines.info](http://30lines.info)

------
IvanK_net
I have written Path Tracer in JS
([http://renderer.ivank.net/](http://renderer.ivank.net/)) and rendered these
images:
[http://renderer.ivank.net/balls.jpg](http://renderer.ivank.net/balls.jpg)
[http://renderer.ivank.net/cornell.jpg](http://renderer.ivank.net/cornell.jpg)

but nobody is talking about it :( Maybe I should render a movie or something.

~~~
ggambetta
That's really impressive! Someone did post links to SmallPT somewhere in this
discussion, though.

------
albertzeyer
Raytracing works really good when you use the GPU for calculation, e.g. via
OpenCL or CUDA.

I just checked, there is already WebCL and an implementation for WebKit
([https://github.com/SRA-SiliconValley/webkit-webcl](https://github.com/SRA-
SiliconValley/webkit-webcl)).

Here is a video:
[http://www.youtube.com/watch?v=9Ttux1A-Nuc](http://www.youtube.com/watch?v=9Ttux1A-Nuc)

------
fekberg
I think this is awesome, however, I think it would be even more awesome to get
a walk through of the code and the thought process behind minifying it in a
blog post, the past days with all the jsfiddles are nice so don't get me wrong
on that part. I just think it adds more value if the code is somewhat
explained (I know ray tracing is explained on tons of places). Just my two
cents.

~~~
davidpardo
You can find the whole commented source at
[http://www.gabrielgambetta.com/tiny_raytracer_full.js](http://www.gabrielgambetta.com/tiny_raytracer_full.js)

~~~
fekberg
Thank you for that!

------
brador
I'm loving this jsfiddle 1-upmanship. Really squeezing out what it's capable
of.

------
staunch
If you haven't seen this yet, "The Physics of Light and Rendering | A Talk by
John Carmack" is really enjoyable.

[http://www.youtube.com/watch?v=MG4QuTe8aUw](http://www.youtube.com/watch?v=MG4QuTe8aUw)

------
nwh
Change the "w" variable to > 9000 and it completely kills Safari, can't even
close the tab or the browser. Sweet demo though, I remember being amazed
seeing this sort of thing the first time.

------
gumuz
Awesome! I tried to look into building a simple raytracer many times, but the
either math gets me everytime or I just didn't come across the right
"raytracer for dummies" tutorials.

Any suggestions?

~~~
ggambetta
The fully commented (but not entirely clean) code is here:
[http://www.gabrielgambetta.com/tiny_raytracer_full.js](http://www.gabrielgambetta.com/tiny_raytracer_full.js)

Also, I'm halfway through writing a Computer Graphics textbook, half of it
dedicated to raytracing.

~~~
jamiek88
I'd buy it, please post the link once its done, or if you want any proof
readers or people to type in the code to check for typos I'd be happy to help.

------
jebblue
That's impressive to me, don't like JavaScript but doing that is impressive.
It's also interesting to see how useful a canvas element is.

------
snake_plissken
Anyone got some good links to the algebra/geometry behind raytracing?

~~~
berkut
Depends how far you want to take it...

There's plenty of links on the web, but if you're really serious (it can be
quite addictive writing one), get hold of the "Raytracing/Rendering bible" :
Physically Based Rendering by Matt Pharr and Greg Humphreys.

There's also a plethora of research freely available with cutting edge
techniques to read.

~~~
snake_plissken
Thanks for the book reco!

------
ttty
Why this?

// Shorten some names. var math = Math;

~~~
choult
Capital letters are bigger, and therefore take up more space.

~~~
stickupkid
No.

------
jasongaya
Great, thanks for share with us.

------
eonil
This is interesting!

------
mrcactu5
it is great to see the reflections upon reflections.

~~~
ggambetta
<inception>Reflections upon reflections? We need to go deeper.</inception>

------
ThePhysicist
mind = blown

------
jheriko
i dont really understand why these things are considered impressive. all of
the technically challenging bits are handled by the enormous stack of
technology involved.

granted the js is highly size optimised, and that probably required some
reasonable effort. i see nothing clever here at all. also, the fact that its
35 lines is a weird measure - i can see ways to reduce that trivially - why
isn't everything to do with the render baked into the final loop?.

the byte count is a more useful measure.

4k/64k executable demos are much more impressive - even though there is a
stack of technology underneath you have to do things like butcher your C/C++
standard libraries or not use them at all...

~~~
PhasmaFelis
> _i dont really understand why these things are considered impressive. all of
> the technically challenging bits are handled by the enormous stack of
> technology involved._

For one thing, it's a reminder of how awesome the technology stack that we all
take for granted is.

------
10098
To be fair, it's not exactly a "raytracer", it's a program capable of
rendering that specific scene (i.e. bunch of spheres) using a recursive
raytracing algorithm, which isn't awfully complex in itself. Not trying to say
it's bad or anything, just want to point out that it's not very surprising for
something like this to be under 100 loc in a high-level language.

~~~
GuiA
A tiny tip coming from a friendly place, if I may- your comment comes off as
slightly pedant and elitist. I'm sure it was not in your intention to bring
down the original author of this demo, who is probably very excited about what
he worked hard on, but rather to highlight how deep of a field raytracing is
and to encourage him to not be content with this first venture into it, and to
explore more of it.

A good way to do that is to write your comment from a "Yes and..."
perspective, rather than a "Yes but..." perspective. In one case you're
showing the author how tall the wall front of him is, in the other you show
him how you yourself climbed that wall when you were in his position.

It helps a lot :)

~~~
dalek_cannes
I just checked out the author's site. He seems much higher up that wall than
grandparent poster :)

\- born in uruguay

\- worked his way up to google

\- learned BASIC at 5 (and made childhood drawings that included handwritten
basic code)

\- read First Blood at 9

\- wrote first short story at 7

Meanwhile I go to grandparent poster's site and find... well. I think I sort
of understand where the criticism is coming from.

~~~
10098
and you find a blog with 1.5 semi-coherent posts and a shitty sidescroller?
:-)

I'm not criticizing the author or his work, I'm just saying that writing a
recursive function that does p + kv recursively shouldn't take a lot of code.
Do I need to end each comment with a smiley face to prevent it from being
taken the wrong way?

~~~
ggambetta
I agree with you, it's not a very complicated thing. But that's the beauty of
it - raytracers are _simple_ but produce stunning images (it _is_ a raytracer,
though - _it traces rays_! Plus it does ambient + point lights, reflections,
shadows... the kind of stuff raytracers do)

It doesn't take a lot of code, sure. But _" a cross-platform game framework in
100,000 lines of C++"_ is not the current fad in HN ;)

