ShaderEffect QML Type

カスタムシェーダを矩形に適用します。詳細...

Import Statement: import QtQuick
Inherits:

Item

プロパティ

詳細説明

ShaderEffect タイプは、カスタムvertex およびfragment (pixel) シェーダを矩形に適用します。これにより、ドロップシャドウ、ぼかし、カラーライズ、ページカールなどのエフェクトを QML シーンに追加することができます。

注意: 使用している Qt Quick scenegraph バックエンドによっては、ShaderEffect タイプがサポートされていない場合があります。例えば、software バックエンドでは、エフェクトは全くレンダリングされません。

シェーダー

Qt 5では、エフェクトはGLSL(OpenGL Shading Language)のソースコードで提供され、多くの場合、QMLに文字列として埋め込まれていました。Qt 5.8 から、ローカルまたは Qt リソースシステム内のファイルを参照できるようになりました。

Qt 6では、Qt QuickはVulkan、Metal、Direct3D 11などのグラフィックスAPIもサポートしています。そのため、GLSLソース・ストリングでの作業はもはや不可能です。むしろ、新しいシェーダー・パイプラインは、Vulkan互換のGLSLコードをSPIR-Vにコンパイルし、その後、リフレクション情報を収集し、HLSL、Metal Shading Language、さまざまなGLSLバージョンなどの他のシェーディング言語に翻訳することに基づいています。出来上がったアセットは1つのパッケージにまとめられ、通常、.qsb の拡張子を持つファイルに保存されます。このプロセスはオフラインで行われるか、遅くともアプリケーションのビルド時に行われます。実行時に、シーングラフと基礎となるグラフィックス抽象化は、これらの.qsb ファイルを消費します。したがって、ShaderEffect は、インラインシェーダーコードの代わりに、Qt 6 のファイル(ローカルまたは qrc)参照を期待します。

vertexShaderfragmentShader プロパティは Qt 6 の URL であり、例えばImage.source とよく似た動作をします。ただし、ShaderEffect でサポートされているのはfileqrc のスキームのみです。file スキームを省略することも可能で、便利な方法で相対パスを指定できます。このようなパスは、コンポーネント(.qml ファイル)の場所からの相対パスとして解決されます。

シェーダーの入力とリソース

vertexShader への入力には、ユニフォーム入力と頂点入力の 2 種類があります。

以下の入力は定義済みです:

  • vec4 qt_Vertex (位置 0 - 頂点の位置)、左上の頂点の位置は (0, 0)、右下の頂点の位置は (width,height)。
  • vec2 qt_MultiTexCoord0 は位置 1 - テクスチャ座標で、左上の座標は (0, 0)、右下の座標は (1, 1) です。supportsAtlasTextures がtrueの場合、座標は代わりにアトラス内の位置に基づきます。

注意: 実際に重要なのは頂点の入力位置だけです。名前は自由に変更できますが、位置は常に頂点位置の場合は0 、テクスチャ座標の場合は1 でなければなりません。ただし、これは頂点入力にのみ適用され、フラグメントシェーダで入力として使用される頂点シェーダからの出力変数(典型的には補間されたテクスチャ座標)には必ずしも当てはまらないことに注意してください。

以下のユニフォームが定義済みです:

  • mat4 qt_Matrix - 結合された変換行列で、ルート項目からこの ShaderEffect への行列の積、および直交投影。
  • float qt_Opacity - 結合された不透明度、ルートアイテムからこの ShaderEffect までの不透明度の積。

注意: VulkanスタイルのGLSLには、個別のユニフォーム変数がありません。代わりに、シェーダは常に0 のバインディングポイントを持つユニフォームブロックを使用する必要があります。

注意 : ユニフォームブロックレイアウト修飾子は常にstd140 でなければなりません。

注意 :頂点入力とは異なり、定義済みの名前(qt_Matrix、qt_Opacity)は変更してはいけません。

