アーティストのためのまてりある式にゅうもん
こんにちは、なんです。
この記事はUnreal Engine 4 Advent Calender 2019その2
の8日目の記事になります。
はじめに
実はこの記事、なにもUE4に限ったことではなくノード型マテリアルエディターを使ったマテリアルの作成において、どんなケースでも当てはまる「基本の考え方」について解説するものになります。
趣旨
アーティストは数字が苦手…残念ながら3D CGやゲームエンジンに入門したてのアーティストでは特に、マテリアル式の意味をさっぱり理解せず、なんとなく「これを繋げるとこうなる」的に覚えてしまっていたり、そもそも写経だけで自分ではマテリアル式を組み立てる方法さえ分からない、というケースが散見されます。
そこでこの記事では、マテリアル式で使う基本的な演算ノードについて解説を行い、数式によって見た目や色がどう変化するのか?についてお話ししたいと思います。
※ちなみにこの辺の知見って基本すぎるし分かるやろ?ってコンセンサスなのかほとんどちゃんと取り上げているソースを見ないのがちょっと残念。
Part1
それでは早速UE4でかんたんなマテリアルを組みましょう。
どれくらい簡単かというとこれくらい簡単です。
このマテリアルはシェーディングモデルをUnlitに設定しました。
Unlitはベースカラーやメタル、ラフネスといった質感を持たないエミッシブカラー(自己発光色)だけで見た目を作るマテリアルです。
左に置いた赤いノードはVector Parameterです。「Color」となっていますが、名前を好きにつけられるのでぼくがColorと入力したのです。YasaiでもOnikuでもなんでも構いません。とにかく意味しているのは4つの要素を持つベクターパラメーターである、ということだけです。そしてこの、ベクターパラメーターこそアーティストを最初に混乱させるノードだとぼくは思います。
なぜならこの、ベクターパラメーターは「色」を表現しているからです。
拡大しました!わかりやすい!
Param(1,0,0,0)となっているのが分かりますね。そう、この数値の意味はRGBになぞらえて、Rを1、Gを0、Bを0にしたので赤いのです。最後のグレーの場所はアルファ(透過)だと考えてください。つまりRGB+Aです。
UE4のマテリアルノードでは「色」というノードを使わず、このようにベクターパラメーターを用いて色を表現します。
それではベクターパラメーターってなんでしょうか?ベクターとはベクトルのことです。数学でベクトルとか聞いたことはありますよね。もうこのベクトルという名称が出てきただけでも苦手意識を感じてしまうひとがいるかもしれません。
数値は基本的に「量」を表します。つまり大きさです。
誰でも1より10が大きいことは理解できると思います。0.1より1.0が大きいことも理解できますよね。
UE4においても、他のノードグラフにおいても、単独の数値があったなら、それは同じように大きさを表しています。今回の「Color」と名付けたベクターパラメーターでは、数値の大きさはRGB(+A)各チャンネルの「明度」をコントロールしています。
それではこの数値を複数用意したなら、なにを表現できるでしょうか。
↑簡単なグラフを作ってみました。
このグラフを2次元の平面と考えることができます。
すると(0,0)はこの平面の原点座標になります。(1,1)はXとYの座標が1になる場所のことです。勘の良い方ならもう気付いたかも知れません。
同様にして数値をひとつ増やして(1,0,0)と表現すると、3D空間における位置、つまり座標を表現することができます。驚きませんか?これが3Dアーティストにとって最も身近なベクターパラメーターの意味です。つまりRGBという色を表現している3つの数値を使って、3次元空間における位置を表すことができるのです。
ベクターパラメーターとは?
もう一度ベクターパラメーター、あるいはベクトルについて考えます。
ちょっと調べてみると…
大きさだけでなく、向きももった量
要素を(縦または横に)一列に並べたもの
というのがGoogle先生の最初に出て来ました。
先ほどのグラフを思い出せば、ベクトルが向きを表現できることは理解できますね。また、向きや位置を表現するには数値が二つ以上ないと難しいことも分かります。
もっと3Dアーティスト風にいえば、RGBで表す色も3D空間の頂点の位置もベクターパラメーターであり、それは単に数値を2つとか3つとかそれ以上とか並べたものだ、ということです。
ではこういう捉え方はどうでしょう。
『複数の数値の組み合わせであるベクターパラメーターによって、色や位置や方向を表現することができる。なにを表現するかはその時の都合で良い』
↑思考が柔軟じゃなかったり、固定観念に囚われている(色は色でしかないとか)と、この考えが案外分からないというか、捉えられません。また、アーティストとエンジニアの間でコミュニケーション不全が発生してしまう原因も、この辺にあるのではないだろうか?とぼくは考えています。
PART2
スタート地点を(たぶん)過ぎたので先に進みましょう。まさか…すでに混乱していないですよね?
ここからが本題です。
先ほどまではベクターパラメータの数値は(1,0,0,0)でした。これを(100,0,0,0) にしてみました。すると…
マテリアルプレビューが変化して、このようにエミッシブによる発光表現が得られます。これは、パラメーターの意味が分からなくても「エミッシブを上げたので光った」という風に理解しやすいですね。
ではフォトショップで…
↑のように50%のグレーで背景を塗りつぶしました。
次に↑のように背景を複製してレイヤーにし、乗算で重ねてみました。
その結果はどうなるでしょうか?
Photoshopで絵を描いたり、写真の編集をしていればご存じですよね。はい、元のグレー画像よりも暗いグレーが表示されるはずです。
しかし多くのアーティストは「乗算すると暗くなる」ことを知っていますが「なぜ乗算すると暗くなるのか?」は分からない、と答えます。「そういうものだから」で済ませているからです。
まったく同じ状況をUE4のマテリアルで表現することができます。
上で「Multiply」とあるのが「乗算ノード」です。単純にかけ算をするための演算ノードになります。そしておそらく、最も頻繁にマテリアル式で使うノードとも言えるでしょう。
色についてはグレースケールではなくRGBカラーで考えると、前述のフォトショで作成したように50%のグレーはRGBそれぞれが.5になります。各色8bitの256階調であれば128(または127)ですね。
■追記■
Photoshopなどで各色8bitで24bitカラーの場合、中間グレーは128になるので計算式は128×128なのでは?という疑問はもっともです。しかし実際の計算は0から1.0の間で行い、カラー設定によって2bit(白と黒しかない)や8bitあるいはHDRIなどで使う各色32bitまでの「階調(帯域)」に当てはめているのです。
そして「乗算」というのは「かけ算」ですから
0.5×0.5=0.25
という答えが得られます。
1が真っ白、0が真っ黒で中間のグレーが0.5です。数値は「明るさ」を表していますので0.5に0.5を掛けたら0.25になり、暗くなるのです!
※エンジニアやテクニカルな事象を理解しているアーティストにとっては「それ知らなかったんですか?」ということかと思いますが、実際に乗算ノードの意味を説明できる初学者アーティストは少ないです。なので、これをヒントに「エンジニアとアーティストのコミュニケーション不全」について理解が深まれば、というのがこの記事の本当の主題であるかも知れません。
PART3
さらにフォトショップでこんな画像を作ってみました。
周囲は真っ黒なので数値にすると0で、真ん中の丸い部分は真っ白なので1です。
これを512×512のテクスチャとしてUE4にインポートします。
さらにノードをこのように組んでみました。
マテリアルのプレビューを分かりやすく立方体にするとこうなります。
また、Multiplyノードの右上にある△をクリックすることで演算結果をプレビューすることもできます。
なにをしているのかというと「白黒マスクで指定範囲に色をつけた」のですが、今までと同様、こういうマスクを使って色を塗れば、指定範囲に色がつくことは知っていても「なぜ指定範囲だけに色がつくのかの理由」を説明できるひとは少ないのではないでしょうか。それではあかんのです。
そこで、このように考えましょう。
↑Excelで白黒マスクに乗算を数値化したもの。Xの列は1が白で0が黒。Yの列はXに5をかけ算したもの。0になにをかけても0のままなのに対し、1に5をかければ当然答えは5になります。(数式に直すとY=5Xです)
さらに重要なこととして、Photoshopでの乗算は「白より明るい色」が存在しないので乗算の結果は必ず「もとより暗い色」になります。最大値は1×1なので1なのです。
しかしUE4での色はパラメーター(数値)に過ぎませんのでどんな数値でも掛けることができます。その結果…
ベクターパラメーターを(100,0,0,0)にすれば…
このような結果を得ることができます。
Photoshopでは乗算によって元の色より明るい色を作ることができません。しかしUE4を始めとするノードグラフ式のマテリアル(シェーダー)では1より大きな数をパラメーターとして利用することができるため、乗算によって「元より明るい色」を作成することができるのです。
PART4
それではもうひとつ基本的な「算数」をしましょう。
↑もまたExcelで簡単なグラフを作りました。
緑で示した列がもとのグラフでY=Xです。数値を単純に整数で増やしたものなので直線グラフ(リニアなグラフ)になります。
青い列はこれに+5をしたものです。(数式ではY=X+5)
右側のグラフを見ると、元のグラフに対して+5をしたものは「上側に移動」しているのが分かると思います。この「上側に移動」したのはなんでしょうか?そう、明るさなのです。
UE4でのノードグラフで加算は「Add」になります。
マテリアルプレビューの結果は↑の通りです。
その意味を考えると、先ほどの乗算では0になにを掛けても0のままでしたから黒い部分は光りませんでした。ところが、今度は加算…つまり足し算ですから0+100=100です。そのため、マスクを使うケースでの加算はうまい利用法がすぐには思いつきません。
しかし、先にExcelでグラフの例を示しましたが、加算を使うと「グラフを移動(シフト)させられる」ことが分かっています。
そこで
マテリアル式をこのように変えて見ました。
ちょっと要素が増えましたね。
左上にある赤いマテリアルノードは「Texture Coordinate」というものです。これはUV座標を操作するためのもので、テクスチャをタイリングしたり、UV座標で「動かす」ために使います。
また「UV」と書いてあるのは「スカラーパラメーター」です。定数(Constant)に対して変数(Parameter)があるのですが、スカラーパラメーターは単純な数値の大小を与えるのに使います。
■追記■
ベクターパラメーターが座標や向きを表現できるのに対してスカラーパラメーターは単純な数値の大小、つまり「量」を与えます。ここでスカラーとは英語(正確にはラテン語)のScaleから来ていて「Scalar」と書きます。Scale(スケール)が拡大縮小を表現するように、スカラーはベクトルをかけ算したり足し算したりするときに使います。
先ほどのベクターパラメーターを「Color」と名付けていたように、パラメーターの名前は好きなようにつけることができます。分かりやすいように「UV」としましたが、これもSushiでもNikuでも効果は同じことです。
どうでしょうか。
この結果はTexCoordによって与えられる「もともとのUV座標」に対してAddつまり加算で0.2を足して、白黒マスクのUV入力につなぎました。その結果、キューブのメッシュに投影されるマスクの座標が動いたわけです。
加算はPhotoshopであれば単純に「元の色に対して色を足し算する=明るくなる」結果が得られますが、UE4では色を明るくする以外に、UV座標を動かす操作、つまり「座標ベクトルを移動させる」ことにも使えます。
ではさらに…UV座標というのは横をU、縦をVと定めたテクスチャマッピング用の座標系であることは3Dアーティストならご存じですよね。通常は0,0から始まり、1,1でひとつのUV平面を形成しています。
つまりUVを操作するならば…U座標とV座標をそれぞれ別々に動かせたほうが便利そうですね。
さらに見慣れないノード式が出て来ましたが、これはAppend Vectorというもので、二つの数値をベクトルとして並べてくれる(合成する)ものです。Appendをいくつも重ねればもっと多数の要素からなるベクトルを作ることもできます。
このマテリアル式では「U」と「V」というスカラーパラメーターを用意して、Appendによりベクトルとして合成し、TexCoordのUV座標にAddで加算を行っています。
Uは0になっているので横方向には動きませんが、Vに0.2を入力してあるので縦方向にマスクが移動するはずです。
いかがでしょうか。
予想通り、キューブに投影されたマスクが縦方向に移動したのが分かると思います。
また、パラメーターはマテリアルインスタンスで自由に操作したり、ダイナミックマテリアルインスタンスを作成することで、ゲームプレイ中でも動的に動かすことが可能です。
このような仕組みを使えば、エフェクトでUV座標の中でテクスチャを動かしたりすることができるのです。
最後に
今回は長くなりましたのでここまでにしますが、ほかにもUE4のマテリアル演算にはPower(べき乗)やDivide(割り算)、さらにFloor(切り下げ)やdot(内積)などがあります。
しかし、マテリアル式を考えるための基本は、今回の記事で示した通りです。すべてはその応用に過ぎません。
それぞれ意味が分かってしまえばそれほど難しいものではありません。数学や幾何学が苦手だった方でも、じっくり考えればきっと理解できると思います。好きなゲームを作るために「なぜそうなるのか?」という理由を理解することはとても大切です。
明日は