夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【Blender, Unity】ノーマルマッピングでちょっとした凹凸をつける

私がノーマルマッピングを初めて体験したのはXBOX360バイオショックというゲームでした。
壁のタイルがデコボコして縁がテカテカしているように見えるのを「これがノーマルマッピングかー」と感動しながら視点をグリグリ動かして遊んでいました。

さて、そんな感動的なノーマルマッピングを自分がモデリングした物体に施せる日が来るとはその時は思いもしませんでした。

これまでモデリングしてきたCR-Xですが、正直ノーマルマッピングを試せるような場所はほとんどありません。
と、いうことで今まで忘れていたナンバープレートを急遽取り付けてみました。

ついでに今までテクスチャで汚く反射を書き込んで誤魔化していたヘッドライトの具もモデリングし、完成したモデルがこちら。

f:id:takujidev:20151020220430j:plain

f:id:takujidev:20151020220443j:plain

肝心のナンバープレートは残念ながら解像度が足りなかったせいか少しいびつにデコボコしているように見えます。

今回は白黒で高さを表すハイトマップを手書きで作成し、それをUnityに取り込む時点でノーマルマップ化しています。

こちらがハイトマップ。
f:id:takujidev:20151020221058p:plain

白いほど高い所、黒いほど低い所です。ここではナンバープレートとホイールナットだけ白くしています。

UnityのProjectパネルからハイトマップのファイルを選択し、Texture Type をNormal mapにし、Create from Grayscaleにチェックを入れればUnityが内部的に青紫色のノーマルマップとして扱ってくれます。

f:id:takujidev:20151020221328p:plain

あとはこれをStandard シェーダーのNormal Mapスロットにドラッグするとデコボコするはずです。
デコボコ具合は先ほどのテクスチャ取り込み設定画面のBumpinessかNormal Mapスロットのパラメーターで設定できますので、いい感じに設定してあげます。私はNormal Mapのパラメーターは1のままBumpinessを0.01にするといい具合になりました。 なお、Bumpinessの値を変更したあとはApplyボタンを押さないと反映されないので注意です。

拡大するとこんな感じです。

ノーマルマッピングなしの場合
f:id:takujidev:20151020223335j:plain

ノーマルマッピングありの場合
f:id:takujidev:20151020223351j:plain

あんまり綺麗じゃありませんでしたね。

Blenderの場合は新たにテクスチャスロットを作ってそこにグレースケールのハイトマップを開き、Influence設定のGeometry:Normalにチェックを入れ、こちらもパラメーターを変化させて丁度良い具合にします。
f:id:takujidev:20151020224135j:plain
Blenderレンダリングした場合はUnityよりは少し綺麗に見えます。
ただ、地面に反射したナンバープレートはおかしく表示されてしまいました。

さて、ライトのモデリングですが、こうなっています。

f:id:takujidev:20151020224716p:plain

前回の百式のくだりで書いた通り、UnityではスペキュラーマップのRGBチャネルの値によってMetallicパラメーターを設定できます。

tf.hateblo.jp


ライトの反射鏡のようなパーツは不透明の白(RGBアルファ全部最大値)にすれば綺麗な鏡面になります。
あとはライトのガラスを表現すれば完成ですが、透き通った材質を表現するにはマテリアルを分け、そのマテリアルのシェーダーのパラメーターを変える必要があります。
使うシェーダーは同じStandardシェーダーですが、Rendering ModeをTransparentにします。
あとはテクスチャーを設定してやればOKです。マテリアルが違っても同じテクスチャを共用することは可能です。

最後に、Smoothnessの値を調整して太陽の光が当たった時にいい感じに反射するようにしてみました。

f:id:takujidev:20151020230623j:plain

今回でCR-Xモデリングは完成となります。この1台作るのに1ヶ月以上かかったと思います。
もっとペースアップが必要ですね。

最終的にVerts 3749, Faces 3679, Tris 7198となりました。

