Q100508: 階層 (インスタンス ソース) インスタンス化によるシーン グラフ クックのパフォーマンスの向上

フォローする

まとめ

ジオメトリが繰り返されるシーンでは、インスタンス化を使用すると、メモリ フットプリントが削減され、シーン グラフ クックのパフォーマンスが向上します。通常、インスタンス化は、ジオメトリが多くのコピー間で同じであり、必要な変更が変換だけである場合にうまく機能します。この記事では、「階層インスタンス化」と呼ばれるインスタンス ソースを使用したインスタンス化の方法について説明し、それを使用してジオメトリを点群の点にインスタンス化する方法の例を示します。

他の利用可能なインスタンス化アプローチの概要については、 Katana開発者ガイドの次のセクション「インスタンス化」を参照してください。

点群インスタンス化に関する以下のセクションを示すサンプル プロジェクトについては、 Katanaプロジェクト ファイル「 PointcloudInstancingAndmaterialAssign_Arnold.katana 」を参照してください。

階層インスタンス化の概要

次のセクションでは、階層インスタンス化の概要を説明します。インスタンス化のより詳細な説明については、 Renderman ドキュメント: RenderMan 25 Docs - Instancing in Katanaで、インスタンス化の入門として 3 つのインスタンス化メソッドすべてを設定する方法が説明されています。

階層インスタンス化では、シーン グラフの位置の階層全体をインスタンス化できます。インスタンスの場所は、インスタンスを含むシーン グラフの場所であり、インスタンスは、シーン グラフのソースの場所の下にあるジオメトリによって定義されます。インスタンス ソースは、シーン グラフの場所の type 属性を「インスタンス ソース」に設定することによって宣言されます。インスタンスの場所自体は、type 属性を「instance」に設定することで宣言されます。

インスタンスソースは、インスタンス化される階層の最上位の位置を表すグループ位置のtype 属性を「インスタンスソース」に設定することで宣言されます。

インスタンスの場所のタイプは「インスタンス」である必要があります。 geometry.instanceSource文字列属性をこれらの場所に設定し、インスタンス ソース シーン グラフの場所を指すようにする必要があります。

点群への階層インスタンス化

点群へのインスタンス化は、前のセクションで説明した単一のインスタンスの場所へのインスタンス化に似ています。違いは、「instance」タイプの複数の場所を使用する代わりに、インスタンスの場所が、インスタンス ソースを指すgeometry.instanceSource文字列属性を持つ「pointcloud」タイプの 1 つの場所だけであることです。次の手順では、この設定について説明します。

1. Alembic_In を使用してインスタンス ソースをインポートし、シーン グラフ内のジオメトリの親の場所のタイプを「インスタンス ソース」として設定します。

2. Alembic_In を使用して Alembic 点群をインポートし、インスタンス ソースを指すようにgeometry.instanceSource属性を設定します。

この方法を使用すると、シーン内の個々のインスタンスをあまり細かく制御できないことに注意してください。たとえば、シーン グラフの位置は点群内の各点に対して生成されないため、個々のインスタンスに異なるマテリアルを割り当てることは容易ではありません。ただし、この方法を使用すると、同じマテリアルのシェーダ プロパティを任意の属性を持つ個々のインスタンスごとに変更できます。さらに、点群をスケーリングするとすべてのインスタンスもスケーリングされるため、個々のインスタンスの変換は簡単に変更できません。マテリアルのバリエーションや、変換をより詳細に制御する必要がある場合は、よりカスタマイズ可能な OpScript アプローチについて以下のセクションをお読みください。

OpScript Luaを使用した点群への階層インスタンス化

点群への階層インスタンス化により、点群内の各点に対して場所の階層全体をインスタンス化できます。 OpScript を使用して、シーン グラフ内で点群内の各点のインスタンスの位置を生成すると、各インスタンスに異なるマテリアルを個別に割り当てることができ、インスタンスの位置の変換をより詳細に制御できるという利点があります。潜在的な欠点は、特にインスタンスが数千ある場合、シーン グラフが少し扱いにくいことです。以下は、点群への階層インスタンス化を実現する手順です。

1. Alembic_In ノードを使用して点群とインスタンス ソースをインポートします。次に、インスタンス ソースのtype属性を「インスタンス ソース」に設定します。

