Edd Biddulph

Twitter | CV


May 2016
Quake 2 Realtime GPU Pathtracing

This is a from-scratch GPU-based pathtracer created specifically for Quake 2. It has several optimisations which are only viable due to the typical characteristics of Quake 2 such as support for parallogram-shaped lightsources, BSP ray traversal, and special handling of sky 'surfaces' (portals). It doesn't officially have a name, but you can call it Raylgun.

Sam Lapere (of Ray Tracey fame) made a great post putting together a lot of my answers to his questions about this project, and also provided some useful tips on getting it running yourself. Sam is quite passionate about raytracing in videogames, be sure to check out his other posts and past projects.

Here are some average framerate measurements as measured by Quake 2 itself along with the graphics hardware that was used:

AMD FirePro W8100 49.3 fps
NVIDIA Quadro K6000 32.8 fps
GeForce GTX 96031.1 fps
AMD FirePro W710029.3 fps
GeForce GTX 68022.1 fps


YouTube Video 1
YouTube Video 2
YouTube Video 3
GitHub Page

Console Commands

gl_pt_recompile_shadersForces the shader programs to be recompiled. This is usually necessary after altering some aspect of the pathtracer via the console because some parameters are inserted into the shader source code itself.
gl_pt_print_static_infoPrints some pathtracing-related information about the current map. This information only pertains to things which are processed at map loading time.

Console Variables

NamePurposeRequires vid_restartRequires gl_pt_recompile_shaders
gl_pt_enableEnables the pathtracing codepath. When this is set to zero, the original Quake 2 rendering is used and all other pathtracer settings are ignored.NoNo
gl_pt_stats_enableEnables a continuous display of per-frame information. This is useful for finding out how well the pathtracer is performing. NoNo
gl_pt_bouncesThe number of secondary bounces of light. A value of 0 means all illumination is direct. Note: The sky is not sampled by secondary bounces.NoYes
gl_pt_shadow_samplesThe number of shadow rays to cast towards an individual lightsource. A higher number of shadow samples means less noise in shadows. Zero shadow samples means no shadows at all.NoYes
gl_pt_light_samplesThe number of light samples to make. A higher number of light samples means less noise overall, but the shader must re-compute importance sampling weights for each light sample (since storing them in registers is prohibitively slow). Zero light samples means no light from explicitly-sampled lightsources.NoYes
gl_pt_sky_enableEnables light emission from the sky. If this is disabled then the sky itself is still drawn, it just won't emit any light.NoYes
gl_pt_sky_samplesThe number of BRDF-sampled rays to trace and test against skyportals.NoYes
gl_pt_ao_enableEnables ambient occlusionNoYes
gl_pt_ao_radiusThe ambient occlusion radius.NoNo
gl_pt_ao_colorThe color of the ambient occlusion contribution. Note: This is a scalar value because Quake 2's console doesn't allow vector-valued variables.NoNo
gl_pt_ao_samplesThe number of BRDF-sampled rays to trace for ambient occlusion.NoYes
gl_pt_translucent_surfaces_enableCurrently not used, but will be used to enable the application of pathtracing to translucent surfaces.NoNo
gl_pt_lightstyles_enableEnables the use of lightstyles (animated colour and intensity of static entity lightsources).NoNo
gl_pt_dlights_enableEnables the use of dlights (dynamic lightsources created at runtime by entities).NoNo
gl_pt_brushmodel_shadows_enableEnables the casting of shadows by brushmodels (entities with rigid polygonal geometry defined by the BSP).NoYes
gl_pt_aliasmodel_shadows_enableEnables the casting of shadows by aliasmodels (entities with deforming triangle mesh geometry defined by separate MD2 files).NoYes
gl_pt_bounce_factorThe scalar amount of absorption simulated at each surface-light interaction in secondary bounces. Has no effect if the number of bounces is zero.NoNo
gl_pt_diffuse_map_enableEnables the modulation of light by the surface albedo maps (the original textures of Quake 2).NoYes
gl_pt_static_entity_lights_enableEnables the creation of static entity lights when the map is loaded. These lights can be quite costly as for each one 4 triangular lightsources are created, arranged in a tetrahedron.YesNo
gl_pt_depth_prepass_enableEnables a depth pre-pass which draws all entities into the depth buffer before pathtracing is performed. This eliminates overdraw (except for translucent surfaces) with minimal drawcall overhead so is recommended for improving performance.NoNo