From ea06956b8b4f18e2b0cfea9e96da3bec9cb2e6c8 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Sun, 21 Sep 2025 17:59:12 +0200 Subject: [PATCH] Adjust heading levels to match rest of tutorial --- en/courses/18_Ray_tracing/00_Overview.adoc | 10 +++++----- en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc | 8 ++++---- .../18_Ray_tracing/02_Acceleration_structures.adoc | 10 +++++----- en/courses/18_Ray_tracing/03_Ray_query_shadows.adoc | 6 +++--- en/courses/18_Ray_tracing/04_TLAS_animation.adoc | 6 +++--- .../18_Ray_tracing/05_Shadow_transparency.adoc | 12 ++++++------ en/courses/18_Ray_tracing/06_Reflections.adoc | 6 +++--- en/courses/18_Ray_tracing/07_Conclusion.adoc | 6 +++--- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/en/courses/18_Ray_tracing/00_Overview.adoc b/en/courses/18_Ray_tracing/00_Overview.adoc index bb1f810f..9266a777 100644 --- a/en/courses/18_Ray_tracing/00_Overview.adoc +++ b/en/courses/18_Ray_tracing/00_Overview.adoc @@ -1,6 +1,6 @@ -== SIGGRAPH 2025: Hands-on Vulkan Ray Tracing with Dynamic Rendering += SIGGRAPH 2025: Hands-on Vulkan Ray Tracing with Dynamic Rendering -=== Overview +== Overview Welcome! In this series, we enhance a Vulkan renderer with ray tracing features to implement real-time pixel-perfect shadows (with and without transparency) and a bonus reflection effect. You will work with provided scaffolded code (based on the Vulkan Tutorial) and fill in key shader functions following step-by-step instructions. @@ -41,7 +41,7 @@ At the top of the C++ file, note the following variable: At certain intervals, you will be instructed to update this variable and re-build to verify the effect of key changes, no need to write new code. -=== Chapters in this series +== Chapters in this series - xref:./00_Overview.adoc[Overview] - xref:./01_Dynamic_rendering.adoc[Dynamic rendering] @@ -52,7 +52,7 @@ At certain intervals, you will be instructed to update this variable and re-buil - xref:./06_Reflections.adoc[Reflections] - xref:./07_Conclusion.adoc[Conclusion] -=== Build and run +== Build and run You can build and run the provided sample either from Visual Studio (set 38_ray_tracing as the start-up project) or via command line: @@ -63,5 +63,5 @@ cmake --build build --target 38_ray_tracing --parallel; start .\build\38_ray_tra Note that the above hasn't changed from the base tutorial, and you may continue to build on other platforms as you have for the rest of the tutorial. -=== Navigation +== Navigation - Next: xref:./01_Dynamic_rendering.adoc[Dynamic rendering] diff --git a/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc b/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc index aa0c576c..e5e27606 100644 --- a/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc +++ b/en/courses/18_Ray_tracing/01_Dynamic_rendering.adoc @@ -1,10 +1,10 @@ -== Dynamic Rendering += Dynamic Rendering *Objective*: Ensure the base project uses *dynamic rendering* and understand how to verify it using RenderDoc. In dynamic rendering, we no longer create a VkRenderPass or VkFrameBuffer; instead we begin rendering with `vkCmdBeginRenderingKHR`, specifying attachments on-the-fly. This makes our code more flexible (no need to predeclare subpasses) and is now the "modern" way to render in Vulkan. -=== Task 1: Check the setup for dynamic rendering +== Task 1: Check the setup for dynamic rendering In the provided code base, locate the initialization of the graphics pipeline: @@ -83,7 +83,7 @@ commandBuffers[currentFrame].beginRendering(renderingInfo); For more context, refer to the previous tutorial link:../../03_Drawing_a_triangle/02_Graphics_pipeline_basics/03_Render_passes.adoc[chapter]. -==== Dynamic rendering with RenderDoc +=== Dynamic rendering with RenderDoc Use RenderDoc to launch the application and capture a frame: @@ -109,6 +109,6 @@ NOTE: Dynamic rendering reduces CPU overhead and, with the `VK_KHR_dynamic_rende After this step, you should be comfortable that dynamic rendering is set up correctly. We can now move on to ray tracing features. -=== Navigation +== Navigation - Previous: xref:./00_Overview.adoc[Overview] - Next: xref:./02_Acceleration_structures.adoc[Acceleration structures] diff --git a/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc b/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc index ff2ab6f7..67a16e72 100644 --- a/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc +++ b/en/courses/18_Ray_tracing/02_Acceleration_structures.adoc @@ -1,4 +1,4 @@ -== Acceleration Structures (BLAS/TLAS) += Acceleration Structures (BLAS/TLAS) *Objective*: Create *Bottom-Level Acceleration Structures* (BLAS) for the model's geometry, and a *Top-Level Acceleration Structure* (TLAS) to instance those BLASes. Bind the TLAS to the shader so we can use Ray Queries. @@ -17,7 +17,7 @@ We'll create one BLAS per distinct mesh/material and one TLAS that references th The ray query will use the TLAS. In Vulkan, building an AS involves a few steps: describe geometry, query build sizes, allocate buffers, create the AS handle, then issue a build command. -=== Task 2: Create a BLAS for each submesh +== Task 2: Create a BLAS for each submesh Go to the definition of `createAccelerationStructures`. Here we will first create the BLASes for each submesh in the model. The code already has a loop iterating over `submeshes`, which contains the geometry data. @@ -125,7 +125,7 @@ image::../../../images/38_TASK02_blas_build.png[] Now you have a BLAS for each model in the scene. Next we need to put them all together into a single TLAS which will then be consumed by our fragment shader. -=== Task 3: Create a TLAS with instances of the BLASes +== Task 3: Create a TLAS with instances of the BLASes Now that we have the BLASes, we need to create a TLAS that references them. The TLAS will hold instances of the BLASes, allowing us to place them in the scene with transformations (position, rotation, scale). @@ -239,7 +239,7 @@ endSingleTimeCommands(*cmd); Done! You have now created a TLAS that references all the BLASes for the submeshes in the model. The TLAS is ready to be used in ray queries in the fragment shader. -=== Task 4: Bind the acceleration structure to the shader +== Task 4: Bind the acceleration structure to the shader To make the acceleration structure available in the shader, we need to add a descriptor set binding for the TLAS. This is done in the `createDescriptorSetLayout()` function (you may ignore the higher bindings for now): @@ -301,6 +301,6 @@ Re-build and run using: You will see no visual difference, but rest assured, your Acceleration Structures are now set up and ready to be used in the fragment shader. -=== Navigation +== Navigation - Previous: xref:./01_Dynamic_rendering.adoc[Dynamic rendering] - Next: xref:./03_Ray_query_shadows.adoc[Ray query shadows] \ No newline at end of file diff --git a/en/courses/18_Ray_tracing/03_Ray_query_shadows.adoc b/en/courses/18_Ray_tracing/03_Ray_query_shadows.adoc index 096f3667..ecf060d7 100644 --- a/en/courses/18_Ray_tracing/03_Ray_query_shadows.adoc +++ b/en/courses/18_Ray_tracing/03_Ray_query_shadows.adoc @@ -1,10 +1,10 @@ -== Ray Query Shadows (Opaque Geometry) += Ray Query Shadows (Opaque Geometry) *Objective*: Add a simple shadow test in the fragment shader using a ray query. We will cast a ray from each fragment point toward the light and darken the fragment if something is hit (hard shadow). Congratulations: you have a valid TLAS/BLAS for the scene! Now, let's use it to cast some rays. -=== Task 5: Implement ray query shadows +== Task 5: Implement ray query shadows In the fragment shader, we will use a ray query to cast a shadow ray from the fragment position towards the light source. If the ray hits any geometry before reaching the light, we will darken the fragment color: @@ -102,6 +102,6 @@ image::../../../images/38_TASK06_shadows_static.gif[] The object is rotating, but the shadows are static. This is because we have not yet updated the TLAS to account for the object's animation. The TLAS needs to be rebuilt whenever the object moves or animates, so let's implement that next. -=== Navigation +== Navigation - Previous: xref:./02_Acceleration_structures.adoc[Acceleration structures] - Next: xref:./04_TLAS_animation.adoc[TLAS animation] diff --git a/en/courses/18_Ray_tracing/04_TLAS_animation.adoc b/en/courses/18_Ray_tracing/04_TLAS_animation.adoc index 60e4b256..7237666c 100644 --- a/en/courses/18_Ray_tracing/04_TLAS_animation.adoc +++ b/en/courses/18_Ray_tracing/04_TLAS_animation.adoc @@ -1,4 +1,4 @@ -== TLAS Animation += TLAS Animation *Objective*: Ensure shadows update when the object animates by rebuilding the TLAS with updated instance transforms each frame. @@ -6,7 +6,7 @@ To account for the object's animation, we need to update the TLAS whenever the o This involves updating the instance transforms and rebuilding the TLAS. We will do this in the `updateTopLevelAS()` function, which is called every frame with the current model matrix. -=== Task 6: Update the TLAS for animations +== Task 6: Update the TLAS for animations First we need to update the instance transforms with the current model matrix. This is done by iterating over the `instances` vector and setting the transform for each instance, then update the instances buffer. @@ -277,6 +277,6 @@ float4 fragMain(VSOutput vertIn) : SV_TARGET { NOTE: Ray Query vs Ray Tracing Pipeline: Notice how we added a ray tracing effect (shadows) directly in the fragment shader. We did not need a separate ray generation shader or any new pipeline. This is the power of ray queries (also known as inline ray tracing): we integrate ray traversal into our existing rendering pipeline. This keeps the shader logic unified and avoids extra GPU shader launches. On many mobile GPUs, this approach is not only more convenient but necessary: as mentioned, current mobile devices mostly support ray queries and not the full ray pipeline, and they run ray queries efficiently in fragment shaders. This is a key reason we focus on ray queries in this lab. -=== Navigation +== Navigation - Previous: xref:./03_Ray_query_shadows.adoc[Ray query shadows] - Next: xref:./05_Shadow_transparency.adoc[Shadow transparency] \ No newline at end of file diff --git a/en/courses/18_Ray_tracing/05_Shadow_transparency.adoc b/en/courses/18_Ray_tracing/05_Shadow_transparency.adoc index 89c17d00..a31f87d1 100644 --- a/en/courses/18_Ray_tracing/05_Shadow_transparency.adoc +++ b/en/courses/18_Ray_tracing/05_Shadow_transparency.adoc @@ -1,4 +1,4 @@ -== Implementing Transparency in Shadows += Implementing Transparency in Shadows *Objective*: Add support for transparent objects in the scene. We will implement a simple alpha test to discard fragments with low alpha values, and replicate this in their corresponding ray traced shadows. @@ -6,7 +6,7 @@ So far we have treated every geometry as opaque. Note however that the leaves ar image::../../../images/38_TASK08_alphacut_before.png[] -=== Task 7: Alpha-cut transparency +== Task 7: Alpha-cut transparency To implement alpha-cut transparency, we will discard fragments with low alpha values in the fragment shader. This is a common technique to handle transparent textures without needing complex blending or sorting: @@ -43,7 +43,7 @@ You will see that the shadows for the leaves are now completely missing! This is Before we do that, let's first inspect the acceleration structures we have built so far, to understand how they are structured and what information is available for each triangle. -=== Task 8: Inspect the acceleration structures with NVIDIA Nsight Graphics +== Task 8: Inspect the acceleration structures with NVIDIA Nsight Graphics RenderDoc does not yet support inspecting Vulkan acceleration structures, but we can use *Nsight Graphics* to verify that our BLAS/TLAS are built correctly. This helps catch mistakes (e.g. wrong geometry counts, offsets) before we rely on them in shaders. @@ -79,7 +79,7 @@ In the new window, you can see the TLAS and its instances: image::../../../images/38_TASK04_nsight_inspector.png[] -=== Task 9: Bindless resources and instance look-up table +== Task 9: Bindless resources and instance look-up table Until now, we did not need to know what triangle our ray intersected, we only cared about whether it hit something or not. But to implement transparency, we need to know the alpha value of the texture used to shade the point on the triangle we hit. This way we can determine if we hit a transparent pixel and we need to continue the traversal, in case we hit some other opaque triangle behind it on the way towards the light. @@ -169,7 +169,7 @@ StructuredBuffer instanceLUTBuffer; Now we will see how we can use these resources with ray query to handle transparent intersections. -=== Task 10: Ray query with alpha test +== Task 10: Ray query with alpha test Remember how `Proceed()` advances the state of the `RayQuery` object to the next intersection candidate along the ray? This is where we will implement our alpha test logic. We will check the alpha value of the texture used for shading the triangle we hit, and if it is below a certain threshold, we will continue the traversal to find the next opaque triangle. Once we find it, we 'commit' it, and the traversal will end. @@ -278,7 +278,7 @@ image::../../../images/38_TASK10_alphacut_shadows.png[] With everything set in place to support transparency in shadows, implementing other effects like reflections is very straightforward! -=== Navigation +== Navigation - Previous: xref:./04_TLAS_animation.adoc[TLAS animation] - Next: xref:./06_Reflections.adoc[Reflections] diff --git a/en/courses/18_Ray_tracing/06_Reflections.adoc b/en/courses/18_Ray_tracing/06_Reflections.adoc index cfc0769b..99d907d5 100644 --- a/en/courses/18_Ray_tracing/06_Reflections.adoc +++ b/en/courses/18_Ray_tracing/06_Reflections.adoc @@ -1,10 +1,10 @@ -== Ray Query Reflections += Ray Query Reflections *Objective*: We will cast a ray in the mirror-reflection direction from the fragment to see what it hits, simulating reflective materials (like a mirror or shiny surface). Reflections are implemented similarly to shadow rays, but we cast a ray from the shaded point along the mirror direction and sample the hit surface color. -=== Task 11: Implement ray query reflections +== Task 11: Implement ray query reflections First, we will use push constants to pass the reflective material flag to the fragment shader. This will allow us to determine if the current material is reflective or not. @@ -158,6 +158,6 @@ With all this in place, you should now see some shiny reflections on the table: image::../../../images/38_TASK11_alphacut_reflections.png[] -=== Navigation +== Navigation - Previous: xref:./05_Shadow_transparency.adoc[Shadow transparency] - Next: xref:./07_Conclusion.adoc[Conclusion] diff --git a/en/courses/18_Ray_tracing/07_Conclusion.adoc b/en/courses/18_Ray_tracing/07_Conclusion.adoc index f480b636..87d72d51 100644 --- a/en/courses/18_Ray_tracing/07_Conclusion.adoc +++ b/en/courses/18_Ray_tracing/07_Conclusion.adoc @@ -1,4 +1,4 @@ -== Conclusion += Conclusion In this course, you've implemented ray traced effects into a Vulkan rasterization pipeline using dynamic rendering and ray queries. Let's summarize the key points: @@ -12,7 +12,7 @@ In this course, you've implemented ray traced effects into a Vulkan rasterizatio We hope this lab gave you a hands-on taste of hybrid rendering with Vulkan's latest features. Happy rendering with Vulkan, and enjoy creating more advanced ray traced effects in your applications! -=== References +== References - Complete the full Vulkan Tutorial at https://github.com/KhronosGroup/Vulkan-Tutorial - Find more Vulkan documentation and resources at https://www.khronos.org/vulkan @@ -27,5 +27,5 @@ The 3D assets were provided by Poly Haven and combined using Blender: - https://polyhaven.com/a/potted_plant_02 - https://polyhaven.com/a/wooden_picnic_table -=== Navigation +== Navigation - Previous: xref:./06_Reflections.adoc[Reflections]