このページでは

Qt Quick 3D - ユーザーパスの例

Qt Quick 3D でのカスタムレンダーパスの作成方法を解説します。

カスタムユーザーパスを使用してレンダリングされた3Dシーン

}

「ユーザーパス」の例では、Qt Quick 3D でのカスタムレンダーパスの作成方法を示します。この例では、複数のユーザー定義レンダーパスを使用してディファードライティングのレンダリングパイプラインを実装し、不透明ジオメトリ、スカイボックス、シーンに埋め込まれた 2D アイテム、および透明ジオメトリといった、レンダリングシーケンス全体を処理する方法を示しています。

内部レンダリングパスの無効化

デフォルトでは、Qt Quick 3D は一連の内部レンダーパスを使用して 3D シーンをレンダリングします。場合によっては、これらの内部パスを無効にし、ユーザー定義のレンダーパスを使用して独自のレンダリングパイプラインを実装したいこともあるでしょう。

内部レンダリングパスを無効にするには、View3D のrenderOverrides プロパティをView3D.DisableInternalPasses に設定します。

View3D {
    id: view3D
    anchors.fill: parent
    renderOverrides: View3D.DisableInternalPasses
    environment: ExtendedSceneEnvironment {
        lightProbe: Texture {
            textureData: ProceduralSkyTextureData {
            }
        }
        backgroundMode: SceneEnvironment.SkyBox
    }

内部レンダリングパスを無効にした場合、画面に何かを表示するためには、View3D に対してメインカラーパスの結果を提供する必要があります。

ジオメトリバッファパス

この例では、最初のカスタム・レンダリング・パスはジオメトリ・バッファ(G-バッファ)パスであり、シーンのジオメトリを複数のレンダリング・ターゲットにレンダリングし、各ターゲットに異なるマテリアル・プロパティを格納します。提供されている例は、Qt Quick の3Dマテリアルが提供する完全なマテリアル・プロパティの一部であり、基本的なディファード・ライティングの実装に必要なプロパティに焦点を当てています。

当社のRenderPass は、GBufferPass.qml で定義されています:

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

ここでは、3つのカラーアタッチメントと1つの深度アタッチメントが定義されています。このパスには3つのテクスチャが必要であり、これらはRenderPass 内でRenderPassTexture オブジェクトとして定義されています。これら3つのRenderPassTexturesは、パスのカラーアタッチメントのターゲットとして使用され、深度アタッチメントにはパス外部から提供される深度テクスチャが使用されます。

RenderPass 自体はAugmentMaterial モードに設定されており、これは、レンダリングされるオブジェクトのマテリアルに追加のシェーダーコードを適用することを意味します。この拡張シェーダーは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);
}

ここでは、ベースカラー、メタリティ、worldNormal、ラフネス、およびワールド位置が、G-バッファの3つのカラーアタッチメントにどのように格納されているかがわかります。

レンダリングパイプラインで G-buffer パスを実際に使用するには、Main.qml 内でそのインスタンスを作成し、必要な深度テクスチャを指定する必要があります。

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
}

レンダリングされたG-バッファテクスチャへの参照を提供するために、3つのRenderOutputProvider インスタンスが作成されます。これらは、後続のライティングパスで使用されます。

G-バッファ・パスのlayerMask プロパティは、ContentLayer.Layer0およびContentLayer.Layer1上に存在するオブジェクトのみをレンダリングするように設定されています。これにより、layers プロパティを適切に設定することで、G-バッファ・パスでレンダリングされるオブジェクトを制御できるようになります。

メインカラーパスとサブレンダリングパス

この例では、単一のフラットなレンダリングパスではなく、メインカラーテクスチャと深度テクスチャを所有し、一連のSubRenderPass 子オブジェクトを通じてすべてのレンダリングを調整する複合的なmainColorPass を使用しています。

各SubRenderPass は、外側のパスと同じレンダリングターゲットを共有し、順番に実行されます。これにより、各ステージが前のステージの結果に積み重ねていく、階層化されたレンダリングパイプラインを簡単に構築できます。

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

