Last Update: May 2020
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.

In 2019, a Vulkan-based renderer using NVIDIA RTX for hardware-accelerated raytracing was created for Quake 2 with a similar goal to this project. You can find out all about that project here. Judging by the About section of that page, my project which began in 2016 served as something of an inspiration for Q2VKPT.

Update Log

May 2020
June 2019
August 2017
August 2016

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 4 (new for August 2017)
GitHub Page

Out-dated Links

YouTube Video 1 (old)
YouTube Video 2 (old)
YouTube Video 3 (old)

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
gl_pt_taa_enableEnables temporal anti-aliasing, which is a form of anti-aliasing which re-uses the previously-rendered frame and blends between them in a smart way.NoYes
gl_pt_exposureSets the exposure parameter for tone-mapping. Currently the tonemapping is Simple Reinhard only.NoNo
gl_pt_gammaSets the gamma exponent of the display. Gamma is applied after tonemapping but before TAA, due to engine limitations.NoNo
gl_pt_bump_factorSets strength of the bumpmapping effect. A higher value means more pronounced bumps.NoNo
gl_pt_bump_enableEnables the bumpmapping effect. Bump maps are generated automatically from diffuse maps by interpreting diffuse pixel brightness as bump height.NoYes
gl_pt_brushlights_enableEnables the casting of light from brushlights, which are those lights attached to moving level objects such as elevators and platforms.NoNo
gl_pt_specular_factorSets a factor adjusting the blending between pure diffuse and pure specular reflection.NoNo

Older screenshots from 2016: