- 水ノ茉の宣伝
- 始まり
- マテリアルピンとは?
- エンジン改造とは?
- Substrate (旧: Strata) 非対応
- リポジトリ
- 実装
- Engine/Source/Runtime/Engine/Public/SceneTypes.h
- Engine/Source/Runtime/Engine/Classes/Materials/Material.h
- Engine/Source/Runtime/Engine/Private/Materials/Material.cpp
- Engine/Source/Runtime/Engine/Private/Materials/MaterialAttributeDefinitionMap.cpp
- Engine/Source/Runtime/Engine/Classes/Materials/MaterialExpressionMakeMaterialAttributes.h
- Engine/Source/Runtime/Engine/Private/Materials/MaterialCachedData.cpp
- Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressionHLSL.cpp
- Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressions.cpp
- Engine/Source/Runtime/Engine/Private/Materials/MaterialHLSLEmitter.cpp
- Engine/Source/Runtime/Engine/Private/Materials/HLSLMaterialTranslator.cpp
- Engine/Source/Editor/MaterialEditor/Private/MaterialEditor.cpp
- Engine/Source/Editor/UnrealEd/Private/MaterialGraph.cpp
- Engine/Source/Editor/UnrealEd/Private/MaterialGraphNode_Root.cpp
- Engine/Shaders/Private/MaterialTemplate.ush
- 簡単な動作確認
- おわり!!!
- 関連するエンジン改造
- UMaterialExpressionBreakMaterialAttributes::Serializeで気になっていたことをようやく調べたの
- ゆっくりと ゆっくりと▼ ゆっくりと ゆっくりと▼
水ノ茉の宣伝
準備中...
ゲームを作る予定なの水ノ茉
始まり
マテリアルピンを追加するエンジン改造をしていきます。
マテリアルピンとは?
Base ColorやMetallicなどの最終的な計算結果を接続する部分のことをマテリアルピンと呼びます。
実装を覗いてみるとマテリアルプロパティやインプットという名称も使われているので、またしても正式名称は知らんです。
相手に伝わるレベルの言葉の揺れは許してね。

パラメーターをシェーダーに渡したい場合は、マテリアルピンを追加する必要があります。
独自のコンスタントバッファを追加すればいいじゃんと思うかもしれませんが、Unreal Engineでそのやり方はまぁまぁな手間を要するので、一般的には実装までの導線が最低限確保されているマテリアルピンの追加が選ばれます。
エンジン改造とは?
ゲームエンジンのコードを書き換える行為をエンジン改造と呼びます。
尚エンジン改造という呼称が正式かは知らんです。
これ以上の真面目な説明はググればヒットするので割愛します。
以下、実際の描画まわりの改造事例です。
前髪を透かしたり


毛先まで綺麗に表現できるポストプロセスなアウトラインを描いたり

キャラと背景を別々のシャドウマップに書き込んでセルフシャドウを抑制したり
髪影を落としたり


頂点IDノードを追加して、それを元に鼻に線を引いたり



独自のトゥーンパス群ですべて描いたり




