水ノ茉の宣伝
準備中...
ゲームを作る予定なの水ノ茉
作業環境
- Windows 10
- Unreal Engine 5.5 (59a9aa7)
- Visual Studio 2022 (17.10.4)
- Visual Studio Code
注意点
本記事は Unreal Engine 5.5 が正式にリリースされる前のブランチ (hash: 59a9aa7) を元に作成した内容です。
正式リリースとは異なる情報が含まれている可能性があります。
始まり
先日情報公開されたのを機に Unreal Engine 5.5 のロードマップを読んでいたところ気になる内容を見つけました。
Render Pass Improvements
In Release 5.5 it is now possible to author scene captures and custom render passes which automatically mirror the main view’s camera and resolution, including temporal AA jitter and screen percentage. This allows compositing layers to be pixel identical, and compositing in general to take advantage of screen percentage for better performance.
Additionally, a user defined intermediate texture, dubbed “UserSceneTexture” can be written to and read from sequentially as a post process material. This means that UE now supports running multi-pass post process effects (such as separable filters or blurs) in a more performant manner.
https://portal.productboard.com/epicgames/1-unreal-engine-public-roadmap/c/1666-render-pass-improvements
読めないので翻訳さん。

\ 中 間 テ ク ス チ ャ /
そう、ついにポストプロセスマテリアルに中間テクスチャが実装されました。
従来であればCanvasやRenderTextureを用いたり、FSceneViewExtensionBase
を使用したり、エンジン改造をしたり・・・
Unityなら当然の如く扱えた中間テクスチャというありふれた行為にバカみたいなコストを払う必要がありました。
ついにその呪縛から解放されます。
そしてなんと中間テクスチャの他にダウンサンプルも実装されていました。

「Render Pass Improvements」の説明にも登場している「separable filters」などのぼかしフィルタは、計算負荷が高いので負荷軽減としてダウンサンプルを100%と言っていいほど組み込みます。
故に最初この内容を見た時は「中間テクスチャだけあっても結局は負荷軽減でダウンサンプル自前でやるしかねぇよなぁ」とテンションがジェットコースターでしたが、いざ実装を見たら大歓喜です。
前回の5.4もポストプロセスに機能面で良い変更点が入っていたので2連続で嬉しいアプデかもです。
破壊的変更に関しては最早気にしないことにしています。
これに関してはエンジン改造を武器に振り回している身分、受け入れるしかねぇと悟りました。
実際にぼかしフィルタを作りながら使い勝手と実装を確認していきましょうか。
実装に関しては個人的に掌握したいだけなので、メモ帳程度です。
Visual Studio Installer
ソリューションを立ち上げて暫く待っていると警告が出力されることがあります。
大体は要求コンポーネントが不足している内容です。
案内に従って不足しているものをインストールしましょう。
面倒くさがってサボるとエンジンビルド失敗します。たぶん。
あとついでに初回ビルド時は、リビルドじゃなくて、ビルド操作を推奨します。
改善されていなければ初手リビルドするとコピーするファイルが存在しなくて失敗するという問題があります。



User Scene Texture と User Texture Divisor の実装確認
中間テクスチャの機能名はUserSceneTextureです。

最初はSceneTextureから選択するスタイルと思っていましたが別ノードの様ですね。
SceneTextureはこれ単体でバリエーション制御とかしているので確かに別ノードで実装した方が内部的にも素直かもですね。
リストボックスを非採用が故に任意のバッファ名でやり取りできる点は寧ろ扱いやすいかも。