https://itunes.apple.com/jp/app/toraberushutingu-retorona/id917570972?mt=8&uo=4&at=10laCt
https://itunes.apple.com/jp/app/beecluster-wu-liaono-zongsukurorushutingugemu/id663801586?mt=8&uo=4&at=10laCt

【Blender, Unity】車体各部の材質の違いによるツヤ・反射の具合をテクスチャでコントロールする

前回はテクスチャマッピングCR-Xのボディやタイヤ・ホイールの色の塗り分けをしました。

tf.hateblo.jp

テクスチャマッピングで色をつけるとマテリアルを分ける必要がないのでドローコールが減ってUnityでの表示処理が軽くなるはずですが、そのままだと全体に同じ質感が適用されてしまいます。
そのため、BlenderやUnityのマテリアルのパラメーターでボディのツヤや映り込みを適切に設定するとタイヤやボディパネルの隙間まで万遍なく艶やかになってしまいます。

これではリアリティが無さすぎるので、今回はスペキュラーマッピングを施して車体の部位や材質によって適切な質感になるように改良してみました。

まずは結果から。

Blenderで普通にSpecular、Mirrorの設定をした状態です。

f:id:takujidev:20151017175829j:plain

向かって左のライトに光が当たるようにしていますが、ライトの周囲の本来隙間になっている部分まで光を反射してしまっています。また、タイヤの側面が周囲の色を反射してまるで硬いプラスチックでできているように見えます。

スペキュラーマップのテクスチャを適用してみました。

f:id:takujidev:20151017180541j:plain

ライト周囲の隙間の部分の反射が抑えられているのがわかりますか?

この状態ではまだタイヤの質感はそのままなので、ボディの映り込み(Mirror)にもテクスチャを設定します。

f:id:takujidev:20151017181006j:plain

タイヤやドアモールの反射が抑えられました。ちょっと抑えすぎな気もしますがまあいいでしょう。
また、ドアとボディの隙間がつや消しになり、ちゃんと分離しているように見えます。

お次はUnityです。
UnityのスタンダードシェーダーではBlenderとは違い、1つのテクスチャで反射と環境マップの映り込みがコントロールされるので設定するテクスチャは1つだけです。

スペキュラーマップ適用前

f:id:takujidev:20151017182222j:plain

適用後

f:id:takujidev:20151017182234j:plain

タイヤの質感が変わっているのがわかりますか?
また、タイヤハウスの内側やバンパーの空気取り入れ口の反射も抑えられています。


さて、これらの質感の設定を実現するテクスチャの作り方ですが、私の場合は例によってこのソフトを使いました。

多分他のペイントソフトにも同じような機能はあると思います。

塗る場所を決めるために前回色付け用に作ったUVレイアウトを引き続き使用します。

表現したい材質に合わせてグレースケールで色をつけます。
よく反射する材質は白、全く反射しない材質は黒、その中間の材質は反射率に合わせた灰色といった感じです。

こうなりました。
f:id:takujidev:20151017183041p:plain

まずは、BlenderのMirror用のマップとしてUVレイアウトの線画のレイヤーを非表示にして書き出します。

f:id:takujidev:20151017190420p:plain

次に、これをベースにBlender、Unity用のスペキュラーマップを作りたいので、レイヤーをコピーします。

複数レイヤーに分けて作っていた場合は、それらのレイヤーをコピーしてから統合します。

次に、編集→色調補正→階調反転で白黒の階調を反転します。

f:id:takujidev:20151017190432p:plain

最後に、編集→輝度を透明度に変換で白黒をアルファ値に変換します。

f:id:takujidev:20151017190109p:plain

ソフトによっては輝度を透明度に変換する時の扱いが逆(輝度=不透明度)だったり、変換した後のベースの色が白だったりするかもしれません。その時は階調反転と輝度の変換の順番を逆にするなど手順の調整が必要かもしれません。
いずれにしましても、必要なのは黒ベースにアルファチャネルが乗った画像です。
Blenderのスペキュラー設定ではアルファチャネルしか見てないようで、白ベースでも黒ベースでも同じ結果になりますが、Unityではベースの色(RGBチャネル)がStandard ShaderのMetallic設定、アルファチャネルがSmoothness設定に対応するので、ベースの色で表示結果が変わります。
ちなみに白ベースのテクスチャーだとこのようにメッキをかけたような質感になります。

