Computer Graphics/Project

Vulkan에 Ray Tracing 도입 하기 (2)

surkim 2025. 4. 11. 16:42

앞 포스트와 이어집니다..

7. Ray Tracing 셰이더 코드 작성

[RTReflection.rgen]

이 셰이더는 레이 트레이싱 작업을 시작하는 셰이더입니다.

화면상의 각 픽셀에 대해 레이를 발사하고, 그 레이가 충돌하는 지점을 찾기 위한 초기 작업을 담당합니다.

#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_nonuniform_qualifier : enable

layout(set = 0, binding = 0) uniform CameraBuffer {
    mat4 view;
    mat4 proj;
    vec3 camPos;
} camera;

layout(set = 1, binding = 0, rgba16f) uniform image2D outputImage;
layout(set = 1, binding = 1) uniform accelerationStructureEXT topLevelAS;

layout(location = 0) rayPayloadEXT vec4 payload;

void main() {
    const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
    const vec2 resolution = vec2(gl_LaunchSizeEXT.xy);
    vec2 ndc = (pixelCenter / resolution) * 2.0 - 1.0;

    vec4 rayOrigin = inverse(camera.view)[3];
    vec4 rayTarget = inverse(camera.proj * camera.view) * vec4(ndc, 1.0, 1.0);
    rayTarget /= rayTarget.w;
    vec3 direction = normalize(rayTarget.xyz - rayOrigin.xyz);

    payload = vec4(0.0);

    traceRayEXT(topLevelAS,
        gl_RayFlagsOpaqueEXT,
        0xFF,                // cull mask
        0, 0, 0,             // sbtRecordOffset, sbtRecordStride, missIndex
        rayOrigin.xyz,
        0.001,               // min t
        direction,
        10000.0,             // max t
        0                    // payload location
    );

    imageStore(outputImage, ivec2(gl_LaunchIDEXT.xy), payload);
}

 

 

특이한 점은 payload라는 개념인 거 같습니다.

 

payload는 레이의 추적 결과를 전달하고 저장하는 데 사용됩니다.

기본적으로 초기 값은 (0.0)으로 설정되며,

traceRayEXT 함수에서 레이 트레이싱을 실행한 후, 이 결과는 payload에 업데이트됩니다.

 

traceRayEXT 함수는 raygen, miss, hit 셰이더를 통해 레이 추적을 수행합니다.

이 함수는 TLAS에서 레이와 충돌하는 지점을 찾습니다.

최종적으로 payload 값은 imageStore를 통해 outputImage에 저장됩니다.

 

[RTReflection.rchit]

레이가 삼각형과 충돌했을 때 실행되는 셰이더입니다.

#version 460
#extension GL_EXT_ray_tracing : require

layout(location = 0) rayPayloadInEXT vec4 payload;

void main() {
    payload = vec4(1.0, 0.0, 0.0, 1.0); // debug
}

지금은 디버깅용으로 빨간색을 payload에 담아 보냅니다. 

 

[RTReflection.rmiss]

레이에 아무것도 히트하지 않았을 때 실행되는 셰이더 입니다.

#version 460
#extension GL_EXT_ray_tracing : require

layout(location = 0) rayPayloadInEXT vec4 payload;

void main() {
    payload = vec4(0.0, 0.0, 0.0, 1.0); // debug
}

지금은 디버깅용으로 검정색을 payload에 담아 보냅니다. 

 

8. 커맨드버퍼에 Ray Tracing 기록

Ray Tracing 파이프라인을 커맨드버퍼에 담는 과정은 간단합니다.

 

 

먼저 만든 파이프라인을 바인딩하고 

vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, m_rtPipeline->getPipeline());

 

디스크립터셋도 바인딩합니다.

VkDescriptorSet sets[] = {
	m_globlaDescSets[currentFrame]->getDescriptorSet(),  // set=0 (camera)
	m_rtDescSets[currentFrame]->getDescriptorSet()       // set=1 (outputImage + TLAS)
};
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR,
	m_rtPipeline->getPipelineLayout(), 0, 2, sets, 0, nullptr);

 

그리고 vkCmdTraceRayKHR 함수를 실행합니다.

