February 9th, 2008
Reaching the result of the last image took me about two days. It's also my first program written entirely with Emacs, so there was a little C-M-S-whatever fighting but it was really worth learning.
First image - after almost a day of coding:

15 seconds rendering time, about 500 lines of code and... well, it looks exactly as a flag of my nationality... (It's an infinite, horizontal, red plane).
The same day rendering improved a bit more:

And more...



Reaching finally:

Next day work went just a little bit forward, I corrected mistakes in calculations of diffuse lightening, removed artifacts, added simple anti-aliasing, voilla:

Variation of previous picture:

At last, nearly finished. Specular, diffuse, ambient and reflected lightening in place!

Still no refraction... and no texture support. If I won't get bored too soon I guess I'll add some of this features. And hence I can create a little road map for C++ version.
Two days later...
Code rewritten, refraction seems to more/less work, simple functional textures and texture mapping is done. There are for sure minor things to correct in lightening model, and plane mapping.
Texturing:

Refraction:



Another refraction example:

Summary given for the last rendering is as follows:
(1233284 main rays) (0 reflect) (1578544 refract) (61606006 shadow rays) traced = 64417834 in 522.00 seconds
So it took 8.7 minutes to trace 64 millions rays... I guess it would at least triple with reflections.
Code under GNU GPL3 license can be seen here:
highlighted version and pure source version: raytracer.ml
It's 900 lines without functions generating scenes (and 1267 with them). Not so big.
Static pages
Tags
Newest articles
Recently updated
External links
Comment by lambda ninja
submitted on February 12th, 2008 at 21:07
Well done! ;)
Comment by Marcin
submitted on February 13th, 2008 at 17:20
Niezle Tomku :)
Comment by Jon Harrop
submitted on March 28th, 2008 at 17:09
Great program!
Only takes 335s on my dual core 4400+ AMD64. Your "collide" function is very slow though, e.g. reallocating the accumulator at every step unnecessarily. Just optimizing it a bit brings the time down to 199s on my machine:
let minimal_distance = 0.00001 in
let vx = s.center.Vect.x -. ray_start.Vect.x in
let vy = s.center.Vect.y -. ray_start.Vect.y in
let vz = s.center.Vect.z -. ray_start.Vect.z in
let dx = ray_dir.Vect.x in
let dy = ray_dir.Vect.y in
let dz = ray_dir.Vect.z in
let r = s.radius in
let v' = vx *. vx +. vy *. vy +. vz *. vz in
let d' = dx *. dx +. dy *. dy +. dz *. dz in
let a = 2.0 *. (vx *. dx +. vy *. dy +. vz *. dz) in
let delta = a *. a -. 4.0 *. d' *. (v' -. r *. r) in
if delta minimal_distance then
if second minimal_distance then second else infinity in
if t >= best_t then collision else
let opacity' = 1.0 -.
(Material.get_property
~material:(get_object_material obj)
~property:`TRANSPARENCY) in
t, sphere, opacity +. opacity'
Add a comment [+] Hide the comment form [-]