Skip to content
Vilanel

Rendering and lighting

Vilanel's renderer uses forward shading, bindless resources and GPU-driven culling. Lighting uses real-world units, and rendering is tested with measurements and reference images.

How a frame is rendered

  • Depth prepass and clustered forward shading. Lights are sorted into a 3D grid over the view, so each pixel only processes the lights near it. Forward shading also makes transparency and anti-aliasing simpler than a deferred renderer would.
  • Reverse-Z floating-point depth, which keeps depth precision high at long distances.
  • GPU-driven culling. Visibility, level of detail and skinning are handled on the GPU. The camera also uses occlusion culling based on the previous frame's depth, and each shadow is culled against its own view.
  • Temporal anti-aliasing, with motion vectors that include skeletal animation so moving limbs do not smear.

Data shared by every camera, such as the sky, sky lighting and reflections, is computed once per frame. Data that belongs to one camera, such as culling, lights, shadows and history, is kept separately, so a second camera can render the same world in the same frame. Extra cameras are currently limited to previews, minimaps and probes.

Real-world light units

Unit
The sunLux (128,000 above the atmosphere)
Point and spot lightsCandela
ExposureEV100, in photographic stops
Pixel brightness readoutCandela per square metre

Real units make lighting predictable and measurable. After tonemapping, a surface that is far too bright can still look normal on screen, so the engine can report the physical brightness of any pixel to check it.

Exposure is based on how much light reaches the ground, so it adapts correctly at sunset. Automatic exposure is also available, but it is off by default so it does not override a level's intended look.

The sky

The atmosphere is recalculated every frame, so the sun can move freely. It is tested against a path-traced reference, and its settings are not tuned to match that reference, so the comparison stays meaningful.

Clouds are rendered as a 3D volume. They cast shadows on the ground and into fog, add light to the scene and appear in reflections. A level describes its weather as a schedule of presets, and the sky blends smoothly between them. A single wind moves both the clouds and the fog.

At night the sky shows real stars, a moon with phases that casts shadows, and a blue shift that mimics how our eyes adapt to the dark.

A level can also use a photographed HDR sky instead. Its brightness is set in real-world units, so it stays consistent with the rest of the lighting.

Testing

The runtime has options designed for testing:

OptionWhat it does
--screenshotRender with a fixed clock, save a frame and exit
--compareCompare the frame with a stored reference image
--cameraSet an exact camera position and angle
--radiancePrint a pixel's brightness in real-world units
--time, --weatherSet the time of day and the weather
--gpu-timings, --cpu-timingsShow where frame time is spent on the GPU and CPU

Reference images of the sample level are captured from fixed cameras, including one taken on the second frame to catch problems that only appear while the scene is loading. Two automated sweeps compare sky measurements across a whole day against stored values.

Related