VkStridedDeviceAddressRegionKHR emptyRegion{};
g_vkCmdTraceRaysKHR(
	cmd,
	&m_rtPipeline->getRaygenRegion(),
	&m_rtPipeline->getMissRegion(),
	&m_rtPipeline->getHitRegion(),
	&emptyRegion,
	m_extent.width,
	m_extent.height,
	1);

 

raygenRegion, missRegion, hitRegion은 Shader Binding Table(SBT)에서 정의한 각 셰이더의 범위입니다.

emptyRegion은 교차 셰이더(intersection shader)를 사용할 때 필요한 파라미터입니다.

현재는 교차 셰이더를 사용하지 않기 때문에 빈 구조체를 전달해야 합니다.

없으면 에러납니다!

 

10. 확장 설정

Vulkan 확장 설정도 해야합니다.

 

Ray Tracing은 기본적으로 1.2 버전부터 사용 가능합니다.

vulkan 인스턴스 생성할 때 버전을 바꿔줍니다.

appInfo.apiVersion = VK_API_VERSION_1_2;

 

하지만 1.2 버전의 기본 기능으로 제공되는 것은 아닙니다.

따라서 추가확장을 명시해야합니다.

 

ray tracing 을 쓰기 위한 확장들을 간단하게 설명하겠습니다.

 

 

VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME

가속 구조를 생성하고 관리할 수 있게 해주는 확장입니다.

이 확장을 통해 BLAS와 TLAS를 생성하고 레이 트레이싱에 필요한 구조체들을 처리할 수 있습니다.

 

VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME

레이 트레이싱 파이프라인과 셰이더, SBT를 바인딩하여 레이 트레이싱 작업을 최적화할 수 있습니다.

이 확장 덕분에 traceRayEXT를 사용하여 레이 추적을 실행할 수 있습니다.

 

VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME

GPU의 메모리 주소를 셰이더에서 직접 참조할 수 있게 해주며,

SBT에서 메모리 주소를 직접 사용하여 레이 트레이싱 셰이더를 최적화합니다.

 

VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME

GPU와 CPU 간의 작업 동기화를 효율적으로 관리하여

레이 트레이싱과 같은 고부하 작업에서 성능을 최적화할 수 있습니다.

 

VK_KHR_SPIRV_1_4_EXTENSION_NAME

최신 SPIR-V 버전인 1.4를 사용하여 레이 트레이싱 셰이더 성능을 최적화할 수 있습니다.

이 확장 덕분에 최신 SPIR-V 기능을 활용할 수 있습니다.

 

VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME

부동소수점 연산을 셰이더 내에서 제어할 수 있어, 레이 트레이싱에서 정확한 계산을 필요로 할 때 유용합니다.

 

 

이로써 Vulkan에서 Ray Tracing을 사용할 수 있는 환경이 갖춰졌습니다.

 

정리하자면

0. Vulkan에서 레이트레이싱에 필요한 확장을 준비합니다. 

1. 레이트레이싱에 필요한 가속구조(BLAS -> TLAS)를 준비합니다.

2. 결과를 저장할 이미지를 준비합니다.

3. 이 데이터를 셰이더에서 볼 수 있게 바인딩 합니다. 

4. Pipeline과  Shader Binding Table을 준비합니다.

5. 레이를 쏘는 커맨드를 적재하면 됩니다.

 

하나하나 기능이 도입될 때의 흐름과

거기에 필요한 구조를 잘 알고 있어야

나중에 문제가 생기거나, 최적화 여지를 찾을 때 중요합니다.

 

현재 구현된 기능은 아주 기본적인 부분이지만

이를 바탕으로 Reflection과 Global Illumination(GI) 기능을 추가할 예정입니다.

'Computer Graphics > Project' 카테고리의 다른 글

RT reflection 첫 도입  (0) 2025.04.14
20250414  (0) 2025.04.14
Vulkan에 Ray Tracing 도입 하기 (1)  (0) 2025.04.11
Vulkan에 Ray Tracing 도입 하기 (0)  (0) 2025.04.11
20250411  (0) 2025.04.11