Quake level Raytracer

Since Quake 1 levels contain all information necessary for displaying it, I thought it would be fun to create a ray tracing engine for them. In the process I could brush up on some basic 3D math and rendering techniques.

Overview

The application works by loading the Quake level specified on the command line. Based on the level data, a scene is constructed and fed into the ray tracing engine. Tracing is done in parallel using a task scheduler, where all pixels are divided evenly over all available worker threads. Depending on the settings, the renderer will apply ambient occlusion and soft shadowing to the scene. Supersampling can be enabled as well. When the scene tracing is finished, an TGA image is written to disk.

Download

Example renders

Background

Quake level files

In the original Quake game, a level file contained the following data:

Level geometry

Geometry for brush-based entities, like doors and platforms

Entity definitions, like lights, monsters, weapons and player spawn points

Texture data and several mipmap levels

Light maps

Visibility data used to cull invisible geometry while rendering

Note that, although a level contains light maps, the light entities are still present in the file as well. This data is in the game used for effects like light switches and fading. In this project, the ray tracer will ignore the light maps themselves and will calculate the scene lighting solely based on the light entities.

Ray tracer

In a nutshell, a ray tracer is actually the reverse of how an eye works. In nature, photons from a light source bounce around in the world and finally reach your eye. The combination of all photons eventually make up the image you see. In a ray tracer, rays shoot out of a virtual eye, bounce around in the virtual scene and try to end up at a light source. This is computationally less expensive to model, although less accurate. For more information about raytracing, see Wikipedia for a good explanation.

Project and code

Most of the project was spent figuring out how Quake was rendering its levels and how to interpret the BSP file. Looking on the internet did yield some technical documentation, but in the end, nothing beats rummaging around in the source code for Quake and its developer tools.