UnityのHDRP向けのLOD対応背景アセットのテクスチャを作る
はじめに
背景アセット用のHDRP向けのSubstanceを利用したテクスチャの制作手順をメモします。 LODに対応したアセットとして作成していきます。 我流で適当にやっているものなのでこれで正しいのかはわかっていないのですが、参考程度にはなるかと……。
- Unity: 2019.3.0f3
- HDRP: 7.1.6
- Substance Painter: 2019.3.0
- Substance Designer: 2019.2.3
2020/01/17追記
この記事の手順を簡略化するためのツールを作りました。
Substance Automation Toolkitを利用してHDRP向けLOD0テクスチャをLOD1、LOD2に転写するツールを作成した | 測度ゼロの抹茶チョコ
DetailMap無しバージョン
最初にシンプルな場合で作り方の手順を見ていきます。
LOD対応の3Dモデルを準備する
好きなモデリングソフトウェアでハイポリと各LODのモデルを作成してください。
ハイポリモデル
ハイポリモデルとして次のようなモデルを用意しました。
ポリゴン数は55,884triです。
後でテクスチャ作成時にマテリアルを割り当てるために、マテリアルごとに頂点カラーを割り当ててあります。
Nゴンが含まれていると、Substanceでベイクする際にうまく三角形化してくれない場合があるので、あらかじめモデリングツールで三角形化しておきます。
ハイポリモデルでは、とりあえず縁をベベルしておくとベイクしたときよい感じになります。
ハイポリモデルはUVを展開しておく必要はありません。
LOD0モデル
LOD0のモデルとして次のようなモデルを用意しました。
ポリゴン数は4428triです。モデルの割にはちょっと多いですかね。
ベイクする前に三角形面化しておくのがポイントです。
テクスチャ作成のためにUV展開をしました。 UVは次のとおりです。
LOD1モデル
LOD1モデルとして次のようなモデルを用意しました。
ポリゴン数は588triです。
こちらも三角形面化しておきます。
UVは次のとおりです。
LOD2モデル
LOD2モデルとして次のようなモデルを用意しました。
ポリゴン数は12triです。
こちらも三角形面化しておきます。
UVは次のとおりです。
Substance PainterでLOD0のテクスチャを作成する
Substance Painterを開き、「PBR - Metallic Roughness (allegorithmic)」でLOD0のモデルを読み込みます。
「TEXTURE SET SETTINGS」から「Bake Mesh Maps」を選択します。
「High Definition Meshes」から、ハイポリのメッシュを選択します。
とりあえずパラメータはそのままで「Bake Material Mesh Maps」をクリックしてベイクを開始します。
ベイクした結果をみるとうまくベイクできていないようです。
面の後ろ方向に飛ばすレイがハイポリに到達していないようなので、「Max Rear Distance」を上げてもう一度ベイクします。
今度はうまくベイクできました。
テクスチャを作成していきます。
まずはコンクリートのマテリアルをレイヤーにドラッグ&ドロップします。
マスクを追加します。「Add mask with color selection」を実行します。
「Pick color」でメインの部分を選択します。
コンクリートのマテリアルがheightだけでnormalを出力していないようです。
最終的にはheightもnormalに焼いてくれるのかもしれませんが、今回は表面のnormalも必要なのでnormalを出力するように変更します。
つぎにボルトの部分の金属のマテリアルを割り当てます。 金属のマテリアルをレイヤーにドラッグ&ドロップします。
マスクを追加します。「Add mask with color selection」を実行します。
「Pick color」でボルトの部分を選択します。
こちらもNormalを出力しておきます。
適当にペイントも加えていきます。 fillレイヤーを追加します。
ペイントがわかりやすいようにピンクにしました。
「Add black mask」を実行します。
maskを選択した状態で右クリックから「Add paint」を実行します。
「Particles」から「Leak Heavy」を選択して適当にペイントしていきます。
ひとまずこれでペイントは完了とします。
次にテクスチャを出力していきます。
「File」から「Export Textures...」をクリックします。
開いたウィンドウの「CONFIGURATION」タブを開きます。
「Unity HD Render Pipeline」の項目を見つけて右クリックから複製します。
複製したらわかり易い名前をつけた後に、RGBのマップを一枚追加します。
追加したマップの名前を「$mesh$textureSetMicroNormal」とし、「Input maps」のNormalをドラッグ&ドロップし、RGBチャンネルに割り当てます。 「Mesh maps」のNormalやConverted mapsのNormalではないので注意してください。
次にGrayのマップを2枚追加します。
それぞれ「$mesh$textureSetMetallic」と「$mesh$textureSetSmoothness」と名付けます。
「$mesh$textureSetMetallic」に「Metallic」をドラッグ&ドロップしてGrayチャンネルに割り当てます。
「$mesh$textureSetSmoothness」に「Glossiness」をドラッグ&ドロップしてGrayチャンネルに割り当てます。
これで新しく作成したpresetは次のようになります。
プリセットは保存されているので次回以降はpreset作成は行う必要はありません。
「EXPORT」タブから「Config」で作成したpresetを選択し、エクスポート先のディレクトリを指定して 「Export」します。
今回はEmissiveやAnisotropyなどは使わないため、マップの数が足りないと警告が出ています。 必要に応じて「TEXTURE SET SETTINGS」からテクスチャを追加しておけば出力されます。
これでHDRPに必要なBaseColor、MaskMap、NormalMapは出力されました。 LOD1、LOD2を作成するのに必要なMetallic、Smoohness、MicroNormalも出力されました。
MicroNormalはメッシュのノーマルを含まない表面のディティールのノーマルマップです。
こちらが通常のノーマルマップ。
こちらがMicroNormalとして出力されたノーマルマップです。
Substance Designerで各LODのテクスチャを作成する
作成したLOD0のテクスチャをもとにSubstance DesignerでLOD1とLOD2のテクスチャを作成します。 また、LOD0のBent NormalがSubstance Painterでは作成されないので、そちらのベイクも行います。
Substance Designerを立ち上げます。
「Empty」なグラフを作成します。
EXPLORERからsbsを右クリックして「Link」から「3D Mesh」を選択します。
ハイポリとLOD0、LOD1、LOD2の3Dモデルを読み込みます。
LOD0のBent Normalをベイクする
最初にLOD0のBent Normalをベイクしていきます。
EXPLORERからLOD0を右クリックして「Bake model Information」をクリックします。
「Add high definition model」の「From Resources」からハイポリモデルを選択します。
「Add baker」から「Bent Normal Map from Mesh」を選択します。
Real valueとFrontal valueを適当に変更しておきます。
UnityのNormalはDirectXではなくOpenGLだそうなので、Baker Parametersの「Normal Orientation」を「OpenGL」に変更しておきます。
「Start Rrender」を実行します。
Bent Normalマップが無事ベイクされました。
LOD1のテクスチャを作成する
次にLOD1のテクスチャを作成していきます。 作成するのはBaseColor、MaskMap、NormalMap、BentNormalMapです。 ハイポリからメッシュのノーマルマップとBent Normal、アンビエントオクルージョンマップをベイクします。 LOD0からBase ColorとMetallicとSmoothness、Micro Normalをベイクします。
最初にハイポリからベイクしていきます。
EXPRORERからLOD1を右クリックして「Bake model Information」をクリックします。
「Add high definition model」の「From Resources」からハイポリモデルを選択します。
レイのFrontal valueとRear valueを適当に変更します。
「Add baker」から「Ambient Occlusion Map from Mesh」、「Bent Normals Map from Mesh」、「Normal Map from Mesh」を追加します。
Bent NormalとNormalの「Normal Orientation」をOpenGLに変更します。
「Start Rrender」を実行します。
ハイポリのマップがひととおりベイクできました。
次にLOD0のモデルから転写をします。
まずは今使ったハイポリのモデルを除去します。
「Add high definition model」の「From Resources」からLOD0モデルを選択します。
Delete bakerでさきほど追加したbakerを全部削除します。
Add bakerで「Transferred Texture from Mesh」を4つ追加します。
追加したBakerの名前を「BaseColor」、「Metallic」、「Smoothness」、「MicroNormal」とします。
「From File...」から、それぞれLOD0のBaseColor、Metallic、Smoothness、MicroNormalのテクスチャを設定します。 MicroNormalについてはNormal Mapのチェックボックスをチェックします。
「Start Rrender」を実行します。
LOD0の情報がベイクされました。
ベイクされたテクスチャを組み合わせてHDRP用のテクスチャに仕上げます。
EXPRORERでsbsにLOD1という空のグラフを作成します。
HDRPのMaskMapを作成していきます。
ベイクされた「metallic」、「Smoothness」、「ao」をグラフにドラッグ&ドロップします。
MetallicとSmoothnessをGrayscaleとして読み込みます。
「RGBA Merge」でマージします。 MaskMapはrがメタリック、gがao、bがディティールマスク(今回は使わない)、aがスムースネスです。
Outputノードを接続し、MaskMapという名前にします。 UsageでLinearを指定しました。
次にノーマルマップを作成していきます。
ベイクされたNormal from meshとmicronormalをグラフにドラッグ&ドロップします。
Normal Combineノードでノーマルを合成します。
Outputノードを接続しNormalという名前にします。 UsageをnormalのNormaXYZRightにしました。
EXPRORERのLOD1のグラフを右クリックしてExport outputs as bitmapsでテクスチャとしてグラフの結果を出力します。
LOD2のテクスチャを作成する
LOD2のテクスチャはLOD1のテクスチャの作り方と同じです。 ハイポリからメッシュのノーマルマップとBent Normal、アンビエントオクルージョンマップをベイクします。 LOD0からBase ColorとMetallicとSmoothness、Micro Normalをベイクします。
ボルトのようなものを平面にベイクするにはAverage normalsを外すとよいかもしれません。
Gamasutra: Peter Kojesta's Blog - Skewmesh Tutorial: Remove Skewing in Normal map bakes
Average normalsの場合。
Average normalsをオフにした場合。
新しいグラフを作成し、RGBA mergeでMaskMapを作成、Normal Combineでノーマルを作成します。
HDRPに持ち込む
HDRPのUnityプロジェクトを新しく立ち上げます。
LOD0、LOD1、LOD2のモデルをUnityに読み込みます。
マテリアルをセットするためのPrefab Variantを作成します。
テクスチャをUnityに読み込みます。
NormalとBent NormalについてはTexture TypeをNormal mapに変更しApplyします。
MaskMapのsRGBのチェックを外します。
LOD1、LOD2のテクスチャを必要に応じてMax Sizeを小さめにします。
「Create > Material」でMaterialを作成します。
マテリアルのテクスチャに対応するテクスチャをドラッグ&ドロップしていきます。 Metallicを1に指定します。
さきほど作成したPrefab Variantにマテリアルを設定します。
適当なシーンを作りました。
空のGameObjectを作成しLODのルートとします。
LODのルートの下にさきほど作成したPrefab Variantを配置します。
LODのルートオブジェクトに「Lod Group」コンポーネントをアタッチします。
ドラッグ&ドロップでLOD Groupを設定します。
好みでクロスフェードにしました。
あとはルートのオブジェクトをProjectビューにドラッグ&ドロップしてprefab化して完成です。
DetailMap無し・opacityベイク有りバージョン
次にLOD2のOpacityベイクを入れたバージョンをやっていきます。
3Dモデルの準備
次のようなモデルを用意しました。
ハイポリ:
LOD0:
LOD1:
LOD2:
LOD2ではポリゴンで表現することを諦めてalpha clipしようと考えています。
Alpha Clipに使用するアルファをどうするかですが、 Substance DesignerではOpacityをベイクする事ができるのでそれを使います。
Substance PainterでLOD0のテクスチャ作成
テクスチャを適当に作成しました。
先ほど作成したプリセットを利用してExportします。
Substance Designerで各LODのテクスチャの作成
LOD0、LOD1のテクスチャの作成は先程と全く同じです。
LOD2のハイポリのベイクの際に、「Opacity Mask from Mesh」を追加しopacityマップを作成します。
BaseColorのalphaをこのopacityマップに置き換えます。 BaseColorとOpacityをグラフにドラッグ&ドロップします。
Alpha mergeノードを使ってalphaを置き換えます。
UnityでLOD2のマテリアル作成時にAlpha Clippingを有効にします。 Double-Sidedも有効にします。
LOD2のモデルを表示したところです。
LODを適用するとこんな感じになりました。
DetailMap有りバージョン
HDRPのLitシェーダにはDetail Mapという機能があります。 その機能を利用する例も示しておきます。
モデルの準備
次のようなモデルを用意しました。
ハイポリ
LOD0
UV
UV1
LOD1
UV
UV1
LOD2
UV
UV1
広い天面のあるモデルです。 この天面部分にDetailMapを適用していきます。
各LODのモデルにはUVとUV1が展開されています。
UVでは天面はだいぶ小さめに展開されています。 UV1では天面を全面に展開しています。
Substance Painterでテクスチャを作成する
「TEXTURE SET SETTINGS」の「Channels」から「Blending mask」を追加します。
「Blending mask」が天面の部分だけ白くなるようにマスクを作成します。
天面のディティールはあとから追加するのでnormalマップとRoughnessマップはとりあえず単色を出力するようにしておきます。 天面を濡れた路面にしたいのでラフネスは低く設定しています。
コンフィグからGrayマップを追加してDetail Maskの「Blending mask」をMaskMapとして出力するようにします。
エクスポートすると、BaseColor、MaskMap、Normal、Metallic、Smoothness、DetailMaskが出力されます。
Substance Designerで各LODのテクスチャを作成する
LOD0は最初の手順と同じです。
LOD1とLOD2では、LOD0から転写する際に「Transferred Texture from Mesh」をさらにもう一つ追加してDetail Maskを転写します。
RGBA mergeでMaskMapを作成する際にDetail Maskをbに入れてやります。
Substance DesignerでDetail Mapを作成する
アスファルトのsbsarファイルをベースにDetail mapを作成していきます。
DetailMapはrがアルベドのグレイスケール、gとaがnormalのyとx、bがsmoothnessとなっています。
Mask and detail maps | High Definition RP | 7.1.6
sbsarからアルベドとノーマル、Glossinessを引っ張ってきてテクスチャを作成します。
アルベドがそのままグレイスケール化すると最終結果が暗くなりすぎたのでレベルノードを挟んで若干明るくしています。 これでよいのかは不明です……。
できたマップを出力します。
UnityのHDRPでマテリアルにテクスチャを割り当てる
Detail mapをインポートしたらsRGBのチェックを外します。
マテリアルのDetail mapのテクスチャスロットにDetailMapテクスチャを割り当てます。 するとタイリングの設定などが出てきます。
今回のモデルは大きめなのでタイリングをさせて細かいディティールをよい感じにします。 Detail Mapのアルベド、ノーマル、スムースネスの強さも適当に設定します。
次のようになりました。
天面に近づいても十分なディティールを保てていることがわかります。
天面のUVには左下の水色の部分しか割いていないのですが、UV1でDetail Mapを与えることで十分なディティールが保ててよいですね。
Detail mapは全LODで共通のものを使っています。 他のマテリアルでもDetail Mapだけ使いまわしていけますね。 その他のテクスチャの解像度を下げてもDetail Mapだけ解像度高くしておけばごまかせたりもします。
おわりに
HDRP向けLOD対応のテクスチャの作成手順メモでした。
正直、割と手間なのでLODモデルは自動生成したほうがよいのではという気分になってきました……。 Simplygonとか有名ですよね、使ったことないのでどんな感じなのかはわからないですが。 あの手の自動LOD生成ってどのくらいのクオリティなんでしょうね。気になります。
なにかこの記事で不明な点、気になる点があれば私のTwitterアカウントにどうぞ。