このページでは

Qt Quick 3Dにおけるユーザー定義のレンダリングパス

Qt Quick 3Dは、レンダリングの詳細のほとんどを自動的に処理する、3Dレンダリング用の高レベルAPIを提供します。しかし、高度なユースケースでは、アプリケーションがレンダリングパイプラインを完全に制御する必要がある場合があります。ユーザー定義のレンダリングパスを使用すると、アプリケーションは内部のレンダリングパイプラインを無効にし、独自のカスタムパスを定義できるようになります。

ユーザー定義のレンダーパスにより、次のような高度なレンダリング技術が可能になります:

  • ディファードシェーディングおよびライティング
  • マルチパス・レンダリング効果
  • カスタム後処理パイプライン
  • レイヤーベースのフィルタリングを用いた選択的レンダリング
  • スクリーンスペース効果(アンビエントオクルージョン、反射など)
  • カスタムシャドウマッピング技術
  • デバッグ用可視化パス

カスタマイズレベル

Qt Quick 3Dでは、互いに補完し合う3つのレンダリングカスタマイズレベルが用意されており、それぞれが異なるユースケースに適しています:

レベル適用範囲ユースケース
Effectポストプロセッシングシーンのレンダリング後にエフェクトを適用します(ぼかし、カラーグレーディングなど)
CustomMaterialマテリアルごとのシェーダー個々のマテリアルごとにカスタマイズされた頂点シェーダーおよびフラグメントシェーダー
RenderPass (ユーザー・レンダリング・パス)パイプラインの完全な制御ディファードレンダリング、マルチパス、カスタムレンダターゲット

ユーザー・レンダリング・パス(RenderPass )は、デフォルトのレンダリング・パイプラインを補完したり、完全に置き換えたりできる、最も高度な制御機能を提供します。これは、CustomMaterial およびEffect を補完するものです:CustomMaterial は個々のオブジェクトのレンダリング方法をカスタマイズするのに対し、ユーザー・レンダリング・パスはレンダリングの全体的な戦略とアーキテクチャを制御します。

ユーザー・レンダリング・パスの使用

ユーザー・レンダリング・パスは、次の 2 つの方法で使用できます。

内部パスの補完

内部パスを無効にすることなく、デフォルトのレンダリングパイプラインと並行して、カスタムRenderPass オブジェクトを追加できます。これは、Effect やCustomMaterial で後に使用されるテクスチャへのレンダリングや、補助的なレンダリングターゲットの作成に役立ちます。

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
}

内部パスの置き換え

レンダリングパイプラインを完全に制御するには、renderOverrides プロパティを設定してQt Quick 3Dの内部レンダリングを無効にします:

View3D {
    renderOverrides: View3D.DisableInternalPasses

    // Your custom render passes go here
}

内部パスが無効になっている場合、Qt Quick 3Dはデフォルトのレンダリングを一切行いません。つまり、以下の操作を行う必要があります:

  • シーンをレンダリングするために、少なくとも1つのRenderPass を定義する
  • SimpleQuadRenderer や同様の仕組みを介して表示するための最終出力テクスチャを用意する
  • 深度バッファや透明度など、レンダリングに関するすべての側面を処理すること

注:内部パスを無効にすると 、完全な制御が可能になりますが、同時にすべての責任も負うことになります。自動シャドウレンダリング、透明度のソート、環境反射などの機能は、必要に応じてカスタムパスで実装する必要があります。

基本概念

ユーザー定義のレンダリングパスは、いくつかの主要なコンポーネントから構成されます:

RenderPass

RenderPass 型は主要な構成要素です。これは、何がどのようにレンダリングされるかを制御する一連のコマンドを含む、単一のレンダリング操作を定義します。各パスでは以下の操作が可能です:

  • 1つ以上のカラーテクスチャへのレンダリング(最大4つのレンダリングターゲットを同時に使用可能)
  • 深度およびステンシル情報の書き込み
  • レイヤーに基づいて、レンダリングするオブジェクトをフィルタリングする
  • グラフィックスパイプラインの状態(ブレンディング、カリングなど)を上書きする
  • 元のマテリアルを使用する、カスタムシェーダーで拡張する、または完全に上書きする

RenderPassTexture

RenderPassTexture 型は、レンダリングターゲットとして機能するテクスチャを定義します。これらは、さまざまな形式(RGBA8、RGBA16F、RGBA32Fなど)の色テクスチャ、または深度/ステンシルテクスチャです。レンダリングパステクスチャは、あるパスの出力として使用され、後続のパスへのテクスチャ入力としても使用できます。

RenderOutputProvider

RenderOutputProvider 型は、あるパスの出力テクスチャを、マテリアルや他のパスで使用可能なテクスチャ入力として公開することで、レンダリングパスを相互に接続します。これは、後続のパスが先行するパスの結果を読み取る必要があるマルチパスレンダリングにおいて不可欠です。

ContentLayer

ContentLayer シングルトンは、どのオブジェクトをどのパスでレンダリングするかをフィルタリングするために使用されるレイヤー定数(Layer0~Layer23)を提供します。オブジェクトを特定のレイヤーに割り当て、パス内でRenderablesFilter を使用することで、各パスで何がレンダリングされるかを正確に制御できます。

