Tuesday, 31 March 2009

Implementing Minilight in Clojure (1)

Minilight is a global illumination renderer, designed to act as a minimal example of how to achieve certain rendering techniques. Minilight includes:

  • Monte-carlo path-tracing transport
  • Emitter sampling
  • Progressive refinement
  • RGB light
  • Diffuse materials
  • Triangle modelling primitives
  • Octree spatial index
  • Pin-hole ‘lens’
  • Ward linear tone-mapping

Together, this set of techniques is part of the Global illumination rendering algorithm. This considers not only a single ray (see my previous attempt) but reflections and emissions from all objects in the scene.

Over the next few weeks, I'll attempt to implement this in Clojure.

So for part 1, we'll look at reading in a scene file and converting it into a Clojure representation. The format for a model is simple. There's an example here.

Clojure really simplifies things because of the read function and because it's homioiconic (a Clojure function is a Clojure data structure).

The main gotcha I found was that read, by default, throws an exception when it reaches the end of the file. This made things slightly more complicated than I needed. Further investigation shows that read takes some optional parameters allowing you to control how EOF should be treated.

For now, I've just read the data in raw form. I've no idea if this will be a suitable data structure for actually doing anything with, but we'll see how this evolves...

(defstruct model

(defstruct triangle

(defmacro safe-read [x]
`(read ~x false nil))

(defn read-triangles
((fn [triangles]
(let [geom [(safe-read r) (safe-read r) (safe-read r)] refl (safe-read r) emit (safe-read r)]
(if (first geom)
(recur (cons (struct triangle geom refl emit) triangles))
triangles))) nil))

(defn load-model
(with-open [r (PushbackReader. (reader f))]
(.skip r (count "#MiniLight"))
(struct model
(read r) ;iterations
(read r) ;width
(read r) ;height
(read r) ;eye-position
(read r) ;look-direction
(read r) ;view-angle
(read r) ;sky-emission
(read r) ;ground-reflection
(read-triangles r)))) ;triangles