Qt Quick 3D - Beispiel für Benutzerpässe
Veranschaulicht die Erstellung benutzerdefinierter Render-Pässe in „ Qt Quick 3D “.

}
Das Beispiel „User Passes“ veranschaulicht, wie man benutzerdefinierte Render-Passes in „ Qt Quick 3D “ erstellt. Es implementiert eine Render-Pipeline mit verzögerter Beleuchtung unter Verwendung mehrerer benutzerdefinierter Render-Passes und zeigt, wie die gesamte Render-Sequenz gehandhabt wird: opake Geometrie, Skybox, in die Szene eingebettete 2D-Elemente und transparente Geometrie.
Interne Render-Passes deaktivieren
Standardmäßig verwendet „ Qt Quick 3D “ eine Reihe interner Render-Passes, um die 3D-Szene zu rendern. Manchmal möchten Sie diese internen Render-Passes möglicherweise deaktivieren und Ihre eigene Rendering-Pipeline mithilfe benutzerdefinierter Render-Passes implementieren.
Um die internen Render-Pässe zu deaktivieren, setzen Sie die Eigenschaft „ renderOverrides “ des „ View3D “ auf „ View3D.DisableInternalPasses “.
View3D {
id: view3D
anchors.fill: parent
renderOverrides: View3D.DisableInternalPasses
environment: ExtendedSceneEnvironment {
lightProbe: Texture {
textureData: ProceduralSkyTextureData {
}
}
backgroundMode: SceneEnvironment.SkyBox
}Wenn Sie die internen Render-Pässe deaktivieren, müssen Sie das Ergebnis des Hauptfarb-Passes bereitstellen, damit „ View3D “ überhaupt etwas auf dem Bildschirm anzeigen kann.
Geometrie-Buffer-Pass
In diesem Beispiel ist der erste benutzerdefinierte Render-Pass ein Geometrie-Buffer-Pass (G-Buffer), der die Szenengeometrie in mehrere Render-Ziele rendert und dabei unterschiedliche Materialeigenschaften in jedem Ziel speichert. Das bereitgestellte Beispiel ist eine Teilmenge der vollständigen Materialeigenschaften, die von Qt Quick 3D -Materialien bereitgestellt werden, und konzentriert sich auf die Eigenschaften, die für eine grundlegende Implementierung der verzögerten Beleuchtung erforderlich sind.
Unser „ RenderPass “ ist in „ GBufferPass.qml “ definiert:
RenderPass {
id: gbufferPass
clearColor: Qt.rgba(0.0, 0.0, 0.0, 0.0)
property alias layerMask: filter.layerMask
required property RenderPassTexture depthTexture
RenderPassTexture {
id: gbuffer0
format: RenderPassTexture.RGBA16F
// rgb: baseColor (linear), a: metalness
}
RenderPassTexture {
id: gbuffer1
format: RenderPassTexture.RGBA16F
// rgb: normal, a: roughness
}
RenderPassTexture {
id: gbuffer2
format: RenderPassTexture.RGBA16F
// rgb: emissive, a: ao/spare
}
commands: [
ColorAttachment { target: gbuffer0; name: "GBUFFER0" },
ColorAttachment { target: gbuffer1; name: "GBUFFER1" },
ColorAttachment { target: gbuffer2; name: "GBUFFER2" },
DepthTextureAttachment { target: gbufferPass.depthTexture },
RenderablesFilter {
id: filter
renderableTypes: RenderablesFilter.Opaque
}
]
materialMode: RenderPass.AugmentMaterial
augmentShader: "gbuffer_augment.glsl"
}Es definiert 3 Farb-Attachments und 1 Tiefen-Attachment. Der Pass benötigt 3 Texturen, die als „ RenderPassTexture “-Objekte innerhalb von „ RenderPass “ definiert sind. Diese 3 „RenderPassTextures“ dienen als Ziele für die Farb-Attachments des Passes, während das Tiefen-Attachment eine von außerhalb des Passes bereitgestellte Tiefentextur verwendet.
Der „ RenderPass “ selbst ist auf den Modus „ AugmentMaterial “ eingestellt, was bedeutet, dass er die Materialien der gerenderten Objekte durch zusätzlichen Shader-Code erweitert. Der Erweiterungs-Shader ist in der Datei „ gbuffer_augment.glsl “ enthalten, die die erforderlichen Materialeigenschaften an die verschiedenen Renderziele ausgibt.
void MAIN_FRAGMENT_AUGMENT()
{
vec3 baseColor = BASE_COLOR.rgb;
float metalness = METALNESS;
float roughness = ROUGHNESS;
vec3 worldNormal = normalize(WORLD_NORMAL);
// GBuffer 0: albedo + metalness
GBUFFER0 = vec4(baseColor, metalness);
// GBuffer 1: normal (encoded to 0..1) + roughness
GBUFFER1 = vec4(worldNormal * 0.5 + 0.5, roughness);
// GBuffer 2: world position
GBUFFER2 = vec4(qt_varWorldPos, 1.0);
}Hier sehen Sie, wie die Grundfarbe, die Metallizität, die Weltnormale, die Rauheit und die Weltposition in den drei Farb-Attachments des G-Buffers gespeichert werden.
Um den G-Buffer-Pass tatsächlich in der Render-Pipeline zu nutzen, müssen wir in „ Main.qml “ eine Instanz davon erstellen und die erforderliche Tiefentextur bereitstellen:
RenderPassTexture {
id: mainDepthStencilTexture
format: RenderPassTexture.Depth24Stencil8
}
GBufferPass {
id: gbufferPass
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
depthTexture: mainDepthStencilTexture
}
RenderOutputProvider {
id: gbuffer0Provider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: gbufferPass
attachmentSelector: RenderOutputProvider.Attachment0
}
RenderOutputProvider {
id: gbuffer1Provider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: gbufferPass
attachmentSelector: RenderOutputProvider.Attachment1
}
RenderOutputProvider {
id: gbuffer2Provider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: gbufferPass
attachmentSelector: RenderOutputProvider.Attachment2
}Es werden drei „ RenderOutputProvider “-Instanzen erstellt, um Verweise auf die gerenderten G-Buffer-Texturen bereitzustellen, die im nachfolgenden Beleuchtungsdurchgang verwendet werden.
Die Eigenschaft „ layerMask “ des G-Buffer-Passes ist so eingestellt, dass nur Objekte gerendert werden, die sich auf ContentLayer.Layer0 und ContentLayer.Layer1 befinden. Auf diese Weise können wir steuern, welche Objekte im G-Buffer-Pass gerendert werden, indem wir ihre Eigenschaft „ layers “ entsprechend einstellen.
Hauptfarb-Pass und SubRenderPässe
Anstelle eines einzelnen flachen Render-Passes verwendet dieses Beispiel einen zusammengesetzten „ mainColorPass “, der die Hauptfarb- und Tiefentexturen enthält und das gesamte Rendering über eine Abfolge von „ SubRenderPass “-Unterobjekten koordiniert.
Jeder „ SubRenderPass “ nutzt dieselben Renderziele wie der übergeordnete Pass und wird der Reihe nach ausgeführt. Dadurch lässt sich auf einfache Weise eine mehrschichtige Rendering-Pipeline aufbauen, bei der jede Stufe das Ergebnis der vorherigen ergänzt.
RenderPass {
id: mainColorPass
clearColor: "black"
// Preserve depth across SubRenderPasses so geometry depth is available
// when rendering the skybox, transparent objects, and 2D items.
renderTargetFlags: RenderPass.RenderTargetFlags.PreserveDepthStencilContents
commands: [
ColorAttachment {
target: mainColorTexture
},
DepthTextureAttachment {
target: mainDepthStencilTexture
},
RenderablesFilter {
// Nothing renders directly in the outer pass; all rendering
// is delegated to the SubRenderPasses below.
renderableTypes: RenderablesFilter.None
},
// 1. Deferred lighting: shade opaque geometry stored in the G-buffer.
SubRenderPass {
renderPass: RenderPass {
id: deferredLightingPass
materialMode: RenderPass.OriginalMaterial
commands: [
PipelineStateOverride {
// The full-screen quad must not write or test depth;
// geometry depth was already written by the G-buffer pass.
depthWriteEnabled: false
depthTestEnabled: false
},
RenderablesFilter { layerMask: ContentLayer.Layer13 }
]
}
},
// 2. Skybox: render the environment behind all scene geometry.
SubRenderPass {
renderPass: RenderPass {
id: skyboxPass
passMode: RenderPass.SkyboxPass
commands: [
PipelineStateOverride {
// The skybox is rendered "at infinity" so it must
// depth-test (to be hidden by geometry) but must not
// write depth.
depthTestEnabled: true
depthWriteEnabled: false
}
]
}
},
// 3. 2D items: render any Qt Quick Items embedded in the 3D scene.
SubRenderPass {
renderPass: RenderPass {
id: item2DPass
passMode: RenderPass.Item2DPass
}
},
// 4. Transparent objects: render blended geometry on top of everything else.
SubRenderPass {
renderPass: RenderPass {
id: transparentItemPass
materialMode: RenderPass.OriginalMaterial
commands: [
RenderablesFilter {
renderableTypes: RenderablesFilter.Transparent
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
},
PipelineStateOverride {
// Enable alpha blending and depth testing so transparent
// objects sort correctly against opaque geometry.
blendEnabled: true
depthTestEnabled: true
targetBlend0.enable: true
targetBlend0.srcColor: RenderTargetBlend.SrcAlpha
targetBlend0.dstColor: RenderTargetBlend.OneMinusSrcAlpha
targetBlend0.srcAlpha: RenderTargetBlend.One
targetBlend0.dstAlpha: RenderTargetBlend.OneMinusSrcAlpha
}
]
}
}
]
}Der äußere Pass setzt ` renderableTypes: RenderablesFilter.None`, sodass im übergeordneten Pass nichts direkt gerendert wird – das gesamte Rendering wird an die Unterpässe delegiert. Das Flag „ PreserveDepthStencilContents “ stellt sicher, dass die vom G-Buffer-Pass geschriebenen Tiefenwerte jedem Unterpass zur Verfügung stehen.
Subpass für verzögerte Beleuchtung
Der erste Unterpass führt die Berechnung der verzögerten Beleuchtung durch. Er rendert das Vollbild- deferredLightingQuad -Modell, das die G-Buffer-Texturen abtastet und die Beleuchtung für jedes Pixel berechnet.
Model {
id: deferredLightingQuad
layers: ContentLayer.Layer13
castsShadows: false
receivesShadows: false
geometry: PlaneGeometry {
// geometry doesn't matter, just need 4 verts
plane: PlaneGeometry.XY
}
materials: [
CustomMaterial {
id: lightingPassMaterial
property TextureInput gbuffer0: TextureInput {
enabled: true
texture: Texture {
textureProvider: gbuffer0Provider
}
}
property TextureInput gbuffer1: TextureInput {
enabled: true
texture: Texture {
textureProvider: gbuffer1Provider
}
}
property TextureInput gbuffer2: TextureInput {
enabled: true
texture: Texture {
textureProvider: gbuffer2Provider
}
}
shadingMode: CustomMaterial.Unshaded
fragmentShader: "lighting.frag"
vertexShader: "lighting.vert"
}
]
}Der „ deferredLightingQuad “ wird auf „ ContentLayer.Layer13 “ gesetzt, sodass er für den G-Buffer-Pass unsichtbar ist und nur von diesem Sub-Pass gerendert wird.
Ein „ PipelineStateOverride “ deaktiviert sowohl Tiefenschreibvorgänge als auch Tiefenprüfungen für das Quad. Der G-Buffer-Durchlauf hat bereits die korrekte Tiefe für die Szenengeometrie geschrieben, daher darf das Vollbild-Quad die Tiefe weder verändern noch prüfen.
Skybox-Subpass
Der zweite Sub-Pass rendert die Skybox der Szenenumgebung unter Verwendung des speziellen „ RenderPass.SkyboxPass “-Pass-Modus. „ Qt Quick 3D “ übernimmt das Zeichnen der Skybox-Geometrie unter Verwendung der Einstellungen „ lightProbe “ und „ backgroundMode “ aus dem „ SceneEnvironment “.
Ein „ PipelineStateOverride “ aktiviert die Tiefenprüfung, sodass die Skybox korrekt hinter der Szenengeometrie verborgen wird, während Tiefenschreibvorgänge deaktiviert sind, da sich die Skybox „im Unendlichen“ befindet und niemals Geometrie verdecken darf.
Subpass für transparente Objekte
Transparente Objekte können nicht im G-Buffer gespeichert werden, da sie eine von hinten nach vorne sortierte Überblendung erfordern. Stattdessen werden sie zuletzt mit ihren ursprünglichen Materialien über einen speziellen Sub-Pass gerendert.
Der transparente Kegel in der Szene wird wie folgt deklariert:
Model {
id: cone
layers: ContentLayer.Layer1
source: "#Cone"
y: 100
materials: [
PrincipledMaterial {
baseColor: Qt.rgba(0.0, 1.0, 0.0, 0.5)
alphaMode: PrincipledMaterial.Blend
metalness: 0.0
roughness: 0.5
}
]
}Der Subpass für transparente Objekte verwendet einen „ RenderablesFilter “, um nur transparente Renderelemente auf den entsprechenden Ebenen auszuwählen, und ein „ PipelineStateOverride “ ermöglicht das Alpha-Blending, während der Tiefentest aktiv bleibt, damit transparente Objekte korrekt gegenüber undurchsichtiger Geometrie sortiert werden.
Transparente Objekte müssen nach allen undurchsichtigen Durchläufen gerendert werden, damit der Tiefenpuffer vollständig gefüllt ist, bevor die Überblendung erfolgt.
2D-Elemente im 3D-Subpass
Qt Quick 3D können Standard-2D-Elemente des „ Qt Quick “ mithilfe von „ Node “ als Container in die 3D-Szene einbetten. Um diese Elemente in eine benutzerdefinierte Render-Pipeline einzubinden, fügen Sie einen Sub-Pass mit „ passMode “ hinzu: „ RenderPass.Item2DPass“.
Node {
x: -200
y: 100
Item {
anchors.centerIn: parent
ColumnLayout {
Button {
text: "Click Me!"
}
Rectangle {
color: "blue"
implicitWidth: 50
implicitHeight: 50
NumberAnimation on rotation {
from: 0
to: 360
duration: 4000
loops: Animation.Infinite
running: true
}
}
}
}
NumberAnimation on eulerRotation.y {
from: 0
to: 360
duration: 6000
loops: Animation.Infinite
running: true
}
}Der Modus „ Item2DPass “ weist „ Qt Quick 3D “ an, alle „ Qt Quick “-Elemente, die untergeordnete Elemente von 3D-Knoten sind, in das aktuelle Renderziel zu rendern und mit den bereits vorhandenen 3D-Inhalten zu kombinieren.
Rendering auf den Bildschirm
Um schließlich das Ergebnis unserer benutzerdefinierten Render-Pässe auf dem Bildschirm anzuzeigen, müssen wir sicherstellen, dass die Hauptfarbtextur des „ View3D “ mit dem Ergebnis des Hauptfarb-Passes aktualisiert wird.
SimpleQuadRenderer {
texture: Texture {
textureProvider: mainColorPassProvider
}
}
RenderPassTexture {
id: mainColorTexture
format: RenderPassTexture.RGBA16F
}
RenderOutputProvider {
id: mainColorPassProvider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: mainColorPass
attachmentSelector: RenderOutputProvider.Attachment0
}Die „ SimpleQuadRenderer “ dient dazu, die von der „ mainColorPass “ erzeugte Hauptfarbtextur in den Framebuffer der „ View3D “ zu blitten. Die „ RenderOutputProvider “ stellt den ersten Farb-Attachment von „ mainColorPass “ als Textur bereit, die von der „ SimpleQuadRenderer “ ausgelesen werden kann.
© 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.