Hubbry Logo
Doom engineDoom engineMain
Open search
Doom engine
Community hub
Doom engine
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
Contribute something
Doom engine
Doom engine
from Wikipedia
id Tech 1
Developersid Software (John Carmack, John Romero, Dave Taylor)
Final release
1.9 / February 1, 1995; 31 years ago (1995-02-01)
Repositorygithub.com/id-Software/DOOM
Written inC, Assembly language
PlatformMS-DOS, PC-98, Windows, Mac, Linux, Android, Amiga, NeXTSTEP, NeXT, Jaguar, 32X, PlayStation, 3DO, Nintendo 64, Saturn, Game Boy Advance, Switch, BSD, Unix, others
PredecessorWolfenstein 3D engine
SuccessorQuake engine
LicenseGNU GPL-2.0-or-later[1]
3DO: MIT[2]

id Tech 1, also known as the Doom engine, is the game engine used in the id Software video games Doom and Doom II: Hell on Earth. It is also used in Heretic, Hexen: Beyond Heretic, Strife: Quest for the Sigil, Hacx: Twitch 'n Kill, Freedoom, and other games produced by licensees. It was created by John Carmack, with auxiliary functions written by Mike Abrash, John Romero, Dave Taylor, and Paul Radek. Originally developed on NeXT computers,[3] it was ported to MS-DOS and compatible operating systems for Doom's initial release and was later ported to several game consoles and operating systems.

The source code to the Linux version of Doom was released to the public under a license that granted rights to non-commercial use on December 23, 1997, followed by the Linux version of Doom II about a week later on December 29, 1997.[4][5] The source code was later re-released under the GNU General Public License v2.0 or later on October 3, 1999.[6][7] The dozens of unofficial Doom source ports that have been created since then allow Doom to run on previously unsupported operating systems and sometimes radically expand the engine's functionality with new features.

Although the engine renders a 3D space, that space is projected from a two-dimensional floor plan. The line of sight is always parallel to the floor, walls must be perpendicular to the floors, and it is not possible to create multi-level structures or sloped areas (floors and ceilings with different angles). Despite these limitations, the engine represented a technological leap from id's previous Wolfenstein 3D engine. The Doom engine was later renamed[citation needed] to "id Tech 1" in order to categorize it in a list of id Software's long line of game engines.[8]

Game world

[edit]

The Doom engine separates rendering from the rest of the game. The graphics engine runs as fast as possible, but the game world runs at 35 frames per second regardless of the hardware, so multiple players can play against each other using computers of varying performance.[9]

Level structure

[edit]

A simple setup demonstrating how Doom represents levels internally

Map view in editor

Viewed from the top down, all Doom levels are actually two-dimensional, demonstrating one of the key limitations of the Doom engine: room-over-room is not possible. This limitation, however, has a silver lining: a "map mode" can be easily displayed, which represents the walls and the player's position, much like the first image to the right.

Basic objects

[edit]

The base unit is the vertex, which represents a single 2D point. Vertices (or "vertexes" as they are referred to internally) are then joined to form lines, known as "linedefs". Each linedef can have either one or two sides, which are known as "sidedefs". Sidedefs are then grouped together to form polygons; these are called "sectors". Sectors represent particular areas of the level.

Sectors

[edit]

Each sector contains a number of properties: a floor height, ceiling height, light level, a floor texture and a ceiling texture. To have a different light level in a particular area, for example, a new sector must be created for that area with a different light level. One-sided linedefs therefore represent solid walls, while two-sided linedefs represent bridge lines between sectors.

Sidedefs

[edit]

Sidedefs are used to store wall textures; these are completely separate from the floor and ceiling textures. Each sidedef can have three textures; these are called the middle, upper and lower textures. In one-sided linedefs, only the middle texture is used for the texture on the wall. In two-sided linedefs, the situation is more complex. The lower and upper textures are used to fill the gaps where adjacent sectors have different floor and ceiling heights: lower textures are used for steps, for example. The sidedefs can have a middle texture as well, although most do not; this is used to make textures hang in mid air. For example, when a transparent bar texture is seen forming a cage, this is an example of a middle texture on a two-sided linedef.

Binary space partitioning

[edit]

Doom makes use of a system known as binary space partitioning (BSP).[10] A tool is used to generate the BSP data for a level beforehand. This process can take quite some time for a large level. It is because of this that it is not possible to move the walls in Doom; while doors and lifts move up and down, none of them ever move sideways.

The level is divided up into a binary tree: each location in the tree is a "node" which represents a particular area of the level (with the root node representing the entire level). At each branch of the tree there is a dividing line which divides the area of the node into two subnodes. At the same time, the dividing line divides linedefs into line segments called "segs".[11]

At the leaves of the tree are convex polygons, where further division of the level is not needed. These convex polygons are referred to as subsectors (or "SSECTORS"), and are bound to a particular sector. Each subsector has a list of segs associated with it.[10]

The BSP system sorts the subsectors into the right order for rendering. The algorithm is fairly simple:

  1. Start at the root node.
  2. Draw the child nodes of this node recursively. The child node closest to the camera is drawn first using a Scanline algorithm. This can be found from looking at which side of the node's dividing line the camera is on.
  3. When a subsector is reached, draw it.[12]

The process is complete when the whole column of pixels is filled (i.e., there are no more gaps left). This ordering ensures that no time is used drawing objects that are not visible and as a result maps can become very large without any speed penalty.

Rendering

[edit]

Drawing the walls

[edit]
Animated comparison of camera rotation in a true 3D environment, left, vs shearing in a 2.5D environment like Doom, right.

All of the walls in Doom are drawn vertically; it is because of this that it is not possible to properly look up and down. It is possible to perform a form of look up/down via "y-shearing", and many modern Doom source ports do this, as well as later games that use the engine, such as Heretic. Essentially this works by moving the horizon line up and down within the screen, in effect providing a "window" on a taller viewable area. By moving the window up and down, it is possible to give the illusion of looking up and down. However, this will distort the view the further up and down the player looks.

