2019年4月3日

UV Overlap の対処法


Unity で UV Overlap 関連の警告が出たときの原因と対策をメモメモ…



※このページの内容の動作確認にはUnity2018.2を使用しています。
Unity 2018 以降でライトマップをベイクしたときに次のようなメッセージが表示される場合の対処法です。
There are *** objects in the Scene with overlapping UV's. Please see the details list below or use the 'UV Overlap' visualisation mode in the Scene View or Object Maps for more information.

- ObjectA: *** texels
- ObjectB: *** texels
- ObjectC: *** texels
...

実はこのエラーについては公式のマニュアル(UV overlap)がきちんと用意されています。かなり丁寧に説明されているので基本的にそっちを見てもらえればいいのですが、現時点ではまだ翻訳されてないっぽいので一応簡単に対応策をメモしておきます。

UV Overlap とは

そもそも "UV Overlap" とは一体何かというと「ライトマップに展開したポリゴンのUVどうしが近すぎて対応するピクセルが重なっちゃってるよ!」という状態のことです。通常、ライトマップを焼くときにはオブジェクトをバラバラにUV展開して「この部分に当たる間接光はこんな色、こっちはこんな色…」と画像データに書き込んでいきます。

簡略化したUV展開のイメージ図 近すぎるとピクセルがダブる

しかし、ライトマップの解像度が低かったり、複雑なメッシュを狭い範囲に無理やり押し込んで展開したりした場合は、オブジェクトの複数の面(ポリゴン)がテクスチャの同じ点(ピクセル)を共有してしまう場合があるのです。隣接する面なら問題ないのですが、本来離れた位置にあるUVのかたまり(いわゆる"島")が同じ点を共有しているとおかしくなります。上の図の赤いマスがそうです(実際はバイリニアの処理などが入って補間されるため、純粋に重なった部分だけではなくその周囲の点も重なっているとみなされます)。そうなるとライティングが正確でなくなり、明るい部分なのに影が見えるとか、暗い面なのに明るい面の情報が適用されちゃってるとかいう事態に陥るというわけです。

重なっている部分を確認する方法


たとえばここにバナナが落ちていますね。ライトマップを焼いたところ案の定エラーが出たので、UVが重なっているかどうかを確認してみましょう。

方法その1. シーンビューの描画モードを "UV Overlap" にする


シーンビューの左上にあるドロップダウンメニューで、描画モードを通常の "Shaded" から "UV Overlap" に変更しましょう。他の部分と被っている箇所が赤く表示されるはずです。うまくいかない場合はベイクしなおしてみてください。


方法その2. Lighting ウィンドウからライトマップを直接確認する


まず調べたいオブジェクトを選択状態にします。それから Lighting ウィンドウにある Object Maps の項目を開きましょう。あとはドロップダウンメニューから "Baked UV Overlap" を選択すれば、該当するライトマップが表示されます。赤くなっている部分が重なっているとみなされる箇所です。

対策

基本的な対策は「展開されるUVの余白を大きくする」か「ライトマップの解像度を上げる」かのどちらかです。ライトマップのファイルサイズやベイク結果を見ながら、複数の対策方法を組み合わせて調整してみてください。

あ、それから、紹介するのは Unity 2018.2 時点で有効な方法です。今後のバージョンアップで仕様が変わったりもっと簡単な方法が導入されたりするかもしれないので、参考程度にご覧ください。

対策1. Lightmap Resolution や Lightmap Size の値を大きくする


最も手軽に設定できる方法です。Lighting > Lightmapping Settings から "Lightmap Resolution" や "Lightmap Size" の項目を変更します。すると単純にマップの解像度が上がるので、重なっているピクセルの数は減るというわけです。ただしライトマップのファイルサイズもどんどん大きくなるので注意。

対策2. インポート設定の Pack Margin の値を大きくする


モデルをインポートするときに "Generate Lightmap UVs" にチェックを入れた状態で、その下の Advanced > Pack Margin の値を変更してみましょう。この値を大きくすればするほど、UV展開したときの「島」の余白が大きくなるため重なりにくくなります。ただし、余白を大きくしたぶん他の部分のサイズにしわ寄せが来るかもしれません。


ちなみに Lighting ウィンドウの Lightmapping Settings にある Lightmap Padding という項目は、UV展開したときの「オブジェクト」どうしの間隔をどれだけ広くするかという値です。あまり別のオブジェクトと展開図が重なることはないと思いますが状況に応じてこちらも変更してみてください。

対策3. Mesh Renderer の Scale In Lightmap の値を大きくする


対象となるゲームオブジェクトの Mesh Renderer にある Lightmap Settings > Scale In Lightmap の値を変更する方法です。たとえば遠景の大きい建物とかをライトマップにそのまま等倍で焼いてしまうと無駄なので(どうせ細かい部分は見えないし)、Scale In Lightmap を0.1とか0.2に設定してライトマップ中のサイズを縮小させるわけですが、この値が小さいとUVも小さくなり重なりやすくなります。逆に大きくすれば余白が広がって重なりにくくなります。


たとえばバナナの Scale In Lightmap を 1 から 4 に変更するとこんな感じになります。ライトマップ中で割り当てられるサイズ自体が大きくなるので、結果的に余白も増えて UV Overlap 問題は無事解決しました!

…ただし上の例ではファイルサイズは4倍に増えています。バナナの陰影を正しく描画するためにファイルサイズが4倍に…。「たしかに解決はしたけど、それって本当に必要なの?」と常に自分に問いかけながら調整するようにしましょう。

対策4. ライトマップ用UVを自分で作成する


インポート設定で "Generate Lightmap UVs" にチェックを入れておくとUnityが自動でUV展開してくれますが、このUVを自分でカスタムすることも可能です。"Generate Lightmap UVs" をオフにすると、まず通常のテクスチャ用UVが使用され、もしUV2(チャンネル2)が存在すればそちらが使われるようになります。あらかじめ余白を大きめにとって展開しておくとか、シームを入れる位置を変えて不自然さを誤魔化すとか、いろいろ改善できるかもしれませんね。めんどくさいので自分はやりません(ひどい)。

対策5. 気にしない


最も効率的で有用な解決策、それは「気にしない」ことです。

そもそも UV Overlap がなぜダメかというと、ベイクした情報が正確でなくなり、望ましくないライティング結果になってしまうからです(こういう視覚的に不自然な見た目を Artifacts 「アーティファクト」と呼ぶそうです)。逆に言うと、実際にプレイしたときに不自然に感じなければ何の問題もないとも言えます。

この警告を回避するためだけにどうでもいいオブジェクトの割り当てサイズを大きくしたり、ライトマップのファイルサイズを数MB単位で増やしたり、無駄な時間を費やしたりするのはバカバカしいです。いちいち警告メッセージが表示されるのはあまり良い気持ちはしませんが、ほどよく無視しましょう。


0 件のコメント:

コメントを投稿