- Qt 6.12
- Qt Quick 3D
- Qt Quick 3D Examples and Tutorials
- Qt Quick 3D - Volumetric Light Example
- Qt Quick 3D | Commercial or GPLv3

# Qt Quick 3D - Volumetric Light Example

Demonstrates how the QtQuick3D Render Extension can be used to implement volumetric light.

#### Overview

This example shows how to use QtQuick3D Render Extension to make a volumetric light extension and how can it be use as a component in a project.

##### Controls

For navigation, you can orbit around the scene and you can use settings panel to change lights, volumetric fog and scene settings.

#### Implementation

The Volumetric fog extension is implemented in the `VolumetricFogExtension`. This is located in the separate sub-project `VFExtension`, so you can easily re-use it in other projects.

The VolumetricFogExtension has the following properties that need to be set:

     VolumetricFogExtension {
         id: froxelExtension
         froxelWidth: 160
         froxelHeight: 96
         froxelDepth: 96
         nearPlane: 1.0
         farPlane: 4000.0
         fogVolumes: [ fogSphere ]

         iesTexture: settings.iesLights ? iesAtlasTexture : null
         iesCount: iesTextureData.sources.length
         iesLightProfiles: [
         IESLightProfileIndex { light: pinkSpot; index: settings.iesLightIndex; intensity: 0.5}
         ]
     }

The `froxelWidth`, `froxelHeight`, and `froxelDepth` properties define the resolution of the 3D froxel grid used by the volumetric compute shader. Higher resolution produces more detailed light scattering at the cost of GPU memory and compute time.

The `nearPlane` and `farPlane` properties define the depth range over which the volumetric effect is computed, and should match the PerspectiveCamera's clip distances.

The `fogVolumes` property holds a list of Fog3DVolume nodes that define where volumetric fog is present in the scene.

##### IES Light Profiles

IES light profiles can be used to shape the angular light distribution of spot lights. The `iesTexture` property takes a Texture whose data is generated by an IESTextureData object that parses `.ies` files and packs them into a 2D atlas texture. The `iesCount` property specifies how many profiles are packed in the atlas, and `iesLightProfiles` maps individual lights to profile indices via IESLightProfileIndex objects.

     Texture {
         id: iesAtlasTexture
         textureData: IESTextureData {
             id: iesTextureData
             sources: [
                 "qrc:/assets/l0.ies",
                 "qrc:/assets/l1.ies",
                 "qrc:/assets/l2.ies",
                 "qrc:/assets/l3.ies",
                 "qrc:/assets/l4.ies",
                 "qrc:/assets/l5.ies"
             ]
         }
         tilingModeHorizontal: Texture.ClampToEdge
         tilingModeVertical: Texture.ClampToEdge
         minFilter: Texture.Linear
         magFilter: Texture.Linear
         generateMipmaps: false
     }

##### Attaching the Extension to a View3D

The extension is registered with the View3D through its `extensions` property, which lets the render pipeline invoke the extension's compute shader each frame:

     View3D {
         extensions: [ froxelExtension ]
     }

##### Fog Volumes

Fog regions are defined using Fog3DVolume nodes placed in the scene. Each volume supports two shapes via the `type` property: `Fog3DVolume.Sphere` and `Fog3DVolume.Box`. The `extents` property defines the bounding dimensions, while `color` and `density` control the visual appearance.

Animated noise is applied by advancing `noiseOffset` each frame. Height-based density falloff can be enabled with `heightEnabled` together with `leastIntenseY`, `mostIntenseY`, and `heightCurve`:

     Fog3DVolume {
         id: fogSphere
         type: Fog3DVolume.Sphere
         extents: Qt.vector3d(5000, 5000, 5000)
         color: settings.fogVolumeColor
         density: settings.fogVolumeDensity
         noiseOffset: Qt.vector3d(se.time * 0.1 * settings.fogSpeed, 0, 0)
         noiseScale: settings.fogVolumeNoiseScale
         heightEnabled: settings.fogVolumeHeightEnabled
         leastIntenseY: settings.fogVolumeHeightLeastY
         mostIntenseY: settings.fogVolumeHeightMostY
         heightCurve: settings.fogVolumeHeightCurve
     }

##### VolumetricFogEffect

The extension exposes its result through the read-only `froxelTexture` property, a 3D RGBA texture containing the accumulated light scattering data for each froxel. This texture is consumed by the VolumetricFogEffect post-processing effect added to the ExtendedSceneEnvironment. The effect ray-marches through the froxel texture and composites the volumetric light onto the rendered frame:

     environment: ExtendedSceneEnvironment {
         effects: [
             VolumetricFogEffect {
                 froxelTexture: froxelExtension.froxelTexture
                 cameraPosition: camera.scenePosition
                 cameraForward: camera.forward
                 invViewMatrix: camera.sceneTransform
                 marchSteps: froxelExtension.froxelDepth
                 nearPlane: froxelExtension.nearPlane
                 farPlane: froxelExtension.farPlane
                 frameBaseJitter: se.temporalAAEnabled &&
                                  se.temporalAAMode === SceneEnvironment.TAAMotionVector &&
                                  se.antialiasingMode !== SceneEnvironment.MSAA ? 1.0 : 0.0
                 jitterIntensity: settings.jitterIntensity
             }
         ]
     }

The `marchSteps` property controls the number of ray marching steps and should match `froxelDepth`. The `frameBaseJitter` and `jitterIntensity` properties enable temporal dithering to reduce banding artifacts when used together with temporal anti-aliasing.

Example project @ code.qt.io