The Doom engine renders the walls as it traverses the BSP tree, drawing subsectors by order of distance from the camera so that the closest segs are drawn first. As the segs are drawn, they are stored in a linked list. This is used to clip other segs rendered later on, reducing overdraw. This is also used later to clip the edges of sprites.

Once the engine reaches a solid (1-sided) wall at a particular x coordinate, no more lines need to be drawn at that area. For clipping the engine stores a "map" of areas of the screen where solid walls have been reached. This allows far away parts of the level which are invisible to the player to be clipped completely.[13]

The Doom graphic format stores the wall textures as sets of vertical columns; this is useful to the renderer, which essentially renders the walls by drawing many vertical columns of textures.

Floor and ceiling

[edit]

The system for drawing floors and ceilings ("flats") is less elegant [according to whom?] than that used for the walls. Flats are drawn with a flood fill-like algorithm. Because of this, if a bad BSP builder is used, it is sometimes possible to get "holes" where the floor or ceiling bleeds down to the edges of the screen, a visual error commonly referred to as a "slime trail".[14] This is also the reason why if the player travels outside of the level using the noclip cheat, the floors and ceilings will appear to stretch out from the level over the empty space.

The floor and ceiling are drawn as "visplanes". These represent horizontal runs of texture, from a floor or ceiling at a particular height, light level and texture (if two adjacent sectors have exactly the same floor, these can get merged into one visplane). Each x position in the visplane has a particular vertical line of texture which is to be drawn.

Because of this limit of drawing one vertical line at each x position, it is sometimes necessary to split visplanes into multiple visplanes. For example, consider viewing a floor with two concentric squares. The inner square will vertically divide the surrounding floor. In that horizontal range where the inner square is drawn, two visplanes are needed for the surrounding floor.

Doom contained a static limit on the number of visplanes; if exceeded, a "visplane overflow" would occur, causing the game to exit to DOS with one of two errors, "No more visplanes!" or "visplane overflow (128 or higher)". The easiest way to invoke the visplane limit is a large checkerboard floor pattern; this creates a large number of visplanes.

As the segs are rendered, visplanes are also added, extending from the edges of the segs towards the vertical edges of the screen. These extend until they reach existing visplanes. Because of the way this works, the system is dependent on the fact that segs are rendered in order by the overall engine; it is necessary to draw nearer visplanes first, so that they can "cut off" by others further away. If unstopped, the floor or ceiling will "bleed out" to the edges of the screen, as previously described. Eventually, the visplanes form a "map" of particular areas of the screen in which to draw particular textures.

While visplanes are constructed essentially from vertical "strips", the actual low level rendering is performed in the form of horizontal "spans" of texture. After all the visplanes have been constructed, they are converted into spans which are then rendered to the screen. This appears to be a trade off: it is easier to construct visplanes as vertical strips, but because of the nature of how the floor and ceiling textures appear it is easier to draw them as horizontal strips.

Things (sprites)

[edit]

Each sector within the level has a linked list of things stored in that sector. As each sector is drawn the sprites are placed into a list of sprites to be drawn. If not within the field of view these are ignored.

The edges of sprites are clipped by checking the list of segs previously drawn. Sprites in Doom are stored in the same column based format as the walls are, which again is useful for the renderer. The same functions which are used to draw walls are used to draw sprites as well.

While subsectors are guaranteed to be in order, the sprites within them are not. Doom stores a list of sprites to be drawn ("vissprites") and sorts the list before rendering. Far away sprites are drawn before close ones. This causes some overdraw but usually this is negligible.

There is a final issue of middle textures on 2-sided lines, used in transparent bars for example. These are mixed in and drawn with the sprites at the end of the rendering process, rather than with the other walls.

Games using the Doom engine

[edit]

The Doom engine achieved most of its fame as a result of powering the classic first person shooter Doom, and it was used in several other games. It is usually considered that the "Big Four" Doom engine games are Doom, Heretic, Hexen: Beyond Heretic, and Strife: Quest for the Sigil.

Games built directly on the Doom engine

[edit]
Year Title Developer
1993 Doom id Software
1994 Doom II: Hell on Earth
Heretic Raven Software
1995 Hexen: Beyond Heretic Raven Software
1996 Final Doom TeamTNT
Heretic: Shadow of the Serpent Riders Raven Software
Hexen: Deathkings of the Dark Citadel
Strife: Quest for the Sigil Rogue Entertainment

Games based on the Doom or Doom II code

[edit]

In the 1990s a handful of developers acquired licenses to distribute total conversions of Doom, and following the 1997 source code release a number of standalone titles have been produced in the engine, including freeware, fangames and commercial titles.[15]

Year Title Developer
A.D Cop Electronic Music and Animated Graphics Co., Ltd.
1996 Killing Time (PC) Logicware
Chex Quest Digital Café
Mars 3D Engine Technology Co. Ltd.
1997 Doom 64 Midway Studios San Diego
Chex Quest 2: Flemoids Take Chextropolis Digital Café
HacX Banjo Software
1998 3D Hero

TAO