レンダリングコマンド

各RenderPass には、その動作を構成するコマンドのリストが含まれています:

  • ColorAttachment: カラー・レンダリング・ターゲットを指定します
  • DepthStencilAttachment: 深度/ステンシルの処理を指定します
  • DepthTextureAttachment: 深度出力にテクスチャを使用する
  • RenderablesFilter: レイヤーおよびタイプ(不透明/透明)に基づいてオブジェクトをフィルタリングします
  • PipelineStateOverride: グラフィックスパイプラインの状態を制御します
  • SubRenderPass: このパス内で別のレンダリングパスを実行する
  • AddDefine: シェーダープリプロセッサの定義を追加する

マテリアルモード

各RenderPass には、レンダリング中のマテリアルの処理方法を制御するmaterialMode プロパティがあります。3つのモードでは、マテリアルの制御レベルが異なります:

OriginalMaterialモード

このモードでは、オブジェクトに割り当てられたマテリアルを変更せずにレンダリングします。レンダリングパイプラインの構造(複数のパス、カスタムレンダリングターゲットなど)を制御しつつ、マテリアルの挙動を標準のままにしておきたい場合に便利です。

RenderPass {
    materialMode: RenderPass.OriginalMaterial
    commands: [
        ColorAttachment { target: myColorTexture },
        DepthStencilAttachment { }
    ]
}

AugmentMaterialモード

このモードでは、既存のマテリアルパイプラインにカスタムシェーダーコードを挿入します。マテリアルの基本的な挙動を維持しつつ、追加データ(法線、位置など)を複数のレンダターゲットに出力する必要があるディファードレンダリングにおいて特に有用です。

RenderPass {
    materialMode: RenderPass.AugmentMaterial
    augmentShader: "my_augment.glsl"
    commands: [
        ColorAttachment { target: gbuffer0; name: "GBUFFER0" },
        ColorAttachment { target: gbuffer1; name: "GBUFFER1" },
        DepthStencilAttachment { }
    ]
}

拡張シェーダーファイルには、MAIN_FRAGMENT_AUGMENT() 関数が含まれています:

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);
}

詳細については、「複数のレンダリングターゲット向けのAugmentシェーダー」を参照してください。

OverrideMaterialモード

このモードでは、すべてのオブジェクトのマテリアルを単一のマテリアルに置き換えます。シャドウマッピング、深度プリパス、デバッグ用可視化などの特殊なパスに有用です。

RenderPass {
    materialMode: RenderPass.OverrideMaterial
    overrideMaterial: CustomMaterial {
        fragmentShader: "depth_only.frag"
        // All objects will use this material
    }
    commands: [
        DepthTextureAttachment { target: depthTexture }
    ]
}

レンダーパスコマンド

コマンドはcommands プロパティで指定され、定義された順序で実行されます。

カラーアタッチメント

ColorAttachment コマンドは、カラーレンダリングターゲットを指定します。name プロパティは、オーグメントシェーダー内でこのアタッチメントにどのようにアクセスするかを定義します。

ColorAttachment {
    target: myTexture      // RenderPassTexture to render to
    name: "GBUFFER0"      // Name for shader access (optional)
}

1 パスにつき、最大 4 つのカラーアタッチメント(複数のレンダリングターゲット用)を設定できます。

深度アタッチメント

深度の処理には2つの方法があります:

DepthStencilAttachment 暗黙的な深度/ステンシルバッファを使用する方法:

DepthStencilAttachment { }  // Creates depth/stencil buffer automatically

DepthTextureAttachment 深度出力に明示的なテクスチャを使用する方法:

RenderPassTexture {
    id: depthTex
    format: RenderPassTexture.Depth24Stencil8
}

DepthTextureAttachment {
    target: depthTex  // Explicit depth texture
}

複数のパス間で深度バッファを共有する必要がある場合や、シェーダーでテクスチャ入力として使用する必要がある場合は、DepthTextureAttachment を使用してください。

Renderablesフィルター

RenderablesFilter コマンドは、レイヤーの割り当てとレンダラブルタイプに基づいて、どのオブジェクトをレンダリングするかを制御します。

RenderablesFilter {
    layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
    renderableTypes: RenderablesFilter.Opaque
}

layerMask プロパティは、ビット単位のOR演算を使用してレイヤーを組み合わせます。renderableTypes プロパティには以下の設定が可能です:

  • RenderablesFilter.Opaque: 不透明なオブジェクトのみをレンダリング
  • RenderablesFilter.Transparent: 透明なオブジェクトのみをレンダリング
  • RenderablesFilter.Opaque |RenderablesFilter.Transparent: 両方をレンダリング

パイプライン状態の上書き

PipelineStateOverride コマンドは、グラフィックスパイプラインの状態をきめ細かく制御します。このコマンドを使用すると、深度テスト、ブレンド、カリング、ポリゴンモードなどを上書きできます。

