Fact-checked by Grok 2 weeks ago

Stencil buffer

The stencil buffer is an auxiliary per-pixel buffer in rendering pipelines, typically 8 bits deep and integrated with the depth buffer, that enables selective ing of fragments during rendering to control which pixels are drawn or modified. It functions as a , allowing developers to restrict drawing operations to specific regions of the , such as confining effects to object silhouettes or excluding areas from further processing. In the rendering process, the stencil buffer operates through a stencil test, which compares a programmable reference value against the stored stencil value at each fragment's location using a bitwise and a comparison function (e.g., less than, equal, greater than, or always pass). If the test passes or fails, combined with the outcome of the depth test, one of several stencil operations is applied to update the buffer: these include keeping the current value, replacing it with the reference, setting it to zero, inverting bits, or incrementing/decrementing it (with wrapping or clamping at the buffer's bit limits, usually 0 to 255 for 8-bit depth). The buffer can be cleared to a uniform value, for read/write control, and configured separately for front- and back-facing primitives in APIs like and . This functionality supports key applications in real-time graphics, including shadow volume rendering for casting accurate shadows by marking occluded pixels, object outlining via multi-pass techniques that isolate edges, and decal projection or by restricting modifications to defined shapes. In modern GPUs, stencil buffers remain essential for efficient per-pixel decisions, often packed with depth data in formats like D24S8 (24-bit depth, 8-bit stencil), and are exposed through graphics APIs for programmable control in shaders and fixed-function pipelines.

Fundamentals

Definition and Purpose

The stencil buffer is an auxiliary per-pixel data buffer in graphics rendering hardware, typically allocated 8 bits per pixel, that operates alongside the color buffer and depth buffer to selectively mask or restrict rendering operations on a pixel-by-pixel basis. It stores unsigned integer values, usually ranging from 0 to 255 in an 8-bit configuration, which serve as a reference for comparison tests during the rendering process. This buffer enables precise control over which fragments contribute to the final image, functioning as a mask to enable or disable drawing in specific regions without altering the underlying geometry or color data. The primary purpose of the stencil buffer is to facilitate complex and optimizations in rendering, such as shadows, reflections, and scene partitioning, by defining visibility through conditional testing and updating of stored values. For instance, it allows developers to restrict rendering to designated areas, like mirroring only visible portions of a or isolating geometric volumes for , thereby enhancing efficiency in multipass rendering pipelines. These capabilities stem from its role in per-pixel decision-making, which goes beyond the depth buffer's handling to support arbitrary masking logic tailored to application needs. Historically, hardware support for the stencil buffer gained prominence with the graphics chip in 1997, which introduced a 1-bit stencil buffer for mass-market acceleration, marking an early step toward widespread adoption in professional and consumer GPUs. By the late 1990s, implementations expanded to 8-bit depths in chips like NVIDIA's , solidifying its integration into standard graphics APIs. Today, the stencil buffer is a core feature in modern GPUs across APIs like and , essential for real-time rendering in games and simulations. In a general workflow, during the rasterization stage of the , incoming fragments' stencil values are compared against the buffer's contents using programmable functions, with successful tests allowing updates to the buffer or proceeding to subsequent operations like depth testing, thereby defining the boundaries of renderable regions. This process integrates seamlessly with the fragment processing phase, where the buffer's state influences whether pixels are written to the color or depth buffers.

Architecture

The stencil buffer is typically allocated in with the Z-buffer to optimize storage in graphics hardware, forming a combined depth-stencil buffer. Common modern formats pack 24 bits for depth precision and 8 bits for the stencil component into a 32-bit per-pixel structure, as standardized in extensions like GL_OES_packed_depth_stencil. Historically, earlier formats included 15 bits for the Z-buffer and 1 bit for the stencil, as seen in initial implementations such as D15S1. This packing reduces while enabling efficient access during rendering. Data in the stencil buffer is represented as unsigned values per , ranging from 0 to $2^n - 1, where n is the allocated to the (commonly 8 bits today). These values support operations like masking and counting in per-pixel tests. supports packed formats for seamless integration, such as the 32-bit combined Z-stencil structure, which allows atomic updates to both buffers in a single memory transaction. The evolution of the stencil buffer began with Silicon Graphics Incorporated (SGI) in the late 1980s and early 1990s, where it was first introduced as per-pixel stencil testing in their IRIS GL library on systems like the VGX workstation. Early SGI implementations varied in depth, with the Indigo 2 Extreme providing 4 stencil bits and the MXI expanding to 8 bits, influencing the transition to . By the late 1990s and 2000s, consumer GPUs from (e.g., Riva TNT with 8-bit stencil) and adopted the 8-bit standard, embedding it in fixed-function pipelines without support for floating-point stencil values in rasterization stages. Performance considerations for the stencil buffer center on , as reads and writes to the buffer occur per fragment, potentially increasing latency in high-resolution rendering. Optimizations in fixed-function pipelines, such as early stencil rejection, discard fragments before expensive computations if the stencil test fails, reducing unnecessary buffer accesses and improving throughput. Stencil operations are particularly efficient on 8-bit surfaces compared to deeper buffers, minimizing overhead in scenarios like masking.

Stencil Test