さらに、GLSL タイプにマッピングできるプロパティはすべて、シェーダで利用可能 にすることができます。以下のリストは、プロパティがどのようにマッピングされるかを示しています:

  • bool, int, qreal -> bool, int, float - シェーダの型が QML の型と異なる場合、値は自動的に変換されます。
  • QColor -> vec4 - シェーダに色が渡されるとき、最初に乗算されます。したがって、Qt.rgba(0.2, 0.6, 1.0, 0.5) はシェーダでは vec4(0.1, 0.3, 0.5, 0.5) になります。
  • QRect,QRectF -> vec4 - Qt.rect(x, y, w, h) はシェーダでは vec4(x, y, w, h) になります。
  • QPoint QPointF, , -> vec2QSize QSizeF
  • QVector3D -> vec3
  • QVector4D -> vec4
  • QTransform -> mat3
  • QMatrix4x4 -> mat4
  • QQuaternion -> vec4、スカラー値は 。w
  • Image -> sampler2D - Originは左上隅にあり、カラー値は事前乗算されます。テクスチャは、Image アイテムの fillMode を除いて、そのまま提供されます。fillMode を含めるには、 または Image::layer::enabled を使用します。ShaderEffectSource
  • ShaderEffectSource -> sampler2D - 原点は左上隅にあり、色の値は事前乗算されます。

サンプラーは、シェーダーコードの中で、別のユニフォーム変数として宣言されたままです。シェーダはこれらのバインディングポイントを自由に選択できます。ただし、0 はユニフォームブロックのために予約されています。

シェーディング言語やAPIの中には、イメージオブジェクトとサンプラーオブジェクトを分けて考えるものがあります。Qt Quickは、SPIR-Vでサポートされているように、シェーダーでは常にイメージ・サンプラー・オブジェクトを組み合わせて動作します。したがって、ShaderEffect用に提供されるシェーダは、常にlayout(binding = 1) uniform sampler2D tex; スタイルのサンプラ宣言を使用する必要があります。基礎となる抽象化レイヤとシェーダーパイプラインは、アプリケーションに対して透過的に、サポートされるすべてのAPIとシェーディング言語に対して、この作業を行います。

QMLシーングラフバックエンドは、テクスチャアトラスにテクスチャを割り当てることができます。アトラスに割り当てられたテクスチャがShaderEffectに渡される場合、デフォルトではテクスチャ座標が0から1になるように、テクスチャアトラスからスタンドアロンテクスチャにコピーされ、期待されるラップモードが得られます。しかし、これはメモリ使用量を増加させます。テクスチャのコピーを避けるには、 qt_MultiTexCoord0 を使ってシンプルシェーダ用にsupportsAtlasTextures を設定するか、各 "uniform sampler2D <name>" に対して、テクスチャの正規化されたソース矩形が割り当てられる "uniform vec4 qt_SubRect_<name>" を宣言します。スタンドアロンテクスチャの場合、ソース矩形は [0, 1]x[0, 1] です。アトラス内のテクスチャの場合、ソース矩形はテクスチャが保存されているテクスチャアトラスの部分に対応します。テクスチャアトラス内の「ソース」と呼ばれるテクスチャのテクスチャ座標を計算する正しい方法は、「qt_SubRect_source.xy + qt_SubRect_source.zw * qt_MultiTexCoord0」です。

fragmentShader からの出力は事前に乗算されている必要があります。blending が有効な場合、ソースオーバーブレンディングが使用されます。ただし、アルファチャンネルにゼロを出力することで、加算ブレンドを実現できます。

import QtQuick 2.0

