b l u r b   |    f e a t u r e s   |    g a l l e r y   |    t e c h n i c a l   |    r e f e r e n c e s   |    t h a n k s


Back in 2004 I was working on some relatively technical facets of 3d animation, a part of 3d which I had gravitated towards through pure curiosity. Having left school very early in life to pursue a career in delinquency, and skipping the common path of (advanced) study as a result, I felt I was missing some fundamental mathematical knowledge and that it was affecting my work. I was doing technical stuff for a job, without feeling like I ever knew what the hell I was doing!

So. I had the idea to do what every computer science graduate does - write a raytracer. This would expose me to practical mathematics relevant to both my day job and my area of interest. Problem was, I didn't like the idea of having to learn a programming language in order to do this - the brain cells dedicated to understanding the finer points of memory management seemed better expended elsewhere.

What to do? It just so happened that through my use of Maya I had learned MEL, so why not use that? A great idea I thought as I knew MEL intimately at the time and it meant I could focus on raytracer code, and not C++ syntax! Anyone with even a basic understanding of anything would appreciate that MEL is possibly the last language you would voluntarily use for such an excercise, yet it was still possible and that formed part of the challenge!

So I bought two books, read them in bed at night, and one Sunday morning wrote melray. The first session which was 12 hours long resulted in a Lambert shaded sphere being rendered with a directional light. Around another 30 hours were spent debugging some bits and adding additional 'features'. The goal was never to create something useful or useable, but rather to expose me to concepts for understanding. Once understanding was found, the task was complete.

So why write about it now, all these years later? I realised that pretty soon, the knowledge I have of how melray was put together, and also the capacity to run it, will be gone. Documenting things gives me something to look back on. Think of it as taking a polaroid when you're on vacation, only this snapshot is of melray and how it looked and functioned ...



Part of the challenge I set to myself, was that melray had to be self contained. It could not rely on specific features within Maya unless absolutely required. You want to construct a ray? Well, I had to incorporate the notion of a ray. You want to describe a scene? Well, I had to create a scene description language. Multiply a vector you say? Write the routine for vector multiplication... You get the idea.

There were sadly some exceptions which were insurmountable at the time and required direct help from Maya. The critical one which saddens me to this day, was the inability of melray to write image files. Maya included a command for writing files in binary format. Problem was, at the end of each line Maya placed a 'null' character. This null character voided the intended file format which made writing image files impossible. There may have been a solution (which included writing my own binary writer), but it was all beside the point and I had thought of a solution to my problem - use Maya particles as my rasterizer! When melray renders, it draws each pixel as a square particle, coloured to the correct value. The bonus to this is the ability to watch melray 'render'.

The other component of melray which relies on Maya is data storage. Again at the time, I could not think of a way to store the required data structures within the code, and so I create locators within Maya which represent each melray node. The locators store extra attributes which are later queried. Though aside from those two things, melray was completely self contained as planned. Later on, when adding distributed raytracing, I called on some inbuilt Maya math functions such as sqrt - it seemed superfluous rewriting these.



Honest answer, stuff all! melray can render spheres and infinite planes. It can do this with lambert shaders of a solid colour. It will light your scene with an array of light sources including, and completely limited to, Infinite, Point, Ambient and Occlusion. As a bonus, it will raytrace your scene and give you accurate reflections and shadows (including soft, distributed shadows). It cannot do polygons as it only knows about simplistic, mathematically described shapes. But, it will allow you to create a background from a solid colour - yeah!

In short, it can't really do anything. But it is an interesting thing nonetheless.

One feature of melray which is fun to watch is the 'Solid Rendering' mode. melray does not engage with the Maya scene in any way (except in the small exceptions mentioned earlier), as the rendered scene is completely described within the hand written scene description. What solid rendering does though, is to 'draw' the melray scene back into Maya, using projected 'pixels' and nurbs curves which represent cast rays. The result is a heavily foreshortened and occluded image showing the melray scene as a 3d projection - it's actually quite cool to watch!

Take a look at the feature set, check out some renders and watch the video clips which show the renderer in action. And if you are really nerdy, you can download the source code. It is completely uncommented as I wrote the thing in a pretty intense thought stream - it was all about the functionality.

enjoy ...

[2020 Update]

I was fortunate enough to work with a talented young man by the name of Shawn Wang in 2017. Shawn had the inspiration to write a raytracer too. I urged him to use Python for the task, and so over the subsequent weeks he set about creating a decent little raytracer. Seeing the joy Shawn was getting from the process reminded me of the same experience I'd had years before. And so with the wind on my back, I was determined to add some small updates to melray.

Over the subsequent weeks, global diffuse illumination was added. To see bounce lighting within a classic Cornell box from such a simple and also old piece of code was quite exciting!

As part of the revisit, I was determined to isolate the cause of the memory leak that plagued melray since its inception. And it didn't take long to find it.

