Qt 3D 概要

Qt 3D は、開発者が必要とするあらゆるレンダリングパイプラインを迅速に実装できる、完全に設定可能なレンダラーを提供する。さらに、 は、レンダリング以外のニアリアルタイム・シミュレーションのための汎用フレームワークを提供します。Qt 3D

Qt 3D は、コアと、任意の機能を実装できる任意の数のアスペクトにきれいに分離されている。アスペクトはコンポーネントや エンティティと相互作用し、機能の一部を提供する。アスペクトの例としては、物理、オーディオ、コリジョン、人工知能(AI)、経路探索などがある。

基本3D機能

Qt 3D は3Dフレームワークで、3D図形の描画や移動、カメラの移動が可能です。以下の基本機能をサポートしています:

マテリアル

Qt 3D は、複数のレベルのカスタマイズを可能にする、堅牢で非常に柔軟なマテリアルシステムを備えています。異なるプラットフォームやOpenGLバージョンでの異なるレンダリングアプローチに対応し、異なるステートセットで複数のレンダリングパスを可能にし、異なるレベルでパラメータをオーバーライドするメカニズムを提供し、シェーダを簡単に切り替えることができます。これらはすべて、C++またはQMLプロパティバインディングを使用して行います。

Material タイプのプロパティは、参照されるエフェクトプロパティで指定される GLSL シェーダプログラムのユニフォーム変数に簡単にマッピングできます。

マテリアルの使用例については、以下の例を参照してください:

シェーダー

Qt 3D は、OpenGLのプログラム可能なレンダリングパイプラインのすべてのステージをサポートしています:頂点、テッセレーション制御、テッセレーション評価、ジオメトリ、フラグメントシェーダ。コンピュート・シェーダーは将来のリリースを予定しています。

シェーダの使用例については、Qt 3D:Wireframe QML Exampleを参照してください。

シャドウマッピング

影はOpenGLでは直接サポートされていませんが、影を生成するためのテクニックは無数にあります。シャドウマッピングは、見栄えの良い影を生成するのに使いやすく、パフォーマンスコストも非常に小さくなります。

シャドウマッピングは通常、2パスレンダリングを使用して実装されます。最初のパスでは、シャドウ情報が生成されます。2番目のパスでは、特定のレンダリング技術を使用してシーンを生成すると同時に、1番目のパスで収集した情報を使用して影を描画します。

シャドウマッピングの背景にある考え方は、光に最も近いフラグメントだけが点灯するというものです。他のフラグメントの後ろにあるフラグメントはオクルードされるため、影になります。

したがって、最初のパスでは、光の視点からシーンを描画します。保存される情報は、単純に、このライト空間で最も近いフラグメントの距離です。OpenGLの用語では、これは、深度テクスチャがアタッチされたフレームバッファオブジェクト(FBO)を持つことに相当します。実際、目からの距離は深度の定義であり、OpenGLによって行われるデフォルトの深度テストは、実際には最も近いフラグメントの深度のみを保存します。

フラグメントに陰影をつける必要はなく、深度を計算するだけなので、カラーテクスチャのアタッチメントも必要ありません。

次の画像は、セルフシャドウの平面と三つ葉の結び目のあるシーンを表示しています:

次の画像は、シーンの誇張されたシャドウマップテクスチャを示しています:

この画像は、光の視点からシーンをレンダリングするときに保存される深度を示しています。暗い色は、浅い深度(つまり、カメラに近い)を表します。このシーンでは、ライトはシーン内のオブジェクトのどこか上、メインカメラに対して右側に配置されています(最初のスクリーンショットと比較してください)。これは、おもちゃの平面が他のオブジェクトよりもカメラに近いという事実と一致します。

シャドウマップが生成されると、2回目のレンダリングパスが行われます。この2回目のパスでは、ノーマルシーンのカメラを使ってレンダリングします。ここでは、フォンシェーディングなど、どのようなエフェクトでも使用できます。シャドウマップアルゴリズムがフラグメントシェーダで適用されることが重要です。つまり、光に最も近いフラグメントは照らされて描画され、それ以外のフラグメントは影になって描画されます。

最初のパスで生成されたシャドウマップは、フラグメントとライトの距離に関する必要な情報を提供します。次に、フラグメントを光空間に再マッピングし、それによって光から見た深さと、シャドウマップテクスチャ上の座標を計算すれば十分です。次に、シャドウマップテクスチャを与えられた座標でサンプリングし、フラグメントの深さをサンプリングの結果と比較することができます。フラグメントがより遠くにある場合は影になり、そうでない場合は照明されます。

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

