Mapping PBR to Modern DirectX Shader Pipelines
Physically based rendering (PBR) relies on real-world optical physics to calculate how light interacts with surfaces, primarily through microfacet theory and energy conservation. In modern real-time rendering, mapping these mathematical models to modern DirectX (DirectX 12 and High-Level Shader Language Shader Model 6+) requires a structured division of labor across descriptor bindings, vertex processing, pixel shading, compute-based image-based lighting (IBL), and hardware-accelerated ray tracing (DXR). This article outlines how PBR equations and texture data directly map to the stages and features of contemporary DirectX shader pipelines.
Texture Packing and Root Signature Setup
The standard metallic-roughness PBR workflow relies on a set of material parameters that must be exposed to the pipeline. DirectX 12 utilizes root signatures and descriptor tables to bind these resources efficiently with minimal CPU overhead.
Typically, material textures are packed into channel-efficient combinations:
- Base Color / Albedo: RGB (sRGB format, sampled as linear in shaders) with an optional Alpha channel for opacity.
- Normal Map: Two- or three-channel tangent-space normals (often BC5 or BC7 compressed).
- Roughness-Metallic-Occlusion (RMO): A single composite texture packing Ambient Occlusion in the Red channel, Roughness in the Green channel, and Metallic in the Blue channel to conserve texture samplers and memory bandwidth.
These textures, along with constant buffers containing light transforms, intensities, and camera positions, are bound to the pipeline via the Root Signature as Shader Resource Views (SRVs) and Constant Buffer Views (CBVs).
The Vertex Shader Stage
The vertex shader prepares spatial data for the microfacet calculations executed later in the pipeline. Its primary duties for PBR include:
- Transforming local vertex positions to clip space for rasterization, and world space for lighting vectors.
- Transforming and passing surface normal vectors, tangents, and bitangents (or signs) to the pixel shader to construct the Tangent-Bitangent-Normal (TBN) matrix.
- Passing UV coordinates for material map sampling.
Shader Model 6 allows the efficient transmission of these interpolated attributes via user-defined output structures.
The Pixel Shader: Evaluating the BRDF
The pixel shader executes the Bidirectional Reflectance Distribution Function (BRDF). The standard formulation is the Cook-Torrance microfacet specular shading model combined with a Lambertian diffuse model:
\[f(l, v) = k_d f_{\text{lambert}} + k_s f_{\text{cook-torrance}}\]
In the pixel shader, the implementation unfolds in several discrete steps:
- Vector Construction: The shader reconstructs the normal using the sampled normal map and the TBN matrix. It computes the normalized view vector (\(V\)), light direction vector (\(L\)), and halfway vector (\(H = \frac{V + L}{\|V + L\|}\)).
- Fresnel Term (\(F\)): Computed using the Schlick approximation. For dielectrics, base reflectivity (\(F_0\)) is typically clamped around 0.04, while for metals, \(F_0\) is derived directly from the albedo texture based on the metallic map.
- Normal Distribution Function (\(D\)): Evaluated using the Trowbridge-Reitz GGX distribution to model microfacet alignment relative to \(H\) based on the surface roughness value.
- Geometric Shadowing (\(G\)): Calculated using the Smith model with the Schlick-GGX formulation, accounting for microfacet self-shadowing and masking based on both the view and light angles.
- Direct Light Accumulation: The specular Cook-Torrance term \(\frac{D \cdot F \cdot G}{4(\mathbf{N} \cdot \mathbf{V})(\mathbf{N} \cdot \mathbf{L})}\) is combined with the diffuse component \((1 - F) \frac{\text{Albedo}}{\pi}\) and modulated by the light's irradiance and incoming angle (\(\mathbf{N} \cdot \mathbf{L}\)).
HLSL intrinsic functions like dot,
saturate, and fast vector arithmetic execute these
calculations with low latency on modern GPU compute units.
Compute Shaders and Image-Based Lighting (IBL)
To account for indirect, ambient light without full path tracing, modern pipelines utilize the split-sum approximation for Image-Based Lighting. Compute shaders are used offline or during scene initialization to pre-integrate environment maps:
- Diffuse Irradiance: A compute shader convolves an environment cubemap to capture low-frequency irradiance. The pixel shader samples this cubemap using the surface normal.
- Specular Pre-Filtered Environment Map: Compute shaders generate a mipmapped cubemap where each mip level corresponds to a specific roughness level convolved with the GGX distribution.
- BRDF Integration LUT: A 2D lookup texture pre-integrates the Fresnel response and geometric shadowing across varying roughness and incidence angles. The pixel shader samples this LUT using \(\mathbf{N} \cdot \mathbf{V}\) and roughness.
During the forward or deferred pixel shading pass, indirect diffuse and specular components are resolved by combining these lookups with the material's AO, metallic, and roughness values.
Integration with DirectX Raytracing (DXR)
In DirectX 12 pipelines utilizing DXR, PBR functions migrate into hit
shaders (ClosestHitShader) or callable shaders.
Instead of relying solely on rasterized shadow maps and pre-filtered
cubemaps, ray generation shaders cast shadow and reflection rays into
the Top-Level Acceleration Structure (TLAS). When a surface is
intersected, the ClosestHitShader samples the same PBR
textures and evaluates the Cook-Torrance BRDF to determine the material
response to traced light paths, producing physically accurate ambient
occlusion, multi-bounce reflections, and area-light penumbras.