Qt Quick 3D - カスタムマテリアルの例
シェーディングされたカスタムマテリアルの作成方法を示します。

この例では、シェーディング処理が施された custom materials の作成方法を示します。シェーディング処理が施されたマテリアルを使用する場合、完全なシェーダープログラムを記述する必要はありません。代わりに、Qtの標準シェーダーを修正する関数を記述します。これにより、生成されたマテリアルはデフォルトでライティングやシャドウマッピングに参加し、ライトプローブとの互換性も確保されます。 特別な動作を必要とするケースについてのみ、カスタムロジックを記述すれば済みます。これは、PrincipledMaterial 用に生成されるシェーダーコードを、頂点シェーダーおよびフラグメントシェーダーの特定の段階で呼び出される独自のカスタム関数で効果的に拡張することで実現されます。
シェーディングされたカスタムマテリアルを作成するには、shadingMode プロパティをCustomMaterial.Shaded に設定します。
単純なマテリアル
最初のモデルでは、カスタムロジックを一切追加しないシンプルなマテリアルを使用しています。このカスタムマテリアルは、他のマテリアルと同様にモデルに設定します:
Model {
source: "weirdShape.mesh"
scale: Qt.vector3d(100, 100, 100)
rotation: Quaternion.fromEulerAngles(-90, 0, 0)
x: v3d.radius
materials: [
CustomMaterial {
shadingMode: CustomMaterial.Shaded
fragmentShader: "material_simple.frag"
property color uDiffuse: "fuchsia"
property real uSpecular: 1.0
}
]
}shadingMode とfragmentShader を設定するほか、マテリアルにuDiffuse とSpecular という2つのプロパティを追加します。これらはフラグメントシェーダーによって読み込まれます。
フラグメントシェーダーのコードは簡潔です:
void MAIN()
{
SPECULAR_AMOUNT = uSpecular;
BASE_COLOR = uDiffuse;
}すべてのシェーダーは、MAIN 関数を実装する必要があります。この関数では、マテリアルで定義されたプロパティを使用して、Qtの標準シェーダーコードで使用される値を設定します。これらをユニフォームとして宣言する必要はない点に注意してください。必要なのは、名前が一致していることを確認することだけです。 マテリアルに一致するプロパティがない場合、シェーダーのコンパイルエラーが発生します。
特殊変数SPECULAR_AMOUNT およびBASE_COLOR は、PrincipledMaterial のspecularAmount およびbaseColor に対応しています。これらは、PrincipledMaterial を使用したのと同様に、標準シェーダーコードによってライティング計算を行うために使用されます。
ライトのカスタム処理
次のオブジェクトでは、カスタムライティングを実装した、より複雑なマテリアルを使用します。このマテリアルではユニフォーム名の呼び方が異なりますが、それ以外の使用方法は同じです:
materials: [
CustomMaterial {
shadingMode: CustomMaterial.Shaded
fragmentShader: "material_customlights.frag"
property color uDiffuse: "orange"
property real uShininess: 150
}
]フラグメントシェーダーでは、あらゆる種類のライトに対して独自のロジックを実装しています:
void MAIN()
{
SPECULAR_AMOUNT = 1.0;
ROUGHNESS = 0.5;
BASE_COLOR = uDiffuse;
}
void AMBIENT_LIGHT()
{
DIFFUSE += uDiffuse.rgb * TOTAL_AMBIENT_COLOR;
}
void DIRECTIONAL_LIGHT()
{
DIFFUSE += uDiffuse.rgb * LIGHT_COLOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(NORMAL), TO_LIGHT_DIR)));
}
void POINT_LIGHT()
{
DIFFUSE += uDiffuse.rgb * LIGHT_COLOR * LIGHT_ATTENUATION * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(NORMAL), TO_LIGHT_DIR)));
}
void SPOT_LIGHT()
{
DIFFUSE += uDiffuse.rgb * LIGHT_COLOR * LIGHT_ATTENUATION * SPOT_FACTOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
}ここでは、さまざまな光の種類に関するプロパティを参照する、多くの新しい特殊キーワードを使用しています。各キーワードの説明については、『CustomMaterial 』のドキュメントを参照してください。各光の種類には独自の関数があることに注意してください。実装されていない関数についてはデフォルトの実装が使用され、PrincipledMaterial のように動作します。例えば、このシェーダーではSPECULAR_LIGHT() を実装していないため、組み込みのスペキュラー反射が得られます。
頂点シェーダーの追加
カスタムマテリアルでは、頂点シェーダーを使用してモデルのジオメトリを変更することもできます。ここでは、フラグメントシェーダーと頂点シェーダーの両方を指定し、ユニフォーム値として取り込まれるプロパティをいくつか追加しています:
materials: [
CustomMaterial {
id: material
shadingMode: CustomMaterial.Shaded
vertexShader: "material_distortion.vert"
fragmentShader: "material_customlights.frag"
property real uTime: 0.0
property real uAmplitude: 0.3
property color uDiffuse: "yellow"
property real uShininess: 50
NumberAnimation {
target: material
property: "uTime"
from: 0.0
to: 31.4
duration: 10000
loops: Animation.Infinite
running: true
}
}
]頂点シェーダーは非常に短いです:
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void MAIN()
{
VERTEX.y += sin(uTime + VERTEX.x*10.0) * uAmplitude;
}これにより、時間とともに変化する正弦波に従って各頂点を変位させ、モデルを変形させます。
透明なマテリアル
最後に、透明なマテリアルを持つ球体を追加します。パフォーマンス上の理由から、Qtでは透明性を完全にリアルな方法で実装していません。その代わりに、Qtはシーン内のすべての不透明なオブジェクトをテクスチャにレンダリングし、透明なマテリアルはこのテクスチャから読み取ります。つまり、透明なマテリアルは他のオブジェクトの前に配置されたときに最良の結果が得られます:
Model {
id: screenSphere
source: "#Sphere"
scale: Qt.vector3d(0.75, 0.75, 0.75)
y: 60
z: 750;
materials: [
CustomMaterial {
shadingMode: CustomMaterial.Shaded
fragmentShader: "material_transparent.frag"
}
]この例では、物理的な屈折を再現しようとしない単純な歪み関数を実装します:
void MAIN()
{
vec2 size = vec2(textureSize(SCREEN_TEXTURE, 0));
vec2 uv = FRAGCOORD.xy / size;
vec3 view = normalize(VIEW_VECTOR);
vec3 projection = view - view * normalize(NORMAL);
vec3 refraction = projection * projection;
uv += refraction.xy * 0.5;
vec3 col = texture(SCREEN_TEXTURE, uv).rgb;
col = col * 0.8 + vec3(0.2);
BASE_COLOR = vec4(col, 1.0);
}SCREEN_TEXTURE は、シーン内のすべての不透明なオブジェクトを表示するテクスチャを指します。まず、このテクスチャ内で、現在の頂点の画面上の位置に一致する UV 座標を計算します。次に、テクスチャのルックアップを行う前に、この位置にオフセットを加えて屈折効果をシミュレートします。
最後に、20%の白をブレンドして、わずかな曇り感を出します。出力はBASE_COLOR に割り当てられているため、Qtがこの上に照明を追加することに注意してください。これが、球体の表面に反射が見える理由です。
シェーディングなしのマテリアル
また、(便利なキーワードを使いながらも)完全なシェーダープログラムを使用するカスタムマテリアルを作成することも可能です。「customshaders」のサンプルでは、もう一つのカスタムマテリアルのグループである「アンシェーディングされたカスタムマテリアル」を紹介しています。
© 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.