The stencil test is a per-fragment operation in the graphics rendering pipeline that can be performed early, before the fragment if early fragment tests are supported and the shader does not modify gl_FragDepth, or late, after the fragment but before the depth test otherwise. It compares the current value stored in the stencil buffer at the fragment's location against a programmable reference value to determine whether the fragment proceeds to subsequent stages. This test enables selective rendering by discarding fragments that fail the comparison, facilitating techniques such as masking and multipass effects. The comparison is configured using functions like GL_ALWAYS (always passes), GL_NEVER (always fails), GL_LESS (passes if reference < stencil value), GL_LEQUAL, GL_GREATER, GL_GEQUAL, GL_EQUAL, or GL_NOTEQUAL, applied after bitwise ANDing both values with a read mask to select relevant bits. The reference value is clamped to the range [0, 2^n - 1], where n is the number of stencil bits (typically 8), and the read mask (set via glStencilFunc) controls which bits participate in the comparison, allowing per-bit granularity. If the test passes, the fragment advances; otherwise, it is discarded, and an associated stencil operation is applied to update the buffer. Upon test outcome, stencil buffer updates are determined by three programmable operations: one for stencil fail (sfail), one for stencil pass but depth test fail (dpfail), and one for both passing (dppass). Available operations include GL_KEEP (retain current value), GL_ZERO (set to 0), GL_REPLACE (set to reference value), GL_INCR (increment, saturating at maximum), GL_INCR_WRAP (increment with wraparound), GL_DECR (decrement, saturating at 0), GL_DECR_WRAP (decrement with wraparound), and GL_INVERT (bitwise invert). These are masked by a write mask (set via glStencilMask), which bitwise ANDs the new value before storing, protecting specified bits from modification. If the depth test is disabled, the dpfail operation is skipped, and dppass applies directly on stencil pass. The logic can be expressed in as follows:
if (stencil_func(stencil_value & read_mask, reference & read_mask, func)) {
    if (depth_test_passes()) {
        stencil_value = apply_operation(stencil_value, dppass, write_mask);
    } else {
        stencil_value = apply_operation(stencil_value, dpfail, write_mask);
    }
} else {
    stencil_value = apply_operation(stencil_value, sfail, write_mask);
}
This structure allows the stencil test to interact with the depth buffer for combined visibility decisions, such as in occlusion culling.

Integration in Rendering Pipeline

Relation to Other Buffers

In the graphics rendering pipeline, the stencil buffer operates during the fragment processing stage, specifically after fragment shading. In , it occurs before the depth test, enabling early fragment rejection if the stencil test fails and avoiding unnecessary depth computations and blend operations, thereby improving fill rate efficiency on the GPU. In , the depth test precedes the stencil test. The stencil buffer exhibits strong synergy with the depth buffer (Z-buffer), as stencil operations can be configured to depend on depth test outcomes, such as incrementing or decrementing stencil values only when the depth test passes or fails. This interdependence allows the stencil to conditionally enable or disable depth writes, facilitating complex visibility determinations. Furthermore, depth and stencil data are frequently packed into a single buffer format, like D24S8 (24 bits for depth and 8 bits for stencil), which optimizes usage by sharing the same per-pixel allocation rather than requiring separate buffers. Interaction with the color buffer occurs post-testing: fragments that pass both stencil and depth tests proceed to update the color buffer, while failures mask these writes, preventing unintended overwrites. This masking is essential for multi-pass techniques, where the stencil buffer protects specific screen regions during subsequent renders, ensuring precise control over final pixel colors without affecting non-target areas. In advanced rendering contexts, the stencil buffer enhances integration in deferred pipelines by flagging pixels with material IDs during the pass, enabling targeted shading in later passes to process only relevant G-buffer regions and reduce overdraw. Similarly, in forward rendering, it partitions by marking visibility zones, allowing efficient separation of elements for layered effects or optimizations.

Z-Fighting Mitigation

Z-fighting is a visual artifact in characterized by shimmering or flickering pixels, arising from insufficient sub-pixel precision in the depth buffer when rendering nearly coplanar polygons. This occurs because the depth values of the polygons are so close that rounding errors during depth testing cause alternating visibility between surfaces across frames, particularly noticeable on large, flat areas like or walls. The stencil buffer mitigates in such scenes by marking pixels covered by an occluding surface (e.g., a base or ), allowing subsequent coplanar (e.g., overlays or details) to render only in those regions without relying on the depth buffer, thus avoiding precision conflicts. This approach leverages the stencil buffer's per-pixel integer values to create a precise of covered areas, ensuring the secondary adheres exactly to the primary surface's contours, such as in application or multi-layered coplanar . The technique typically involves a two-pass rendering process. In the first pass, occluders are rendered with the depth test enabled to establish depth values, while the stencil buffer is configured to replace its value with 1 only for front-facing polygons passing the depth test, effectively marking the covered regions (e.g., set to 1). In the second pass, occludees are rendered with the depth test disabled and the stencil test set to draw only where the stencil value equals 1, ensuring they appear coplanar without artifacts. This method assumes consistent polygon winding order to correctly identify front-facing surfaces for stencil updates. Limitations include its inapplicability to transparent surfaces, where depth testing is necessary for proper alpha blending and , potentially introducing overdraw or incorrect . Additionally, the approach requires careful across passes and may increase usage due to multiple renders of the same .

Shadow Rendering Techniques

Shadow Volumes

Shadow volumes are a technique for generating real-time dynamic shadows in 3D rendering by extruding the silhouettes of occluder objects from a light source to form infinite pyramidal volumes that delineate shadowed regions. The stencil buffer is employed to perform a per-pixel point-in-volume test, marking pixels inside the volume as shadowed by incrementing or decrementing stencil values based on the winding order of the volume's faces relative to the viewer. The integration of shadow volumes with the stencil buffer was advanced by Mark Heidmann in 1991, who proposed rendering the front-facing caps of the to increment the stencil buffer where the depth test passes (Z-pass), followed by rendering the back-facing caps to decrement it, effectively counting the number of volume boundaries enclosing each . This approach enables efficient hardware-accelerated shadow computation by leveraging the stencil test to restrict subsequent scene rendering to lit areas only. Carmack's Reverse, introduced by for in 2004, is a Z-fail variant of the stencil shadow volume method that addresses artifacts from near-plane clipping by inverting the depth test behavior. In this two-pass technique, shadow volume front faces are rendered with stencil increment on depth fail, and back faces with decrement on depth fail; the final scene pass then renders only where the stencil value equals zero, indicating lit s outside the volume. The stencil value in Z-fail represents the net number of front-minus-back faces whose projections enclose the pixel, providing a robust count even when the viewpoint lies inside the shadow volume. Optimizations for shadow volume generation often employ trees to efficiently extract occluder silhouettes and construct volumes per light source, reducing geometry complexity in dynamic scenes. Hardware support for operations in GPUs, widely available since the early 2000s with architectures like and , has enabled real-time performance by accelerating the stencil updates and two-sided rendering.

Planar Shadows

Planar shadows are a rendering that projects the outline of occluding objects onto a flat receiver surface, such as the , using the light source as the center of , with the stencil buffer employed to confine the shadow to that surface and mitigate rendering artifacts. This approach is particularly suited for scenes where shadows fall onto planar geometry, enabling efficient computation without requiring complex volumetric structures. By transforming the occluder's vertices onto the plane via a specialized , the technique produces geometrically accurate shadows that align precisely with the light's perspective. The core method involves calculating a 4×4 shadow matrix based on the light position \mathbf{l} = (L_x, L_y, L_z, L_w) and the receiver equation \mathbf{p} \cdot \mathbf{X} = 0, where \mathbf{p} = (n_x, n_y, n_z, d) are the plane coefficients with \mathbf{n} = (n_x, n_y, n_z). Let \dotprod = \mathbf{p} \cdot \mathbf{l}. The matrix M has its fourth row as [0, 0, 0, 1]. For the first three rows (indices i = 0,1,2 for x, y, z), the elements are M_{ij} = \delta_{ij} \dotprod - l_i p_j for columns j = 0,1,2,3, where \delta_{ij} is the (l_w = 1 for point lights and 0 for directional lights). This implements a that maps 3D points to their projections on the plane. The resulting may extend infinitely for directional lights but is typically clipped to the view to bound computation. The plays a crucial role by first marking the receiver plane's pixels, ensuring the projected is drawn only within those bounds and avoiding depth conflicts with other . To implement planar shadows, the rendering pipeline follows these steps: clear the stencil buffer to 0 and render the scene normally, including the lit receiver plane while setting the stencil value to 1 for pixels where the depth test passes; then, for each occluder, compute the shadow matrix, multiply it with the current modelview matrix, and render the transformed geometry using alpha blending (e.g., source alpha and one-minus-source alpha) to darken the area, with the stencil test requiring equality to 1 and an operation to increment or replace the value to 2 upon passing, preventing subsequent projections from over-darkening the same pixel; finally, apply a small polygon offset to the shadow rendering to resolve z-fighting with the plane. This stencil masking restricts shadows to the receiver surface, handling cases where projections overlap or extend beyond the plane's visible area by leveraging frustum clipping. Compared to naive projective rendering without stenciling, this method offers key advantages, including the elimination of double blending artifacts—where multiple layers darken pixels excessively—through the stencil's one-time-write , and improved handling of self-ing by confining projections to the without interfering with the occluder's own depth-tested rendering. Additionally, by using the to the infinite or unbounded nature of projections (e.g., from point lights), it ensures remain clipped to the viewable receiver extent, reducing unnecessary fill rate and avoiding visual inconsistencies like "shadow swimming" from unmasked extensions during camera movement. These benefits make the performant on supporting operations, with minimal overhead when depth testing is enabled in 32-bit modes.

Spatial Shadows

Spatial shadows extend traditional shadow volume techniques to handle area or spatial light sources, producing soft-edged shadows with umbra and penumbra regions by scaling and extruding multiple silhouettes around the light source. This approach approximates the varying light blockage from extended light sources, where the penumbra represents partial occlusion transitioning from full shadow to illuminated areas. Originally inspired by hard shadow volumes, these methods modernize the extrusion process to generate wedge-shaped volumes that capture penumbral geometry without requiring full volumetric sampling. In stencil-based implementations, spatial shadows rely on multi-pass accumulation to build umbra and penumbra masks. Front-facing and back-facing wedges of the extruded volumes are rendered sequentially into the (or a dedicated buffer), incrementing or decrementing values to count traversals through the shadow . Overlap counts in the buffer then determine shadow during a final , where higher counts indicate deeper umbra and lower counts yield softer penumbral blending via alpha or additive operations. This enables percentage-closer-like filtering adapted for volumes, smoothing edges based on silhouette depth variations. Key techniques include extruded volumes, first conceptualized by in 1977 and modernized with penumbra for real-time approximation. Each silhouette edge generates a defined by four planes—two for the umbra boundary and two for the penumbra—rasterized efficiently to avoid overdraw in complex scenes. For efficiency in intricate environments, spatial data structures like hashing can accelerate silhouette extraction and , reducing the computational cost of volume construction. Modern adaptations integrate these stencil techniques with pipelines, where shadow volumes are rendered into the during geometry passes to mask light contributions from area sources. Layered stencil updates support multiple area lights by accumulating per-light masks in sequence, allowing blended occlusion without full scene re-rendering per source. This combination maintains real-time performance while providing physically plausible soft shadows in dynamic scenes.

