[UE5][Shader]furcraeaToonLock — UE5で作る Unlit + MPC ベースのトゥーンシェーダ

Material Parameter Collection(MPC)を使ってライト方向を制御する Toon Shader

最近、UE5でセルルック表現を色々試しているのですが、今回は Forward Renderer でも比較的安定して見える Toon Shader を作ってみました。

名前は furcraeaToonLock。

このシェーダでは、UE標準のライティングモデルに強く依存せず、Unlit + Emissive ベースで独自にライティングを計算しています。

そのため、

  • Forward Renderer
  • Deferred Renderer

の違いによる見た目の変化をかなり抑えられる構成になっています。

今回の記事では、

  • なぜ Unlit ベースで作ったのか
  • どうやって Toon Band を制御しているのか
  • ライト方向をどう扱っているのか
  • なぜ RampTexture 方式を考えているのか

などをまとめてみます。


なぜ Unlit + Emissive 構成にしたのか


■ Lit版 vs Unlit版 比較画像

左:

  • UE標準 Lit

右:

  • furcraeaToonLock

UE5の標準ライティングは非常に強力ですが、セルルックでは環境によって見え方が変化しやすいという問題があります。

特に、

  • Forward / Deferred の差
  • GI
  • Reflection
  • Specular
  • ポストプロセス

などが強く影響すると、「狙ったトゥーン感」が崩れやすくなります。

そこで今回は、

  • PixelNormalWS
  • DirectionalLight の方向
  • 独自の NdotL 計算

を使い、自前でセルシェーディングを行う構成にしました。

最終的な色は Emissive に出力しています。


ライト方向は Blueprint + MPC で制御

  • DirectionalLight
  • GetForwardVector
  • SetVectorParameterValue

が見える範囲

ライト方向は、Blueprint から Material Parameter Collection に渡しています。

今回使っているのは、

DirectionalLight -> GetForwardVector

です。

取得したベクトルを、

MPC_LightDir

LightDir

パラメータにセットし、マテリアル側で参照しています。

これによって、

  • ライト回転
  • Toon境界
  • ハイライト方向

などがリアルタイムに更新されます。


2Band / 3Band の Toon 制御

今回のシェーダでは、2Band / 3Band を切り替えられるようにしています。

最初は smoothstep ベースも試しましたが、グラデーション感が強くなりすぎて、セルルック特有の「段差感」が弱くなってしまいました。

そのため、最終的には step ベースで制御しています。

2Band はかなりグラフィック寄りで、強いアニメ感があります。

3Band は少しリッチで、柔らかいアニメ表現になります。


アウトラインについて

  • ON / OFF 比較

アウトラインは、別メッシュ + 別マテリアル構成で作っています。

今回は、

  • TwoSided
  • TwoSidedSign
  • OpacityMask
  • World Position Offset

を使って背面のみを描画し、法線方向へ膨らませる方式にしました。

最終的には、かなり軽量で扱いやすい構成になっています。


Material Graph 構成


■ Material Graph 全体スクショ

必須:

  • PixelNormalWS
  • MPC_LightDir
  • NdotL
  • Emissive

が見える範囲

マテリアル全体はかなりシンプルです。

基本的には、

PixelNormalWS

NdotL

step

Shadow Color / Light Color

Emissive

という流れで構成しています。

現在はさらに次の展開として、

RampTexture

を使った Toon Ramp Shader 化も進めています。


RampTexture ベースの次世代版について

現在制作中の次バージョンでは、RampTexture を使って Toon 色自体を制御する構成を試しています。

通常の toon shader は、

step(NdotL)

だけで明暗を切り替えることが多いですが、RampTexture を使うことで、

  • 暖色系
  • 紫系
  • 夜景風
  • アニメ風

など、絵作り全体をコントロールできるようになります。

現在は、

furcraeaToonRampShader

として開発中です。


Forward Renderer でも比較的安定した Toon 表現

おすすめ内容:

  • ライト回転
  • 2Band ↔ 3Band
  • Outline
  • Rim
  • Highlight

今回の構成では、ライト方向を Blueprint + MPC 経由で渡しているため、Forward Renderer 環境でも比較的安定した Toon 表現を維持できます。