Engine Technology Co. Ltd.
1999 Batman Doom[16] ACE Team
2000 Sonic Robo Blast 2 Sonic Team Junior
2003 Freedoom Freedoom Team
2008 Chex Quest 3 Charles Jacobi
Blasphemer Blasphemer Team
Action Doom 2: Urban Brawl[17] Scuba Steve
2009 Harmony[18] Thomas van der Velden
2014 The Adventures of Square[19] BigBrik Games
2016 Blade of Agony[20] Daniel Gimmer
2017 Rise of the Wool Ball[21] MSPaintR0cks
2018 REKKR[22] Mockingbird Softworks
Annie[23] SergeJkn
Ashes[24] Vostyok
Total Chaos[25] wadaholic
2019 Hocus Pocus Doom[26] Ravage
Hedon[27] Zan_HedonDev
Shrine[28] Scumhead
2020 Project Osiris[29] ArcturusDeluxe
2021 Castlevania: Simon’s Destiny[30] batandy
Vomitoreum[31] Scumhead
2022 Hands Of Necromancy[32] HON Team
CountryCide[33] TrenchWork
Project Absentia[34] Waffle Iron Studios
I Am Sakuya: Touhou FPS Game[citation needed] Sigyaad Team
2023 Supplice[35] Mekworx
Venturous[36] PixelFox
Apocalyptic Vibes[37] Amanito Computing
2024 Hands of Necromancy 2[38] HON Team
Beyond Sunset[39] Metacorp / Vaporware
Selaco[40] Altered Orbit Studios
Borrowhelen[41] 4-Cube Games
2025 Mala Petaka[42] Sanditio Bayu, Hellforge Studios
Mohrta[43] Scumhead, Osiol
Captain Wayne[44] Ciaran Games LLC, Silver Lining Interactive

See also

[edit]

Notes

[edit]

References

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
The Doom engine, also known as id Tech 1, is a pioneering game engine developed primarily by programmer at for the 1993 video game Doom. It introduced efficient rendering techniques, including (BSP) trees to organize level geometry and determine visibility, enabling fast, texture-mapped visuals on contemporary PC hardware without full 3D polygons. The engine separates game logic from assets stored in WAD files, facilitating and ports, and includes components for multiplayer networking over IPX and a sound system with positional audio. Originally compiled for DOS using Watcom C, it powered Doom (1993), : Hell on Earth (1994), and licensed titles like Heretic (1994), Hexen: Beyond Heretic (1995), and Strife (1996), establishing foundational standards for the FPS genre with its speed, scalability, and distribution model. Its was publicly released on December 23, 1997, under a non-commercial license by Carmack, who noted its outdated aspects like fixed-point math and polar clipping while encouraging community enhancements for features such as slopes and transparency; it was later relicensed under the GNU GPL in 1999, spawning hundreds of source ports for modern platforms. Despite limitations like no true vertical aiming or overhanging geometry due to its 2D map structure, the engine's innovations in real-time rendering and level design influenced subsequent id Tech iterations and the broader industry.

History and Development

Origins and Creation

The Doom engine originated in late 1992 at , when lead programmer conceived it as a significant advancement over the raycasting technology used in the company's previous title, . Carmack's vision was driven by the need to address 's restrictive flat-world design, which limited environments to uniform floor and ceiling heights without variations or multi-level structures. This evolution aimed to enable pseudo-3D spaces with dynamic height differences, textured ceilings, and more immersive level geometries, transforming gameplay into a more architecturally complex experience. Initial prototype development began shortly after 's release, with Carmack focusing on optimizing performance for the era's hardware. The engine was written primarily in , with performance-critical sections in to leverage the speed of 386 processors, and compiled using the Watcom C compiler, targeting as the primary platform to ensure broad accessibility on consumer PCs. This low-level approach allowed for efficient rendering of the ambitious features, building on techniques Carmack had refined during porting efforts for to other systems like the SNES. Key milestones marked steady progress through 1993, culminating in the core engine's completion by late that year, just ahead of Doom's release on December 10. During this phase, the engine integrated with early level editing tools—precursors to modern Doom builders—enabling designers to construct and iterate on multi-height sectors efficiently. To enhance rendering efficiency amid growing level complexity, Carmack later introduced during development.

Key Developers and Innovations

The Doom engine was primarily architected by lead programmer at , who handled the core technical implementation, including the rendering and spatial partitioning systems. Collaborating closely were project leader and designer , who influenced level integration and gameplay flow, and graphic artist (no relation to John), who focused on integrating visual assets into the engine's rendering pipeline. This division of labor allowed for rapid iteration, with Carmack's programming expertise complemented by the artistic and design contributions that ensured seamless asset loading and visual coherence. A major innovation was the first widespread adoption of (BSP) trees in a , pioneered by to efficiently partition static 3D worlds and resolve during rendering. This offline preprocessing technique divided levels into convex subspaces, enabling fast traversal and front-to-back drawing without a full z-buffer, which dramatically improved performance on 1993 hardware. Complementing this, Carmack implemented column-based for walls and sprites, storing assets vertically to match the engine's per-column rendering approach, which minimized memory access and maximized cache efficiency. Additionally, the engine introduced textured floors and ceilings, a feature uncommon in contemporary games like Wolfenstein 3D, which previously used solid colors; this enhanced visual immersion while maintaining performance through specialized rendering techniques detailed in the engine's pipeline. Similarly, artist Kevin Cloud worked on asset pipelines alongside , creating and optimizing textures, sprites, and environmental elements to fit the engine's constraints, ensuring high-quality visuals without compromising speed. Another breakthrough was the introduction of variable height sectors, allowing floors and ceilings to differ in elevation within the same level, which enabled multi-story environments like overhanging balconies and staircases—a leap beyond the uniform-height raycasting of predecessors like . This feature, implemented by Carmack, supported vertical gameplay tactics while maintaining the engine's architecture of horizontal flats and vertical walls.

Source Code Release and Licensing

