So the idea this summer is to play around with the "Realtime Raytracer" that various people here in Utah have worked on. If you've ever played around or written a raytracer before, you know that generally they are very, very slow. However, to counterbalance the slowness, they give excellent quality images. The realtime raytracer is designed to run on multiple CPUs, and the computer I run it on has 32 processors. A significant portion of the speed comes from the fact that the code has been highly optimized, with particular attention to the specific hardware it is being run on. Even so, the "realtime" label can sometimes be misleading...
So what exactly am I doing on the RTRT? Well, right now I'm looking at adding interreflections between objects, and to get started, at specifically diffuse (non specular) objects. Essentially, the idea is that if you bring a bright yellow object close to a grey surface, some of the yellow will "bleed" onto the grey surface, even if the surfaces are perfectly diffuse. Generally raytracers don't deal with this, and those renderers that do add interreflections are very slow.
But seeing as this is the realtime raytracer, getting 1 frame ever 5 minutes doesn't sound too appealing. So.... this work.
Here are some initial images showing the type of image I'd like to get
(like the origianl Cornell Box image, or more specifically like the pathtraced
ones, which I rendered), and the type of image that is currently available in
realtime:
![]() Original Cornell Box image |
![]() Cornell Box scene using RTRT before any modifications (5/22) |
![]() Cornell Box scene using RTRT as a pseudo-pathtracer. (SLOW... 1 frame in ~ 120 seconds on 8 processors) (6/5) |
![]() Cornell Box scene using RTRT as a pseudo-pathtracer. (SLOW... 1 frame in ~ 120 seconds on 8 processors) Using a brighter light (5/31) |
The idea here is to allocate arrays for each of the walls/ceiling/floor which store the irradiance divided by pi. Thus an intersection with a wall (for example) would include a lookup into the array, and the result would be multiplied by the albedo to give the "ambient" term.
One of the nice things about this method is it can be implemented two ways. These arrays can either be formed with a standard preprocess or with incremental improvements in each frame. Most of the images below use the incremental method since I can see the results quicker.
Of course, what I've described works only for a static objects. Since I'd like to allow the blocks to move around the room, a different method needs to be used on these (or any other) non-static objects.
First Images of Simple Walls, Ceiling, and Floor of Cornell Box...
![]() Using RTRT to pseudo pathtrace (80s. on 8 processors) (6/5) |
![]() First frame of incremental method (30s on 1 processor, 2.6s on 8 processors) (6/5) |
![]() 20th frame of incremental method (~300s/20 frames on 1 processor, ~30s/20 frames on 8 processors) (6/5) |
![]() Incremental method Overnight on one processor (6/5) |
Incremental Method of Building up Irradiance Texture Maps...
![]() Incremental method on all surfaces (6/6) |
![]() Incremental method on just walls (6/6) |
![]() Incremental method on walls, grid around small box filled with fake colors (6/6) |
Preprocessed Method of Building up Irradiance Texture Maps...
(from current viewpoint)
![]() Preprocessed method. 100x100 irradiance "textures" on all surfaces, 1000 rays per pixel (6/7) |
The five 100x100 textures from the preprocess method shown at left (6/7) |
(viewpoint independant)
![]() Preprocessed method. 100x100 irradiance "textures" on all surfaces, 10000 rays per pixel (6/8) |
The five 100x100 textures from the preprocess method shown at left (6/8) |

Using the Irradiance Volume
![]() Using an Irradiance Volume to color the blocks. Note the blocks still have no effect on the room. Irradiance Volume: 5x5x5 grid (63 samples) 98 directions/rays per sample (6/10) |
![]() Using an Irradiance Volume to color the blocks. Blocks do have an effect of the room. Grid around blocks: 403 Irradiance Volume: 5x5x5 grid (63 samples) 98 directions/rays per sample (6/12) ~1.4 fps on 8 processors at 350x350 pixels |
Using a Lazy Interreflection Grid
Here, a grid is built up around dynamic objects, as above. However, there are two major differences. First, the grid is built up dynamically, which almost eliminates the preprocess stage, and only grid cells which are actually used need to be computed. Secondly, since the grid is built up statically, the interreflection term can be computed for a surface at a given orientation, which gives accurate results.
Also in here is a hack to get the shadows to appear as dark as they do in the pathtraced image. Without this, they appear similar to the shadows in the immediately preceding images.
![]() Pathtraced image (6/20) |
![]() Using an Irradiance Volume to color the blocks. Using an lazy (built incrementally) grid around the blocks to affect the room. 100 rays/cell 603 grid cells 0.5-1.4 fps on 8 processors at 350x350 pixels |
Go here to see more images using the incremental method at various heights off the ground (6/21).
Here I'm just sending out a ray 'porcupine' whenever I hit the walls to see if any of the dynamic objects (the blocks) are close enough to affect the wll color.
Go here to see these images (6/29).
Last Modified: June 29, 2000
Chris Wyman (wyman@cs.utah.edu)