Generating Lightmap UVsのパラメータ、仕事してる?

はじめに

この記事は、かねてよりGenerating Lightmap UVsの各種パラメータがきちんと動いていないんじゃないかという疑念を抱いていたので、それを検証する内容です。検証環境はUnity2019.4.31f1とUnity2022.3.15f1(ようは2019と2022のLTS)で行っています。

VRChat向けに書いた以下の記事の内容を補填するために書いていますので、VRChat向けの話になっています。

また、この記事を書いているうちにVRChatがUnity2019からUnity2022に上がることが確定したのですが、Unity2020の時にGenerating Lightmap UVsに新しい項目が追加されています。

それについても記事の最後の方で少し調査しています。多分知っておかないと、デフォルトの設定になっているので、2022でライティングする初心者が辛い目に合いそうなパラメータです。

基本の4つのパラメータについて

基本のパラメータは以下の4つ
Hard Angle
・Pack Margin
・Angle Error
・Area Error
Unityリファレンスから説明を抜粋します。

Hard Angle

隣接する三角形間の角度 (単位は度)。Unityはそれを鋭い切れ目と見なし、継ぎ目を作成します。これを 0 と 180 の間の値に設定できます。これはデフォルトで 88 度に設定されています。

これを 180 度に設定すると、Unity はすべてのエッジが滑らかであると見なし、これは有機的なモデルでは現実的です。デフォルト値 (88度) は機械的なモデルには現実的です。

恐らくUVの切れ目(シーム)を入れる角度を決定するパラメータで、デフォルト88度は機械のような角ばったモデルは綺麗に展開できるよ……ということなのでしょうが、多少数値を変えても全然UVが変わらないので、イマイチ効き目が分からないパラメータです。

他のパラメータ(特にAngle ErrorとArea Error)との関係性が気になるので、極力シンプルなモデルで検証します。

・Pack Margin

メッシュが 1024x1024 のライトマップ全体を占めると仮定したときの、隣接するチャート間のマージン (単位はピクセル)。これを 1 から 64 の間の値に設定できます。値を大きくするとマージンが増えますが、チャートに必要なスペースも増加します。デフォルトでは 4 ピクセルに設定されています。

詳細については、後述の Pack Margin を参照してください

まぁ説明不要ですね。領域間に必要な隙間のピクセル数です。これは動いてる気配あるので、今回の検証からは省いています。
 
Angle Error

ソースジオメトリの角度から UV 角度の可能な最大偏差 (0–100%)。これはデフォルトで 8% に設定されています。

これにより、UV 空間の三角形と元のジオメトリの三角形との違いを制御します。通常、ライトマップを適用するときにアーティファクトを避けるため、これはかなり低くする必要があります

UV の角度と元のジオメトリの角度の差が小さくないと、角度の歪みが出る……ということらしいですが、ようは世界地図とかの歪みと同じやつだろうなと思っています。
 
UVに対応してるのは頂点なので、UV上では綺麗な三角形に見えても、3Dモデル上では引き延ばされていたりします。その場合、ポリゴンごとの解像度が全く均一じゃなくなるので、暗くなったり明るくなったりするのを抑制する機能なのかなーというのが、私の見立てです。
 
可能な最大偏差……ということなので、多分100%にすればこのパラメータの影響はなくなるんじゃないかなと思った……のですが75%までしかありませんでした。検証時は1%か75%でいこうと思います。
 
・Area Error

ソースジオメトリの領域から UV 領域の可能な最大偏差 (0–100%)。これは、デフォルトでは 15% に設定されています。
 
これにより、相対的な三角形領域を維持する度合いを制御します。値を大きくするとチャートを少なくすることができますが、三角形の解像度が変わる可能性があります。そのため、発生する歪みがライトマップの品質を損なわないことを確認してください。

三角形の領域が小さかったり大きかったりすると、解像度が全く均一じゃなくなって、ポリゴン間で明るさの差異が発生するのを抑制するパラメータっぽいです。

このパラメータも要はAngle Errorと似たような感じっぽいので、検証時は1%か75%でいこうと思います。

使用するモデルについて

モデルは
・立方体
・球
の二つで行きます。


立方体、UV1は以下のような形です。

球、UV1は以下のような形です。

これを使ってGenerate Lightmap UVsをします。

検証結果について

色々画像沢山撮ったんですが、貼り付けるのが大変な量になってしまったので、結論とそれを裏付ける形で画像を貼っていきたいと思います。

最初にも述べた通り上記4つのパラメータの検証は2019と2022両方で行っていますが、動作としては変わった部分は見られませんでした。

それで、検証の結論としては
①     Hard Angleは動いている!ただし、大体機能してるのが0~10くらいまで……。
②     Hard Angleを0にすると1ポリゴン単位でバラバラに敷き詰められる。
③     Hard Angleのおすすめは1か2のどちらか
④     Angle ErrorとArea Errorは1にしようが75にしようが、結果に影響している様子が見受けられなかった

ではまず①~③について、まとめて説明します。

Hard Angleは動いていたのですが、実際には球であろうと立方体であろうと、10以上(もっというと7とか8くらいから)は次のようなUVで変わる様子がありませんでした。

そしてHard Angleが0になると、問答無用でポリゴン単位でバラバラにします。

そこで1を試してみようかと思い、Hard Angleを1にしたところ次のようなUVが得られました。

