Skip to content

HDR Sky DomeΒΆ

RayON supports two sky models: a built-in procedural gradient (zero setup required) and a full HDR environment map loaded from an .hdr file and projected as an equirectangular sky dome.


Built-in gradient skyΒΆ

When no YAML sky key is specified, the renderer uses a simple linear gradient between a horizon colour and a zenith colour:

settings:
  background_color: [0.05, 0.05, 0.08]  # overrides gradient with a solid colour

Omit background_color entirely to get the default blue-to-white gradient. This sky model requires no image files and renders at zero memory cost.


HDR environment sky domeΒΆ

An equirectangular .hdr file (Radiance RGBE format) is mapped onto an infinite sphere around the scene. Any ray that misses all geometry samples the sky dome at the corresponding direction.

settings:
  hdr_sky: "../resources/hdri/venice_sunset_8k.hdr"

The mapping is derived from the ray's unit direction vector:

\[\theta = \arccos(d_y), \quad \phi = \text{atan2}(-d_z,\; d_x)$$ $$u = \frac{\phi + \pi}{2\pi}, \quad v = \frac{\theta}{\pi}\]

The resulting $ (u, v) \in [0,1]^2 $ coordinates index into the equirectangular texture, with \(v = 0\) at the north pole and \(v = 1\) at the south pole.

Switching sky in interactive modeΒΆ

In interactive mode the sky can be cycled at runtime without restarting:

Input Effect
Numpad + or = Next HDRI in directory
Numpad βˆ’ or βˆ’ Previous HDRI in directory

A Sky combo-box in the Environment section of the ImGui panel also lets you pick any loaded .hdr file by name.


Downloading the HDRI filesΒΆ

The bundled HDRIs are sourced from Poly Haven under the CC0 licence. Because each file is 25–250 MB, they are not included in the repository. A download script is provided:

# Download 8K HDRIs (recommended quality)
cd resources/hdri
bash download_hdri.sh 8k

# Or lower resolutions
bash download_hdri.sh 2k
bash download_hdri.sh 4k

The six bundled environments:

Environment Source
venice_sunset polyhaven.com/a/venice_sunset
kloppenheim_06 polyhaven.com/a/kloppenheim_06
autumn_crossing polyhaven.com/a/autumn_crossing
studio_small_03 polyhaven.com/a/studio_small_03
sunflowers_puresky polyhaven.com/a/sunflowers_puresky
rosendal_plains_2 polyhaven.com/a/rosendal_plains_2

Adding your own HDRIs

Any equirectangular .hdr file works β€” just place it in resources/hdri/ and reference it from your YAML scene file or cycle to it with Numpad +/-.


HDR sky render 0 HDR sky render 1 HDR sky render 3 HDR sky render 4 HDR sky render 5 HDR sky render 6 HDR sky render 7 HDR sky render 8 HDR sky render 9

Technical implementationΒΆ

float16 GPU textureΒΆ

The .hdr file is decoded from Radiance RGBE (four bytes per pixel) to 32-bit float triplets by stb_image, then each channel is converted to IEEE 754 float16 (half precision). The resulting four-channel half-float image is uploaded to a cudaTextureObject_t with format:

cudaChannelFormatDesc{16, 16, 16, 16, cudaChannelFormatKindFloat}

CUDA hardware automatically promotes the fp16 values to fp32 on tex2D<float4> fetch β€” no shader-side conversion is needed.

Memory impact:

Resolution Uncompressed fp32 (VRAM) fp16 VRAM Saving
2K (2048 Γ— 1024) 32 MB 16 MB 50 %
4K (4096 Γ— 2048) 128 MB 64 MB 50 %
8K (8192 Γ— 4096) 512 MB 256 MB 50 %

Binary disk cache (.hdrcache)ΒΆ

Loading and decoding an 8K .hdr file (β‰ˆ 200 MB on disk) takes several seconds. On subsequent launches, the renderer writes a binary sidecar next to the .hdr file (e.g. venice_sunset_8k.hdr.hdrcache) and reads it on the next run.

A .hdrcache file is a compact binary blob with a 24-byte header followed by the raw fp16 pixel data β€” no decompression or format conversion needed. Typical time savings: 5–10Γ— faster loads compared to re-decoding the RGBE source.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  magic  β”‚  version  β”‚  w  β”‚  h  β”‚  (16 bytes)
β”‚            source_size          β”‚  (8 bytes, staleness check)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  width Γ— height Γ— 4 Γ— uint16_t β”‚  (raw fp16 pixels, RGBA order)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The source file's byte-size is stored in the header. If the .hdr file is replaced or modified (size changes), the cache is automatically invalidated and regenerated.

To skip the cache entirely (e.g. for diagnostics):

./rayon --no-hdr-cache --scene ../resources/scenes/default_scene.yaml

fp16 clampingΒΆ

HDR scene radiance values can exceed the fp16 finite range (65 504). Values above this threshold are clamped to Β±65504 before storage β€” ensuring the GPU texture never receives ±∞, which would propagate as NaN during path-tracing arithmetic and produce black "firefly" pixels.

Stale cache files

If you have .hdrcache files created by an older version of RayON (before the clamping fix), delete them and let the renderer regenerate them. Newly generated caches are identified by a version field in the header and will be automatically regenerated when the version does not match.