PipelineStateOverride {
    depthTestEnabled: true
    depthWriteEnabled: false
    blendEnabled: true
    cullMode: PipelineStateOverride.Back
    polygonMode: PipelineStateOverride.Fill
}

その他の例については、「パイプライン状態の制御」を参照してください。

サブ・レンダリング・パス

SubRenderPass コマンドを使用すると、現在のレンダリングパス内で別のレンダリングパスを実行することで、レンダリングパスの階層的な合成が可能になります。

RenderPass {
    id: parentPass
    commands: [
        ColorAttachment { target: colorTex },
        SubRenderPass { renderPass: childPass },
        // More commands after child pass
    ]
}

RenderPass {
    id: childPass
    // This pass executes within parentPass
}

定義の追加

AddDefine コマンドは、シェーダーのコンパイルに影響を与えるシェーダープリプロセッサ定義を追加します。

AddDefine {
    name: "USE_SPECIAL_MODE"
    value: 1
}

簡単な例:シングルパスレンダリング

以下は、ユーザー定義のレンダーパスを示す最小限の例です:

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

この例では:

  1. 内部パスを無効にします
  2. レンダリングターゲットテクスチャ(colorTarget)を作成します
  3. そのテクスチャにレンダリングするレンダリングパスを定義します
  4. RenderOutputProvider を使用してテクスチャを公開します
  5. 結果を以下のように表示しますSimpleQuadRenderer
  6. 標準マテリアルを使用した球体をレンダリングします

レイヤーの操作

ContentLayer シングルトンは、オブジェクトをレイヤーに整理するための定数を提供し、各パスで何がレンダリングされるかをきめ細かく制御できるようにします。

レイヤー定数

Qt Quick 3D では、ユーザーが割り当て可能な 24 のレイヤーが用意されています:

  • ContentLayer.Layer0 ContentLayer.Layer23 経由:個別のレイヤー
  • ContentLayer.LayerAll: すべてのユーザーレイヤーを統合したもの
  • ContentLayer.LayerNone: レイヤーなし

注:レイヤー24 ~31は内部使用のために予約されています。

オブジェクトをレイヤーに割り当てる

layers プロパティを使用して、オブジェクトをレイヤーに割り当てます:

Model {
    source: "#Cube"
    layers: ContentLayer.Layer0
    materials: PrincipledMaterial { baseColor: "red" }
}

Model {
    source: "#Sphere"
    layers: ContentLayer.Layer1 | ContentLayer.Layer2
    materials: PrincipledMaterial { baseColor: "blue" }
}

ビット単位のOR演算を使用することで、オブジェクトを複数のレイヤーに所属させることができます。

レイヤーによるフィルタリング

レンダリングパスで `RenderablesFilter ` を使用して、レンダリングするレイヤーを選択します:

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

ユースケース:選択的レンダリング

実用的な例として、特定のオブジェクトをワイヤーフレームのオーバーレイとしてレンダリングする場合が挙げられます:

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

テクスチャ管理

ユーザーによるレンダリングパスは、レンダリングターゲットとして、また後続のパスやマテリアルへの入力として、テクスチャに大きく依存しています。

レンダーパスのテクスチャ形式

RenderPassTexture さまざまなユースケースに対応するため、以下のフォーマットをサポートしています:

色形式:

フォーマット説明使用例
RGBA8チャンネルあたり8ビット標準的なカラー出力、メモリ使用量が少ない
RGBA16F16ビット浮動小数点HDRレンダリング、中間バッファ
RGBA32F32ビット浮動小数点高精度演算
R8、R16、R16F、R32FR8, R16, R16F, R32Fグレースケールデータ、専用バッファ

深度形式:

フォーマット説明
深度1616ビット深度
深度2424ビットの色深度
深度3232ビット深度
深度24・ステンシル824ビットの深度 + 8ビットのステンシル

テクスチャ定義の例:

RenderPassTexture {
    id: hdrColorBuffer
    format: RenderPassTexture.RGBA16F  // HDR color
}

RenderPassTexture {
    id: depthBuffer
    format: RenderPassTexture.Depth24Stencil8  // Depth + stencil
}

RenderPassTexture {
    id: normalBuffer
    format: RenderPassTexture.RGBA16F  // Store normals
}

パス間のテクスチャの共有

複数のパスで同じ深度テクスチャを共有できるため、パス間で深度テストを行うことができます:

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

レンダリング出力プロバイダー

RenderOutputProvider は、レンダリングパスの出力をTexture の入力として公開します:

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

attachmentSelector プロパティは、パスに複数のレンダリングターゲットがある場合に、どのカラーアタッチメントを使用するかを指定します:

  • RenderOutputProvider.Attachment0: 最初のカラーアタッチメント
  • RenderOutputProvider.Attachment1: 2番目のカラーアタッチメント
  • RenderOutputProvider.Attachment2: 3番目のカラーアタッチメント
  • RenderOutputProvider.Attachment3: 第4のカラーアタッチメント

パスの連鎖の例

複数のパスを連結して、各パスが前のパスの出力を処理するようにすることができます:

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

パイプライン状態の制御