UsedSceneTexturesのビット演算用の型はまだ32ビットなのか。
マテリアルインプットなどのビット演算で使用されていた型たちは、5.2から5.3のタイミングで64ビットに格上げされたので、それに倣って随時されると思ったのですが、まだですか・・・
SceneTextureから取得できる要素を増やす際には当然、ESceneTextureId列挙体にも追加するんですが、32以上だとビット演算が死んじゃうので毎回64ビットに拡張対応しているので、そろそろ標準で64にして欲しいな。
PPI_Anisotropyが既に30だから割とすぐ超過しちゃうのよね。
地味にビット演算でゼロに戻ってくるだけだからビルドエラーにならない初見殺しポイントなのよ。
ここは引き続き拡張する時の注意点っと。
ほぇー。FMinimalSceneTexturesがUserSceneTextureのFRDGTextureRefを所有してるんだ。
mutable付与されてるわ。
FSceneTexturesはあっちこっちで使われているから全対応面倒だったのかな。
というかポストプロセス階層から随分と旅立ったな。
最初は違和感あったけど、SceneCaptureのRTに対応してるからこの場所でも妥当か。
ポストプロセスの機能の割に400行のヒット数は異常だと思ったけど、SceneCaptureを考えたらそんなもんでしたね。
FSceneTexturesに入ってるならエンジン改造との親和性も高いのでぱっと見は優等生かも。
ダウンサンプルは予想通りGetDownscaledViewRectにぶち込んでるだけですね。
本当にUtils関数群便利過ぎる。
今後改造でお付き合いすることになる部分は大体把握できたので使っていきましょうか。
ガウシアンぼかしとは
ぼかしフィルタのひとつです。
真面目な説明はググればヒットするので割愛します。


パス構成
作成するのは1パスなぼかしフィルタではなく、2パスなぼかしフィルタです。
冒頭で触れた「separable filters」というやつですね。
ガウシアンぼかしの最適化手法として一般的だと思うので係数まわりの説明は割愛します。
というのは建前で、数字について正確に説明するほどの技量がないです。
パスの流れとしてはこんな感じです。
左が入力テクスチャ、右が出力テクスチャです。




1パス目の結果を中間テクスチャに書き込む感じですね。
説明のために2パス目の結果も中間テクスチャに書き込むので、最終的なコンポジットを含めると3パス構成となります。
シーンカラーに直書きでも実装は出来ますが、一般的なアプローチが中間テクスチャを用いるという感じです。
ぼかしパスについては中間テクスチャがないと破綻するような例が特に思い付かなった。
特定オブジェクトだけをぼかす場合でもシーンカラー直書きで確か出来るし。

水平ぼかしを作る
1パス目の水平ぼかしを作っていきます。
ポストプロセスマテリアルを作る




マテリアルパラメータコレクションを作る
水平と垂直、異なるポストプロセスマテリアルで共通のパラメータ制御をするためにMPCを使用します。




Enabledがぼかしの有効性、Kernelがぼかし幅、Sigmaがぼかし度合い
カスタムノードで組んでいく
こういう感じのノードを組んでいきます。

SceneTexture


TextureCoordinate

CollectionParameter




Custom





Define Value はなにも入力しないでおっけい

カスタムノードを書く
水平と垂直の両方に対応したコードを書いていきます。
コピペ

コード全文
#ifdef HORIZONTAL_PASS
#define PPI_TargetSceneTextureId PPI_PostProcessInput0
#else
#define PPI_TargetSceneTextureId PPI_UserSceneTexture0
#endif
#define CalcWeight(Value, Sigma) (1.0 / (sqrt(PI * 2.0) * Sigma) * exp(-Pow2(Value) / (2.0 * Pow2(Sigma))))
BRANCH
if (Enabled <= 0.0)
{
return SceneColor.rgb;
}
float Weight = CalcWeight(0.0, Sigma);
float3 Color = SceneColor.rgb * Weight;
const uint Kernel = max(1, round(InKernel));
LOOP
for (uint i = 1; i < Kernel; i++)
{
float4 NewUV;
#ifdef HORIZONTAL_PASS
NewUV.xy = UV + float2( float(i), 0.0) * InvSize;
NewUV.zw = UV + float2(-float(i), 0.0) * InvSize;
#else
NewUV.xy = UV + float2(0.0, float(i)) * InvSize;
NewUV.zw = UV + float2(0.0, -float(i)) * InvSize;
#endif
float4 NewClampedUV;
NewClampedUV.xy = ClampSceneTextureUV(ViewportUVToSceneTextureUV(NewUV.xy, PPI_TargetSceneTextureId), PPI_TargetSceneTextureId);
NewClampedUV.zw = ClampSceneTextureUV(ViewportUVToSceneTextureUV(NewUV.zw, PPI_TargetSceneTextureId), PPI_TargetSceneTextureId);
float NewWeight = CalcWeight(float(i), Sigma);
Color += SceneTextureLookup(NewClampedUV.xy, PPI_TargetSceneTextureId, 0).rgb * NewWeight;
Color += SceneTextureLookup(NewClampedUV.zw, PPI_TargetSceneTextureId, 0).rgb * NewWeight;
Weight += NewWeight + NewWeight;
}
return Color * (1.0 / Weight);
水平と垂直のバリエーション
#define HORIZONTAL_PASS
が存在する場合は水平方向にぼかす処理になり、存在しない場合は垂直方向にぼかす処理が採用されるようになっています。
Additional DefinesでDefine Nameを入力しただけで数値未指定の理由はこういうことだったのです。
ifndef運用が好きじゃない人は自由にEqualに変えてもらっても良きです。
CalcWeightは本当ならushに関数を用意したかったのですがファイルの作成が面倒だったのでマクロで雑に解決です。
心配性の方はSigmaにmax(0.0001, Sigma)
を付けてください。
ゼロ値を指定されるとゼロ除算で動作が担保されません。
ViewportUVToSceneTextureUV, ClampSceneTextureUV, SceneTextureLookup
関数と機能説明はちょっと長いので過去の記事を参照してください。
Blendable Location はこっち。
ポストプロセスマテリアルをセット