インスタンス化とは、GPUにベースオブジェクトの多数のコピー(インス タンス)を描画させる方法です。多くの場合、位置、向き、色、マテリアル・プロパティ、スケールなどが異なります。Qt 3D は、Qt Quick Repeater 要素に似た API を提供します。この場合、デリゲートがベースオブジェクトで、モデルがインスタンスごとのデータを提供します。したがって、Mesh コンポーネントがアタッチされたエンティティが最終的に glDrawElements の呼び出しに変換されるのに対し、インスタンス化されたコンポーネントを持つエンティティは glDrawElementsInstanced の呼び出しに変換されます。

インスタンス化レンダリングは将来のリリースで予定されています。

ユニフォームバッファオブジェクト

ユニフォーム・バッファ・オブジェクト(UBO)は、OpenGL シェーダ・プログラムにバインドして、大量のデータをすぐに利用できるようにすることができます。UBO の典型的な使用例は、マテリアルまたはライティングパラメータのセットです。

役に立つヒント

3Dレンダリングにとても役立つプログラミングのヒントが、このページにあります: Qt 3D レンダリングプロのヒント

設定可能なレンダラー

C++とQMLの両方のAPIのサポートと、完全に設定可能なレンダラーを組み合わせるために、フレームグラフの概念が導入されました。シーングラフが 何をレンダリングするかのデータ駆動型の記述であるのに対し、フレームグラフどのようにレンダリングするかのデータ駆動型の記述です。

フレームグラフによって、開発者は、Zフィルパスを含む単純なフォワード・レンダラーか、ディファード・レンダラーを使用するかなどを選択することができる。また、透過オブジェクトをいつレンダリングするかなどの制御も可能です。これはすべて純粋にデータから設定されるため、C++コードに触れることなく、実行時に動的に変更することも非常に簡単だ。カスタムレンダリングアルゴリズムを実装した独自のフレームグラフを作成して、Qt 3D を拡張することも可能です。

3D拡張機能

Qt 3D 、3Dコンテンツを画面に表示するという基本的な機能だけでなく、3Dオブジェクトに関連する以下のような拡張機能のホストとしても機能する拡張性と柔軟性を備えています:

  • 物理シミュレーション
  • 衝突検出
  • 3D位置オーディオ
  • リジッドボディ、スケルトン、モーフターゲットアニメーション
  • 経路探索とその他のAI
  • ピッキング
  • パーティクル
  • オブジェクトのスポーン

パフォーマンス

Qt 3D 最新のハードウェアは、基本クロック速度よりもコア数を増やすことでパフォーマンスを向上させるため、『Steelcase』は利用可能なCPUコア数に応じて性能が向上し、スケールアップするように設計されている。多くのタスクは互いに独立しているため、複数のコアを使用することが効果的です。たとえば、パス検索モジュールで実行される処理は、デバッグ情報や統計情報をレンダリングするときを除いて、レンダラで実行されるタスクと強く重なることはない。

Qt 3D アーキテクチャ

Qt 3D の主な使用例は、ほぼリアルタイムでオブジェクトをシミュレートし、それらのオブジェクトの状態を画面にレンダリングすることである。スペースインベーダーの例では、以下のオブジェクトが含まれている:

  • プレイヤーの地上大砲
  • 地面
  • 防御ブロック
  • 敵のスペースインベーダー船
  • 敵のボスの空飛ぶ円盤
  • 敵やプレイヤーが撃つ弾丸

伝統的なC++の設計では、これらのタイプのオブジェクトは、通常、ある種の継承ツリーに配置されたクラスとして実装されます。継承ツリーのさまざまな分岐によって、ルート・クラスに次のような機能が追加されます:

  • ユーザー入力を受け付ける
  • サウンドを再生する
  • アニメーションする
  • 他のオブジェクトと衝突する
  • 画面に描画される

スペースインベーダーの例にある型は、これらの特徴に照らして分類することができる。しかし、このような単純な例でさえ、エレガントな継承ツリーを設計するのは容易ではありません。

このアプローチや他の継承のバリエーションには、多くの問題がある:

  • 深く広い継承階層は、理解、維持、拡張が難しい。
  • 継承の分類法はコンパイル時に決まってしまう。
  • クラス継承ツリーの各レベルは、単一の基準または軸でしか分類できません。
  • 共有機能は、時間の経過とともにクラス階層を上昇する傾向がある。
  • 開発者が何をしたいかを予測することは不可能です。

深く広い継承ツリーを拡張するには、通常、元の作者が使用した分類法を理解し、それに同意する必要があります。そのため、Qt 3D 、オブジェクトのインスタンスに機能を付与する手段として、継承の代わりに集約に重点を置いている。具体的には、Qt 3D 、エンティティ・コンポーネント・システム(ECS)を実装している。

ECSの使用

ECSでは、エンティティはシミュレートされたオブジェクトを表すが、それ自体には特定の動作や特性はない。エンティティに1つまたは複数のコンポーネントを集約させることで、エンティティに追加の動作を追加することができます。各コンポーネントは、オブジェクトタイプのビヘイビアの垂直スライスです。

