User-Defined Render Passes in Qt Quick 3D
Qt Quick 3D provides a high-level API for 3D rendering that handles most rendering details automatically. However, for advanced use cases, applications may need complete control over the rendering pipeline. User-defined render passes enable this by allowing applications to disable the internal rendering pipeline and define their own custom passes.
User render passes enable advanced rendering techniques such as:
- Deferred shading and lighting
- Multi-pass rendering effects
- Custom post-processing pipelines
- Selective rendering with layer-based filtering
- Screen-space effects (ambient occlusion, reflections, etc.)
- Custom shadow mapping techniques
- Debug visualization passes
Levels of Customization
Qt Quick 3D offers three complementary levels of rendering customization, each suited to different use cases:
| Level | Scope | Use Cases |
|---|---|---|
| Effect | Post-processing | Applies effects after the scene is rendered (blur, color grading, etc.) |
| CustomMaterial | Per-material shaders | Custom vertex and fragment shaders for individual materials |
| RenderPass (User Render Passes) | Complete pipeline control | Deferred rendering, multiple passes, custom render targets |
User render passes (RenderPass) provide the most control, allowing you to either supplement or completely replace the default rendering pipeline. This complements CustomMaterial and Effect: CustomMaterial customizes how individual objects are rendered, while user render passes control the overall rendering strategy and architecture.
Using User Render Passes
User render passes can be used in two ways:
Supplementing Internal Passes
You can add custom RenderPass objects alongside the default rendering pipeline without disabling internal passes. This is useful for rendering to textures that are then used by Effect or CustomMaterial, or for creating auxiliary render targets.
View3D {
// Internal passes still run normally
RenderPassTexture { id: customTexture; format: RenderPassTexture.RGBA16F }
RenderPass {
// Custom pass renders to texture
commands: [
ColorAttachment { target: customTexture },
DepthStencilAttachment { }
]
}
// Use customTexture in an Effect or material
}Replacing Internal Passes
For complete control over the rendering pipeline, disable Qt Quick 3D's internal rendering by setting the renderOverrides property:
View3D {
renderOverrides: View3D.DisableInternalPasses
// Your custom render passes go here
}When internal passes are disabled, Qt Quick 3D will not perform any default rendering. This means you must:
- Define at least one RenderPass to render your scene
- Provide the final output texture to display via SimpleQuadRenderer or similar mechanism
- Handle all rendering aspects including depth buffers, transparency, etc.
Note: Disabling internal passes gives you complete control, but also complete responsibility. Features like automatic shadow rendering, transparency sorting, and environment reflections must be implemented in your custom passes if needed.
Core Concepts
User-defined render passes are built from several key components:
RenderPass
The RenderPass type is the main building block. It defines a single rendering operation with a set of commands that control what gets rendered and how. Each pass can:
- Render to one or more color textures (up to 4 simultaneous render targets)
- Write depth and stencil information
- Filter which objects to render based on layers
- Override graphics pipeline state (blending, culling, etc.)
- Use original materials, augment them with custom shaders, or override them entirely
RenderPassTexture
The RenderPassTexture type defines textures that serve as render targets. These can be color textures in various formats (RGBA8, RGBA16F, RGBA32F, etc.) or depth/stencil textures. Render pass textures are used as outputs from one pass and can be used as texture inputs to subsequent passes.
RenderOutputProvider
The RenderOutputProvider type connects render passes by exposing the output textures from one pass as texture inputs that can be used by materials or other passes. This is essential for multi-pass rendering where later passes need to read the results of earlier passes.
ContentLayer
The ContentLayer singleton provides layer constants (Layer0 through Layer23) used for filtering which objects render in which pass. By assigning objects to specific layers and using RenderablesFilter in your passes, you can control precisely what gets rendered in each pass.
Render Commands
Each RenderPass contains a list of commands that configure its behavior:
- ColorAttachment: Specifies a color render target
- DepthStencilAttachment: Specifies depth/stencil handling
- DepthTextureAttachment: Uses a texture for depth output
- RenderablesFilter: Filters objects by layer and type (opaque/transparent)
- PipelineStateOverride: Controls graphics pipeline state
SubRenderPass: Executes another render pass within this pass- AddDefine: Adds shader preprocessor defines
Material Modes
Each RenderPass has a materialMode property that controls how materials are handled during rendering. The three modes offer different levels of material control:
OriginalMaterial Mode
This mode renders objects with their assigned materials unchanged. It's useful when you want to control the rendering pipeline structure (multiple passes, custom render targets) but keep the material behavior standard.
RenderPass {
materialMode: RenderPass.OriginalMaterial
commands: [
ColorAttachment { target: myColorTexture },
DepthStencilAttachment { }
]
}AugmentMaterial Mode
This mode injects custom shader code into the existing material pipeline. It's particularly useful for deferred rendering where you need to output additional data (like normals, positions, etc.) to multiple render targets while preserving the material's base behavior.
RenderPass {
materialMode: RenderPass.AugmentMaterial
augmentShader: "my_augment.glsl"
commands: [
ColorAttachment { target: gbuffer0; name: "GBUFFER0" },
ColorAttachment { target: gbuffer1; name: "GBUFFER1" },
DepthStencilAttachment { }
]
}The augment shader file contains a MAIN_FRAGMENT_AUGMENT() function:
void MAIN_FRAGMENT_AUGMENT()
{
// Access material properties
vec3 color = BASE_COLOR.rgb;
float metal = METALNESS;
float rough = ROUGHNESS;
vec3 normal = normalize(WORLD_NORMAL);
// Write to multiple render targets
GBUFFER0 = vec4(color, metal);
GBUFFER1 = vec4(normal * 0.5 + 0.5, rough);
}See Augment Shaders for Multiple Render Targets for more details.
OverrideMaterial Mode
This mode replaces all object materials with a single material. It's useful for specialized passes like shadow mapping, depth prepass, or debug visualization.
RenderPass {
materialMode: RenderPass.OverrideMaterial
overrideMaterial: CustomMaterial {
fragmentShader: "depth_only.frag"
// All objects will use this material
}
commands: [
DepthTextureAttachment { target: depthTexture }
]
}Render Pass Commands
Commands are specified in the commands property and execute in the order they are defined.
Color Attachment
The ColorAttachment command specifies a color render target. The name property defines how the attachment is accessed in augment shaders.
ColorAttachment {
target: myTexture // RenderPassTexture to render to
name: "GBUFFER0" // Name for shader access (optional)
}You can have up to 4 color attachments per pass (for multiple render targets).
Depth Attachments
There are two ways to handle depth:
DepthStencilAttachment uses an implicit depth/stencil buffer:
DepthStencilAttachment { } // Creates depth/stencil buffer automaticallyDepthTextureAttachment uses an explicit texture for depth output:
RenderPassTexture {
id: depthTex
format: RenderPassTexture.Depth24Stencil8
}
DepthTextureAttachment {
target: depthTex // Explicit depth texture
}Use DepthTextureAttachment when you need to share the depth buffer between multiple passes or use it as a texture input in shaders.
Renderables Filter
The RenderablesFilter command controls which objects are rendered based on their layer assignment and renderable type.
RenderablesFilter {
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
renderableTypes: RenderablesFilter.Opaque
}The layerMask property uses bitwise OR to combine layers. The renderableTypes property can be:
RenderablesFilter.Opaque: Render only opaque objectsRenderablesFilter.Transparent: Render only transparent objectsRenderablesFilter.Opaque| RenderablesFilter.Transparent: Render both
Pipeline State Override
The PipelineStateOverride command provides fine-grained control over graphics pipeline state. It can override depth testing, blending, culling, polygon mode, and more.
PipelineStateOverride {
depthTestEnabled: true
depthWriteEnabled: false
blendEnabled: true
cullMode: PipelineStateOverride.Back
polygonMode: PipelineStateOverride.Fill
}See Pipeline State Control for more examples.
Sub Render Pass
The SubRenderPass command allows hierarchical composition of render passes by executing another render pass within the current pass.
RenderPass {
id: parentPass
commands: [
ColorAttachment { target: colorTex },
SubRenderPass { renderPass: childPass },
// More commands after child pass
]
}
RenderPass {
id: childPass
// This pass executes within parentPass
}Add Define
The AddDefine command adds shader preprocessor defines that affect shader compilation.
AddDefine {
name: "USE_SPECIAL_MODE"
value: 1
}Simple Example: Single Pass Rendering
Here's a minimal example showing user-defined render passes:
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
View3D {
anchors.fill: parent
renderOverrides: View3D.DisableInternalPasses
// Camera and lights
PerspectiveCamera { z: 300 }
DirectionalLight { }
// Define render target texture
RenderPassTexture {
id: colorTarget
format: RenderPassTexture.RGBA16F
}
// Define the render pass
RenderPass {
id: mainPass
materialMode: RenderPass.OriginalMaterial
clearColor: "skyblue"
commands: [
ColorAttachment { target: colorTarget },
DepthStencilAttachment { }
]
}
// Display the result
SimpleQuadRenderer {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: mainPass
attachmentSelector: RenderOutputProvider.Attachment0
}
}
}
// Scene content
Model {
source: "#Sphere"
materials: PrincipledMaterial {
baseColor: "red"
metalness: 0.0
roughness: 0.3
}
}
}This example:
- Disables internal passes
- Creates a render target texture (colorTarget)
- Defines a render pass that renders to that texture
- Uses RenderOutputProvider to expose the texture
- Displays the result with SimpleQuadRenderer
- Renders a sphere with standard material
Working with Layers
The ContentLayer singleton provides constants for organizing objects into layers, allowing fine-grained control over what renders in each pass.
Layer Constants
Qt Quick 3D provides 24 user-assignable layers:
ContentLayer.Layer0throughContentLayer.Layer23: Individual layersContentLayer.LayerAll: All user layers combinedContentLayer.LayerNone: No layers
Note: Layers 24-31 are reserved for internal use.
Assigning Objects to Layers
Assign objects to layers using the layers property:
Model {
source: "#Cube"
layers: ContentLayer.Layer0
materials: PrincipledMaterial { baseColor: "red" }
}
Model {
source: "#Sphere"
layers: ContentLayer.Layer1 | ContentLayer.Layer2
materials: PrincipledMaterial { baseColor: "blue" }
}Objects can belong to multiple layers using bitwise OR.
Filtering by Layer
Use RenderablesFilter in your render passes to select which layers to render:
RenderPass {
id: pass1
commands: [
ColorAttachment { target: texture1 },
RenderablesFilter {
layerMask: ContentLayer.Layer0
}
]
// Only renders objects on Layer0 (red cube)
}
RenderPass {
id: pass2
commands: [
ColorAttachment { target: texture2 },
RenderablesFilter {
layerMask: ContentLayer.Layer1 | ContentLayer.Layer2
}
]
// Only renders objects on Layer1 or Layer2 (blue sphere)
}Use Case: Selective Rendering
A practical example is rendering certain objects as wireframe overlays:
View3D {
renderOverrides: View3D.DisableInternalPasses
RenderPassTexture { id: colorTex; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: depthTex; format: RenderPassTexture.Depth24Stencil8 }
// Pass 1: Render solid objects
RenderPass {
id: solidPass
commands: [
ColorAttachment { target: colorTex },
DepthTextureAttachment { target: depthTex },
RenderablesFilter { layerMask: ContentLayer.Layer0 }
]
}
// Pass 2: Render wireframe overlay
RenderPass {
id: wireframePass
commands: [
ColorAttachment { target: colorTex },
DepthTextureAttachment { target: depthTex },
PipelineStateOverride {
polygonMode: PipelineStateOverride.Line
depthTestEnabled: true
depthWriteEnabled: false
},
RenderablesFilter { layerMask: ContentLayer.Layer1 }
]
}
SimpleQuadRenderer {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: wireframePass
attachmentSelector: RenderOutputProvider.Attachment0
}
}
}
Model {
source: "#Sphere"
layers: ContentLayer.Layer0 // Rendered solid
materials: PrincipledMaterial { baseColor: "blue" }
}
Model {
source: "#Sphere"
layers: ContentLayer.Layer1 // Rendered as wireframe
materials: PrincipledMaterial { baseColor: "yellow" }
}
}Texture Management
User render passes rely heavily on textures both as render targets and as inputs to subsequent passes or materials.
Render Pass Texture Formats
RenderPassTexture supports various formats for different use cases:
Color Formats:
| Format | Description | Use Case |
|---|---|---|
| RGBA8 | 8-bit per channel | Standard color output, lower memory usage |
| RGBA16F | 16-bit floating point | HDR rendering, intermediate buffers |
| RGBA32F | 32-bit floating point | High precision calculations |
| R8, R16, R16F, R32F | Single channel variants | Grayscale data, specialized buffers |
Depth Formats:
| Format | Description |
|---|---|
| Depth16 | 16-bit depth |
| Depth24 | 24-bit depth |
| Depth32 | 32-bit depth |
| Depth24Stencil8 | 24-bit depth + 8-bit stencil |
Example texture definitions:
RenderPassTexture {
id: hdrColorBuffer
format: RenderPassTexture.RGBA16F // HDR color
}
RenderPassTexture {
id: depthBuffer
format: RenderPassTexture.Depth24Stencil8 // Depth + stencil
}
RenderPassTexture {
id: normalBuffer
format: RenderPassTexture.RGBA16F // Store normals
}Sharing Textures Between Passes
Multiple passes can share the same depth texture, allowing depth testing across passes:
RenderPassTexture {
id: sharedDepth
format: RenderPassTexture.Depth24Stencil8
}
RenderPass {
id: geometryPass
commands: [
ColorAttachment { target: colorTex1 },
DepthTextureAttachment { target: sharedDepth }
]
}
RenderPass {
id: transparentPass
renderTargetFlags: RenderPass.PreserveDepthStencilContents
commands: [
ColorAttachment { target: colorTex2 },
DepthTextureAttachment { target: sharedDepth }
// Uses depth from geometryPass for depth testing
]
}Render Output Provider
The RenderOutputProvider exposes render pass outputs as Texture inputs:
// Define a render pass with color output
RenderPass {
id: firstPass
commands: [
ColorAttachment { target: intermediateTexture }
]
}
// Expose its output
RenderOutputProvider {
id: intermediateProvider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: firstPass
attachmentSelector: RenderOutputProvider.Attachment0
}
// Use in a material
CustomMaterial {
property TextureInput inputTex: TextureInput {
texture: Texture { textureProvider: intermediateProvider }
}
fragmentShader: "process.frag"
}The attachmentSelector property specifies which color attachment to use when a pass has multiple render targets:
RenderOutputProvider.Attachment0: First color attachmentRenderOutputProvider.Attachment1: Second color attachmentRenderOutputProvider.Attachment2: Third color attachmentRenderOutputProvider.Attachment3: Fourth color attachment
Pass Chaining Example
Multiple passes can be chained together where each pass processes the output of the previous pass:
View3D {
renderOverrides: View3D.DisableInternalPasses
// Intermediate textures
RenderPassTexture { id: tex0; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: tex1; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: tex2; format: RenderPassTexture.RGBA16F }
// Pass 1: Render scene
RenderPass {
id: scenePass
commands: [
ColorAttachment { target: tex0 },
DepthStencilAttachment { }
]
}
// Pass 2: Process tex0 -> tex1
RenderPass {
id: process1
materialMode: RenderPass.OriginalMaterial
commands: [
ColorAttachment { target: tex1 }
]
}
Model {
layers: ContentLayer.Layer10
geometry: PlaneGeometry { }
materials: CustomMaterial {
property TextureInput input: TextureInput {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: scenePass
}
}
}
fragmentShader: "effect1.frag"
}
}
// Pass 3: Process tex1 -> tex2
RenderPass {
id: process2
commands: [
ColorAttachment { target: tex2 },
RenderablesFilter { layerMask: ContentLayer.Layer11 }
]
}
Model {
layers: ContentLayer.Layer11
geometry: PlaneGeometry { }
materials: CustomMaterial {
property TextureInput input: TextureInput {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: process1
}
}
}
fragmentShader: "effect2.frag"
}
}
// Display final result
SimpleQuadRenderer {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: process2
}
}
}
}Pipeline State Control
The PipelineStateOverride command provides detailed control over graphics pipeline state, allowing customization of depth testing, blending, culling, and more.
Depth Testing and Writing
Control how depth values are tested and written:
PipelineStateOverride {
depthTestEnabled: true
depthWriteEnabled: true
depthFunction: PipelineStateOverride.LessOrEqual
}The depthFunction property can be:
Never,Less,Equal,LessOrEqualGreater,NotEqual,GreaterOrEqual,Always
Blending
Enable and configure blending for transparency:
PipelineStateOverride {
blendEnabled: true
// Uses default blend mode (source alpha blending)
}For multiple render targets, use per-target blend states. PipelineStateOverride exposes the per-attachment value-type properties targetBlend0 through targetBlend7 (of type renderTargetBlend) and the blend factor and operation enums are in the RenderTargetBlend namespace:
PipelineStateOverride {
targetBlend0.enable: true
targetBlend0.srcColor: RenderTargetBlend.SrcAlpha
targetBlend0.dstColor: RenderTargetBlend.OneMinusSrcAlpha
targetBlend0.opColor: RenderTargetBlend.Add
targetBlend1.enable: false // No blending for attachment 1
}Culling
Control face culling:
PipelineStateOverride {
cullMode: PipelineStateOverride.Back // Override material's cull mode to Back
}Setting cullMode here overrides the value the material would otherwise specify for this pass. Options: None (no culling), Front (cull front faces), Back (cull back faces).
Wireframe Rendering
Render geometry as wireframes:
PipelineStateOverride {
polygonMode: PipelineStateOverride.Line
cullMode: PipelineStateOverride.None // Show both sides
}The polygonMode can be Fill (default) or Line (wireframe).
Scissor Rectangles
Limit rendering to a rectangular region:
PipelineStateOverride {
usesScissor: true
scissor: Qt.rect(100, 100, 400, 300) // x, y, width, height
}Viewport Control
Override the viewport:
PipelineStateOverride {
viewport: Qt.rect(0, 0, 800, 600)
}Complete Example: Wireframe Overlay
This example renders a scene normally, then overlays a wireframe version:
View3D {
renderOverrides: View3D.DisableInternalPasses
RenderPassTexture { id: color; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: depth; format: RenderPassTexture.Depth24Stencil8 }
// Solid pass
RenderPass {
id: solidPass
clearColor: "black"
commands: [
ColorAttachment { target: color },
DepthTextureAttachment { target: depth },
RenderablesFilter {
layerMask: ContentLayer.Layer0
renderableTypes: RenderablesFilter.Opaque
}
]
}
// Wireframe overlay
RenderPass {
id: wirePass
renderTargetFlags: RenderPass.PreserveColorContents |
RenderPass.PreserveDepthStencilContents
commands: [
ColorAttachment { target: color },
DepthTextureAttachment { target: depth },
PipelineStateOverride {
polygonMode: PipelineStateOverride.Line
depthTestEnabled: true
depthWriteEnabled: false
blendEnabled: true
},
RenderablesFilter { layerMask: ContentLayer.Layer0 }
]
}
SimpleQuadRenderer {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: wirePass
}
}
}
PerspectiveCamera { z: 300 }
DirectionalLight { }
Model {
source: "#Sphere"
layers: ContentLayer.Layer0
materials: PrincipledMaterial {
baseColor: "blue"
metalness: 0.5
roughness: 0.3
}
}
}Augment Shaders for Multiple Render Targets
When using RenderPass.AugmentMaterial mode, you provide an augment shader that injects custom code into the material's fragment shader. This is particularly useful for deferred rendering where you need to output material data to multiple render targets (MRT).
The MAIN_FRAGMENT_AUGMENT Function
Your augment shader file must define a MAIN_FRAGMENT_AUGMENT() function:
void MAIN_FRAGMENT_AUGMENT()
{
// Your custom shader code here
}This function is called during the fragment shader after material calculations are complete, giving you access to material properties and the ability to write to custom outputs.
Available Built-in Variables
Inside MAIN_FRAGMENT_AUGMENT(), the engine substitutes a set of macros that expose material pipeline data. Only the macros listed below are part of the augment shader API:
| Macro | Type | Description |
|---|---|---|
BASE_COLOR | vec4 | Material base color (linear color space, after material processing). |
METALNESS | float | Material metalness in the range 0.0 to 1.0. |
ROUGHNESS | float | Material roughness in the range 0.0 to 1.0. |
WORLD_NORMAL | vec3 | World-space surface normal (post normal-mapping). |
WORLD_TANGENT | vec3 | World-space tangent vector. |
WORLD_BINORMAL | vec3 | World-space binormal vector. |
DIFFUSE_LIGHT | vec3 | Accumulated diffuse light contribution. |
SPECULAR_LIGHT | vec3 | Accumulated specular light contribution. |
EMISSIVE_LIGHT | vec3 | Material emissive contribution. |
F0 | vec3 | Fresnel reflectance at normal incidence. |
F90 | vec3 | Fresnel reflectance at grazing incidence. |
Note: Some examples (including the deferred-rendering one below) read the world-space fragment position via qt_varWorldPos. This is the engine's underlying varying name, not an augment-shader macro, and falls into the same semi-public category as the .glsllib files described in Built-in Shader Facilities: it works in practice but is not guaranteed to remain stable across releases.
Writing to Named Outputs
Color attachments in your render pass can have names that correspond to output variables in your shader:
RenderPass {
commands: [
ColorAttachment { target: tex0; name: "GBUFFER0" },
ColorAttachment { target: tex1; name: "GBUFFER1" },
ColorAttachment { target: tex2; name: "GBUFFER2" }
]
}In your augment shader:
void MAIN_FRAGMENT_AUGMENT()
{
GBUFFER0 = vec4(...); // Writes to first attachment
GBUFFER1 = vec4(...); // Writes to second attachment
GBUFFER2 = vec4(...); // Writes to third attachment
}Qt Quick 3D supports up to 4 simultaneous color attachments (GBUFFER0 through GBUFFER3).
Complete Augment Shader Example
Here's a complete example for a deferred rendering G-buffer pass:
// gbuffer_augment.glsl
void MAIN_FRAGMENT_AUGMENT()
{
// Get material properties
vec3 baseColor = BASE_COLOR.rgb;
float metalness = METALNESS;
float roughness = ROUGHNESS;
vec3 worldNormal = normalize(WORLD_NORMAL);
vec3 worldPos = qt_varWorldPos;
// GBuffer 0: Albedo (RGB) + Metalness (A)
GBUFFER0 = vec4(baseColor, metalness);
// GBuffer 1: World Normal (RGB) + Roughness (A)
// Encode normal from [-1,1] to [0,1] for storage
GBUFFER1 = vec4(worldNormal * 0.5 + 0.5, roughness);
// GBuffer 2: World Position
GBUFFER2 = vec4(worldPos, 1.0);
}Used with a render pass (RenderPassTexture instances are declared as direct children of the enclosing View3D and referenced by id):
View3D {
RenderPassTexture { id: gbuffer0; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: gbuffer1; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: gbuffer2; format: RenderPassTexture.RGBA16F }
RenderPass {
id: gbufferPass
materialMode: RenderPass.AugmentMaterial
augmentShader: "gbuffer_augment.glsl"
commands: [
ColorAttachment { target: gbuffer0; name: "GBUFFER0" },
ColorAttachment { target: gbuffer1; name: "GBUFFER1" },
ColorAttachment { target: gbuffer2; name: "GBUFFER2" },
DepthStencilAttachment { }
]
}
}Preserving Material Behavior
The augment shader runs in addition to the normal material pipeline, not instead of it. This means:
- The material's textures, properties, and calculations still occur
- You're adding extra outputs, not replacing the primary color output
- The original material's RGBA output is still written to the first color attachment unless overridden
If you only need to output custom data and don't need the standard material calculations, consider using RenderPass.OverrideMaterial instead.
When to Use Augment vs Override
Use AugmentMaterial when:
- You need material properties (metalness, roughness, normals) for G-buffers
- You want to leverage existing material features like texture mapping
- You need multiple render targets with material data
Use OverrideMaterial when:
- You need identical behavior for all objects (depth prepass, shadow maps)
- You don't need per-material properties
- You want maximum performance by bypassing material calculations
Built-in Shader Facilities
Augment shaders and custom materials used in render passes have access to Qt Quick 3D's built-in shader infrastructure through an include system. These shader library files (.glsllib) provide functionality for lighting, shadows, tonemapping, and more.
Include Syntax:
Use \#include directives in your shader code to import functionality:
#include "tonemapping.glsllib"
#include "lightsData.glsllib"
#include "shadowMapping.glsllib"
#include "funcprocessPunctualLighting.glsllib"
void MAIN()
{
// Use included functions
vec3 color = qt_tonemap(hdrColor);
}Available Shader Libraries:
These shader libraries are located in the engine at src/runtimerender/res/effectlib/ and are considered semi-public: they are usable in user shaders but do not have the same binary compatibility guarantees as the rest of Qt's public API.
| Library | Description |
|---|---|
tonemapping.glsllib | Provides qt_tonemap() function for HDR to LDR conversion using the built-in tonemapping algorithm |
lightsData.glsllib | Contains scene lighting information (light positions, colors, directions, etc.) that can be accessed in custom lighting calculations |
shadowMapping.glsllib | Provides functions for sampling from the default shadow maps, enabling custom materials to receive shadows |
funcprocessPunctualLighting.glsllib | Contains qt_processPunctualLighting() and other built-in lighting functions for standard PBR lighting calculations |
sampleProbe.glsllib | Functions for sampling image-based lighting probes (qt_sampleDiffuse(), qt_sampleGlossyPrincipled()) |
Example: Custom Lighting with Built-in Functions
Here's an example fragment shader using the built-in lighting facilities:
#include "lightsData.glsllib"
#include "funcprocessPunctualLighting.glsllib"
#include "tonemapping.glsllib"
#include "sampleProbe.glsllib"
void MAIN()
{
vec3 worldPos = ...; // From G-buffer or varying
vec3 normal = ...;
vec3 viewDir = normalize(CAMERA_POSITION - worldPos);
vec3 baseColor = ...;
float roughness = ...;
float metalness = ...;
vec3 F0 = mix(vec3(0.04), baseColor, metalness);
vec3 diffuseAccum = vec3(0.0);
vec3 specAccum = vec3(0.0);
// Use built-in punctual lighting (directional, point, spot lights)
qt_processPunctualLighting(diffuseAccum,
specAccum,
baseColor,
worldPos,
normal,
viewDir,
vec3(1.0), // specularAmount
vec3(1.0), // specularTint
roughness,
metalness,
F0,
vec3(1.0)); // F90
// Add image-based lighting
vec4 probeDiffuse = vec4(baseColor, 1.0) * qt_sampleDiffuse(normal);
vec4 probeSpecular = qt_sampleGlossyPrincipled(normal, viewDir, F0, roughness);
diffuseAccum += probeDiffuse.rgb;
specAccum += probeSpecular.rgb;
vec3 color = diffuseAccum + specAccum;
// Apply tonemapping
FRAGCOLOR = vec4(qt_tonemap(color), 1.0);
}Note: These shader libraries are semi-public API. While they are stable and intended for use in custom shaders, Qt does not guarantee that their internal implementation or available functions will remain unchanged between releases. However, commonly used functions like qt_tonemap() and qt_processPunctualLighting() are unlikely to change significantly.
Advanced Example: Deferred Rendering
Deferred rendering is a technique where geometry information is rendered to multiple textures (called a G-buffer or geometry buffer) in a first pass, and lighting calculations are performed in a second pass using the stored geometry data. This approach is particularly efficient when you have many lights, as each pixel is shaded only once regardless of the number of lights.
Deferred Rendering Architecture
The deferred rendering pipeline consists of two main passes:
- Geometry Pass (G-Buffer Pass): Renders scene geometry to multiple render targets, storing material properties such as albedo, normals, roughness, metalness, and world position.
- Lighting Pass: Renders a full-screen quad that samples the G-buffers and performs lighting calculations for each pixel based on the stored geometry data.
G-Buffer Pass Implementation
First, define a G-buffer pass that outputs material data to multiple render targets:
GBufferPass.qml: The G-buffer render targets are exposed as required properties so the enclosing View3D supplies them and can read their outputs:
import QtQuick
import QtQuick3D
RenderPass {
id: gbufferPass
clearColor: Qt.rgba(0.0, 0.0, 0.0, 0.0)
property alias layerMask: filter.layerMask
// Provided by the View3D that uses this pass
required property RenderPassTexture gbuffer0 // rgb: baseColor, a: metalness
required property RenderPassTexture gbuffer1 // rgb: normal, a: roughness
required property RenderPassTexture gbuffer2 // rgb: world pos, a: spare
required property RenderPassTexture depthTexture
materialMode: RenderPass.AugmentMaterial
augmentShader: "gbuffer_augment.glsl"
commands: [
ColorAttachment { target: gbufferPass.gbuffer0; name: "GBUFFER0" },
ColorAttachment { target: gbufferPass.gbuffer1; name: "GBUFFER1" },
ColorAttachment { target: gbufferPass.gbuffer2; name: "GBUFFER2" },
DepthTextureAttachment { target: gbufferPass.depthTexture },
RenderablesFilter {
id: filter
renderableTypes: RenderablesFilter.Opaque
}
]
}gbuffer_augment.glsl:
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);
}The augment shader accesses material properties computed by the material pipeline and writes them to the three G-buffer attachments. Normals are encoded from [-1,1] to [0,1] range for storage.
Lighting Pass Implementation
The lighting pass renders a full-screen quad that samples the G-buffers and computes lighting:
// Lighting pass model (full-screen quad)
Model {
id: deferredLightingQuad
layers: ContentLayer.Layer13 // Dedicated layer for lighting quad
geometry: PlaneGeometry {
plane: PlaneGeometry.XY // Quad in screen space
}
materials: CustomMaterial {
// Texture inputs for G-buffers
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"
}
}
// Lighting pass renders the quad to main output
RenderPass {
id: deferredLightingPass
materialMode: RenderPass.OriginalMaterial
commands: [
ColorAttachment { target: mainColorTexture },
DepthStencilAttachment { },
RenderablesFilter { layerMask: ContentLayer.Layer13 }
]
}The lighting vertex shader (lighting.vert) creates a full-screen quad in normalized device coordinates, and the fragment shader (lighting.frag) samples the G-buffers and performs lighting calculations.
Complete Integration
Here's how to integrate both passes in a View3D:
View3D {
renderOverrides: View3D.DisableInternalPasses
// Main output texture
RenderPassTexture { id: mainColorTexture; format: RenderPassTexture.RGBA16F }
// Shared depth texture
RenderPassTexture { id: mainDepthStencilTexture; format: RenderPassTexture.Depth24Stencil8 }
// G-buffer render targets
RenderPassTexture { id: gbuffer0Tex; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: gbuffer1Tex; format: RenderPassTexture.RGBA16F }
RenderPassTexture { id: gbuffer2Tex; format: RenderPassTexture.RGBA16F }
// G-buffer pass
GBufferPass {
id: gbufferPass
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
gbuffer0: gbuffer0Tex
gbuffer1: gbuffer1Tex
gbuffer2: gbuffer2Tex
depthTexture: mainDepthStencilTexture
}
// Expose G-buffer outputs
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
}
// Lighting pass (defined above)
// Display final result
SimpleQuadRenderer {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: deferredLightingPass
attachmentSelector: RenderOutputProvider.Attachment0
}
}
}
// Scene objects
Model {
layers: ContentLayer.Layer0
source: "#Sphere"
materials: PrincipledMaterial {
baseColor: "red"
metalness: 0.5
roughness: 0.3
}
}
// Camera and lights
PerspectiveCamera { z: 300 }
DirectionalLight { eulerRotation.x: -45 }
}Rendering Flow
The rendering proceeds as follows:
- G-buffer Pass: Scene objects on Layer0 and Layer1 are rendered. For each object, the augment shader writes albedo, normals, roughness, metalness, and position to three color attachments. Depth is written to the shared depth texture.
- Lighting Pass: The full-screen quad on Layer13 is rendered. Its custom material samples the three G-buffer textures and the depth texture, reconstructs the scene information, and performs lighting calculations (directional lights, image-based lighting, etc.) to produce the final lit color.
- Display: The result of the lighting pass is displayed via SimpleQuadRenderer.
Advantages and Limitations
Advantages:
- Efficient with many lights (each pixel lit once)
- Lighting complexity independent of scene complexity
- Easy to implement screen-space effects
- Decouples geometry and lighting passes
Limitations:
- Higher memory bandwidth due to G-buffer reads/writes
- No hardware MSAA (requires alternative anti-aliasing)
- Transparency requires separate forward pass
- More complex pipeline to set up and maintain
For a complete working example, see Qt Quick 3D - User Passes Example.
Complete Rendering Pipeline Example
A realistic custom rendering pipeline often needs to combine multiple pass types: opaque geometry, skybox background, 2D overlays, and transparent objects. Here's a complete example showing how to organize these using SubRenderPass for hierarchical composition:
View3D {
renderOverrides: View3D.DisableInternalPasses
environment: SceneEnvironment {
backgroundMode: SceneEnvironment.SkyBox
lightProbe: Texture {
textureData: ProceduralSkyTextureData { }
}
}
RenderPassTexture {
id: mainColorTexture
format: RenderPassTexture.RGBA16F
}
RenderPassTexture {
id: mainDepthStencilTexture
format: RenderPassTexture.Depth24Stencil8
}
// Main pass orchestrates the complete render path:
// 1. Opaque geometry (deferred)
// 2. Skybox background
// 3. 2D UI overlays
// 4. Transparent objects (forward)
RenderPass {
id: mainColorPass
clearColor: "black"
renderTargetFlags: RenderPass.PreserveDepthStencilContents
commands: [
ColorAttachment { target: mainColorTexture },
DepthTextureAttachment { target: mainDepthStencilTexture },
RenderablesFilter {
renderableTypes: RenderablesFilter.None // Parent doesn't render
},
// Sub-pass 1: Deferred lighting
SubRenderPass {
renderPass: RenderPass {
id: deferredLightingPass
materialMode: RenderPass.OriginalMaterial
commands: [
PipelineStateOverride {
depthWriteEnabled: false
depthTestEnabled: false
},
RenderablesFilter { layerMask: ContentLayer.Layer13 }
]
}
},
// Sub-pass 2: Skybox (behind everything)
SubRenderPass {
renderPass: RenderPass {
passMode: RenderPass.SkyboxPass
commands: [
PipelineStateOverride {
depthTestEnabled: true
depthWriteEnabled: false
}
]
}
},
// Sub-pass 3: 2D Qt Quick content
SubRenderPass {
renderPass: RenderPass {
passMode: RenderPass.Item2DPass
}
},
// Sub-pass 4: Transparent objects (forward rendering)
SubRenderPass {
renderPass: RenderPass {
materialMode: RenderPass.OriginalMaterial
commands: [
RenderablesFilter {
renderableTypes: RenderablesFilter.Transparent
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
},
PipelineStateOverride {
blendEnabled: true
depthTestEnabled: true
depthWriteEnabled: false
}
]
}
}
]
}
// G-buffer pass (referenced by deferred lighting)
GBufferPass {
id: gbufferPass
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
depthTexture: mainDepthStencilTexture
}
// Full-screen quad for deferred lighting
Model {
layers: ContentLayer.Layer13
geometry: PlaneGeometry { plane: PlaneGeometry.XY }
materials: CustomMaterial {
property TextureInput gbuffer0: TextureInput {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: gbufferPass
attachmentSelector: RenderOutputProvider.Attachment0
}
}
}
// ... other G-buffer inputs
shadingMode: CustomMaterial.Unshaded
fragmentShader: "lighting.frag"
vertexShader: "lighting.vert"
}
}
// Display final result
SimpleQuadRenderer {
texture: Texture {
textureProvider: RenderOutputProvider {
textureSource: RenderOutputProvider.UserPassTexture
renderPass: mainColorPass
}
}
}
// Opaque 3D content
Model {
layers: ContentLayer.Layer0
source: "#Sphere"
materials: PrincipledMaterial { baseColor: "red" }
}
// Transparent 3D content
Model {
layers: ContentLayer.Layer1
source: "#Cone"
materials: PrincipledMaterial {
baseColor: Qt.rgba(0.0, 1.0, 0.0, 0.5)
alphaMode: PrincipledMaterial.Blend
}
}
// 2D content in 3D space
Node {
x: -200
y: 100
Item {
Button { text: "Click Me!" }
Rectangle {
color: "blue"
width: 50; height: 50
}
}
}
PerspectiveCamera { z: 300 }
DirectionalLight { eulerRotation.x: -45 }
}Key Concepts
SubRenderPass for Hierarchical Organization:
The main pass uses SubRenderPass commands to execute child passes in sequence. The parent pass itself doesn't render anything (RenderablesFilter.None), it just orchestrates the child passes. This provides a clear structure and allows depth buffer sharing across all sub-passes.
Pass Modes:
RenderPass.UserPass(default): Custom rendering with your geometry and materialsRenderPass.SkyboxPass: Renders the environment skybox from SceneEnvironmentRenderPass.Item2DPass: Renders 2D Qt Quick content embedded in the 3D scene
Render Order:
- Opaque geometry rendered to G-buffer
- Deferred lighting applied to full-screen quad
- Skybox rendered behind geometry (depth test enabled, depth write disabled)
- 2D UI overlays rendered on top
- Transparent objects rendered last with blending
Depth Buffer Sharing:
The mainDepthStencilTexture is shared across passes using PreserveDepthStencilContents. This ensures skybox renders behind geometry and transparent objects test against opaque geometry correctly.
Item2D Content:
Qt Quick 2D items (Button, Rectangle, Text, etc.) placed in Node objects are rendered by RenderPass.Item2DPass. These items are positioned in 3D space but rendered as 2D overlays that can receive mouse/touch input.
Performance Considerations
User-defined render passes provide maximum control but require careful consideration of performance implications.
Texture Format Choices
Choose texture formats based on your needs:
| Format | Size per Pixel | Use Case |
|---|---|---|
| RGBA8 | 4 bytes | Final output, simple color buffers |
| RGBA16F | 8 bytes | HDR content, intermediate buffers, normals |
| RGBA32F | 16 bytes | High precision calculations, positions |
| R16F | 2 bytes | Single-channel HDR (depth, AO, etc.) |
For a 1920x1080 framebuffer:
- RGBA8: ~8 MB
- RGBA16F: ~16 MB
- RGBA32F: ~32 MB
- Three RGBA16F G-buffers: ~48 MB
Recommendation: Use RGBA16F for intermediate buffers and RGBA8 or R8 where sufficient.
Deferred vs Forward Rendering
| Aspect | Deferred Rendering | Forward Rendering |
|---|---|---|
| Many lights | Efficient (O(lights + pixels)) | Expensive (O(lights * objects)) |
| Memory bandwidth | High (G-buffer reads/writes) | Lower |
| Transparency | Requires separate pass | Natural support |
| MSAA | Not directly supported | Hardware MSAA works |
| Setup complexity | More complex | Simpler |
Use deferred rendering when:
- You have many lights (10+)
- Screen-space effects are important
- Scene is mostly opaque
Use forward rendering when:
- Few lights (<5)
- Lots of transparency
- Memory bandwidth is constrained
- Simpler pipeline is preferable
Pass Ordering Optimization
Render passes execute in the order they are encountered. Optimize by:
- Rendering opaque geometry before transparent geometry
- Using depth prepass when beneficial (reduces overdraw in complex scenes)
- Minimizing render target switches
- Reusing depth buffers across passes when possible
Render Target Flags
The renderTargetFlags property controls memory behavior:
RenderPass {
// First pass: write new content
renderTargetFlags: 0 // Default: clear render targets
}
RenderPass {
// Second pass: add to existing content
renderTargetFlags: RenderPass.PreserveColorContents |
RenderPass.PreserveDepthStencilContents
}
RenderPass {
// Depth not needed after this pass
renderTargetFlags: RenderPass.DoNotStoreDepthStencilContents
}PreserveColorContents/PreserveDepthStencilContents: Keep existing data (e.g., for multi-pass rendering to same target).
DoNotStoreDepthStencilContents: Hint that depth/stencil can be discarded (on some hardware this can improve performance by avoiding memory writes).
When to Use User Passes
Consider using user render passes when:
- Implementing deferred rendering
- Creating complex multi-pass effects
- Needing explicit control over render order
- Implementing custom rendering techniques
- Building screen-space effects that need geometry data
Avoid user passes when:
- Default rendering meets your needs
- You only need post-processing (use Effect instead)
- You only need custom material shaders (use CustomMaterial instead)
- Performance is critical and extra passes would be wasteful
Common Patterns and Use Cases
User render passes enable many advanced rendering techniques. Here are some common patterns:
Deferred Shading/Lighting
Store geometry attributes in G-buffers and perform lighting in screen space. Covered in detail in Advanced Example: Deferred Rendering.
Edge Detection and Outlining
Render scene normally, then apply edge detection in a second pass:
// Pass 1: Render scene with normals/depth
RenderPass {
id: scenePass
commands: [
ColorAttachment { target: colorTex },
DepthTextureAttachment { target: depthTex }
]
}
// Pass 2: Edge detection using depth discontinuities
RenderPass {
id: edgePass
commands: [
ColorAttachment { target: outlineTex },
RenderablesFilter { layerMask: ContentLayer.Layer10 }
]
}
Model {
layers: ContentLayer.Layer10
geometry: PlaneGeometry { }
materials: CustomMaterial {
property TextureInput depthInput: TextureInput {
// depthProvider is the id of a RenderOutputProvider that exposes
// depthTex as a sampleable texture (see "Render Output Provider"
// earlier in this page).
texture: Texture { textureProvider: depthProvider }
}
fragmentShader: "edge_detect.frag"
// Shader samples depth, computes gradients, draws edges
}
}Custom Post-Processing Chains
Chain multiple post-processing effects together by feeding each pass's output into the next via RenderOutputProvider. See Pass Chaining Example for a worked example of a multi-stage chain (scenePass → process1 → process2 → display).
Selective Wireframe Overlay
Render some objects solid and others as wireframe overlays. See the example in Working with Layers.
Debug Visualization
Create debug passes that visualize normals, depth, or other data:
// Normal visualization pass
RenderPass {
materialMode: RenderPass.OverrideMaterial
overrideMaterial: CustomMaterial {
fragmentShader: "debug_normals.frag"
// FRAGCOLOR = vec4(normalize(NORMAL) * 0.5 + 0.5, 1.0);
}
commands: [
ColorAttachment { target: debugTex }
]
}Custom Shadow Mapping
Implement custom shadow mapping with explicit control:
// Shadow map pass (render from light's perspective)
RenderPass {
id: shadowPass
materialMode: RenderPass.OverrideMaterial
overrideMaterial: CustomMaterial {
fragmentShader: "depth_only.frag"
}
commands: [
DepthTextureAttachment { target: shadowMapTex }
]
}
// Main pass using shadow map
RenderPass {
id: mainPass
commands: [
ColorAttachment { target: colorTex },
DepthStencilAttachment { }
]
}
// Materials in main pass sample shadowMapTex for shadow testingImportant Considerations
When working with user render passes, keep these important points in mind:
Shadow Handling
User render passes do not automatically include Qt Quick 3D's internal shadow rendering. If you disable internal passes and need shadows, you must:
- Implement your own shadow mapping passes
- Render the scene from light's perspective to a depth texture
- Sample the shadow map in your lighting calculations
Alternatively, for simpler cases, you may not need shadows or can use pre-baked shadow maps.
HDR and Tonemapping
When using floating-point render targets (RGBA16F, RGBA32F), your rendering is in linear HDR space. You must apply tonemapping in your final display pass to convert to displayable LDR:
CustomMaterial {
fragmentShader: "tonemap.frag"
}// In tonemap.frag
vec3 tonemap(vec3 hdr) {
// Simple Reinhard tonemapping
return hdr / (hdr + vec3(1.0));
}
void MAIN() {
vec3 hdrColor = texture(hdrInput, UV0).rgb;
FRAGCOLOR = vec4(tonemap(hdrColor), 1.0);
}Qt Quick 3D provides qt_tonemap() function in shaders that can be used for this purpose.
Depth Texture Generation
When you need depth as a texture (for effects like depth-of-field), use DepthTextureAttachment instead of DepthStencilAttachment:
RenderPassTexture {
id: depthTex
format: RenderPassTexture.Depth24Stencil8
}
RenderPass {
commands: [
ColorAttachment { target: colorTex },
DepthTextureAttachment { target: depthTex }
// depthTex can now be sampled in shaders
]
}Clear Values and Render Target Management
Each pass can specify clear values:
RenderPass {
clearColor: Qt.rgba(0.0, 0.0, 0.0, 0.0)
depthClearValue: 1.0
stencilClearValue: 0
}When a pass doesn't preserve contents (default), render targets are cleared to these values before rendering. When PreserveColorContents or PreserveDepthStencilContents is set, existing content is kept and clear values are ignored.
Layer Organization Best Practices
Organize your layers logically:
- Layer0-2: Main scene objects
- Layer3-4: Transparent objects (separate pass)
- Layer10+: Full-screen quads for post-processing
- Layer15+: UI/debug overlays
Document your layer usage in comments and be consistent across your application.
Shader Compatibility
Augment shaders and custom materials used in render passes must be compatible with Qt Quick 3D's shader infrastructure:
- Use GLSL-compatible syntax
- Include appropriate
\#includedirectives for Qt Quick 3D functions - Be aware of available built-in variables
- Test on all target platforms (OpenGL, Vulkan, Metal, D3D)
Multiple Render Targets Limitations
When using multiple render targets (MRT):
- Maximum of 4 color attachments
- All attachments must have the same dimensions
- Blend state can be specified per-attachment via PipelineStateOverride
- Not all hardware supports MRT (check device capabilities)
Transparency
Transparent objects are challenging with deferred rendering. Common approaches:
- Forward pass for transparent: Render opaque geometry deferred, transparent geometry in a separate forward pass
- Separate transparent G-buffer: Render transparent geometry to a separate set of G-buffers with blending enabled
- Weighted blended order-independent transparency: Use specialized OIT techniques
For most cases, a separate forward pass for transparent objects is simplest.
API Reference
The following table provides a complete reference of all types related to user render passes:
| Feature | QML Type | Description |
|---|---|---|
| Main render pass definition | RenderPass | Defines a rendering pass with commands and material mode |
| Render target textures | RenderPassTexture | Texture used as render target (color or depth/stencil) |
| Texture output provider | RenderOutputProvider | Exposes render pass output as texture input |
| Layer constants | ContentLayer | Singleton providing layer filtering constants |
| Color output | ColorAttachment | Specifies a color render target |
| Depth/stencil (default) | DepthStencilAttachment | Uses implicit depth/stencil buffer |
| Depth/stencil (texture) | DepthTextureAttachment | Uses explicit depth texture |
| Object filtering | RenderablesFilter | Filters objects by layer and type |
| Pipeline state | PipelineStateOverride | Overrides graphics pipeline state |
| Nested pass execution | SubRenderPass | Executes another render pass |
| Shader defines | AddDefine | Adds shader preprocessor define |
| Per-target blend state | renderTargetBlend | Blend configuration for MRT |
| Display helper | SimpleQuadRenderer | Renders final output to View3D |
Related Types
| Type | Description |
|---|---|
| CustomMaterial | Custom material with vertex/fragment shaders |
| Effect | Post-processing effects |
| View3D | 3D view with renderOverrides property |
| Model | 3D model with layers property |
Examples
- Qt Quick 3D - User Passes Example: Complete deferred rendering example
See Also
- Programmable Materials, Effects, Geometry, and Texture data: Overview of Qt Quick 3D customization features
- Qt Quick 3D Architecture: Understanding the rendering pipeline
© 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.