Houdiniで橋のモデリングを行いUnityのHDRPでセットアップして表示してみる(Part 4)
はじめに
この記事はシリーズのPart 4です。 目次はこちらです。
モデルの結合
最後に全てをまとめていきます。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge57ノードのパラメータを次のように設定します。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge58ノードのパラメータを次のように設定します。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge59ノードのパラメータを次のように設定します。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge60ノードのパラメータを次のように設定します。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge61ノードのパラメータを次のように設定します。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge62ノードのパラメータを次のように設定します。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge63ノードのパラメータを次のように設定します。
Mergeノードを作成し、次のように接続します。
すっかり忘れていたのですが、Normalノードを作成し、bottompart0lod2の前に差し込みます。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge64ノードのパラメータを次のように設定します。
Mergeノードを作成し、次のように接続します。
Switchノードを作成し、次のように接続します。
作成したswitch1ノードのパラメータを次のように設定します。
Object Mergeノードを作成し、次のように配置します。
作成したobject_merge65ノードのパラメータを次のように設定します。
Mergeノードを作成し、次のように接続します。
Switchノードを作成し、次のように接続します。
作成したswitch2ノードのパラメータを次のように設定します。
Groupノードを作成し、次のように接続します。
作成したgroup7ノードのパラメータを次のように設定します。
指定した角度より大きく曲がっているエッジをUVのシームとしています。
UV Flattenノードを作成し、次のように接続します。
作成したuvflatten1ノードのパラメータを次のように設定します。
UV Layoutノードを作成し、次のように接続します。
作成したuvlayout1ノードのパラメータを次のように設定します。
Switchノードを作成し、次のように接続します。
作成したswitch3ノードのパラメータを次のように設定します。
Divideノードを作成し、次のように接続します。
作成したdivide1ノードのパラメータを次のように接続します。
nullノードを作成し、lod2と名付け、次のように接続します。
Shift+Oでネットワークボックスに囲います。
lod2のネットワークをコピーしペーストします。
Object Mergeのlod2を読み込んでいる部分をlod1に変更します。
最後のnullノードの名前をlod1へ変更します。
lod1のネットワークをコピーしペーストします。
Object Mergeのlod1を読み込んでいる部分をlod0に変更します。
startpropとendpropにDeleteノードを入れ忘れていたので入れます。
それぞれパラメータを次のように設定します。
最後のnullノードの名前をlod0へ変更します。
なんか想定よりもポリゴン数が多いと思ったら、topのノードにミスを発見したので今から修正を行います。
次のようにMergeノードを一つ足してつなぎ直します。
lod0にbooleanをしたものが入らないようにします。
lod0のネットワークをコピーしペーストします。
ハイポリにUVは必要ないため、UV計算をしているノードを削除します。
Object Mergeのlod0を読み込んでいる部分をhiに変更します。
最後のnullノードの名前をhiへ変更します。
Switchノードを作成し、次のように接続します。
作成したswitch12ノードのパラメータを次のように設定します。
Labs Axis Align (Beta)ノードを作成し、次のように接続します。
作成したaxis_align2ノードのパラメータを次のように設定します。
Transformノードを作成し、次のように接続します。
作成したtransform70ノードのパラメータを次のように設定します。
Translateのxはch("../parameters/centerx")
で、yはch("../parameters/centery")
で、zはch("../parameters/centerz")
です。
nullノードを作成し、OUTPUTと名付け、次のように接続し、レンダーフラグをオンにします。
Shift+Oでネットワークボックスに囲います。 Cキーでネットワークボックスに色を付けます。
sideprops1のmirrorを忘れていたので追加していきいます。
HDA化する
組み込みのboxノードなどと同じように、作成した橋のノードもsopレベルとgeometryレベルの両方に用意します。
まずはsopレベルのノードを作成します。
ノード全体を選択して、Shift+Cでノードをサブネットに格納します。
ネットワーク内部に入ると何故か余計なOutputノードが生成されているので削除します。
subnetの名前をbridge_000とします。
今後、他の橋を作るかもしれないので番号を後ろにつけておきました。
Edit Parameter Interfaceを実行します。
最初からあるラベルは非表示にします。
Edit Parameter Interfaceのウィンドウを開いたまま、bridge_000ノードの内部に入ります。
nullに集約しておいたパラメータを全部ドラッグ&ドロップしてパラメータに追加します。
Acceptします。
各種パラメータがサブネット上に現れます。
bridge_000ノードを右クリックしてCreate Digital Asset...を選択します。
名前などを適切に設定し、Acceptを押します。
その後開くEdit Operator Type PropertiesウィンドウでTabキーのパスを指定します。
ハンドルを設定します。
次の図のCreate HandleからBoundingBoxを選択します。
centerx、centery、centerz、sizex、sizey、sizez、uniform_scaleにそれぞれパラメータを次のように割り当てます。
Acceptします。
bridge_000のノードを選択した状態で、シーンビュー上でEnterキーを押すとハンドルが出てきて、それで操作できるようになります。
つぎにgeometryレベルのノードを作成します。
新しく/obj
階層でGeometryノードを作成し、bridge000geoと名付けます。
bridge000geoのノードの内部に入って、Bridge 000ノードを新たに作成します。
/obj
階層に戻って、bridge000geoノードのEdit Parameter Interfaceを実行します。
フォルダを追加し、Bridge 000と名付けます。
bridge000geoノード内部に入り、bridge_000ノードからパラメータをドラッグ&ドロップします。
Acceptします。
bridge000geoノードにBridge 000のタブが増えてコントロールできるようになりました。
bridge000geoノードを右クリックしてCreate Digital Asset...を実行します。
適当に名前を決めてAcceptします。
場合によっては警告が出るかもしれませんがとりあえずNo Changesします。
先程のsopレベルのノードのときと同様にしてTABキーのパスとHandleを設定します。
Acceptすると警告が出るかもしれませんがNo Changesで。
これでHDAの作成は完了です。
作成した.hiplcファイルです。
引き続き、Unityに持ち込むためのシーンの構築とテクスチャの作成に移りますが、Apprenticeの方はテクスチャ作成用に必要となる頂点カラー付きのモデルを出力する手段がないと思うのでここまでです。 お疲れさまでした。 Apprenticeでもobj書き出しなどはできた気がするのでそういったことを試してみても良いかもしれません。
Indie以上の方は続きへと進みます。
シーンを作成し配置してfbx出力をする
新しいHoudiniのシーンを開きます。
まずは橋を配置する周辺のオブジェクトを作成します。
geoノードを作成します。backgroundと名付けます。
Boxノードを作成し配置します。
作成したbox1ノードのパラメータを次のように設定します。
PolyExtrudeノードを作成し、次のように接続します。
作成したpolyextrude1ノードのパラメータを次のように設定します。
PolyExtrudeノードを作成し、次のように接続します。
作成したpolyextrude2ノードのパラメータを次のように設定します。
Mirrorノードを作成し、次のように接続します。
Gridノードを作成し、次のように配置します。
作成したgrid1ノードのパラメータを次のように設定します。
Mergeノードを作成し、次のように接続します。
Normalノードを作成し、次のように接続します。
Transformノードを作成し、次のように接続します。
作成したtransform1ノードのパラメータを次のように設定します。
これで背景は完成です。
ひとつ上の/obj
階層に戻ります。
Bridge 000のジオメトリを作成します。
bridge000geo1を選択した状態でシーンビューでエンターキーを押し、ハンドルを出して良い感じの大きさに調節します。
Generate UVのチェックを入れておきます。
fbxを出力していきます。
/out
階層に移動します。
Filmbox FBXノードを作成し、outputbackgroundfbxと名付けます。
作成したoutputbackgroundfbxノードのパラメータを次のように設定します。
シーンのhipファイルを適当な場所に保存します。
その後、Sace to Diskを実行するとfbxが保存されています。
同様にして各LODのbridgeを出力してもよいのですが、せっかくなのでPDG/TOPsを使ってみることにします。
Filmbox FBXノードを作成し、outputbridgefbxと名付けます。
作成したoutputbridgefbxノードのパラメータを次のように設定します。
@lodname
はTOPsから与えるものです。
/tasks
階層に移動します。
topnet1の名前をoutput_fbxと変更します。
output_fbxの内部に入ります。
Wedgeノードを作成します。
作成したwedge1ノードのパラメータを次のように設定します。
1つ目のTarget Parameterは/obj/itsuki_bridge_000_geo1/lod
です。
ROP Fetchノードを作成し、次のように接続します。
作成したropfetch1ノードのパラメータを次のように設定します。
もう一つROP Fetchノードを作成質疑のように配置します。
作成したropfetch2ノードのパラメータを次のように設定します。
Wait for Allノードを作成し、次のように接続し、Outputフラグを立てます。
TasksのGenerate Static Work Itemsを実行してみます。
staticなタスクのドットが表示されました。
TasksのCook Output Nodeを実行します。
Cookが終わるとすべてのLODのfbxが出力されています。
今回はLOD違いを出すためにTOPsを利用しましたが、パラメータ違いのバリエーションを出力して確認したい場合などに便利な機能ですね。
このシーンとTOPsの.hiplcファイルはこちらです。
Substance PainterでのLOD0のテクスチャの作成
次はテクスチャの作成に移ります。 今回は出力したfbxに対してSubstance Painterでテクスチャを作ります。
頑張ればSubstance Designerでテクスチャ作成のノードを作ればフルプロシージャルにテクスチャまで行けそうな気もしますが、今回はSubstance Painterで手作業でテクスチャを作成します。 Substance Painterのパーティクルブラシを使いたいので……。 Substance Designerを使ったフルプロシージャルのマテリアルの構築は読者への課題とするということで。
newしてLOD0のモデルをSubstance Painterで読み込みます。
HDRPのMaskMapのためにTEXTURE SET SETTINGSからBlending maskを追加しておきます。 今回は使いませんが……。
Bake Mesh Mapsを実行します。
Output Sizeを適当に変更し、high Definition Meshsにハイポリのfbxを指定します。
ベイクしようとしたら次のようにエラーを起こしてしまいました。
不正なメッシュが混ざっているとこういう事になりがちです。 ベベルが爆発していたりnon manifoldが含まれていたりなどなど。
normalにnanが含まれている可能性があるので、次のようなVertex Wrangleのノードを作って接続して調べてみます。
vector n = v@N;
int flag = isnan(n.x) || isnan(n.y) || isnan(n.z);
setdetailattrib(geoself(), "NaN", flag, "max");
Geometry SpreadSheetのDetailを見てみるとNanが1
になっていてNormalにnanが含まれていることがわかります。
../bottom_hi
のObject MergeにつなぐとNaNなNormalは含まれていないようです。
top_hiのノードにはNaNなNormalが含まれているようでした。
このようにしてノードをつなぎ直していくと、polybevel1が問題だったことがわかりました。
polybevel1ノードのパラメータを次のように修正します。
PolyBevel、爆発しやすいので嫌になっちゃいますね。
hdaを変更したら、ノードを右クリックからSave Node Typeを実行します。
橋を配置したシーンファイルを開き、output_fbxのタスクをDirty Allしてfbxを消去してから実行します。
もう一度、Substance Painterのプロジェクトを作り直します。
再度、ハイポリのベイクを行います。
ベイク時にAverage Normalsのチェックを外したほうが良い感じに焼けました。
無事にベイクができました。
マテリアルを割り当てていきます。
コンクリートのマテリアルを適当に選んっでレイヤーにドラッグ&ドロップします。
スケールを8倍にします。
Color Selectionなマスクを追加します。
コンクリートにしたい部分を選択します。
コンクリートのダメージ部分に割り当てるマテリアルを追加します。
こちらもColor Selectionマスクを追加します。
同様にして次々とマテリアルを割り当てていきます。
フォルダを追加します。
フォルダにプラスチックのマテリアルを2個割り当てました。
プラスチックの色を黄色と黒にします。
上川のプラスチックにblackマスクを追加します。
マスクを選択した状態でadd fillを追加します。
AlphasからLine Stripesをドラッグ&ドロップします。
StripeのHeightを1にします。
Scaleを16にしました。
フォルダにColor Selection Maskを追加します。
Fillレイヤーを追加します。
colorとroughだけを出力し、適当に暗い値にします。
BaseColorとRoughのレイヤー合成モードをMultiplyにします。
Fillレイヤーにブラックマスクを追加し、add paintします。
ParticlesのLeaksを使って塗っていきます。
Smart Maskなどを使って汚しを加えていきます。
次の記事のとおりに、HDRP用のテクスチャとLOD1、LOD2のベイクで使うテクスチャを出力します。
UnityのHDRP向けのLOD対応背景アセットのテクスチャを作る | 測度ゼロの抹茶チョコ
Substance DesignerでLOD1、LOD2のテクスチャの作成
次の記事を参考に、LOD1とLOD2のテクスチャを作成します。
UnityのHDRP向けのLOD対応背景アセットのテクスチャを作る | 測度ゼロの抹茶チョコ
UnityのHDRPで表示する
プロジェクトの作成
Unityの新しいHDRPのプロジェクトを作成します。
Package Managerを開いてUpdate to 7.1.7をクリックします。
Project SettingsのEdtirからEnter Play Mode Settingsのオプションをオンにします。 これでだいぶプレイモードへ入るのが早くなります。
fbxのインポートとLODの設定
fbxとテクスチャをUnity上にインポートします。
何故かHoudiniからエクスポートしたfbxをUnityで読み込むと100分の1のスケールになっているので、インポートしたfbxのscaleを100に変更します。
インポートしたNormalとBent NormalマップのTexture Typeを Normal Mapに変更します。
インポートしたMask MapのsRGBのチェックを外します。
Materialを作成します。
マテリアルにテクスチャを割り当てていきます。
bridge000LOD0の上で右クリックしてCreateからPrefab Variantを作成します。
作成したVariantのマテリアルを作成したマテリアルに差し替えます。
VariantのTransformをrevertします。
同様にしてLOD1とLOD2のVariantも作成します。
シーンに空のゲームオブジェクトを配置します。
作成したGameObjectの名前をbridge_000に変更します。
bridge_000の子に、作成したVariant3種を配置します。
bridge_000にLOD Groupコンポーネントをアタッチします。
ドラッグ&ドロップして各LODにモデルを割り当てます。
bridge_000をプロジェクトビューにドラッグ&ドロップしてprefab化します。
シーンの設定
Settings/HDRenderPipelineAssetを選択します。
Screen Space ReflectionやScreen Space Shadowなどを有効にします。
新しいシーンを作成します。
Global Volumeを作成します。
newしてプロファイルを作成します。
Overrideを追加してExposure、Ambient Occlusionを設定します。
もう一つGloval Volumeを作成します。
Sky and Fog Volumeと名付けます。 newして新しいプロファイルを作成します。
Add OverrideしてVisual Environment、Fog、Gradient Skyを追加し、適当に設定します。
もう一つGloval Volumeを作成します。
Post Process Volumeと名付けます。 newして新しいプロファイルを作成します。
Add Overrideしてポストプロセスを適当に設定します。
backgroundとbridge_000のprefabを配置します。
Main Cameraの位置を調整します。
Main CameraにSimpleCameraControllerを追加します。
Main Cameraのアンチエイリアスを設定します。
スポットライトを適当に配置します。
Areaライトを配置してみます。
プレイモードに入って右ドラッグとwasdキーで移動して見ることができます。
リアルタイムレイトレのセットアップをする
リアルタイムレイトレーシングに対応したグラフィックカードを利用している場合はリアルタイムレイトレのセットアップをできます。
Window/Render PilelineからHD Render Pipeline Wizardを開いてHDRP + DXRからFix Allを実行します。
エディタをリスタートするように促されます。
リスタートするとエラーが出ていますが気にせず進めます。
HD RenderPiplineAssetから、Realtime Raytracigを有効にします。
Global Volumeから各種レイトレを有効にしていきます。
ライトの設定から影のレイトレの設定も行えます。
一通り設定してみたところ、こんな感じになりました。
おわりに
とても長い記事なりましたが、読んでくださった方はお疲れさまでした。
スクショを大量に撮って貼り付けるのに疲れてしまって、文章の推敲ができていなかったり、VEXなどのプログラム部分の細かい解説などがつけられていません……。 何かわからないことがあったら私のTwitterアカウントまでリプなどをいただければ時間のあるときにお返事できると思います。