PipelineStateOverride コマンドを使用すると、グラフィックスパイプラインの状態を詳細に制御でき、深度テスト、ブレンディング、カリングなどをカスタマイズできます。

深度テストと書き込み

深度値のテストおよび書き込み方法を制御します:

PipelineStateOverride {
    depthTestEnabled: true
    depthWriteEnabled: true
    depthFunction: PipelineStateOverride.LessOrEqual
}

depthFunction プロパティには、以下の値を設定できます:

  • Never,Less,Equal,LessOrEqual
  • Greater,NotEqual,GreaterOrEqual,Always

ブレンディング

透明度のためのブレンディングを有効にして設定します:

PipelineStateOverride {
    blendEnabled: true
    // Uses default blend mode (source alpha blending)
}

複数のレンダリングターゲットがある場合は、ターゲットごとのブレンド状態を使用します。PipelineStateOverride は、アタッチメントごとの値型プロパティtargetBlend0 からtargetBlend7 (型はrenderTargetBlend )を公開しており、ブレンド係数および演算の列挙型はRenderTargetBlend 名前空間にあります:

PipelineStateOverride {
    targetBlend0.enable: true
    targetBlend0.srcColor: RenderTargetBlend.SrcAlpha
    targetBlend0.dstColor: RenderTargetBlend.OneMinusSrcAlpha
    targetBlend0.opColor:  RenderTargetBlend.Add

    targetBlend1.enable: false  // No blending for attachment 1
}

カリング

面のカリング制御:

PipelineStateOverride {
    cullMode: PipelineStateOverride.Back   // Override material's cull mode to Back
}

ここでcullMode を設定すると、このパスに対してマテリアルが本来指定する値が上書きされます。オプション:None (カリングなし)、Front (前面の面をカリング)、Back (背面の面をカリング)。

ワイヤーフレームレンダリング

ジオメトリをワイヤーフレームとしてレンダリングします:

PipelineStateOverride {
    polygonMode: PipelineStateOverride.Line
    cullMode: PipelineStateOverride.None  // Show both sides
}

polygonMode には、Fill (デフォルト)またはLine (ワイヤーフレーム)を指定できます。

矩形切り取り

レンダリングを矩形領域に制限します:

PipelineStateOverride {
    usesScissor: true
    scissor: Qt.rect(100, 100, 400, 300)  // x, y, width, height
}

ビューポート制御

ビューポートを上書きする:

PipelineStateOverride {
    viewport: Qt.rect(0, 0, 800, 600)
}

完全な例:ワイヤーフレームのオーバーレイ

このサンプルでは、シーンを通常通りレンダリングした後、ワイヤーフレーム版を重ね合わせます:

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

複数のレンダリングターゲット用のオーグメントシェーダー

RenderPass.AugmentMaterial モードを使用する場合、マテリアルのフラグメントシェーダーにカスタムコードを挿入するオーグメントシェーダーを指定します。これは、マテリアルデータを複数のレンダターゲット(MRT)に出力する必要があるディファードレンダリングにおいて特に有用です。

MAIN_FRAGMENT_AUGMENT関数

オーグメントシェーダーファイルでは、MAIN_FRAGMENT_AUGMENT() 関数を定義する必要があります:

void MAIN_FRAGMENT_AUGMENT()
{
    // Your custom shader code here
}

この関数は、フラグメントシェーダー内でマテリアル計算が完了した後に呼び出され、マテリアルプロパティへのアクセスや、カスタム出力への書き込みが可能になります。

利用可能な組み込み変数

MAIN_FRAGMENT_AUGMENT() 内では、エンジンがマテリアルパイプラインデータを公開する一連のマクロを代入します。オーグメントシェーダー API の一部となるのは、以下のマクロのみです:

マクロ型説明
BASE_COLORvec4マテリアルのベースカラー(マテリアル処理後の線形色空間)。
METALNESSfloat0.0 から 1.0 の範囲のマテリアルのメタリック度。
ROUGHNESSfloat0.0 から 1.0 の範囲のマテリアルのラフネス。
WORLD_NORMALvec3ワールド空間における表面法線(ポスト・ノーマルマッピング)。
WORLD_TANGENTvec3ワールド空間の接線ベクトル。
WORLD_BINORMALvec3ワールド空間のバイノーマルベクトル。
DIFFUSE_LIGHTvec3蓄積された拡散光の寄与。
SPECULAR_LIGHTvec3蓄積されたスペキュラー光の寄与。
EMISSIVE_LIGHTvec3マテリアルの発光寄与量。
F0vec3法線入射時のフレネル反射率。
F90vec3接線入射時のフレネル反射率。

注:一部の 例(以下のディファード・レンダリングの例を含む)では、qt_varWorldPos を介してワールド空間のフラグメント位置を読み取っています。 これはエンジンの基盤となる可変名であり、augment-shader マクロではありません。また、「組み込みシェーダー機能」で説明されている.glsllib ファイルと同じ「セミパブリック」カテゴリに分類されます。つまり、実際には機能しますが、リリース間で安定性が保証されるわけではありません。

名前付き出力への書き込み

