DirectX Raytracing – Hit group, Shader Record Table Acceleration Structure 갱신 등

계속 내 엔진의 D3D12렌더러에 DirectX Raytracing 기능을 적용하고 있다. 그 동안 상당히 많은 깨달음이 있었고 코드도 거의 엄청나게 갈아엎었다. 어떻게 쓰는지 감을 잡아가고 있다.

Local Root Parameter , Hit Group관련
하나의 피봇을 공유하는 매시들의 집합을 오브젝트라 할때, 이 오브젝트 안에서는 여러개의 재질(텍스처등)을 사용할 수 있고 이 경우 각각은 다른 텍스처 좌표를 갖기 때문에 각각 다른 인덱스 리스트를 가진다. 이를 3dsmax에선 서브 매터리얼 그룹이라 부르고 내 엔진에선 FaceGroup이라 부른다. 그리고 DXR에선 이런 케이스에 해당하는 객체들을 Geometry라 부른다.
어쨌든 버텍스 리스트는 공유하지만 인덱스 리스트와 재질(텍스처 포함)은 달리 사용하는 객체들이며 따라서 Draw도 각각 해주게 된다. Bottom Level Acceleration Structure하나당 Object 하나로 대응을 시켜놨는데 raytracing shader안에서 이 각각의 Geometry들이 자신의 재질 정보와 자신의 인덱스 리스트(Index Buffer)를 어떻게 참조할 것인가…를 놓고 상당히 고민했다.
아니 무슨 특별한 기법이 있는건 아니고 그 방법을 몰라서 엄청 고생했다.
답은 다음과 같다.

  1. Geometry개수*Hit group shader개수 만큼 Hit Group내에 Shader Record Table을 설정한다.
  2. Top Level Acceleration Structure를 만들때 InstanceContributionToHitGroupIndex값으로 이 인스턴스가 참조할 시작 Shader Record Table의 인덱스를 넣어준다.
  3. shader안에서 TraceRay()를 호출할때 Geometry strider를 1이상의 숫자로 지정할것(hit group의 shader가 2개라면 stride는 2)
  4. 이제 hit shader가 호출될때 Local Root Paramter로서 Index – InstanceContributionToHitGroupIndex(TLAS설정시) + Geometry Index(자동부여) * Geomeytr Stride(TraceRay()호출 시 지정) – 의 Shader Record Table이 선택된다.

이제 Instance안의 Geometry들은 정확히 자신의 material을 사용할 수 있다.

렌더링
raytracing shader안에서 재귀적으로 TraceRay()를 호출할 수 있다. 이때 어느 hit group 쉐이더를 사용할지 선택할 수 있다. 따라서 한번의 DispatchRay()호출로 라이팅(반사포함)과 그림자를 모두 처리할 수 있다.
이것으로 반사처리와 그림자처리를 구현했다.
데모에서는 캐릭터의 머리 위에 광원을 배치하고 모든 오브젝트들에게 반사재질을 적용했다.

Acceleration Structure 업데이트 성능 개선
동적인 오브젝트들의 경우 월드좌표로 변환된 상태의 버텍스 데이터로 Bottom Level Acceleration Structure를 구축/업데이트 하도록 했었으나 이를 전면적으로 수정했다.
동적인 오브젝트들의 경우도 skinned mesh가 아니면 BLAS는 전혀 갱신하지 않고 TLAS갱신시에 변환 매트릭스만 바꾸도록 했다.
skinned mesh의 경우 로컬 공간에서만 skinning처리를 하고 최종적으로 월드변환하는 매트릭스는 따로 빼서 BLAS업데이트 시 성능 저하를 줄이도록 했다.
BLAS업데이트에서 발생할 성능저하에 공포에 가까운 두려음을 가지고 있어서 그동안은 30프레임 정도로 갱신주기를 제한해왔으나 오늘 AS쪽 코드를 대폭 수정하고나서 모든 프레임에 BLAS/TLAS업데이트를 하도록 했다.
결과는 ‘생각보다 느리지 않네.’
그냥 갱신주기 제한 두지 않고 업데이트 해도 될것 같다. GTX1660TI로 개발중인데 이녀석보다 RTX가 TLAS/BLAS업데이트가 빠를테니 실질적으론 거의 문제가 되지 않을것 같다.


답글 남기기

댓글을 게시하려면 다음의 방법 중 하나를 사용하여 로그인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중