女子高生になりたい

はるみちゃんのブログだよ。えへへ。

VAT(頂点アニメーションテクスチャ)を使ってHoudiniで作成した破壊シミュレーションをUnityにもってくる

Houdiniで作成した破壊シミュレーションをUnityにもってくる手順をメモとして残しておきたいと思います。

シミュレーション結果をUnityで利用するには、VAT(頂点アニメーションテクスチャ)をエクスポートし、それをUnityで利用します。

VATとは

VAT(頂点アニメーションテクスチャ)とは、名前の通りテクスチャに頂点のアニメーション情報(位置、回転)を書き込んだものになります。

このテクスチャに書き込まれた値を元に、各頂点の位置を決定していきます。

VATをexportする

今回はまず、Houdiniのシェルフからシンプルな破壊シミュレーションを生成しました。

こんな感じで、地面に落下すると要所要所のパーツが外れるものです。

f:id:sakata_harumi:20210617224730p:plain

エクスポートには、Labs Vertex Animation Texturesノードを利用します。SideFX Labsのインストールが必要です。

f:id:sakata_harumi:20210617224946p:plain

設定はこんな感じ。Method、Engine、SOP Pathを設定しています。あと、Target Texture Sizeも良しなに。

f:id:sakata_harumi:20210617225300p:plain

重要なのは Method
ここを間違うとうまく動かなくなります。今回はRigid。

Method
Soft シミュレーションを通じてトポロジーが一定のもの
Rigid パックプリミティブを元にしたリジッドボディシミュレーション
Fluid シミュレーション中にトポロジに変化があるもの
Sprite 空間を移動するポイントを常にカメラを向くカードで表示

(引用: Game Tools | 頂点アニメーションテクスチャ (VAT) | SideFX )

これでRenderすると、Paths/Projectで指定したパスにテクスチャ、FBX、マテリアルがエクスポートされます。

テクスチャは各頂点の位置を記録したもの、回転を記録したものの二種類ができているはずです。

f:id:sakata_harumi:20210617230709p:plain
position texture

f:id:sakata_harumi:20210617230705p:plain
rot texture

UnityでVATを利用する

Textureのimport

まずは、テクスチャをUnityにインポートします。このとき、テクスチャのサイズや値が変わってしまうような設定は切る必要があります。

f:id:sakata_harumi:20210617232031p:plain

  • sRGBをオフにする
  • Non-Power of 2をNoneにする
  • Generate Mip Mapsをオフにする
  • Filter ModeをPoint(no fitler)にする

Shaderのimport

SideFXが提供している SideFX LabのリポジトリにVATを使うためのシェーダーがあります。

github.com

※似た内容のリポジトリとして「GameDevelopmentToolset」というリポジトリも存在しますが、こちらは古いものなので注意

最新のReleaseが1.173なので、こちらをダウンロードしました。

(が、UnityのShaderが入っているディレクトリは本記事執筆してから13ヶ月間特に更新がないみたいなので、どのタイミングのコードでも内容は同じです)

unity→shaders→URP にpackage.jsonが入っているので、Unityパッケージマネージャー→ add package from diskからパッケージをimportします

URPのパッケージですが、中に入っているShaderGraphはHDRPでも動作しました。

これで、VATの利用に必要なShaderがimportできました。

f:id:sakata_harumi:20210617234753p:plain

materialをimport

