インスタンスレンダリング

はじめに

Qt Quick 3D はModel オブジェクトのインスタンス化をサポートしています。インスタンス化とは、1つのオブジェクトを1回の描画呼び出しで複数回レンダリングするテクニックのことです。(例えば、OpenGL 関数glDrawElementsInstanced など)。

インスタンス化によって、バリエーションを持ったモデルを複製することができます。Repeater3D を使うのとは対照的に、モデルとそのグラフィックリソースは一度だけ割り当てられます。複製されたインスタンスのレンダリングは、GPU によって低レベルで行われます。モデルの複雑さにもよりますが、これで数桁の性能向上が見込めます。

実際には、インスタンス化は、各インスタンスがベースモデルに対してど のように変更されるかを指定するテーブルを定義することで行われます。

インスタンス化API

インスタンス化APIの主な原則は、明示的であることです:既存のAPI内でインスタンス化の機会を自動検出しようとはしません。その代わりに、各モデルはinstancing プロパティを設定してInstancing オブジェクトを参照することで、個別にマークされます。同じInstancingオブジェクトを複数のモデルで同時に使うことができます。

Instancingオブジェクトは、各コピーがどのようにレンダリングされるかを定義するテーブルを指定します。利用可能な変更は以下の通りです:

  • 変形:位置、回転、スケール。
  • カラー:モデルのマテリアルにブレンドされるカラー。
  • カスタムデータ:カスタムマテリアルで使用できるデータ

QtはInstancingを継承した3つのQML型を提供しています:

  • InstanceList すべてのインスタンスを列挙し、各インスタンスのプロパティへのバインディングを可能にします。
  • RandomInstancing 定義された範囲内でランダムなインスタンスを生成することで、素早くテストやプロトタイプを作成する方法を提供します。
  • FileInstancing 外部ファイルからインスタンステーブルを読み込みます。

インスタンス生成の例では、QML APIを使ってシーンを作成する方法を示しています。

他の種類のインスタンステーブルも、QQuick3DInstancing をサブクラス化することで、C++で定義することができます。例えば、particle system は、内部で独自のインスタンステーブルを使用しています。これはModelParticle3D.instanceTable として利用できます。

カスタムシェーダコードを書くことで、インスタンステーブルを使って、物理ベースレンダリングのための変数、スケルタルアニメーションのウェイト、ディストーションなど、カスタムマテリアルで表現できる追加プロパティを制御することができます。インスタンステーブルのカスタムデータは、4つの浮動小数点数で構成されます。

カスタムインスタンシングの例では、C++で実装されたカスタムマテリアルとインスタンステーブルを組み合わせる方法を示しています。

アルファブレンディングとインスタンス化

アルファブレンディング アルファブレンディングを正しく行うには、半透明のオブジェクトを前後逆にレンダリングする必要があります。このため、QtQuick3D は不透明オブジェクトと半透明オブジェクトを別々にソートし、正しい順序でレンダリングします。しかしインスタンス化では、depth-sorting がオ ンにされていない場合、GPU はインスタンス化テーブルで指定された順序 でインスタンスをレンダリングします。パフォーマンス上の理由から、QtQuick3D はデフォルトでテーブルをソートしません。インスタンス数が多いと時間がかかるからです。これは、半透明のインスタンスが互いに重なったり、他の半透明オブジェクトと重なったりすると、結果がおかしく見える可能性があることを意味します。一般的に、不透明度が低いとエラーは目立ちません。

完全に不透明なオブジェクトと、重なっていない半透明のオブジェクトは、常に正しくレンダリングされます。これは、Qt が深度バッファテストを使って不透明なオブジェクトの後ろに描画されないようにするためです。しかし、ソートがないため、不透明オブジェクトのパフォーマンスに影響が出る可能性があります:最適な順序でレンダリングされない可能性があり、同じピクセルが複数回書き込まれる可能性があるため、フラグメント・シェーダの作業が増えます。

レンダラはインスタンステーブルの内容を検査しないので、インスタンステーブルに半透明のアルファ値が含まれている場合は、明示的に指定する必要があります:レンダラーがアルファブレンドを有効にするように、hasTransparency プロパティをtrue に設定します。これはすべてのインスタンスに適用されます:完全に不透明なインスタンスも深度テストなしでレンダリングされ、目に見えるエラーが発生する可能性があります。

シーンの他の部分に対するレンダリングの順序は、モデルのdepth bias を設定することで調整できます。

トランスフォームとインスタンス化

各インスタンスは、インスタンステーブルに独自のトランスフォームを持ちます。これはインスタンス化されたモデルのトランスフォームと組み合わされます。いくつかの使用例があるため、これは少し複雑です:

  • 個々のインスタンスに適用されるモデル上のトランスフォームを行う。これにより、インスタンステーブルを変更することなく、すべてのインスタンスを一度に回転させるなど、安価なアニメーションが可能になります。
  • インスタンスのグループ全体を一度にトランスフォームする。
  • モデル階層のインスタンス化。

これらのすべてのケースをサポートするために、モデルのトランスフォームは、ローカルインスタンスのトランスフォームと グローバルインスタンスのトランスフォームの2つの部分に分割されます。概念的には、インスタンス化は次のように実行されます:

  • まず、モデルはローカルインスタンス変換に従って変換されます。
  • 次に、各インスタンスは、インスタンステーブル変換を適用して計算されます。
  • 最後に、インスタンス化されたオブジェクトのグループ全体が、グローバルインスタンス変換に従って変換されます。

デフォルトでは、モデルのローカルインスタンス変換はモデルのスケールと回転で構成され、残りはグローバルインスタンス変換に入ります。

これは、モデルのinstanceRoot プロパティを設定することで制御できます。これは、インスタンスの座標系の原点を定義します。最も一般的な使用方法は、モデルの階層をインスタンス化する場合です。例えば、立方体の周りを回る球体などです:

Model {
    id: cube
    instancing: someInstanceTable
    source: "#Cube"
    materials: DefaultMaterial { diffuseColor: "lightgray" }
    Node {
        Model {
            source: "#Sphere"
            instanceRoot: cube
            instancing: cube.instancing
            x: 150
            materials: DefaultMaterial { diffuseColor: "gray" }
        }
        NumberAnimation on eulerRotation.y {
            from: 0
            to: 360
            duration: 4000
            loops: Animation.Infinite
        }
    }
}

instanceRoot は、球体のインスタンスが立方体の要素であるかのように配置されることを指定するために必要です。階層内の各モデルは、instancing プロパティを指定する必要があります。通常の場合、これらはすべて同じInstancing オブジェクトに設定する必要があります。

instanceRoot は、単一のモデルをインスタンス化する場合にも使用できます。例えば、中心から外れた点を中心に回転する円柱などです:

 Node {
    id: parentNode
    Model {
        source: "#Cylinder"
        instanceRoot: parentNode
        instancing: anotherInstanceTable
        x: 25
        materials: DefaultMaterial { diffuseColor: "white" }
    }
    NumberAnimation on eulerRotation.y {
        from: 0
        to: 360
        duration: 1000
        loops: Animation.Infinite
    }
}

ピッキングとインスタンス化

Picking は、ユーザーインターフェイスのインタラクションからモデルを選択できるメカニズムです。インスタンス化されたレンダリングでは、同じモデルの複数の表現が存在するため、ピッキング結果には が含まれます。 インスタンス化されたピッキングは、ベースモデルに プロパティを設定することで有効になります。instance index pickable

本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。