Additional Rendering Applications

Reflections

The stencil buffer facilitates the rendering of realistic reflections on planar surfaces, such as mirrors or calm water, by precisely masking the reflected scene to the boundaries of the reflective polygon. This technique involves identifying the mirror polygon and rendering it into the stencil buffer, setting stencil values to 1 within its bounds while maintaining 0 elsewhere, which clips subsequent rendering to the mirror area. The scene geometry is then reflected across the mirror plane by applying a transformation matrix to the vertex coordinates, ensuring points on the plane remain fixed while others are mirrored symmetrically. This approach, introduced in early hardware-accelerated rendering pipelines, leverages the stencil test to avoid rendering reflections outside the designated surface. The process unfolds in a multi-pass rendering sequence to integrate reflections seamlessly into the scene. In the first pass, the opaque geometry of the scene is rendered with depth testing enabled, but the mirror polygon is drawn solely to the stencil buffer (with color and depth writes disabled) to establish the mask. The second pass renders the transformed reflected geometry only where the stencil value equals 1, typically with depth testing disabled to prevent conflicts with the original scene's depth buffer and avoid overwriting visible elements. A third pass then renders the mirror surface itself, blending it over the reflection using alpha transparency or depth testing to simulate the reflective material's properties. This method ensures the reflection appears confined and correctly positioned without artifacts from overdraw. Edge cases in reflection rendering are managed through targeted optimizations and constraints inherent to the stencil buffer. For the reflection view, portal-like culling is applied to the reflected , excluding outside the mirror's visible bounds to reduce computational overhead and prevent unnecessary rendering of distant or occluded objects. Recursive reflections, where a reflected scene includes further mirrors, extend the technique by iteratively applying the stencil mask and transformations; however, this is limited primarily by performance degradation from excessive pass counts, typically to a small number of levels (e.g., 3 to 5 in practice). To mitigate costs, implementations often cap depth or use simplified for deeper levels. While environment mapping with cube maps offers efficient approximations for dynamic or curved reflections by precomputing or updating a 360-degree texture, the stencil buffer enables precise, geometry-based planar reflections that accurately duplicate the scene without approximation errors. This exactness comes at the cost of additional geometry passes but provides superior fidelity for flat, local reflectors in real-time applications.

Decals and Compositing

The stencil buffer plays a crucial role in decal projection by masking rendering to specific surface intersections, preventing artifacts like z-fighting when overlaying textures onto base geometry. In this technique, a depth-prepass renders the base surface while writing a unique stencil value to affected pixels, ensuring subsequent decal geometry—such as bullet holes or graffiti projected onto walls—only updates pixels where the stencil matches the predefined value. This approach disables depth testing during decal rendering to allow precise blending without interference from the base's depth values. For , the stencil buffer enables layered effects by marking targeted areas for multi-pass blending, such as applying blood splatter or environmental decals to dynamic hit locations in without affecting surrounding . A common involves an initial pass to set stencil values for intersection regions via ray-casting or , followed by restricted rendering passes that blend the effect only where the stencil test passes, using operations like stencil replace or increment to handle multiple layers. This method supports dynamic markings, like vehicle damage in simulations, by isolating updates to precise regions. Advanced techniques leverage the stencil buffer in screen-space decals, where projected textures are applied post-deferred shading; a stencil mask derived from depth bounds rejects fragments outside surface intersections, ensuring decals conform to without additional geometry submission. In real-time (CSG)-like operations, the stencil buffer facilitates unions by tracking per —toggling bits to count intersecting and rendering only visible results after evaluation—enabling efficient blending of overlaid volumes like modular or destructible environments. Performance benefits arise from early stencil rejection, which culls overdraw in multi-pass rendering; for instance, masking dynamic objects in screen-space s avoids unnecessary fragment , maintaining frame rates above 30 in complex scenes with heavy decal usage, as demonstrated in production rendering pipelines. This rejection occurs at the level before , reducing computational load compared to unmasked blending approaches.

Portal and Occlusion Culling