特に、

  • Toon境界
  • 段差感
  • アウトライン
  • 色のコントロール

などが崩れにくい点が気に入っています。


Download / BOOTH

今回紹介した内容は、BOOTHで公開中の furcraeaToonLock をベースにした実装メモです。

  • 2Band / 3Band
  • Outline
  • Rim
  • Highlight
  • MPC Light Direction

などを含めた構成になっています。

BOOTH:
https://furcraea.booth.pm/

商品ページ:
https://furcraea.booth.pm/items/8219556

次はさらに、RampTexture を使って色味自体をコントロールできる

furcraeaToonRampShader

も作っていく予定です。

[UE5.8][C++]遂に完成したC++プラグインUE用HLSL.EditorのMaterial作成機能

もうこれでノードスパゲッティから解放される

導入方法

0,以下のリンクを1つダウンロード (特に理由がなければ最新版使ってください)

furcraeaHLSLEditor_UE5.8.0V9.zip UE5.8に対応しました。
https://drive.google.com/file/d/14nWd_4X9uQvt6KjFlmgRbYp2LUYSth8o/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V8.zip float4出力に対応しました。
https://drive.google.com/file/d/1PaBHAT9O4m6DC6UceUtwrj5o8N9qrrhn/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V7.zip ポストプロセスマテリアル対応
https://drive.google.com/file/d/1ieBRb5zpW36LGldmREROGcWJ8WZot1Xg/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V6_2.zip コーディングBugFix
https://drive.google.com/file/d/1BzMiQt4dXcu8p-dIfkyH3v1SRVSKjiCn/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V6.zip コーディングBugFix
https://drive.google.com/file/d/1APYn65u1yo3xkJlDFmqJ2yuCE5zHViqc/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V5.zip 関数インライン化によるコンパイラ整理
https://drive.google.com/file/d/1YiUHmR1g6d9WwvAtd1rGADsiNZEXRMNX/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4.zip (V4) FragmentShader とVertexShader(Optional)に分離
https://drive.google.com/file/d/1gInP7W5hFB3pwlwbrbkekSzC8xOwusap/view?usp=sharing

furcraeaHLSLEditor_UE5.7.3V4.zip ユーザーが作った)CodeMaterialAssetと同じフォルダに変更
https://drive.google.com/file/d/1XhVZgV6FRiyGOOquqO5nJVFXbmg_8DA-/view?usp=sharing

furcraeaHLSLEditor_UE5.7.3V3.zip Projects と RenderCore を bBuildEditorをガード外に移動
https://drive.google.com/file/d/1Qmz5Y_uT0VGKkrk1wskvw2DRbnND6or4/view?
usp=drive_link

furcraeaHLSLEditor_UE5.7.3V2.zip 1つしかCodeMatUser.ushがない不備修正
https://drive.google.com/file/d/1CSXmSebk7hLM02qM5jKDv2ndNJ4jhUi7/view?usp=sharing

1,Pluginsフォルダにzipを解凍して入れてください。

  パスの例:UEプロジェクトフォルダ\Plugins\furcraeaHLSLEditor\Shaders

2,プラグインで「furcraeaHLSLEditor」を有効化

使用方法

コンテンツブラウザで右クリック>Miscellaneous>Code Material Assetを作成

できた New Code Material AssetをダブルクリックでHLSL編集画面が開く

Saveをクリックすると。。。GeneratedフォルダーにM_NewCodeMaterialAssetが作成されます。>CodeMaterialAssetと同じフォルダーに保存するように変更しました。


まだまだ、1つしかCodeMatUser.ushがないので一つしかマテリアルが成立しないなどの不備があるので更新していく予定です。<-以下の画像のように修正済みです。

furcraeaHLSLEditorをGitHub で公開しました。
https://github.com/nobolu-ootsuka-unrealengine/furcraeaHLSLEditor/commits?author=nobolu-ootsuka-unrealengine

修正履歴



1つしかCodeMatUser.ushがないので一つしかマテリアルが成立しないなどの不備を修正

furcraeaHLSLEditor_UE5.7.3V2