On December 23, 1997, id Software released the source code for the Linux version of the Doom engine (version 1.10) under the DOOM Source License, a restrictive non-commercial agreement that permitted non-profit use to encourage community-driven ports and modifications while protecting commercial interests. This release, spearheaded by , provided developers with access to the engine's core without the proprietary game data, explicitly requiring users to possess legitimate Doom binaries for compatibility. The initial impact was immediate and widespread, enabling the rapid development of source ports that extended the engine to new platforms while maintaining binary compatibility with original Doom WAD files. For instance, DOSDoom emerged within a day of the release as the first DOS-targeted port, followed by WinDoom, which adapted the code for Windows environments with features like TCP/IP networking. These early ports preserved the engine's performance on legacy hardware and facilitated , ensuring Doom's longevity beyond its original DOS ecosystem. Subsequent licensing evolutions broadened the code's accessibility; on October 3, 1999, granted permission for re-release under the GNU General Public License version 2 (GPLv2) or later, transitioning from the initial non-profit restrictions to full open-source terms that allowed derivative works and commercial redistribution of modifications. This change spurred advanced derivatives, such as ZDoom, initially released on March 6, 1998, which introduced enhancements like dynamic lighting and improved scripting under the GPLv2. Legally, id Software retained copyright over the proprietary assets, including WAD files containing levels, textures, sounds, and sprites, which remained separate from the open-sourced engine code and required separate licensing for use. This distinction prevented unauthorized distribution of complete games while empowering the community to innovate on the engine itself, with modern ownership under (via ) upholding these separations.

Core Architecture

Game World Fundamentals

The Doom engine utilizes a pseudo-3D architecture, often described as , which constructs immersive environments from fundamentally 2D maps augmented with height attributes rather than employing full 3D geometry. However, there is an ongoing debate in the gaming community about classifying it as 2.5D or full 3D, with some arguing that features like Z-axis coordinates for entities and vertical movement (such as jumping and falling) qualify it as 3D despite its limitations. This approach allows for efficient rendering on hardware by projecting flat sectors into a perspective view, simulating depth through variable heights for floors and ceilings while maintaining all structural elements in a horizontal plane. Unlike contemporary true 3D engines, it eschews complex polygonal models or arbitrary surface orientations, prioritizing speed and simplicity in level design and traversal. The operates on a fixed grid in the X-Y plane, where vertices defining the map's layout are placed at positions ranging from -32,768 to 32,767 units. These coordinates form the backbone of the 2D , with Z-axis values introduced solely for vertical offsets in sectors and movable entities, enabling elevation changes without intersecting or overlapping geometry. Player and object positions are computed using 32-bit (16.16 format), providing sub-unit precision for smooth movement and within this grid-based framework. This use of fixed-point arithmetic ensures full determinism in the engine, which enables the efficient demo system by avoiding non-deterministic behaviors associated with floating-point arithmetic in C, where implementations can vary across platforms. World scale in the map editor aligns directly with map units, which the engine interprets with fixed-point scaling for enhanced precision, effectively treating each editor unit as 65,536 internal subunits to handle fractional movements accurately. This scaling ensures consistent proportions, where typical gameplay elements like doorways span 128 units wide, establishing a human-scale environment without requiring floating-point operations. The automap grid, when enabled, visually represents 64 units per square for mapper , reinforcing the engine's grid-aligned . Fundamental constraints shape the engine's world model, notably the use of sector-based static light levels that are uniform within sectors to modulate brightness, with dynamic effects such as flickering light types and temporary brightening from player actions like firing weapons, though lacking per-pixel or moving light sources. Occlusion culling is limited to the (BSP) tree, which determines rendering order but does not incorporate advanced techniques like portal visibility or runtime shadowing. These limitations, including the prohibition of sloped surfaces—all floors and ceilings remain perfectly horizontal—stem from the engine's 2D foundational structure, preventing overlaps or non-planar geometry while optimizing for real-time performance on limited processors. Sectors serve as the primary building blocks, encapsulating these attributes into discrete, enclosed volumes.

Level Data Structure