外側のパスでは、renderableTypes:RenderablesFilter.None を設定することで、親パス内では直接レンダリングが行われないようにします。すべてのレンダリングはサブパスに委譲されます。PreserveDepthStencilContents フラグを設定することで、G-バッファパスによって書き込まれた深度値がすべてのサブパスで利用可能になります。

ディファードライティング・サブパス

最初のサブパスは、ディファードライティングの計算を実行します。このサブパスは、フルスクリーンのdeferredLightingQuad モデルをレンダリングし、G-バッファのテクスチャをサンプリングして、各ピクセルごとにライティングを評価します。

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

deferredLightingQuad は、G-バッファパスからは不可視であり、このサブパスによってのみレンダリングされるよう、ContentLayer.Layer13 上に配置されます。

PipelineStateOverride は、クワッドに対する深度書き込みと深度テストの両方を無効にします。Gバッファパスでは、シーンのジオメトリに対してすでに正しい深度が書き込まれているため、フルスクリーンのクワッドは深度を変更したりテストしたりしてはなりません。

スカイボックス・サブパス

2番目のサブパスでは、特別な「RenderPass.SkyboxPass 」パスモードを使用して、シーン環境のスカイボックスをレンダリングします。Qt Quick 3Dは、「SceneEnvironment 」の「lightProbe 」および「backgroundMode 」設定を使用して、スカイボックスのジオメトリを描画します。

PipelineStateOverride を有効にすると深度テストが行われるため、スカイボックスはシーンのジオメトリの背後に正しく隠されます。一方、スカイボックスは「無限遠」に位置し、ジオメトリを遮ってはならないため、深度書き込みは無効になっています。

透明オブジェクトのサブパス

透明オブジェクトは、背面から前面への順にソートされたブレンディングが必要であるため、G-バッファに格納することはできません。その代わりに、専用のサブパスを介して、元のマテリアルを使用して最後にレンダリングされます。

シーン内の透明な円錐は、次のように宣言されています:

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

透明サブパスでは、RenderablesFilter を使用して、一致するレイヤー上の透明なレンダラブルのみを選択し、PipelineStateOverride により、深度テストを有効に保ちつつアルファブレンディングを有効にすることで、透明オブジェクトが不透明なジオメトリに対して正しくソートされるようにします。

透明オブジェクトは、ブレンドが行われる前に深度バッファが完全に埋まるよう、すべての不透明パスの後にレンダリングする必要があります。

3Dサブパス内の2Dアイテム

Qt Quick 3D では、Node をコンテナとして使用して、標準のQt Quick 2D アイテムを 3D シーン内に埋め込むことができます。これらのアイテムをカスタムレンダリングパイプラインに含めるには、passMode を使用したサブパスを追加します: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
    }
}

Item2DPass モードは、Qt Quick 3Dに対し、3Dノードの子要素であるすべてのQt Quick アイテムを、既存の3Dコンテンツと合成して現在のレンダリングターゲットにレンダリングするよう指示します。

画面へのレンダリング

最後に、カスタム レンダリング パスの結果を画面に表示するには、View3D のメイン カラー テクスチャが、メイン カラー パスの結果で確実に更新されるようにする必要があります。

SimpleQuadRenderer {
    texture: Texture {
        textureProvider: mainColorPassProvider
    }
}

RenderPassTexture {
    id: mainColorTexture
    format: RenderPassTexture.RGBA16F
}

RenderOutputProvider {
    id: mainColorPassProvider
    textureSource: RenderOutputProvider.UserPassTexture
    renderPass: mainColorPass
    attachmentSelector: RenderOutputProvider.Attachment0
}

SimpleQuadRenderer は、mainColorPass によって生成されたメインカラーテクスチャを、View3D のフレームバッファにブリティッシュするために使用されます。RenderOutputProvider は、mainColorPass の最初のカラーアタッチメントを、SimpleQuadRenderer がサンプリング可能なテクスチャとして公開します。

サンプルプロジェクト @ 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.