NormalMapを活用する
ゲームキャラクターなどでは描画速度を確保するためになるべくポリゴンを削減したりします。
でもある程度の詳細度も欲しい…。そんな時には凹凸を疑似的に表現できるNormalMapが便利です。
その凸凹を画像に変換することを「焼き込み/Bake(ベイク)」と呼びます。NormalMap以外にも表面色や反射色などもBakeすることができます。
NormalMapはすこし複雑なのでいったん流れを整理したいと思います。例ではCyclesでの方法を紹介します。
これから行おうとしているのは「ハイポリモデルと同じ位置にあるローポリモデルのUVを使ってNomalMapをBakeする」という方法です。
大まかな流れは以下のようになります。
- ハイポリモデル・ ローポリモデル を用意する
- Bake先(NormalMapになる)画像を新規作成する
- ローポリモデルのUV展開を行う
- 新規作成した画像をNodeEditerのimageノードで指定しておく
- ハイポリモデルとローポリモデルをできうる限り同じ位置にセット
- Bakeする
NormalMapをBakeする工程
ハイポリモデル・ ローポリモデルを用意する
ハイポリモデルとはスカルプトなどで作った高解像度(多ポリゴン)モデルのことです。ローポリモデルは低解像度(少ポリゴン)モデルのことです。
ハイポリモデルとローポリモデルはどちらが先に存在していないといけないということはありませんので、作業上のやりやすさや効率などで各自の好みでよいかと思います。
今回は人の頭部のモデルを用意してみました。
マルチソリューションモデファイアを使ってローポリとハイポリを混在させた状態のモデルをBakeに用いることも可能ですがこれについては別記事でまとめたいと思います。
Bake先(NormalMapになる)画像を新規作成する
Bakeするには空の画像(でなくてもいいのですが)が必要です。
UV/imageEditer(UVイメージエディタ)にて新規画像を生成しておきましょう。画像サイズは各位のプロジェクトに合わせた大きさにしてください。
画像が大きければ詳細な結果が得られますが、それだけレンダリングにも時間が掛かりますので、そのへんはトレードオフになります。
画像はuntitleのままにしておかないで名前を付けておくと後々混乱しなくてよいでしょう。ここではnomalという名前にしました。
この段階ではまだ画像を保存する必要はありません。
新規作成した画像をNodeEditerのimageノードで指定しておく
画像を生成しただけではその画像がBake対象になってくれません。Bake対象にするためにNodeEditer(ノードエディタ)で画像を読み込む必要があります。
ローポリに対してマテリアルが存在する必要があります。もしマテリアルがまだ無い場合は生成してください。
NodeEditerのNew(新規)ボタンから生成すると楽でよいかと思います。
さらにNodeEditerにてTextrue(テクスチャ)からImage Textrue(画像テクスチャ)ノードを出します。
そして先ほど生成した空の画像(nomalと名前を付けた)を指定します。
このノードはこの段階でどこかに繋ぐ必要はありませんが、後々NormalMapを指定するノードにするならNormalノードなどに接続しておくのも手です。
ローポリモデルのUV展開を行う
NormalMapのBakeはローポリモデルのUVをもとに実行されます。ですのでローポリモデルがUV展開データを持っていないとBakeはできません。
UV展開データがない場合は「No Active UV layer found in the object ”XXXX”」というエラーがでてBakeが失敗します。
UV展開作業はとてもつまらんですが、UV展開は品質に直結しますのでがんばりましょう…。
UV展開作業はUV/imageEditer画面で行っているかと思いますが、この段階でUV/imageEditer画面には先ほど生成した(nomalと名前を付けた)画像が表示されている状態にしておいてください。
こうしておくことでBakeの結果が表示されることになります。もし表示状態にしてなくてもエラーになるわけではありません。
もし同一マテリアル内で複数のImageTextrueノードで画像が読み込まれている場合はフォーカスされている(選択されている/ 枠が黄色になっている) ImageTextrueノードの画像にBakeが行われます。
複数のImageTextrueノードにフォーカス(選択状態)されている場合は、最後に選択されたもの(アクティブ状態/枠が黄色になっているもの)が対象になります。
画像が読み込まれているImageTextrueノードが一つしか無い場合は、フォーカスされていなくてもそのImageTextrueノードに読み込まれている画像がBake対象になります。
逆に新規画像は存在してるのにImageTextrueノードに読み込まれていない場合はエラーになります。
Bake前には必ずどのImageTextrueノードにフォーカスがあっているか確認してください。
オブジェクトに複数マテリアルが存在している場合
どうもそのオブジェクトに対して最初に作成されたマテリアルがBake対象になるようです。
複数のマテリアルが存在している状態でテストしてみましたが、マテリアルを切り替えてBakeすることはうまくいきませんでした。
なにか方法がありそうですが、今のところは不明です。
もちろんハイポリモデルはUV展開をする必要はありません。というかスカルプトしたモデルなんてUV展開したらパソコンが死んでしまうかも…。
ハイポリモデルとローポリモデルをできうる限り同じ位置にセット
ハイポリモデルの凹凸は同じような位置にあるローポリモデルにUVを介して転写されるようなイメージでBakeされます。
ですのでハイポリモデルとローポリモデルはできるだけ同じ位置にいなければなりません。
同じ位置というのはOriginの位置だけを指すのではなく、形状もなるべく同じようになっていなくてはいけないということです。
あまりにもローポリにしてハイポリと形状がかけ離れすぎてしまった場合、うまく凹凸の位置が対応せずBakeの結果が空白(水色)になってしまうこともあります。
ですのでNormalMapで疑似的に再現できる高低には限度があることになります。
後述するRayDistanceである程度の調整はできますが、もし凹凸がうまくBakeできないならローポリモデルがちゃんとハイポリモデルに対応した形状になっているかを確認したほうが良いかと思います。
ハイポリの凹凸をできるだけ転写することのできる、なるべくポリゴンの少ないローポリモデルが理想です。そうはいってもなかなか難しいですけどね…。
Bakeする
さて準備が整ったらBakeをします。
Bakeの設定はプロパティパネルのBakeで行います。
BakeType(ベイクタイプ)
BakeTypeをNormalにします。
これで先ほど作った新規画像(nomalと名前を付けた)にNormalMapがBakeされることになります。
Space(スペース)
Spaceは法線に関しての設定です。デフォルトでTangentになっているかと思いますがそのままでOKです。
Swizzle(変換)
SwizzleはNormalMapの色要素をどの方向に対応させるかの設定です。
NormalMapではRGBの量で法線方向が表現されますので、このSwizzleを変えることでRGBが受け持つ方向をコントロールすることができます。
通常ではここも変更する必要はありません。
Margin(余白)
MarginはNormalMapのBakeされる範囲の設定です。0pxにするとUVの境界ぎりぎりまでしかBakeされません。これではローポリの場合継ぎ目が目立ったりしてしまうのであまりよろしくありません。
ですので特に理由がない場合はMarginは設定しておいた方がよいかと思います。デフォルトは16pxです。そのままでOKでしょう。
Selected to Active(選択→アクティブ)
Selected to Activeは今回のようにハイポリモデルとローポリモデルが別々なオブジェクトの場合にチェックします。
読んで字のごとくですが、「選択したオブジェクトからアクティブなオブジェクトへ」という意味です。
Blenderでは複数のオブジェクトを選択するとき、SelectedとActiveという状態が生まれます。
Selectedは選択されているものすべてを表し、Activeは選択されているものの中で一番最後に選択されたものを表します
このSelectedとActiveはObjectモードだけでなくEditモードでも必要になってくる概念なので覚えておきましょう。
今回のBakeの場合ではハイポリモデルを選択して、それからShiftを押しながらローポリモデルを選択するとハイポリモデルがSelectedとなりローポリモデルがActiveとなります。
ですのでローポリモデルを選択してからハイポリモデルを選択してActiveにしてBakeしようとすると、Bakeする対象がローポリからハイポリになってしまう上に、ハイポリにはUV展開データが存在しないのでエラーになります。
Bakeの場合の選択は
ハイポリー→ローポリ
の順番であると覚えておくといいでしょう。
RayDistance(レイの距離)
RayDistanceは凹凸の再現性の調整です。高低をどこまで再現するかということです。
ハイポリモデルの凹凸の差が激しい場合、どんなにうまくローポリモデルを作っても、凹凸に追従できない場合もあるかもしれません。
その場合、ある程度RayDistanceの値を増やすことで凹凸の再現範囲が広がりBakeがうまくいく場合があります。
できるだけローポリモデルでハイポリモデルを追従するのが好ましいですが、最後の微調整はRayDistanceで行うと効率的かもしれません。
Cage(ケージ)
RayDistanceと排他的なのがCageです。
RayDistanceが値によって画一的に応答の再現度を調整するのにたいしてCageはオブジェクトを使って凹凸を再現する範囲を調整します。
Cageは檻とか籠とかという意味だと思いますが、まさにそのイメージかと思います。
ハイポリをCageに指定したオブジェクトで包むようにしてあげれば、そのオブジェクトの内側であれば凹凸を再現してくれるようになります。
ただCageになれるオブジェクトは制限があって、ローポリモデルと同じ枚数のFace(面)で構成されている必要があります。
ですのでCageはローポリモデルをコピーしてハイポリとローポリの形状が乖離している場所を見つけてその部分を包括するように頂点を編集する、というのがいいのではないかと思います。
うまく使えればローポリでポリゴンを節約したまま大きな凹凸も表現できるかもしれません。
Cage→Extrusion
CageのExtrusionはCage範囲の拡張です。 RayDistanceと意味は似ていると思います。Cageの範囲を微調整するプロパティです。
Clear(クリア)
ClearはBakeする毎に画像を初期化する設定です。いったんまっさらにしてからBakeするということですね。普通はチェックをつけたままでいいと思います。
シェーディングをSmoothに
最後に重要な設定があります。
ハイポリモデル、ローポリモデル双方のシェーディングをSmoothにしてください。
そうしないとポリゴンのカクカクが凹凸としてBakeされてしまいます。
人体や動物などはポリゴンのカクカクは好ましくないかと思うので、忘れずにSmoothにしてください。
もちろんロボットなどの直線的なモデルであえてポリゴンのカクカクが出るようにしたい場合はFlatシェーディングのままでOKです。
最終確認
さて確認です。
- Bake先の画像を新規作成している?
- UV/image Editer画面でBake先の画像を表示している?(Bake結果をすぐ確認するため)
- ローポリモデルのUV展開済み?
- ローポリにマテリアルが存在している?
- そのマテリアルにTextrueImageノードにてBake先の画像が読み込まれており、かつそのノードが選択(またはアクティブ)状態になっている?
- ハイポリモデル、ローポリモデルの位置合わせOK?
- 必要であればCageモデル作る
- BakeTypeはNormalになっている?
- Selected to Activeにチェックはついている?
- Cageモデルを使う場合はCageにチェックしている?
- ハイポリモデルを選択して、そのあとshiftを押しながらローポリモデルを選択した?
- Selected to Activeの状態になっている?
- ローポリ、ハイポリのシェーディングをSmoothにした?(ポリゴンのカクカクが好ましくない場合)
Bakeを実行する
確認がOKでしたらBakeボタン(ベイク)を押しましょう。
ポリゴンの量によってBake結果に掛かる時間が変わるはずです。ハイポリモデルが詳細であればあるほど時間が掛かります。もちろんパソコンの性能によっても時間は左右されます。
一応プログレスバーがinfoに表示されますが、時間が掛かる場合は止まったまんまになったりあんまりあてになりません。気長に待ちましょう。(バージョン2.78以降はプログレスバーの挙動が修正されているそうです)
Bakeが終わると、UV/imageEditerに結果が表示されるかと思います。
変わった色の変な画像が出来上がっていることでしょう。この画像で凹凸を再現できるのかと思うと不思議なものです。
画像を見渡して、再現できていない場所などがないか(凹凸が存在する場所なのに水色一色になってしまっている場所)を確認します。
もし再現できていない箇所があるようでしたらRayDistanceの調整、Cageの使用、またはローポリモデルの編集も必要になるかもしれません。
なんどかやり直す羽目になってしまうかもしれませんが、良いモデルのためですので頑張りましょう。
失敗した例
無調整でのBake
実際に失敗した例を挙げておきます。先ほどのBakeではRayDistanceを0.00のままで行いました。そのBake結果が以下です。
確認すると、顔のほとんどの範囲がシアン一色になっているのがわかります。これは凸凹を拾うことができず結果的になんら凸凹をBakeできなかった部分となります。これではほとんどNormalMapとしては意味がありません。ちゃんと凸凹を拾うように調整する必要があります。
RayDistanceを調整したBake
今度はRayDistanceを0.1に設定してBakeしてみました。
先ほどと違い、ちゃんと顔の全面で凸凹の情報がBakeされていることがわかります。口の部分に一部平らになってしまっている部分がありますが、これは口の中に相当しますので特に問題ないでしょう。
オブジェクトの位置がずれたBake
オブジェクトの位置がずれるとどのようなことになるのか試してみた結果です。
ローポリモデルをX軸にずらして配置してみました。
その場合のBakeの結果がこちら。
ピカソですかね?盛大に失敗しているのがわかりますよね。
このように位置が狂っているとちゃんとしたBakeができませんので位置合わせは厳密に行ってください。
Smoothシェーディングを忘れた場合
SmoothシェーディングにしないとポリゴンのカクカクがBakeされると説明しましたが、以下のようになってしまいます。
ハイポリ、ローポリどちらともFlatシェーディングにしてBakeした結果です。
ポリゴンのカクカク(境目)がBakeされてしまっているのがお分かりになりますでしょうか?
これを失敗とするかどうかはコンセプトによるかと思いますが、多くの場合では好ましくはないと思います。
Bake結果を保存する
納得のいくNormalMapになったら、画像を保存しておきましょう。
BakeしたNormalMapを適用する
NormalMap画像をNormalMapとして適用するにはNormalMapノードが必要です。
TextrueImageノードに先ほどベイクしたNormalMap画像を読み込んで、Color出力コネクタをNormalMapノードのColor入力コネクタに繋ぎます。
NormalMapノードのNormal出力コネクタをDiffuseBSDFやGlossyBSDFなどのNormal入力コネクタに繋ぐとNormalMapがオブジェクトに適用されます。
NormalMapノードにはBakeで用いたUVMapを指定してください。またStrength(強さ)で凸凹の強さを調整できます。
レンダリングするなどして凹凸の再現性を確認してみてください。
実際に凹凸が付くわけではないので角度によってはのっぺりしてしまう場合もありますが、結構ちゃんと凹凸があるように見えるかと思います。
まとめ
やや長い記事になってしまいましたが、NormalMapのBakeの工程をお伝えすることができましたでしょうか?
実際に手順を覚えてしまえばたいして難しい作業ではありませんのでどしどし試してみてくださいね。