SvenGL | C++ SvenGL RayTracer Gallery

All images were previewed using SDLViewer and finally rendered using RayTracer in a resolution of 1024x768 pixels, 24-bit colour depth. The computer was an AMD Athlon Thunderbird 900 MHz, equipped with a CardExpert GeForce2 MX graphics card, running Windows 98. Anti-aliasing was enabled, using 5 rays stochastically sampled (by using jittered sampling with a jitter strength of 0.1). A block size of 1 pixel was used, the maximum recursion depth was set to 5, shadow computation was turned on, 30 non-weighted jittered discrete cone rays were spawned for gloss/translucency, normalisation was enabled with a normalisation brightness factor of 1.1 and finally the images were converted from BMP to JPG (because each bitmap file was about 2.25 MB). Note that when converting to JPG some small irregularities were introduced at sharp discontinuous colour changes. And remember, although the ray tracer is quite powerful (well, at least in my opinion), it is slow because I performed almost no optimisation whatsoever.
The following command was used to generate the BMP files from, e.g., spheres.sdl (the various SDL files are included in the source-code):

 
raytracer data/sdl/spheres.sdl 1024 768 1 30 1 0.05 3 0.1 1  1.1 spheres 

Click on the small images to view their full-sized versions.

Rendered with OpenGL Rendered with RayTracer
This is my rendering of the famous Abalone board game in which two players compete in order to push 6 balls of their opponent off the board. I adapted it a bit using a smaller amount of holes and I made the board out of solid wood-grain texture. The board itself is a CSG object constructed by cutting squares from a central rectangle (these are scaled 3D cubes of course). The balls were made very shiny. The picture's brightness was artificially increased.
Rendertime: 01:59:01 (= 7141 seconds)