レンダリングパス内のカラーアタッチメントには、シェーダー内の出力変数に対応する名前を付けることができます:

RenderPass {
    commands: [
        ColorAttachment { target: tex0; name: "GBUFFER0" },
        ColorAttachment { target: tex1; name: "GBUFFER1" },
        ColorAttachment { target: tex2; name: "GBUFFER2" }
    ]
}

オーグメントシェーダー内では:

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では、最大4つのカラーアタッチメント(GBUFFER0~GBUFFER3)を同時にサポートしています。

オーグメントシェーダーの完全な例

以下は、ディファード・レンダリングのGバッファ・パスに関する完全な例です:

// 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);
}

レンダリングパス(RenderPassTexture )で使用する場合、インスタンスは外側のView3D の直接の子として宣言され、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 { }
        ]
    }
}

マテリアルの挙動の保持

オーグメントシェーダーは、通常のマテリアルパイプラインに取って代わるのではなく、それに加えて実行されます。つまり、

  • マテリアルのテクスチャ、プロパティ、および計算は引き続き行われます
  • 主要なカラー出力を置き換えるのではなく、追加の出力を生成している
  • 上書きされない限り、元のマテリアルの RGBA 出力は引き続き最初のカラーアタッチメントに書き込まれます

カスタムデータを出力するだけで、標準のマテリアル計算は必要ない場合は、代わりにRenderPass.OverrideMaterial の使用を検討してください。

「Augment」と「Override」の使い分け

次のような場合は「AugmentMaterial 」を使用してください:

  • Gバッファ用にマテリアルプロパティ(メタルネス、ラフネス、法線)が必要な場合
  • テクスチャマッピングなどの既存のマテリアル機能を活用したい場合
  • マテリアルデータを含む複数のレンダリングターゲットが必要な場合

OverrideMaterial を使用するケース:

  • すべてのオブジェクトで同一の挙動が必要な場合(深度プリパス、シャドウマップなど)
  • マテリアルごとのプロパティを必要としない場合
  • マテリアル計算をバイパスして、パフォーマンスを最大化したい場合

組み込みのシェーダー機能

レンダリングパスで使用されるオーグメントシェーダーやカスタムマテリアルは、インクルードシステムを通じてQt Quick 3Dの組み込みシェーダーインフラストラクチャを利用できます。これらのシェーダーライブラリファイル(.glsllib )は、ライティング、シャドウ、トーンマッピングなどの機能を提供します。

インクルード構文:

シェーダーコード内で\#include ディレクティブを使用して、機能をインポートします:

#include "tonemapping.glsllib"
#include "lightsData.glsllib"
#include "shadowMapping.glsllib"
#include "funcprocessPunctualLighting.glsllib"

void MAIN()
{
    // Use included functions
    vec3 color = qt_tonemap(hdrColor);
}

利用可能なシェーダーライブラリ:

これらのシェーダーライブラリは、エンジン内の `src/runtimerender/res/effectlib/ ` に配置されており、準公開と見なされます。つまり、ユーザーシェーダーで使用することは可能ですが、Qtのその他の公開APIと同様のバイナリ互換性は保証されません。

ライブラリ説明
tonemapping.glsllib組み込みのトーンマッピングアルゴリズムを使用したHDRからLDRへの変換を行うqt_tonemap() 関数を提供します
lightsData.glsllibカスタム照明計算で参照可能なシーンの照明情報(ライトの位置、色、方向など)を含みます
shadowMapping.glsllibデフォルトのシャドウマップからサンプリングを行う関数を提供し、カスタムマテリアルがシャドウを受け取れるようにします
funcprocessPunctualLighting.glsllib標準的な PBR ライティング計算のための `qt_processPunctualLighting() ` およびその他の組み込みライティング関数が含まれています
sampleProbe.glsllib画像ベースのライティングプローブをサンプリングするための関数(qt_sampleDiffuse() 、qt_sampleGlossyPrincipled() )

例:組み込み関数を使用したカスタムライティング

以下は、組み込みのライティング機能を使用したフラグメントシェーダーの例です:

#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);
}

注:これらのシェーダーライブラリは セミパブリックAPIです。これらは安定しており、カスタムシェーダーでの使用を意図していますが、Qtは、リリース間で内部実装や利用可能な関数が変更されないことを保証するものではありません。ただし、qt_tonemap() やqt_processPunctualLighting() のような一般的に使用される関数が大幅に変更される可能性は低いと考えられます。

応用例:ディファード・レンダリング

遅延レンダリングとは、第1パスでジオメトリ情報を複数のテクスチャ(Gバッファまたはジオメトリバッファと呼ばれる)にレンダリングし、第2パスで保存されたジオメトリデータを使用して照明計算を行う手法です。このアプローチは、ライトの数が多くても各ピクセルのシェーディングが1回だけで済むため、特に効率的です。

ディファード・レンダリングのアーキテクチャ

