[Haskell-cafe] announce: Glome.hs-0.3 (Haskell raytracer)
andrewcoppin at btinternet.com
Sat Apr 26 03:50:05 EDT 2008
Jim Snow wrote:
> The Scene Description Language (SDL) is the best and worst thing about
> It's very intuitive and user-friendly, so a person can reasonably
> write a complex scene in pure code without using an external GUI editor.
Not to mention that there's a smooth and continuous path from "I
rendered a reflective sphere on a chequered plane" to "I build a complex
CSG object" to "I wrote my first animation" to "I just built a particle
physics system / fractal terrain generator / inverse kinetics animator /
> Unfortunately, the SDL is so complex it's well-nigh impossible to
> support in other third-party applications.
I don't think it would be "impossible" to support in 3rd party apps. A
lot of work, certainly! Especially the way the parser does parsing and
macro expansion in the same pass, so a macro body need not contain a
syntactically-complete code fragment. I think if somebody sat down and
wrote something that would do all the macro expansion, variable
substitution and so forth to leave just few geometry descriptions,
*those* would be quite easy to parse and manipulate for 3rd parties.
> It's also slow. The scene has to be re-parsed for every frame. For
> complex scenes, the scene parsing could take longer than the actual
For complex scenes, or scenes involving complex algorithms like fractal
generation or something, parsing can indeed take far longer than
rendering. The SDL is basically a scripting language. It's kinda
flexible in its own way, but totally useless in speed terms. It also
lacks all the features of a "real" programming language - abstraction,
encapsulation, rich data types, powerful control structures... actually,
all the things that Haskell excells at. I did start a project a while
back to try and make it possible to describe POV-Ray scenes in Haskell,
thus leveraging the full power of the language. But that never came to
[The "clock" variable is one way to animate, yes. Another is to use the
"frame_number" variable. A common idiom is to generate an initial state
at frame #1, and on each frame, read the state from disk, update it,
write the updated version back to disk, and then render the frame.
Obviously this destroys the ability to render frames in arbitrary order
or distribute them across a render farm, but that's rather unavoidable.
Note that the loading and saving must be hand-coded, from scratch, every
time you want to do this. Tedious...]
>> Personally, I'd quite like to write my own ray tracer to address some
>> of these limitations. But every time I try, I end up hitting design
>> issues [Haskell works very differently to Java] or performance issues
>> [which I don't even know how to begin debugging]. Not to mention that
>> POV-Ray uses sophisticated techniques like volume bounding that I
>> know nothing about. (There's nothing like using an inherantly
>> superior algorithm to make your code orders of magnitude faster...)
> I haven't really run into any issues where Haskell didn't let me do
> what I want, except for the performance counters thing mentioned way
> back at the beginning of this thread (and which I've more or less
> given up on for now, since the acceleration structure seems to be
> working okay and I have other things to work on).
Well, for example, Haskell doesn't have hetrogenous lists - which are
trivial in any OOP language. That's quite awkward to get around. Also,
both spheres and cylinders have a "radius" property, but then you end up
with name clashes. Again, a non-issue in OOP languages. [I gather
there's some new GHC language extension to partially solve this one -
but only when types are statically known. In the general case, you'd
have to write a "radius class" and define instances... yuck!]
> A good acceleration structure definitely makes everything go a lot
> faster. It's the difference between rendering a scene in a few
> seconds or ten minutes.
> BIH is what I'm using. It's relatively new. Here's a paper about
> it: http://ainc.de/Research/BIH.pdf
> The actual constructor is based loosely on this pseudocode:
I'll take a look. Certainly all the ray tracers I've written just test
every ray against every object - O(n) complexity? Hmm, that's not
> You don't need to drop support for the whole multitude of primitives,
> though the ones that are packet-friendly will render faster. Many
> modern ray tracers spend most of their time traversing the
> acceleration structure rather than doing intersection tests with
> actual geometry, so all you really need to do to get most of the
> benefit of packet tracing is to make the acceleration structure
> support packets. (For the actual geometry, you can fall back on
> mono-rays.) I tried 2x2 packets out last night and got about a 10-15%
> speed improvement on the level-3 SPD sphereflake. (Shadow and
> reflection rays are still mono rays; if I converted them over, the
> improvement would presumably be more significant.) The simplifying
> assumption you make when you're traversing the acceleration structure
> with packets is that if one ray in the packet hits a bounding volume,
> you assume that they all do. That adds a little overhead if the rays
> are coherent (all starting near a common origin and pointing in almost
> the same direction), or a lot of overhead if they aren't coherent. If
> used appropriately, the performance gains outweigh the overhead by a
> considerable margin.
Something else to add to my list of "things I should look into"...
> Cones and spheres and boxes and the like can be made into some fairly
> elaborate scenes, but you can't really make, say, a realistic human
> figure out of those sorts of primitives.
No, but with things like isosurfaces and parametric surfaces, the world
is your oyster. And you can do a surprising amount of things with blobs.
I understand that all those curved surfaces which are currently popular
in consumer electronics are done with splines, not triangles...
> Also, real data sets like terrain or 3d-scanned geometry are easy to
> represent as triangles.
Well that's true enough...
> It's appropriate to support both approaches, so you can do whatever
> makes the most sense for the application.
Indeed. And since I never use triangles for anything, I've never
bothered working out how to support them. ;-)
More information about the Haskell-Cafe