Projects と RenderCore を bBuildEditorをガード外に移動(ランタイムでも必要なモジュールのため)


furcraeaHLSLEditor_UE5.7.3V3

CodeMaterialAsset が吐くMaterialのフォルダを (固定)Generated から (ユーザーが作った)CodeMaterialAssetと同じフォルダに変更した

CodeMaterialCompiler.cpp に2箇所変更しました。

① MakeMaterialPackagePath 関数(生成先パスを決定)

  • 変更前:/Game/Generated/M_xxx 固定
  • 変更後:Asset->GetOutermost()->GetName() でアセット自身のパッケージパスを取得し、FPackageName::GetLongPackagePath()
    でフォルダ部分を抜き出して {同じフォルダ}/M_xxx を返す ② CreateOrLoadMaterial の MakeDirectory 呼び出し
  • 変更前:MakeDirectory(“/Game/Generated”) 固定
  • 変更後:MakeDirectory(FPackageName::GetLongPackagePath(MakeMaterialPackagePath(Asset))) —
    生成先パスからフォルダを算出して作成 これにより、例えば Content/0_furcraeaTokyo/CodeMaterialAsset/NewCodeMaterialAsset に保存された CodeMaterialAsset
    に対しては、生成マテリアルも同じ Content/0_furcraeaTokyo/CodeMaterialAsset/M_NewCodeMaterialAsset に出力されます。

furcraeaHLSLEditor_UE5.7.3V4

アウトライン表示用のVertexNormalを拡張のために

FragmentShader VertexShader(Optional)に分離しました!

安定性のためにincludeを辞めました。

furcraeaHLSLEditor_UE5.7.4V5.zip


ルール: FragmentShaderCode / VertexShaderCode には 関数定義を書かない。ヘルパーが必要なら全てインライン化する。
コンパイラの整理

  • ExtractHelperFunctions + エスケープトリック (将来の一般的ヘルパー対応) は保持
    // @param float3 ColorC = 0.90,0.20,1.20//でBPでパラメーター化

furcraeaHLSLEditor_UE5.7.4V6.zip


・日本語コメントがあるとVertex Shader側のコードカラーリングが効いてない不具合を修正
・こんどは両ペインで改行が入力できないを解決
・ユーザーが .ush のボディ内で Phase * Time のように Time を直接書いても View.GameTime として展開され、HLSL
コンパイルエラー → クラッシュが防がれます。

furcraeaHLSLEditor_UE5.7.4V7.zip

ポストプロセスマテリアルを CodeMaterialAssetで作れるようになりました。
Domain が「Post Process」の時に Blendable Location ドロップダウンが横に表示されます:

CustomDepth のアウトライン系には Before Tonemapping が一般的です。

自動生成パラメーターにテクスチャが指定できるようになりました。
// ===== Fragment Shader =====
// @param Texture2D AlbedoTex
// @param Texture2D HatchTex = /Game/3Dnchu/Textures/T_Stroke-SD11.T_Stroke-SD11
// @param float HatchTiling = 10.0

なぜか裏面だけに色が乗ってる場合

● Vertex Shader Code に何か入っているはずです。

Vertex Shader Code が空でないとプラグインが「シェル法アウトライン用」と判断して:

  • TwoSided = true
  • BlendMode = Masked
  • OpacityMask = TwoSidedSign × -1(裏面のみ表示) を自動設定します。これが原因です。 修正手順:
  1. CodeMaterialAsset エディタで Vertex Shader Code を完全に空 にする
  2. Save をクリックして再生成 Vertex Shader Code が空になると:
  • TwoSided = false
  • BlendMode = Opaque
  • OpacityMask なし → 表面だけに通常表示

furcraeaHLSLEditor_UE5.7.4V8.zip

 float4出力に対応しました。

furcraeaHLSLEditor_UE5.8.0V9.zip

UE5.8に対応しました。

【UE5.3】シェーダーファイルのインクルード方法について(Customノード編)についてをやってみた。

こちらの記事を丸っと参考にさせていただいて

【UE5】シェーダーファイルのインクルード方法について(Customノード編)

確認をとった

プロジェクト名はProjects_CustomNode

