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 automaticallyDepthTextureAttachment 深度出力に明示的なテクスチャを使用する方法:
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
}
}
}この例では:
- 内部パスを無効にします
- レンダリングターゲットテクスチャ(colorTarget)を作成します
- そのテクスチャにレンダリングするレンダリングパスを定義します
- RenderOutputProvider を使用してテクスチャを公開します
- 結果を以下のように表示しますSimpleQuadRenderer
- 標準マテリアルを使用した球体をレンダリングします
レイヤーの操作
ContentLayer シングルトンは、オブジェクトをレイヤーに整理するための定数を提供し、各パスで何がレンダリングされるかをきめ細かく制御できるようにします。
レイヤー定数
Qt Quick 3D では、ユーザーが割り当て可能な 24 のレイヤーが用意されています:
ContentLayer.Layer0ContentLayer.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ビット | 標準的なカラー出力、メモリ使用量が少ない |
| RGBA16F | 16ビット浮動小数点 | HDRレンダリング、中間バッファ |
| RGBA32F | 32ビット浮動小数点 | 高精度演算 |
| R8、R16、R16F、R32F | R8, R16, R16F, R32F | グレースケールデータ、専用バッファ |
深度形式:
| フォーマット | 説明 |
|---|---|
| 深度16 | 16ビット深度 |
| 深度24 | 24ビットの色深度 |
| 深度32 | 32ビット深度 |
| 深度24・ステンシル8 | 24ビットの深度 + 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,LessOrEqualGreater,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_COLOR | vec4 | マテリアルのベースカラー(マテリアル処理後の線形色空間)。 |
METALNESS | float | 0.0 から 1.0 の範囲のマテリアルのメタリック度。 |
ROUGHNESS | float | 0.0 から 1.0 の範囲のマテリアルのラフネス。 |
WORLD_NORMAL | vec3 | ワールド空間における表面法線(ポスト・ノーマルマッピング)。 |
WORLD_TANGENT | vec3 | ワールド空間の接線ベクトル。 |
WORLD_BINORMAL | vec3 | ワールド空間のバイノーマルベクトル。 |
DIFFUSE_LIGHT | vec3 | 蓄積された拡散光の寄与。 |
SPECULAR_LIGHT | vec3 | 蓄積されたスペキュラー光の寄与。 |
EMISSIVE_LIGHT | vec3 | マテリアルの発光寄与量。 |
F0 | vec3 | 法線入射時のフレネル反射率。 |
F90 | vec3 | 接線入射時のフレネル反射率。 |
注:一部の 例(以下のディファード・レンダリングの例を含む)では、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つのパスで構成されます。
- ジオメトリ・パス(G-バッファ・パス):シーンのジオメトリを複数のレンダリングターゲットにレンダリングし、アルベド、法線、ラフネス、メタリティ、ワールド位置などのマテリアルプロパティを格納します。
- ライティング・パス: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 }
}レンダリングの流れ
レンダリングは次のように進行します:
- G-バッファ・パス:Layer0およびLayer1上のシーンオブジェクトがレンダリングされます。各オブジェクトについて、オーグメントシェーダーはアルベド、法線、ラフネス、メタリティ、および位置を3つのカラーアタッチメントに書き込みます。深度は共有深度テクスチャに書き込まれます。
- ライティングパス:Layer13上のフルスクリーンクワッドがレンダリングされます。そのカスタムマテリアルは、3つのGバッファテクスチャと深度テクスチャをサンプリングし、シーン情報を再構築した上で、ライティング計算(指向性ライト、画像ベースライティングなど)を実行し、最終的なライティング適用後の色を生成します。
- 表示:ライティングパスの結果は、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: 環境スカイボックスをSceneEnvironmentRenderPass.Item2DPass: 3Dシーンに埋め込まれた2DのQt Quick コンテンツをレンダリングします
レンダリング順序:
- 不透明ジオメトリをGバッファにレンダリング
- フルスクリーンのクワッドにディファードライティングを適用
- ジオメトリの背後にスカイボックスをレンダリング(深度テスト有効、深度書き込み無効)
- その上に2D UIオーバーレイをレンダリング
- 透明オブジェクトを最後にブレンド処理を施してレンダリング
深度バッファの共有:
mainDepthStencilTexture は、PreserveDepthStencilContents を使用して各パス間で共有されます。これにより、スカイボックスがジオメトリの背後にレンダリングされ、透明オブジェクトが不透明なジオメトリに対して正しくテストされることが保証されます。
Item2D コンテンツ:
Qt Quick Node オブジェクト内に配置された2Dアイテム(ボタン、矩形、テキストなど)は、 によってレンダリングされます。これらのアイテムは3D空間に配置されますが、マウスやタッチ入力を受け付けることができる2Dオーバーレイとしてレンダリングされます。RenderPass.Item2DPass
パフォーマンスに関する考慮事項
ユーザー定義のレンダリングパスは最大限の制御を可能にしますが、パフォーマンスへの影響を慎重に検討する必要があります。
テクスチャ形式の選択
ニーズに応じてテクスチャ形式を選択してください:
| フォーマット | 1ピクセルあたりのサイズ | 使用例 |
|---|---|---|
| RGBA8 | 4バイト | 最終出力、シンプルなカラーバッファ |
| RGBA16F | 8 バイト | HDR コンテンツ、中間バッファ、法線 |
| RGBA32F | 16 バイト | 高精度計算、位置 |
| R16F | 2 バイト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 | シェーダープリプロセッサ定義を追加する |
| ターゲットごとのブレンド状態 | renderTargetBlend | MRT用のブレンド設定 |
| 表示ヘルパー | SimpleQuadRenderer | 最終出力を以下にレンダリングしますView3D |
関連する型
| タイプ | 説明 |
|---|---|
| CustomMaterial | 頂点シェーダー/フラグメントシェーダーを備えたカスタムマテリアル |
| Effect | ポストプロセスエフェクト |
| View3D | renderOverrides プロパティを持つ3Dビュー |
| Model | layers プロパティを持つ3Dモデル |
例
- Qt Quick 3D - ユーザーパス例:完全なディファード・レンダリングの例
関連項目
- プログラム可能なマテリアル、エフェクト、ジオメトリ、およびテクスチャデータ:Qt Quick の3Dカスタマイズ機能の概要
- Qt Quick 3D アーキテクチャ:レンダリングパイプラインの理解
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.