ディファード・レンダリング・パイプラインは、主に以下の2つのパスで構成されます。

  1. ジオメトリ・パス(G-バッファ・パス):シーンのジオメトリを複数のレンダリングターゲットにレンダリングし、アルベド、法線、ラフネス、メタリティ、ワールド位置などのマテリアルプロパティを格納します。
  2. ライティング・パス:Gバッファをサンプリングするフルスクリーンのクワッドをレンダリングし、保存されたジオメトリデータに基づいて各ピクセルに対してライティング計算を実行します。

G-バッファ・パスの実装

まず、マテリアルデータを複数のレンダリングターゲットに出力するGバッファパスを定義します:

GBufferPass.qml:G-バッファのレンダリングターゲットは、必要なプロパティとして公開されます。これにより、これを囲むView3D がそれらを提供し、その出力を読み取ることができます:

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);
}

オーグメントシェーダーは、マテリアルパイプラインによって計算されたマテリアルプロパティにアクセスし、それらを3つのGバッファアタッチメントに書き込みます。法線は、保存のために[-1,1]の範囲から[0,1]の範囲にエンコードされます。

ライティング・パスの実装

ライティングパスでは、G-バッファをサンプリングしてライティングを計算するフルスクリーンのクワッドをレンダリングします:

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

ライティング頂点シェーダー(lighting.vert )は、正規化デバイス座標系でフルスクリーンのクワッドを作成し、フラグメントシェーダー(lighting.frag )はGバッファをサンプリングしてライティング計算を実行します。

完全な統合

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

レンダリングの流れ

レンダリングは次のように進行します:

  1. G-バッファ・パス:Layer0およびLayer1上のシーンオブジェクトがレンダリングされます。各オブジェクトについて、オーグメントシェーダーはアルベド、法線、ラフネス、メタリティ、および位置を3つのカラーアタッチメントに書き込みます。深度は共有深度テクスチャに書き込まれます。
  2. ライティングパス:Layer13上のフルスクリーンクワッドがレンダリングされます。そのカスタムマテリアルは、3つのGバッファテクスチャと深度テクスチャをサンプリングし、シーン情報を再構築した上で、ライティング計算(指向性ライト、画像ベースライティングなど)を実行し、最終的なライティング適用後の色を生成します。
  3. 表示:ライティングパスの結果は、SimpleQuadRenderer を介して表示されます。

利点と制限

利点:

  • 多数のライトがあっても効率的(各ピクセルは1回だけ照らされる)
  • シーンの複雑さに依存しないライティング処理
  • スクリーンスペースエフェクトの実装が容易
  • ジオメトリパスとライティングパスを分離できる

制限事項:

  • Gバッファの読み書きにより、メモリ帯域幅の需要が高くなる
  • ハードウェアMSAAなし(代替のアンチエイリアシングが必要)
  • 透明度処理には別途フォワードパスが必要
  • 設定および維持管理のためのパイプラインがより複雑になる

完全な動作例については、「Qt Quick 3D - User Passes Example」を参照してください。

完全なレンダリングパイプラインの例

リアルなカスタムレンダリングパイプラインでは、不透明なジオメトリ、スカイボックス背景、2Dオーバーレイ、透明オブジェクトなど、複数のパス種別を組み合わせる必要がよくあります。ここでは、SubRenderPass を使用して階層的な合成を行う方法を示す完全な例を紹介します。

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

重要な概念

SubRenderPass 階層的構成に関する概念:

メインパスは、SubRenderPass コマンドを使用して、子パスを順次実行します。親パス自体は何もレンダリングせず(RenderablesFilter.None )、単に子パスの実行を調整する役割を果たします。これにより、明確な構造が提供され、すべてのサブパス間で深度バッファを共有できるようになります。

パスモード:

  • RenderPass.UserPass (デフォルト): 自身のジオメトリとマテリアルを使用したカスタムレンダリング
  • RenderPass.SkyboxPass: 環境スカイボックスをSceneEnvironment
  • RenderPass.Item2DPass: 3Dシーンに埋め込まれた2DのQt Quick コンテンツをレンダリングします

レンダリング順序:

  1. 不透明ジオメトリをGバッファにレンダリング
  2. フルスクリーンのクワッドにディファードライティングを適用
  3. ジオメトリの背後にスカイボックスをレンダリング(深度テスト有効、深度書き込み無効)
  4. その上に2D UIオーバーレイをレンダリング
  5. 透明オブジェクトを最後にブレンド処理を施してレンダリング

深度バッファの共有:

mainDepthStencilTexture は、PreserveDepthStencilContents を使用して各パス間で共有されます。これにより、スカイボックスがジオメトリの背後にレンダリングされ、透明オブジェクトが不透明なジオメトリに対して正しくテストされることが保証されます。

Item2D コンテンツ:

Qt Quick Node オブジェクト内に配置された2Dアイテム(ボタン、矩形、テキストなど)は、 によってレンダリングされます。これらのアイテムは3D空間に配置されますが、マウスやタッチ入力を受け付けることができる2Dオーバーレイとしてレンダリングされます。RenderPass.Item2DPass

パフォーマンスに関する考慮事項

ユーザー定義のレンダリングパスは最大限の制御を可能にしますが、パフォーマンスへの影響を慎重に検討する必要があります。

