[Haskell-cafe] Announce: glome-hs-0.51 (Haskell raytracer, now with type classes)

Jim Snow jsnow at cs.pdx.edu
Sun May 25 02:35:39 EDT 2008


A new version of my raytracer has been posted:

http://syn.cs.pdx.edu/~jsnow/glome/
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/glome-hs-0.51

(This should really be named 0.5.1, but I didn't think of that until 
after I uploaded it to hackage.)

There's not much new functionality, but it now uses type classes for the 
supported primitives, and has been optimized a bit more.  Much of the 
tutorial I hastily wrote for 0.4.x 
(http://www.haskell.org/haskellwiki/Glome_tutorial) is now quite out of 
date.

Most of the primitives have been moved to their own module, with the 
exception of SolidItem (an existential type used to make composite 
primitives), [SolidItem] (allowing me to treat lists of Solids like 
single solids), Void (a non-object, equivalent to []::[SolidItem]), and 
Instance (used for transformations).  It might be possible to move those 
to their own modules as well, but it would require mutual recursion 
between modules, and that's probably more trouble than it's worth.  (I 
made an attempt at that, but I quickly gave up.)

I also gave up on trying to use a global mutable variable to count the 
number of bounding hierarchy nodes a particular ray hits; instead, I 
added rayint_debug, which behaves just like rayint (the standard 
ray-object intersection routine), except that it returns an integer 
(that I can use to count whatever I like) along with the ray 
intersection.  Using a global counter in this instance would have been 
much simpler, but I don't think I understand "seq" well enough to be 
able to force the increment to actually happen.

http://syn.cs.pdx.edu/~jsnow/glome/Screenshot-glome-hs-bih.png

The resulting renders can be very useful to determine where Glome is 
spending most of its time, and to verify that the the bounding interval 
hierarchy is really doing the right thing.

I also added packet tracing, which makes it possible to trace four rays 
at a time, using a specialized ray intersection method "packetint".  
(This is a common technique to amortize the acceleration structure's 
memory lookup cost over multiple rays.)  It seemed to be a big win when 
I first implemented it before converting over to type classes, but now 
it seems to be faster without it, so I probably made a mistake somewhere.

A cosmetic change is that Glome now renders into a drawlist instead of 
directly to the screen, so the whole image doesn't get laboriously 
re-traced whenever there's window damage.  Unfortunately, that means you 
can't watch as it draws anymore, which was a useful way of knowing which 
parts of the image were slow to render.

I've started looking more seriously into optimization (suggestions 
welcome).  Don Stewart's blog post 
(http://cgi.cse.unsw.edu.au/~dons/blog/2008/05/16#fast) was quite 
useful, but it seems like there's a lot of arcane knowledge required to 
understand what's really happening in "core" code.  Is there any better 
reference than Andrew Tolmach's paper "An External Representation for 
the GHC Core Language (2001)" 
http://citeseer.ist.psu.edu/tolmach01external.html?

-jim


More information about the Haskell-Cafe mailing list