この記事はUnreal Engine 4 (UE4) Advent Calendar 2014の13日目の記事です。
今回はこれといったテーマはないですが、先日のUE4勉強会でEpicの下田さんがやっていたようなマテリアルのネタをとりとめもなく紹介していこうと思います。
まずこの画像をご覧ください。
この画像の真ん中部分、皆さんには何色に見えるでしょうか?
左が白、右が黒はどなたでも同じだと思いますが、真ん中はグレーにみえますか?
よく見ていただければわかるのですが、これはグレーではなく黒と白のチェッカーです。
現在のPCやゲーム機はフルカラー画像が当たり前ですが、20年位前は16色とか256色とかが主流でした。
16色では滑らかなグラデーションを描こうとしても16階調しか作れませんし、それを作ると他の色は全く使えないことになります。
そんな時代に生み出されたグラデーションや半透明を表現する方法がこのチェッカーパターンによる表現でした。
当時はディスプレイもCRTで滲みもあったため、結構それっぽく見えたんですよ。
なんでこんな話をするのかというと、UE4の半透明って色々コスト高いよねっていう…
話が見えない?
つまり、この技術を使えば不透明でも半透明できるじゃん!というわけです。
それを実現するのがこのマテリアルファンクションです。
エンジン側のコンテンツとして存在しているDitherTemporalAAです。
UE4勉強会でも下田さんが使われていましたが、気づかれた方はいらっしゃるでしょうか?
このファンクションは主にOpacityMaskに使用する命令で、毎フレーム変化するディザパターンでピクセルを描画したりしなかったりします。
しかもそれにTemporalAAがかかると、複数フレームで大変綺麗に半透明っぽくなります。
実装してみた結果がこちらです。
どうでしょう?半透明にしか見えませんよね?
でも、これが不透明マテリアルです。
よく見れば、後ろのボックスの真っ直ぐであるはずの辺がざわついているのがわかりますが、動いてればそんなに気づきません。
この手法の半透明はライティング等がすべて不透明マテリアルとして行われるので、他の不透明マテリアルから浮いてしまうような状況を避けられますし、半透明マテリアルを使うよりコストが安いです。
しかし、制限も多い技術です。
先のマテリアルの入力、Alpha Thresholdにアルファ値を入力するのですが、こちらはデフォルトが0.5で、結果画像も0.5です。
この数値が一番綺麗に表示されますが、1.0や0.0に近い値ではうまく表現できません。
0.8くらいでは半透明っぽさは完全に失われてしまいますし、0.2くらいになるとディザパターンがまるわかりになります。
また、TemporalAAのお陰で、カメラが動いた際に奥のオブジェクトが伸びたように見えてしまいます。
もちろん、TemporalAAが無効の場合、あまり綺麗に描画されません。
下の画像はNoAAの場合の結果です。
シャドウマップも厳しいものがあります。
以下の画像がシャドウキャスタとして使用した場合のシャドウマップですが、さすがにこれは使えないですね。
静止画ではわからないですが、かなりざわざわします。
このように問題もある技術ではありますが、制限さえ守れば十分使い道がある技術です。
制限としては、
1.シャドウキャスタとして使用しない
2.アルファ値0.5付近から動くことがない
3.TemporalAAが使用できない環境ではない
これくらいでしょうか。
これらの条件から考えると、幽霊とか使えそうですね。
では、続きからは他のマテリアルの紹介を行います。
勉強会でもやったのですが、OpacityMaskを利用したオブジェクトが消えていく演出をもう少しかっこよくしてみました。
あれだとただ消えるだけですが、紙が燃えて消えていくような演出のほうが見栄えはするでしょう。
紙が燃えるときはやはり黒っぽくなって、最終的に穴が空くという感じになるかと思いますが、これを実現してみました。
動画じゃないとイマイチわかりづらいかもしれませんが、徐々に黒くなって穴が開いていきます。
マテリアルはこんな感じ。
MF_Paper_Deletion関数はこれです。
関数の出力はBaseColorBlendとOpacityMaskです。
OpacityMaskはそのままマテリアル入力のOpacityMaskに繋ぎます。
BaseColorBlendは様々な使い方があると思いますが、今回はBaseColor,Roughness,Normalの3つのブレンド値として使用しました。
紙が燃えるときは最初はオレンジっぽくなり、その後黒くなるよ!というのを実現したい場合はルックアップテクスチャを利用しましょう。
ルックアップテクスチャはRGBが色、Aにブレンド値を入れた幅256のテクスチャを用意します。
このテクスチャをサンプリングする際のUの値としてBaseColorBlendを利用し、DeletionColorの代わりにサンプリングしたRGB,BaseColorBlendの代わりにサンプリングしたAを利用しましょう。
この方がアーティストさんがいろいろかっこいい演出を作れるでしょう。
次もやはり削除演出です。
『Halo 4』では一部の敵を倒すと最後に着弾した地点から球状に崩れ去っていく演出がありました。
簡易ではありますが、これを実現したのがこちらです。
動きのある演出なので、シャドウマップのざわつきはゲームポーズされない限りそれほど問題にならないと思います。
あとはパーティクルでも飛ばしてあげればよりそれっぽくなるかな、とは思います。
マテリアルは以下です。
MF_Sphere_Deletion関数はこちら。
球の中心座標はワールド空間で指定するようにしていますが、Actorのローカル空間のほうがいいかもしれません。
次も消去、出現に使用できる演出用マテリアルです。これまた『Halo 4』から。
いわゆる空間ワープ的な演出として、ブラックホール的な何かに吸い込まれたり吐出されたりすることがあるかと思います。
これはある点に対して頂点を吸い込ませるようにすればいいのですが、そのために以下のマテリアルを作成しました。
MF_Absorption関数はこちら。
結果はこうなります。
どこに吸い込まれているのかがわかりやすいですね。
静止画だと微妙にも感じますが、動くとなかなかかっこいいですよ。
こちらはプレイヤーよりも手前側(カメラ側)にあるオブジェクトを丸くくり抜く演出用のマテリアルです。
手前と奥の柱はどちらも同じマテリアルですが、手前の物だけくり抜かれます。
残念なことにシャドウマップもくり抜かれてしまうのでシャドウに関しては焼き付けたほうがいいでしょう。
また、今回は単純にプレイヤー位置より深度がカメラ側にあれば、という判定をしていますが、カメラからプレイヤーまでレイトレースして衝突したオブジェクトだけ有効にするほうがいいでしょう。
マテリアルは以下です。
話は変わってエンジン備え付けのマテリアル関数にFlowMapが存在しています。
FlowMapはValve社が『Portal 2』で実装した、2Dベクタフィールドテクスチャを利用した水などの流れを作成するシェーダです。
従来の水の流れはUVスクロールで実現している場合が多いと思いますが、今どきはさすがに厳しいですよね。
基本的に1方向にしか進みませんし、流れを変えたいならポリゴンを細かく分けなきゃいけません。
細かく分けたとしてもUVスクロールなのがまるわかりなのでかっこ良くないです。
『Portal 2』ではテクスチャのRGをテクスチャのUV方向のベクタフィールドと定義、この方向にUVを移動させ、同じように移動させているもう1つの画像とブレンドすることで流れができているかのように見せかけます。
動画でなければわかりにくいので参考画像は提示しませんが、マテリアルは以下のようになります。
ベクタフィールドテクスチャは適当なものを用意しました。
関数的にはテクスチャである必要はなく、何らかのベクトルであればOKです。
テクスチャの生成にはオーサリングツールがあると聞いたことがありますが、ツールの名前はわかりません。申し訳ないです。
また、この技術は空の雲の流れにも使用できます。
『The Last of Us』の空の演出に用いられているそうです。
最後におまけのポストプロセスを1つ。
『ドラゴンクエスト』シリーズでお馴染み、旅の扉の演出で使用されるラスタースクロールです。
マテリアルは以下。
とまあ、完全にとりとめのないマテリアル紹介記事ですが、マテリアルはインタラクティブな処理にもよく使われます。
モデリングもテクスチャ描きも出来ないという方でも面白おかしいマテリアルの作成はできます。
マテリアルはこわくな~い、ということで、皆さんも色々いじってみてはいかがでしょう?
明日は@housakusleepingさんによる動画での解説だそうです。
動画による解説は大変貴重です。楽しみですね!