With MEL, anytime you pass something to a function, that something consumes some memory. It's very small, but let's say you passed an array of float variables that require a couple of kilobytes into the function, well those kilobytes are never released! This happens even when passing by reference. As a raytracer involves millions of calls to functions, each time passing small amounts of data, you quickly end up with a memory leak. I quickly realised that there was a workaround; global variables. Instead of passing data into and out of functions, I would set and retrieve a global variable. For example, just before calling the 'ray intersect' function, I would set three global float variables, which would then be queried within the function. This was a perfect workaround! The only problem was, it became a nightmare to manage the setting and retrieving of these variables within the global illumination code. However, it at least allowed the change to render out a few higher resolution images than had been possible in the past.

This link discusses the findings with some practical examples.


The final feature that was added, was writing out to an ASCII based file format - PPM! PPM is super simple to write to and is supported by many image viewers. So once this was combined with the memory fix, it was easy to render out some decent resolution images.






  • Scanline recursive raytracer
  • Raytraced reflections (multiple levels of recursion)
  • Raytraced shadows
  • Brute force sub-sampling. Box filtered (no adaptive filtering here!)
  • Post render multipixel blur (box filtered)
  • Maximum image resolution 512x256 (owing to excessive memory usage)
  • Distributed raytraced shadows (for soft, area light style shadows)
  • Solid rendering (for drawing the scene spatially within the Maya viewport)
  • Stochastic jittering
  • [2017 Update] Global diffuse illumination


  • Mathematical sphere (geometric, formerly algebraic)
  • Infinite plane


  • Distant/Infinite (with soft shadowing)
  • Ambient
  • Point (with linear decay)
  • Occlusion (with adjustable spread/cone/maxdist etc)
  • Fog


  • Per-pixel shader evaluation (a limitation, not a feature!)
  • Lambert shading model
  • Reflections
  • Colour
  • Background (uniform in colour)


  • There isn't really one, though I suppose a basic pinhole model is correct. Best not to move the camera though as stuff breaks!




Sphere with raytraced shadow

Multiple spheres - 30minutes, 2gb RAM

Render showing ambient Occlusion - 18minutes, 1gb RAM

Render projected back into the Maya viewport via 'Solid rendering' feature

Maya Sprite particles used as pixels

Floating spheres (rendered in 2004)

----------------------------- [2017 Updates] -----------------------------

[2017 Update] Checkerboard shader!

[2017 Update] Cornell box! This required 29GB of ram and required 90 minutes of render time

[2017 Update] PPM image format combined with memory leak workaround allows higher resolution renders

Video showing melray rendering in action



melray source MEL script files can be downloaded here - http://melray.clintond.com/source/melray.zip.

  • Load the included Maya scene.
  • Place all files within a known script folder and 'source melray;'.
  • Tweak parameters and thats kinda it!




To describe the required 3d scene, melray includes a super simplistic scene description. It intentionally avoids simply translating the Maya scene, although that would have been a bloody good feature to have had! Objects are defined and their parameters are set, eg define a sphere and specify its position and radius. An example scene is below:

name = camera1;
type = camera;
pos = 0 0 -25;


name = sphere1;
type = sphere;
pos = 5 1 5;
radius = 4;
material = redmat;

name = ground;
type = plane;
pos = 0 1 0;
dist = 5.1;
material = groundmat;


name = light1;
type = point;
pos = 10 20 0;
color = 1.0 1.0 1.0;
intensity = .5;
shadow = 1;
shadcol = 0.0 0.0 0.0;
decay = 0;

name = occ;
type = occlusion;
hitcolor = 0.0 0.0 0.0;
misscolor = 0.5 0.5 0.5;
intensity = 0.6;
samples = 16;
bias = 0.01;
cone = 0.8;
maxdist = 6;


name = redmat;
type = material;
color = 1 0.5 0.0;
refcol = 1 1 1;
reflectivity = 0.85;

name = groundmat;
type = material;
color = 0.8 0.8 0.8;
refcol = 1 1 1;
reflectivity = 0;


name = background;
type = background;
color = 0.0 0.0 0.0;




It would have been impossible for me to have created melray without these two books - I consider melray nothing more than the implementation of other peoples discoveries:

Computer Graphics: Mathematical First Steps
P. A. Egerton
W. S. Hall
isbn: 0-13-599572-8

This is a must-have reference for basic, high-school level maths. It focuses on maths related directly to computer graphics and was the source for 98 percent of the melray vector library. It discusses things like vector functions, matrices etc.

An Introduction to Ray Tracing
Andrew S. Glassner
isbn: 0-12-286160-4

This book made for bed-time reading for a couple of weeks (seriously). It gave me the core understanding of a raytracer which was essential. It also provided the mathematical formula for the sphere!

Both books provided 10x more nerdy stuff than I even extracted, and both proved invaluable. There were other books I bought on the subject, yet never opened (ssssh, don't tell Jo, they cost hundreds of dollars). The limitations of writing a ray tracer in MEL meant that memory usage and render times blew way out of proportion very quickly, meaning new features were not really worth the effort - probably a shame actually as I had some great ideas for realtime screensaver style fractal landscape generation and rendering ...




And no introspective web entry would be complete without some form of thanks. Thanks to my Dad for showing me computer graphics as an 11 year old kid. Thanks to Chris Cooper for showing me that you can be a nerd, and still be an incredibly helpful and kind person. And thanks to Jo for supporting every single 'flavour of the month' pursuit I have had - and will continue to have!

It's only life, enjoy it!

clinton, 2010