まとめ
繰り返しジオメトリを含むシーンでは、インスタンス化を使用することでメモリ使用量を削減し、シーングラフのクックパフォーマンスを向上させることができます。一般的に、インスタンス化は、ジオメトリが複数のコピー間で同一であり、必要な変更がトランスフォームのみである場合に有効です。この記事では、「階層的インスタンス化」と呼ばれるインスタンスソースを用いたインスタンス化の手法について説明し、ポイントクラウドのポイントにジオメトリをインスタンス化する例を示します。
利用可能なその他のインスタンス化アプローチの概要については、 Katana開発者ガイドの「インスタンス化」セクションをお読みください。
ポイント クラウドのインスタンス化に関する以下のセクションを説明するサンプル プロジェクトについては、 Katanaプロジェクト ファイルPointcloudInstancingAndMaterialAssign_Arnold.katanaを参照してください。
詳細情報
階層的インスタンス化の概要
以下のセクションでは、階層型インスタンス化の概要を簡単に説明します。インスタンス化に関するより詳細な説明については、RenderManのドキュメント「RenderMan 26 Docs - Instancing in Katanaをご覧ください。インスタンス化の入門として、3種類のインスタンス化手法の設定方法を全て紹介しています。
階層的インスタンス化では、シーングラフのロケーションの階層全体をインスタンス化できます。インスタンスロケーションとは、インスタンスが含まれるシーングラフのロケーションであり、シーングラフ内のソースロケーションのジオメトリによって定義されます。インスタンスソースは、シーングラフのロケーションのtype属性を「instance source」に設定することで宣言されます。インスタンスロケーション自体は、type属性を「instance」に設定することで宣言されます。
インスタンス ソースは、インスタンス化される階層の最上位レベルの場所を表すグループ場所のtype 属性を「インスタンス ソース」に設定することによって宣言されます。
インスタンスの場所は「instance」型である必要があります。これらの場所には、インスタンスのソースシーングラフの場所を指すgeometry.instanceSource文字列属性を設定する必要があります。
ポイントクラウドへの階層的インスタンス化
ポイントクラウドへのインスタンス化は、前のセクションで説明した単一のインスタンスロケーションへのインスタンス化と似ています。違いは、「instance」タイプのロケーションを複数使用する代わりに、インスタンスロケーションが「pointcloud」タイプのロケーション1つだけであり、 geometry.instanceSource文字列属性でインスタンスソースを指す点です。この設定手順は以下のとおりです。
1. Alembic_In を使用してインスタンス ソースをインポートし、シーン グラフ内のジオメトリの親の位置のタイプをinstance sourceとして設定します。
2. Alembic_In を使用して Alembic ポイント クラウドをインポートし、 geometry.instanceSource属性をインスタンス ソースを指すように設定します。
この方法を使用すると、シーン内の個々のインスタンスに対するきめ細かな制御が難しくなることに注意してください。例えば、ポイントクラウド内の各ポイントに対してシーングラフの位置が生成されないため、個々のインスタンスに異なるマテリアルを割り当てることは容易ではありません。ただし、この方法を使用すれば、任意の属性を持つ個々のインスタンスに対して、同じマテリアルのシェーダープロパティを変更することができます。さらに、ポイントクラウドをスケーリングすると、すべてのインスタンスもスケーリングされるため、個々のインスタンスの変換を簡単に変更することはできません。マテリアルのバリエーションや、変換に対するより詳細な制御が必要な場合は、以下のセクションで、よりカスタマイズ可能なOpScriptアプローチについてご確認ください。
OpScript Lua を使用したポイントクラウドへの階層的インスタンス化
ポイントクラウドへの階層的インスタンス化により、ポイントクラウド内の各ポイントに対して、階層構造全体にわたる位置をインスタンス化できます。OpScriptを使用してポイントクラウド内の各ポイントのシーングラフ内でインスタンス位置を生成すると、各インスタンスに個別に異なるマテリアルを割り当てることができ、インスタンス位置の変換をより細かく制御できるという利点があります。潜在的な欠点は、特にインスタンスが数千個ある場合、シーングラフがやや扱いにくくなることです。ポイントクラウドへの階層的インスタンス化を実現する手順は次のとおりです。
1. Alembic_Inノードを使用して、ポイントクラウドとインスタンスソースをインポートします。次に、インスタンスソースのtype属性を「instance source」に設定します。
2. OpScript ノードを作成し、その場所パラメータをインスタンスを生成するシーングラフの場所(例:「/root/world/geo/derivedassets」)に設定します。
3. OpScriptノードでuser.instanceSourceLocationパラメータを作成し、インスタンスソースのシーングラフの場所に設定し、 user.pointCloudLocationを設定します。 パラメータをポイントクラウドのシーングラフの位置に追加します。ユーザーパラメータの作成手順については、 Katanaユーザーガイド「ユーザーパラメータの追加」を参照してください。
4. 次に、次のコードを OpScript ノードのscriptパラメータにコピーして、各ポイントのインスタンスの場所を生成します。
-- 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 は、ポイント クラウド内の各ポイントに対して「instance」タイプの場所を作成し、各インスタンスの場所のgeometry.instanceSource属性を、 user.instanceSourceLocationパラメータで指定されたインスタンス ソースに設定します。
5. 最後に、PruneノードまたはVisibilityAssignノードを使用して、ポイントクラウドの位置をシーングラフから削除し、レンダリングから除外します。VisibilityAssignノードを使用すると、ポイントはビューアで引き続き表示されますが、Pruneノードを使用すると、インスタンスの表示がビューアに表示されなくなります。
マテリアル割り当てによるマテリアルバリエーション
インスタンスごとにマテリアルを変更すると、割り当てられたマテリアルなど、インスタンスソースのプロパティがすべてのインスタンスに継承されるため、余分な作業が発生する可能性があります。このセクションでは、インスタンス化によるパフォーマンス上のメリットを維持しながら、インスタンスごとにマテリアルとシェーダーを変更する方法について説明します。
OpScript によるリーフ レベルおよび階層的なインスタンス化を使用してポイント クラウド上の各ポイントのインスタンスの場所を作成すると、インスタンスの場所ごとにマテリアルを割り当てることができるという利点があります。
インスタンスの位置を生成したら、各インスタンスの位置ごとにマテリアルを変更できます。特定のインスタンスを識別するには、シーングラフでインスタンスの位置を展開し、ビューアで目的のインスタンスを選択するだけです。提供されているサンプルプロジェクトでは、インスタンスの位置は/root/world/geo/derivedassets location配下にあります。
その後、MaterialAssign ノードを使用するか、インスタンスの場所にmaterialAssign属性を設定してマテリアルの場所を指定することにより、マテリアルを目的の場所に割り当てることができます。
さらに詳しく
インスタンス化の概要については、下記の最初のリソースリンクをご覧ください。その他のリソースでは、各インスタンス化手法における高度なインスタンス化のトピックについて詳しく説明されています。
- Katana開発者ガイド: インスタンス化
- Q100517: リーフレベル(インスタンスID)インスタンス化によるシーングラフのクックパフォーマンスの向上
- Q100514: インスタンス配列インスタンス化によるシーングラフのクックパフォーマンスの向上
- Renderman ドキュメント: RenderMan 26 ドキュメント: Katanaでのインスタンス化
添付ファイル
私たちはそれを聞いて申し訳ございません
理由をお聞かせください