まとめ
ジオメトリが繰り返されるシーンでは、インスタンス化を使用すると、メモリ フットプリントが削減され、シーン グラフ クックのパフォーマンスが向上します。通常、インスタンス化は、ジオメトリが多くのコピー間で同じであり、必要な変更が変換だけである場合にうまく機能します。この記事では、「インスタンス配列」の場所を使用してインスタンス化する方法について説明し、それを使用してジオメトリを点群の点にインスタンス化する方法の例を示します。
他の利用可能なインスタンス化アプローチの概要については、 Katana開発者ガイドの次のセクション「インスタンス化」を参照してください。
点群インスタンス化に関する以下のセクションを示すサンプル プロジェクトについては、次のKatanaプロジェクト ファイル「 instanceArray_arnold_material.katana 」を参照してください。
インスタンス配列
次のセクションでは、配列のインスタンス化の概要を説明します。インスタンス化のより詳細な説明については、 Renderman ドキュメント: RenderMan 25 Docs - Instancing in Katanaで、インスタンス化の入門として 3 つのインスタンス化メソッドすべてを設定する方法が説明されています。
インスタンス配列では、インスタンスの場所は、「インスタンス配列」タイプの単一の場所の属性を介して 1 つ以上のインスタンス ソースにマッピングされます。インスタンス配列は階層インスタンス化に似ていますが、複数のインスタンス ソースを簡単に設定できるという利点もあります。欠点の 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. マージの下流で、OpScript ノードを作成し、そのapplyWhereパラメータを特定の場所に変更します。 OpScript ノードのパラメータの上部に新しい場所パラメータが表示されます。 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 25 ドキュメント - Katanaでのインスタンス化
添付ファイル
私たちはそれを聞いて申し訳ございません
理由をお聞かせください