On this page

Qt Quick 3D - Volumetric Light Example

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

An stage with all kind of volumetric lights

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

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.