// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \example VolumetricFog
    \ingroup quick3d-examples
    \title Qt Quick 3D - Volumetric Light Example
    \examplecategory {3D}
    \brief Demonstrates how the QtQuick3D Render Extension can be used to implement volumetric light.
    \image volumetricFog-example.jpg
           {An stage with all kind of volumetric lights}

    \section1 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.

    \section2 Controls

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

    \section1 Implementation

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

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

    \qml
        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}
            ]
        }
    \endqml

    The \c froxelWidth, \c froxelHeight, and \c 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 \c nearPlane and \c farPlane properties define the depth range over which the volumetric
    effect is computed, and should match the \l PerspectiveCamera's clip distances.

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

    \section2 IES Light Profiles

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

    \qml
        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
        }
    \endqml

    \section2 Attaching the Extension to a View3D

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

    \qml
        View3D {
            extensions: [ froxelExtension ]
        }
    \endqml

    \section2 Fog Volumes

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

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

    \qml
        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
        }
    \endqml

    \section2 VolumetricFogEffect

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

    \qml
        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
                }
            ]
        }
    \endqml

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

*/