The technique in rendering leverages the to enable efficient of interconnected scenes divided into cells, such as indoor environments. polygons are defined as planar boundaries connecting adjacent cells in a spatial partitioning structure like a (BSP) tree, allowing visibility determination between regions. To render through a , the polygon is first rasterized into the with a specific value (e.g., 1), enabling a that restricts subsequent drawing operations to the portal's projected screen area via the . This masking prevents from outside the portal from appearing incorrectly, while discards non-visible surfaces during traversal of connected cells. The process repeats depth-first for nested portals, incrementing or tracking values to manage levels and avoid infinite loops. In occlusion culling, the stencil buffer facilitates hardware-accelerated determination of hidden by counting visible of potential occludees against pre-rendered occluders. Occluders—typically large, conservative bounding volumes or silhouettes—are rendered first with depth testing enabled but color writes disabled, incrementing the stencil buffer value for each passing to quantify screen coverage. For candidate occludees, a low-polygon (e.g., bounding ) is then rendered similarly, and an occlusion query retrieves the count that survives both depth and stencil tests; if this count falls below a (often 0 or a small fraction of screen ), the full is culled to skip unnecessary draw calls. This image-space approach provides conservative but fast culling, integrating hierarchical depth buffers (hi-Z) for early rejection and precise clipping. Such stencil-based methods integrate seamlessly with tree partitioning, as pioneered in games like , where portals define cell connectivity for initial culling, and the stencil buffer refines per-pixel visibility in hardware rendering passes. This combination optimizes large, complex indoor scenes by minimizing overdraw and vertex processing, potentially reducing draw calls by orders of magnitude in visibility-limited environments. Modern GPUs enhance these techniques through extensions for conditional rendering tied to queries, allowing dynamic skipping of occluded subtrees without CPU intervention.

API Implementations

OpenGL

In , the stencil buffer is controlled through a set of functions in the fixed-function pipeline, enabling per-fragment testing and updates during rasterization. The stencil test is activated by calling glEnable(GL_STENCIL_TEST), which applies the test to incoming fragments before they affect the . Once enabled, the comparison function, reference value, and are specified using glStencilFunc(func, ref, mask), where func determines the test (e.g., GL_ALWAYS, GL_EQUAL), ref is the reference value clamped to the stencil buffer's , and mask bitwise-ANDs with both the reference and the fragment's stencil value for comparison. The outcomes of the stencil test—stencil fail, depth fail (if depth testing is enabled), and depth pass—are handled by glStencilOp(sfail, dpfail, dpass), which specify operations like GL_KEEP, GL_INCR, GL_DECR, or GL_ZERO to update the stencil buffer. Additionally, glStencilMask(mask) controls which bits of the stencil buffer can be written, with the mask applying to both front- and back-facing primitives unless specified otherwise. To support two-sided rendering, such as in shadow volumes where front and back faces require different stencil operations, provides separate control for front- and back-facing polygons via the glStencilFuncSeparate(face, func, ref, mask) and glStencilOpSeparate(face, sfail, dpfail, dpass) functions, along with glStencilMaskSeparate(face, mask). These were introduced as the EXT extension in (building on earlier vendor extensions like ATI_separate_stencil) and incorporated into the core specification. The face parameter accepts GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK to target specific winding directions, allowing asymmetric stencil behavior without state changes between draw calls. In modern OpenGL versions (3.3 and later), the stencil buffer functionality is retained primarily in the compatibility profile to support legacy fixed-function pipelines, while the core profile emphasizes programmable shaders but still includes the stencil test as part of the fragment processing pipeline. Direct interaction with the stencil buffer from shaders is limited and typically requires extensions; for instance, the rare ARB_shader_stencil_export extension (approved 2010) allows fragment shaders to export a per-fragment stencil reference value via the gl_FragStencilRefARB output variable, influencing the test or write operations without reading the buffer contents. Reading the stencil buffer in shaders is not natively supported and generally requires off-line queries like glReadPixels. The following example demonstrates enabling the stencil test and configuring it to increment the stencil value on depth pass for front faces (common in shadow volume extrusion), using separate functions for clarity:
c
glEnable(GL_STENCIL_TEST);  // Enable stencil testing[](https://registry.khronos.org/OpenGL-Refpages/gl4/html/glEnable.xhtml)
glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 0xFF);  // Always pass for front faces, full mask[](https://registry.khronos.org/OpenGL-Refpages/gl4/html/glStencilFuncSeparate.xhtml)
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR);  // Increment on depth pass for front[](https://registry.khronos.org/OpenGL-Refpages/gl4/html/glStencilOpSeparate.xhtml)
glStencilMask(0xFF);  // Allow writes to all bits[](https://registry.khronos.org/OpenGL-Refpages/gl4/html/glStencilMask.xhtml)
This setup ensures fragments from front-facing geometry update the stencil only upon passing the depth test, facilitating techniques like occlusion culling.

Direct3D, Vulkan, and Metal