f:id:takujidev:20151017191603j:plain

Zガンダムに出てくる百式を再現する時にはいいかも知れませんね。

UnityのStandardシェーダーにスペキュラーマップを設定するにはMetallicのテクスチャ用スロットにプロジェクトファイルにコピーしたテクスチャーファイルをドラッグ&ドロップします。
Standard(Specular setup)シェーダーの場合はSpecularのテクスチャスロットにドラッグします。
私は環境マッピングによる映り込みがよりはっきりしているStandardシェーダーの方が良いと思いました。

先ほど書いた通り、Unityではスペキュラーと環境マップの映り込みは1つのテクスチャ(アルファチャネルによるSmoothnessの値)で制御されます。
アルファ値が高ければ表面がなめらかになり周囲の景色がはっきりと映り込みます。また、スペキュラーはより鋭く小さくなります。
これが結構厄介で、アルファ値が最大だとスペキュラーが小さくなりすぎて逆に見えなくなり、ツヤ感が下がってしまいます。
ペイントソフトでアルファ値を変更したテクスチャをいくつか作って比べてみました。

アルファ値が100%の場合

f:id:takujidev:20151017195051j:plain

98%に下げた場合

f:id:takujidev:20151017195108j:plain

95%に下げた場合

f:id:takujidev:20151017195120j:plain

フェンダーのあたりのスペキュラーの大きさとボディに映る景色を比べてみてください。100%の場合はスペキュラーが全く見えません。95%に下げたくらいがちょうどいい感じですが、景色の映り込みが弱いので、私は間をとって98%に設定しました。


Blenderの場合はまずMaterialのパネルを開いてからTextureのパネルを開き、テクスチャのスロットを一つ選び、Newをクリックします。
まだ色のテクスチャを設定していない場合はImageのOpen Imageアイコンをクリックして前回作った色分け用のテクスチャを設定します。
同様にSpecular用とMirror用のテクスチャも開きます。
Specularのテクスチャを設定する場合はマテリアルパネルのSpecularのIntensityは0.000に設定し、テクスチャパネルのSpecular: Intensityにチェックを入れます。一方、MirrorのテクスチャはShading:Mirrorにチェックを入れます。
以上の設定でBlender上でいい感じに表示されると思います。


さて、ここで残念なお知らせがあります。

秋葉原を舞台にしたオープンワールドなレースゲームというコンセプトでこれまで開発してきましたこのゲームですが、モバイルデバイスでは満足できる処理速度が出ないことが判明しました。
最近開発機としてiPhone 6を使い始めましたが、目標としてきた30フレームには届きませんでした。
もしかするとiPhone 6sだと行けるかもしれませんが、最新機でしか満足に遊べないゲームというのも考えものです。

また、アプリのサイズも問題で、現状200Mバイト以上あります。
これではストレージの空き領域が厳しい16GBのiPhoneからは真っ先に消される運命でしょう。

そこで、少しコンセプトをねじ曲げようかと考えています。
舞台を秋葉原ではないもう少しシンプルな景色の場所にして処理速度を稼ぎやアプリサイズを小さくするという目論見です。
もしかするとオープンワールドという要素も置き去りになる可能性があります。

と、いう訳で、完成がいつになるのか全く目処がつきませんが、コンセプトをリニューアルしてさらに開発を進めていきたいと思います。

https://itunes.apple.com/jp/app/toraberushutingu-retorona/id917570972?mt=8&uo=4&at=10laCt
https://itunes.apple.com/jp/app/beecluster-wu-liaono-zongsukurorushutingugemu/id663801586?mt=8&uo=4&at=10laCt