The Doom engine stores level data in WAD (Where's All the Data) files, which use a lump-based archive format consisting of a 12-byte header identifying the file type (IWAD for internal game data or PWAD for patches), the number of lumps, and an offset to the directory; followed by a directory of 16-byte entries for each lump specifying its offset, size, and 8-character name; and the raw data lumps themselves in arbitrary order. Levels are encapsulated within map-specific lumps prefixed by a marker like E1M1, containing the core geometry and entity data required for the game world. Core level components begin with vertices, defined as 4-byte records storing fixed-point X and Y coordinates (16.16 format) to represent 2D points in the grid, serving as endpoints for structural lines. Linedefs connect pairs of vertices in 14-byte records, including indices to start and end vertices, flags for properties like impassability or two-sided rendering, a special type for effects (e.g., teleporters), a tag for sector triggers, and indices to one or two sidedefs; these define the boundaries and behaviors of walls and portals. Sidedefs, in 30-byte records, attach to linedefs and specify texture mappings with X and Y offsets for alignment, names for upper, lower, and middle textures (padded to 8 bytes, with "-" indicating transparency), and a reference to the adjacent sector for spatial context. Sectors enclose areas bounded by linedefs in 26-byte records, detailing floor and ceiling heights (in map units), texture names for flats, level (0-255), special types (e.g., damage floors or secrets), and a tag linking to linedef triggers for dynamic effects. Object placement occurs via the THINGS lump, where each 10-byte record positions entities as 2D sprites with X and Y coordinates, facing angle (in 0-359 degrees, multiples of 45), type identifier (e.g., 1 for player start, 7 for spider demon, 5 for blue key), and flags for skill levels, multiplayer spawning, or behavior (deaf monsters). These define interactive elements like enemies, items, and lights without inherent 3D orientation beyond angle and height inheritance from sectors. During loading, the engine reads these raw lumps and preprocesses the geometry by generating segments (SEGS) from linedefs, subdividing sectors into convex subsectors (SSECTORS) for efficient partitioning, and building a binary space partitioning (BSP) node tree (NODES) to organize the map for traversal and rendering, enabling hidden surface removal without per-frame calculations. This BSP integration allows rapid occlusion queries during gameplay, with subsector segmentation ensuring convex polygons for texture projection.
LumpSize per EntryKey FieldsPurpose
VERTEXES4 bytesX, Y coordinates2D map points for geometry.
LINEDEFS14 bytesVertex indices, flags, type, tag, sidedef indicesWall connections and properties.
SIDEDEFS30 bytesTexture offsets, upper/lower/middle textures, sectorWall texturing and adjacency.
SECTORS26 bytesFloor/ceiling heights, flat textures, light, type, tagEnclosed areas and effects.
THINGS10 bytesX/Y position, angle, type, flagsEntity placement and attributes.

Binary Space Partitioning

The (BSP) tree in the Doom engine organizes the 2D level geometry into a hierarchical structure of convex subspaces, enabling efficient visibility determination and rendering without a full z-buffer. This approach, adapted by from earlier research, partitions the map using lines extended from linedefs as hyperplanes, ensuring all resulting regions (subsectors) are convex polygons that simplify and occlusion checks. The tree is precomputed offline during level compilation, transforming the raw map data into a where each node represents a partitioning line, and leaf nodes correspond to visible subsectors. BSP tree construction begins with the entire map as the initial region and proceeds recursively: a suitable linedef is selected as the splitter, extended infinitely in both directions to form a partitioning , and the map is divided into two half-spaces containing the remaining geometry. Any linedefs intersected by the splitter are split at the intersection point to avoid crossing partitions, increasing the total number of segments while ensuring convexity. The selection of the splitter aims to balance the tree by minimizing the difference in subtree sizes, often using heuristics to evaluate potential lines based on the number of affected segments and overall balance, as outlined in methods for generating efficient partitioning trees. This recursive process continues until all subregions are small convex subsectors, typically bounded by 4 to 20 segments, resulting in a with depth proportional to the map's complexity. The original Doom node builder, iBSP, implemented this in on , taking seconds to minutes per level depending on size. During rendering, the BSP tree is traversed from the root node using the player's viewpoint to classify and prioritize subsectors for . The function R_RenderBSPNode recursively visits nodes, computing the viewpoint's position relative to each partitioning plane to determine if it lies in the front (positive side), back (negative side), or on the plane. Subtrees on the opposite side of the viewpoint are early, while visible portions are sorted front-to-back to allow natural occlusion—closer walls obscure farther ones without depth testing. Bounding boxes around subtrees provide additional coarse , discarding entire branches if they fall outside the view . This traversal identifies active subsectors, which are then rendered by their bounding segments (segs) as walls, ensuring only visible is processed and maintaining consistent on 1993 hardware. Central to both construction and traversal is the side-classification mathematics, which uses vector cross products to evaluate point positions relative to lines. For a point P=(x0,y0)P = (x_0, y_0) and a line defined by points A=(x1,y1)A = (x_1, y_1) and B=(x2,y2)B = (x_2, y_2), the signed value d=(x2x1)(y1y0)(x1x0)(y2y1)d = (x_2 - x_1)(y_1 - y_0) - (x_1 - x_0)(y_2 - y_1) indicates the side: d>0d > 0 for one half-space (front), d<0d < 0 for the other (back), and d=0d = 0 for collinearity, used in splitting to find intersection points along the line. During tree building, this formula identifies intersections for segment splits; in rendering, it drives the recursive decisions for viewpoint navigation. This efficient 2D computation, requiring only multiplications and subtractions, aligns with the engine's fixed-point arithmetic for speed.

Rendering Pipeline

Wall and Surface Drawing

The Doom engine renders vertical walls and surfaces through a column-based projection technique that transforms 2D map geometry into a 3D perspective view on the screen. Wall segments, known as segs, are projected by converting their endpoint vertices into angular positions using Binary Angular Measurement (BAM) and a (viewangletox) to determine corresponding screen x-coordinates. The vertical extent of each column is calculated based on the segment's distance from the player and the sector's ceiling and floor heights, ensuring perspective scaling where closer walls appear taller. This process avoids full ray tracing by relying on pre-partitioned geometry, drawing one column at a time across the screen width. Texture application occurs via vertical strips extracted from wall textures, which are stored rotated 90 degrees counterclockwise to optimize cache access during rendering. Each column's texture coordinate is offset to align with the wall's position in the , and the strip is scaled vertically by the projected height; upper and lower textures fill from to mid-point and mid-point to floor, respectively. Mid-textures, applied to the middle portion of segs, handle features like and windows, with support for transparency in specific cases such as switch animations. Shading is applied using fixed-point light level calculations per column, diminishing with distance. To manage overlaps and occlusion, segs are processed in front-to-back order as dictated by the (BSP) tree traversal, clipping each new segment against previously drawn ones using a span occlusion array (solidsegs). Backface culling eliminates invisible sides by checking if the angle between segment endpoints exceeds 180 degrees from the view. This painter's algorithm approach ensures distant walls are obscured without a depth buffer, limiting the engine to convex rooms but enabling efficient rendering on 1993 hardware. Special effects for walls include through frame cycling, where textures switch based on elapsed time and predefined sequences defined in the level . Transparent or masked mid-textures, such as those for fences or switches, are rendered in a separate pass (R_DrawMasked) after walls to composite semi-transparent elements correctly. These effects are constrained to avoid overhead, with no support for arbitrary transparency on full walls.

Floor and Ceiling Texturing

In the Doom engine, floors and ceilings are rendered as horizontal planes textured with low-resolution , which are 64x64 images lacking the vertical seams found in wall textures. These flats are projected onto the screen using an inverse perspective transformation to simulate 3D depth, with the projection divided into horizontal spans bounded by the vertical walls already drawn in the scene. The rendering process begins after walls are processed, using data from wall column projections to define the visible areas for each flat. Floor and ceiling heights are computed relative to the player's eye position and the sector's predefined floor and ceiling elevations. Calculations employ 16.16 for precision, determining the screen-space y-coordinates where the flat intersects the view ; for instance, the floor Z is derived as the difference between player height and sector height, scaled by distance from the viewpoint. Since sectors are strictly flat with no support for slopes or varying heights within a single plane, this results in uniform Z-levels per sector, simplifying the projection but limiting geometric variety. Performance is enhanced through visplanes, data structures that aggregate and deduplicate rendering of identical flats across the scene. Each visplane captures a unique combination of height, texture index, light level, and screen x-extent, with top and bottom y-boundary arrays defining discontinuous horizontal segments for drawing. The engine precomputes up to 128 visplanes per frame by merging subsectors sharing the same flat properties, avoiding redundant texture mapping and column draws; this hashing-based lookup (later improved in ports) significantly reduces overdraw in open areas. Exceeding the visplane limit in dense levels triggers errors, as seen in the classic "no more visplanes" overflow. Variants handle special environmental effects without altering the core flat system. Sky sectors use a dedicated infinite ceiling flat, mapped with cylindrical texture coordinates that pan based on yaw to create parallax scrolling, rendering behind all other elements. Water and sludge effects rely on sector special types that dynamically adjust floor height with sinusoidal bobbing tied to player movement, combined with lowered light levels and optional transparency via overlaid walls, to evoke liquid surfaces. Span boundaries for these flats are determined by occlusion from previously rendered walls.

Sprite and Entity Rendering

The Doom engine renders interactive elements, such as enemies, items, and projectiles, as 2D sprites that employ billboarding to always face the player's viewpoint. These sprites consist of pre-rendered 2D images stored in the game's WAD files in a column-based format, mirroring the structure used for wall textures to enable shared rendering functions. During rendering, the engine calculates the sprite's orientation by aligning it perpendicular to the from the player, effectively rotating the 2D image in the horizontal plane while keeping it upright in the vertical axis. Scaling is applied based on the from the player to the sprite's position, with closer sprites appearing larger and farther ones smaller, creating a sense of depth in the pseudo-3D environment. To manage visibility and depth, sprites are collected during the BSP traversal and sorted by their distance from the player, drawn in back-to-front order to handle overlaps correctly among themselves. Occlusion against the world geometry is achieved by clipping sprite columns against the segments (segs) of the BSP subsectors that have already been rendered, ensuring sprites do not pierce walls or floors. This clipping uses the z-buffer equivalent provided by the ordered BSP drawing, where only visible spans of each sprite column are plotted onto the screen buffer, minimizing overdraw and maintaining performance on 1993-era hardware. Animations for entities are driven by frame sequences defined in the WAD lumps, where each sprite type (e.g., for a specific ) includes multiple frames named systematically, such as "TROOA0" for the first frame of a trooper. These frames are selected via state machines in the engine's system, which update states each (1/35th of a second) based on behaviors like walking, attacking, or dying, transitioning to the next frame or sprite lump as needed. This approach allows for simple yet effective animations without requiring complex skeletal systems. Sprite lighting employs a palette-based shading system with 32 discrete levels, applied uniformly across the sprite but modulated by the ambient light level of the enclosing sector and a distance-based falloff from the player. Rather than per-pixel dynamic lights, the engine shifts the sprite's color indices in the 256-color palette toward darker equivalents (e.g., from full to shadowed versions) based on these factors, with farther sprites receiving progressively dimmer to simulate . This method, computed per sprite during drawing, avoids costly real-time calculations while providing visual depth cues.

Audio and Input Systems

Sound Engine Mechanics

The Doom engine's sound effects are stored as raw (PCM) data within WAD files, consisting of unsigned 8-bit monaural samples typically sampled at 11025 Hz to ensure compatibility with contemporary PC sound hardware such as the Sound Blaster. These PCM lumps are loaded into memory via the WAD caching system during initialization, allowing quick access for playback without on-the-fly decompression. Positional audio in the engine employs a straightforward stereo panning mechanism, where the left-right balance is determined by the relative angle to the sound source, calculated from the differences in both X and Y coordinates, scaled through a separation parameter ranging from approximately 32 to 224. attenuation is calculated based on the approximate to the source, using a fast integer approximation for efficiency; sounds are clipped beyond a maximum of 1200 units (in fixed-point FRACUNIT scaling) and reach full volume within 160 units. This approach provides basic spatial cues without true 3D spatialization, relying on hardware output for immersion. Sound mixing supports up to 32 concurrent channels in the engine's design, though practical limits often cap at around 16 due to hardware constraints of the , with allocation managed through a priority system defined in the sfxinfo structure. Higher-priority sounds, such as weapon fire, preempt lower-priority ones like ambient effects when channels are saturated, ensuring critical remains audible; channel reuse occurs dynamically via the S_getChannel function to minimize interruptions. The mixing process updates positional volumes frame-by-frame, applying lookup tables for left/right channel scaling to simulate directionality. Music playback utilizes files converted to a MUS format, handled through the sound library developed by Paul Radek for DOS compatibility, which synthesizes tracks via FM synthesis or MIDI-compatible hardware. Level music loops continuously by restarting the track upon completion, invoked via S_ChangeMusic with the looping flag enabled, providing uninterrupted atmospheric scoring without interrupting sound effects. The library interfaces with the engine's I_SetMusicVolume and related functions to maintain separate volume controls for music and effects, preventing overlap in the audio output stream.

Input Handling and Controls

The Doom engine processes user inputs through an event-driven polling mechanism synchronized to the game's fixed 35 Hz rate, ensuring consistent across varying hardware speeds. During each , approximately 1/35th of a second, the system collects discrete inputs from the keyboard, , and , translating them into movement deltas and orientation changes for the player entity. This approach applies vectors based on input states—such as forward up to approximately 3.125 units per for running—before applying friction and clipping speeds to a maximum of 30 units per per axis. Delta-based movement then resolves these changes relative to the previous position, enabling smooth navigation within the environment. Standard controls rely on the for directional movement (forward, backward, strafe left/right) and turning, with the for running and spacebar for actions like opening or firing weapons. Mouse input handles relative aiming and turning, where horizontal movement adjusts the player's view angle, and sensitivity can be tweaked via in-game menus or configuration files to scale the per of mouse displacement—ranging from subtle adjustments for precision to higher values for faster sweeps. support, implemented through direct polling of the PC's analog , maps the stick's X and Y axes to turning and forward/backward movement, respectively, with up to four buttons bound to fire, use, and strafe functions, serving as a precursor to modern input APIs like . Collision detection integrates seamlessly with input processing by validating proposed movement deltas against the level geometry using axis-aligned bounding box () checks, where the player occupies a fixed 32x32 . These checks test intersections with linedefs (sector boundaries defining walls and floors) and things (other entities like monsters), rejecting or sliding the movement vector if a collision occurs—large deltas exceeding 15 units are subdivided into smaller steps for accuracy, allowing the player to slide along walls without sticking. This ensures responsive navigation while respecting the engine's spatial constraints. Input configuration is managed through a plain-text file generated by the setup utility (setup.exe), which stores key bindings as hexadecimal scancodes mapped to actions, enabling remapping of keyboard and inputs without recompiling the engine. sensitivity and other parameters, such as turning speed multipliers, are also persisted here, with defaults favoring on period hardware. For , the engine incorporates autoaim on projectile weapons, which scans for valid targets within an angular tolerance of approximately ±5.6 degrees off-center (ANG26 in engine units) and a maximum range, automatically pitching or yawing shots toward the nearest enemy to simulate intuitive targeting in the absence of full 3D aiming.

Limitations and Optimizations

Performance Constraints

The Doom engine targeted a frame rate of 35 frames per second on an Intel 80386 processor running at 33 MHz, with rendering synchronized to the monitor's vertical sync (V-sync) to prevent and ensure consistent playback across networked multiplayer sessions. Memory constraints reflected 1993 hardware realities, capping total system RAM support at 8 MB while imposing strict level design limits, such as a maximum of 32,767 sectors per map, to fit within conventional and allocations under DOS. The engine operated as a fully single-threaded application in a non-preemptive DOS environment, lacking any multitasking support and blocking execution during I/O operations like disk reads or network packets. Features such as sloped floors or recursive portals were precluded due to exceeding the computational budget of contemporary CPUs. Another key rendering limitation was the 128 visplane cap, which could cause visual artifacts like missing textures or "fuzzy" walls in maps with highly complex floor/ceiling variations. Performance optimizations centered on efficiency for low-end hardware, utilizing fixed-point mathematics for all spatial and trigonometric computations to bypass the slow or absent floating-point units in 386 processors, and employing column-based texture caching in the renderer to reuse precomputed vertical spans and alleviate CPU bottlenecks during scene traversal.

Hardware Dependencies

The Doom engine was developed primarily for the operating system running on PC-compatible computers, targeting hardware prevalent in 1993. It required a minimum of an Intel 80386 processor operating at 33 MHz and 4 MB of RAM to load and execute the game effectively, as the engine's real-time rendering and level loading demanded efficient and CPU cycles. output was constrained to VGA mode at a resolution of 320×200 pixels with 256 colors, leveraging the standard VGA hardware found in most PCs of the era without any dedicated 3D . To enhance user experience on this platform, the engine supported optional peripherals for audio and input. Sound output relied on devices such as the Sound Blaster card for high-fidelity digitized effects and music via , while basic support provided fallback audio. Input handling was optimized for keyboard and combinations, with compatibility for the joystick to enable analog control in a time when digital pads were common but not universal. The absence of GPU hardware meant all rendering, including and occlusion culling, was performed entirely in software using highly optimized assembly code tailored to the 386 . Early ports to consoles in 1995, such as the Super NES and PlayStation, highlighted the engine's tight coupling to PC hardware, necessitating major adaptations to accommodate limited processing power, memory, and graphics capabilities. For the Super NES release in September 1995, developers created a custom Reality Engine that diverged significantly from the original, stripping complex features like the tree to fit within the console's 128 KB RAM and reliance on the Super FX-2 for polygon-like rendering. The PlayStation port, arriving later that year, retained more of the core engine structure but required modifications for the console's 2 MB RAM and geometry transformation hardware, including simplified map data from the version to reduce computational overhead. These changes ensured playability but often resulted in reduced visual fidelity and frame rates compared to the PC original.

Notable Bugs and Exploits

The Doom engine contained several notable bugs that affected rendering, collision detection, and security. The visplane overflow limited the engine to rendering only 128 unique floor and ceiling planes, resulting in visual artifacts such as missing textures in complex maps. A significant collision detection issue stemmed from flaws in the blockmap data structure, causing inaccuracies where projectiles could pass through walls or miss intended targets due to improper line-of-sight checks. Furthermore, vulnerabilities in the engine allowed for arbitrary code execution (ACE), exploitable through modified savegames or loaders, enabling the injection and running of unauthorized code, including demonstrations of running other games like Snake within Doom.

Legacy and Derivatives

Official Expansions and Ports

The Doom engine powered several official titles developed or published by , beginning with the seminal Doom, released on December 10, 1993, for , which established the engine's capabilities for fast-paced 3D rendering and multiplayer gameplay. This was followed by Doom II: Hell on Earth in 1994, which expanded the engine's features with new enemy behaviors, weapon types, and larger level designs while maintaining compatibility with the original's architecture. These core games formed the foundation for subsequent official content, including expansions that introduced additional levels without altering the engine's core mechanics. Official expansions included Master Levels for Doom II, released on December 26, 1995, which added 21 new single-player maps curated by from community submissions, providing extended gameplay within the Doom II framework. Final Doom, published by in 1996, comprised two distinct episode packs—TNT: Evilution developed by Team TNT and The Plutonia Experiment by the Casali brothers—each featuring 32 levels designed for Doom II, emphasizing increased difficulty and environmental variety while adhering to the engine's level format constraints. Early console ports extended the engine's reach, such as the version of Doom released on November 28, 1994, which adapted the PC original for hardware with limited resources, supporting up to four-player multiplayer via link cable. Licensed variants of the Doom engine enabled commercial derivatives by other studios under id Software's oversight. Raven Software's Heretic, released on December 29, 1994, modified the engine for a fantasy setting, introducing inventory-based magic systems and flying mechanics while preserving the sector-based rendering and sprite handling. This was succeeded by Hexen: Beyond Heretic in 1995, which further evolved the engine with hub-world progression, class-based characters, and puzzle elements, enhancing scripting for more complex interactions. A notable later official release was in 1997, developed by under supervision for the , featuring a customized engine variant with enhancements like colored sector lighting—allowing up to five dynamic colored lights per area for atmospheric effects—and new particle systems for fog and animations, alongside 32 original levels.

Community Modifications and Forks

Following the release of the Doom engine on December 23, 1997, under a non-commercial and its relicensing under the GNU GPL on October 3, 1999, the community rapidly developed modifications and forks that extended the engine's capabilities while preserving its core gameplay. These efforts transformed the engine into a highly flexible platform for modern hardware, enabling enhanced rendering, modding tools, and compatibility with new features without altering the original game's essence. One of the earliest influential source ports was Boom, released in 1998 by TeamTNT (Jim Flynn, Stan Gula, Ty Halderman, Lee Killough, and Rand Phares). Boom focused on limit removal to address vanilla Doom's hardcoded restrictions, such as the visplane overflow that limited map complexity, introducing generalized limits that allowed for more intricate level designs with higher numbers of sectors, lines, and vertices. It also added editing-friendly features like generalized linedef and sector types, enabling adjustable parameters for effects such as friction, wind, and scrolling—often referred to as "sliders" for fine-tuning map behaviors—while maintaining compatibility with original Doom maps and demos. Boom's conservative approach ensured it ran on DOS hardware of the era, fixing numerous bugs and serving as a foundation for subsequent ports. ZDoom, initially released on March 6, 1998, by Marisa Heit (), emerged as another pivotal , merging elements from earlier projects like ATB Doom and NTDOOM to support Windows, , and other platforms. It introduced advanced support through DECORATE for actor definitions and later ZScript (added in version 2.3.0 in 2010), a full scripting language that allowed developers to create complex behaviors, custom weapons, and interactive elements beyond vanilla capabilities. ZDoom also pioneered true rendering, enabling angled floors and ceilings for more dynamic environments, along with uncapped framerates and improved z-clipping to handle vertical . Its derivative, GZDoom (maintained by Christoph Oelckers since 2005 and ongoing as of 2025), expanded on this with hardware-accelerated rendering for dynamic lighting, models, and high-resolution textures, while retaining software rendering options for compatibility. GZDoom's ongoing development has made it the de facto standard for mod-heavy playthroughs. In November 2025, UZDoom was announced as a successor project to GZDoom, building on its features with further optimizations for contemporary systems. In the 2020s, specialized ports continued to evolve the engine for niche uses. DSDA-Doom, forked from PrBoom+ in November 2020 by the Doom Speed Demos Archive team, emphasizes competitive play with robust demo recording, playback, and timing tools, supporting MBF21 features like arch-vile revives and silent teleports while enforcing strict vanilla-like behavior for fair speedrunning. It includes an in-game console, scripting via Lua, and compatibility with Heretic, Hexen, and UDMF maps, making it essential for archival and tournament-grade Doom. Similarly, the Eternity Engine, originally based on SMMU and actively developed since 2007 by James Pugh and others, provides "vanilla+" enhancements such as extended scripting with ACS extensions, skybox support, and randomized map elements, all while prioritizing demo compatibility and limit-removing features to augment classic experiences without requiring UDMF. The engine's modularity, particularly through WAD file format support, fostered a vibrant ecosystem that leverages these ports for gameplay overhauls and total conversions. Brutal Doom, released in 2010 by Marcos Abenante (Sergeant Mark IV), exemplifies this flexibility as a GZDoom-compatible WAD that amplifies combat intensity with interactive gore, new weapons, and third-person views, which has garnered significant popularity within the community by enhancing the engine's sprite-based rendering without engine modifications. Earlier, (1997) demonstrated total conversion potential as a non-violent promotional WAD by Digital Café, replacing demons with "Flemoids" and weapons with zappers in a cereal-branded adventure, proving the engine's adaptability for family-friendly reinterpretations while using vanilla Doom assets. These mods, enabled by the source ports' , have sustained a community producing thousands of WADs annually. As of 2025, community efforts focus on modernizing the engine for contemporary hardware, with ports like GZDoom integrating renderers alongside for high-resolution support up to 4K and beyond, improving performance on multi-core systems and enabling features like true high-dynamic-range lighting. Experimental community projects, such as neural network-based texture upscaling in forks like those derived from Doomsday Engine, apply AI to enhance original low-res assets to 4x or 8x resolutions while preserving fidelity, though these remain niche due to compatibility challenges. This ongoing ensures the Doom engine's relevance nearly three decades after its debut.

References

  1. https://doomwiki.org/wiki/Doom_engine
  2. https://doomwiki.org/wiki/Doom_source_code
  3. https://doomwiki.org/wiki/Doom_rendering_engine
  4. https://doomwiki.org/wiki/WinDoom
  5. https://doomwiki.org/wiki/ZDoom
  6. https://doomwiki.org/wiki/Room-over-room
  7. https://doomwiki.org/wiki/Fixed_point
  8. https://doomwiki.org/wiki/Lighting_effects
  9. https://doomwiki.org/wiki/Autoaim
  10. https://doomwiki.org/wiki/Visplane_overflow
  11. https://doomwiki.org/wiki/Flawed_collision_detection
  12. https://doomwiki.org/wiki/ACE_Engine
  13. https://doomwiki.org/wiki/Boom
  14. https://doomwiki.org/wiki/DSDA-Doom
  15. https://doomwiki.org/wiki/Brutal_Doom
Add your contribution
Related Hubs
Contribute something
User Avatar
No comments yet.