In 9 and subsequent versions, stencil buffer functionality is managed through render states, including D3DRS_STENCILENABLE to activate stenciling (set to TRUE or FALSE, default FALSE), D3DRS_STENCILFUNC to define the comparison function (e.g., D3DCMP_LESS for less-than tests), and D3DRS_STENCILOP to specify operations on stencil values (e.g., D3DSTENCILOP_INCR for increment). These states allow pixel-level masking during rendering, enabling techniques like shadow volumes by conditionally writing to the buffer based on test outcomes. Starting with 11, enhanced control is provided through shader semantics, where pixel shaders can output the stencil reference value using SV_StencilRef, allowing dynamic per-pixel adjustments rather than relying solely on API-set constants; this feature, introduced in 11.3, supports more granular stencil operations in complex scenes. In 12, stencil configuration is encapsulated in pipeline state objects (PSOs) via the D3D12_DEPTH_STENCIL_DESC structure, which defines depth and stencil tests, operations, and masks; dynamic aspects, such as the stencil reference value, can be updated per draw call using root signatures to bind constants or descriptors, promoting efficient state management in low-level programming models. Vulkan exposes stencil buffer support through the VkPipelineDepthStencilStateCreateInfo structure in graphics pipeline creation, featuring VkStencilOpState substructures for front and back faces that specify test enables, comparison functions (e.g., VK_COMPARE_OP_LESS), and operations (e.g., VK_STENCIL_OP_INCREMENT_AND_CLAMP); this allows separate handling of face orientations for culling and masking. Stencil attachments are integrated into render passes via VkAttachmentDescription, using formats like VK_FORMAT_D24_UNORM_S8_UINT for combined 24-bit depth and 8-bit stencil storage, with explicit memory allocation and binding required for buffers. Metal configures the stencil buffer using MTLDepthStencilDescriptor, which includes stencilFront and stencilBack properties as MTLStencilDescriptor instances; these define comparison functions such as .less (MTLCompareFunctionLess, passing if the reference is less than the stencil value) and operations like .incrementClamp (MTLStencilOperationIncrementClamp, incrementing the value up to the maximum of 255). The API's tile-based deferred rendering architecture leverages stencil tests early in the —often before fragment —to discard tiles efficiently, reducing and compute overhead in mobile and embedded scenarios. Since 2010, cross-API developments in Direct3D, Vulkan, and Metal have emphasized explicit control and performance, with features like shader-outputtable stencil references (e.g., SV_StencilRef in Direct3D 11.3) enabling programmable refinements beyond fixed-function limits. Optimizations for mobile and virtual reality workloads, such as Metal's tile-based integration, prioritize early rejection to conserve power, while stencil buffers increasingly interface with compute shaders for hybrid rendering pipelines, though core mechanisms have seen no fundamental redesigns through 2025.

