Trinity Engine is a unified flatscreen and OpenXR VR engine for Quake III Arena, forked from Quake3e. It serves as the engine component alongside the Trinity game mod and Trinity Tracker server administration and statistics platform.
Launch the same client in either mode:
trinity.exe +set vr_enabled 1
trinity.exe +set vr_enabled 0
On Linux, use the packaged trinity executable's filename in place of
trinity.exe. The default is flatscreen; the selected mode is saved. You can
also put set vr_enabled 1 in your game directory's autoexec.cfg to prefer VR
on startup. In Trinity's System settings, select Display Mode and choose
Apply. Switching uses vid_restart and retains an eligible live match.
VR requires the Vulkan renderer, a GPU with two-view Vulkan multiview support, and an active OpenXR runtime supporting the Vulkan enable2 graphics binding. Entering VR selects Vulkan. A bundled OpenXR loader does not replace your headset vendor's runtime. Flatscreen play and dedicated servers do not require a headset or runtime.
Supported: Windows x64 with the SteamVR, PICOXR and Virtual Desktop VDXR runtimes, and Linux arm64 on the Steam Frame. Linux x86_64 and macOS OpenXR are untested.
See VR setup and migration for runtime setup, module compatibility, mirror controls, and migration from Trinity VR.
The engine also supports crossplay between flatscreen and VR clients:
Server engine: Advertises vr_support=1 in serverinfo and reads each
client's vr userinfo key. A client that reports VR sends 32-bit buttons and VR
head orientation data; the rest send the standard 16-bit fields. The server
selects the field width per packet from that key.
Client engine: Reports its display mode through the vr userinfo key and
widens commands only on servers that advertise vr_support. Switching display
mode keeps the connection.
The engine handles OpenXR tracking, input, and stereo rendering together with the Trinity game mod's VR-aware game interfaces. See VR_PROTOCOL.md for the full protocol specification.
Stencil shadow volumes (cg_shadows 2) are reworked across all three renderers — OpenGL,
Vulkan, and OpenGL2 (the renderer the WebAssembly demo player uses) — built on a z-fail
("Carmack's reverse") approach so shadows stay correct even when the camera is inside a
shadow volume:
- Sealed silhouettes — Model edges are welded by position so the silhouette forms closed loops, sealing the light leaks and cracks that plain edge-matching left on Quake III's models.
- Capped volumes — Volumes are closed at both ends, eliminating the "ghost shadow" silhouettes that floated in mid-air when players jumped.
- Configurable distance —
r_shadowDistance(default256) sets the extrusion and cull distance, replacing the old hardcoded 512-unit extrusion and greatly reducing wall bleed. - Raw light direction — Extrusion follows the actual light direction instead of clamping to straight down, producing correct shadows from all light angles.
- Expanded entity culling — Shadows don't disappear the moment their caster leaves the screen.
- BSP clipping —
r_shadowClip 1clips shadow volumes against world geometry to curb floor/wall bleed;r_shadowClipPenetration(default4) andr_shadowClipExtension(default16) tune how far a clipped volume may pass through and extend past a surface. Some bleed can still occur where a shadow spills across stairs or through a gap.
The defaults are tuned for normal play; just set cg_shadows 2.
On the Vulkan renderer, Trinity Engine can output true HDR (scRGB linear FP16) to an
HDR display, for brighter highlights and more lifelike color than standard dynamic range.
It requires the Vulkan renderer, r_fbo 1, and an HDR-capable display with HDR enabled in
the OS. This is separate from r_hdr, which only sets internal framebuffer precision.
Toggle it in-game under Setup → Display → HDR Display and tune it under
Setup → Display → HDR Calibration, or set the cvars directly:
r_hdrDisplay(default0) — master toggle;1enables true HDR output. Latched (takes effect aftervid_restart).r_hdrPeak(default400) — your display's usable peak brightness in nits, the main value to match to your panel. Best found with the calibration screen, which reflects the brightness the panel actually reaches (often well below its rated peak). Range250–10000; the in-game calibration slider covers250–2000.r_hdrPaperWhite(default0) — nits that normal (SDR) white maps to;0= auto from the peak.r_hdrHighlightBoost(default1.0, range0.5–2.0) — extra emphasis on the brightest highlights; does not change overall brightness.r_hdrSaturation(default0.0, range0–1) — how far the brightest highlights bleed toward white (1keeps full color,0lets them go fully white).r_hdrSaturationFull(default1.5, range0.5–3.0) — emitter intensity at which that bleed reaches its maximum.r_hdrSoftKnee(default1.0, range0–2) — how gradually the highlight treatment eases in above paper-white.r_hdrActive(read-only) —1when HDR output is genuinely live (HDR swapchain up and the display's HDR switch on).r_hdrStatus(read-only): HDR state of the outputs being shown (the window, or in VR the headset and the desktop mirror when it is on):active(HDR output is live),available(can be turned on withr_hdrDisplay),nofbo(needsr_fbo 1),ossetting(the display can show HDR but its HDR switch is off in the system display settings) orunsupported(no output being shown can display HDR). The menus enable their HDR rows from it.
Server-side demo recording captures complete match state — all entities, player states,
and server commands — into a compact, zstd-compressed, delta-encoded .tvd format.
Client-side playback supports multiple viewpoints, smooth interpolation between snapshots,
and seeking via replay from the beginning.
tvrecord/tvstop— manual recording controlsv_tvAuto— automatic recording on map loadsv_tvAutoMinPlayers— minimum concurrent non-spectator human players to keep auto-recording (0 = always keep)sv_tvAutoMinPlayersSecs— seconds the threshold must be continuously met (0 = instantaneous)sv_tvDownload— notify clients to download the completed demo via HTTP at map change (requiressv_dlURL)cl_tvDownload— opt in to automatic TV demo downloads from the server- 0 = No download, ever
- 1 = Offer download. Cgame-controlled handling. For Trinity, show a dialog. 1 = default to decline after
cg_tvdTimeoutseconds - 2 = Offer download. Cgame-controlled handling. For Trinity, show a dialog. 2 = default to accept after
cg_tvdTimeoutseconds
- Client-side viewpoint switching and seek during playback
The same TV capture can be broadcast while the match is being played.
With sv_tvLive 1 the dedicated server offers the in-progress match as
a TVL1 byte stream on a loopback TCP socket (same port number as the
UDP game port); a consumer such as the
Trinity tracker relays it to
browser viewers, where this engine's WASM build plays it live (cl_tv).
The stream survives map changes on one connection — each map session
ends with an end marker and the next starts with a fresh header.
sv_tvLive— offer the live TVL1 stream tap (default0)sv_tvLiveKeyframeMsec— keyframe cadence for the live stream, in ms (default1000); the relay derives its viewer holdback from ittv_resync— (WASM build) command the embedding page runs on tab foreground, so a throttled tab's backlog snaps back to the playback cushion instead of replaying
The engine compiles to WebAssembly via Emscripten, enabling browser-based playback of .tvd demos
with no install required:
make web— web engine that loads game assets from a configurable JSON manifest
The loader (loader.js) is an ES module that handles fetching the engine, game assets,
and demo files into an Emscripten virtual filesystem. It parses TVD headers to determine the map
and fs_game, fetches the appropriate pk3s, and supports browser-side asset caching. It can be
used as a web client or demo player, and embedded into an existing page.
Requires the Emscripten SDK (emcmake/emmake).
Botlib can fly a grapple along its routes. It reads Trinity navigation data (maps/<map>.aat) beside the map's own .aas, falling back to stock routing on maps that have none, while the game module decides when a bot shoots, bites, and lets go. bot_grapple defaults to 1; 2 logs every route shot, bite, and tow ending. Navigation reads never mark a pak referenced, so clients are never asked to download server-only data.
Game DLL callbacks for server startup and shutdown events, enabling integration with external tooling for statistics tracking and server management.
sv_conTap— with1, stream the server console over a loopback TCP socket on a kernel-assigned port, advertised read-only in serverinfo assv_conPort(0= no tap offered). The Trinity tracker consumes this fortrinity console.com_writeConfig— with0, never write archived cvars back toq3config.cfg(q3config_server.cfgon dedicated servers). Disable on multi-instance dedicated hosts that share a homepath, where the write-back cross-contaminates instances.sv_fpsdefaults to40and clientrateto50000— the values the Trinity mod is tuned against.
Trinity Engine binaries do not ship with Quake III Arena game content. To play, drop the engine alongside an existing Quake III Arena installation, or assemble the required pk3s yourself:
- Original game data —
pak0.pk3from your retail Quake III Arena CD (and the Team Arenapak0.pk3if you want to play missionpack maps). Place inbaseq3/andmissionpack/respectively. - Quake III Arena 1.32 point release —
pak1.pk3throughpak8.pk3forbaseq3/, pluspak1.pk3throughpak3.pk3formissionpack/. If you don't already have these, the ioquake3 project hosts the patch data here: https://ioquake3.org/extras/patch-data/. - Trinity mod pk3s —
pak8t.pk3(baseq3) andpak3t.pk3(missionpack) ship with each release.
Earlier Trinity Engine releases bundled the point release pk3s directly. They have been removed to keep download sizes small for the common case where players already have a Quake III installation.
Downloaded builds will be quarantined by Gatekeeper. Before launching for the first time, remove the quarantine attribute:
xattr -cr Trinity.appTrinity: A unified Quake III Arena / Team Arena game mod featuring unlagged weapons, VR head and torso tracking, an orbital follow camera for spectating and demo playback, Quake Live-style damage indicators, and visual enhancements. It provides the VR-aware game modules and server-side support for crossplay between this engine's VR mode, Trinity Standalone and flatscreen players.
Trinity Engine: This project. Unified flatscreen and OpenXR VR client, dedicated server, and TrinityVision player, forked from Quake3e. Loads game modules at runtime; VR uses compatible cgame/UI QVMs or the packaged native fallback where permitted.
Trinity Standalone: Standalone-headset VR client for Meta Quest, PICO and the Steam Frame APK, based on ioquake3 with this engine's Vulkan renderer and VM subsystem. Loads the Trinity mod's QVMs at runtime and ships native module libraries built from a pinned Trinity release for the cases a flat-only QVM would break VR.
Trinity VR: The earlier separate PCVR client, sunset once this engine's VR mode is released.
Trinity Tracker: A real-time statistics tracking and server administration platform. Monitors multiple Quake 3 servers, tracks player performance and match history, provides leaderboards, and serves a web interface with live updates via WebSocket. Includes CLI tools for server management and game asset extraction.
Note: both this engine and Trinity Standalone load the Trinity mod's QVMs at runtime and carry bundled native modules only as a fallback. Pure servers require VR-compatible QVMs; the native fallback is limited to non-pure baseq3 and missionpack sessions.
The following is the original Quake3e README, preserved for reference.
This is a modern Quake III Arena engine aimed to be fast, secure and compatible with all existing Q3A mods. It is based on last non-SDL source dump of ioquake3 with latest upstream fixes applied.
Go to Releases section to download latest binaries for your platform or follow Build Instructions
This repository does not contain any game content so in order to play you must copy the resulting binaries into your existing Quake III Arena installation
Key features:
- optimized OpenGL renderer
- optimized Vulkan renderer
- raw mouse input support, enabled automatically instead of DirectInput(\in_mouse 1) if available
- \in_minimize - hotkey for minimize/restore main window (win32-only, direct replacement for Q3Minimizer)
- \video-pipe - to use external ffmpeg binary as an encoder for better quality and smaller output files
- significally reworked QVM (Quake Virtual Machine)
- improved server-side DoS protection, much reduced memory usage
- raised filesystem limits (up to 20,000 maps can be handled in a single directory)
- reworked Zone memory allocator, no more out-of-memory errors
- non-intrusive support for SDL2 backend (video, audio, input), selectable at compile time
- tons of bug fixes and other improvements
Based on Quake-III-Arena-Kenny-Edition with many additions:
- high-quality per-pixel dynamic lighting
- very fast flares (\r_flares 1)
- anisotropic filtering (\r_ext_texture_filter_anisotropic)
- greatly reduced API overhead (call/dispatch ratio)
- flexible vertex buffer memory management to allow loading huge maps
- multiple command buffers to reduce processing bottlenecks
- reversed depth buffer to eliminate z-fighting on big maps
- merged lightmaps (atlases)
- multitexturing optimizations
- static world surfaces cached in VBO (\r_vbo 1)
- useful debug markers for tools like RenderDoc
- fixed framebuffer corruption on some Intel iGPUs
- offscreen rendering, enabled with \r_fbo 1, all following requires it enabled:
screenMaptexture rendering - to create realistic environment reflections- multisample anti-aliasing (\r_ext_multisample)
- supersample anti-aliasing (\r_ext_supersample)
- per-window gamma-correction which is important for screen-capture tools like OBS
- you can minimize game window any time during \video|\video-pipe recording
- high dynamic range render targets (\r_hdr 1) to avoid color banding
- bloom post-processing effect
- arbitrary resolution rendering
- greyscale mode
In general, not counting offscreen rendering features you might expect from 10% to 200%+ FPS increase comparing to KE's original version
Highly recommended to use on modern systems
Based on classic OpenGL renderers from idq3/ioquake3/cnq3/openarena, features:
- OpenGL 1.1 compatible, uses features from newer versions whenever available
- high-quality per-pixel dynamic lighting, can be triggered by \r_dlightMode cvar
- merged lightmaps (atlases)
- static world surfaces cached in VBO (\r_vbo 1)
- all set of offscreen rendering features mentioned in Vulkan renderer, plus:
- bloom reflection post-processing effect
Performance is usually greater or equal to other opengl1 renderers
Original ioquake3 renderer, performance is very poor on non-nvidia systems, unmaintained
Discord channel: https://discordapp.com/invite/X3Exs4C