Auf dieser Seite

Qt Quick 3D - Beispiel für eine Erweiterung für volumetrischen Nebel

Zeigt, wie volumetrischer Nebel in einer Render-Erweiterung implementiert wird.

Ein kahlgeblätterter Baum auf einer runden, stufenförmigen Bühne, beleuchtet von roten, grünen und blauen volumetrischen Lichtstrahlen, mit einem Einstellungsfeld für Beleuchtung, Nebel und Schatten

Übersicht

Dieses Beispiel implementiert volumetrischen Nebel als „ Qt Quick 3D “ render extension und zeigt, wie Sie die Erweiterung in Ihrem eigenen Projekt wiederverwenden können.

Die Erweiterung unterteilt den Kamera-Frustum in ein 3D-Gitter aus „Froxeln“(frustum-ausgerichtete Voxel) und nutzt einen Compute-Shader, um das Licht zu akkumulieren, das in jeder Zelle in Richtung der Kamera gestreut wird. Ein Post-Processing-Effekt fügt das Ergebnis anschließend in den gerenderten Frame ein.

Steuerung

Ziehen Sie mit der Maus, um die Kamera um die Szene herum zu drehen. Verwenden Sie das Einstellungsfenster, um die Beleuchtung, den Nebel, die Nachbearbeitung und die Schatteneinstellungen anzupassen.

Implementierung

Hinweis: Die Erweiterung fügt mit einem Compute-Shader Licht in das Froxel-Gitter ein und erfordert daher eine Grafik-API sowie Hardware mit Compute-Shader-Unterstützung. OpenGL-Versionen älter als 4.3 und OpenGL ES-Versionen älter als 3.1 bieten keine Compute-Unterstützung. Weitere Informationen finden Sie unter QRhi::Compute.

Der Typ „ VolumetricFogExtension “ implementiert die Erweiterung für volumetrischen Nebel. Er befindet sich im separaten Unterprojekt „ VFExtension “, sodass Sie ihn unverändert zu Ihrem eigenen Projekt hinzufügen können.

Legen Sie die folgenden Eigenschaften für „ VolumetricFogExtension “ fest:

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}
    ]
}

Die Eigenschaften „ froxelWidth “, „ froxelHeight “ und „ froxelDepth “ definieren die Auflösung des Froxel-Gitters, das der Compute-Shader ausfüllt. Eine höhere Auflösung erzeugt eine detailliertere Lichtstreuung, beansprucht jedoch mehr GPU-Speicher und Rechenzeit.

Die Eigenschaften „ nearPlane “ und „ farPlane “ definieren den Tiefenbereich, den der volumetrische Effekt abdeckt. Passen Sie diese an die Clip-Abstände des „ PerspectiveCamera “ an.

Die Eigenschaft „ fogVolumes “ enthält die Liste der „ Fog3DVolume “-Knoten, die festlegen, wo in der Szene Nebel vorhanden ist.

IES-Lichtprofile

Ein photometrisches Profil der Illuminating Engineering Society (IES) bestimmt die Winkelverteilung des Lichts eines Spotlichts. Die Eigenschaft „ iesTexture “ nimmt einen „ Texture “ entgegen, dessen Daten von einem „ IESTextureData “-Objekt stammen. Dieses Objekt analysiert „ .ies “-Dateien und packt sie in eine 2D-Atlas-Textur. Die Eigenschaft „ iesCount “ gibt an, wie viele Profile der Atlas enthält, und „ iesLightProfiles “ ordnet einzelne Lichter über „ IESLightProfileIndex “-Objekte den Profilindizes zu.

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
}
Hinzufügen der Erweiterung zu einer „View3D“

Fügen Sie die Erweiterung zur Liste „ extensions “ des „ View3D “ hinzu. Die Render-Pipeline ruft dann den Compute-Shader der Erweiterung einmal pro Frame auf:

View3D {
    extensions: [ froxelExtension ]
}
Nebelvolumina

Ein „ Fog3DVolume “-Knoten definiert einen Nebelbereich in der Szene. Die Eigenschaft „ type “ wählt eine von zwei Formen aus („ Fog3DVolume.Sphere “ oder „ Fog3DVolume.Box “), und die Eigenschaft „ extents “ legt die Begrenzungsabmessungen fest. Die Eigenschaften „ color “ und „ density “ steuern das Erscheinungsbild.

Durch Erhöh noiseOffset in jedem Frame wird das Rauschen animiert. Damit die Dichte mit der Höhe abnimmt, setzen Sie „ heightEnabled “ auf „ true “ und passen Sie „ leastIntenseY “, „ mostIntenseY “ und „ heightCurve “ an:

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

Die Erweiterung stellt ihr Ergebnis über die schreibgeschützte Eigenschaft „ froxelTexture “ bereit, eine 3D-RGBA-Textur, die die gesammelten Lichtstreuungsdaten für jeden Froxel enthält. Fügen Sie den Post-Processing-Effekt „ VolumetricFogEffect “ zu „ ExtendedSceneEnvironment “ hinzu, um diese Textur zu nutzen. Der Effekt führt einen Ray-March durch die Froxel-Textur durch und setzt das volumetrische Licht in das gerenderte Bild ein:

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
    }
]

Die Eigenschaft „ marchSteps “ steuert die Anzahl der Ray-Marching-Schritte. Passen Sie diese an „ froxelDepth “ an. Die Eigenschaften „ frameBaseJitter “ und „ jitterIntensity “ aktivieren zeitliches Dithering, wodurch Streifenartefakte reduziert werden, wenn die Szene zusätzlich zeitliches Antialiasing verwendet.

Wiederverwendung der Erweiterung in Ihrem eigenen Projekt

Das Unterprojekt „ VFExtension “ wird als eigenständiges QML-Modul kompiliert. Um es in einem anderen Projekt zu verwenden, kopieren Sie das Verzeichnis, fügen Sie es mit „ add_subdirectory() “ hinzu und verknüpfen Sie die Bibliothek mit Ihrem Zielprojekt:

add_subdirectory(VFExtension)

target_link_libraries(myapp PRIVATE VFExtension)

Importieren Sie anschließend das Modul in QML:

import VFExtension

Hinweis: Die Erweiterung enthält private „ Qt Quick 3D “-Header und ist gegen „ Qt6::Quick3DPrivate “ verknüpft. Für die private API wird keine Garantie für Quell- oder Binärkompatibilität übernommen, daher sind bei einem Wechsel zu einer neueren Qt-Version möglicherweise Änderungen an der Erweiterung erforderlich.

Beispielprojekt auf code.qt.io

Siehe auch Qt Quick 3D – Beispiel für die „Stencil Outline“-Erweiterung, Qt Quick 3D – Einfaches Nebelbeispiel sowie benutzerdefinierte Render-Passes unter Qt Quick 3D.

© 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.