【UE5】マテリアルCustomノードの使い方

UEのシェーダーを勉強中のプログラマーの尾関です。

今回はHLSLを直接記述できる「Customノード」の基本的な使い方について紹介します。

Customノードとは

Customノードとは、マテリアルノードを使わずにシェーダー (HLSL) を直接記述できるノードで、メリットとしては以下のとおりです。

  • for文やif文による条件分岐など、既存のマテリアルノードでは難しい処理が可能
  • より複雑なシェーダーを記述しやすくなる

このメリットにより、例えば Shadertoy などからコードの流用が容易となります。

Customノードを使うデメリット

Customノードを使うデメリットは以下のとおりです。

  • マテリアルノードの「視覚的なわかりやすさ」という利点が失われる
  • 実装と保守のコストが上がる可能性がある
  • 最適化を手動で行う必要がある
  • HLSLコードの記述方法により、プラットフォーム依存の問題が発生する可能性がある

こういったデメリットがあるため「どうしてもマテリアルノードで実装できない処理のみ Customノードを使う」といった用途が良さそうです。

Customノードの基本的な使い方

Customノードの作成

Customノードは、Customで検索して作成します。

シェーダーコードの記述方法

シェーダーコードはCustomノード、または詳細タブの “Code” から入力します。

ただ入力補完などの補助機能は期待できないため、別のシェーダーエディタを使用してコードを記述し、それをペーストするのが良さそうです。

生成されるHLSLコードの確認方法

メニューから「ウィンドウ > シェーダーコード > HLSLコード」を選びます。

CustomExpression” で検索すると対象のコードが見つかります。もしくは「Addtional Defines」で定数を設定すると、検索しやすくなります。

引数の設定 (Inputs)

引数は “Inputs” から設定します。Input Name に名前を指定し、データ型は接続されたノードから自動判定されます。

ここでは “UV” という引数を追加してみました。

Customノードの引数UVに TexCoordノードを渡すと、UV値が flaot2 として代入されます。

また引数を増やしたい場合は、Inputsのところにある「+」ボタンで増やせます。

戻り値の設定 (Output Type)

戻り値は “Output Type” から設定します。

Additional Outputsの使い方

出力(戻り値)を増やすには “Additional Outputs” の「+」をクリックで項目が増えます。

  • Output Name: 出力名
  • Output Type; 出力データ型

例えば Output Name に “RetEmissive“、Output Type に “CMOT Float 1” を指定して、エミッシブの値を出力できます。

Additional Defines: 定数

「+」で項目を追加して、”Define Name” に定数名、”Define Value” に値を設定します。

例えば定数名を “EMISSIVE_POWER” が “100” とすると、以下のようにコードに “EMISSIVE_POWER” を含めることができます。

コンパイル

[CTRL+S]で保存すると、自動でコンパイルされます。ただコードの修正はすぐに反映されないようなので、少し待ってから[CTRL+S]で保存するとうまくいく場合があります。

エラー対応

コンパイルしたときに以下のエラーが出ることがあります。

エラーログは「統計」タブに出力されます。

統計タブが表示されていない場合、マテリアルエディタ上部にある「統計」の項目をクリックして有効にすると、統計タブが表示されます。

そしてエラーコードを見ても原因がわからない場合は、メニューから「ウィンドウ > シェーダーコード > HLSLコード」を選んでHLSLコードを表示することができます。

UVとテクスチャを引数に渡す方法

Customノードを選択して、”Inputs” に “UV” と “Tex” を追加します。

そして TexCoord ノードと Texture Object ノードを接続します。

HLSLコードを例えば以下のように記述することで、UVに合ったピクセルの値をベースカラーに設定できます。

組み込みマテリアルノードは使用できない

HLSL内では、エンジンが提供しているマテリアルノードは使用できません。

そのため、組み込みのマテリアルノードの機能を使いたい場合は、同等のものを別途自作する必要があります。

例えば SphereMaskのHLSLコードの実装例は以下のようになります。

このCustomノードの引数 (Inputs) には以下を定義します。

  • Center [VectorParameter]: 中心座標
  • Position [TexCoord]: UV座標
  • Radius [ScalarParameter]: 半径
  • Hardness [ScalarParameter]: 境界のシャープ値 (0.0~1.0)

マテリアルグラフは以下のように実装しました。

オパシティマスクのマテリアルパラメータを表示するには Blend ModeMasked にします。

メッシュを丸でくり抜くことができました。

Parameters.TexCoordsを使う方法

HLSLコードでは “Parameters” という定義が使えます。そしてParametersには TexCoords が含まれている…はずなのですが、

実際に使ってみると、未定義のメンバーというエラーになりました。

生成されるHLSLコードを読んでみたところ、「#define NUM_TEX_COORD_INTERPOLATORS 0」という定義が見つかり、Parameters の TexCoordsが無効化されていました。

調べてみたところ「そのマテリアル内で UV を使っていない場合は TexCoordsの定義は最適化のため自動で無効化される」とのこと。

そこで意図的に “TexCoord” を使用するように修正…。

以下の Parameters.TexCoordsを使用した HLSL コードが正常に動作するようになりました。

Custom Primitive Data (CPD) に HLSL からアクセスする方法

Unreal Engineには Custom Primitive Data (CPD) という、プリミティブデータにシェーダーパラメータを含める方法が用意されています。

ここに保存したパラメータを Customノードからアクセスする方法を紹介します。

まずは VectorParameter ノードの作成。

そしてノードの詳細タブから「Use Custom Primitive Data」にチェックを入れると、Custom Primitive Data を使うことができます。

HLSL から Custom Primitive Data にアクセスするには「GetPrimitiveData(Parameters.PrimitiveId).CustomPrimitiveData」を使用します。

そしてマテリアルをレベルに配置した任意のメッシュに割り当て、詳細タブの Custom Primitive Data からパラメータを「+」で追加します。

[0] に 0.5、[1] に 0.5 を割り当てると、中心に穴を開けることができました。

さらに、for文のコードをテストするため、Custom Primitive Data を「8つ」作ってみます。

  • v0 [0]
  • v1 [4]
  • v2 [8]
  • v3 [12]
  • v4 [16]
  • v5 [20]
  • v6 [24]
  • v7 [28]

[]の中は数字はアドレス (Primitive Data Index)の値となります。

シェーダーコードは以下のように for文でマスクを合成するようにしました。

for文で中心座標を別々に処理することで、複数のマスクを動かせるようになりました。

おしまい

今回Customノードでシェーダーコードを色々試したときに GPUハングが発生してしまい、プロジェクトが開けなくなることがありました (ハングするマテリアルを貼り付けたアクターがレベルにあるため、プロジェクトを起動するとGPUハングする)。

HLSLを直接書くと、そういった問題が起きる可能性があるので、バックアップを取っておくのは大切ですね。

以上、Customノードの使い方の紹介でした。

 

(Visited 47 times, 4 visits today)

コメント投稿は締め切りました。