Ray Tracing

Ok, I’ve got most of what I want done on the Ray Tracing project — enough at least to publish some code and do some blogging. This first article describes the overall coding structure, and how to use the project. I’ll get into some of the more difficult aspects of ray tracing in future posts.

Before going any further, here’s the source code.

Running the Application

After extracting the zip file, you’ll find two directories: Executable and Source Code. Pre-compiled binaries are in the Executable directory, and the source code is in the, errr… you get the picture.

Again, this project was built against XNA, so to run the executable you’ll need to install the following software:

To compile the project, you’ll need:

Controls

You can use the keyboard and/or an Xbox 360 Game Pad to control the application. The controls are as follows:

Control Device Description
W, A, S, D Keyboard Move the camera Forward, Left, Back, and Right respectively.
Print Screen Keyboard Take a screen shot.
R Keyboard Reload the scene from an Xml file (if the scene was initially loaded with an Xml file). Note: this version of the project auto loads changes to the Xml file. As such, you don’t really need ‘R’, but it can be used as a ‘Reset’ feature.
Left Thumbstick Game Pad Move the position of the camera along the X and Y axes (target stays fixed).
Triggers Game Pad Move the position of the camera along the Z axis.
Right Thumbstick Game Pad Move the camera’s target along the X and Y axes.
X Button Game Pad Toggle the ray tracing coloring methods. Theses methods are WithoutLighting, WithLighting, WithHardShadows, WithReflection, and WithRefraction.
Code Organization

The are three assemblies that make up the application. These are:

Assembly Name Description
Bespoke.Games.Framework This is a set of basic classes I use when working in XNA.
Bespoke.Games.Framework.RayTracing Class libraries specific to the ray tracing project. This is where the bulk of code resides for this project.
BasicRayTracing The executable and host of the Game-derived class. There’s very little actual code here — just initialization and the main update and rendering loops.
Significant Classes Description
RayCamera The camera within a ray tracing scene. The Initialize() method generates and caches a set of direction vectors for casting rays into the scene.

RaySceneManager

Maintains the list of shapes and actors within the scene and implements the Ray Tracing algorithm within its Draw method.
SceneLoading\*.* All of these classes support the Xml scene loading. The entry point to Xml scene loading is the class RaySceneLoader.

IShape / Sphere / Plane / Triangle / ShapeBase

Procedurally created “simple” shapes.

Actor

“Complex” shapes made from 3D models. Actors use the XNA content pipeline to extract the index and vertex buffers to produce a set of Triangle objects.

So now to the code itself. Of the above significant classes, the RaySceneManager is where the ray tracing is actually happening — starting with the Draw() method. Essentially, with each pass through the Draw() method we build up a Texture2D object by casting a set of rays into the scene, collecting a color at the closest object intersection (or the background color if there is no intersection). We then draw the resulting texture to the screen. Here’s that code (with some timing code removed):

The ray direction vectors are precalculated in the RayCamera.Initialize() method. Most of the work here is handed off to the TraceRay() method, and it’s this method that returns a color to be stored in the texture to be rendered. The TraceRay() method casts a ray into the scene and determines a resulting color using a variety of methods. I’ve used a delegate to allow for different color retrieval methods within the same coding architecture (for effects such as shadows and refraction). Here’s the general TraceRay() algorithm:

  1. Find the closest “simple” shape object that the ray intersects.
  2. Find any closer shapes contained within “complex” objects (Actor instances) that the ray intersects.
  3. With the closest intersected shape in hand, get a color at that intersection point and return it to the calling method.

This third step looks something like:

Where sCurrentColorMethodHandler is a delegate pointing to the currently selected color method.

I’ve been typing on this for awhile now, so I think I’ll call it quits for the moment and let you experiment with the code. I’ve included a set of scenes you can get started with, and you’re welcome to use this code in any way that you see fit.

Please note, there are a number of known deficiencies with this implementation. These include: no refraction for solid objects (e.g. spheres), slow uniform grid initialization for the uniform spatial subdivision algorithm, ray initialization could be improved, and in-code documentation. And I’m certain there are dozens upon dozens of other problems that I don’t know about. Please go easy on me if you find these. This project has been about learning ray tracing, and I’m very happy with what I’ve produced thus far. But as with everything, this is a work-in-progress and is far from a ‘finished’ state.

Here’s a screenshot from a fairly complex scene (17,000 shapes) using uniform spatial subdivision:

Uniform Spatial Subdivision

If you have any questions please let me know. Here’s a link to the code again.

RayTracing Source Code

Paul

8 Comments so far

  1. Joel Martinez on February 26th, 2007

    random and mostly worthless tidbit. I notice you had a Point3 struct that takes a Vector3. You can make converting between the two data types painlessly easy using handy dandy implicit conversion operators :-D

    public static implicit operator Vector3(Point3 p)
    {
    Vector3 v = new Vector3();
    v.X = p.X;
    v.Y = p.Y;
    v.Z = p.Z;
    return v;
    }

    public static implicit operator Point3(Vector3 v)
    {
    Point3 p = new Point3();
    p.X = (int)v.X;
    p.Y = (int)v.Y;
    p.Z = (int)v.Z;
    return p;
    }

  2. ZMan on February 27th, 2007

    Looks nice – so what parts of XNA do you intend to use other than the render surface and the Input stuff? WOuld be nice to use XNA to render a quick view to mvoe about the scene before you spend time doing the slow ray trace.

  3. Paul on February 27th, 2007

    I’m using a bunch of XNA primitives (Ray, BoundingBox, Color, Vector, etc.) but yeah the primary use of XNA in this project has been texture rendering and input. I dig the idea of using hardware rendering for positioning the scene and then a trigger to ray trace the scene. In fact the project I submitted for this graphics class allowed you to toggle between hardware and software rendering (though I maintained seperate camera positions) — but I removed that out of the version I posted.

    Maybe a split-screen view with hardware rendering on one side and ray tracing on the other. I haven’t used XNA’s viewport stuff yet, sounds like an opportunity to do just that. I’m also thinking that the ray tracing draw method should be run asynchronously from the main rendering loop with the output viewport updated as a new pass finishes.

    Thanks for the suggestions all.

    Paul

  4. Mateusz Kierepka on February 27th, 2007

    Nice work!

  5. Tronix on March 8th, 2007

    It’s all about shaders. =D

    http://my.fit.edu/~pvinson
    ^ C# MDX HLSL == Goodness

    It’s still a work in progress but should be finished within a month or so.

    My hat goes off to you and everyone else that uses managed code to write ray tracers. Keep up to good work.

  6. Paul on March 8th, 2007

    I dig your project Tronix. Good stuff. If you would, give me a shout when you’re finished. I’d really like to see the end result.

    Paul

  7. mysdn on February 1st, 2008

    great example for those who want to use xna for rendering and ray tracing for quality still images
    at the same time. we need more of these samples

    my hat more than goes off to you

  8. maantas on February 13th, 2008

    Hy there. I am pleased to meat raytracer :)
    anyways, i am not a programer of any so, pardon for not comenting the code itself.
    though i am very interested in raytracing consept.
    i have this idea, an have nobody to ask if that would work anyhow, therefore ill ask u. do you think its possible to write a raytracer which would cast rays not in a straight line? meaning slightly bended curves instead of lines?
    what do u think?
    here i decribe my idea in more words and some pictures:
    http://3dideas.wordpress.com/
    what do you think?
    m.

Leave a reply