Substrate (旧: Strata) 非対応
Substrateはマテリアルピンの構成が異なり内部でピンの再接続が行われています。
再接続部分を対応していないので、Substrateは非対応という感じです。
リポジトリ
最新バージョンのみ保守しています。
過去バージョンが動かないと言われても基本的には知らんがなスタイルです。
- Unreal Engine 5.3
- Unreal Engine 5.4
- Unreal Engine 5.5
- https://kafues511.jp/2026/01/10/6737/
- https://github.com/kafues511/UnrealEngine/tree/toon-lit-material-pin/5.5
- Releases めんどうだから後日やるかも分からん
実装
アウトラインマスクとアウトラインカラーを格納するピンを追加していきます。
アウトラインマスクの型はfloat、アウトラインカラーの型はfloat3を想定します。
Engine/Source/Runtime/Engine/Public/SceneTypes.h
マテリアルプロパティの列挙体にアウトラインマスクとアウトラインカラーを追加します。
MaterialPropertyの頭文字を取ってMPですね。
Engine/Source/Runtime/Engine/Classes/Materials/Material.h
ピンの接続関係なを保持する変数です。
型によって使用するFMaterialInput構造体が異なります。
カラーはベクターとかでもたしか問題なかった気がしますが、精度がfloatとuintで面倒なことになるので、基本的にはカラーの方を使います。
DEPRECATEDの対応は不要と思いますがメモ程度に書いています。
Engine/Source/Runtime/Engine/Private/Materials/Material.cpp
static_assertの対応です。
要素の増減によってはシリアライズの互換性が無くなるため、static_assertで「対応忘れずにね♪」というスタイルだと思います。
非推奨な要素からお引越ししている箇所ですが、先ほどと同様に対応不要です。
書いておいても特に影響が見られなかったのでコメントアウトせずに直書きメモなのです。
これも上記同様ですね。BreakMaterialAttributesノードが主にバージョンアップによって並び順に破壊的な変更が発生した際に、互換性の処理を行うのですが、中身の実装をしていないのでハリボテです。この辺りはエンジンのバージョンアップによって場合によっては発生する作業なのでかなり業務寄りです。
マテリアルピンの接続を取得する関数です。
ツールチップ的な説明ではなく、構成要素の型とかの内部情報の説明ですね。
ピンに刺さっているノードのコンパイルまわりです。
接続されている場合はそれが展開されて、未接続の場合はFMaterialAttributeDefintion::CompileDefaultValueに飛ばされて任意の初期値が適用されます。
ピンの有効性です。
シェーディングモデルがToonLitの場合のみ有効、それ以外はグレーアウトするように指定しています。
UMaterialEditorOnlyDataのコンストラクタは5.3では一部で且つ決め打ちな大雑把な対応でしたが、5.4からはアトリビュートから共通の初期値・デフォルト値を取得するように改修されたようです。
適当にToFColorSRGBにしていますが、リニア運用の場合はToFColor(false)に変えてくださいね。
Engine/Source/Runtime/Engine/Private/Materials/MaterialAttributeDefinitionMap.cpp
先ほど触れたピン未接続時の初期値を指定しています。
アウトラインマスクはマスクをしないが初期値なのでCompiler->Constant(1.0f)を指定、アウトラインカラーは黒色が初期値なのでCompiler->Constant3(0.0f, 0.0f, 0.0f)を指定しています。
Compiler引数からシェーディングモデルの情報が取得可能なため、条件に応じて初期値を変えることもできます。
アトリビュートマップに追加したマテリアルプロパティを登録しています。
左からGUIDが個体識別、表示名等、紐付けするマテリアルプロパティ、型の種類、初期値、それを使用するシェーダーステージって感じです。
他にもデフォルト引数で隠れている要素もあるので、覗いてみると面白いかもです。
そしてシェーダーステージを指定している通り、頂点シェーダーで扱うピンを追加する場合はまた違う種類を指定しないとなのですよね。
地味に面倒ですが、マテリアルエディタという面倒なシステムに対応する都合上、これくらい明示的な方がいいんでしょうね。
これもアトリビュート関連ですね。
LOCTEXTはたしか文字列のキャッシュなので頻繁に使う場合メモリに載せておいて確保と解放の手間を省くとかだった気がします。
間違えてたらすまん。
Engine/Source/Runtime/Engine/Classes/Materials/MaterialExpressionMakeMaterialAttributes.h
ピンの接続関係などを保持する変数のMakeMaterialAttributesノード版です。
ちなみに使ったことないです。

Engine/Source/Runtime/Engine/Private/Materials/MaterialCachedData.cpp
MakeMaterialAttributesノードに接続されているピンの更新まわりです。
上記同様です。
Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressionHLSL.cpp
MakeMaterialAttributesノード関連です。
使わないから語りたいことがない件について。
Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressions.cpp
マテリアルプロパティに対応した入力情報が詰まった変数を返している部分です。
ピンの接続性を64ビットフラグに突っ込んで返している箇所です。
static_assertは同様に要素数を変更したら対応してね♪の静的な通知機能です。
シェーダーコンパイル部分ですね。
static_assertは同様に要素数を変更したら対応してね♪の静的な通知機能です。
ちなみに以降はMaterialExpressionMakeMaterialAttributesではなく、それをばらすMaterialExpressionBreakMaterialAttributesノードです。