見た目を確認する
書き込み先をシーンカラーから中間テクスチャに変更する

User Scene Textureに文字列を指定することでそのポストプロセスマテリアルのRenderTargetはSceneColorから中間テクスチャに切り替わります。
この状態で Apply か Save this asset をすると先ほどまで確認できた水平ぼかしが見れなくなり、代わりにデバッグ情報が表示されます。
DebugPrintは作成手順が整備されているとはいえ、可視化しないと把握が面倒な部分を整備してくれたのは地味に嬉しいですね。

あとついでに、露出は重ね掛けする必要が無いのでDisable Pre Exposure Scaleにチェックを入れて切ってください。

垂直ぼかしを作る
2パス目の垂直ぼかしを作っていきます。
基本的には水平ぼかしで作成した内容のコピペです。
だから垂直だけ作りたい場合でも水平の手順を踏んで下さいね。
そうしないと内容スッカスカ。
ポストプロセスマテリアルを作る



カスタムノードを組む
こういう感じのノードを組んでいきます。

UserSceneTexture


Custom


カスタムノードを書く―――ことないか
ただの見出しです。
PPI_UserSceneTexture0
ノード的にはSceneTextureとUserSceneTextureで分かれていますが、内部で呼ばれている関数は同様にSceneTextureLookupです。
そしてPPI_XXXも名称がPPI_PostProcessInput0とPPI_UserSceneTexture0で違いますが、これまた内部的には#define PPI_UserSceneTexture0 PPI_PostProcessInput0
となっているのでHLSLコードだけで見れば特段変わったことはないですね。
中間テクスチャとシーンカラーの両方をフェッチしている場合は、その限りではないかもですが。
ポストプロセスマテリアルをセット

できた

ダウンサンプルしてみる
解像度を半分にしてみます。
そして飽きてきたのでざっくりになります。


Resolution Relative To Input に Blur (Horizontal) を入力


Blendable Location は Scene Color Before DOF を選択

User Scene Texture に Blur (Vertical) と入力
ピンを接続



User Texture Divisor
User Texture Divisor が除算値を入力するところです。
Resolution Relative To Input
ここに中間テクスチャの名前を入力すると、出力サイズが指定された中間テクスチャサイズと同様になります。
上の例だと Blur (Horizontal) がハーフ解像度なので Blur (Vertical) の出力も同様のサイズになる感じです。
最終的な出力はシーンカラーサイズにまでアップサンプルしないといけないので、新しく最終出力的なポストプロセスマテリアルを作った感じでした。
おわり!!!
あとは深度と速度を書き込めるようにしてTSR対策を標準で出来れば割と文句ないかもですね。


