# Devlog: Week 8: Writing a Ray Tracer in Julia

It is real long since I studied coordinate geometry or computer graphics. This last week, dusting the very little remains of what I knew, I decided to work on a ray tracer. When I started, I did not know what a ray tracer was. Slowly, I understood that it was one algorithm that is used to construct a 3D scene on a 2D screen. Broadly, this is how it works

Define the eye/camera/viewpoint Define the screen in m*n pixels Shoot a ray for each pixel in the screen from the eye. For each ray, Find nearest intersected surface Find a color for the point based on surface reflection/refraction or the light source and shading model Plot the color on the pixel

I decided to build one that would trace spheres, so I had to define 3 major types - Vector, Ray, Sphere, and a helper type Intersection to store where an object intersected with the screen.

type Vector x::Real y::Real z::Real end type Ray origin::Vector direction::Vector end type Sphere center::Vector radius::Real color::Vector end type Intersection point::Vector distance::Real normal::Vector object end

Interestingly when I went about defining methods for the vector, I found Julia had inbuilt support for finding dot and cross products, so all I had to do was piggyback on those implementations and build my vector class. Also, thanks to Julia's multiple dispatch mechanism, overriding inbuilt operators was as simple as this:

function +(a::Vector, b::Vector) return toVec(toList(a) + toList(b)) end

That done, I went about implementing the core algorithm, and a couple of simple shading models, being Lambertian and the Blinn Phong shading models.

Once I'd implemented it all, and fixed all bugs that produced seemingly awesome but wrong images, the main loop consisted of this:

for x in 1:imageWidth, y in 1:imageHeight traceWorker(x, y, imageArray, cameraPos, lightSource, objects) end //See full implementation <a href="https://github.com/madhuvishy/ray-tracer/blob/master/tracer.jl#L119">here</a>

I used Images.jl plugin, to build the image, and ImageView to display it, and when I ran my code with the above main loop I got something like this:

☁ ray-tracer [master] ⚡ time julia tracer.jl julia tracer.jl 11.55s user 0.26s system 98% cpu 11.933 total

But having used Julia, I had to put it's parallel processing capabilities to test. And because each of the calculations in ray tracing are independent of each other, I could put this, to use. And now my loop became...

@parallel for x in 1:imageWidth, y in 1:imageHeight traceWorker(x, y, imageArray, cameraPos, lightSource, objects) end //See full implementation <a href="https://github.com/madhuvishy/ray-tracer/blob/master/tracer.jl#L119">here</a>

Sweet! Let's check the new running time.

☁ ray-tracer [master] time julia tracer.jl julia tracer.jl 6.44s user 0.11s system 99% cpu 6.566 total

Yay! Down by almost 50%. Pretty sure there are more ways to optimize my code, but this is how far I've gotten till now.

**Now, for our final showdown.**

Woah, but no...

Ummm, circles or spheres?

Yes this.

Thanks to fellow HackerSchooler Lita Cho for patiently explaining how ray tracers work :) Check it out at: https://github.com/madhuvishy/ray-tracer/