[Vulkan ray tracking] 샘플 코드의 다음 단계인 raygen 사다에 대해서.

개요


이전에 쓴 프로그램은 이동을 최우선으로 하기 때문에 템플릿에 대한 설명이 깊지 않거나'그런 것'으로 쓰였지만, 샘플 코드에 자주 기재된 레이건 페이지 내용을 먼저 조사해 기사에 남기로 했다.

샘플 코드 위치


· Khronos 공식
아마 여러분들이 제일 먼저 참고하신 코드일 거예요.
https://github.com/KhronosGroup/Vulkan-Samples/tree/master/samples/extensions/raytracing_basic
・NVIDIA Vulkan Ray Tracing Tutorial
해설이 덧붙여져 있어서 매우 이해하기 쉽다
NVIDIA는 하드웨어뿐만 아니라 이런 환경에서도 한 발 앞서는 모습입니다.
https://nvpro-samples.github.io/vk_raytracing_tutorial_KHR/#accelerationstructure/top-levelaccelerationstructure/helperdetails:raytracingbuilder::buildtlas()

무엇을 사다라고 하는가


ray tracing pipeline의 출발점과 끝점입니다.여기서 레이를 건너뛰고 miss 농담기와 rchiit 농담기 등을 통해 픽셀의 색을 계산한 후 최종 결과를 2Dimage에 저장해 디스플레이를 통해 화면을 출력한다.
위의 그림은 일반 또는 전통적인 도형 파이프라인이고 다음 그림은 지연 노선이다.위의 그림에서 Vertex, 즉 다각형의 정점을 중심으로 파이프에 흐르고(이후 API로 계산) 세계의 형상을 묘사하지만 지연 운행 파이프에서 세계의 중심은ray의 원천(camera 또는eye 등)을 날리는 것이다.거기서 보이는 경치를 그대로 계산해서 2Dimage로 그려라.

참조: https://developer.nvidia.com/blog/vulkan-raytracing/
Figure 2. Traditional rasterization pipeline versus the ray tracing pipeline

템플릿의 raygen 페이지 번호


main 함수만 추출합니다.픽셀마다 면도기라고 부르는 것으로 추정된다.좌표계의 이름은 여러 가지가 있지만 여기에는 아래의 그림의 이름을 통일적으로 사용한다.이것은 OpenGL의 그림이기 때문에 좌표축의 방향 등에서 일부 오차가 있다.

참조: https://learnopengl.com/Getting-started/Coordinate-Systems
The global picture
raygen.rgen
void main()
{
  const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
  const vec2 inUV        = pixelCenter / vec2(gl_LaunchSizeEXT.xy);
  vec2       d           = inUV * 2.0 - 1.0;

  vec4 origin    = cam.viewInverse * vec4(0, 0, 0, 1);
  vec4 target    = cam.projInverse * vec4(d.x, d.y, 1, 1);
  vec4 direction = cam.viewInverse * vec4(normalize(target.xyz), 0);

  uint  rayFlags = gl_RayFlagsOpaqueEXT;
  float tMin     = 0.001;
  float tMax     = 10000.0;

  traceRayEXT(topLevelAS,     // acceleration structure
              rayFlags,       // rayFlags
              0xFF,           // cullMask
              0,              // sbtRecordOffset
              0,              // sbtRecordStride
              0,              // missIndex
              origin.xyz,     // ray origin
              tMin,           // ray min range
              direction.xyz,  // ray direction
              tMax,           // ray max range
              0               // payload (location = 0)
  );

  imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(prd.hitValue, 1.0));
}
단락별로 보다.

제1단락

const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
const vec2 inUV        = pixelCenter / vec2(gl_LaunchSizeEXT.xy);
  vec2       d           = inUV * 2.0 - 1.0;
gl_LaunchIDEXT에서는 창의 왼쪽 위 모서리를 원점으로 하고 상대 픽셀 위치는 정수(Screen Space)로 저장됩니다.픽셀센터의 위치는 플랫을 원하기 때문에 0.5를 추가합니다.
이어 스크린 스페이스를 UV 공간의 픽셀 센터의 상대적 위치로 할당(inUV)했다.즉, Screen Space를 (0, 0)에서 (1, 1)까지의 공간으로 보고 pixcel center의 위치를 계산하기 때문에 화면 크기(창 크기)에 따라 나눈다.pixel center에서 (0,0)에서 (1,1)까지의 값을 가져옵니다.
마지막으로 위의 UV 공간에서 Clip Space로 변환합니다.Clip Space는 UV 공간(0, 0)에서 (1, 1)으로, (-1, -1)에서 (1, 1)로 상대적으로 큽니다.그래서 좌표가 바뀌었어요.
d = inUV * 2.0 - 1.0
계산할 수 있다.이렇게 하면 (0, 0)의 점이 (-1, -1), (1, 1)의 점이 (1, 1)로 투영되므로 Screen Space에서 Clip Space로 변환할 수 있습니다.중간 점이 연속적으로 투영됩니다.

제2단락

vec4 origin    = cam.viewInverse * vec4(0, 0, 0, 1);
vec4 target    = cam.projInverse * vec4(d.x, d.y, 1, 1);
vec4 direction = cam.viewInverse * vec4(normalize(target.xyz), 0);

최종적으로traceRayEXT 함수를 통해ray를 발사하는 데 사용할 변수를 확정합니다.origin은 World Space에서 camera의 위치를 가리킨다.이것은 uniform 변수를 외부에서 직접 제공할 수도 있고, 본 예시에서처럼viewInverse 행렬을 보여 줄 수도 있습니다.viewInverse는 앞으로도 사용할 수 있기 때문에viewInverse만 주면 효율이 더 좋습니다.View Space에서 camera의 위치는 (0, 0, 0, 1)에 고정되어 있고, 반대로 View Matrix를 통해 World Space에서 이렇게 되기 위해 View Space를 만들었다) camera의 위치는
viewInverse * vec4(0,0,0,1)
계산할 수 있다.보충으로 좌표가 변환된 역행렬이 걸려 있기 때문에 위의 그림의 변환을 할 수 있는 역행렬이다.
이어서direction(즉camera)에서ray로 날아오르는 방향을 구합니다.앞으로 스크린 스페이스로 전환할 때 픽셀 센터가 월드 스페이스로 향하는 방향이다.즉, 레이 트랙킹에서 모든 픽셀에 대해 월드 스페이스로 한 번 변환한 다음,camera에서 레이를 건너뛸 수 있는 색을 찾는다(당연히 계산량이 증가할 것이다).
구체적으로 말하면 1단에서 구한 d를 사용한다.d 는 Clip Space에 있으므로 View Space에 가져옵니다.
target = projInverse * vec4(d.x, d.y, 1, 1)
View Space 내의 방향 벡터를 계산하여 World Space로 변환
direction = viewInverse * vec4(normalize(target.xyz), 0)

세 번째 단락 다음.


traceRayEXT 함수를 사용하여 위에서 구한origin과direction의raytracking을 진행하고,ray에 맞으면 rchiit 면도기로 전진하며,miss 면도기 처리에 부딪히지 않으면.
최종 결과는payload에 저장되기 때문에 이미지 스토어 함수로 이미지에 저장하여 처리를 완료합니다.

좋은 웹페이지 즐겨찾기