2. OpScript ノードを作成し、そのlocationパラメーターを、インスタンスを生成する必要があるシーン グラフの場所 (例: "/root/world/geo/derivedassets") に設定します。

3. OpScript ノードでuser.instanceSourceLocationパラメータを作成し、それをインスタンス ソースのシーン グラフの場所に設定し、 user.pointCloudLocationを設定します。 パラメータを点群のシーン グラフの位置に設定します。ユーザー パラメータの作成手順については、 Katanaユーザー ガイド: ユーザー パラメータの追加」を参照してください。

4. 次に、次のコードを OpScript ノードのスクリプトパラメータにコピーして、各ポイントのインスタンスの場所を生成します。

 -- Read op arguments
local instanceSourceLocation = Interface.GetOpArg( "user.instanceSourceLocation" ):getValue()
local pointCloudLocation = Interface.GetOpArg( "user.pointCloudLocation" ):getValue()

if Interface.AtRoot() then
 
-- Read the point cloud
 
local points = Interface.GetAttr( "geometry.point.P" , pointCloudLocation):getNearestSample(Interface.GetCurrentTime())

 
-- Loop over points
 
local x, y, z
 
local gb = GroupBuilder()
 
for i= 0 , #points/ 3 - 1 do
     x = points[
3 *i+ 1 ]
     y = points[
3 *i+ 2 ]
     z = points[
3 *i+ 3 ]

     
-- Build op arguments for the child location
     gb:update(Interface.GetOpArg())
     gb:set(
"childAttrs" , Interface.GetAttr( "" , instanceSourceLocation))
     gb:set(
"childAttrs.type" , StringAttribute( "instance" ))
     gb:set(
"childAttrs.geometry.instanceSource" , StringAttribute(instanceSourceLocation))
     gb:set(
"childAttrs.xform.interactive.translate" , DoubleAttribute({x, y, z}))

     
-- Create the child
     Interface.CreateChild(
         
string . format ( "child%04d" , i),
         Interface.GetOpType(),
         gb:build())
 
end
else
 
local childAttrs = Interface.GetOpArg( "childAttrs" )
 
for i= 0 , childAttrs:getNumberOfChildren() -1 do
     Interface.SetAttr(childAttrs:getChildName(i), childAttrs:getChildByIndex(i))
 
end
end

上記の OpScript は、点群内の各点に対して「インスタンス」タイプの位置を作成し、各インスタンスの位置のgeometry.instanceSource属性をuser.instanceSourceLocationパラメータで指定されたインスタンス ソースに設定します

5. 最後に、Prune ノードまたは VisibilityAssign ノードを使用してシーン グラフから点群の位置を削除し、レンダリングから除外されます。 VisibilityAssign ノードを使用すると、ビューアにポイントが表示されたままになりますが、Prune ノードはビューアにインスタンスの表示を空のままにします。

マテリアル割り当てによるマテリアルバリエーション

すべてのインスタンスは割り当てられたマテリアルなどのインスタンス ソースのプロパティを継承するため、インスタンスごとにマテリアルを変更すると、追加の作業が発生する可能性があります。このセクションでは、インスタンス化のパフォーマンス上の利点を維持しながら、インスタンスごとにマテリアルとシェーダーを変更する方法について説明します。

OpScript でリーフレベルの階層インスタンスを使用して点群上の各点のインスタンスの場所を作成すると、インスタンスの場所ごとにマテリアルを割り当てることができるという利点があります。

インスタンスの場所を生成した後、各インスタンスの場所ごとにマテリアルを変更できます。特定のインスタンスを識別するには、シーン グラフでインスタンスの場所を展開し、ビューアで目的のインスタンスを選択するだけです。提供されているサンプル プロジェクトでは、インスタンスの場所は /root/world/geo/derivedassets の場所の下にあります。

次に、マテリアルをマテリアル割り当てノードを使用するか、マテリアルの場所を指すインスタンスの場所にマテリアル割り当て属性を設定することによって、目的の場所にマテリアルを割り当てることができます。

参考文献

インスタンス化の概要については、以下の最初のリソース リンクを参照してください。以下の他のリソースでは、各インスタンス化方法に関するその他の高度なインスタンス化トピックについて詳しく説明します。

添付ファイル

私たちはそれを聞いて申し訳ございません

理由をお聞かせください