Rendered with OpenGL Rendered with RayTracer
The idea for this scene was based on the last picture in the book "Computer Graphics Principles and Practice" (yes, the famous CG-bible aka Foley-van Dam, ISBN 0-201-12110-7). So I modelled a sort of ballet room (with a nice bronze practice-bar), three silver mirrors, four spot lights on the ceiling and two windows. A spot light was placed in front of these windows to create the illusion of light seeping through them. The floor was texture mapped with a nice wood texture to give a really realistic look to the overall picture. Because the dull back wall is reflected in the mirrors, I decided to hang a painting on this wall... the smiling face of Eeyore (Winnie the Pooh's friend). The 'dancing figures' themselves are shapes modelled using solid textures made of RGB cubes. The picture's brightness was artificially increased.
Rendertime: 00:55:30 (= 3330 seconds)

(a) Rendered with RayTracer (b) Rendered with RayTracer
(c) Rendered with RayTracer (d) Rendered with RayTracer
(e) Rendered with RayTracer (f) Rendered with RayTracer
Quadrics are interesting surfaces, they are a natural extension of the 2D conics. The implementation was relatively easy because I only had to solve their respective equations for the ray hitting the surface. Note that quadrics form a subclass of the algebraic surfaces. The following quadrics are rendered: (a) is a one-sheet hyperboloid, (b) is a two-sheet hyperboloid, (c) is an elliptic cylinder, (d) is an elliptic cone, (e) is an elliptic paraboloid, and (f) is a hyperbolic paraboloid. Each quadric was constructed from a solid texture of marble with a fully reflective surface. A fully reflective sphere was added to the scene to show some nice shadows and reflections. Note that quadrics are infinite objects so I truncated them in a bounding box. I also added atmospheric attenuation (the farther away from the eye an object is, the more it is blended with the background).
Rendertime (a): 00:05:02 (= 302 seconds)
Rendertime (b): 00:18:14 (= 1094 seconds)
Rendertime (c): 00:06:03 (= 363 seconds)
Rendertime (d): 00:08:19 (= 499 seconds)
Rendertime (e): 00:04:50 (= 290 seconds)
Rendertime (f): 00:12:15 (= 735 seconds)

(a) Rendered with OpenGL (b) Rendered with RayTracer
(c) Rendered with RayTracer
Being able to succesfully render algebraic surfaces was quite a challenge. It all started with rendering a torus: I used a quartic root solver to accomplish this. The step towards more general quartic surfaces was rapidly made and this resulted in a shape called an algebraic surface. I already had the algebraic surfaces of degree two (the quadrics which can be seen above) and now included some cubics (third degree) and quartics (fourth degree). Technically speaking, the torus is also a quartic but texture mapping a torus is done differently from the more general algebraic surfaces (who use shrink wrapping from a sphere). The image in (b) was done using no special properties. In (c) however, the bodies were made 80% transparent and specular reflection was added (note that post-normalisation was disabled). In (b) and (c) you can see a pinched surface with holes (cubic) in the upper-left corner, a pinched surface with a lobe (cubic) in the upper-right corner, a four lobed-shape (quartic) in the lower-left back corner, a tooth-cube (quartic) in the lower-right corner, and the non-orientable Steiner's Roman-surface (quartic) in the lower-left front corner. Note that I didn't bother to program the rendering of algebraic surfaces using purely OpenGL techniques (tesselation), so the only thing you can see there are the bounding boxes.
Rendertime (b): 00:06:12 (= 372 seconds)
Rendertime (c): 00:10:09 (= 609 seconds)

(a) Rendered with OpenGL (b) Rendered with RayTracer
(c) Rendered with RayTracer (d) Rendered with RayTracer
(e) Rendered with RayTracer (f) Rendered with RayTracer
(g) Rendered with RayTracer (h) Rendered with RayTracer
This was one of my first attempts at using a CSG object to create a simple dish. Two spheres were used (I took the difference between them) and the resulting object was truncated with the use of a cube placed on top. The remains of this are clearly visible in the OpenGL rendering of CSG objects. Ray tracing this shape resulted in (b). I then increased the surface's roughness: (c) has a value of 0.1, (d) has 0.2, (e) has 0.3, (f) has 0.4, and (g) has 0.5. This factor is used when randomly perturbing the surface's normal at the hitpoint (which is fundamentally different from bump mapping). Image (h) was rendered using a solid marble texture and its brightness was artificially increased.
Rendertime (b): 00:10:23 (= 623 seconds)
Rendertime (c): 00:10:24 (= 624 seconds)
Rendertime (d): 00:10:24 (= 624 seconds)
Rendertime (e): 00:10:24 (= 624 seconds)
Rendertime (f): 00:10:24 (= 624 seconds)
Rendertime (g): 00:10:24 (= 624 seconds)
Rendertime (h): 00:11:06 (= 666 seconds)

Rendered with OpenGL Rendered with RayTracer
This was really a killer for CPU time (although it's nothing compared to rendering meshes) ! The scene relies heavily on CSG objects and although a simple CSG is used for the bowl (the difference of two spheres and a cone), the transparency (85%) combined with the fish made the refraction of rays rather complicated. This resulted in a very huge render time (nearly three and a halve hours). Note the distortion of the fish as they swim near the edge of the bowl.
Rendertime: 03:25:25 (= 12325 seconds)

(a) Rendered with OpenGL (b) Rendered with RayTracer
(c) Rendered with RayTracer (d) Rendered with RayTracer
(e) Rendered with RayTracer (f) Rendered with RayTracer
Gloss (blurred reflection) is quite difficult to model at first sight. With ordinary ray tracing this effect can't be accomplished, but by using distributed ray tracing I came one step closer to reality. The technique I used was based on non-weighted jittered discrete cone tracing and I spawned 30 rays for each point hit on the blue surface. The gloss factor is gradually increased to show the effect: in (b) it is 0.0, in (c) it is 0.1, in (d) it is 0.2, in (e) it is 0.4, and in (f) it is 0.6.
Rendertime (b): 00:03:54 (= 234 seconds)
Rendertime (c): 00:25:37 (= 1537 seconds)
Rendertime (d): 00:25:47 (= 1547 seconds)
Rendertime (e): 00:25:05 (= 1505 seconds)
Rendertime (f): 00:26:08 (= 1568 seconds)

Rendered with OpenGL (a) Rendered with RayTracer
Rendered with OpenGL (b) Rendered with RayTracer
Rendered with OpenGL (c) Rendered with RayTracer
Rendered with OpenGL (d) Rendered with RayTracer
Rendered with OpenGL (e) Rendered with RayTracer
Using some example photos from Hill's book as a template I created the first two scenes. The first scene (a) is literally described in his book and it's no big deal (although it was one of the first scenes I constructed to test my code), the second scene (b) is another story: based on a photo in the book I created this scene and added the face of professor F. Arickx (RUCA) in the middle (his face looks blown-up because of the inverse mapping from a circle to a rectangle). The marble checkerboard is actually a texture image tiled 2 times in the texture's space. Note that I rendered the teapot as a mesh, explaining the high render times. I also included a third scene (c) which was based on an SDL file I found on the Internet. It was used for another Advanced Computer Graphics Course. Note that the candles are actually tori (as can be seen by the presence of bounding extents). For this last scene, post-normalisation was disabled (due to the extremely high intensity of the candles' flames because of their rather high emissive colour component). In (d) I rendered Tux, the famous Linux penguin (the positions and scales of the spheres were based on those of a friend of mine - Wim Vanhooff - who once wrote a crude ray tracer in Java which could only render spheres, hence the penguin's blobby form). While writing a report for a seminar about DNA Computing, I decided to render a DNA double helix (artistic impression), which can be seen in (d) (shadow computation was disabled). A textured flat cube was used as a background to create more effect. The positions, scales and rotations of the spheres and cylinders were calculated by a specially by me written program.
Rendertime (a): 03:31:12 (= 12672 seconds)
Rendertime (b): 00:16:50 (= 1010 seconds)
Rendertime (c): 01:29:07 (= 5347 seconds)
Rendertime (d): 00:04:12 (= 252 seconds)
Rendertime (e): 00:21:22 (= 1282 seconds)

Rendered with OpenGL (a) Rendered with RayTracer
Rendered with OpenGL (b) Rendered with RayTracer
Rendered with OpenGL (c) Rendered with RayTracer
Rendered with OpenGL (d) Rendered with RayTracer
Rendered with OpenGL (e) Rendered with RayTracer
Rendered with OpenGL (f) Rendered with RayTracer
Rendered with OpenGL (g) Rendered with RayTracer
Rendered with OpenGL (h) Rendered with RayTracer
Rendered with OpenGL (i) Rendered with RayTracer
Rendered with OpenGL (j) Rendered with RayTracer
Rendered with OpenGL (k) Rendered with RayTracer
Correctly ray tracing meshes proved to be quite a task. But I succeeded and the results are magnificant. Every face in a mesh is triangulated and a bounding box is calculated. When ray tracing, all the intersections with the mesh' faces' are calculated, sorted and the negative hit times are removed. The intersections with the triangles themself are based on barycentric coordinates, so I can easily perform real Phong shading. Note that although Phong shading removes most of the discontinuities in the lighting model, it cannot remove the shape's discontinuities itself (take a look at the edges of the two cups). I added some water texture to the bottom plane to gain some effect. The difference between (a) and (b) is that in (b) specular reflection was added. I disabled shadow computation for (a) but enabled it for (b). I also artificially increased (b)'s brightness. When I was able to succesfully load Wavefront Object Files (OBJ), I downloaded some meshes from the Internet and ray traced them. The result is visible in (c) and (d), a cow (2,903 vertices, 5,804 faces, very long render time) and a pig (3,522 vertices, 7,040 faces, very long render time). The 'spots' on the cow were generated using a solid texture. The meshes in (e), (f) and (g) were converted from 3D Studio Max meshes to OBJ-files and imported in the ray tracer. In (e) you can see an X-Wing from Star Wars (766 vertices, 1,289 faces), in (f) you can see a zeppelin (1,104 vertices, 2,048 faces), and finally, in (g) you can see a lavalamp (958 vertices, 1,828 faces), lit by three differently coloured light sources. The lava lamp is made transparent to see the candle-wax bubbles inside. In images (c) through (g), shadow computation was disabled. The image in (h) was based on the movie Tron, in which a light cycle game was shown (although I didn't show the light these cycles make). You can see a recogniser flying above the game grid and in the back you can see a green light cycle smashing into the wall. In (i) you can see my version of a popular chess scene. I made the board a bit reflective and added a nice statue of the Venus from Milo. Notice how the 'black' pieces are actually carved from wood. While wandering the Internet, I discovered a nice mesh of a skeleton, so I decided to ray trace it. The result is visible in (j), the skeleton consists of 8,168 vertices and 16,033 faces. It took over eight hours to render this beauty ! And that is nothing compared to what you can see in (k): a naked wooden woman (12,758 vertices, 25,506 faces) hovering above the water, surrounded by the stars and a statue of Beethoven (3,440 vertices, 2,949 faces) himself (and a curiously looking female head (9866 vertices, 2,940 faces) at the right). And check out its render time, it's over ten hours !
Rendertime (a): 01:05:21 (= 3921 seconds)
Rendertime (b): 01:04:20 (= 3860 seconds)
Rendertime (c): 05:54:25 (= 21265 seconds)
Rendertime (d): 06:53:00 (= 24780 seconds)
Rendertime (e): 00:59:55 (= 3595 seconds)
Rendertime (f): 00:43:23 (= 2603 seconds)
Rendertime (g): 01:31:49 (= 5509 seconds)
Rendertime (h): 01:07:34 (= 4054 seconds)
Rendertime (i): 00:53:48 (= 3228 seconds)
Rendertime (j): 08:12:52 (= 29572 seconds)
Rendertime (k): 10:18:50 (= 37130 seconds)

Rendered with OpenGL (a) Rendered with RayTracer
Rendered with OpenGL (b) Rendered with RayTracer
Rendered with OpenGL (c) Rendered with RayTracer
Rendered with OpenGL (d) Rendered with RayTracer
Rendered with OpenGL (e) Rendered with RayTracer
Rendered with OpenGL (f) Rendered with RayTracer
  (g) Rendered with OpenGL
Rendered with OpenGL (h) Rendered with RayTracer
Rendered with OpenGL (i) Rendered with RayTracer
Rendering transparent bodies is quite a thrill ! Especially the bending of the rays as they pass through the various shapes adds a certain mystique to a scene. One of the first test scenes is rendered in (a) in which an opaque (white) sphere lies behind a 80% transparent (red) cube which is partially penetrated by another 80% transparent (blue) cube. The magnification effect on the sphere is clearly visible in the blueish part. The sphere in (b) is 80% transparent and rests on a fully reflective checker board surface (with smoothly varying colours). For (c) I've overdone myself: an 80% transparent torus in which a solid textured green torus lies, is shown. I also included a solid textured yellow sphere in the torus. The bending of the rays is clearly visible when looking at the XYZ-axes that penetrate the outer torus. The solid texture on the inner green torus was done using contour lines based on two coordinates and a sin*cos relation for measuring the distance. In (d) you can see a hollowed-out cylinder with water in it (another cylinder). I placed a small stick (ended with two knows) inside the glass and used a metal texture for the floor and cloud textures for the two walls behind. You can see the vague projection of the light cone of a spot light at the left of the glass. In (e) I placed a transparenct sphere and a torus above a greenish glass table. The surrounding background was blue (which is partially visible through the transparent bodies). For (f) I placed a rather solid torus on top of a checker board table. Above it are three transparent spheres (they form a union CSG). The same setup was used in (g), but there is one big difference: the three transparent sphere are not a union CSG but intersect each other, which results in more distortion and a more expressed (although still faint) shadow on the checker board. In (h) you can see a transparent ash tray which was made by taking the differences of a flattened cube and a torus and four cylinders (to place the cigarettes in). The image in (i) is a transparent landscape above a checkerboard, you can clearly see the distortion of the squares. The landscape was based on a 32x32 terrainmap (and thus consisted of 2,048 triangles) and took more than five hours to render (note that shadow computation was disabled) !
Rendertime (a): 00:10:10 (= 610 seconds)
Rendertime (b): 00:10:20 (= 620 seconds)
Rendertime (c): 00:11:11 (= 671 seconds)
Rendertime (d): 00:18:45 (= 1125 seconds)
Rendertime (e): 00:29:51 (= 1791 seconds)
Rendertime (f): 00:40:43 (= 2443 seconds)
Rendertime (g): 00:24:57 (= 1497 seconds)
Rendertime (h): 02:17:32 (= 8252 seconds)
Rendertime (i): 05:18:40 (= 19120 seconds)

Rendered with OpenGL (a) Rendered with RayTracer
Rendered with OpenGL (b) Rendered with RayTracer
One of the first scenes rendered, is shown in (a). A large central yellow sphere is surrounded by several walls. A small red sphere is placed in front. Everything is made fully reflective which - when ray tracing - results in an overlit scene. But this can easily be resolved by post-normalising the colours (which is possible because my ray tracer uses a render buffer). In (b) a simple scene is shown consisting of many fully reflective spheres. The brightness of (a) was artificially increased.
Rendertime (a): 00:20:10 (= 1210 seconds)
Rendertime (b): 00:06:13 (= 373 seconds)

Rendered with OpenGL (a) Rendered with RayTracer
Rendered with OpenGL (b) Rendered with RayTracer
Continuing the use of CSG (it really is an addiction indeed), I created a hollow bucky ball with holes (visible in (a)). This was rapidly done by taking the difference between a yellow sphere and red buckyball (although the colour of this last shape doesn't really matter because it is removed from the final CSG object). The buckyball in turn is a mesh. Looking at a photograph of several small watch parts I decided to create one myself which you can see in (b). The result is a CSG which looks rather technical. Note the hole inside the top cone. The watch part at the right in (b) is made out of solid texture of grey marble.
Rendertime (a): 00:06:05 (= 365 seconds)
Rendertime (b): 00:08:58 (= 538 seconds)

Rendered with OpenGL (a) Rendered with RayTracer
Rendered with OpenGL (b) Rendered with RayTracer
Rendered with OpenGL (c) Rendered with RayTracer
Rendered with OpenGL (d) Rendered with RayTracer
Texture mapping is fun ! Computing the texture lookup for a sphere is relatively easy (convert to spherical coordinates and use the two angles for texture lookup). Texture mapping a torus is a bit more difficult. Both techniques are shown in (a) for which I used a texture map of the earth (it was properly stretched so no degeneracies are visible when mapping it onto primitives. In (b) you can see a 'mathematical world' in which a sea is surrounded by a torus texture mapped with stars. Above it flies a tooth cube with the world on it and a cube texture mapped with Klein bottles is partially immersed in the water. At the right a green marble disc is visible but the main event is located near the middle where a landscape is located. This landscape was created from a terrain map of the Mandelbrot set and converted to a mesh using Landscape. On top of the landscape you can see the XYZ-axes (rotated) and a photo of me. For (c) I wrote a program which generated SDL code for all the spheres (there is a total of 1,297 spheres !). The same process was used to construct (d), in which you can see tori around tori around tori around a torus (there is a total of 8x8x8 + 1 = 513 tori !). This object is also known as a torloid.
Note that in (c) I disabled shadow-computation.
Rendertime (a): 00:03:55 (= 235 seconds)
Rendertime (b): 01:38:46 (= 5926 seconds)
Rendertime (c): 03:12:29 (= 11549 seconds)
Rendertime (d): 00:48:54 (= 2934 seconds)

(a) Rendered with OpenGL (b) Rendered with RayTracer
(c) Rendered with RayTracer (d) Rendered with RayTracer
(e) Rendered with RayTracer (f) Rendered with RayTracer
Motion blurring shapes was one of the final enhancements I made to the ray tracing engine. I used a classical pool table scene to illustrate the effect of a moving ball (three lights were used, one of them very faint). The white cueball was moved with speeds of 1.0 units in the X and Z directions (so that it would move towards the yellow ball) and a small rotation was added for more effect. In (b) I disabled motion blur, in (c) I used only 2 samples in time (notice how the cue ball is partially blended with the green table cloth), in (d) I used 8 samples and in (e) I used 16 samples. In (f) you can look at the pool table from above (rendered with 8 samples in time).
Rendertime (a): 00:08:01 (= 481 seconds)
Rendertime (b): 00:16:43 (= 1003 seconds)
Rendertime (c): 01:06:16 (= 3976 seconds)
Rendertime (d): 02:12:17 (= 7937 seconds)
Rendertime (e): 01:13:28 (= 4408 seconds)

(a) Rendered with OpenGL (b) Rendered with RayTracer
(c) Rendered with RayTracer (d) Rendered with RayTracer
(e) Rendered with OpenGL (f) Rendered with RayTracer
(g) Rendered with OpenGL  
Having found a way to perform distributed cone tracing, I quickly realised soft shadows were only a tiny bit of code away... In (b) you can see rendering with shadow computation disabled, in (c) you can see the traditional hard shadows and in (d) you can see the soft shadows (using 30 rays for each shadow cone). A classical scene (much encountered on the Internet) consists of the arrangement of chrome spheres which is ray traced in (f) and (g) (the former one uses hard shadows while the latter one uses soft shadows).
Rendertime (b): 00:04:14 (= 254 seconds)
Rendertime (c): 00:06:47 (= 407 seconds)
Rendertime (d): 01:39:10 (= 5950 seconds)
Rendertime (f): 00:09:54 (= 594 seconds)
Rendertime (g): 02:57:53 (= 10673 seconds)

Rendered with OpenGL (a) Rendered with SDLViewer
Rendered with OpenGL (b) Rendered with SDLViewer
Watching a scene being ray traced is one thing, but seeing the rays themselves is a whole other experience. Well, I did it. In (a) you can see the blue normal vectors pointing off the surfaces of a cube, a torus and a sphere (1% of every hit is shown). In (b) you can see rays bouncing of fully reflective mirrors (0.01% of every first hit is shown). Each ray has its own colour, and is coloured grey when it vanishes into the air (thus when no more object intersections are encountered). Note that when ray tracing both scenes, I disabled shadow computation and anti-aliasing. In (a) I also disabled post-normalisation. The pictures were made using SDLViewer.
Rendertime (a): 00:00:31 (= 31 seconds)
Rendertime (b): 00:02:35 (= 155 seconds)