Rectangle {
    width: 200; height: 100
    Row {
        Image { id: img;
                sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
        ShaderEffect {
            width: 100; height: 100
            property variant src: img
            vertexShader: "myeffect.vert.qsb"
            fragmentShader: "myeffect.frag.qsb"
        }
    }
}

この例では、myeffect.vertmyeffect.frag に Vulkan スタイルの GLSL コードが含まれており、qsb ツールで処理されて.qsb ファイルが生成されると仮定しています。

#version 440
layout(location = 0) in vec4 qt_Vertex;
layout(location = 1) in vec2 qt_MultiTexCoord0;
layout(location = 0) out vec2 coord;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
void main() {
    coord = qt_MultiTexCoord0;
    gl_Position = qt_Matrix * qt_Vertex;
}
#version 440
layout(location = 0) in vec2 coord;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D src;
void main() {
    vec4 tex = texture(src, coord);
    fragColor = vec4(vec3(dot(tex.rgb, vec3(0.344, 0.5, 0.156))), tex.a) * qt_Opacity;
}

Note: Scene Graph テクスチャは、OpenGL で一般的な左下ではなく、左上に原点があります。

シェーダーを1つだけ持つ

vertexShaderfragmentShader の両方を指定することは必須ではありません。多くの ShaderEffect 実装は、デフォルトのビルトイン頂点シェーダに依存しながら、実際にはフラグメントシェーダのみを提供したいと思うでしょう。

デフォルトの頂点シェーダは、テクスチャ座標を0 の位置vec2 qt_TexCoord0 としてフラグメントシェーダに渡します。

デフォルトのフラグメントシェーダは、テクスチャ座標が頂点シェーダから0 の位置でvec2 qt_TexCoord0 として渡されることを期待し、バインディングポイント1source という名前のサンプラ 2D からサンプリングします。

警告 警告:シェーダが1つだけ指定されている場合、シェーダのライタはデフォルトのシェーダが期待するユニフォームブロックレイアウトを認識している必要があります:qt_Matrix は常にオフセット 0 にあり、qt_Opacity がオフセット 64 に続いていなければなりません。qt_Matrixは常にオフセット0に、qt_Opacityはオフセット64に置かなければなりません。これは、アプリケーションが提供するシェーダが行列や不透明度を使用しない場合でも必須です。なぜなら、実行時に頂点シェーダとフラグメントシェーダの両方に公開される単一のユニフォームバッファが存在するからです。

警告 頂点入力の場合とは異なり、頂点シェーダとフラグメントシェーダの 間でデータを渡す場合、基礎となるグラフィックス API によっては、 同じ名前を使用する必要があるかもしれません。最も顕著なのは、デフォルトのビルトイン頂点シェーダに依存しなが らフラグメントシェーダを指定する場合、テクスチャ座標は0 の位置qt_TexCoord0 として渡されるため、フラグメントシェーダは同じ名前(qt_TexCoord0)で入力を宣言することを強く推奨します。たとえば、基礎となる GLSL シェーダソースコードにロケーション修飾子がなく、シェーダリンク処理中の変数名に基づいてマッチングが行われる非コアプロファイルの OpenGL コンテキストで実行する場合などです。

ShaderEffectとアイテムレイヤー

ShaderEffect タイプはlayered items と組み合わせることができます。

エフェクト無効のレイヤー エフェクトが有効なレイヤー
Item {
    id: layerRoot
    layer.enabled: true
    layer.effect: ShaderEffect {
       fragmentShader: "effect.frag.qsb"
    }
}
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D source;
void main() {
    vec4 p = texture(source, qt_TexCoord0);
    float g = dot(p.xyz, vec3(0.344, 0.5, 0.156));
    fragColor = vec4(g, g, g, p.a) * qt_Opacity;
}

複数のレイヤーアイテムを組み合わせることも可能です:

Rectangle {
    id: gradientRect;
    width: 10
    height: 10
    gradient: Gradient {
        GradientStop { position: 0; color: "white" }
        GradientStop { position: 1; color: "steelblue" }
    }
    visible: false; // should not be visible on screen.
    layer.enabled: true;
    layer.smooth: true
 }
 Text {
    id: textItem
    font.pixelSize: 48
    text: "Gradient Text"
    anchors.centerIn: parent
    layer.enabled: true
    // This item should be used as the 'mask'
    layer.samplerName: "maskSource"
    layer.effect: ShaderEffect {
        property var colorSource: gradientRect;
        fragmentShader: "mask.frag.qsb"
    }
}
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D colorSource;
layout(binding = 2) uniform sampler2D maskSource;
void main() {
    fragColor = texture(colorSource, qt_TexCoord0)
                    * texture(maskSource, qt_TexCoord0).a
                    * qt_Opacity;
}

その他の注意事項

デフォルトでは、ShaderEffectは4つの頂点で構成され、各コーナーに1つずつ配置されます。ページカールのような非線形の頂点変換では、mesh の解像度を指定することで、頂点の細かいグリッドを指定できます。

Qt 5 からの移行

ShaderEffect アイテムを使用した Qt 5 アプリケーションでは、Qt 6 への移行が必要です:

  • シェーダーコードを.vert.frag の別々のファイルに移動する、
  • シェーダーを Vulkan 互換の GLSL に更新します、
  • qsb ツールを実行する、
  • Qt リソースシステムで実行ファイルに結果の.qsb ファイルを含める、
  • そして、vertexShaderfragmentShader プロパティでファイルを参照します。

Qt Shader Toolsモジュールで説明されているように、CMake がビルド時にqsb ツールを起動することで、これらのステップの一部を自動化することができます。詳細と例については、Qt Shader Tools Build System Integrationを参照してください。

シェーダーコードの更新に関しては、一般的に必要とされる変更の概要を以下に示します。

Qt 5 の頂点シェーダQt 6 の頂点シェーダ
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 coord;
uniform highp mat4 qt_Matrix;
void main() {
    coord = qt_MultiTexCoord0;
    gl_Position = qt_Matrix * qt_Vertex;
}
#version 440
layout(location = 0) in vec4 qt_Vertex;
layout(location = 1) in vec2 qt_MultiTexCoord0;
layout(location = 0) out vec2 coord;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
void main() {
    coord = qt_MultiTexCoord0;
    gl_Position = qt_Matrix * qt_Vertex;
}

変換プロセスのほとんどは、GL_KHR_vulkan_glsl と互換性があるようにコードを更新することです。Qt Quick は GLSL と Vulkan が提供する機能のサブセットを使用しているため、典型的な ShaderEffect シェーダの変換処理は通常簡単です。

  • GL_KHR_vulkan_glsl拡張はGLSL 140以上のために書かれているため、version ディレクティブは440 または450 、他のGLSLバージョンを指定しても動作します。
  • 入力と出力には最新の GLSLinout キーワードを使用しなければなりません。さらに、場所の指定が必要です。入力と出力のロケーション名前空間は別々なので、両方に0から始まるロケーションを割り当てても安全です。
  • 頂点シェーダ入力に関しては、ShaderEffect で指定できるのは、頂点位置の位置0 (従来はqt_Vertex という名前)とテクスチャ座標の位置1 (従来はqt_MultiTexCoord0 という名前)だけです。
  • 頂点シェーダ出力とフラグメントシェーダ入力は、シェーダコードに よって定義されます。フラグメントシェーダは、vec4 出力が位置 0 になければなりません(通常、fragColor と呼ばれます)。移植性を最大にするために、頂点出力とフラグメント入力は同じ位置番号と同じ名前の両方を使うべきです。フラグメントシェーダのみを指定する場合、テクスチャ座標は、上記のスニペット例に示すように、ビルトイン頂点シェーダから0 の位置にvec2 qt_TexCoord0 として渡されます。
  • ユニフォームブロック外のユニフォーム変数は、合法ではありません。むしろ、ユニフォームデータは、バインディングポイント0 を持つユニフォームブロック内で宣言されなければなりません。
  • 一様ブロックは、 std140 修飾子を使用することが期待されます。
  • 実行時、頂点シェーダとフラグメントシェーダは、バインディングポイント 0 にバインドされた同じユニフォームバッファを取得します。したがって、一般的なルールとして、ユニフォームブロックの宣言は、シェーダ間で同一でなければなりません。これには、どちらかのシェーダで使用されていないメンバも含まれます。いくつかのグラフィックスAPIでは、ユニフォームブロックは、アプリケーションに対して透過的に、従来の構造体ユニフォームに変換されるため、メンバ名は一致する必要があります。
  • シェーダーの1つだけを提供する場合は、組み込みシェーダーがユニフォームブロックの先頭でqt_Matrixqt_Opacity 。(より正確には、それぞれオフセット0と64)一般的なルールとして、常にブロックの最初と2番目のメンバとしてこれらを含めます。
  • この例では、ユニフォーム・ブロックはブロック名buf を指定しています。この名前は自由に変更できますが、シェーダ間で一致する必要があります。layout(...) uniform buf { ... } instance_name; のようなインスタンス名の使用はオプションです。指定した場合、メンバへのアクセスはすべて instance_name で修飾する必要があります。
Qt 5 のフラグメントシェーダQt 6 のフラグメントシェーダ
varying highp vec2 coord;
uniform lowp float qt_Opacity;
uniform sampler2D src;
void main() {
    lowp vec4 tex = texture2D(src, coord);
    gl_FragColor = vec4(vec3(dot(tex.rgb,
                        vec3(0.344, 0.5, 0.156))),
                             tex.a) * qt_Opacity;
}
#version 440
layout(location = 0) in vec2 coord;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
    mat4 qt_Matrix;
    float qt_Opacity;
};
layout(binding = 1) uniform sampler2D src;
void main() {
    vec4 tex = texture(src, coord);
    fragColor = vec4(vec3(dot(tex.rgb,
                     vec3(0.344, 0.5, 0.156))),
                          tex.a) * qt_Opacity;
}
  • 精度修飾子 (lowp,mediump,highp) は現在使用されていません。
  • 組み込み GLSL 関数の呼び出しは、最新の GLSL 名に従わなければなりません。特に、texture2D() の代わりにtexture() を使用します。
  • サンプラーは 1 から始まるバインディングポイントを使用しなければなりません。
  • Qt Quick がmultiview を有効にしてレンダリングされる場合、例えば VR/AR 環境の 3D シーンのレンダリングの一部で、左右の目のコンテンツがシングルパスで生成される場合、ShaderEffect のシェーダはこれを考慮して記述する必要があります。たとえばビュー数が 2 の場合、2 の行列が存在します(qt_Matrix は 2 つの要素を持つ mat4 の配列です)。頂点シェーダはgl_ViewIndex を考慮する必要があります。マルチビュー対応シェーダの作成に関する一般的な情報については、QSB マニュアルの Multiview のセクションを参照してください。