プロジェクトフォルダの直下にShadersフォルダを作成します。

Glitter.usf


float3 Glitter = float3(0.0,1.0,0.0);

return Glitter;

先ほど作成したシェーダーファイルを適用させるために、Projects_CustomNode.Build.cs に RenderCore を追加します。

// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class Projects_CustomNode : ModuleRules
{
	public Projects_CustomNode(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore","RenderCore" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
		
		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}

Projects_CustomNode.h を開き、新しく “Modules/ModuleManager.h” を インクルードします。
さらに、継承クラスとして FDefaultGameModuleImpl を宣言し、StartupModule関数 と ShutdownModule関数 を一緒にオーバライドします。

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"


class FProjects_CustomNodeModule : public FDefaultGameModuleImpl
{
public:
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
};

Projects_CustomNode.cpp を開き、IMPLEMENT_PRIMARY_GAME_MODULE の最初の引数を Projects_CustomNode.h 側のクラス名に書き換えます。

// Copyright Epic Games, Inc. All Rights Reserved.

#include "Projects_CustomNode.h"
#include "Modules/ModuleManager.h"

void FProjects_CustomNodeModule::StartupModule()
{
	FString ShaderDir = FPaths::Combine(FPaths::ProjectDir(), "Shaders");
	AddShaderSourceDirectoryMapping("/Project", ShaderDir);
}
void FProjects_CustomNodeModule::ShutdownModule()
{
}
IMPLEMENT_PRIMARY_GAME_MODULE(FProjects_CustomNodeModule, Projects_CustomNode, "Projects_CustomNode" );

以上の流れが完了しましたら、一度ビルドを行います。

マテリアル作成しCustomノードのCodeに

#include "/Project/Glitter.usf"
return 0;

と入力したらOKでした。

プロジェクトデータ

https://drive.google.com/file/d/1Ro4pcatwqWKCQ64ZUObSndKtIyagYKE7/view?usp=sharing

UE4 きれいなグラデーションの虹色のレインボーのマテリアルが作りたい

正解はtexCoordの応用だった。

texCoordを縦のグラデーションと横グラデーションに分け

値をLerpのAlphaにつないでお好きな色をA,Bにつなぐ。

2つ作ってMultplyして縦横グラデーションになるようにMIXした。

さらに回転させたい

下の部分が見切れていたので追加しました。

参考

UE4]UMGで使えるでシンプルなグラデーションを作 …historia.co.jp

https://wgld.org/d/glsl/g008.html

https://wgld.org/d/glsl/g010.html

UE4 きれいなグラデーションの虹色のレインボーのマテリアルが作りたい https://furcraea.tokyo/2021/12/28/ue4-%e3%81%8d%e3%82%8c%e3%81%84%e3%81%aa%e3%82%b0%e3%83%a9%e3%83%87%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%81%ae%e8%99%b9%e8%89%b2%e3%81%ae%e3%83%ac%e3%82%a4%e3%83%b3%e3%83%9c%e3%83%bc%e3%81%ae/

[UnrealEngine] Surface Translusent Material

これは自分の中でかなりおおきな発見だった。

Shading Modelを変更しなくても、透明で、ベースカラー、Metalic スペキュラ、ラフネス、エミッシブ、Normal、タンジェント、ワールド位置オフセット、ワールドディスプレースメント、テッセレーション乗数、アンビエントオクルージョン、屈折が使える

詳細は以下

https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/Materials/HowTo/Transparency/

【UnrealEngine】水っぽいマテリアルを作ったときのメモ(屈折率)

https://qiita.com/nchhujimiyama/items/8d2c820f2a1367864569

他にも

#UE4 #UE4Study ちゃんとびったりUVスクロールする方法

あー基本をわすることなかれ.

遠まわりして、深夜の3時まで悩んでしまった。

BreakOutFloat2Componentsも初見

MakeFloat2も1度見たことあったかどうか

なぜだかHLSLでこうしても動かなかった

return float2(texCoord.x,texCoord.y+Time);

参考

https://answers.unrealengine.com/questions/409094/how-to-make-a-scroll-view-in-materialany-direction.html