CPU side

Since Steel Nomad Light does not have a CPU test, the main role of the CPU in the test is to compose command lists for the GPU to execute. The task system allows heavy parallel execution. The rendering — including scene update, visibility evaluation and command list building—is done with multiple CPU threads using one thread per available logical CPU core. This shortens the CPU rendering time and reduces the chance of the CPU becoming a bottleneck.

Multi sub-pass rendering

When available, multi sub-pass rendering or an equivalent API technology is used for the G-buffer, decals, illumination and transparency rendering steps. This is used in Steel Nomad Light when using the Vulkan, Metal, and DirectX 12 graphics APIs and is supported by the GPU.

Geometry Rendering

Opaque objects are rendered using a deferred rendering method in the graphics pipeline using temporary G-buffer targets for PBR material parameters. The shading is done in linear HDR color space utilizing temporary G-buffer data and scene lights information. In addition to the final lighting result, some data from the G-buffer is saved for use in future shading passes.

Transparent objects are rendered in an order-independent way using two passes. The first pass uses temporary targets to store accumulated color contribution and transparency weighted based on linear depth and the total transparency. The second pass calculates the final color from the accumulated color and transparency. The result of the transparent objects pass is blended on top of the final surface illumination.


Decals are rendered right after G-buffer rendering. Decals modify the G-buffer and add further details to geometry surfaces.

Surface Illumination

Specular reflections and diffuse global illumination use data sampled from multiple probes distributed around the benchmark scene.


Particles are simulated on the GPU using compute shaders. The particles are rendered at the same time with transparent geometries using the same order-independent technique. The particles are illuminated by directional light.

Grass rendering

Blades of grass are distributed with their level of detail, size and density set based on distance from camera. This is done in computer shaders, then rendered to the G-buffer.

Asynchronous compute

Steel Nomad Light does not use asynchronous compute. For details on Steel Nomad's implementation, please refer to the Steel Nomad user guide.

Volumetric clouds

The sky is drawn in a compute shader using ray-march volumetric cloud rendering. The sky is dynamic, with clouds moving throughout the timeline.

Screen-space shadows

Screen-space shadows are used to calculate contact shadows.

Screen-space reflections

Screen-space reflections are used to calculate reflections of pixels rendered on screen. A cube map fallback is used for reflections of surfaces outside of screen-space.


Heat Distortion

The heat distortion effect is generated with the use of particles. For particles that generate the effect, a distortion field is rendered to a texture using a 3D noise texture as input. This field is then used to distort the input image in the post-processing phase.


Bloom is based on a compute shader FFT that evaluates several effects with one filter kernel. The effects are blur, streaks, anamorphic flare and lenticular halo. Bloom is computed in reduced resolution to make it faster.

Volume illumination

Steel Nomad Light does not feature volume illumination. For details on Steel Nomad's Volume Illumination implementation, please refer to the Steel Nomad user guide.

Depth of Field

Depth of Field uses a Scatter-as-Gather approach. Background and foreground are calculated in separate passes and combined in a final pass.

Steel Nomad uses XeGTAO for ambient occlusion. In Steel Nomad, the ultra quality setting is used and XeGTAO is rendered in compute shaders. Steel Nomad Light uses the high quality setting and renders XeGTAO in pixel shaders.

You can read more about this technique at its GitHub page.


Motion vectors are computed in a fragment shader during G-buffer rendering. Two history textures are used to store data from previous frames, depth and illumination, and an exponential moving average with variance clipping is used to blend the data of the current frame. Depth texture is linearized in a separate pass for the blending to work correctly. Motion vectors from the current frame are used as an offset for sampling the history textures in the resolve pass.