この記事では、LOPsにおける、アセットの組み立て方法について解説します。
このチュートリアルでは、アセット部門として簡単な花瓶の置かれた本棚のアセットの組み立てを行います。
ここではStage Managerについて簡単にご紹介させて頂きます。こちらの詳しいご紹介は次の記事で行わせて頂く予定です。
本文を確認する前に、まずはInstancingとPoint Instancerについてご紹介します。
Instancing
OpenUSDのドキュメント(英語)
USDは2つの形式でインスタンスを提供します。
- ネイティブインスタンスは、アセットの大量のコピーを効率的に表すために、単一の「マスタープリミティブ」を生成するようにUSDに指示するプロパティです。
- Point Instancerは、ジオメトリの膨大なコピーを効率的に表現できる特別なスキーマです。
どちらのタイプのインスタンスも、各プリミティブのトップレベルのTransformをサポートし、primvarsを(ネイティブインスタンス上またはPoint Instancerプリミティブ上で)オーサリングして、インスタンスごとのマテリアルプロパティを設定することもできます。ネイティブインスタンスは各インスタンスの実際のTransformであり、各インスタンスはシーン内で一意の名前空間として表されます。インスタンスからヒーローに簡単に昇格することができます(「instanceable」プロパティをオフにするだけです)。
Point Instancerは高速ですが、すべてのインスタンスのTransformは、Point Instancerプリミティブのアトリビュート配列として設定されます。昇格には、シーンの変更が含まれます。ポイントインスタンスは、主に存在するインスタンスの数に基づいて優先される必要があります。
Point Instancer
OpenUSDのドキュメント(英語)
USDには独自のポイントインスタンサーモデルが付属しています。これは非常に強力で、ジオメトリ、ボリューム、他の階層のインスタンス化、さらには他のポイントインスタンサーのインスタンス化にも使用できます。
Point Instancerスキーマは、膨大な量のジオメトリをできるだけ速く描画するように設計されています。主に多くのデブリをシミュレーションしてアニメーション化する必要があるFXアーティスト向けに設計および実装されました。Point Instancer LOPは、ポイント上でHoudiniの標準インスタンスアトリビュートを使用して、各インスタンスのTransformを調整します。
ポイント間でインスタンス化された各モデルは「プロトタイプ」と呼ばれ、Point Instancerプリミイティブは任意の数のプロトタイプを割り当てることができます。インスタンスごとのバリエーションをPoint Instancerプリミティブのアトリビュートで表現できない場合、異なるプロトタイプを使用する必要があります。プロトタイプにはアニメーション化されたジオメトリを含めることができ、Point Instancerプリミティブは他のPoint Instancerのプロトタイプにすることができます。
この手法の欠点は、Point Instancerがパイプラインに対処するための柔軟性がはるかに低いことです。個々のPoint Instancerインスタンスのペアレント化には追加の作業が必要であり、個々のインスタンスへの変更はスキーマから利用可能なアトリビュートに制限されます。また、任意の数の一意のプロトタイプを使用できますが、プロトタイプが多すぎると、Point Instancersを使用することによるパフォーマンス上の利点が相殺される可能性があります。
Point InstancersおよびNative Instancesを便利に使用するために、いくつかのLOPノードが用意されています。
- Instance Variation
VEXスニペットを使用してインスタンスのさまざまなプロパティをランダマイズします。 - Instance Retime
プロトタイプの時間を変更します。 - Instance Extract
インスタンスの抽出と昇格をします。 - Instance Transform
個々のインスタンスを手動で編集します。
それでは本文に移ります。
念のため、作業中には頻繁にファイルを保存するようにして下さい。
アセンブリ(組み立て)
- Houdiniで新規シーンを作成します。
- DesktopをSolarisに変更します。
DesktopにSolarisがない場合は、Scene Graph Treeペインを作成してください。 - /stage 階層に移動します。
この階層でSOPのようにノードチェーンを構成することでインスタンスを作成していきます。 - Reference LOPを作成し、名前をBookShelves に変更します。
Primitive Passを /$OS/LeftShelf に設定します。
Reference Fileを $HIP/LOPS_DEMO_FILES/Library/Assets/BookShelves/BookShelfAsset.usd に設定します。
リファレンスはプリミティブをLOPネットワークにロードする最も一般的な方法のひとつです。
- Reference LOPの下に、Duplicate LOP を追加します。
※これ以降のノードはパラメータの設定が終わるまでエラーを出力する可能性があります。
Separate Source and Destination Primitives にチェックを入れます。
Modify Source Primitiveを Source primitives are first duplicates に設定します。
Dustination Primitivesを /BookShelves/ に設定します。
Duplicate Nameを RightShelf に設定します。
Translateを 1.5,0,0 に設定します。
- duplicate LOPの下に、Set Variant LOPを追加します。
Primitivesを /BookShelves/RightShelf に設定します。
Variant Setを model に設定します。
Variant Nameを BookShelf2 に設定します。
※各パラメータ値ではキャメルケースが利用されています。Houdiniでは大文字と小文字は区別されるので、例えば「BookShelf」と「bookshelf」は異なるものである事に注意して下さい。
- Set Variant LOPの下に、Null LOPを追加し、名前をSHELVESとします。
次にStamp Managerを使用して棚にあるインスタンスを配置します。
- 何も配線しない状態で Stage Manager LOP を作成します。
パラメータペインで緑色の「+」記号をクリックしてフォルダを追加し、名前をPotsに変更します。
Stage Managerのパラメータペイン左上のOpen the file browserボタンをクリックし、LOPS_DEMO_FILES/Library/Assets/ClayJars(およびHerbs)フォルダ内の、ClaysJarsAsset.usdおよびHerbJarsAsset.usdをPotsフォルダの下にドラッグアンドドロップします。
- 次に、これらのjarを複製し、それぞれに固有のバリエーションを割りてます。最終的に7種類のjar(瓶)を作成します。
もっとも簡単な複製方法はStage Manager上の各プリミティブを右クリックして、Duplicate をクリックすることです。
ここではClaysJarsAssetを3回、HerbJarsAssetを2回複製します。
- プリミティブを複製したら、それぞれに固有のバリアントを設定します。これは、Stage ManagerのVariants列の犬のボタンをクリックして選択することができます。
今回は1個、1個別のバリアントを設定します。
全ての処理が終了すると、Stage Managerは以下のようになります。
これでインスタンス化するモデルが揃いましたので、コレクションを作成します。
- Stage Manager LOPの下に、Collection LOPを追加します。
Collection Nameを StuffToBeInstanced に設定します。
Primitive Patternを /Pods/* に設定します。
- Instancer LOPを作成します。第1入力に、以前作成したSHELVESを、第2入力にCollection LOPを接続します。
Primitive Pathを /BookShelves/Contents に設定します。
Primitive Kindを Group に設定します。
Prototype Sourceを Second Inputs に設定します。
Prototype Primitivesを %StuffToBeInstancedに設定します。
Enterキーを押して、Instancer LOPの中に入ります。
Instancer LOP の中の設定
次に、瓶をインスタンス化するポイントクラウドを作成します。 これは様々な方法で実現が可能ですが、このチュートリアルでは、そのひとつについて紹介します。
- LOP Import SOP を作成します。※Instancer LOPの中はSOPコンテキストになります。
LOP Pathを /stage/SHELVES に設定します。
Primitivesを * に設定します。
- Stage Manager LOPの下に、Unpack USD SOPを追加します。
Geometry Typeを Polygons に設定します。
次に、瓶をインスタンス化する領域を保存して、その上にいくつかのポイントを散布できるようにします。
そのためのグループを作成する方法をひとつご紹介します。
- ビューポートで、スペースキー+ 2キーを押してトップビューに移動します。 Wキーを押してワイヤフレームモードを切り替えます。
- シーンビュー上でtabメニューを開き、”Gro” と入力してGroupツールを起動します。
- 4キーを押して、プリミティブ選択モードに移行します。
以下の画像の様に選択を行い、右クリック->Accept Selectionで選択を確定させます。
これにより、Unpack USD SOPの下に自動的にGroup SOPが作成されます。
- Group SOPの下に、Blast SOPを追加し、Group1以外のコンポーネントを削除します。
この時点ではまだ、棚の上部と下部の両方の面があることがわかります。次に底面を取り除きます。
- Blast SOPの下に、Delete SOPを追加し、法線方向を利用して底面を削除します。
NormalタブのEnableにチェックを入れ、Directionを 0,-1,0 に設定します。
Spread Angle を 50 に設定します。
- Delete SOPの下に、Scatter SOPを追加します。
Force Total Count を 300 に設定します。
Relax Iterations を 100 に設定します。
Scale Radii by を 2 に設定します。
Max Relax Radius を 14 に設定します。
Primvarの作成
次に、瓶のbase color、specular roughness、albedo をオーバーライドする為のランダムな数値を作成して、ランダムな特性を与えます。 これはHoudiniで言うところのジオメトリアトリビュートになり、USDでは、これをPrimvarと呼びます。
- Delete SOPの下に、Attribute Randomize SOP を追加し、名前をbasecolor とします。
Attribute Name を $OS に設定します。
これにより、X、Y、およびZコンポーネントに0〜1のランダムな値を持つ「basecolor」というアトリビュートが作成されます。つまり、これらのプリミティブにシェーダーがアタッチされていて、そのシェーダに「basecolor」というパラメータがある場合、この値でオーバーライドされます。ノード名に$OSを使用すると、SOPをコピーし、SOPの名前を変更することで、新しい名前のアトリビュートを作成できるようになります。
- basecolor SOPをコピーしてbasecolor SOPの下に繋ぎ、名前をrough に変更します。
Dimensions を 1 に設定します。
Min Value を 0.5 に設定します。
- rough SOPをコピーしてrough SOPの下に繋ぎ、名前をalbedomult に変更します。
Min Value を 0.2 に設定します。
Dimensionsパラメータはアトリビュートの次元数を設定するパラメータですので、この値が1の場合、アトリビュートの値はfloatになります。これをデフォルトの3のままにすると、アトリビュートはベクトルになります。ただし今回の場合は、ベクトルのままでもシェーダはroughおよびalbedomultがfloat型であることを予測して、自動的に変換を行うため、問題はありません。
- albedomult SOPの下に、Output SOP を追加し、名前をOUT とします。
Tips
シェーダ内のパラメータのラベルにカーソルを合わせると、上記のシェーダアトリビュートの名前を確認できます。
- OUTノードのNode Infoを確認します。ポイントのアトリビュートがbasecolor、rough、およびalbedomultであることがわかります。チェーンの最後のSOPで右クリックしSpreadsheetをクリックすると、basecolor、rough、およびalbedomultの値が、設定した範囲内でのランダムな値で設定されている事が確認できます。
- Uキーを押して/stage階層に戻ります。
仕上げとUSDファイルの保存
棚のScatterを散布した位置に、様々なバリアントを持った瓶がコピーされました。 ここからは、Instancer LOPのSeedパラメータを使用して、適切な分布を取得します。
- Instancer LOP上で以下の設定を行います。
Point Attributes to Copy を basecolor albedomult rough に設定します。
※USDでは、ポイント間でインスタンス化された各モデルのことをプロトタイプ(Prototype)と呼びます。Tips
現在、すべての瓶(jar,pot)は同じ方向を向いています。これは、Nアトリビュートとupアトリビュート(またはorientアトリビュート)を変更することで違う方向を向かせることが可能です。
これをアセットとして保存する前に、もう1つやるべきことがあります。Scene Graph Treeを確認すると、「Contents」グループにKindが未定義のプリミティブ「Prototypes」があることがわかります。これを修正します。
- Configure Primitive LOPを追加します。
Primitives を /BookShelves/Contents/Prototypes /BookShelves/Contents/Prototypes/* に設定します。
Kind にチェックを入れ、 Groupに設定します。
これにより、「Prototypes」がGroupとして定義されます。
- USD ROP LOPを追加します。
Output File を $HIP/tutorials/PackedShelves.usd に設定します。
Layer Metadata下のDefault Primitive を /BookShelves に設定します。
[Save to Disc]ボタンをクリックし、ファイルの保存を行います。
- Configure Primitive LOPの下に、ライトを追加することで、レンダリング結果をシーンビュー上でプレビューすることも可能です。
Karmaによるプレビューを行うには、ビューポートのドロップダウンから[Karma]を選択します。(デフォルトは[Persp]です)
これで、次のチュートリアルに進む準備ができました。アセットの結果を確認するには、Reference LOPを使用して、
先ほど保存したUSDファイル($HIP/tutorials/PackedShelves.usd)と
デモファイル($HIP/LOPS_DEMO_FILES/Library/Assets/InstancedShelves/PackedShelves.usd)をロードします。
トラブルシューティング
USD ROPからUSDファイルを保存しようとすると、次のようなエラーが表示されます。
Warning: Upgrading crate file </path/to/file/PackedShelves.usd> from version 0.7.0 to 0.8.0: A SdfPayloadListOp value was detected which requires crate version 0.8.0.
ほとんどの場合、この警告は無視して問題ありません。 「crate」とは、USDバイナリファイル形式の名前です。 デフォルトでは、新しいUSDファイルは特定のバージョン(この記事の執筆時点では “0.7”形式)で書き込まれます。
ただし、Houdiniで利用される一部のUSD構造は「0.7」形式で表現できないため、ファイルを「0.8」形式で書き込むことを警告しています。つまり、古いバージョンのUSDを使用するアプリケーションは、生成したファイルを読み取れない可能性があります。
ですので、Houdiniのみを使用しているユーザーには問題のない内容となります。