共通ルート編
シークレットラブ(仮)のネタバレを含みます。
名取さん随分と可愛いキャラやなぁ。
癒されるわ。
別に……いいですよ。と言ってる割にはめっちゃ嫌そうで草。
マウント合戦、おもろい。
なるほどね、これで冒頭のシーンに戻るのね。
若干気になるのは楓さんの取り巻きはこの状況に立ち会っているのかね。
先に帰らしたのかね。
クレープ持ってる楓さんかわいい!
楓さんキスしてる!!
かわい!!!
え、まって、共通ルートってここからなのかよ。
ここまでは体験版ってこと?
はぇー。
導入が約6万文字か。
あら、美沙さん大胆。
清楚系変態の美沙さん。
いつもなら上から順に、この作品ならハルさんから攻略するタイプですが、今回は例外的に楓さんを先に。
ふむふむ。おっぱい。
おっぱい?
なに書こうとしたんだっけ。
あー。おっぱい、輪郭線入れるべき、というメモをしたかったの。
ハルさんの私服、材質なに?
楓さんの会話のテンポまじ好きだわ。
昔から思ってたんだけどカロリーより脂質抑えた方がいいんじゃないの?
黒髪ロングの破壊力すごい。
でもちょっと水色のリムライト違和感あるよな。
絵的には普通なんだろうけどライティングという観点から見ると違和感半端ない。
スッポンじゃなくてスッポンポンかぁ!!
語呂良くて大変草。
なんだ、草野さん、いい子じゃん。
これなら主人公さんはパシられても文句ないですわ。
学祭少し進んで眠った
シークレットラブ(仮)のネタバレを含みます。
苺クレープおいしそう!
奏命様の影響も相まって最近苺欲が沸々と沸いております。
え、あぁ。食べ過ぎ防止で禁止なのね。なら妥当だわ。
ケーキの型は持ってないよねぇ。シフォンの焼き型ならあるんだけど。
普通のケーキは苺が高いからという理由で作る気が中々起きなかった学生時代は。
レジン。単語が懐かしいわ。
aaaaaaaaaaaaaaaaaaaaaaa.
かわいいいいいいいいいいいいいい。
そうだぞ先輩、ムード壊すな、ばーか。
ふふふふふ。
SDFテクスチャ作成ツールの続き
ふふ~ん♪
制御点の配置と塗り潰し対応が済んだらようやく使える状態になりそう。
これでアニメ調な顔陰を作れるぞ。
いぇーい。
次は衣類の濡れ表現をやりたいな。
顔陰もえっちですけど、衣類の濡れはもっとえっち。
SDFテクスチャ作成ツールの続きの続き
スプラインで制御点の分布をしてみた。
32の制御点を元にSDFしてるんだけどまだ荒いんだよねぇ。
SDFテクスチャ作成ツールの続きの続きの続き
昔作成した顔陰マテリアルの大改修。
当初の予定ではスプラインで全部書く予定でしたが、鼻の陰とか頬の部分をマスク的に運用して、全体の陰は普通に関数で書いた方が綺麗かもですね。
ベイク方法はシンプルに頂点変換させてシーンキャプチャで撮影です。

かわいい。

かわいいんですけど、シェーディングが結構悩ましいんですよね。
アニメ作品に従うと画像のようなベタ塗りが正解なんですが、エロゲのようなCG絵に従うと結構ディフューズしてるんですよ。
色塗りの勉強がてらにWhirlpoolの作品も遊びたかったりします。

パッケージを見て即購入したんですが、実は未プレイ。
サンプルのCG絵を見ただけなんですが、リムの表現がやたら綺麗なんですよね。
そりゃ人力で塗ってるから当然っちゃ当然なんですけど。
資料として興味は大変そそられるんですが、このブランドは驚異の未プレイ率100%
竜姫とpieces1作目は冒頭だけ少し覗いてそのまま積みました。
たぶん体験版の範囲にすら到達してない。

セレオブの逆光時に輪郭線を消す表現もいいなぁと思ったまま実装にまでは移せてない現状。
温泉のシーンだっけ?
くくるさんと蓼科のファンクラブ名称に草生えるシーン。
ちっぱいで思い出したけどリドジョも遊びたいのよね。
あの人は虚無だけど。
古のPCデータ移行失敗でセーブデータ死んだから、あの長い長い茉優先輩との日々が消えたままなのよね。
ダメだ書き始めると遊びたい欲があることを自覚するから精神衛生に悪い。
絶望的な最終プレイ日時
他にもクロスとか色々と夢中になっていたらエロゲが遠ざかりました。

コード書くのもエロゲするのも両方楽しいからバランスが取れないんですよね。
とはいえ再来週の25日は別です。
ここ最近の唯一の楽しみです。