Item LayersQSB マニュアル、およびQt Shader Tools Build System Integrationも参照してください

プロパティ ドキュメント

blending : bool

このプロパティが true の場合、fragmentShader からの出力は、ソースオーバーブレンドモードを使用して背景とブレンドされます。false の場合、背景は無視されます。ブレンドはパフォーマンスを低下させるので、ブレンドが不要な場合はこのプロパティを false に設定する必要があります。デフォルト値はtrueです。


cullMode : enumeration

このプロパティは、アイテムのどの面を表示するかを定義します。

定数説明
ShaderEffect.NoCulling両側が見える
ShaderEffect.BackFaceCulling表側のみ表示
ShaderEffect.FrontFaceCulling裏側のみ表示

デフォルトは NoCulling です。


fragmentShader : url

このプロパティには、前処理されたフラグメントシェーダーパッケージのファイルへの参照が含まれます。通常、拡張子は.qsb です。この値は、Image などの他の QML タイプと同様に、URL として扱われます。ローカルファイルであるか、Qtリソースシステム経由で埋め込まれたファイルにアクセスするためにqrcスキームを使用する必要があります。URLは絶対URLでも、コンポーネントのURLからの相対URLでもかまいません。

vertexShaderも参照してください


log : string [read-only]

このプロパティは、シェーダーをコンパイルしようとした最新の試行からの警告とエラーのログを保持します。このプロパティは、status が Compiled または Error に設定されると同時に更新されます。

