vk_mini_path_tracer
A beginner-friendly Vulkan path tracing tutorial in under 300 lines of C++.
Top Related Projects
Implementation of Peter Shirley's Ray Tracing In One Weekend book using Vulkan and NVIDIA's RTX extension.
Ray tracing examples and tutorials using VK_KHR_ray_tracing
One stop solution for all Vulkan samples
C++ examples for the Vulkan graphics API
Quick Overview
The vk_mini_path_tracer is a minimalistic path tracer implemented using Vulkan. It serves as an educational tool to demonstrate real-time ray tracing techniques and Vulkan ray tracing extensions. The project is part of the NVIDIA Vulkan Ray Tracing Tutorials and provides a compact, yet functional path tracer.
Pros
- Excellent learning resource for Vulkan ray tracing
- Compact and focused implementation
- Well-documented code with explanatory comments
- Demonstrates modern GPU-based rendering techniques
Cons
- Limited features compared to full-fledged renderers
- May require advanced graphics knowledge to fully understand
- Specific to Vulkan, not applicable to other graphics APIs
- Requires compatible hardware with ray tracing support
Code Examples
- Setting up a ray tracing pipeline:
void createRtPipeline()
{
// Create the ray tracing pipeline
nvvk::RayTracingPipelineGenerator rtPipelineGen;
// Setup ray generation shader
rtPipelineGen.addShader(readFile("spv/raytrace.rgen.spv"), VK_SHADER_STAGE_RAYGEN_BIT_KHR);
// Setup miss shader
rtPipelineGen.addShader(readFile("spv/raytrace.rmiss.spv"), VK_SHADER_STAGE_MISS_BIT_KHR);
// Setup closest hit shader
rtPipelineGen.addShader(readFile("spv/raytrace.rchit.spv"), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
// Create the pipeline
m_rtPipeline = rtPipelineGen.createPipeline(m_device);
}
- Tracing rays:
void traceRays()
{
vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, m_rtPipeline);
vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, m_pipelineLayout, 0, 1, &m_rtDescSet, 0, nullptr);
VkStridedDeviceAddressRegionKHR raygenShaderEntry{};
// ... Set up shader binding table entries
vkCmdTraceRaysKHR(cmdBuf, &raygenShaderEntry, &missShaderEntry, &hitShaderEntry, &callableShaderEntry, m_size.width, m_size.height, 1);
}
- Updating the scene:
void updateScene(float deltaTime)
{
// Update camera
m_camera.update(deltaTime);
// Update push constants
PushConstantRay pcRay{};
pcRay.clearColor = m_clearColor;
pcRay.lightPosition = m_lightPosition;
pcRay.lightIntensity = m_lightIntensity;
pcRay.lightType = m_lightType;
vkCmdPushConstants(cmdBuf, m_pipelineLayout, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 0, sizeof(PushConstantRay), &pcRay);
}
Getting Started
- Clone the repository:
git clone https://github.com/nvpro-samples/vk_mini_path_tracer.git
- Install Vulkan SDK and required dependencies
- Build the project using CMake:
mkdir build && cd build cmake .. make
- Run the executable:
./vk_mini_path_tracer
Competitor Comparisons
Implementation of Peter Shirley's Ray Tracing In One Weekend book using Vulkan and NVIDIA's RTX extension.
Pros of RayTracingInVulkan
- More comprehensive implementation with advanced features like denoising and temporal accumulation
- Includes a user interface for real-time parameter adjustments
- Supports loading external 3D models and textures
Cons of RayTracingInVulkan
- Higher complexity and steeper learning curve for beginners
- Requires more system resources due to advanced features
- Less focused on educational purposes compared to vk_mini_path_tracer
Code Comparison
vk_mini_path_tracer:
void trace_ray(Ray* ray, Hit* hit) {
hit->t = 1e20f;
for (int i = 0; i < g_num_spheres; i++) {
intersect_sphere(ray, &g_spheres[i], hit);
}
}
RayTracingInVulkan:
void TraceRay(const Ray& ray, HitInfo& hitInfo, float tMin, float tMax) {
hitInfo.distance = tMax;
for (const auto& object : scene.objects) {
object->Intersect(ray, tMin, hitInfo);
}
}
The code snippets show similar ray tracing logic, but RayTracingInVulkan uses more advanced C++ features and a more flexible object-oriented approach.
Ray tracing examples and tutorials using VK_KHR_ray_tracing
Pros of vk_raytracing_tutorial_KHR
- More comprehensive tutorial covering various aspects of Vulkan ray tracing
- Includes multiple examples demonstrating different ray tracing techniques
- Better documentation and explanations for each step of the implementation
Cons of vk_raytracing_tutorial_KHR
- More complex codebase, potentially harder for beginners to grasp
- Requires more setup and dependencies compared to the mini path tracer
- May be overkill for simple ray tracing projects
Code Comparison
vk_raytracing_tutorial_KHR:
void createRtDescriptorSet()
{
m_rtDescSetLayoutBind.addBinding(RtDescriptorSetBindings::eAccelerationStructure, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1,
VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSet = nvvk::allocateDescriptorSet(m_device, m_rtDescPool, m_rtDescSetLayout);
}
vk_mini_path_tracer:
void createDescriptorSet()
{
VkDescriptorSetLayoutBinding binding{};
binding.binding = 0;
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
binding.descriptorCount = 1;
binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = 1;
layoutInfo.pBindings = &binding;
}
One stop solution for all Vulkan samples
Pros of Vulkan-Samples
- Comprehensive collection of Vulkan samples covering various aspects of the API
- Official repository maintained by Khronos Group, ensuring up-to-date and accurate implementations
- Includes performance best practices and optimization techniques
Cons of Vulkan-Samples
- Larger and more complex codebase, potentially overwhelming for beginners
- Focuses on general Vulkan usage rather than specific path tracing techniques
- May require more setup and configuration to run individual samples
Code Comparison
vk_mini_path_tracer:
void traceRay(Ray& ray, vec3& color, int depth) {
if (depth >= MAX_DEPTH) return;
HitRecord rec;
if (world.hit(ray, 0.001f, FLT_MAX, rec)) {
// Handle ray intersection and recursive tracing
}
}
Vulkan-Samples:
void VulkanSample::draw()
{
auto command_buffer = getCommandBuffer(true);
vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
drawGeometry(command_buffer);
vkCmdEndRenderPass(command_buffer);
flushCommandBuffer(command_buffer);
}
The vk_mini_path_tracer focuses on ray tracing logic, while Vulkan-Samples demonstrates general Vulkan rendering pipeline setup and execution.
C++ examples for the Vulkan graphics API
Pros of Vulkan
- Comprehensive collection of Vulkan examples covering a wide range of techniques and features
- Well-documented and organized codebase with clear explanations for each example
- Regularly updated to incorporate new Vulkan features and best practices
Cons of Vulkan
- Focuses on individual techniques rather than a complete path tracing implementation
- May be overwhelming for beginners due to the large number of examples and advanced concepts
- Less emphasis on performance optimization compared to vk_mini_path_tracer
Code Comparison
vk_mini_path_tracer:
void PathTracer::trace_rays() {
// Simplified path tracing implementation
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Ray tracing logic
}
}
}
Vulkan:
void VulkanExample::buildCommandBuffers() {
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
// Command buffer setup and recording
}
The vk_mini_path_tracer focuses on implementing a compact path tracer, while Vulkan provides examples of various Vulkan concepts and techniques. The code snippets illustrate the different approaches: vk_mini_path_tracer implements core path tracing logic, while Vulkan demonstrates Vulkan-specific command buffer setup.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
vk_mini_path_tracer
A relatively small, beginner-friendly path tracing tutorial.
:arrow_forward: Load the tutorial! :arrow_backward:
This tutorial is a beginner-friendly introduction to writing your own fast, photorealistic path tracer in less than 300 lines of C++ code and 250 lines of GLSL shader code using Vulkan. Here's an example of what you'll render at the end of this tutorial!
Vulkan is a low-level API for programming GPUs â fast, highly parallel processors. It works on a wide variety of platforms â everything from workstations, to gaming consoles, to tablets and mobile phones, to edge devices.
Vulkan is usually known as a complex API, but I believe that when presented in the right way, it's possible to make learning Vulkan accessible to people of all skill levels, whether they're never programmed graphics before or whether they're a seasoned rendering engineer. Perhaps surprisingly, one of the best ways to introduce Vulkan may be with GPU path tracing, because the API involved is relatively small.
We'll show how to write a small path tracer, using the NVVK helpers, included in the nvpro-samples framework, to help with some Vulkan calls when needed. For advanced readers, we'll also optionally talk about performance tips and some of the implementation details inside the helpers and Vulkan itself.
The final program uses less than 300 lines of C++ and less than 250 lines of GLSL shader code, including comments. You can find it here.
Here are all the Vulkan functions, and NVVK functions and objects, that we'll use in the main tutorial:
Vulkan Functions | ||
---|---|---|
vkAllocateCommandBuffers | vkBeginCommandBuffer | vkCmdBindDescriptorSets |
vkCmdBindPipeline | vkCmdDispatch | vkCmdFillBuffer |
vkCmdPipelineBarrier | vkCreateCommandPool | vkCreateComputePipelines |
vkDestroyCommandPool | vkDestroyPipeline | vkDestroyShaderModule |
vkFreeCommandBuffers | vkGetBufferDeviceAddress | vkQueueSubmit |
vkQueueWaitIdle | vkUpdateDescriptorSets |
NVVK Functions and Objects | ||
---|---|---|
nvvk::Buffer | NVVK_CHECK | nvvk::Context |
nvvk::ContextCreateInfo | nvvk::createShaderModule | nvvk::DescriptorSetContainer |
nvvk::make | nvvk::RayTracingBuilderKHR | nvvk::ResourceAllocatorDedicated |
Chapters
Extra Chapters
These are optional, extra tutorials that show how to polish and add new features to the main tutorial's path tracer. Make sure to check out the list of further Vulkan and ray tracing resources at the end of the main tutorial as well!
Building and Running
Please see the instructions here.
Top Related Projects
Implementation of Peter Shirley's Ray Tracing In One Weekend book using Vulkan and NVIDIA's RTX extension.
Ray tracing examples and tutorials using VK_KHR_ray_tracing
One stop solution for all Vulkan samples
C++ examples for the Vulkan graphics API
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot