Understanding Perspective Projection Variants: 0→1, 1→0 (Reversed-Z), and Infinite Depth – Why Modern Engines Should Care

In a previous article, we explored the differences in coordinate systems across graphics APIs like Metal, Direct3D, OpenGL, and Vulkan. This follow-up dives deeper into a related but often overlooked topic: perspective projection depth conventions.

These conventions—mapping view-space Z to normalized device coordinates (NDC) and the depth buffer—profoundly impact depth precision, shadow mapping quality, numerical stability, and cross-API compatibility in engines targeting Metal, Direct3D, Vulkan, OpenGL, ARKit, ARCore, and OpenVR.

1. The Three Major Perspective Projection Variants

Modern graphics engines primarily use one of three depth mapping variants:

Variant Near Plane Far Plane Typical APIs/Engines
Standard (0 → 1) 0 1 Classic Direct3D, Metal, OpenGL
Reversed-Z (1 → 0) 1 0 Modern Direct3D/Vulkan AAA engines
Infinite Reversed-Z 1 ∞ (asymptotic to 0) High-end engines (open worlds, space)

Each represents a trade-off in precision, range, and implementation complexity.

2. Standard Depth: 0 → 1 (Near → Far)

This is the traditional model:

  • Near plane maps to depth 0
  • Far plane maps to depth 1
  • Depth values increase with distance

Characteristics:

  • Intuitive and matches early API designs
  • Works well for small-scale scenes

Limitations:

  • Most depth precision is concentrated near the camera
  • Distant objects suffer from z-fighting (flickering due to insufficient precision)

The non-linear nature of perspective projection wastes floating-point precision near the near plane, leading to issues in large outdoor scenes.

3. Reversed-Z: 1 → 0 (Near → Far)

Reversed-Z inverts the mapping:

  • Near plane → depth 1
  • Far plane → depth 0

When paired with a floating-point depth buffer, this dramatically improves precision because floating-point formats have higher density near 0.

Why it works:

  • Far geometry maps closer to 0, where precision is greatest
  • Reduces z-fighting in distant areas
  • Better stability for large worlds

Requirements:

  • Reverse depth test (use GREATER instead of LESS)
  • Custom projection matrix
  • Adjustments in shadow and post-process shaders

Modern adoption: Widely used in AAA titles and supported natively in Direct3D 12, Vulkan, and Metal. As noted in NVIDIA’s depth precision analysis, reversed-Z significantly mitigates the nonlinearity of 1/z depth distribution.

Visualizing Depth Precision | NVIDIA Technical Blog

4. Infinite Perspective Projection (with Reversed-Z)

This variant eliminates the far plane:

  • Near plane = 1
  • Far approaches 0 asymptotically

Benefits:

  • No far-plane clipping artifacts
  • Ideal for open-world games, space simulations, skyboxes, and atmospheric rendering
  • Even better numerical stability

Costs:

  • Requires careful matrix construction and consistent handling in culling, depth tests, shadows, and unprojection

When properly implemented, infinite reversed-Z offers the most robust depth model for modern engines.

Reversed-Z in OpenGL | nlguillemot

5. Impact on Shadow Mapping

Depth conventions matter most in shadow mapping, where precision mismatches cause artifacts like shadow acne and peter-panning.

With Standard 0→1:

  • Bias values increase rapidly with distance
  • Far shadows lose precision, requiring heavy cascaded shadow map (CSM) tuning

With Reversed-Z / Infinite:

  • Precision is higher at distance
  • Biases can be smaller and more adaptive
  • Shadows remain stable across large cascades
  • Bias direction reverses (push toward smaller depth)

A unified depth model simplifies portable shadow code across APIs.

6. Engine-Level Implications

Your depth convention affects far more than shaders:

  • Projection matrix construction
  • Screen-to-world unprojection
  • Ray casting and object picking
  • CPU/GPU depth agreement
  • Interoperability with external APIs (ARKit, ARCore, OpenVR)

Best practice: Maintain a single internal representation supporting all variants, with conversion layers for external APIs. This enables switching modes without rewriting core math or shaders.

7. Handling External API Differences

APIs disagree on depth:

  • ARKit: 0→1, right-handed
  • ARCore: OpenGL-style
  • OpenVR: Right-handed, column-major
  • Vulkan: Configurable depth, Y-flipped NDC

Recommended approach:

  1. Extract core parameters (FOV, aspect, near/far)
  2. Rebuild projection internally in your chosen mode
  3. Convert only for handedness/axis differences
  4. Explicitly select depth variant

This decouples your engine from API quirks and avoids subtle bugs.

8. Connection to Coordinate Systems (Part 1 Recap)

Depth conventions are tightly coupled with handedness, axis orientation, and clip space. If you missed it, read the companion article:

👉 Navigating Coordinate System Differences in Metal, Direct3D, OpenGL, and Vulkan

Consider this Part 2: Depth and Projection.

9. Potential Future Topics (Part 3+)

  • Linear depth reconstruction across APIs
  • Depth-aware effects (fog, depth of field)
  • Cascaded shadow maps precision analysis
  • Frustum culling with reversed-Z
  • Picking in infinite projections
  • Visual depth debugging techniques

Conclusion

Perspective projection isn’t one-size-fits-all—it’s a spectrum of design choices. Selecting 0→1, reversed-Z (1→0), or infinite reversed-Z directly influences visual fidelity, shadow quality, scalability, and cross-platform reliability.

Modern engines—especially those targeting large worlds or multiple APIs—gain massive benefits from adopting reversed-Z and infinite projections, provided the system is coherently designed from CPU to GPU.

Once unified, depth mode becomes a powerful feature rather than a liability.

What depth convention does your engine use? Share in the comments!