注意: Qt 6 では、シェーダパイプラインは、Vulkan スタイルの GLSL シェーダのコンパイルと変換をオフラインで、または遅くともビルド時に行います。これは必ずしも実行時にシェーダーのコンパイルが行われないことを意味しませんが、仮にコンパイルが行われたとしても、ShaderEffect 、その段階で構文エラーや同様のエラーが発生することはありません。したがって、このプロパティの値は通常空です。

statusも参照のこと


mesh : variant

このプロパティは、ShaderEffect の描画に使用されるメッシュを定義します。GridMesh オブジェクトを保持することができます。このプロパティにサイズ値が割り当てられている場合、ShaderEffect は暗黙的に、その値を持つGridMeshmesh resolution として使用します。デフォルトでは、このプロパティのサイズは 1x1 です。

GridMeshも参照


status : enumeration [read-only]

このプロパティは、シェーダーの現在の状態を示します。

定数説明
ShaderEffect.Compiledシェーダプログラムが正常にコンパイルおよびリンクされた。
ShaderEffect.Uncompiledシェーダプログラムはまだコンパイルされていません。
ShaderEffect.Errorシェーダプログラムのコンパイルまたはリンクに失敗しました。

フラグメントシェーダまたは頂点シェーダのソースコードを設定すると、ステータスはUncompiledになります。新しいシェーダソースコードでShaderEffect が初めてレンダリングされると、シェーダがコンパイルおよびリンクされ、ステータスが Compiled または Error に更新されます。

