mushroom log

不完全勉強メモ

CommonUI Pluginの(デザイン的な)話

この記事はUnreal Engine (UE) Advent Calendar 2022 Part3の13日目の記事です。

CommonUI Pluginについて

UE4.26ごろからひっそりと、Epic公式のCommonUI Pluginが利用できるようになっています。現時点でまだExperimentalなのですが、すでにFortnite等で実用化されているようで、十分な実績があります。また、今年11月のUnreal Insiteでもライブが行われ、その便利さがアピールされました。

さて、このPluginでは以下のようなメリットを受けられます。

色々ありますが、デザイナー視点では「スタイルを分離できる」点にとても嬉しさを感じますね! そこで今回は、Common UIのデザイン方面での使い方を紹介していきます。

Common UI Pluginの導入について

 

 

(すいません、現在執筆中です)

 

 

Common UI Widgetの作り方

Common UIウィジェットの機能を使う場合、Common User Widgetクラスを継承したウィジェットを作成する必要があります。

 

 

(すいません、現在執筆中です)

 

 

ボタンを作成する場合はCommon Button Baseクラスを継承する必要があります。作成時点では空っぽですが、何かしらのプリミティブを挿入すると見慣れたボタン型の形が表れます。

Styleの作り方

 

 

(すいません、現在執筆中です)

 

 

 

なお、従来のプリミティブButtonウィジェットにあるPaddingが設定できないため、押し下げた表現がデフォルトではできません。

 

 

(すいません、現在執筆中です)

 

 

 

※ただし、このサウンド設定は排他制御が効かないようです。短時間でClickやHoverが発生すると、それだけのサウンドが再生されて非常にうるさくなります。

Styleを使った応用

 

 

(すいません、現在執筆中です)

 

 

最後に

スタイルを分離できることで、デザイナーだけで完結できる作業が増えます。また、紹介したように、見た目のコントロールを一か所に記述できることで、管理上のメリットが大きいです。ワンオフが増えがちなゲームUIでは場合によりけりですが、特にノンゲームでの利用では、WebデザインにおけるCSSのような存在として、大いに役立つ可能性があります。

今回紹介していないCommon UI Pluginのその他のメリットについても強力で、非常にお勧めできるプラグインとなっています。ぜひ、UIデザイナーの方は採用を検討してみてはいかがでしょうか。

それでは!

参考サイト

  •  

油彩風フィルタ

明けましておめでとうございます。本年も怠惰にやっていきますがよろしくお願いします。昨年から、あくまで自分用メモとして投げやりな更新をちらちらと再開していましたが、今年は自分なりの勉強やこれまでの学習の成果を、後から読んでもわかる程度に文書にして吐き出していきたいと思います。がんばります。

さて新年一発目は、昨年実践してできた(と思う)油彩風フィルタについてまとめておきます。

概要

 kuwaharaフィルターによる実装です。このフィルタをざっくり説明すると、ある点Pの色を決めようとするとき、Pを中心に4象限のエリアを設定し、分散の最も小さいエリアの平均カラーをPの色をして採用する、という感じだそうです。

f:id:noume:20210103174117p:plain

実際やってみました。↓

 今回はサンプルピクセル3x3サイズで実装してみました。使用バージョンはUE4.25です。

実装手順

1:カラーをサンプルする

まずはカラーをサンプルする準備をします。2つほどマテリアル関数を作ります。

f:id:noume:20210103155437p:plain

MF_GetOffsetPixelは、指定したピクセル幅のオフセットをとるためのマテリアル関数です。マテリアル上でテクスチャはUV値0~1で正規化されているので、nピクセル分ズレた位置の情報をとるためにUV値自体をずらします。これをSceneTextureのInvSize(=1/ピクセル数)と掛け合わせて元のTexCoordに足すことで行っています。輪郭線検出などでもよく見る方法ですね。

f:id:noume:20210103161455p:plain

MF_GetOffsetPixelColorは、さきほどの関数からの戻り値を使って、オフセットされた場所の色情報をとってきます(関数を分けていますが、今回はColorしか使わないのでまとめてしまってもいいかもしれません)。

2:分散値を求める

次に先ほどのサンプルカラーを元に、kuwaharaフィルターにおける各エリアの分散値を求めます。分散の導出はこんな式だったはず

f:id:noume:20210103171146p:plain

f:id:noume:20210103171237p:plain

ごちゃごちゃしてますがやってることは単純です。MF_GetAreaVarienceでは、まず分散の計算のためR、G、Bそれぞれの平均値を出して、サンプルしたカラーとともに分散の実際の処理(MF_GetVarienceV3)に渡しています。その後戻り値をR、G、Bをすべて合算して評価値としています。また、エリアの平均カラーは最終的に採用されるカラーの候補となるため、Outputノードを増やして出力するようにします。

