RefractionClick here to view.
First, all the initial rays are processed, generating additional rays where they intersect with objects. Then, the second-level rays are processed, generating third-level rays, which continues until all rays terminate on a side of the simulation. At each stage, if the ray being processed and the previously processed ray become too distant from each other, or if they hit different things, another initial ray is generated between the two rays and propagated forward up to the current level. After a certain limit is reached, or once no more rays are generated, execution stops, and the rays are drawn into WebGL using the GLOW framework.
Each polygon contains attribute information that allows any point within it to be accurately interpolated. This was difficult originally, as the interpolation across a triangle in WebGL is linear, but the interpolation needed for an accurate circular spread of light is radial. I solved this by passing the raw x and y positions of each vertex and also some identical values recording the locations of each ray, their intersections, and their intensities. While this is not an elegant solution and goes against the typical design patterns in GL, I was able to use it to accomplish my task. Feel free to view the shader source to understand how this part works.
I originally designed this experiment after learning about optics in my AP Physics class. More specifically, I learned about the spherical aberration, which is essentially the fact that circular or spherical lenses don't actually do what people teach about lenses. People teaching things that are just inaccurate is one of my biggest pet peeves, so I set out to show what light actually does when it hits a lens. As it turns out, it's actually quite pretty.
Update: This demo is now on the Chrome Experiments website!