Computer Graphics/VulkanPT

Vulkan에 Ray Tracing 도입 하기 (0)

surkim 2025. 4. 11. 15:07

현재 Ray gen, hit, miss 셰이더가 정상적으로 작동하는 것을 확인했습니다.
테스트 결과는 다음과 같습니다.

 

현재 화면에서는 카메라에서 쏘는 레이가 맞는 부분은 빨간색, 맞지 않는 부분은 검정색으로 렌더링되고 있습니다.

 

 

Vulkan에서 Ray Tracing을 처음 시도하다 보니, 구현 방법과 플로우에 초점을 맞추어 기록을 해보겠습니다.


특히 Vulkan은 명시적인 API라서, Ray Tracing을 추가하면서 새로운 옵션들을 도입하게 됩니다.

이 과정에서 각 옵션이 의미하는 바와 그 필요성을 이해하는 것이 중요합니다.

 

1. Ray Tracing 정보를 저장할 Texture 생성

다음은 Ray Tracing 결과를 저장할 텍스처를 생성하는 코드입니다:

m_rtReflectionTextures[i] = Texture::createAttachmentTexture(m_context.get(), m_extent.width, m_extent.height, 
VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_ASPECT_COLOR_BIT);

 

코드 자체보다는 플래그 옵션이 중요한 부분입니다.

여기서 주요 플래그는 VK_IMAGE_USAGE_STORAGE_BIT와입니다.

이 옵션이 왜 중요한지 이해하는 것이 핵심입니다.

 

기존 렌더링 파이프라인은 기본적으로

VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT

VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT

이런 옵션을 사용하여 데이터를 처리하지만,

 

Ray Tracing은 이미지를 직접 읽고 쓰는 방식으로 동작합니다.

RenderPass를 쓰지 않는 것이 핵심입니다.

Ray Tracing은 렌더패스와 다르게 독립적으로 셰이더에서 직접 이미지에 데이터를 기록하고 처리합니다.

즉, 기존 렌더링 파이프라인과는 별도로 동작하며, 렌더링 파이프라인과 동시에 또는 별개로 실행될 수도 있습니다.

 

2. Descriptorset Layout 구성

binding = 0 에 앞서 만든 이미지를

binding = 1 에 TLAS를 넣을 layout을 정의합니다.

void DescriptorSetLayout::initRayTracing(VulkanContext* context) {
	this->context = context;
	std::vector<VkDescriptorSetLayoutBinding> bindings(2);

	bindings[0].binding = 0;
	bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
	bindings[0].descriptorCount = 1;
	bindings[0].stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
	bindings[0].pImmutableSamplers = nullptr;

	bindings[1].binding = 1;
	bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
	bindings[1].descriptorCount = 1;
	bindings[1].stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
	bindings[1].pImmutableSamplers = nullptr;

	VkDescriptorSetLayoutCreateInfo layoutInfo{};
	layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
	layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
	layoutInfo.pBindings = bindings.data();

	if (vkCreateDescriptorSetLayout(context->getDevice(), &layoutInfo, nullptr, &m_layout) != VK_SUCCESS) {
		throw std::runtime_error("failed to create ray tracing descriptor set layout!");
	}
}

이때 중요한 것은 

 

1번 바인딩의

VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR 플래그입니다.

 

이제 가속 구조(ACCELERATION_STRUCTURE)가 뭔지 알아야합니다.

 

가속 구조는 Ray Tracing에서 중요한 역할을 합니다.

Ray Tracing의 핵심은 레이가 어디에 충돌하지 계산하는 것입니다.

이때 가속 구조는 레이와 씬 사이의 상호작용을 효율적으로 계산하는 데 사용됩니다.

Ray Tracing은 가속 구조를 통해 충돌 검사를 최적화하고 성능을 향상시킬 수 있습니다.

 

지금은 BLAS와 TLAS

2 종류를 사용합니다.

 

BLAS (Bottom Level Acceleration Structure)

BLAS는 개별 객체의 기하학적 데이터(버텍스와 인덱스 정보)를 저장합니다.

BLAS 내부에서는 BVH (Bounding Volume Hierarchy)를 사용하여 삼각형들을 계층적으로 묶어 관리합니다.

 

BVH는 충돌 검사를 최적화하기 위해 공간을 계층적으로 나누는 기법입니다.

Ray Tracing에서는 수많은 삼각형을 검사해야 하므로,

삼각형들을 하나의 Bounding Box로 묶어 더 큰 공간 단위로 검사하고, 충돌 가능성이 있는 부분만 세밀하게 검사합니다.

참고 : https://en.wikipedia.org/wiki/Bounding_volume_hierarchy

 

TLAS (Top Level Acceleration Structure)

TLAS는 전체 씬에서 각 객체들의 위치와 변환 정보를 포함하는 가속 구조입니다.

TLAS는 BLAS의 배치 및 위치를 관리하며,

씬 내의 모든 객체들을 레이와 충돌하는 관계를 계산하는 데 사용됩니다.

 

TLAS는 각각의 BLAS가 레이와 충돌할 수 있도록

3D 공간에서의 인스턴스화된 위치와 변환 정보 (Model Matrix)를 저장합니다.

TLAS는 BLAS의 여러 인스턴스를 조합하여 하나의 큰 구조체를 구성하며,

이를 통해 씬 내의 레이 추적을 최적화합니다.

 

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

pt - 0. path tracing 렌더러 시작  (2) 2025.04.25
BRDF 정리  (0) 2025.04.22
The Rendering Equation 정리  (0) 2025.04.21
Vulkan에 Ray Tracing 도입 하기 (2)  (1) 2025.04.11
Vulkan에 Ray Tracing 도입 하기 (1)  (0) 2025.04.11