f:id:noume:20210103163954p:plain

f:id:noume:20210103164122p:plain

f:id:noume:20210103164156p:plain

そして分散を求めるマテリアル関数はこうなります。ごちゃってますが、これも単純に各ピクセルのカラーと平均カラーとの差の2乗を足し合わせて最後に割る、という分散の式をノードに置き換えているだけです。

3:エリアの評価と最終カラー決定

先ほどまでようやくエリアの分散と平均カラーを求める準備ができたので、あとはこれを4つのエリア全てで計算して評価するだけです。

f:id:noume:20210103171842p:plain

Customノードの中の式はこんな感じです。4つの値を比較して最も小さいものを選択する、というやつですが、みたままそのままifだらけなので、これはもっといい書き方がありそうな気がします。

if(AreaA > AreaB){
	if(AreaB > AreaC){
		if(AreaC > AreaD){
		 return ColorD;
		}
		else{
		 return ColorC;
		}
	}
	else{
		if(AreaB > AreaD){
		 return ColorD;
		}
		else{
		 return ColorB;
		}
	} 
}
else{
	if(AreaA > AreaC){
		if(AreaC > AreaD){
		 return ColorD;
		}
		else{
		 return ColorC;
		}
	}
	else{
		if(AreaA > AreaD){
		 return ColorD;
		}
		else{
		 return ColorA;
		}
	}
}

以上をポストプロセスマテリアルとして設定すれば、以下のような絵ができていると思います。なんとなく平滑化がかかってる気がしますね。

f:id:noume:20210103175559p:plain

終わりに

本来kuwaharaフィルターは任意のピクセルでのサンプルができるようにするものらしいですが、ご覧の通りノードでやるにはかなりごちゃるのでカラーサンプルからCustomノードを使う必要がありそうです。HLSLにもう少し詳しくなったら、再度挑んでみたいですね。

カスタムマスクで演出する(力技回答)

Discordチャンネル回答用。結果的にだいぶ脳筋で解決することにしました。

質問内容をざっくりいうと、以下のような遷移エフェクトのマスクを作りたいがどうすればいいか、ということでした。ここまでにマスク画像を使った解決策を考えてみましたが、下記エフェクトでは中央の四角の枠が、正方形からスタートして長方形に変形したのち回転を交えて拡大する、という動きをしているので、マスク画像の閾値で制御する方法ではちょっと対応できないとのことでした。そこで代わりの解決策を考えてみることにしました。

f:id:noume:20201226224649g:plain

PostProcess Materialを使う

まずはMaterial DomainをPostProcessにしたポストプロセスマテリアルを作ります。ポスプロとはこれまた大雑把に言うと、レンダラーが色々計算して仕上げてきた絵に後乗せ加工する自動Photoshopみたいなやつです。詳しい説明やどのように設定するのか、といったことは公式ドキュメント読んでみてください。

f:id:noume:20201226210245p:plain

SceneTextureノードの「PostProcessInput0」のチャンネルを指定します。これがレンダラーの上げてきた完成絵です。ここに色なりテクスチャなりを合成した絵を作って、Lerpでブレンドします。

CustomDepthを使う

さてこのブレンドのマスクに何を使うか、といったところなんですが、マテリアル上だけでこねこねすると数式的なやつとか説明とかが大変になりそうなので、もっと手っ取り早い解決策を探すことにしました。で、ポスプロを使ったことで閃いた、もっと簡単な方法を説明しようと思います。

まず板をレベルに配置します。そして以下のようにレンダリング設定を変更します。

f:id:noume:20201226210746p:plain

この板に影を落としてほしくないのでついでにCast Shadowもきっておきます。

f:id:noume:20201226210850p:plain

この時点で、見た目上は全く透明な板ができあがります。

f:id:noume:20201226210945p:plain

そして、さきほどのポスプロマテリアルに次のようなノードを追加します。

f:id:noume:20201226211053p:plain

CustomDepthというのは、ざっくりいうと、指定した(上のレンダリング設定でRender CustomDepth Passにチェックを入れた)オブジェクトだけを抜き出したチャンネルを作る、マスク用に便利な機能です(もちろん詳しい話は公式ドキュメントをお読みください)。するとこの時点で先ほどのシーンが、こんな形に板部分だけ抜き取ったような絵ができあがっています。

f:id:noume:20201226211320p:plain

あとは気合で調整

この時点でお判りでしょうが、あとはこのマスク代わりの板切れをどうコントロールするかだけの問題になります。カメラを置いたその前で、スケールをかけたり回転させたり出したり消したり、といったことを通常のBPやシーケンサでちょいちょいやるだけ、ということになるので、マテリアルでUVどうこうするよりは直感的ですよね。四角いマスクだけでなく、任意の形のメッシュを準備し、CustomDepthに書き出すようにすれば、自由な形でマスキングできます。