EngineをUnityにしていることで、先ほどHoudiniからexportした先のディレクトリにmaterials/****.mat も同時に生成されているはずです。これをUnityに取り込みます。

すると、VATの生成に利用したMethodに対して適切なShader(SideFX/VAT_Rigid_SG)を利用したマテリアルがimportされます。

ここのPositionMapとRotation Mapに先ほどのテクスチャを入れるだけでマテリアルの設定は完了です。

f:id:sakata_harumi:20210617235208p:plain

自分でマテリアルを生成する場合などで、Speed、Number Of Frams、Pivot Min/Max、Position Min/Maxの値を設定する必要がある場合、このパラメータはLabs Vertex Animation Textureノード、もしくはmaterials以下に出力されているjsonから確認できます。

f:id:sakata_harumi:20210617235709p:plain

結果を確認

先ほどHoudiniからexportした先のディレクトリにmeshs/***.fbx が生成されているはずです。
これをUnityのシーンに設置して、マテリアルを適用させてあげると完了です

このように、無事Unityで破壊シミュレーションの結果を利用することができました!

youtu.be

もう少し複雑なシミュレーションを試す

先の例は変化が大きくなかったので、もっとバラバラになるパターンも試してみたいと思います。

シェルフで生成されたネットワークを少しいじって、パーツがバラバラになるようにします。

f:id:sakata_harumi:20210618001142p:plain

voronoi fractureノードを利用して、モデルをボロノイ分割しました。

あとは手順は全く同じで、VATをエクスポートし、Unityから利用しました。

結果はこんな感じ。問題なくできました。

youtu.be

因みに上の動画はURPで実行していますが、HDRPでも問題ありませんでした。

もっと複雑なシミュレーションを試す

今度は、もっと複雑なネットワークで試してみます。単純な形状で破壊シミュレーションをした後、その破片の形状を複雑なものに置き換えるネットワークです。

f:id:sakata_harumi:20210618001825p:plain

このようなアニメーションになるはずです。(動画はHoudiniでレンダリングしたもの)

www.youtube.com

これを全く同じ手順でVATをエクスポートし、Unityから利用したのが以下の動画です。

youtu.be

うまくいきませんでした ( ;∀;) コロシテ...コロシテ...と声がきこえてきます。

断面のディテールを表現するために、RBD Interior Detail geometryノードを利用しているのですが、これのせいでメッシュの構造が最初と変わってしまったから・・が原因でしょうか?

はっきりした事はわかりませんが、何でもかんでもうまくいくわけではないということで、利用の際には注意が必要そうです。
定期的にVATに出力して、うまくいくか試しつつ開発を進めていくのが良さそうです。

さいごに。

これまでの例では、モデルにテクスチャが貼られていなかったりと、実際のゲームで使えないものでした。

実際のゲームで使うには、提供されているShaderGraphを良しなにカスタマイズする必要があります。 幸い、ShaderGraphの構造自体は非常にシンプルなので安心です。

f:id:sakata_harumi:20210618003124p:plain

難しいのは中央のVAT_Rigid_SubGraphの中で使われているカスタムノードのHLSLなんですが、多分実務的には理解しなくても大丈夫です。

(こちらはまたじっくりと読んで理解しようと思います)

実際ゲームで使うために、例として以下のようなカスタマイズをしてみました。

  • MasterノードをLitにした
  • テクスチャを貼れるようにした
  • シミュレーションの時間を外部からfloatで与えられるようにした

f:id:sakata_harumi:20210618003440p:plain

このShaderを使ってみると、(わかりにくいですが)テクスチャが反映されていることがわかります。

f:id:sakata_harumi:20210617223201p:plain

おわり。次は流体シミュレーションでも試してみようと思います。

PackedMapを利用する場合のShaderの例(続・Houdiniで制作したSmokeシミュレーションを連番テクスチャとして吐き出してUnityで利用するまで。)

はじめに

この記事は

sakataharumi.hatenablog.jp

の続きです。

前回の記事はColorMap、NormalMapを出力しましたがEmission Mapは使用していませんでした。

本記事では、EmissionMapを使ってみようと試行錯誤した記録と結果を書いていきます。

EmissionMapを得るためにPackedMapを出力

TextureSheetsノードの設定をし、PackedMapを出力します。

  • Render Emission Layerにチェック
  • Channel Pack Normal, Emission, Alphaにチェック
  • Render Packed Mapで出力

f:id:sakata_harumi:20210608235358p:plain

すると、PackedMapが出力されます。

こちらは名前の通り、複数の情報(法線、エミッション、アルファ)が1つのテクスチャに書かれたもので、どのチャンネルに何の情報が書かれているかをChannel Packing タブから確認・変更できます

f:id:sakata_harumi:20210608235546p:plain

BlueのチャンネルにEmissionの情報が書かれていることがわかります。

RedとGreenにNormalの情報が書かれているんですが、X,Y成分のものしか書かれていません。
一見これでええんか?と思いますが何とZを復元できるらしいです・・!詳しくは次のシェーダーを作る過程でみていきたいと思います。

f:id:sakata_harumi:20210609001000p:plain
出力したPackedMap

VFX Graphで使うShaderの実装

ここで得られたのはPackedMapなので、NormalMap、EmissionMapと分解されているわけではありません。

なので、自分でShaderを実装して利用することにします。

1. Shader Graphの作成

VFX Shader Graphを作成し、デフォルトで生成される出力用ノード(Visual Effect Masterノード)の設定を変更。Litにチェックをつけておきます。

f:id:sakata_harumi:20210609001339p:plain

これで、NormalやEmissionを設定できるインプットが出現しました。

2. flip bookの設定

とりあえず、NormalやEmissionは置いておいてメインのテクスチャをアニメーション可能にしていきます

f:id:sakata_harumi:20210609001722p:plain

FlipBookPlayerの現在のインデックスの値は「texIndex」というプロパティで取得できます。この値をShader Graphの入力として与えています。

f:id:sakata_harumi:20210609001828p:plain

3. Normal Mapの設定

次に、Normal Mapを復元し設定していきます。RとGがNormalの情報(X,Y成分)に相当することがわかっているので、これらの値を利用します。

f:id:sakata_harumi:20210609002227p:plain

で、Z成分の復元なんですがこれには「Normal Reconstruct Z」というノードがあるのでこれを利用することで復元できます。

docs.unity3d.com

復元式は以下。


\sqrt{1.0 - saturate(x * x + y * y)}

Z成分は1.0が基準であり、xyベクトルの大きさが大きいとZ成分は小さく(凹凸が大きく)なり、小さいと大きく(凹凸が少なく)なるので、感覚的には納得です。

4. Emission Mapの設定

BチャンネルがEmissionの情報になっているので、これを利用します。 ネットワークは以下のようにしてみました。あってるのかは正直わからん。 間にカラーをブレンドして発光色を決められるのかな。

f:id:sakata_harumi:20210610010907p:plain

EmissionMapでは黒い部分ほど発光度が下がります。

結果はこんな感じ。

f:id:sakata_harumi:20210610010952p:plain

Houdiniで制作したSmokeシミュレーションを連番テクスチャとして吐き出してUnityで利用するまで。

HoudiniでPyroエフェクトを使ったボリュームのシミュレーションを試していたんですが、これどうやってゲーム制作で使うんだ?と思い調べて試した記録です。

結論、Texture Sheetとしてフレーム単位で2Dイメージを出力したものを使うのが良さそうなので、そちらを試してみました。

SideFX Labsの導入

今回使用するTexture SheetsノードはSideFX Labsに含まれるものなので、もし入っていない場合は入れておきます。

www.sidefx.com

ちょっと前まではGameDevToolsと呼ばれていたとのこと。ゲーム開発以外にも使えるということのアピールのために、名前が変わったんですかね。

Texture Sheetsの利用

カメラとMantra Render Nodeは既に設置してある前提で、Mantraノードの下にLabs Texture Sheetsノードを設置します

f:id:sakata_harumi:20210606215538p:plain

設定はこんな感じ。

だいたいこちらを参考に進めました。

support.borndigital.co.jp

TextureSheets

  • Export Normal, Render RGB Lightsにチェックを入れる
    • ノーマルマップも欲しいので
  • Nodes→Node To Renderにレンダリングしたいobjを指定
  • Settingsにいい感じのResolutionとImages per Lineをセットする
    • Override Resolutionにもチェックを入れておく

f:id:sakata_harumi:20210607000636p:plain

Mantra

  • Images→Extra Image Planes→Shading Normalにチェックを入れる
  • Objects→Exclude Lightsに「@rgb_lightrig」と入力 f:id:sakata_harumi:20210607005720p:plain f:id:sakata_harumi:20210607005917p:plain

Render RGB Lightsにチェックを入れておくと、良い感じにノーマルマップが生成されるらしいです。

Render RGB Lightを有効にすると、下記画像のように軸に合わせてR、G、Bの6個のライトが作成されます。

Volumeのノーマル情報を出力することは大変ですが、Houdiniのこの拡張機能では2つの方法をブレンドして可能にしています。Houdiniはデフォルトでボリュームのグラディエントをレンダリングする機能があります。それが下記画像のVolume Normalsとなります。こちらはDetailを保持します

(引用: Houdini Game Dev Tools:Texture Sheetsのリアルタイム合成を行う – Born Digital サポート )

なるほどわからん

これで、レンダリングするとTexture Sheetが出力されます。・・・と、結構簡単にできそうなものなんですが、実はいくつかハマりました。

(Emission Layerの出力と利用についてはまだ試せてないので、またそのうち試してみようと思います)

アスペクト比がおかしい

カメラのResolutionを512x512で設定して、とりあえずRenderしてみると以下のようにアスペクト比が崩れたTextureSheetが出力されてしまいました。

f:id:sakata_harumi:20210607001553p:plain

こちらの解消方法なんですが、どうやらOverride Camera Resolutionにチェックを入れると、良い感じにTextureSheetsのサイズに応じて良い感じに調整して出力してくれるようです。

こちらにチェックを入れない場合、自分でImages per Line、Resolutionを調整し正しいアスペクト比で出力されるようにしないといけないようです。

まだアスペクト比がおかしい

実は、Override Camera Resolutionにチェックを入れても直ぐには上記事象は解決しませんでした・・。

こちらの原因は、上記の変更後「Render Color Map」を押下してTexture Sheetを書き出していたからのようです。

Color Mapはシーケンスデータから生成されるので、シーケンスデータを再生成しないと先ほどの設定は反映されません

素直に全て再Renderすると無事うまくいきました。

f:id:sakata_harumi:20210607002144p:plain

f:id:sakata_harumi:20210607002114p:plain

ノーマルマップも良い感じに生成されてます!

Unityで取り込むと透過されない

EXRで出力していたのですが、UnityにSpriteとしてロードすると原因不明ですがうまく透過されませんでした

f:id:sakata_harumi:20210607003615p:plain

今回は諦めてEXR→PNGに変換することで解消しました( ;∀;)

せっかくなのでHDRのまま使いたいんだけどなあ

VFX Graphを作成

最後に、VFX Graphを作ってUnityで再生できるようにします。

グラフはとても簡単。

f:id:sakata_harumi:20210607010626p:plain

Flipbookを利用して連番アニメーションを再生します。

また、せっかく作成したノーマルマップを使いたいのでOutput Contextをデフォルトのものから Lit Quadに変更します。

完成

これで無事UnityにSmokeシミュレーションの結果をもってくることができました。

ノーマルマップを使うか使わないかで、結構質感が変わりますね。Emissionも試してみたいところ。

(ノーマルマップなし)

youtu.be

(ノーマルマップ利用)

youtu.be

Houdini Engine for UnityでHoudiniで作ったプロシージャルモデルをUnity上で利用する

突然ですが、最近(ここ数日レベル)はHoudiniに入門しています。

きっかけはVFX Graphでエフェクトを制作していた際、自分の思っているものにするにはVectorFieldというものが必要で、それを作成するためにはHoudiniが必要・・やるか・・という感じです。

で、まあ、せっかくGWもあることだし腰を据えて勉強してみよう、という。

そこで、今回はHoudiniで作ったプロシージャルモデルをUnityへもっていく方法を試しました。

今回はその記録記事を書いていきたいと思います。

本記事の利用環境

  • windows 10
  • Houdini Indie 18.5
  • Unity 2020.2.3f1 (URP)

※ 本記事ではHoudini Engineを利用しているため、Houdini Apprenticeでは実行不可能です。詳細は公式のライセンス比較ページを参照ください

HDA(Houdini Digital Asset)の作成

プロシージャルモデルをUnityで利用するためには、Houdiniを使ってHDAを作る必要があります。

(手順1) HDAにしたいノード群をサブネットにする

サブネットにしたい対象のノードを選択し、画像の赤枠で囲った部分を押下するとサブネット化可能です。

f:id:sakata_harumi:20210504014154p:plain

図にはMaterialノードがありますが、これはSOPではなくサブネット外部の別のネットワークタイプのノード(VOP)を参照しているため、HDAにすることができません。

もしマテリアルにVOPのノードを指定した状態でMaterialノードを含めてHDA化しようとすると、以下のような警告が表示されます。

f:id:sakata_harumi:20210504013903p:plain

(手順2) 使用したいパラメータをアウトプットする
プロシージャルモデルを利用するんですから、当然パラメータによってその形状等を変化させたいわけです。

しかし、全てのパラメータがUnity上で変更できるようになるわけではなく、アウトプットしたパラメータだけが変更可能になります。

まず、Edit Parameter Interfaceから設定画面を開きます。

f:id:sakata_harumi:20210504015218p:plain

そして、サブネットの中に入ってアウトプットしたいパラメータをD&Dでもってくると設定可能です。

f:id:sakata_harumi:20210504015354p:plain

(手順3) HDAをエクスポートする

サブネットの上で右クリック > Create Digital Asset でHDA作成します。 色々細かい設定が出てきますが、よくわからないのでそのままにしました。とりあえず問題なさそうです。

f:id:sakata_harumi:20210504015452p:plain

Unityへ取り込む

(手順1) Houdini Engine for Unityを導入
公式の導入記事を参考に、カスタムパッケージをUnityプロジェクトに取り込みます。

www.sidefx.com

(手順2) HDAをインポート

Houdini Engine > Load File > HDAからインポートできます。先ほどエクスポートしたものを選択してください。

f:id:sakata_harumi:20210504020103p:plain

これで、パラメータを変えることでモデルの形状が変化するようになりました!

youtu.be

あとは良きパラメータを指定し、ベイクすることでそのモデルをゲームシーンに利用可能になります。

「ベイクすることで」とあるように、パラメータをゲーム中動的に変更することはできないのでご注意を。

UnityのMaterialを参照する

今回の手順では、Materialをエクスポートできませんでした。

白いままでは味気ないので、Unityで作成したマテリアルを利用できるようにしていきます。

Houdini Engineをインストールしていると、SOPに「Unity Material」というノードが用意されています。通常のMaterialの代わりに、こちらを利用することでUnityで作成したマテリアルを参照できます。

f:id:sakata_harumi:20210504022118p:plain

パラメータのStringにマテリアル(.mat)の Assets以下の相対パスを記述します。

f:id:sakata_harumi:20210504022455p:plain

そして、同手順でHDAを生成するのですが生成したHDAファイルは Assets以下の任意の場所 に置いてください。 「相対パスを記述する」「Assets以下にHDAファイルを置く」この二点がハマりポイントになります。

これで、Sphereに色をつけることができました!

youtu.be

おわりに。

Unityにプロシージャルモデルを取り込む事ができました。広大なマップにオブジェクトを配置したり、単一のモデルから様々なバリエーションのモデルを作成したりと、応用範囲は広そうです。

ただ、個人開発レベルのプロジェクトで活かせるか・・といわれるとまだイメージができてません。面白い応用例を考えてみたいところ。

また、今回は動かないモデルでしたが、Houdiniはシミュレーションも得意っぽいです。

ベイクしたアニメーションをUnityで利用するには、FBXアニメーションやVAX(Vertex Animation Texture)を利用してUnityへ取り込む方法があるようですが、そちらも追々試していけたらと思います。

【その他いろいろな設定】HDRPで絵作りに挑戦していく【Part 3】

前回の続きです。

sakataharumi.hatenablog.jp

4 Ambient Occlusion

Ambient Occlusion(環境遮蔽)を利用して、細かい部分の陰影をつけていきます。

f:id:sakata_harumi:20210214155916p:plain
AO適用前

AO適用前の状態では、例えば、手前の三段重ねの発泡スチロールの横の部分など本来光が遮られていそうな場所でも光があたってしまっている事がわかります。

docs.unity3d.com

ボリュームの設定から、AOを追加し、Intensityなどを調整しました。 f:id:sakata_harumi:20210214155451p:plain

f:id:sakata_harumi:20210214155502p:plain
AO適用後

細かい影がくっきりついて、より立体感のある表現になりました。

5 Anti-aliasing

Anti-aliasingを設定してきます。

docs.unity3d.com

AAにはいくつか種類がありますが、今回は Temporal anti-aliasing (TAA) を利用します。

f:id:sakata_harumi:20210214161755p:plain

Temporal anti-aliasing (TAA)
他のAA手法では、現在のフレームのみを元にして計算されますが、TAAでは過去のフレームの情報も利用してエッジをなめらかにします。

MSAAと比較しても動きのあるエッジのスムージングに優れているようです。 ただし、Motion Vectorの設定がなされていないとオブジェクトが速く動いた場合などでアーティファクトが発生してしまうようなので、注意が必要です。

f:id:sakata_harumi:20210214164150p:plain

f:id:sakata_harumi:20210214161706p:plain
TAA適用後

6 Reflection Probe

Reflection Probeを設定し、鏡面反射成分の反映をしていきたいと思います。

1つのReflection Probeでシーン全体をカバーすることもできますが、そうすると本来反射するべきでないものも反射されてしまう・されるべきものが反映されないという事になります。

例えば、こちらはシーン全体で1つのRPを設置(中央)したときのあるお店の壁です。
映り込みがほぼありません。

f:id:sakata_harumi:20210214171827p:plain

一方、シーン全体で5つほどのRPを並べたときの同じお店の壁です。
こちらだといい感じに反射しているように見えます。

f:id:sakata_harumi:20210214171952p:plain

この辺りはよき匙加減でやる必要がありそうです。

f:id:sakata_harumi:20210214175350p:plain
RP適用後

7 Fog

軽くFogを追加していきます。

f:id:sakata_harumi:20210214183547p:plain

明るいシーンであれば、Volumetric Fogを利用することでライトシャフトを表現できたりとビジュアルが向上するんですが、今回は暗いシーンなのであまり関係はありません。

f:id:sakata_harumi:20210214183559p:plain
Fog追加後

8 Post Processing

最後にPost Processをかけて全体的な見た目を調整していきます。

8.1 Bloom

光がにじみ出ているような表現をするフィルターです。
とりあえずこれを入れて置いたらそれっぽくなります。

f:id:sakata_harumi:20210214190010p:plain

f:id:sakata_harumi:20210214190018p:plain

8.2 Depth of Field

被写界深度の設定です。これを設定することで、カメラのピントがあってない部分がぼやけるような表現が可能になります。

DoFの設定には大きくManualとUse Physical Cameraの二種類があります。
Manualでは焦点のあうRangeを手動で決定できますが、ちゃんと調整しないと違和感の強いものになってしまいます。

そこで、今回はUse Physical Cameraモードを用います。こちらはCameraの物理的な設定値を利用することでDoFをコントロールすることができます。

Cameraの設定からAperture(絞り)をコントロールすることで、ボケの効果を調節できます。
値が大きいほど(左にスライド)、全体的にボケるようになります。

さらにその下、Apertune ShapeのBlade CountとCurvatureでボケの形状の調節ができます。

f:id:sakata_harumi:20210214192906p:plain
Post processの設定
f:id:sakata_harumi:20210214192932p:plain
Cameraの設定

f:id:sakata_harumi:20210214192944p:plain
DoF適用後

結果

(before) f:id:sakata_harumi:20210215013756p:plain

(after) f:id:sakata_harumi:20210215013738p:plain

www.youtube.com

大分良い感じになりました('ω')

次は番外編として、キャラクターを出してプレイアブルなフィールドにしてみたいと思います。

【光りを放つものを作っていく】HDRPで絵作りに挑戦していく【Part 2】

前回の続きです。

sakataharumi.hatenablog.jp

3. 光りを放つものを作っていく

今回のシーンでは、光を放つものが3つあります。

1つが既に発光している店の扉。もう1つが提灯。最後が店の看板です。

今回は、この3つについて設定をしていきたいと思います。

3.1 店の扉

店の中から発される光を設定していきます。

本当は扉の裏に光源を設置し、扉がその光を透通すような表現をするのが正しいのかもしれないんですけど、今回は扉自体が光を放出しているとして、Emissionの設定を行っていきます。

Standard ShaderのDocumentを見てみると

エミッシブマテリアルは、通常、内側から照らされているように見えるゲームオブジェクトに使用されます。例えば、暗闇の中で見えるモニターの画面、高速時にブレーキをかけている車のディスクブレーキ、コントロールパネルの光るボタン、モンスターの目などです。

とあるので、今回のユースケースにも適していそうです。

docs.unity3d.com

一方、物理的に正しそうな表現(物体がその背後にある光源の光を透過させる)もLit Shaderでは可能です。
この後着手していく提灯は、そのように実装していきたいと思います。

Lit ShaderでEmissionの設定

Lit ShaderではEmission inputsの項目でEmissionの設定を行います。

f:id:sakata_harumi:20210210001454p:plain
ドアのLit Shader設定

Use Emission Intensityにチェックを入れると、Emissiveカラーと発光強度を別々に設定することができます。今回は利用していませんが、一通り完成後の調整で使うかもしれません。

Baked Emissionは、GIを利用する場合はチェックを入れないといけません。現状Realtime GIには対応していないようです(Unity 2021系では復活するのかな?)

以下、チェックを入れてないもの/入れたものの比較です。(Bake済み)

f:id:sakata_harumi:20210210000705p:plain
非 Baked Emission
f:id:sakata_harumi:20210210000716p:plain
Baked Emission

Baked Emissionにチェックが入っていない方では、GIが計算されないため段ボール、地面などに本来当たるはずの間接光が反映されていないことがわかります。

Bakedの方では、段ボールはもちろん、地面もうっすら照らされていることがわかります。

ここまで

ちょっと色味と強度を修正してベイクしてみました。 手前の段ボールなどにEmissiveカラーの間接光が反映されていることがわかります。

f:id:sakata_harumi:20210210010752p:plain

3.2 提灯

提灯は内部に光源となる電球が存在して、そこが発光し内部で光が散乱した後に外部へ出ていきます。

このような表現のメカニズムをSubsurface Scatteringといいます。Lit Shaderではこの表現が可能です。

このSubsurface Scatteringでよく例にあげられるのは「人間の肌」です。

たとえば、人間の肌の質感などがよい例である。人間の肌の表面は実は半透明であり、光は完全には反射されず、一度肌の内部に入り、内部において何度も何度も反射と散乱を繰り返した後に、外に出る。そこで出てきた光を見て、人間は色を感じている。(wikipediaから引用)

ja.wikipedia.org

Subsurface Scatteringの前にEmission

比較用に、Material TypeはStandardの状態で、光源を置くのではなくドア同様Emissionを設定してみます。

f:id:sakata_harumi:20210212140336p:plainf:id:sakata_harumi:20210212140344p:plainf:id:sakata_harumi:20210212140354p:plain

充分いい感じに見えますね。。

Subsurface Scattering

まずは、Lit ShaderのMaterial TypeをSSではなくStandardにした状態のまま内部に光源(Point Light)を設置してみます (Emissionの設定は元に戻しておきます)

内部に光源を配置するとき、Lit ShaderのDouble Sidedにチェックをつけておきます。 こうすることで、内部に配置した光源の光が外に漏れる事がなくなります。

f:id:sakata_harumi:20210212114019p:plain

f:id:sakata_harumi:20210212113927p:plain

Surface TypeがOpaque(不透明)のため、内部に光源を配置しても光が一切提灯の中から漏れることがありません。

ここでMaterial TypeをStandard→Subsurface Scatteringに変更します。

すると、内部の光源がいい感じに放出されているような見た目になります。

f:id:sakata_harumi:20210212171232p:plain

ただし、Diffusion Profileが設定されていないので緑色になってしまっています。 新しくDiffusion Profileを作成し、設定していきたいと思います。

・・の前に、少し逸れてしまいますがまずは内部の電球のパラメータを調整していきましょう。

Point Light

提灯の内部にPoint Lightを生成しておきます。 ググると、提灯用LED電球を発見しましたので、これが中に入っているということにして数値を設定していきます。

www.monotaro.com

Radius
光源の半径です。今回は直径45mmの電球とのことなので半径は22.5mm。メートルに換算して0.0255mとなります。

Temperature
色温度。スペックに書いてある通り2200Kelvinを設定します

Intensity
こちらもスペックに書いてある通り340Lumenを設定します。

Range
光の最大到達距離を設定します。
この記事曰く、光源から2mほど離れると照度はほぼ0になるらしいので、Rangeは2に設定してみました。

xtech.nikkei.com

f:id:sakata_harumi:20210212201744p:plain

Diffusion Profile

Diffusion Profileは Create → Rendering → Diffusion Profileから作成できます。 作成後、使用するためにはVolumeのDiffusion Profile Overrideに追加したProfileを登録しておく必要があります。

f:id:sakata_harumi:20210212171902p:plain

Parameters

Scattering Distance
ここをコントロールしてDiffusion Profileの形、ぼかしなどを設定します。 物理的に正しい値をどう設定するのか・・など詳しい事はわかりませんでした。 とりあえず見た目で良い感じになるように設定しています。

Index of Refraction
値を大きくすると鏡面反射の強度が上がります。 今回は光源が内部にあるので関係なさそうです。

Subsurface Scattering only
Post-scatterだとsubsurface scattering適用後にマテリアルにAlbedoを適用します。よって、テクスチャがくっきり表示されます。
Pre and post scatterでは、名前の通りAlbedo適用前後でsubsurface scatteringを適用します。よって、テクスチャがぼやけソフトな感じになります。

Transmission only Parameters
以下はthicknessの利用がONになっているときのみ有効なパラメータです。

今回はONですが、tchikness mapがないのでmaterial全体で均一の厚さ(1.0)の設定にしています。

f:id:sakata_harumi:20210212182741p:plain

Transmission Mode

厚い素材の場合はThick Objectに設定するよう。すると、シャドウマップを利用してSSの計算をするらしい・・ 今回は薄い素材なのでThin Objectに設定しました。

Thickness Remap Values
素材の厚さのmin-maxをmm単位で指定します。 thickness mapの情報を元に0.0~1.0の厚さが設定されているはずなので、そこにThickness Remap Valuesが乗算された値が計算上の厚さになります。

今回は均一でthicknessが1.0のためmaxのみ利用されることになります。
厚めの和紙がだいたい0.3mmくらいみたいなので、そのように設定してみました。

f:id:sakata_harumi:20210212202050p:plain

とりあえずここまでで、提灯がいい感じに発行するようになりました。
Emissionと比べて、やわらかい感じが出ている気がします。

f:id:sakata_harumi:20210212202814p:plain

3.3 看板

看板は普通にEmissionを設定していこうと思います

結果(1)

全ての提灯、看板にライトの設定を入れました。

結果がこちら。

f:id:sakata_harumi:20210213192815p:plain

一部光っていない提灯があるので、原因を探っていきます。

Sceneと表示モードをLight Overlapにします。
この中で、赤い電球マークになっているものがあるのがわかります。

f:id:sakata_harumi:20210213192912p:plain

Shadow maskテクスチャでは、最大4つの重なり合うライト情報までしか格納できません。そのため、それ以上のライトについてはBakeされます。

Light Overlapモードで表示される赤い電球マークは、Bakeされる光源を意味しています。

Bakeされた光源については、リアルタイムで処理されないため光が内部で拡散せず、提灯が光っていないのだと推測してます。

じゃあ全部Realtime Lightにすれば良いのでは?と思うんですが、それはそれでshadow mapが使われたり使われなかったりするせいか狂います

www.youtube.com

といわけで 諦めます v(゚∀。)v

結局、提灯にもEmissionの設定をすることにしました。

結果(2)

f:id:sakata_harumi:20210213215705p:plain

紆余曲折ありましたが、結局Emissionの設定だけに落ち着きました・・

次回はambient occlusionやpost processの設定などやっていきます。

【準備~環境光、ボリュームの初期設定まで】HDRPで絵作りに挑戦していく【Part 1】

今回から何回かにわたり、HDRPを利用したシーンのライティングに挑戦していきたいと思います。

自分もHDRP素人というか、そもそもライティングからよくわからない人間なので、勉強したことの備忘録という感じです。

間違っている箇所もあるかと思いますので、ご了承下さい。

1. アセットとシーンを準備

1.1 アセットのインポートとマテリアル変換

今回利用したアセットはこちら。 https://assetstore.unity.com/packages/3d/environments/urban/japanese-alley-162907

https://www.youtube.com/watch?v=7IWHoTkw_sQ&feature=emb_title

このアセットをインポートすると、Materialsが真っピンクになっていると思います

f:id:sakata_harumi:20210207235931p:plain

これは、ShaderがHDRPに対応していないために起こってます。

HDRPは自動でbuilt-in shaderをHDRP shaderにコンバートしてくれる機能が存在していますので、そちらを利用します。

※ build-in shader以外が使われている場合は手動でHDRP shaderに変換をしないといけないようです。今回利用するアセットは問題ありませんでした

"Render Pipeline Wizard" → "Upgrade Project Materials To High Definition Materials" もしくは "Edit" → "Render Pipeline" → "HD Render Pipeline" → "Upgrade from build in pipeline" → "Upgrade Project Materials To High Definition Materials" からコンバートが可能です

f:id:sakata_harumi:20210208000917p:plain

コンバートすると、概ね正常にプレビューが表示されるようになりました。

f:id:sakata_harumi:20210208001004p:plain

一部、正常にプレビューが読み込めていないものがあります。

こちらは、ピンク色になっているPrefabを選択し、Resetを選択することで解消されるようです。

Resetは赤線の部分から選択できます。

f:id:sakata_harumi:20210208001401p:plain

これで、アセットが利用可能になりました。

1.2 シーンにオブジェクトを設置していく

インポートしたアセットを並べて、シーンを作っていきます。

ここで、電球マークのチェックを外しておいてシーンのライティングが無効になった状態で作業を進めていくと見やすくて良いです。

f:id:sakata_harumi:20210208001812p:plain

いい感じにオブジェクトを置いてみました。 f:id:sakata_harumi:20210208002104p:plain

f:id:sakata_harumi:20210208002031p:plain

これで、準備は完了です。

2. Directional Lightと基本的なVolumeを設定

2.1 Directional Light

今回は夜のシーンを作ろうと思うので、Directional Lightもそれに合わせて設定します。

色温度は4500 kelvin、Intensityは0.5 Luxあたりに設定しました。 (※後で変更することになります)

f:id:sakata_harumi:20210208003530p:plain

こちらの値はUnityの公式ブログのチートシートを参考にできます。

f:id:sakata_harumi:20210209100632p:plain
(引用: https://blogs.unity3d.com/jp/2021/01/07/explore-learn-and-create-with-the-new-hdrp-scene-template/

他にも一般的なライトのIntensityやExposureの値(重要)なども参考にできるので、覚えるまではとても重宝します。。

blogs.unity3d.com

この通り、HDRPは現実世界の値をそのまま反映させることを念頭に実装されていますので、例えば現実世界の電球のパッケージに書かれている値などを参考にする・・等々もしていくと良さそうです。

LightのModeの違い

Lightには "Baked" "Mixed" "Realtime" が存在します。

Baked
ライトからの直接光と間接光をライトマップにベイクします。 Baked Global IlluminationがONのときのみ利用可能。

Global Illuminationとは、直接光だけでなく間接光も計算して表現しようとするレンダリング手法です。

GIにより、例えば直接光が赤色のオブジェクトにあたり、その光が反射して赤色の光を返す・・のような表現が可能になります。

docs.unity3d.com

Bakedモードでは当然ですが、ベイクされるのはstaticオブジェクトのみになります。

非staticなオブジェクトでBakedモードのライトに対してGIを表現しようとするにはライトプローブを利用します。

docs.unity3d.com

Realtime
直接光とシャドウはリアルタイムで処理されます。間接光はリアルタイムGIを有効にしたときのみ反映されます。

※ リアルタイムGIは以前、Enlighten Lightmapperで利用可能でしたが2020.2現在、非推奨であり新規で利用することはできません。Unity 2021.1に代替ソリューションを提供予定・・とのことです

blogs.unity3d.com

Mixed
Bakeするものとリアルタイムに計算するものを混合させることができます。 さらに以下の3つのMixed LightingモードがあってLigthing Settingから選択できます(HDRPではSubtractiveは選択できないっぽい?)

Subtractive
Baked Indirect
Shadowmask

詳細は割愛しますが、ざっくり理解はこんな感じです。

Substractive
Directional Light以外は直接光もBakeする。なので、非staticなオブジェクトからリアルタイムで影を落とせるのはDirectional Lightのものだけ、スペキュラの表現も不可能。
非staticなオブジェクトはライトプローブを利用してstaticオブジェクトからの影を受けることができる。

Baked Indirect
間接光のみを事前計算し、影の事前計算は行わず、Shadow Distanceの範囲でリアルタイムで描画。超えると影は作られない。

Shadowmask Mode: Shadowmask
間接光はベイク、影は事前計算されたシャドウマスクテクスチャを元に表示する。

Shadowmask Mode: Distance Shadowmask
間接光はベイク、影はShadow Distanceの範囲内はリアルタイム、それを超えたものはシャドウマスクテクスチャを利用して描画。

BuildRenderPipeline(以前のレンダーパイプライン)では、Shadowmaskのモードが2つに分かれていましたが、HDRPではShadowmaskモードでさえあれば個々のライトに応じてどちらを利用するか選択ができます。

今回は、Lighting Modeはshadowmask、Directional LightにはDistance Shadow Maskモードを設定しています。

f:id:sakata_harumi:20210208225906p:plain

f:id:sakata_harumi:20210208225923p:plain

2.2 Volumeの初期設定

Volumeはデフォルトのボリュームから必要な値だけオーバーライドする形になります。 ただ、今回はオーバーライドしてる、してないの認識統一が面倒なので、デフォルトのボリュームにこのシーンで使用するために新しく作成したボリュームを設定しておきます。

f:id:sakata_harumi:20210209011206p:plain

細かい調整は後でするとして、最低限SkyboxとExposure(露出)の設定を行います。

f:id:sakata_harumi:20210209014928p:plain

Mode
ModeではGlobal/Localが存在します。Localでは1シーン上にボリュームの設定を変えたい場合(例えば、外の部分と部屋の中の部分があるなど)に使用します。
今回は、外のみなのでシーン全体に適用されるようGlobalに設定しています。

Intensity(HDRI Sky)
先ほどのチートシートにも書かれてる通り、真夜中の環境光は0.001Lux程度とのことでした。 なので、Directional LightとSkyBoxの値を足して0.001Lux程度になるように設定します。
今回はDirectional LightのIntensityを0.0008Lux、Sky BoxのIntensityを0.0002Luxに設定してみました。

明るい昼間の外のシーンでは、太陽光:空=5:1くらいの割合になるようです。

Exposure
Volumeで最も需要なパラメータがExposure(露出)です。

カメラのレンズに入ってくる光の量は昼間の外だと12万Lux、今回のような真夜中のシーンだと0.0001Luxと大きな差があります。 そこで、撮影素子に当たる光の量をいい感じに調整するために露出のコントロールが必要になります。

現実の世界のカメラでは、シャッタースピードと絞り、ISO感度の3要素から適正露出を求めますが、Unityでは(三要素から決定することも可能ですが)露出値をダイレクトに入力できます。

ざっくりとEV値が低いほど明るい絵、高いほど暗い絵になります。

適正露出は先ほどのチートシートが参考になります。

深夜では-2程度が適正とのことでしたので、そのように設定してみました。

Mode Fixedはシーン全体で固定の露出値を使う設定です。 今のところ固定視点のシーンなのでこれで問題ないですが、本来であれば明るいところに視点があるとき、暗いところに視点がある時で露出値を調整しないといけません。

そこで、ExposureのModeにはAutomaticをはじめとする幾つかのモードがあります。こちらは余裕があれば次回以降の記事で見ていければと思います。

ここまでの結果

f:id:sakata_harumi:20210209020002p:plain

まだ暗すぎな感じがしますね。

このシーンには現状Directional Light以外のLightは存在しません。

ドアが光っているのはLitShaderのEmission Inputsが設定されているためです。

次回は主にLit Shaderの設定をみつつ、提灯に明かりを灯す作業をしていこうと思います。