BreakMaterialAttributesノードの各ピンが出力するチャンネル数を指定しています。
原始的な紐づけ方法で草ですわ。
Engine/Source/Runtime/Engine/Private/Materials/MaterialHLSLEmitter.cpp
アウトラインマスクとアウトラインカラーのシェーダーコードを常時展開として指定しています。
理想はCustomDataと同様に使用する場合のみ展開なのですが、ぶっちゃけ実装が面倒だし、大してシェーダーランタイム負荷にもならんので、保守性を優先して簡単な常時展開を採用しています。
判定が偽の場合は、以降に進まないのでシェーダーコードが展開されないって感じです。
Engine/Source/Runtime/Engine/Private/Materials/HLSLMaterialTranslator.cpp
MaterialHLSLEmitterと同様です。
どちらが新コンパイラで旧コンパイラかは忘却しました。
両方把握していれば別にどうということはないという脳筋スタイルです。
Chunkも上記と似たようなものです。
新旧で設計が多少違うのでしょう。
Engine/Source/Editor/MaterialEditor/Private/MaterialEditor.cpp
アウトラインマスクの型であるfloatは、UMaterialExpressionScalarParameterに区分されます。
アウトラインカラーの型であるfloat3は、UMaterialExpressionVectorParameterに区分されます。float2やfloat4も同様にUMaterialExpressionVectorParameterに区分されます。
デフォルト値に戻す処理の対応です。

Engine/Source/Editor/UnrealEd/Private/MaterialGraph.cpp
ピンにカーソルを重ねた際に表示されるツールチップ部分です。
ついでにピンの並び順も兼ねています。
5.4からは拡張したものより後にFront Materialを配置するようになったらしいですね。

Engine/Source/Editor/UnrealEd/Private/MaterialGraphNode_Root.cpp
Constantノードが接続されているかの対応です。
シェーダーコンパイルの最適化に必要なのでしょう。

デフォルト値をUIから書き換えた場合の処理です。

マテリアルエディタを開いた際のピンの属性だったり、デフォルト値だったりの対応です。
エディタまわりはバージョンアップによる機能拡張の影響が、作業範囲の拡大として顕著に表れるので大変怠いです。
Engine/Shaders/Private/MaterialTemplate.ush
ピクセルシェーダーでアウトラインマスクとアウトラインカラーを取得する関数部分です。
関数名の末尾にRawがある場合はノードの結果をそのまま取得、Rawがない場合はGBuffer等に格納するのを想定してクランプ済み、または正規化済みな値を取得する、といった感じで使い分けます。
マテリアルノード側でsaturateする必要が無いように整備してあげるイメージです。
簡単な動作確認
追加したOutline MaskやOutline Colorを目に見える形で動作確認するためにはGBufferに格納しないといけないのですが、そこまでやるのは面倒なので簡単に確認できる方法を軽く紹介します。

型、ピンに対応したCustomノードを作成、接続

Window > Shader Code > HLSL Code をクリック

下の方にスクロールするとCustomノードの計算結果がそれぞれのピンに格納されていることが見れる
おわり!!!
スカラーパラメータであるアウトラインマスク、ベクターパラメータであるアウトラインカラーをピクセルシェーダーに渡すためのマテリアルピンの追加でした。
関連するエンジン改造
UMaterialExpressionBreakMaterialAttributes::Serializeで気になっていたことをようやく調べたの
前々から気になっていたUMaterialExpressionBreakMaterialAttributes::SerializeにDisplacementがない問題について、ようやくちゃんと調べました。
MaterialAttributesノードに興味がないので事務的に対応していましたが、内容を読むと互換性対応なんですよね。
つまりは古いバージョンから新しいバージョンに変える際の対応。
ということでバージョンアップ対応が導入された境界を調べました。
4.15から4.16にアップデートするタイミングで導入されたようです。
4.15ではFixedLegacyMaterialAttributeNodeTypesが未定義。
4.16でFixedLegacyMaterialAttributeNodeTypesが定義且つシリアライズが実装されている。
筆者は4.25あたりから参入した新参者なので存じていませんが、この頃はDisplacementピンが無かったのでしょう。
無いものを繋ぎ直すことは出来ないので未記載。
納得できました。
ゆっくりと ゆっくりと▼ ゆっくりと ゆっくりと▼
流石に草。
特定の最後の文字を削除する機能を追加して対応完了。
直後の双眸(そうぼう)が余裕で読めなかったわ。
読み上げツールはこういう時に助かりますね。
「▼」がピコピコする所為で遷移検出が頻繁に発生するの地味に困るな。
除外文字に紐づく領域は黒塗りして差分から外すか。
遷移処理の頻発は抑制できたけど、ピコピコの所為で差分が安定するまでに若干のタイムラグが起きてる。
UpdateTimeとStableCountを適当に調整して乗り切るかぁ。
内製のツールはこういった少し前の読み上げが搭載されていない作品と相性抜群ですね。
過去の私の作業が報われております。