https://twitter.com/noume_ri/status/1342889896227160064?s=20

↑ 雑に動かしてみた感じが上記。リニアなアニメしかしてないので、ちゃんとイーズ調整したらしゃきっとすると思います。

https://twitter.com/noume_ri/status/1342889896227160064?s=20

細かく言えばレンズの歪みが無視できなかったり、サンプルにあった枠がなかったり、というのがありますが、手軽さとカスタマイズ性を優先した例として挙げてみます。

 そしてもっといい解決策があれば教えてください。

VectorNoiseとDrawMaterial To RT

ぷらぷらとマテリアルネタを探していたわけです。

 ほーんおもろそうやんけ、写経ります。

f:id:noume:20201203074430p:plain

f:id:noume:20201203074456p:plain

ワーイUEサイコーとなるわけですが

Vector 表現式 | Unreal Engine Documentation

これらの関数はランタイムに負荷がかかるため、外見が決定した後は 4.13 以降で導入された Draw Material to Render Target Blueprint 機能を使って計算のすべてまたは一部をテクスチャにベイクすることをお勧めします。 

 なるほどですね。そんなわけで参考にします。

[UE4]マテリアル内で色調整を行ったテクスチャをベイクして処理負荷削減!|株式会社ヒストリア

f:id:noume:20201203081023p:plain

元のマテリアルでRTの描画対象とした属性のところ(今回はOpacityMask)に、書き出ししたテクスチャをぶっ刺します(上のVecterNoiseではRGB3チャンネルで書き出しされているので、テクスチャ出力もRGBをぶっ刺すのがいいぽい。多分チャンネルごとに処理されてる)。

f:id:noume:20201203082245p:plain

確かに負荷は下がっているっぽいですね。終わり。

GLSLをHLSLに置換してCustomノードで遊ぶやつ

GLSL SandboxやShaderToyの超スゴ投稿をUE上でみたいよーというとき。

参考サイト

メモ

基本は上の参考サイト通り。個人的なメモは以下

  • カスタムノード内にreturn がないとエラーになる
  • uniform float timeはtimeノードに、 gl_FragCoord.xy / resolution.xy は単にtexcoord入力に置換できる

Clothシミュレーション

参考サイト

用意するもの

  • 適当に分割されたスケルタルメッシュ
  • UE 4.25.4(手順は4.16ごろと変わってないぽい)

手順

  1. ほどほどに分割したメッシュと、スケルタルメッシュにするためだけに入れた雑ボーンをfbxで書き出し

    f:id:noume:20201117025424p:plain

  2. UEにインポート後、スケルタルメッシュエディタから「セクション選択」をオンにし、対象のクロスを選択→右クリックメニュー「セクションからクロスデータを作成」

    f:id:noume:20201117025844p:plain

  3. 「クロス」パネルから先ほど生成したクロスデータを選択

    f:id:noume:20201117030158p:plain

  4. 「クロスペイントを有効にする」ボタンをオンにするとメッシュがピンク色に変わるので(クロスパネルのClothPaintingがブラシなのを確認して)クロスの頂点を塗る

    f:id:noume:20201117030500p:plain

  5. 必要な個所を塗り終えたら「クロスペイントを無効にする」ボタンでペイントモードを終了する。ただしこのままでは修正が適用されていないので、もう一度メッシュ上で右クリック「クロスデータを適用」を行う必要がある

    f:id:noume:20201117031003p:plain

  6. 適当にレベルに配置し、Wind Directional Sourceを置いて風を送ってみる

    f:id:noume:20201117031445p:plain

  7. 効きが悪ければ、Wind Directional Sourceの風速を上げるなり、クロスパネルの詳細を変えてみるとかするといいかもしれない

    f:id:noume:20201117031729p:plain

追記

ペラいメッシュでない場合は使えない場合もある模様

Audio Visualizar PlugIn

参考先チュートリアル
メモ
  • 標準プラグインのSoundVisualizationPlugInを使うとビジュアライザがさっくり作れる

    f:id:noume:20201031012810p:plain

  • プラグイン固有の関数で使うのはCalculate Frequency Spectrumだけ

    f:id:noume:20201031012949p:plain

  • あとは正方グリッド状にのメッシュを配置して、Calculate Frequency Spectrum関数の戻り値(配列)と同じインデックスのメッシュにスケールをかけるのを更新しつづけるだけ
  • 配列要素数を正方形に並べる場合、総数のsqrt値で行と列のループ処理を簡単にかけるのもよかった。今後も役に立ちそう