みなさんは BoxMask-2D ノードというものをご存じだろうか。

このBoxMask-2D というノードはUV空間に矩形を出現させるという恐ろしいチカラをもったノードで、どんなに精巧に作られたテクスチャであろうと、設定を間違うと全てを塗りつぶしてしまうこともあるという。
なにやら不穏な気配漂うノードだが、目線を消す処理やレターボックス風に使えたり、


と、上手く手なずけることができれば、それほど怖いものでもないかもしない。
ちょうど手元に目パチのサンプル用のキャラがあるので、口をぱくぱくしてみようと思い、この BoxMask-2D を試みることにした。
まずは、ベースとなるテクスチャ。
口も消え、さらにのっぺらぼう率上昇。

テクスチャ設定はそのまま
Mip Gen Settings : NoMipmaps
CompressionSettings : UserInterface2D (RGBA)
Filter : Default
目は前回のを使うとして、今回は口のパターンを用意した。
パターン数は5
128 x 512px

テクスチャの設定は
Mip Gen Settings : NoMipmaps
CompressionSettings : UserInterface2D (RGBA)
Filter : Default
各パターンのサイズは 128 x 80px
BoxMask-2D ノードの攻略をすべく、ワールドワイドウェブに情報を求めた。
そこで入手した貴重な情報によると、

ということらしい。
V2と括弧書きされているところは、Vector2型の値が必要ということで、UV空間での値になるそうだ。つまり 0 から 1.0 の割合で指定することになる。
口パクのテクスチャを作成した際に、切り出した領域をわかりやすくしておいた。

中心位置が分かるように、矩形の範囲を市松に塗り分けた。
矩形の大きさは偶数であることが好ましい。奇数だとピクセルを半分にできないからだ。
必要な座標は Photoshopでは選択範囲を使って簡単に調べることができる。

ドキュメント左上からの選択範囲の大きさが情報パネルに表示される。

ちなみに、選択範囲は飛び地になっていても問題はなく計測できるので、拡大してしっかりとピクセルの状態を確認しながら選択範囲を作るといい。

調べた結果。

これをUV空間の値に変換する。
UV値に変換するのは、テクスチャの大きさで割ればいい。
大事にならないことを祈りつつ BoxMask-2Dノードに必要な情報をつないでいく。
A には TexCoordノードをそのままつなぐ。
B のところには、Constant2Vector ノード(2キーを押しながらクリック)をつないで値を入力する。
X は U方向、 YはV方向に相当する。
入力フォームに 188/512 とタイプしてEnterキーを押すと、計算してくれるから大変助かる。

これで矩形の位置が合っているか確かめるために、あえて下のような状態のテクスチャを書き出して、エンジンのテクスチャを再インポート。

これが
↓こうなれば BoxMask-2D を制御できたことになる。

さっそくキャラのテクスチャに掛け算してみよう。
キャラのRGBに掛け算すると、こ、これは!

なんと恐ろしい。キャラが矩形で塗りつぶされてしまった。
いや、まて、アルファにはBoxMask-2Dの力は及んでいない。黒くなったということは、RGBに 0 が掛けられたということだ。ふと気づいて OneMinusノードを間に入れ、0 と 1 を反転するとうまくいった。

表示倍率を上げると、バイリニアフィルタによって、ピクセルの境界がボケて色のにじみが起こるので油断は禁物。

実際にテクスチャより大きく表示すると絵がボケるため普通はやらないから、等倍で表示して問題ないなら大丈夫だろう。
UV値に変換する手前、奇数にならないようにするのも大事だ。小数点で扱うため丸め誤差が出にくくなる。
この BoxMask-2D ノードを Lerp(LinearInterporate: 線形補間)ノードにつないでキャラと口パクの融合を試みる。OneMinusノードは計算量を減らすために外す。

結果は?

うまく2種類のテクスチャが融合したが、位置がおかしい。
そこで口パクの位置についてUV位置を補正する。
マテリアルの中で複数のテクスチャを扱う場合、UV空間は一つであるため、倍率を揃える必要がある。
キャラ絵は 512 x 512px、一方口パクのテクスチャは 128 x 512px と横が 1/4 しかない。そのままつなぐと横に伸びてしまう。

そこで、TexCoordノードの UTiling を 4.0 にしてアスペクト比を合わす。

当然タイリングするが、BoxMask-2D でマスクするので見えるのは1枚だけだ。問題ない。
あとは、これを適切な位置にずらせばいいだけだ。これも左上からのピクセル数を調べるとわかる。

この数値をテクスチャ解像度で割ればいいだけだが、横方向を4倍にしているため、124/512 とやるとずれてしまうのは少々ややこしい。正しくは 124/128 になる。口パクテクスチャのサイズの通りといえばそうなのだが。
UV座標空間の少数部分のみを視覚化すると下のようなイメージになる。
(普段使う領域は 0~1.0 の領域で、それ以外は暗くしてある)

U方向に4倍ということなので、0~4.0 の領域が圧縮されるかたちで表示サイずに収められるので、見た目にこのように視覚化される。

広角レンズで風景を撮ったのと似てるかもしれない。
画像サイスは一定なのに、広角レンズは視野角が広いのでより広い範囲を収めることができる。
右下方向にずらしたいので、マイナスになるように計算する。つまり、
U方向は、-124/128 =-0.96875
V方向は、 -198/512 = -0.38671875
0原点の場所が左上にずれるイメージで、結果として絵が右下にずれる見た目になる。

これは望遠鏡やカメラのファインダーから景色を覗くのに似ている。

この鳥を真ん中に捉えようとしたときのスコープを動かす向きをイメージするといい。
(対象の進行方向への移動は無視)

この位置補正を加えると、


よしよし、あとはパターンを切り替えられるようにすればOK。

パターン切り替えの計算を追加している部分。

この辺は目パチと基本は同じ。
Indexの値を切り替えることで、口パクのパターンが切り替わるようになった。
目パチは待機中の表現として常時動かすのは気にならないのだけど、口パクについては適宜タイミングを見て動かすほうがいいのでWidgetブループリントで試してみることに。
そのまえに、キャラ絵を元に戻して更新。

ひとまずテストとして、タイムラインからマテリアルのパラメータを書き換えてみる。

キーを打ってそのままだと、補間のタイプが Cubicになっている。

まるでスロットマシン・・・

キーの補間タイプを Conatant に変更。
全部を選んで右クリックするとメニューが出てくるので変更が可能。


Constant はキーの間を補間しないので、キーを打ったタイミングで書き換わることになる。

完成!
BoxMask-2D ノードでうまく部分書き換えができた。UV値の扱いが繊細なので、表示倍率が変わると隙間が出たりするから、調整に気を遣う印象があるけど、以外に使えるやつかもしれない。パーツの切り出しにきれいな値を使えば誤差も減らせるはず。
半透明にしてもきれいにフェードできそう。
Render Opacity を 0.5 にしてみると、

口は自然に薄くなってる。フェードに強いのはありがたい。
目は上に重ねているので、やっぱり明るくなってしまう。
初めて使ったノードだったけどうまくいってよかった。
ちょっと違う文体を意識してみましたがいかがでしょうか?
一息に書かないとブレるので難しいですね。
UV座標の計算については、職業柄 日常なので特に気にはならないのですが、慣れてない方に向けてちょっと丁寧に説明を書いてみました。
ゲーム開発においていろいろ効率化のためにもテクスチャアトラスを作るのは大事ですが、こういったアセットの制作にAIがうまいことやってくれる時代がそう遠くない未来にやって来るかもしれませんね。
ではでは今回はこの辺で
すてきな口パクライフを!