HPC - Ray tracing

Moreno Marzolla

Last updated: 2023-05-27

The file omp-c-ray.c contains the implementation of a simple ray tracing program written by John Tsiombikas and released under the GPLv2+ license. The instructions for compilation and use are included in the comments. Some input files are provided, and should produce the images shown in Figure 1.

Figure 1: Some images produced by the program; the input files are, from left to right: sphfract.small.in, spheres.in, dna.in
Figure 1: Some images produced by the program; the input files are, from left to right: sphfract.small.in, spheres.in, dna.in

Table 1 shows the approximate time (in seconds) needed on my PC (i7-4790 3.60GHz) to render each file using one core. The server is slower because it has a lower clock frequency, but it has many cores so the performance of the parallel version should be much better.

Table 1: Render time with default parameters, single core Intel i7-4790 3.60GHz, gcc 9.4.0
File Time (s)
sphfract.big.in 182.7
sphfract.small.in 7.7
spheres.in 5.9
dna.in 4.,0

To compile:

    gcc -std=c99 -Wall -Wpedantic -fopenmp omp-c-ray.c -o omp-c-ray -lm

To render the scene sphfract.small.in:

    ./omp-c-ray -s 800x600 <sphfract.small.in> img.ppm

The command above produces an image img.ppm with a resolution \(800 \times 500\). To view the image on Windows it is useful to convert it to JPEG format using the command:

    convert img.ppm img.jpeg

and then transferring img.jpeg to your PC for viewing.

The omp-c-ray program accepts a number of optional command-line parameters; use

    ./omp-c-ray -h

to see the complete list.

Parallelize the render() function using appropriate OpenMP directives. The serial program is well structured: in particular, functions don’t modify global variables, so there are not hidden dependences. If you have time, measure the speedup and the strong scaling efficienty of the parallel version.

It might be helpful to know the basics of how a ray tracer works based on the Whitted recursive algorithm (Figure 2).

Figure 2: Operation diagram of a recursive ray tracer
Figure 2: Operation diagram of a recursive ray tracer

The scene is represented by a set of geometric primitives (spheres, in our case). We generate a primary ray (V) from the observer towards each pixel. For each ray we determine the intersections (if any) with the spheres in the scene. The point of intersection p that is closest to the observer is selected, and one or more secondary rays are cast, depending on the material of the object p belongs to:

The time required to compute the color of a pixel depends, among other things, on the number of spheres and lights, and on the material of the spheres, and whether the primary ray intersects a sphere and reflected rays are cast or not. This suggests that there could be a high variability in the time required to compute the color of each pixel, which leads to load imbalance that should be addressed in some way.

Files