テクスチャ形式の選択

ニーズに応じてテクスチャ形式を選択してください:

フォーマット1ピクセルあたりのサイズ使用例
RGBA84バイト最終出力、シンプルなカラーバッファ
RGBA16F8 バイトHDR コンテンツ、中間バッファ、法線
RGBA32F16 バイト高精度計算、位置
R16F2 バイトR16FシングルチャンネルHDR(深度、AOなど)

1920×1080のフレームバッファの場合:

  • RGBA8:約8 MB
  • RGBA16F: 約16 MB
  • RGBA32F:約32 MB
  • RGBA16FのGバッファ3つ:約48 MB

推奨事項:中間バッファにはRGBA16Fを使用し、必要がなければRGBA8またはR8を使用してください。

ディファード・レンダリングとフォワード・レンダリング

アスペクトディファード・レンダリングフォワード・レンダリング
ライトが多数ある場合効率的 (O(光源数 + ピクセル数))計算コストが高い (O(光源数 * オブジェクト数))
メモリ帯域幅高い(Gバッファの読み取り/書き込み)低い
透明度別途パスが必要ネイティブ対応
MSAA直接サポートされていないハードウェアMSAAが動作する
設定の難易度より複雑より簡単

以下の場合はディファードレンダリングを使用してください:

  • ライトの数が多い場合(10個以上)
  • スクリーンスペースエフェクトが重要な場合
  • シーンの大部分が不透明な場合

以下の場合はフォワードレンダリングを使用してください:

  • ライトの数が少ない場合(5個未満)
  • 透明なオブジェクトが多い場合
  • メモリ帯域幅に制約がある場合
  • よりシンプルなパイプラインが望ましい場合

パス順序の最適化

レンダリングパスは、検出された順序で実行されます。以下の方法で最適化します:

  • 不透明なジオメトリを透明なジオメトリよりも先にレンダリングする
  • 有効な場合は深度プリパスを使用する(複雑なシーンでのオーバードローを低減)
  • レンダリングターゲットの切り替えを最小限に抑える
  • 可能であれば、パス間で深度バッファを再利用する

レンダリングターゲットのフラグ

renderTargetFlags プロパティはメモリの挙動を制御します:

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:既存のデータを保持します(例:同じターゲットへのマルチパスレンダリングの場合)。

DoNotStoreDepthStencilContents:深度/ステンシルを破棄してもよいことを示唆します(一部のハードウェアでは、メモリへの書き込みを回避することでパフォーマンスが向上する場合があります)。

ユーザーパスの使用タイミング

次のような場合には、ユーザー・レンダリング・パスの使用を検討してください:

  • ディファード・レンダリングの実装時
  • 複雑なマルチパス効果を作成する場合
  • レンダリング順序を明示的に制御する必要がある場合
  • カスタムレンダリング手法を実装する場合
  • ジオメトリデータを必要とするスクリーンスペースエフェクトを構築する場合

以下の場合はユーザーパスを避ける:

  • デフォルトのレンダリングで要件を満たせる場合
  • ポストプロセッシングのみが必要な場合(代わりにEffect を使用してください)
  • カスタムマテリアルシェーダーのみが必要な場合(代わりにCustomMaterial を使用してください)
  • パフォーマンスが極めて重要であり、余分なパスは無駄になる場合

一般的なパターンと使用例

ユーザーレンダリングパスにより、多くの高度なレンダリング技術が可能になります。以下に一般的なパターンをいくつか挙げます:

ディファードシェーディング/ライティング

ジオメトリ属性をGバッファに格納し、スクリーンスペースでライティングを実行します。詳細は「高度な例:ディファード・レンダリング」で解説されています。

エッジ検出とアウトライン化

シーンを通常通りレンダリングした後、2回目のパスでエッジ検出を適用します:

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

カスタムポストプロセッシングチェーン

RenderOutputProvider を介して各パスの出力を次のパスに引き継ぐことで、複数のポストプロセッシング効果を連鎖させます。多段階チェーンの実例については、「パス連鎖の例」(scenePass →process1 →process2 → 表示)を参照してください。

選択的なワイヤーフレームオーバーレイ

一部のオブジェクトを実体として、他のオブジェクトをワイヤーフレームオーバーレイとしてレンダリングします。「レイヤーの操作」の例を参照してください。

デバッグ用可視化

法線、深度、その他のデータを可視化するデバッグパスを生成します:

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

カスタムシャドウマッピング

明示的な制御によるカスタムシャドウマッピングを実装します:

// 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 testing

重要な考慮事項

ユーザーレンダリングパスを扱う際は、以下の重要な点に留意してください:

シャドウの処理

ユーザーレンダリングパスには、Qt Quick 3Dの内部シャドウレンダリングは自動的に含まれません。内部パスを無効化し、シャドウが必要な場合は、以下の手順を実行する必要があります:

  • 独自のシャドウマッピングパスを実装する
  • ライトの視点からシーンをレンダリングし、深度テクスチャに書き出す
  • ライティング計算においてシャドウマップをサンプリングする

