DirectX 5.0: How Transformed and Lit Vertices Changed Direct3D
The release of DirectX 5.0 marked a turning point for PC 3D graphics
by replacing the cumbersome Direct3D Execute Buffer architecture with
the streamlined DrawPrimitive API, anchored by the
introduction of Transformed and Lit (TL) vertices. By providing a
standardized structure for geometry that had already undergone
coordinate transformation and lighting calculations, DirectX 5.0 allowed
developers to bypass Direct3D's internal geometry pipeline. This
architectural shift gave programmers the flexibility to write
high-performance, custom CPU transformation routines, drastically
reduced API overhead, and created a clean division between geometry
processing and rasterization that set the foundation for the 3D
accelerator revolution.
The Problem with Early Direct3D: Execute Buffers
Prior to DirectX 5.0, Direct3D Immediate Mode relied on Execute Buffers. Introduced in DirectX 2.0 and 3.0, Execute Buffers required developers to bundle vertex data, render states, and primitive instructions into a single, complex memory block before passing it to the runtime.
This model proved unpopular among game developers. Constructing and parsing Execute Buffers introduced massive CPU overhead, required difficult memory management, and made it tedious to update dynamic geometry. Most developers favored proprietary APIs like 3dfx Glide or the cleaner paradigm of OpenGL, both of which allowed more direct control over vertex submission.
The
Introduction of D3DTLVERTEX and
DrawPrimitive
DirectX 5.0 solved these pain points by overhauling Direct3D with the
DrawPrimitive and DrawIndexedPrimitive APIs,
accompanied by flexible vertex formats. At the center of this update was
the D3DTLVERTEX (Transformed and Lit Vertex) structure.
In standard 3D math, a 3D point begins in local object space, undergoes matrix multiplication to transform into world, view, and screen-space coordinates, and then receives lighting calculations based on virtual light sources.
A transformed and lit vertex represented data that had already completed this entire stage:
- Screen-Space Coordinates (\(X, Y, Z\)): The 2D viewport coordinates combined with depth information for the Z-buffer.
- Reciprocal of Homogeneous W (\(RHW\)): A value used by hardware rasterizers for perspective-correct texture mapping.
- Pre-Calculated Lighting: Diffuse and specular color components stored directly in the vertex, removing the need for runtime lighting computation.
- Texture Coordinates (\(U, V\)): Mapping data ready for sampling.
Empowering Custom CPU Pipelines
During the late 1990s, dedicated 3D graphics cards handled rasterization, texture mapping, and depth buffering, but lacked hardware-level geometry processing. Transformation and lighting were handled exclusively by the host CPU.
The introduction of TL vertices meant Direct3D no longer forced
developers to use Microsoft's internal matrix math and lighting
algorithms. Developers could build highly optimized transformation and
lighting engines on the CPU, leveraging instruction sets like Intel's
MMX and later AMD's 3DNow! to manipulate vertex data at peak speeds.
Once processed, the application fed the resulting array of
D3DTLVERTEX structs directly into
DrawPrimitive, allowing the graphics card to focus entirely
on rasterization.
Architectural Legacy
By separating geometry processing from triangle rasterization, DirectX 5.0 established Direct3D as a viable, modern competitor to Glide and OpenGL. Decoupling these phases not only accelerated rendering in late-90s PC gaming, but it also defined the pipeline stages that Microsoft later formalized when hardware-based transformation and lighting arrived with DirectX 7.0 and the launch of the Nvidia GeForce 256.