ランタイム・コンパイルが使用されておらず、シェーダのプロパティがバイトコードのファイルを参照している場合、ステータスは常に Compiled になります。シェーダの内容は、レンダリングパイプラインの後半になるまで(頂点入力 要素と定数バッファデータを検出するための基本的なリフレクションを除 いて)検査されないので、潜在的なエラー(レイアウトやルートシグネチャの不一致な ど)は後の時点で初めて検出されます。

logも参照してください


supportsAtlasTextures : bool [since QtQuick 2.4]

シェーダコードが qt_MultiTexCoord0 がメッシュに対して (0,0) から (1,1) までの範囲に依存しないことを確認するには、このプロパティを true に設定します。この場合、qt_MultiTexCoord0 の範囲はむしろアトラス内のテクスチャの位置に基づきます。このプロパティは、シェーダへの入力として使用されるサンプラーユニフォームが1つより少なくても多くても、今のところ何の効果もありません。

これは qt_SubRect_<name> ユニフォームを提供することとは異なり、後者はアトラスから1つ以上のテクスチャを1つのShaderEffect アイテムで描画することを可能にする一方、supportsAtlasTextures はアトラスから異なるソースイメージを使用するShaderEffect コンポーネントの複数のインスタンスを1つの描画でバッチ処理することを可能にします。どちらも、ShaderEffect によって参照されるとき、テクスチャがアトラスからコピーされるのを防ぎます。

デフォルト値は false です。

このプロパティは QtQuick 2.4 で導入されました。


vertexShader : url

このプロパティには、前処理された頂点シェーダーパッケージのファイルへの参照が含まれ、通常、拡張子は.qsb です。この値は、Image などの他の QML タイプと同様に、URL として扱われます。この値はローカルファイルであるか、Qtリソースシステム経由で埋め込まれたファイルにアクセスするためにqrcスキームを使用しなければなりません。URLは絶対URLでも、コンポーネントのURLからの相対URLでもかまいません。

fragmentShaderも参照して ください。


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