あるいは、より単純なケースでは、影を必要としないか、またはプリベイクされたシャドウマップを使用できる場合があります。

HDRとトーンマッピング

浮動小数点レンダリングターゲット(RGBA16F、RGBA32F)を使用する場合、レンダリングは線形HDR空間で行われます。表示可能な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では、この目的で使用できるqt_tonemap() 関数がシェーダーに用意されています。

深度テクスチャの生成

深度をテクスチャとして必要とする場合(被写界深度などのエフェクト用)、DepthStencilAttachment の代わりにDepthTextureAttachment を使用します:

RenderPassTexture {
    id: depthTex
    format: RenderPassTexture.Depth24Stencil8
}

RenderPass {
    commands: [
        ColorAttachment { target: colorTex },
        DepthTextureAttachment { target: depthTex }
        // depthTex can now be sampled in shaders
    ]
}

クリア値とレンダリングターゲットの管理

各パスでは、クリア値を指定できます:

RenderPass {
    clearColor: Qt.rgba(0.0, 0.0, 0.0, 0.0)
    depthClearValue: 1.0
    stencilClearValue: 0
}

パスが内容を保持しない場合(デフォルト)、レンダリング前にレンダリングターゲットはこれらの値でクリアされます。PreserveColorContents またはPreserveDepthStencilContents が設定されている場合、既存の内容は保持され、クリア値は無視されます。

レイヤーの整理に関するベストプラクティス

レイヤーを論理的に整理してください:

  • レイヤー0~2:メインシーンのオブジェクト
  • レイヤー3~4:透明オブジェクト(別のパス)
  • レイヤー10以降:ポストプロセッシング用のフルスクリーンクワッド
  • レイヤー15以上:UI/デバッグ用オーバーレイ

コメントでレイヤーの使用目的を明記し、アプリケーション全体で一貫性を保ってください。

シェーダーの互換性

レンダリングパスで使用されるオーグメントシェーダーおよびカスタムマテリアルは、Qt Quick 3Dのシェーダーインフラストラクチャと互換性がある必要があります:

  • GLSL互換の構文を使用してください
  • Qt Quick 3D関数については、適切な\#include ディレクティブを含めてください
  • 利用可能な組み込み変数に注意する
  • すべてのターゲットプラットフォーム(OpenGL、Vulkan、Metal、D3D)でテストを行うこと

マルチレンダターゲットの制限事項

複数のレンダリングターゲット(MRT)を使用する場合:

  • カラーアタッチメントは最大4つまで
  • すべてのアタッチメントは同じ寸法でなければならない
  • アタッチメントごとに、以下の方法でブレンド状態を指定できますPipelineStateOverride
  • すべてのハードウェアがMRTに対応しているわけではありません(デバイスの機能を必ず確認してください)

透明度

ディファード・レンダリングでは、透明なオブジェクトの処理は困難です。一般的なアプローチ:

  • 透明オブジェクトに対するフォワードパス:不透明なジオメトリはディファードでレンダリングし、透明なジオメトリは別のフォワードパスでレンダリングする
  • 独立した透明Gバッファ:透明ジオメトリを、ブレンディングが有効な別のGバッファセットにレンダリングする
  • 重み付けされたブレンドによる順序非依存透過(OIT):特殊なOIT技術を使用する

ほとんどの場合、透明オブジェクト用に別のフォワードパスを作成するのが最も簡単です。

APIリファレンス

以下の表は、ユーザー・レンダリング・パスに関連するすべてのタイプの完全なリファレンスを示しています:

機能QML タイプ説明
メインのレンダリングパスの定義RenderPassコマンドとマテリアルモードを含むレンダリングパスを定義します
レンダリングターゲットテクスチャRenderPassTextureレンダリングターゲットとして使用されるテクスチャ(カラーまたは深度/ステンシル)
テクスチャ出力プロバイダRenderOutputProviderレンダリングパスの出力をテクスチャ入力として公開します
レイヤー定数ContentLayerレイヤーフィルタリング定数を提供するシングルトン
カラー出力ColorAttachmentカラーのレンダリングターゲットを指定します
深度/ステンシル (デフォルト)DepthStencilAttachment暗黙的な深度/ステンシルバッファを使用します
深度/ステンシル(テクスチャ)DepthTextureAttachment明示的な深度テクスチャを使用します
オブジェクトフィルタリングRenderablesFilterレイヤーおよびタイプごとにオブジェクトをフィルタリングします
パイプライン状態PipelineStateOverrideグラフィックス・パイプラインの状態を上書きする
ネストされたパスの実行SubRenderPass別のレンダリングパスを実行します
シェーダー定義AddDefineシェーダープリプロセッサ定義を追加する
ターゲットごとのブレンド状態renderTargetBlendMRT用のブレンド設定
表示ヘルパーSimpleQuadRenderer最終出力を以下にレンダリングしますView3D
タイプ説明
CustomMaterial頂点シェーダー/フラグメントシェーダーを備えたカスタムマテリアル
Effectポストプロセスエフェクト
View3DrenderOverrides プロパティを持つ3Dビュー
Modellayers プロパティを持つ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.