References

  1. [1]
    DirectX Frequently Asked Questions - Win32 apps | Microsoft Learn
    A stencil buffer is an additional buffer of per-pixel information, much like a z-buffer. In fact, it resides in some of the bits of a z-buffer. Common stencil/z ...
  2. [2]
    [PDF] The OpenGL Graphics System: A Specification - Khronos Registry
    ... Buffer ... This means familiarity with the es- sentials of computer graphics algorithms as well as familiarity with basic graphics hardware and associated terms.
  3. [3]
    Stencil buffers - UWP applications | Microsoft Learn
    Oct 20, 2022 · A stencil buffer is used to mask pixels in an image, to produce special effects. The mask controls whether the pixel is drawn or not.
  4. [4]
    D3D12_DEPTH_STENCIL_DESC (d3d12.h) - Win32 apps
    Jul 26, 2022 · A D3D12_DEPTH_WRITE_MASK-typed value that identifies a portion of the depth-stencil buffer that can be modified by depth data. DepthFunc. A ...
  5. [5]
    Chapter 9. Efficient Shadow Volume Rendering - NVIDIA Developer
    This chapter describes how to use shadow volumes, the shadowing method used in games such as id Software's Doom 3, to mark shadowed pixels in the stencil buffer ...
  6. [6]
    DXGI_FORMAT (dxgiformat.h) - Win32 apps | Microsoft Learn
    Jan 15, 2025 · A 32-bit z-buffer format that supports 24 bits for depth and 8 bits for stencil. ... Direct3D 10 offers new data compression formats for ...
  7. [7]
    glStencilOp - OpenGL 4 Reference Pages - Khronos Registry
    Stenciling, like depth-buffering, enables and disables drawing on a per-pixel basis. You draw into the stencil planes using GL drawing primitives, then render ...
  8. [8]
    [PDF] Advanced Graphics Programming Techniques Using OpenGL | CGVR
    Aug 9, 1999 · Mark J. Kilgard is a Graphics Software Engineer at NVIDIA Corporation where he works on upcoming RIVA graphics processors. Mark authored the ...
  9. [9]
    GL_OES_packed_depth_stencil - Khronos Registry
    Many OpenGL implementations have chosen to interleave the depth and stencil buffers into one buffer, often with 24 bits of depth precision and 8 bits of stencil ...
  10. [10]
    An interview with Kurt Akeley
    Dec 28, 2009 · The stencil buffer implemented a very simple state-machine, but provided a lot of useful capabilities in the end. One of its useful applications ...
  11. [11]
    History of nVIDIA Graphics cards Vol. 1 - 硬件风云
    At the same time, Riva TNT also has a 24-bit Z buffer (Z-Buffer) and an 8-bit stencil buffer for the first time. TNT's design goal was to achieve twice the ...
  12. [12]
    A trip through the Graphics Pipeline 2011, part 7 | The ryg blog
    Jul 8, 2011 · all benefit from the early rejection we do; but even Z-rejected pixels do a Z-buffer read first (unless they were killed by hierarchical Z).
  13. [13]
    Fragment Performance - NVIDIA Docs
    Stencil-killed fragments are generally the fastest rejection cases possible, as they are 8-bit, rather than 16-bit surfaces. Stencil killing for depth ...
  14. [14]
    Stencil Test - OpenGL Wiki
    Apr 20, 2023 · The Stencil Test is a per-sample operation performed after the Fragment Shader. The fragment's stencil value is tested against the value in ...
  15. [15]
    glStencilFunc - OpenGL 4 Reference Pages - Khronos Registry
    The stencil test conditionally eliminates a pixel based on the outcome of a comparison between the reference value and the value in the stencil buffer. To ...
  16. [16]
    glStencilMask - OpenGL 4 Reference Pages
    ### Summary of Stencil Write Mask and Read Mask from glStencilMask and glStencilFunc
  17. [17]
    Output-Merger Stage - Win32 apps | Microsoft Learn
    May 23, 2021 · ... depth buffer bound, then the stencil test always passes. Otherwise ... stencil buffer, and depth-stencil state for the output-merger stage.
  18. [18]
    Configuring Depth-Stencil Functionality - Win32 apps | Microsoft Learn
    Aug 18, 2020 · This section covers the steps for setting up the depth-stencil buffer, and depth-stencil state for the output-merger stage.
  19. [19]
    Understanding Render Passes - Arm Developer
    If you only need a stencil buffer, allocate a stencil-only format such as S8 , and never attach a depth attachment. If you use a packed depth-stencil ...Missing: Z- | Show results with:Z-
  20. [20]
    Depth and stencil buffers - UWP applications | Microsoft Learn
    Oct 20, 2022 · A depth buffer controls which polygons are rendered, while a stencil buffer masks pixels for special effects like compositing and outlines.
  21. [21]
    Rendering a scene with deferred lighting in Objective-C
    This sample demonstrates a deferred lighting renderer that implements shadows using a shadow map, and culls light volumes using the stencil buffer.
  22. [22]
    Chapter 9. Deferred Shading in S.T.A.L.K.E.R. | NVIDIA Developer
    In S.T.A.L.K.E.R., we stored material and object IDs in the spare components and defined functions in each light shader (accelerated using 2D and 3D texture ...
  23. [23]
    3.5 Coplanar Polygons and Decaling with Stencil
    Values are written to the stencil buffer to create a mask for area to be decaled. ... Z fighting'' or ``flimmering''). An example is shown in in Figure 12 ...
  24. [24]
    None
    ### Summary: Decaling with Stencil Buffer to Avoid Z-Fighting for Coplanar Polygons
  25. [25]
    Shadow algorithms for computer graphics - ACM Digital Library
    A classification of shadow algorithms delineates three approaches: shadow computation during scanout; division of object surfaces into shadowed and unshadowed ...
  26. [26]
    [PDF] Practical and Robust Stenciled Shadow Volumes for Hardware ...
    Mar 12, 2002 · [14] Tim Heidmann, “Real Shadows Real Time”, IRIS Universe, Number. 18, 1991, pp. 28-31. [15] Mark Kilgard, “Improving Shadows and ...
  27. [27]
    [PDF] Fast, Practical and Robust Shadows - People | MIT CSAIL
    Nov 6, 2003 · Heidmann [HEID91] adapted Crow's algorithm to hardware acceleration by using the stencil buffer to compute the per-pixel count for the point-in- ...
  28. [28]
    Chapter 11. Efficient and Robust Shadow Volumes Using ...
    As a result of this pass, the stencil buffer will contain the intersection counter value for each pixel (which is zero for all nonshadowed pixels).Chapter 11. Efficient And... · 11.2 An Overview Of Shadow... · 11.3 Our ImplementationMissing: definition | Show results with:definition
  29. [29]
    John Carmack on shadow volumes - Fabien Sanglard
    I first drew the shadow volumes with depth test disabled, incrementing for back sides and decrementing for front sides. This finishes with a positive value in ...Missing: reverse | Show results with:reverse
  30. [30]
    OpenGL Shadow Volumes: Z-Pass and Z-Fail - Paul's Projects
    Draw shadow volumes into stencil buffer. By default the shadow volumes use the "zFail" technique, with an infinite far clip plane, as described in the ...
  31. [31]
    Shadow volume BSP trees for computation of shadows in dynamic ...
    This paper presents an algorithm for shadow calculation in dynamic polyhedral scenes illuminated by point light sources. It is based on a modification of ...
  32. [32]
    [PDF] Shadows
    Solution: Clear stencil to zero. Draw floor with stencil of one. Draw shadow if stencil is one. If shadow's stencil test passes, set stencil to two.
  33. [33]
    [PDF] Creating Reflections and Shadows Using Stencil Buffers
    stencil to avoid double blending. depth buffer Z fighting artifacts. Shadow fights with depth values from the floor plane. Use polygon offset to raise shadow.
  34. [34]
    Planar Reflections and Shadows using the Stencil Buffer in SlimDX ...
    Aug 11, 2013 · We also add a tiny offset translation, so that the shadow appears on top of the surface it is shadowing, and so hopefully avoid z-fighting. Then ...<|separator|>
  35. [35]
    [PDF] Approximate Soft Shadows on Arbitrary Surfaces using Penumbra ...
    In 1977, Crow presented an algorithm for generating hard shadows.1 By using a stencil buffer, an implementation is possible that uses commodity graphics ...
  36. [36]
    [PDF] Advanced Stencil Shadow and Penumbral Wedge Rendering
    Soft Shadow Correction. • Lighting pass for ordinary stencil shadows uses stencil test. – 0 in stencil buffer at a particular pixel means light can reach that ...
  37. [37]
    Advances in Spatial Hashing: A Pragmatic Approach towards ...
    Jul 24, 2022 · Spatial hashing is a battle-tested technique for efficiently storing sparse spatial data. Originally designed to optimize secondary light ...
  38. [38]
    Chapter 17. Efficient Soft-Edged Shadows Using Pixel Shader ...
    This problem is commonly called "shadow acne" and appears as shadow "leakage" on the lit side of the object, similar to z-fighting. ... "Stochastic Sampling in ...
  39. [39]
    #AltDevBlog » Stencil Buffer Optimisation for Deferred Lights
    I'm going to describe a common technique which uses the stencil buffer for accelerating the rendering of deferred lights.<|control11|><|separator|>
  40. [40]
    14.2 Decaling with Stencil
    The stencil buffer becomes a mask, ensuring that the decal polygon can only affect the pixels that were touched by the base polygon. This is important if there ...
  41. [41]
    Stencil Buffer Techniques (Direct3D 9) - Win32 apps | Microsoft Learn
    Jan 6, 2021 · The stencil buffer enables or disables drawing to the rendering target surface on a pixel-by-pixel basis. At its most fundamental level, it ...<|control11|><|separator|>
  42. [42]
    [PDF] Screen Space Decals - GameDevs.org
    • So we simply didn't draw any decals on dynamic objects. • Used a simple stencil buffer technique. Page 58. Edit this text to create a Heading. ▫ This ...
  43. [43]
    None
    ### Summary: Use of Stencil Buffer in OpenCSG for Real-Time Rendering of Boolean Operations (Unions)
  44. [44]
    [PDF] A Survey of Visibility for Walkthrough Applications - cs.Princeton
    The stencil buffer is composed of a small set of bits (usually more than 4) ... occlusion culling. The technique in. [18] is most suitable for use in the ...
  45. [45]
    That's a wrap: Manifold Garden rendering retrospective
    When each portal renders, we use the stencil buffer to determine the portal visibility. For each portal we stamp a part of the screen with its portal ID.
  46. [46]
    [PDF] Image Space Occlusion Culling
    Image Space Occlusion Culling. 2. Hudson et al, SoCG 97. C. B. A. Viewpoint ... and check the stencil buffer to see if at all visible. • Requires a lot of ...
  47. [47]
    Chapter 29. Efficient Occlusion Culling - NVIDIA Developer
    Disable rendering to screen (set the color mask of all channels to False). Disable writing to depth buffer (just test against, but don't update, the depth ...
  48. [48]
    glEnable - OpenGL 4 Reference Pages - Khronos Registry
    See glScissor. GL_STENCIL_TEST. If enabled, do stencil testing and update the stencil buffer. See glStencilFunc and glStencilOp. GL_TEXTURE_CUBE_MAP_SEAMLESS.
  49. [49]
    glStencilFuncSeparate - OpenGL 4 Reference Pages
    Stenciling, like depth-buffering, enables and disables drawing on a per-pixel basis. You draw into the stencil planes using GL drawing primitives, then render ...
  50. [50]
    glStencilOpSeparate - OpenGL 4 Reference Pages
    To enable and disable the test, call glEnable and glDisable with argument GL_STENCIL_TEST ; to control it, call glStencilFunc or glStencilFuncSeparate.
  51. [51]
    EXT_stencil_two_side - Khronos Registry
    OpenGL 2.0 separate stencil functions set the front and "OpenGL 2.0" back state. Non-separate stencil functions use the stencil face selector to determine what ...
  52. [52]
    [PDF] OpenGL 4.6 (Core Profile) - May 5, 2022 - Khronos Registry
    May 1, 2025 · This subsection is only defined in the compatibility profile. 1.1.2. This subsection is only defined in the compatibility profile. 1. Page 24 ...
  53. [53]
    ARB_shader_stencil_export - Khronos Registry
    This extension provides a mechanism whereby a shader may generate the stencil reference value per invocation. When stencil testing is enabled, this allows the ...
  54. [54]
    D3DRENDERSTATETYPE enumeration (D3D9Types.h) - Win32 apps
    May 24, 2021 · For more information, see Vertex Fog (Direct3D 9). D3DRS_STENCILENABLE. TRUE to enable stenciling, or FALSE to disable stenciling. The default ...
  55. [55]
    Shader Specified Stencil Reference Value (Direct3D 11 Graphics)
    Jun 18, 2021 · This D3D11.3 feature enables developers to read and use the Stencil Reference Value ( SV_StencilRef ) that is output from a pixel shader.
  56. [56]
    Semantics - Win32 apps - Microsoft Learn
    Aug 20, 2021 · System-Value Semantics ; SV_StencilRef, Represents the current pixel shader stencil reference value. Can be written by the pixel shader only.
  57. [57]
    Core structures (Direct3D 12 Graphics) - Win32 apps - Microsoft Learn
    Nov 3, 2022 · Describes depth-stencil state. D3D12_DEPTH_STENCIL_DESC1. Describes ... Describes constants inline in the root signature that appear in shaders as ...
  58. [58]
    Managing Graphics Pipeline State in Direct3D 12 - Win32 apps
    Dec 30, 2021 · In Microsoft Direct3D 12, most graphics pipeline state is set by using pipeline state objects (PSO). An app can create an unlimited number of these objects.
  59. [59]
  60. [60]
    MTLStencilDescriptor | Apple Developer Documentation
    ### Summary of MTLStencilDescriptor