Q100517: Leaf 수준(인스턴스 ID) 인스턴싱을 통한 씬 그래프 쿠킹 성능 향상

요약

반복되는 지오메트리가 있는 모든 장면에서 인스턴싱을 사용하면 메모리 사용량을 줄이고 씬 그래프 쿡 성능을 향상시킬 수 있습니다. 일반적으로 인스턴싱은 여러 복사본에서 지오메트리가 동일하고 필요한 수정 사항이 변환뿐일 때 효과적입니다. 이 문서에서는 리프 수준 인스턴싱이라는 인스턴스 ID 속성을 사용하여 인스턴싱하는 방법을 설명하고, 이를 사용하여 포인트 클라우드의 포인트에 지오메트리를 인스턴스화하는 방법을 예시로 보여줍니다.

사용 가능한 다른 인스턴싱 접근 방식에 대한 개요는 Katana 개발자 가이드의 다음 섹션인 인스턴싱을 읽어보세요 .

아래 섹션 의 포인트 클라우드 인스턴싱을 설명하는 예제 프로젝트는 Katana 프로젝트 파일 " PointcloudInstancingAndMaterialAssign_Arnold.katana "를 참조하세요.

리프 수준 인스턴싱

다음 섹션에서는 리프 레벨 인스턴싱에 대한 간략한 개요를 제공합니다. 인스턴싱에 대한 자세한 내용은 RenderMan 문서를 참조하십시오. RenderMan 26 Docs - Katana 인스턴싱에서는 인스턴싱 소개를 위해 세 가지 인스턴싱 방법을 모두 설정하는 방법을 보여줍니다.

리프 수준 인스턴싱에서는 기존 반복 지오메트리를 인스턴스화할 수 있습니다. 즉, 장면에 이미 여러 번 존재하는 지오메트리는 한 번만 로드되고, 해당 지오메트리가 추가로 생성될 때마다 메모리에 있는 동일한 지오메트리 데이터 집합을 참조합니다. 인스턴싱이 필요한 반복 지오메트리가 있는 기존 Katana 프로젝트는 장면 그래프의 반복 지오메트리 위치에 instance.ID 속성을 추가하여 쉽게 수정할 수 있습니다. 하지만 단점은 자식이 없는 위치만 인스턴스화할 수 있다는 것입니다.

이를 위해 모든 동일한 위치에는 일치하는 instance.ID 속성이 있어야 합니다. 렌더러는 한 위치를 인스턴스 소스로 선택하고, 다른 모든 위치는 해당 위치의 인스턴스로 처리합니다.

참고: 지오메트리가 인스턴스 소스로 선택되는 방식을 이해하는 것은 모든 위치에 지오메트리가 필요한지, 아니면 장면 그래프에서 가장 높은 위치에만 지오메트리가 필요한지 결정하는 데 매우 중요합니다. 인스턴스 소스 선택 방식을 이해하려면 렌더러 설명서를 참조하세요.

포인트 클라우드에 대한 리프 수준 인스턴싱

인스턴스 ID를 사용하여 포인트 클라우드에 인스턴싱하려면 OpScript를 사용하여 인스턴스 소스를 포인트 클라우드의 각 포인트에 복사해야 합니다. 더 간단한 해결책은 OpScript 없이 계층적 인스턴싱을 사용하는 것입니다 ( Q100508: 계층적(인스턴스 소스) 인스턴싱을 사용하여 씬 그래프 쿡 성능 향상 참조). 하지만 두 인스턴싱 방법 모두에 OpScript를 사용하면 개별 인스턴스 위치가 뷰어에 표시되고 각 인스턴스에 개별적으로 재질을 할당할 수 있다는 이점이 있습니다 . 하지만 잠재적인 단점은 특히 인스턴스가 수천 개일 경우 씬 그래프가 다소 복잡해질 수 있다는 것입니다.

OpScript는 인스턴스 위치를 생성하고 포인트 클라우드의 각 포인트에 대한 instance.ID 속성을 복사합니다. OpScript에 의해 위치가 생성되면 렌더러는 한 위치를 지오메트리 소스로 선택하고, 다른 모든 위치는 해당 위치의 인스턴스로 처리됩니다 . 다음은 포인트 클라우드에 리프 수준 인스턴스화를 구현하는 단계입니다.

1. Alembic_In을 사용하여 포인트 클라우드와 인스턴스 소스를 가져옵니다. 그런 다음, instance.ID 라는 속성을 포인트 클라우드 위치의 임의의 문자열 값으로 설정합니다. 이 예에서는 instance.ID bob 으로 설정됩니다.

2. OpScript 노드를 생성하고 인스턴스가 생성될 장면 그래프 위치로 위치 매개변수를 설정합니다( 예: /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())

 
-- Read the instanceID
 
local instanceID = Interface.GetAttr( "instance.ID" , 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.geometry.instanceSource" , StringAttribute(instanceSourceLocation))
      gb:set(
"childAttrs.xform.interactive.translate" , DoubleAttribute({x, y, z}))
      gb:set(
"childAttrs.instance.ID" , StringAttribute(instanceID))

     
-- 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.ID 속성을 포함하여 포인트 클라우드의 각 포인트에 복사합니다.

5. 마지막으로, Prune 노드를 사용하여 씬 그래프에서 포인트 클라우드를 제거하여 렌더링에서 제외합니다. 이 단계는 렌더러가 포인트 클라우드를 인스턴스 소스로 선택하지 않도록 하기 위해 필요합니다.

재료 할당을 통한 재료 변형

인스턴스별로 머티리얼을 수정하면 모든 인스턴스가 머티리얼과 같은 인스턴스 소스의 속성을 상속하므로 추가 작업이 발생할 수 있습니다. 이 섹션에서는 인스턴스화의 성능 이점을 유지하면서 인스턴스별로 머티리얼과 셰이더를 변경하는 방법을 설명합니다.

OpScript를 사용하여 리프 수준 및 계층적 인스턴싱을 사용하여 포인트 클라우드의 각 포인트에 대한 인스턴스 위치를 생성하면 인스턴스 위치별로 재료를 할당할 수 있다는 이점이 있습니다.

인스턴스 위치를 생성한 후, 각 인스턴스의 위치별로 재료를 변경할 수 있습니다. 특정 인스턴스를 식별하는 것은 씬 그래프에서 인스턴스 위치를 확장하고 뷰어에서 원하는 인스턴스를 선택하는 것만큼 간단합니다. 제공된 예제 프로젝트에서 인스턴스 위치는 /root/world/geo/derivedassets 위치 아래에서 찾을 수 있습니다.

그런 다음 MaterialAssign 노드를 사용하거나 인스턴스 위치에 materialAssign 속성을 설정하여 재료 위치를 가리키면서 재료를 원하는 위치에 할당할 수 있습니다.

추가 읽기
인스턴싱 개요는 아래 첫 번째 리소스 링크를 참조하세요. 아래의 다른 리소스에서는 각 인스턴싱 방법과 관련된 고급 인스턴싱 주제에 대해 자세히 설명합니다.

첨부 파일

우리는 문제로 불편을 끼쳐 드려 죄송합니다

이유를 알려주세요