特に球のほうですがいい感じですよね?
おそらくバラバラにする一歩手前なので2ポリゴンが合体して四角形になったのだと思うのですが、四角形は敷き詰めやすいのでこのようにきれいに並んでくれるようです。

ただ平面を誤検出しているのか、立方体の面が崩れてしまっているので、Hard Angleを2にしてみると以下の通りです。

立方体の面は綺麗になりましたが、球の円形に展開されている部分が大きくなっています。
これは数値が大きくなるほど顕著になり、無駄なスペースが出来てしまいます。例としてHard Angleが4の時の球を見てみましょう。

UnityのGenerate Lightmap UVsは左下にあるようなドーナツ状のUVの真ん中に詰めることが出来ないので、その点は注意が必要かもしれません。

以上から、ほとんど曲線しかないのであればHard Angleは1、角ばっている場所がある場合はHard Angleは2くらいがいいのではないかと思っています。

『④Angle ErrorとArea Errorは0にしようが75にしようが、結果に影響している様子が見受けられなかった』について

先ほどの2のパラメータの時のUVは以下の通りです。この時にArea・Angle Errorを1または75にしてみます。

まずは1です。

全く変わっていませんね、次に75です。

こちらも変わっていません。
私が試した中ではHard Angleをどのような値にしても、UVの形が変わることはありませんでした。したがってこの二つの値についてはほとんど気にする必要はなさそうです。

懸念事項
今回は検証するモチベが薄かったので、やりませんでしたがUV1の形状にかなり左右される傾向がありそうです。

例えばこの検証前に適当に試していたときの木のUVはこんな感じでした。

ですがこれを1~10のどの数値で展開しても以下のようなUVになります。

0にするとバラバラになるのですが、このケースだとむしろ0にしてしまって、ライトマップの解像度を大きめにとってしまったほうが良いかもしれません。

またArea ErrorとAngle Errorについても、今回の検証例では全然役に立ってないように見えますが、対象にしたモデルとUVが単純すぎるというのはあるかもしれません。
特に滅茶苦茶なUVの時に効果を発揮しそうな気がするので、一概に効果なしとはいえないのかなと思っています。
(とはいえ、上の木のモデルのUVでも試してみましたが、変わってる様子が見られなかったので、追加の検証は断念しました)

追加機能:Mergin Methodについて

Unity2020LTSで追加された機能のようで、2020LTSの新機能ページから説明を抜粋すると以下の通りです。

重複なしのパッキング
ライトマッピング用のモデルの設定がはるかに簡単になりました。インポート時にパックマージンに必要なサイズを見つけるプロセスを簡素化するために、Unity はモデルインポーターでマージンを 計算 する方法を提供するようになりました。ここでは、モデルが使用される最低ライトマップ解像度と最小スケールを指定できます。それに基づき、Unity のアンラッパーが必要なパックマージンを計算するため、ライトマップが重複することがありません。

相変わらずもうちょっと分かりやすく喋ってほしい感じの説明ですが、どうやら最低ライトマップ解像度と最小スケールを指定することで、良い感じにPack Merginを調整してくれるようです。

ちなみにUnity上でみるとこんな感じになっています。

CalculateとManualがあり、Manualだと従来とUV展開になるのが確認できました。デフォルトではCalculateになっていますので、新しい仕組みでPack Merginが調整されています。

では試しにデフォルトのまま、適応してみましょう。

うーん……なんか明らかに小さいですね……従来の方と比べてみましょう。

なんか個人的に、デフォルトでこれはあまりにもひどくない……?って気持ちになっています。

設定項目の二つの値を大きくすると、隙間が小さくなっていきますが、従来のものとほんの少し違った結果が出てきます。

Min Object Scaleを1→6に

比較すると、従来のより微妙にいい結果が得られている気がするんですが、わざわざ値を設定しなきゃいけない辺り面倒です。

"Calculate"って名前なので、ベイク実行する時に可変する可能性も考えて、試しに何回かベイクしてみたのですが、可変はしませんでした。
まぁ『モデルインポートのプロセス』ってことなので、ベイク結果に合わせて変えるような賢い機能ではないということですね。

とはいえGenerating Lightmap UVsを使う時点で、チェックマーク入れる手間は発生するので、ついでにササっと入れてしまえばいい気はします。

とはいえ、デフォルトの設定があまり良くないので、知らなければUV2解像度が低くなり、ベイク結果が悪化する可能性は十分にあると思います。
初見殺しは止めたまえ……Unity君……。

ここで、ふと既存のプロジェクトを2022に上げた場合どうなるんだろう!って気がつき、急いで検証したのですが、その場合はManualに設定されていたので従来通りです。一安心。

気を付けるべきは2022でGenerating Lightmap UVsを利用する時のみ、ということになります。

おわりに

ということで、上手く使えるケースもあるみたいなのですが、いっそHard Angleを0にして、ポリゴン単位で焼いたほうが良いケースも結構ありそうです。

運用するときはHard Angleを0~2あたりに設定して試してみるといいというのが分かっただけでも収穫でしたが、上手く焼けない時はライトマップの解像度をきちっと取ってあげる必要がありそうですね。

追加機能であるMergin Methodが初心者の罠になりそうなのが、結構辛そうだなと思いました。

以上です。読了お疲れ様です。

この記事が気に入ったらサポートをしてみませんか?