スペースインベーダーの例では、地上は、エンティティにレンダリングが必要であることと、どのようなレンダリングが必要であるかをシステムに伝えるコンポーネントが付加されたエンティティです。敵のスペースインベーダー船は、船をレンダリングさせるだけでなく、音を出したり、衝突させたり、アニメーションさせたり、簡単なAIで操作できるようにするコンポーネントがアタッチされた別のエンティティです。

プレイヤーの地上大砲のエンティティは、AIコンポーネントがないことを除けば、敵のスペースインベーダー船とほぼ同様のコンポーネントを持っています。その代わりに、大砲はプレイヤーが動かして弾を発射するための入力コンポーネントを持っている。

ECSバックエンド

Qt 3D のバックエンドは、アスペクトという形でECSパラダイムのシステム部分を実装している。アスペクトは、1つまたは複数の集約されたコンポーネントの組み合わせによって、エンティティに提供される機能の特定の垂直スライスを実装する。

たとえば、レンダラー アスペクトは、メッシュ、マテリアル、およびオプションでトランスフォーム コンポーネントを持つエンティティを探します。レンダラー アスペクトは、そのようなエンティティを見つけると、そのデータをどのように取り込んで、そこから何かを描画するかを判断します。エンティティにそれらのコンポーネントがない場合、レンダラー アスペクトはそれを無視します。

Qt 3D 追加機能を提供するコンポーネントを集約して、カスタム・エンティティを構築します。 エンジンでは、アスペクトを使用して、特定のコンポーネントを持つエンティティを処理および更新します。Qt 3D

たとえば、物理アスペクトは、何らかの衝突体積コンポーネントと、質量や摩擦係数など、シミュレーションに必要な他のプロパティを指定する別のコンポーネントを持つエンティティを探します。サウンドを発するエンティティには、サウンドエミッターであることを指定するコンポーネントと、いつ、どのサウンドを再生するかを指定するコンポーネントがあります。

ECSは継承ではなく集約を採用しているため、コンポーネントを追加または削除するだけで、実行時にオブジェクトの動作を動的に変更することが可能です。

例えば、パワーアップ後に突然壁を通り抜けて走れるようにするには、パワー アップがタイムアウトするまで、エンティティのコリジョンボリュームコンポーネン トを一時的に削除します。PlayerWhoRunsThroughWalls のために、特別なワンオフのサブクラスを作成する必要はありません。

Qt 3D ECSの実装

Qt 3D は、ECSを単純なクラス階層として実装しています。 の基本クラスは であり、これは のサブクラスです。 は、 に、アスペクトへのプロパティの変更を自動的に伝達する機能と、アプリケーション全体で一意である ID を追加します。アスペクトは追加のスレッドに存在し、 は、ユーザー向けオブジェクトとアスペクト間のデータ転送を簡素化します。Qt 3D Qt3DCore::QNode QObject Qt3DCore::QNode QObject Qt3DCore::QNode

通常、Qt3DCore::QNode のサブクラスは、コンポーネントによって参照される追加のサポートデータを提供します。たとえば、QShaderProgramクラスは、エンティティのセットをレンダリングするときに使用するGLSLコードを指定します。

Qt 3D のコンポーネントは、Qt3DCore::QComponent をサブクラス化し、対応するアスペクトの動作に必要なデータを追加することで実装されます。たとえば、メッシュ・コンポーネントは、OpenGLパイプラインに送られるべき頂点ごとのデータを取得するために、レンダラー・アスペクトによって使用される。

最後に、Qt3DCore::QEntity は、ゼロ個以上のQt3DCore::QComponent インスタンスを集約できるオブジェクトです。

拡張Qt 3D

Qt の一部としてQt 3D に機能を追加したり、マルチスレッドのバックエンドの利点を生かすために独自のアプリケーショ ンに機能を追加したりするには、次のようなタスクがあります:

  • 必要なコンポーネントやデータを特定し、実装する。
  • コンポーネントを QML エンジンに登録する(QML API を使用する場合のみ)。
  • QAbstractAspect をサブクラス化し、サブシステムの機能を実装する。

Qt 3D タスクベースエンジン

Qt 3D では、アスペクトは各フレームで、実行するタスクのセットと、それらの間の依存関係を問われます。タスクは、パフォーマンスを向上させるために、スケジューラによって構成されたすべてのコアに分散されます。

Qt 3Dアスペクト

デフォルトでは、Qt 3D は Qt3DRender と Qt3DInput のアスペクトを提供します。これらのアスペクトによって提供されるコンポーネントやその他のサポートクラスは、それらのモジュールのドキュメントで説明されています。

より多くの機能を提供する追加のアスペクトは、Qt 3D の将来のバージョンで追加される予定です。

© 2025 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.