Effect QML Type
ポストプロセス効果を作成するためのベースコンポーネント。詳細...
Import Statement: | import QtQuick3D |
Inherits: |
プロパティ
- passes : list
詳細説明
Effectタイプは、QtQuick3D に対する独自の後処理エフェクトを実装することができます。
後処理エフェクト
後処理エフェクトは、Qt Quick のShaderEffect アイテムと概念的に非常に似ています。エフェクトがある場合、シーンはまず別のテクスチャにレンダリングされます。その後、View3D のrender mode に応じて、メインレンダリングターゲットにテクスチャ付きクワッドを描画することで、エフェクトが適用されます。エフェクトは、バーテックスシェーダ、フラグメントシェーダ、またはその両方を提供することができます。エフェクトはView3D ごとに、常にシーン全体に適用されます。
エフェクトはSceneEnvironment::effects プロパティのSceneEnvironment に関連付けられます。エフェクトはリストにある順番に適用され、前のステップの出力を次のステップの入力として使用し、最後のエフェクトの出力がView3D の内容を定義します。
注: SceneEnvironment とExtendedSceneEnvironment は、被写界深度、グロー/ブルーム、レンズフレア、カラーグレーディング、ビネットなどのビルトインエフェクトのセットを提供します。これらのエフェクトがアプリケーションのニーズに十分かどうかを常に考慮し、カスタムのポスト処理エフェクトを実装する代わりに、ビルトイン機能を使用することをお勧めします。
エフェクトは多くの点でcustom materials 。ただし、カスタムマテリアルはモデルに関連付けられ、そのメッシュのシェーディングを担当します。一方、エフェクトのバーテックスシェーダは常に四角形(たとえば、2つの三角形)を入力として取得し、フラグメントシェーダはシーンのコンテンツでテクスチャをサンプリングします。
カスタムマテリアルとは異なり、エフェクトはマルチパスをサポートします。複数のエフェクトを適用する必要がある場合、the SceneEnvironment で複数のエフェクトを連鎖させることで、同じ結果が得られることがよくあります。これはカスタムエフェクトの例でも実証されています。しかし、パスには追加のカラーバッファ(テクスチャ)を要求し、これらの追加バッファのどれに出力するかを指定する可能性があります。これにより、後続のパスは、これらの追加バッファの1つ以上と、元のシーンのコンテンツを入力として使用できるため、より複雑な画像処理技術を実装することができます。必要であれば、これらの追加バッファは、フレーム間のコンテンツが保持されることを意味する、拡張された寿命を持つことができ、モーションブラーのような、複数のフレームからのコンテンツの蓄積に依存するエフェクトを実装することができます。
Qt Quick の 2DShaderEffect と比較すると、3D ポストプロセッシングエフェクトは、深度バッファーデータを扱うことができ、中間バッファーで複数のパスを実装できるという利点があります。さらに、テクスチャ関連の機能も拡張されています:Qt Quick 3Dでは、フィルタリングモードをより細かく制御できるようになり、RGBA8以外のテクスチャフォーマット(例えば、浮動小数点フォーマット)でエフェクトを使用できるようになりました。
注意: ポストプロセッシングエフェクトは、View3D のrenderMode がOffscreen
,Underlay
またはOverlay
に設定されている場合に利用可能です。Inline
モードではエフェクトはレンダリングされません。
注: ポストプロセッシングエフェクトを使用する場合、アプリケーションが提供するシェーダは、トーンマッピングが適用されていないリニアカラーデータを期待する必要があります。tonemapMode がSceneEnvironment.TonemapModeNone
以外の値に設定されている場合、メイン レンダー パス中(またはスカイ ボックスがある場合はスカイボックス レンダリング中)に実行されるトーンマッピングは、SceneEnvironment で指定されているポストプロセス エフェクトが少なくとも 1 つある場合、自動的に無効になります。 チェーンの最後のエフェクト(正確には、チェーンの最後のエフェクトの最後のパス)は、メイン レンダー パスで実行されるのと同じトーンマッピングを実行するように、そのフラグメント シェーダが自動的に修正されます。
注意: 独自のトーンマッピングを行うエフェクトは、tonemapMode をSceneEnvironment.TonemapModeNone
に設定することで、ビルトインのトーンマッピングを無効にしたSceneEnvironment で使用する必要があります。
注記: デフォルトでは、エフェクトの入力として使用されるテクスチャは、16 ビット浮動小数点 RGBA などの浮動小数点テクスチャフォーマットで作成されます。デフォルトでは入力フォーマットに従うので、出力テクスチャのフォーマットも同じです。これはBuffer と空の名前を使って上書きできます。デフォルトのRGBA16Fは、0-1の範囲外のカラー値がクランプされることなく、トーンマップされていない線形データを扱うことができるので便利です。
シェーダにデータを公開する
CustomMaterial やShaderEffect のように、Effect オブジェクトのダイナミックプロパティは、通常の QML や Qt Quick の機能を使用して変更したりアニメーションさせることができ、その値は自動的にシェーダに公開されます。以下のリストは、プロパティがどのようにマッピングされるかを示しています:
- bool、int、real -> bool、int、float
- QColorbool, int, real -> bool, int, float,color -> vec4, QML で指定されたカラー値に対して sRGB 空間を仮定してカラーがリニアに変換されます。
"green"
のような Qt 組み込みの色も同様に sRGB 色空間であり、DefaultMaterial やPrincipledMaterial のすべての色プロパティに対して同じ変換が行われるため、Effect のこの動作はこれらに一致します。 - QRect QRectF, -> vec4rect
- QPoint QPointF, , , , -> vec2point QSize QSizeF size
- QVector2D vector2d -> vec3
- QVector3D vector3d -> vec3
- QVector4D vector4d -> vec4
- QMatrix4x4 matrix4x4 -> mat4
- QQuaternion quaternion -> vec4、スカラー値は
w
- TextureInput -> のテクスチャ・プロパティで と のどちらが使用されているかによって、サンプラー2D またはサンプラー立方体になります。 プロパティを false に設定すると、シェーダーにダミーのテクスチャが公開されます。つまり、シェーダーはまだ機能しますが、不透明な黒い画像コンテンツを持つテクスチャをサンプリングします。サンプラー用のプロパティは、 を直接参照するのではなく、常に オブジェクトを参照しなければならないという事実に注意してください。 プロパティに関して言えば、ソース、タイリング、フィルタリング関連のものだけが、エフェクトで暗黙的に考慮されるものです。残りのもの(UV 変換など)は、カスタムシェーダーが適切と考えるように実装することができます。TextureInput Texture CubeMapTexture enabled Texture TextureInput Texture
注意: シェーダコードで参照されるユニフォームに対応するプロパティがない場合、実行時にエフェクトを処理する際にシェーダのコンパイルエラーが発生します。サンプラーユニフォームのように、対応する QML プロパティが存在しない場合、ダミーテクスチャがバインドされる例外もありますが、一般的なルールとして、すべてのユニフォームとサンプラーは、エフェクトオブジェクトで対応するプロパティが宣言されている必要があります。
ユーザー定義エフェクトを始める
カスタムポストプロセッシングエフェクトには、最低でも Effect オブジェクトとフラグメントシェーダースニペットが必要です。エフェクトによっては、カスタマイズされたバーテックスシェーダも必要になります。
簡単な例として、シーンのコンテンツと画像を組み合わせ、さらに赤チャンネルの値をアニメーション的に変化させるエフェクトを作ってみましょう:
Effect { id: simpleEffect property TextureInput tex: TextureInput { texture: Texture { source: "image.png" } } property real redLevel NumberAnimation on redLevel { from: 0; to: 1; duration: 5000; loops: -1 } passes: Pass { shaders: Shader { stage: Shader.Fragment shader: "effect.frag" } } } | void MAIN() { vec4 c = texture(tex, TEXTURE_UV); c.r *= redLevel; FRAGCOLOR = c * texture(INPUT, INPUT_UV); } |
ここでは、画像image.png
を持つテクスチャが、tex
という名前でシェーダに公開されています。redLevel の値は、シェーダ内で同じ名前のfloat
ユニフォームで利用可能です。
フラグメントシェーダはMAIN
という関数を含んでいなければなりません。最終的なフラグメントの色はFRAGCOLOR
によって決定されます。メイン入力テクスチャは、View3D のシーンの内容で、INPUT
という名前でsampler2D
からアクセスできます。クワッドからのUV座標はINPUT_UV
にあります。これらのUV値は、実行時のグラフィックスAPIに関係なく(必要な調整はQt Quick 3Dによって自動的に適用されるため、画像のY軸方向に関係なく)、常にINPUT
のサンプリングに適しています。外部画像によるテクスチャのサンプリングは、TEXTURE_UV
を使用して行われます。INPUT_UV
は、画像に基づくテクスチャとレンダーターゲットとして使用されるテクスチャで異なるロジックを使用して、前述の座標系の違いに対応するために V を反転する必要があるため、クロスプラットフォームアプリケーションには適していません。幸いなことに、これはすべてエンジンによって処理されるので、シェーダはこれ以上のロジックを必要としません。
simpleEffect が利用可能になると、View3D のSceneEnvironment のエフェクトリストに関連付けることができます:
environment: SceneEnvironment { effects: [ simpleEffect ] }
結果は次のようになり、左側が元のシーン、右側がエフェクトを適用したシーンになります:
注: Shader のshader
プロパティの値は、QML や Qt Quick のカスタムと同様に URL で、シェーダースニペットを含むファイルを参照し、ShaderEffect やImage.source とよく似た動作をします。file
とqrc
のスキームのみがサポートされています。file
スキームを省略することも可能で、便利な方法で相対パスを指定できます。このようなパスは、コンポーネント(.qml
ファイル)の場所からの相対パスとして解決されます。
注 : シェーダーコードは、Qt が実行時に使用するグラフィックス API に関係なく、常に Vulkan スタイルの GLSL を使用して提供されます。
注意 : エフェクトによって提供される頂点シェーダーとフラグメントシェーダーのコードは、それ自体が完全な GLSL シェーダーではありません。むしろ、MAIN
関数と、オプションでVARYING
宣言のセットを提供し、それをエンジンがさらにシェーダーコードで修正します。
注: 上記の例は、一部の VR/AR アプリケーションで使用されるオプションのマルチビューレン ダリングモードとは互換性がありません。マルチビューモードの有無にかかわらず機能するようにするには、MAIN() を次のように変更します:
void MAIN() { vec4 c = texture(tex, TEXTURE_UV); c.r *= redLevel; #if QSHADER_VIEW_COUNT >= 2 FRAGCOLOR = c * texture(INPUT, vec3(INPUT_UV, VIEW_INDEX)); #else FRAGCOLOR = c * texture(INPUT, INPUT_UV); #endif }
頂点シェーダを使った効果
頂点シェーダがある場合は、MAIN
という関数を提供しなけれ ばなりません。大半の場合、カスタム頂点シェーダは均質な頂点位置の計算を独自に行いたくはないでしょうが、POSITION
、VERTEX
、MODELVIEWPROJECTION_MATRIX
を使えば可能です。POSITION
がカスタムシェーダーのコードに存在しない場合、POSITION = MODELVIEWPROJECTION_MATRIX * vec4(VERTEX, 1.0);
と同等のステートメントが Qt Quick 3D によって自動的に注入されます。
頂点シェーダとフラグメントシェーダの間でデータを渡すには、VARYING キーワードを使用します。内部的に、これは適切な頂点出力またはフラグメント入力宣言に変換されます。フラグメントシェーダも同じ宣言を使用でき、現在のフラグメントの補間値を読み込むことができます。
組み込みの DistortionSpiral エフェクトとよく似た例を見てみましょう:
VARYING vec2 center_vec; void MAIN() { center_vec = INPUT_UV - vec2(0.5, 0.5); center_vec.y *= INPUT_SIZE.y / INPUT_SIZE.x; } | VARYING vec2 center_vec; void MAIN() { float radius = 0.25; float dist_to_center = length(center_vec) / radius; vec2 texcoord = INPUT_UV; if (dist_to_center <= 1.0) { float rotation_amount = (1.0 - dist_to_center) * (1.0 - dist_to_center); float r = radians(360.0) * rotation_amount / 4.0; mat2 rotation = mat2(cos(r), sin(r), -sin(r), cos(r)); texcoord = vec2(0.5, 0.5) + rotation * (INPUT_UV - vec2(0.5, 0.5)); } FRAGCOLOR = texture(INPUT, texcoord); } |
Effectオブジェクトのpasses
リストは、頂点とフラグメントの両方のスニペットを指定する必要があります:
passes: Pass { shaders: [ Shader { stage: Shader.Vertex shader: "effect.vert" }, Shader { stage: Shader.Fragment shader: "effect.frag" } ] }
最終結果は次のようになります:
エフェクトシェーダの特殊キーワード
VARYING
- 現在のシェーダのタイプに応じて、頂点出力またはフラグメント入力を宣言 します。MAIN
- この関数はエフェクトシェーダ内に必ず存在する必要があります。FRAGCOLOR
- - 最終的なフラグメントの色。フラグメントシェーダの出力。(フラグメントシェーダーの出力。)vec4
POSITION
- - 頂点シェーダで計算された均質位置。(頂点シェーダのみ)。vec4
MODELVIEWPROJECTION_MATRIX
- - スクリーン四辺形の変換行列。mat4
VERTEX
- - 頂点シェーダへの入力。(頂点シェーダのみ)。vec3
INPUT
- または - シーンがレンダリングされた入力テクスチャのサンプラー。ただし、パスが オブジェクトを介して入力をリダイレクトする場合を除きます。その場合、 は、 によって参照される追加カラーバッファのテクスチャを参照します。 VR/AR アプリケーションに関連する可能性があるsampler2D
sampler2DArray
BufferInputINPUT
BufferInputマルチビューレンダリングを有効にすると、これは sampler2DArray になり、入力テクスチャは 2D テクスチャ配列になります。INPUT_UV
- - サンプリング用のUV座標 .vec2
INPUT
TEXTURE_UV
- - 画像ファイルから読み込まれた内容のテクスチャをサンプリングするのに適したUV座標。vec2
INPUT_SIZE
- - テクスチャのサイズ(ピクセル単位)。vec2
INPUT
OUTPUT_SIZE
- - 出力バッファのサイズ(ピクセル単位)。多くの場合、 と同じです。ただし、パスの出力先が、サイズ乗数を持つ追加のバッファである場合を除きます。vec2
INPUT_SIZE
FRAME
- - フレームカウンタ。 の各フレームの後にインクリメントされます。float
View3DDEPTH_TEXTURE
- - 深度テクスチャで、深度バッファのコンテンツとシーン内の不透明なオブジェクト。 と同様に、シェーダ内にこのキーワードが存在すると、デプステクスチャが自動的に生成されます。sampler2D
CustomMaterialVIEW_INDEX
- -uint
マルチビューレンダリングが有効な場合、これは頂点シェーダとフラグメントシェーダの両方で利用可能な現在のビューインデックスです。マルチビューレンダリングを使用しない場合は常に 0 です。
マルチパスエフェクトの構築
マルチパスエフェクトは複数のシェーダを使用することが多く、output とcommands プロパティを使用します。パスリストの各エントリは、エフェクトの入力テクスチャとオプションで他のテクスチャもサンプリングしながら、パスの出力テクスチャに四角形を描画するレンダーパスに変換されます。
マルチパスエフェクトの典型的なアウトラインは次のようになります:
passes: [ Pass { shaders: [ Shader { stage: Shader.Vertex shader: "pass1.vert" }, Shader { stage: Shader.Fragment shader: "pass1.frag" } // This pass outputs to the intermediate texture described // by the Buffer object. output: intermediateColorBuffer ], }, Pass { shaders: [ Shader { stage: Shader.Vertex shader: "pass2.vert" }, Shader { stage: Shader.Fragment shader: "pass2.frag" } // The output of the last pass needs no redirection, it is // the final result of the effect. ], commands: [ // This pass reads from the intermediate texture, meaning // INPUT in the shader will refer to the texture associated // with the Buffer. BufferInput { buffer: intermediateColorBuffer } ] } ]
intermediateColorBuffer
とは何ですか?
Buffer { id: intermediateColorBuffer name: "tempBuffer" // format: Buffer.RGBA8 // textureFilterOperation: Buffer.Linear // textureCoordOperation: Buffer.ClampToEdge }
コメントされたプロパティは、希望する値がデフォルトと一致する場合は必要ありません。
内部的には、この Buffer オブジェクトが存在し、Pass のoutput
プロパティからそれを参照すると、View3D に一致するサイズのテクスチャが作成され、暗黙の入力および出力テクスチャのサイズになります。これを望まない場合は、sizeMultiplier プロパティを使用して、異なるサイズの中間テクスチャを取得できます。これは、シェーダ内のINPUT_SIZE
とOUTPUT_SIZE
ユニフォームが異なる値を持つことにつながります。
デフォルトでは、エフェクトはテクスチャがフレーム間でその内容を保持することを当てにできません。新しい中間テクスチャが作成されると、それはvec4(0.0)
にクリアされます。その後、同じテクスチャを別の目的で再利用できます。したがって、エフェクトパスは、パスの開始時にそのコンテンツについて仮定することなく、常にテクスチャ全体に書き込む必要があります。これには例外があります:bufferFlags が Buffer.SceneLifetime に設定された Buffer オブジェクトです。これは、テクスチャが永久にエフェクトのパスに関連付けられ、他の目的で再利用されないことを示します。このようなカラーバッファの内容は、フレーム間で保存されます。これは通常、モーションブラーのようなエフェクトでピンポン方式で使用されます。最初のパスは、エフェクトのメイン入力テクスチャに加えてパーシステントバッファを入力として受け取り、別の中間バッファに出力し、2番目のパスはパーシステントバッファに出力します。このようにして、最初のフレームでは、最初のパスは空の(透明な)テクスチャをサンプリングし、それ以降のフレームでは、前のフレームの2番目のパスの出力をサンプリングします。3番目のパスは、エフェクトの入力と2番目のパスの出力を一緒にブレンドすることができます。
BufferInput コマンドタイプは、レンダーパスにカスタムテクスチャバッファを公開するために使用されます。
たとえば、mySampler
という名前でレンダーパスシェーダのsomeBuffer
にアクセスするには、そのコマンドリストに次のように追加します:
BufferInput { buffer: someBuffer; sampler: "mySampler" }
sampler
の名前が指定されない場合、デフォルトとしてINPUT
が使用されます。
バッファはレンダーパス間で中間結果を共有するのに便利です。
プリロードされたテクスチャをエフェクトに公開するには、代わりにTextureInput を使用する必要があります。これらはエフェクト自体のプロパティとして定義でき、そのプロパティ名によってシェーダから自動的にアクセスできるようになります。
property TextureInput tex: TextureInput { texture: Texture { source: "image.png" } }
ここでは、tex
は、エフェクトのすべてのパスのすべてのシェーダーで有効なサンプラーです。
プロパティからの均一な値に関しては、エフェクトのすべてのパスは、それらのシェーダで同じ値を読み取ります。必要であれば、特定のパスのユニフォームの値をオーバーライドすることができます。これは、SetUniformValue コマンドをパスのコマンドリストに追加することで実現できます。
注意: パス固有のユニフォーム値セッターのtarget は、エフェクトのプロパティ名である名前のみを参照できます。プロパティの対応するユニフォームの値をオーバーライドすることはできますが、新しいユニフォームを導入することはできません。
パフォーマンスに関する考慮事項
後処理エフェクトを使用する場合、リソースの使用量が増え、パフォーマンスが低下する可能性があることに注意してください。Qt Quick layers やShaderEffect のように、シーンをテクスチャにレンダリングし、それを使ってクアッドにテクスチャを貼ることは、特にフラグメントの処理能力に制限のあるローエンドハードウェアでは、安い操作ではありません。追加で必要なグラフィックメモリの量と GPU 負荷の増加は、どちらもView3D のサイズに依存します(ウィンドウシステムのない組み込みデバイスでは、画面解像度と同じ大きさになることがよくあります)。マルチパスエフェクトや複数のエフェクトを適用すると、必要なリソースやパフォーマンスがさらに増加します。
したがって、開発ライフサイクルの早い段階で、ターゲットとするデバイスとグラフィックススタックが、最終製品の画面解像度で3Dシーンのデザインに含まれるエフェクトに対応できることを確認することが非常に推奨されます。
それが必要なテクニックでは避けられませんが、DEPTH_TEXTURE
は、そのテクスチャのコンテンツを生成するための追加のレンダリングパスを意味し、性能の低いハードウェアではヒットする可能性もあります。したがって、エフェクトのシェーダでDEPTH_TEXTURE
を使用するのは、必 要なときだけにしてください。
シェーダ内の演算の複雑さも重要です。CustomMaterial と同様、最適でないフラグメントシェーダは、レンダリング性能の 低下につながりやすくなります。
1 よりも大きな値が関係するときは、sizeMultiplier in Buffer に注意してください。たとえば、乗数 4 は、View3D の 4 倍の大きさのテクスチャを作成し、それにレンダリングすることを意味します。 シャドウマップやマルチサンプリング、スーパーサンプリングと同様、GPU のパワーが限られたシステムでは、リソースや性能のコスト増が、品質向上によるメリットをすぐに上回っ てしまう可能性があります。
VR/AR に関する考慮事項
Qt Quick 3D XR を使用して仮想現実や拡張現実向けのアプリケーションを開発する場合、ポストプロセッシングエフェクトを機能的に使用することができます。しかし、デザイナーや開発者は、どのようなエフェクトがバーチャルリアリティ環境で意味を持つかを理解するために、特別な注意を払う必要があります。エフェクトの中には、ExtendedSceneEnvironment のビルトイン・エフェクトや、非推奨のエフェクト・モジュールを含め、VR 環境で良好な視覚体験をもたらさないものもあり、ユーザーに身体的な影響(例えば、乗り物酔いやめまいなど)を与える可能性もあります。
VR/ARアプリケーションでより効率的なマルチビューレンダリングモードが有効になっている場合、左目と右目のコンテンツ用に別々のレンダーパスが発生することはありません。代わりに、2つの独立した2Dテクスチャの代わりに、2つのレイヤーを持つ2Dテクスチャ配列を使用して、すべて1つのパスで行われます。これはまた、カラーまたは深度テクスチャを意味する多くの中間バッファが、このモードではテクスチャ配列になる必要があることを意味します。これは、カスタムマテリアルとポストプロセッシングエフェクトに影響します。入力テクスチャ (INPUT
)、深度テクスチャ (DEPTH_TEXTURE
)、スクリーンテクスチャ (SCREEN_TEXTURE
) などのテクスチャは 2D テクスチャ配列になり、sampler2D
の代わりにsampler2DArray
としてシェーダで公開されます。これは texture(), textureLod(), textureSize() などの GLSL 関数に影響します。UV 座標は vec2 ではなく vec3 になります。一方textureSize()はvec2ではなくvec3を返します。レンダリングモードに関係なく機能するように意図されたエフェクトは、適切なifdefで記述することができます:
#if QSHADER_VIEW_COUNT >= 2 vec4 c = texture(INPUT, vec3(INPUT_UV, VIEW_INDEX)); #else vec4 c = texture(INPUT, INPUT_UV); #endif
Shader,Pass,Buffer,BufferInput,Qt Quick 3D - Custom Effect Exampleも参照してください 。
プロパティのドキュメント
本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。