まとめ
繰り返しジオメトリを含むシーンでは、インスタンス化を使用することでメモリ使用量を削減し、シーングラフのクックパフォーマンスを向上させることができます。一般的に、インスタンス化は、ジオメトリが複数のコピー間で同一であり、必要な変更が変換のみである場合に有効です。この記事では、「インスタンス配列」ロケーションを使用したインスタンス化の方法について説明し、ポイントクラウドのポイントにジオメトリをインスタンス化する例を示します。
利用可能なその他のインスタンス化アプローチの概要については、 Katana開発者ガイドの「インスタンス化」セクションをお読みください。
ポイント クラウドのインスタンス化に関する以下のセクションを説明するサンプル プロジェクトについては、次のKatanaプロジェクト ファイル「 instanceArray_arnold_material.katana 」を参照してください。
インスタンス配列
以下のセクションでは、配列のインスタンス化について簡単に説明します。インスタンス化に関するより詳細な説明については、 Rendermanドキュメントをご覧ください。RenderMan 26 Docs - Instancing in Katana 、インスタンス化の入門として、3種類のインスタンス化方法すべてを設定する方法を紹介しています。
インスタンス配列では、インスタンスの位置は、単一の位置(「インスタンス配列」タイプ)の属性を介して、1つまたは複数のインスタンスソースにマッピングされます。インスタンス配列は階層型インスタンス化に似ていますが、複数のインスタンスソースを簡単に設定できるという利点があります。唯一の欠点は、インスタンスごとにマテリアルを変更できないことです。
インスタンス配列の場所には、 geometry.instanceSourceと少なくとも1つの変換属性が含まれている必要があります。instanceSourceに単一のパスのみが含まれている場合、 geometry.instanceIndexは省略可能です。この場合、そのインスタンスソースはインスタンス配列内のすべてのインスタンスに使用されます。
ジオメトリ.インスタンスソース |
1 つ以上のインスタンス ソースのシーン グラフの場所のパスを含む文字列または文字列配列属性 |
ジオメトリ.インスタンスインデックス |
必要なインスタンス数と同じ要素数を持つ配列属性。この配列に格納される値は、 geometry.instanceSource配列における目的のインスタンスソースのインデックスを示します。つまり、 instanceIndexはインスタンスインデックスからインスタンスソースインデックスへのマッピングを構成します。 |
geometry.instanceMatrix geometry.instanceTranslate geometry.instanceRotateX geometry.instanceRotateY |
これらの属性はそれぞれ、インスタンスごとの変換のフラットな配列です。各属性の意味は従来の変換属性と同じで、アニメーションをサポートするためにマルチサンプリングが可能です。 注意: RenderMan は、geometry.instanceMatrix 属性の使用のみをサポートします。 |
インスタンス化属性規則の詳細については、 Katana開発者ガイド: インスタンス化」を参照してください。
ポイントクラウドへの配列インスタンス化
インスタンス配列には、インスタンスを1つの場所のみで保持できるという利点があります。これにより、数千のインスタンス場所があるシーンでもシーングラフのサイズを小さく抑えることができます。インスタンス配列は、インスタンスソースの場所を含むgeometry.instanceSource属性を読み取ってインスタンス配列を生成します。複数のインスタンスソースを参照するには、インスタンスソースのインデックス配列(インスタンスごとに1つ)を含むgeometry.indexArray属性を使用します。以下は、ポイントクラウド内のポイントにジオメトリをインスタンス化するためのインスタンス配列を生成する手順です。
1. ポイントクラウドオブジェクトを作成またはインポートし、AttributeSetノードを使用して、その位置のtype属性をpointcloudに設定します。ポイントクラウドは、PrimitiveCreateノードで生成されたものなど、 geometry.point.P属性を持つ任意のジオメトリです。
すると、シーン グラフでポイント クラウドの場所タイプが変更されたことがわかります。
2. 次に、インスタンスソースとして使用したいジオメトリを作成またはインポートします。次に、別のAttributeSetノードを使用して、その親ロケーションのtype属性をインスタンスソースに設定します。
例えば、ジオメトリが/root/world/geo/src/teapotにある場合、インスタンスソースの場所は/root/world/geo/srcになります。後でこの場所にオブジェクトを追加して、複数のインスタンスソースを使用することもできます。
すると、シーン グラフでインスタンス ソースの場所タイプが変更されたことが表示されます。
3. 2 つのネットワークを結合すると、次のようになります。
4. Mergeノードの下流にOpScriptノードを作成し、 applyWhereパラメータをat specific locationに変更します。OpScriptノードのパラメータ一覧の先頭に、新しいlocationパラメータが表示されます。locationパラメータの値によって、シーングラフ内のどこにインスタンス配列が生成されるかが決まります。この例では、/root/world/geo/instancesを使用しています。
5. OpScriptノードで、 user.pointCloudLocation文字列パラメータを作成し、ポイントクラウドのシーングラフの場所パスを設定します。次に、ウィジェットタイプをScene Graph Locationsとしてuser.instanceSourceLocations文字列配列パラメータを作成し、インスタンスソースのシーングラフの場所パスを配列の値として追加します。
ユーザー パラメータを作成し、ウィジェット タイプを変更する手順については、「 Katanaユーザー ガイド: ユーザー パラメータの追加」を参照してください。
6. 次の OpScript Lua コードは、 Renderman Docs: Instancingにある Pixar の例から抜粋したもので、ポイント クラウドとインスタンス ソースの場所に基づいてインスタンス配列を作成します。
このコードを OpScript ノードのスクリプトパラメータにコピーして、ポイント クラウドの各ポイントにインスタンスが配置されたインスタンス配列を生成します。
-- Read the op arguments
local instanceSourceLocations = Interface.GetOpArg("user.instanceSourceLocations")
local pointCloudLocation = Interface.GetOpArg("user.pointCloudLocation"):getValue()
-- Read the point cloud's points
local pointAttr = Interface.GetAttr("geometry.point.P", pointCloudLocation)
local points = pointAttr :getNearestSample(Interface.GetCurrentTime())
-- Create a single location which will generate an array of instances
-- Set type for this location to 'instance array'
Interface.SetAttr( 'type' , StringAttribute( 'instance array' ))
-- This instance array location must point to the instance source locations
-- through the attribute 'geometry.instanceSource'
Interface.SetAttr( 'geometry.instanceSource' , instanceSourceLocations)
-- The indexArray attribute determines which instance source each instance location represents
local indexArray = {}
-- for each instance create an instance index
for i= 0 ,#points/ 3-1 do
-- For this example, the instances are arbitrarily assigned to an
-- instance source
-- a more stable apporach would be to use an arbitrary attribute
-- on the point cloud to assign an instance source
indexArray[#indexArray +1 ] = i%instanceSourceLocations:getNumberOfTuples()
end
-- Set index for instance array element
Interface.SetAttr( 'geometry.instanceIndex' , IntAttribute(indexArray, 1 ))
-- geometry.instanceMatrix
-- Get the transforms from the points
local numTimeSamples = pointAttr:getNumberOfTimeSamples()
local matrixArrayMap = {}
-- to get motion blur on the instances, create an instanceMatrix at each
-- time sample available from the point cloud points attribute
for idx=0,numTimeSamples -1 do
local sampleTime = pointAttr:getSampleTime(idx)
local points = pointAttr:getNearestSample(sampleTime)
-- each instance in array has its own matrix
local matrixArray = {}
local workMatrix = Imath.M44d():toTable()
-- for each instance build a matrix with a mocked up transformation
for i=0,#points/ 3-1 do
-- grab the points that represent this instance
x = points[ 3 *i +1 ]
y = points[ 3 *i +2 ]
z = points[ 3 *i +3 ]
-- set the translate of the matrix to the points in the point cloud
workMatrix[ 13 ] = x
workMatrix[ 14 ] = y
workMatrix[ 15 ] = z
for j = 1 , 16 do
matrixArray[#matrixArray +1 ]=workMatrix[j]
end
end
matrixArrayMap[sampleTime] = matrixArray
end
Interface.SetAttr('geometry.instanceMatrix', DoubleAttribute (matrixArrayMap, #matrixArrayMap))
上記のOpScriptは、インスタンス配列のgeometry.instanceSource属性を、 user.instanceSourceLocationsユーザーパラメータで設定されたインスタンスソースの位置に設定します。さらに、インスタンス配列のgeometry.instanceIndex属性を、インスタンスソースを交互に表示するように設定しています。最後に、インスタンス配列のgeometry.instanceMatrix属性に、点群内の各点からの移動情報を設定します。
7. インスタンスが作成されたので、ポイント クラウドは不要になったため、Prune ノードを使用してシーンから削除できます。
これで、インスタンス配列をレンダリングして表示できるようになりました。
完成したシーンはここからダウンロードできます: instanceArray.katana
インスタンスごとに割り当てられたマテリアルを変更するためのインスタンス配列の回避策
他のインスタンス化手法とは異なり、インスタンス配列にはインスタンスごとにマテリアルを直接変更するメカニズムはありません。ただし、インスタンスソースロケーションを異なるマテリアルで使用することで、インスタンスごとに異なるマテリアルを使用できます。インスタンス配列を使用する利点は、すべてのインスタンスが1つのシーングラフロケーションに含まれることです。ただし、これはまた、個々のインスタンスがビューアやシーングラフに表示されず、シーンのレンダリングでのみ表示されるため、特定のインスタンスを見つけることがほぼ不可能であることを意味します。
インスタンス配列を生成するには、上記の「インスタンス配列からポイントクラウドへ」セクションを参照してください。インスタンス配列を作成したら、各インスタンスソースのマテリアルを変更することで、インスタンスのバッチごとにマテリアルを変更できます。インスタンスソースのマテリアルを変更するには、MaterialAssignノードを使用します。マテリアルの割り当ては、そのインスタンスソースを使用する各インスタンスの場所に反映されます。MaterialAssignノードを作成し、インスタンスソースとして選択したシーングラフの場所にマテリアルを割り当てるだけです。
さらに詳しく
インスタンス化の概要については、下記の最初のリソースリンクをご覧ください。その他のリソースでは、各インスタンス化手法における高度なインスタンス化のトピックについて詳しく説明されています。
- Katana開発者ガイド: インスタンス化
- Q100508: 階層型(インスタンスソース)インスタンス化によるシーングラフのクックパフォーマンスの向上
- Q100517: リーフレベル(インスタンスID)インスタンス化によるシーングラフのクックパフォーマンスの向上
- Renderman ドキュメント: RenderMan 26 ドキュメント - Katanaでのインスタンス化
添付ファイル
私たちはそれを聞いて申し訳ございません
理由をお聞かせください