Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm developing a basic triangle mesh raytracer on a short deadline.
This means I can't implement every feature I come across, so I'm looking for some feedback about which features you think are most important, taking into consideration the performance of the feature and how much punch it packs.

I'm especially looking for optimization techniques that allow for a faster rendering and simple techniques that make a big impact on the final scene quality.
Is there any chance of making it fast enough to run in realtime?

Here are some example of features I've read about:

  • Anti-aliasing
  • Bounding box
  • Sky box
share|improve this question

closed as not constructive by Nicol Bolas, Trevor Powell, Tetrad Apr 4 '12 at 23:28

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.If this question can be reworded to fit the rules in the help center, please edit the question.

Why does this sound like homework? – Nicol Bolas Apr 4 '12 at 21:03
What does this have to do with game development? – Trevor Powell Apr 4 '12 at 21:27
@TrevorPowell Is there a better stackexchange site to post graphic programming questions? – David Gouveia Apr 5 '12 at 14:08
@DavidGouveia Don't know, but the complete list of stack exchange sites is here: If there's nothing specific in that list, then it's worth mentioning that all programming questions are on-topic at the main StackOverflow site. There are plenty of raytracing questions there, and most seem to have accepted answers. So that seems like a good bet. – Trevor Powell Apr 6 '12 at 3:35
up vote 2 down vote accepted

The biggest problem you're going to run into is that every technique you add to improve image quality will increase the computational cost of the program by a lot more than you'd initially expect. I'll run down a list of techniques you might want to consider by also point out their complexity and cost. All of these techniques fall under the category of Distributed Ray Tracing, which is covered in this research paper.

Soft Shadows - The idea behind soft shadows is to capture the umbra and penumbra cast by an object being illuminated by an area light source. The umbra is the portion of geometry that is completely occluded from light, and the penumbra is the area that some of the light reaches, but not all. The usual shadow technique for ray tracing is to just cast one ray towards the light source, and, if it is occluded, then the origin of that ray can be darkened appropriately. For soft shadows, instead of firing one ray, we fire multiple rays, but each to a random point on the light source. Some of them may hit, and some may be occluded. The final blended result will give either a fully-darkened or partially-lit result. Unfortunately, to get smooth results, I've found that 50 or more shadow rays have to be cast.

Glossy Surfaces - Many basic ray tracers render either completely diffuse or completely reflective surfaces. Glossy surfaces are those which are mostly diffuse by somewhat reflective. The appearance is generated by tracing multiple random rays in the cone of the reflected ray, and blending the results. The angle of the cone is determined by the roughness of the surface. Like soft shadows, many rays have to be traced in order to get smooth results, and there is a great increase in complexity here, because these rays are being traced rather than just cast.

Anti-Aliasing - In order to smooth the hard pixel edges on the final visualization of your scene, you can trace multiple rays through each pixel. Determining the points on the pixel through which the rays will be traced is an area to explore for optimizing how many rays you must trace to get a good image. You could look into something called stratified sampling.

Participating Media - This encompasses fog and dust in the scene that you're ray tracing. It can yield results like a beam of light shining in through a window. To render participating media, you have to use a technique called ray marching. You sample your ray at increments as it's sent into the scene (this sampling is saying "if I just happened to hit a spec of dust, what color would I be?"). At each sample, you cast a shadow ray to the light source. If the point is lit, then you can add the light color to that pixel. The trick is in blending the result so that it's faint enough to still see the image behind the media. Following a common theme, this technique can get expensive because you'll end up casting many shadow rays.

There are some other techniques described in the paper I listed earlier including depth of field and motion blur.

Now, as far as acceleration structures for your ray-tracer are concerned, the best that I can recommend are spatial structure like octrees or kd-trees. You only have to test your rays against geometry which is contained in the spatial partitions it intersects as it travels through the scene. Along those lines, you could also include primitive bounding boxes around your triangle meshes, to further cut down on the number of times you must check your ray against all the triangles of a mesh (because this is the most expensive part of the whole program!).

Also, if you haven't done so already, I highly recommend including a visualization for your rays which can be viewed in a rasterized version of your scene. For example, you press 't' with your mouse hovering over a pixel, and then you can draw lines to represent each type of ray that is cast as the original one makes its way through the scene.

Finally, unless you're developing your ray tracer on the GPU and including every optimization and spatial acceleration data structure in the book, you're unfortunately not going to get it running close to real time.

Good luck :)

share|improve this answer
Nice overview! On the subject of soft shadows, how is an area light represented in code, and how do you pick random points on its surface? – David Gouveia Apr 4 '12 at 18:40
I also find it interesting that a research paper that is almost 30 years old already covers pretty much everything you listed. Hasn't there been any significant progress since then? – David Gouveia Apr 4 '12 at 18:46
@DavidGouveia In the program I worked on, area light sources were just quads, and a random point could be generated on one by calculating random texture coordinates between 0 and 1 and interpolating the result from the four corners. – ktodisco Apr 4 '12 at 18:48
Thanks, that makes sense. :) – David Gouveia Apr 4 '12 at 18:49
For those that are interested, the described random sampling approaches for soft shadows and glossy surfaces are both examples of Monte Carlo rendering techniques. – Mac Apr 4 '12 at 21:48

Ktodisco already mentioned most of what there is to know, but to add to what has already been mentioned I'd like to mention a few more ideas. I've also found this resource to be of great help to me on this subject.

Environment Mapping

Add an environment map to your scene, such as a cube map. A cube map is basically just a collection made up by six textures. Each of the textures represents one of the faces of a cube that describes the "environment". The most common example is a sky box. Given a direction vector from the center of the cube, your CubeMap class should be able to to tell you the color of the pixel that the vector is "pointing to".

Once you have that class, it's pretty trivial to add it to your raytracer. Just redirect any rays that don't intersect anything in the scene, to your cube map, and use the color it returns. From experience this will improve the look of your scene by a large margin. Also, since it doesn't involve casting any additional rays, it won't slow your performance down by much.

Bump Mapping

If you want to add a bit of roughness to your surfaces, one hack I've found was pretty easy to implement was to add a little bit of displacement or randomization to the normals of your surface before calculating your lighting. Using some sort of noise texture (e.g. perlin noise) as a basis for that displacement will also allow you more control over the frequency and depth of the bumps.

Chromatic Dispersion

Haven't tried this on a raytracer yet, but it worked nicely on a glass shader I've created before. Basically the idea is that different light wavelenghts are refracted by different amounts, so whenever you're calculating a refraction, instead of casting one ray, you cast three separate rays with different indices of refraction, and in the end combine the results with a tint of R, G and B for each of the rays. You can also combine this with the fresnel effect which varies the reflectiveness of the surface based on the angle at which you're seeing it. More information here.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.