├── .gitmodules ├── 01-sample-triangle ├── .gitignore ├── premake5.lua ├── sample-triangle.sln ├── sample-triangle.vcxproj ├── sample-triangle.vcxproj.filters ├── sample-triangle.vcxproj.user ├── shaders │ ├── .vscode │ │ └── settings.json │ ├── build-shaders.bat │ ├── chit.rchit │ ├── miss.rmiss │ ├── raygen.rgen │ └── shader-common.h ├── src │ ├── DeviceVulkan.cpp │ ├── DeviceVulkan.h │ ├── logging.cpp │ ├── logging.h │ ├── main.cpp │ ├── pch.cpp │ └── pch.h └── update-proj.bat ├── 02-sample-gltf ├── .gitignore ├── premake5.lua ├── sample-gltf.sln ├── sample-gltf.vcxproj ├── sample-gltf.vcxproj.filters ├── sample-gltf.vcxproj.user ├── shaders │ ├── .vscode │ │ └── settings.json │ ├── build-shaders.bat │ ├── chit.rchit │ ├── miss.rmiss │ ├── raygen.rgen │ └── shader-common.h ├── src │ ├── Camera.cpp │ ├── Camera.h │ ├── DeviceVulkan.cpp │ ├── DeviceVulkan.h │ ├── logging.cpp │ ├── logging.h │ ├── main.cpp │ ├── pch.cpp │ └── pch.h └── update-proj.bat ├── 03-sample-shadows ├── .gitignore ├── premake5.lua ├── sample-shadows.sln ├── sample-shadows.vcxproj ├── sample-shadows.vcxproj.filters ├── sample-shadows.vcxproj.user ├── shaders │ ├── .vscode │ │ └── settings.json │ ├── build-shaders.bat │ ├── chit.rchit │ ├── miss.rmiss │ ├── raygen.rgen │ ├── shader-common.h │ ├── shadow-chit.rchit │ └── shadow-miss.rmiss ├── src │ ├── Camera.cpp │ ├── Camera.h │ ├── DeviceVulkan.cpp │ ├── DeviceVulkan.h │ ├── logging.cpp │ ├── logging.h │ ├── main.cpp │ ├── pch.cpp │ └── pch.h └── update-proj.bat ├── 04-sample-materials ├── .gitignore ├── premake5.lua ├── sample-materials.sln ├── sample-materials.vcxproj ├── sample-materials.vcxproj.filters ├── sample-materials.vcxproj.user ├── shaders │ ├── .vscode │ │ └── settings.json │ ├── build-shaders.bat │ ├── chit.rchit │ ├── miss.rmiss │ ├── raygen.rgen │ ├── shader-common.h │ ├── shadow-chit.rchit │ └── shadow-miss.rmiss ├── src │ ├── App.h │ ├── Camera.cpp │ ├── Camera.h │ ├── DeviceVulkan.cpp │ ├── DeviceVulkan.h │ ├── gltfLoader.cpp │ ├── gltfLoader.h │ ├── logging.cpp │ ├── logging.h │ ├── main.cpp │ ├── pch.cpp │ └── pch.h └── update-proj.bat ├── 05-sample-texture ├── .gitignore ├── premake5.lua ├── sample-texture.sln ├── sample-texture.vcxproj ├── sample-texture.vcxproj.filters ├── sample-texture.vcxproj.user ├── shaders │ ├── .vscode │ │ └── settings.json │ ├── build-shaders.bat │ ├── chit.rchit │ ├── miss.rmiss │ ├── raygen.rgen │ ├── shader-common.h │ ├── shadow-chit.rchit │ └── shadow-miss.rmiss ├── src │ ├── App.h │ ├── Camera.cpp │ ├── Camera.h │ ├── DeviceVulkan.cpp │ ├── DeviceVulkan.h │ ├── gltfLoader.cpp │ ├── gltfLoader.h │ ├── logging.cpp │ ├── logging.h │ ├── main.cpp │ ├── pch.cpp │ └── pch.h └── update-proj.bat ├── 06-sample-reflection ├── .gitignore ├── premake5.lua ├── sample-reflection.sln ├── sample-reflection.vcxproj ├── sample-reflection.vcxproj.filters ├── sample-reflection.vcxproj.user ├── shaders │ ├── .vscode │ │ └── settings.json │ ├── build-shaders.bat │ ├── chit.rchit │ ├── miss.rmiss │ ├── raygen.rgen │ ├── shader-common.h │ ├── shadow-chit.rchit │ └── shadow-miss.rmiss ├── src │ ├── App.h │ ├── Camera.cpp │ ├── Camera.h │ ├── DeviceVulkan.cpp │ ├── DeviceVulkan.h │ ├── gltfLoader.cpp │ ├── gltfLoader.h │ ├── logging.cpp │ ├── logging.h │ ├── main.cpp │ ├── pch.cpp │ └── pch.h └── update-proj.bat ├── 07-sample-refraction ├── .gitignore ├── premake5.lua ├── sample-refraction.sln ├── sample-refraction.vcxproj ├── sample-refraction.vcxproj.filters ├── sample-refraction.vcxproj.user ├── shaders │ ├── .vscode │ │ └── settings.json │ ├── build-shaders.bat │ ├── chit.rchit │ ├── miss.rmiss │ ├── raygen.rgen │ ├── shader-common.h │ ├── shadow-chit.rchit │ └── shadow-miss.rmiss ├── src │ ├── App.h │ ├── Camera.cpp │ ├── Camera.h │ ├── DeviceVulkan.cpp │ ├── DeviceVulkan.h │ ├── gltfLoader.cpp │ ├── gltfLoader.h │ ├── logging.cpp │ ├── logging.h │ ├── main.cpp │ ├── pch.cpp │ └── pch.h └── update-proj.bat ├── LICENSE ├── README.md ├── data ├── backface.gltf ├── backface2.gltf ├── christmas-sphere.gltf ├── christmas-spheres │ ├── ChristmasTreeOrnament05_col.png │ ├── christmas-sphere.bin │ └── christmas-sphere.gltf ├── colored-spheres.gltf ├── icosphere-2-subd.gltf ├── icosphere-4-subd.gltf ├── misc-boxes.gltf ├── reflection-test1.gltf ├── shadow-test1.gltf ├── shadow-test2.gltf └── transmissive1.gltf └── external └── glfw ├── LICENSE.md ├── include └── GLFW │ ├── glfw3.h │ └── glfw3native.h └── lib-vc2019 ├── glfw3.dll ├── glfw3.lib └── glfw3dll.lib /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/glm"] 2 | path = external/glm 3 | url = git@github.com:g-truc/glm.git 4 | [submodule "external/volk"] 5 | path = external/volk 6 | url = git@github.com:zeux/volk.git 7 | [submodule "external/tinygltf"] 8 | path = external/tinygltf 9 | url = git@github.com:syoyo/tinygltf.git 10 | -------------------------------------------------------------------------------- /01-sample-triangle/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | 3 | .vs/ 4 | bin/ 5 | obj/ 6 | 7 | *.spv 8 | 9 | -------------------------------------------------------------------------------- /01-sample-triangle/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "sample-triangle" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win64" } 4 | 5 | project "sample-triangle" 6 | kind "ConsoleApp" 7 | language "C++" 8 | cppdialect "C++17" 9 | 10 | pchheader "pch.h" 11 | pchsource "src/pch.cpp" 12 | 13 | libdirs { 14 | "../external/glfw/lib-vc2019" 15 | } 16 | links { 17 | "glfw3" 18 | } 19 | 20 | defines { 21 | "VOLK_STATIC_DEFINES", 22 | "VK_USE_PLATFORM_WIN32_KHR" 23 | } 24 | 25 | includedirs { 26 | "../external/glfw/include", 27 | "../external/glm", 28 | "../external/volk", 29 | "$(VULKAN_SDK)/Include", 30 | "src" 31 | } 32 | 33 | files { 34 | "../external/glfw/include/**.h", 35 | "../external/glm/glm/**.hpp", 36 | "../external/volk/volk.h", 37 | "../external/volk/volk.c", 38 | "src/**.h", 39 | "src/**.cpp" 40 | } 41 | 42 | filter { 43 | "files:../external/volk/volk.c" 44 | } 45 | flags { "NoPCH" } 46 | 47 | 48 | 49 | filter "platforms:Win64" 50 | system "Windows" 51 | architecture "x64" 52 | 53 | filter "configurations:Debug" 54 | targetsuffix "_D" 55 | defines { "DEBUG" } 56 | symbols "On" 57 | 58 | filter "configurations:Release" 59 | defines { "NDEBUG" } 60 | optimize "On" 61 | 62 | -------------------------------------------------------------------------------- /01-sample-triangle/sample-triangle.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-triangle", "sample-triangle.vcxproj", "{0A60F341-76EB-6006-7FFC-E3FAEB06BD06}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win64 = Debug|Win64 9 | Release|Win64 = Release|Win64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {0A60F341-76EB-6006-7FFC-E3FAEB06BD06}.Debug|Win64.ActiveCfg = Debug Win64|x64 13 | {0A60F341-76EB-6006-7FFC-E3FAEB06BD06}.Debug|Win64.Build.0 = Debug Win64|x64 14 | {0A60F341-76EB-6006-7FFC-E3FAEB06BD06}.Release|Win64.ActiveCfg = Release Win64|x64 15 | {0A60F341-76EB-6006-7FFC-E3FAEB06BD06}.Release|Win64.Build.0 = Release Win64|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /01-sample-triangle/sample-triangle.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /01-sample-triangle/shaders/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.h": "glsl" 4 | } 5 | } -------------------------------------------------------------------------------- /01-sample-triangle/shaders/build-shaders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call :build raygen.rgen 4 | call :build chit.rchit 5 | call :build miss.rmiss 6 | 7 | goto :eof 8 | 9 | :build 10 | %VULKAN_SDK%\bin\glslangValidator.exe -V %1 -o %1.spv 11 | goto :eof 12 | -------------------------------------------------------------------------------- /01-sample-triangle/shaders/chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 9 | 10 | void main() 11 | { 12 | PrimaryRay.color = vec3(0., 0., 1.); 13 | } 14 | -------------------------------------------------------------------------------- /01-sample-triangle/shaders/miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 8 | 9 | void main() 10 | { 11 | const vec3 backgroundColor = vec3(0., 1., 0.); 12 | PrimaryRay.color = backgroundColor; 13 | } 14 | -------------------------------------------------------------------------------- /01-sample-triangle/shaders/raygen.rgen: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 8 | layout(set = 0, binding = 1, rgba8) uniform image2D ResultImage; 9 | layout(set = 0, binding = 2, std140) uniform AppData { UniformParams Params; }; 10 | 11 | layout(location = 0) rayPayloadNV RayPayload PrimaryRay; 12 | 13 | void main() 14 | { 15 | const vec2 pixelCenter = vec2(gl_LaunchIDNV.xy) + vec2(0.5); 16 | const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeNV.xy); 17 | vec2 d = inUV * 2.0 - 1.0; 18 | 19 | vec4 origin = Params.viewInverse * vec4(0., 0., 0., 1.); 20 | vec4 target = Params.projInverse * vec4(d.x, d.y, 1., 1.); 21 | vec4 direction = Params.viewInverse * vec4(normalize(target.xyz), 0.); 22 | 23 | uint rayFlags = gl_RayFlagsOpaqueNV; 24 | uint cullMask = 0xFF; 25 | float tmin = 0.001; 26 | float tmax = 10000.0; 27 | 28 | traceNV(Scene, rayFlags, cullMask, 29 | 0, // sbtRecordOffset 30 | 0, // sbtRecordSize 31 | 0, // missIndex 32 | origin.xyz, 33 | tmin, direction.xyz, tmax, 34 | 0 // payload 35 | ); 36 | 37 | imageStore(ResultImage, ivec2(gl_LaunchIDNV.xy), vec4(PrimaryRay.color, 0.)); 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /01-sample-triangle/shaders/shader-common.h: -------------------------------------------------------------------------------- 1 | 2 | // packed std140 3 | struct UniformParams 4 | { 5 | mat4 viewInverse; 6 | mat4 projInverse; 7 | }; 8 | 9 | struct RayPayload 10 | { 11 | vec3 color; 12 | }; 13 | -------------------------------------------------------------------------------- /01-sample-triangle/src/DeviceVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VK_CHECK(_error) do { \ 4 | if (_error != VK_SUCCESS) { \ 5 | BASSERT(!#_error); \ 6 | } \ 7 | } while (false) 8 | 9 | 10 | struct BufferVulkan 11 | { 12 | VkDeviceSize size; 13 | VkBuffer buffer; 14 | VkDeviceMemory memory; 15 | }; 16 | 17 | struct BufferVulkanCreateInfo 18 | { 19 | VkDeviceSize size; 20 | VkBufferUsageFlags usage; 21 | VkMemoryPropertyFlags memoryProperties; 22 | void* pSrc; 23 | }; 24 | 25 | struct ImageVulkan 26 | { 27 | VkImageType type; 28 | VkFormat format; 29 | VkExtent3D extent; 30 | VkImage image; 31 | VkDeviceMemory memory; 32 | VkImageView view; 33 | }; 34 | 35 | struct ImageVulkanCreateInfo 36 | { 37 | VkImageType imageType; 38 | VkFormat format; 39 | VkExtent3D extent; 40 | VkImageUsageFlags usage; 41 | VkMemoryPropertyFlags memoryProperties; 42 | }; 43 | 44 | struct AccelerationStructureVulkan 45 | { 46 | VkDeviceMemory memory; 47 | VkAccelerationStructureInfoNV accelerationStructureInfo; 48 | VkAccelerationStructureNV accelerationStructure; 49 | uint64_t handle; 50 | }; 51 | 52 | struct AccelerationStructureVulkanCreateInfo 53 | { 54 | VkAccelerationStructureTypeNV type; 55 | uint32_t geometryCount; 56 | uint32_t instanceCount; 57 | VkGeometryNV* pGeometries; 58 | }; 59 | 60 | struct DeviceVulkan 61 | { 62 | VkInstance instance; 63 | VkPhysicalDevice physicalDevice; 64 | VkDevice device; 65 | 66 | uint32_t queueIndex; 67 | VkQueue queue; 68 | 69 | VkPhysicalDeviceRayTracingPropertiesNV rtProps; 70 | 71 | VkSurfaceKHR surface; 72 | VkSurfaceFormatKHR surfaceFormat; 73 | VkSwapchainKHR swapchain; 74 | 75 | std::vector swapchainImages; 76 | std::vector swapchainImageViews; 77 | std::vector waitForFrameFences; 78 | 79 | VkCommandPool commandPool; 80 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 81 | std::vector commandBuffers; 82 | VkSemaphore semaphoreImageAcquired; 83 | VkSemaphore semaphoreRenderFinished; 84 | VkDebugReportCallbackEXT debugCallback; 85 | }; 86 | 87 | struct DeviceVulkanCreateInfo 88 | { 89 | void* hwnd; 90 | uint32_t windowWidth; 91 | uint32_t windowHeight; 92 | }; 93 | 94 | bool createDeviceVulkan(const DeviceVulkanCreateInfo& ci, DeviceVulkan* deviceVulkan); 95 | 96 | void destroyDeviceVulkan(DeviceVulkan& vk); 97 | 98 | uint32_t getMemoryTypeVulkan(const DeviceVulkan& vk, VkMemoryRequirements& memoryRequirements, VkMemoryPropertyFlags memoryProperties); 99 | 100 | bool createBufferVulkan(const DeviceVulkan& vk, const BufferVulkanCreateInfo& ci, BufferVulkan* pBuffer); 101 | 102 | void destroyBufferVulkan(const DeviceVulkan& vk, BufferVulkan& buffer); 103 | 104 | bool createImageVulkan(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, ImageVulkan* pImage); 105 | 106 | void destroyImageVulkan(const DeviceVulkan& vk, ImageVulkan& image); 107 | 108 | bool createShaderVulkan(const DeviceVulkan& vk, const char* filename, VkShaderModule* pShaderModule); 109 | 110 | bool createAccelerationStructureVulkan(const DeviceVulkan& vk, 111 | const AccelerationStructureVulkanCreateInfo& ci, 112 | AccelerationStructureVulkan* pAccelerationStructure); 113 | 114 | void destroyAccelerationStructure(const DeviceVulkan& vk, 115 | AccelerationStructureVulkan& as); 116 | 117 | -------------------------------------------------------------------------------- /01-sample-triangle/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "logging.h" 4 | 5 | void DebugPrint(const char* fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | size_t len = _vscprintf(fmt, args); 10 | std::vector buff(len); 11 | vsnprintf_s(buff.data(), len, _TRUNCATE, fmt, args); 12 | OutputDebugStringA(buff.data()); 13 | va_end(args); 14 | } 15 | -------------------------------------------------------------------------------- /01-sample-triangle/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void DebugPrint(const char* fmt, ...); 4 | 5 | #define BASSERT(expr) ((void)((!!(expr)) || \ 6 | ((DebugPrint("Error: %s, %s:%d\n", #expr, __FILE__, __LINE__),1) \ 7 | && (__debugbreak(),0)) )) 8 | 9 | 10 | -------------------------------------------------------------------------------- /01-sample-triangle/src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /01-sample-triangle/src/pch.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #pragma warning(push) 13 | #pragma warning(disable: 26812) 14 | #include 15 | #pragma warning(pop) 16 | 17 | #define GLFW_EXPOSE_NATIVE_WIN32 18 | #include 19 | #include 20 | 21 | #define GLM_FORCE_RADIANS 22 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 23 | #include 24 | #include 25 | #include 26 | 27 | -------------------------------------------------------------------------------- /01-sample-triangle/update-proj.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | -------------------------------------------------------------------------------- /02-sample-gltf/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | 3 | .vs/ 4 | bin/ 5 | obj/ 6 | 7 | *.spv 8 | 9 | -------------------------------------------------------------------------------- /02-sample-gltf/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "sample-gltf" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win64" } 4 | 5 | project "sample-gltf" 6 | kind "ConsoleApp" 7 | language "C++" 8 | cppdialect "C++17" 9 | 10 | pchheader "pch.h" 11 | pchsource "src/pch.cpp" 12 | 13 | libdirs { 14 | "../external/glfw/lib-vc2019" 15 | } 16 | links { 17 | "glfw3" 18 | } 19 | 20 | defines { 21 | "VOLK_STATIC_DEFINES", 22 | "VK_USE_PLATFORM_WIN32_KHR" 23 | } 24 | 25 | includedirs { 26 | "../external/glfw/include", 27 | "../external/glm", 28 | "../external/volk", 29 | "../external/tinygltf", 30 | "$(VULKAN_SDK)/Include", 31 | "src" 32 | } 33 | 34 | files { 35 | "../external/glfw/include/**.h", 36 | "../external/glm/glm/**.hpp", 37 | "../external/glm/util/glm.natvis", 38 | "../external/volk/volk.h", 39 | "../external/volk/volk.c", 40 | "src/**.h", 41 | "src/**.cpp" 42 | } 43 | 44 | filter { 45 | "files:../external/volk/volk.c" 46 | } 47 | flags { "NoPCH" } 48 | 49 | 50 | 51 | filter "platforms:Win64" 52 | system "Windows" 53 | architecture "x64" 54 | 55 | filter "configurations:Debug" 56 | targetsuffix "_D" 57 | defines { "DEBUG" } 58 | symbols "On" 59 | 60 | filter "configurations:Release" 61 | defines { "NDEBUG" } 62 | optimize "On" 63 | 64 | -------------------------------------------------------------------------------- /02-sample-gltf/sample-gltf.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-gltf", "sample-gltf.vcxproj", "{E1BE6CBA-4D74-E5AF-D668-DF86421DDCB3}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win64 = Debug|Win64 9 | Release|Win64 = Release|Win64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {E1BE6CBA-4D74-E5AF-D668-DF86421DDCB3}.Debug|Win64.ActiveCfg = Debug Win64|x64 13 | {E1BE6CBA-4D74-E5AF-D668-DF86421DDCB3}.Debug|Win64.Build.0 = Debug Win64|x64 14 | {E1BE6CBA-4D74-E5AF-D668-DF86421DDCB3}.Release|Win64.ActiveCfg = Release Win64|x64 15 | {E1BE6CBA-4D74-E5AF-D668-DF86421DDCB3}.Release|Win64.Build.0 = Release Win64|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /02-sample-gltf/sample-gltf.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /02-sample-gltf/shaders/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.h": "glsl" 4 | } 5 | } -------------------------------------------------------------------------------- /02-sample-gltf/shaders/build-shaders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call :build raygen.rgen 4 | call :build chit.rchit 5 | call :build miss.rmiss 6 | 7 | goto :eof 8 | 9 | :build 10 | %VULKAN_SDK%\bin\glslangValidator.exe -V %1 -o %1.spv 11 | goto :eof 12 | -------------------------------------------------------------------------------- /02-sample-gltf/shaders/chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(set = 0, binding = 3) readonly buffer NormalsBuffer { vec4 n[]; } Normals; 9 | layout(set = 0, binding = 4) readonly buffer IndicesBuffer { uint i[]; } Indices; 10 | 11 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 12 | 13 | hitAttributeNV vec2 HitAttribs; 14 | 15 | vec3 interpolate(vec3 a, vec3 b, vec3 c, vec3 barycentrics) 16 | { 17 | return a * barycentrics.x + 18 | b * barycentrics.y + 19 | c * barycentrics.z; 20 | } 21 | 22 | void main() 23 | { 24 | ivec3 ind = ivec3( 25 | Indices.i[3 * gl_PrimitiveID], 26 | Indices.i[3 * gl_PrimitiveID + 1], 27 | Indices.i[3 * gl_PrimitiveID + 2] 28 | ); 29 | 30 | vec3 barycentrics = vec3(1.0 - HitAttribs.x - HitAttribs.y, HitAttribs.x, HitAttribs.y); 31 | 32 | // vec3 p0 = Positions.p[ind.x]; 33 | // vec3 p1 = Positions.p[ind.y]; 34 | // vec3 p2 = Positions.p[ind.z]; 35 | 36 | vec3 n0 = Normals.n[ind.x].xyz; 37 | vec3 n1 = Normals.n[ind.y].xyz; 38 | vec3 n2 = Normals.n[ind.z].xyz; 39 | 40 | vec3 N = normalize(interpolate(n0, n1, n2, barycentrics)); 41 | 42 | vec3 L = normalize(vec3(1., 1., 1.)); 43 | 44 | float ndotl = max(0., dot(N, L)); 45 | 46 | // PrimaryRay.color = p0; 47 | PrimaryRay.color = barycentrics; 48 | 49 | // PrimaryRay.color = normal; 50 | 51 | PrimaryRay.color = vec3(ndotl + 0.1); 52 | 53 | // PrimaryRay.color = N; 54 | 55 | 56 | // PrimaryRay.color = vec3(0., 0., 1.); 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /02-sample-gltf/shaders/miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 8 | 9 | void main() 10 | { 11 | const vec3 backgroundColor = vec3(0., 1., 0.); 12 | PrimaryRay.color = backgroundColor; 13 | } 14 | -------------------------------------------------------------------------------- /02-sample-gltf/shaders/raygen.rgen: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 8 | layout(set = 0, binding = 1, rgba8) uniform image2D ResultImage; 9 | layout(set = 0, binding = 2, std140) uniform AppData { UniformParams Params; }; 10 | 11 | layout(location = 0) rayPayloadNV RayPayload PrimaryRay; 12 | 13 | void main() 14 | { 15 | // https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays 16 | vec2 pixelRaster = gl_LaunchIDNV.xy; 17 | vec2 imageSize = gl_LaunchSizeNV.xy; 18 | 19 | // Compute raytacing NDC (note range [0,1]) 20 | vec2 pixelNDC = (pixelRaster + vec2(0.5)) / imageSize; 21 | 22 | // Remap to range [-1, 1] 23 | vec2 pixelSS = pixelNDC * 2.0 - 1.0; 24 | 25 | // Y is reversed (since raster, NDC & screen space have pos Y pointing down) 26 | pixelSS.y = 1.0 - 2.0 * pixelNDC.y; 27 | 28 | // Compute camera/view space. proj has fov, near, far 29 | vec4 pixelCS = Params.projInverse * vec4(pixelSS.x, pixelSS.y, 0., 1.); 30 | 31 | // Camera is at origin in camera space. Compute direction to pixel in camera spce. 32 | vec4 originCS = vec4(0., 0., 0., 1.); 33 | vec4 directionCS = vec4(normalize((pixelCS - originCS).xyz), 0.); 34 | 35 | // Compute world space values 36 | vec4 directionWS = Params.viewInverse * directionCS; 37 | vec4 originWS = Params.viewInverse * vec4(0., 0., 0., 1.); 38 | 39 | uint rayFlags = gl_RayFlagsOpaqueNV; 40 | uint cullMask = 0xFF; 41 | float tmin = 0.001; 42 | float tmax = 10000.0; 43 | 44 | traceNV(Scene, rayFlags, cullMask, 45 | 0, // sbtRecordOffset 46 | 0, // sbtRecordSize 47 | 0, // missIndex 48 | originWS.xyz, 49 | tmin, directionWS.xyz, tmax, 50 | 0 // payload 51 | ); 52 | 53 | imageStore(ResultImage, ivec2(gl_LaunchIDNV.xy), vec4(PrimaryRay.color, 0.)); 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /02-sample-gltf/shaders/shader-common.h: -------------------------------------------------------------------------------- 1 | 2 | // packed std140 3 | struct UniformParams 4 | { 5 | mat4 viewInverse; 6 | mat4 projInverse; 7 | }; 8 | 9 | struct RayPayload 10 | { 11 | vec3 color; 12 | }; 13 | -------------------------------------------------------------------------------- /02-sample-gltf/src/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "camera.h" 4 | 5 | void cameraMove(Camera& camera, const glm::vec3& value) 6 | { 7 | glm::vec3 right = glm::normalize(glm::cross(camera.forward, camera.up)); 8 | 9 | camera.position += right * value.x; 10 | camera.position += camera.up * value.y; 11 | camera.position += camera.forward * value.z; 12 | } 13 | 14 | void cameraRotate(Camera& camera, const float angleX, const float angleY) 15 | { 16 | glm::vec3 right = glm::cross(camera.forward, camera.up); 17 | 18 | glm::quat pitch = glm::angleAxis(glm::radians(angleY), right); 19 | glm::quat heading = glm::angleAxis(glm::radians(angleX), camera.up); 20 | 21 | glm::quat combined = glm::normalize(pitch * heading); 22 | 23 | camera.forward = glm::normalize(glm::rotate(combined, camera.forward)); 24 | } 25 | 26 | void cameraUpdateProjection(Camera& camera) 27 | { 28 | float left = camera.viewport[0]; 29 | float top = camera.viewport[1]; 30 | float right = camera.viewport[2]; 31 | float bottom = camera.viewport[3]; 32 | 33 | float aspect = float(right - left) / float(bottom - top); 34 | camera.projection = glm::perspectiveRH_ZO( 35 | glm::radians(camera.fovy), aspect, camera.nearz, camera.farz); 36 | } 37 | 38 | void cameraUpdateView(Camera& camera) 39 | { 40 | camera.view = glm::lookAtRH(camera.position, camera.position + camera.forward, camera.up); 41 | } 42 | -------------------------------------------------------------------------------- /02-sample-gltf/src/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Camera 4 | { 5 | std::array viewport; // left, top, right, bottom 6 | float fovy = 60.f; 7 | float nearz = 1.f; 8 | float farz = 1000.f; 9 | 10 | glm::vec3 position; 11 | glm::vec3 up; 12 | glm::vec3 forward; 13 | glm::quat rotation; 14 | glm::mat4 projection; 15 | glm::mat4 view; 16 | }; 17 | 18 | void cameraMove(Camera& camera, const glm::vec3& value); 19 | void cameraRotate(Camera& camera, const float angleX, const float angleY); 20 | void cameraUpdateProjection(Camera& camera); 21 | void cameraUpdateView(Camera& camera); 22 | 23 | -------------------------------------------------------------------------------- /02-sample-gltf/src/DeviceVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VK_CHECK(_error) do { \ 4 | if (_error != VK_SUCCESS) { \ 5 | BASSERT(!#_error); \ 6 | } \ 7 | } while (false) 8 | 9 | 10 | struct BufferVulkan 11 | { 12 | VkDeviceSize size; 13 | VkBuffer buffer; 14 | VkDeviceMemory memory; 15 | }; 16 | 17 | struct BufferVulkanCreateInfo 18 | { 19 | VkDeviceSize size; 20 | VkBufferUsageFlags usage; 21 | VkMemoryPropertyFlags memoryProperties; 22 | void* pSrc; 23 | }; 24 | 25 | struct ImageVulkan 26 | { 27 | VkImageType type; 28 | VkFormat format; 29 | VkExtent3D extent; 30 | VkImage image; 31 | VkDeviceMemory memory; 32 | VkImageView view; 33 | }; 34 | 35 | struct ImageVulkanCreateInfo 36 | { 37 | VkImageType imageType; 38 | VkFormat format; 39 | VkExtent3D extent; 40 | VkImageUsageFlags usage; 41 | VkMemoryPropertyFlags memoryProperties; 42 | }; 43 | 44 | struct AccelerationStructureVulkan 45 | { 46 | VkDeviceMemory memory; 47 | VkAccelerationStructureInfoNV accelerationStructureInfo; 48 | VkAccelerationStructureNV accelerationStructure; 49 | uint64_t handle; 50 | }; 51 | 52 | struct AccelerationStructureVulkanCreateInfo 53 | { 54 | VkAccelerationStructureTypeNV type; 55 | uint32_t geometryCount; 56 | uint32_t instanceCount; 57 | VkGeometryNV* pGeometries; 58 | }; 59 | 60 | struct DeviceVulkan 61 | { 62 | VkInstance instance; 63 | VkPhysicalDevice physicalDevice; 64 | VkDevice device; 65 | 66 | uint32_t queueIndex; 67 | VkQueue queue; 68 | 69 | VkPhysicalDeviceRayTracingPropertiesNV rtProps; 70 | 71 | VkSurfaceKHR surface; 72 | VkSurfaceFormatKHR surfaceFormat; 73 | VkSwapchainKHR swapchain; 74 | 75 | std::vector swapchainImages; 76 | std::vector swapchainImageViews; 77 | std::vector waitForFrameFences; 78 | 79 | VkCommandPool commandPool; 80 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 81 | std::vector commandBuffers; 82 | VkSemaphore semaphoreImageAcquired; 83 | VkSemaphore semaphoreRenderFinished; 84 | VkDebugReportCallbackEXT debugCallback; 85 | }; 86 | 87 | struct DeviceVulkanCreateInfo 88 | { 89 | void* hwnd; 90 | uint32_t windowWidth; 91 | uint32_t windowHeight; 92 | }; 93 | 94 | bool createDeviceVulkan(const DeviceVulkanCreateInfo& ci, DeviceVulkan* deviceVulkan); 95 | 96 | void destroyDeviceVulkan(DeviceVulkan& vk); 97 | 98 | uint32_t getMemoryTypeVulkan(const DeviceVulkan& vk, VkMemoryRequirements& memoryRequirements, VkMemoryPropertyFlags memoryProperties); 99 | 100 | bool createBufferVulkan(const DeviceVulkan& vk, const BufferVulkanCreateInfo& ci, BufferVulkan* pBuffer); 101 | 102 | void destroyBufferVulkan(const DeviceVulkan& vk, BufferVulkan& buffer); 103 | 104 | bool createImageVulkan(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, ImageVulkan* pImage); 105 | 106 | void destroyImageVulkan(const DeviceVulkan& vk, ImageVulkan& image); 107 | 108 | bool createShaderVulkan(const DeviceVulkan& vk, const char* filename, VkShaderModule* pShaderModule); 109 | 110 | bool createAccelerationStructureVulkan(const DeviceVulkan& vk, 111 | const AccelerationStructureVulkanCreateInfo& ci, 112 | AccelerationStructureVulkan* pAccelerationStructure); 113 | 114 | void destroyAccelerationStructure(const DeviceVulkan& vk, 115 | AccelerationStructureVulkan& as); 116 | 117 | -------------------------------------------------------------------------------- /02-sample-gltf/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "logging.h" 4 | 5 | void DebugPrint(const char* fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | size_t len = _vscprintf(fmt, args); 10 | std::vector buff(len); 11 | vsnprintf_s(buff.data(), len, _TRUNCATE, fmt, args); 12 | OutputDebugStringA(buff.data()); 13 | va_end(args); 14 | } 15 | -------------------------------------------------------------------------------- /02-sample-gltf/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void DebugPrint(const char* fmt, ...); 4 | 5 | #define BASSERT(expr) ((void)((!!(expr)) || \ 6 | ((DebugPrint("Error: %s, %s:%d\n", #expr, __FILE__, __LINE__),1) \ 7 | && (__debugbreak(),0)) )) 8 | 9 | 10 | -------------------------------------------------------------------------------- /02-sample-gltf/src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #define TINYGLTF_IMPLEMENTATION 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | // #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. 7 | #pragma warning(push) 8 | #pragma warning(disable : 4996) // printf unsafe 9 | #pragma warning(disable : 4267) // size_t -> uint32_t 10 | #include "tiny_gltf.h" 11 | #pragma warning(pop) 12 | -------------------------------------------------------------------------------- /02-sample-gltf/src/pch.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #pragma warning(push) 15 | #pragma warning(disable: 26812) 16 | #include 17 | #pragma warning(pop) 18 | 19 | #define GLFW_EXPOSE_NATIVE_WIN32 20 | #include 21 | #include 22 | 23 | #define GLM_ENABLE_EXPERIMENTAL 24 | #define GLM_FORCE_RADIANS 25 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | -------------------------------------------------------------------------------- /02-sample-gltf/update-proj.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | -------------------------------------------------------------------------------- /03-sample-shadows/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | 3 | .vs/ 4 | bin/ 5 | obj/ 6 | 7 | *.spv 8 | 9 | -------------------------------------------------------------------------------- /03-sample-shadows/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "sample-shadows" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win64" } 4 | 5 | project "sample-shadows" 6 | kind "ConsoleApp" 7 | language "C++" 8 | cppdialect "C++17" 9 | 10 | pchheader "pch.h" 11 | pchsource "src/pch.cpp" 12 | 13 | libdirs { 14 | "../external/glfw/lib-vc2019" 15 | } 16 | links { 17 | "glfw3" 18 | } 19 | 20 | defines { 21 | "VOLK_STATIC_DEFINES", 22 | "VK_USE_PLATFORM_WIN32_KHR" 23 | } 24 | 25 | includedirs { 26 | "../external/glfw/include", 27 | "../external/glm", 28 | "../external/volk", 29 | "../external/tinygltf", 30 | "$(VULKAN_SDK)/Include", 31 | "src" 32 | } 33 | 34 | files { 35 | "../external/glfw/include/**.h", 36 | "../external/glm/glm/**.hpp", 37 | "../external/glm/util/glm.natvis", 38 | "../external/volk/volk.h", 39 | "../external/volk/volk.c", 40 | "src/**.h", 41 | "src/**.cpp" 42 | } 43 | 44 | filter { 45 | "files:../external/volk/volk.c" 46 | } 47 | flags { "NoPCH" } 48 | 49 | 50 | 51 | filter "platforms:Win64" 52 | system "Windows" 53 | architecture "x64" 54 | 55 | filter "configurations:Debug" 56 | targetsuffix "_D" 57 | defines { "DEBUG" } 58 | symbols "On" 59 | 60 | filter "configurations:Release" 61 | defines { "NDEBUG" } 62 | optimize "On" 63 | 64 | -------------------------------------------------------------------------------- /03-sample-shadows/sample-shadows.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-shadows", "sample-shadows.vcxproj", "{6D93A6AC-5961-9AB2-42F5-0AD92E627617}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win64 = Debug|Win64 9 | Release|Win64 = Release|Win64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {6D93A6AC-5961-9AB2-42F5-0AD92E627617}.Debug|Win64.ActiveCfg = Debug Win64|x64 13 | {6D93A6AC-5961-9AB2-42F5-0AD92E627617}.Debug|Win64.Build.0 = Debug Win64|x64 14 | {6D93A6AC-5961-9AB2-42F5-0AD92E627617}.Release|Win64.ActiveCfg = Release Win64|x64 15 | {6D93A6AC-5961-9AB2-42F5-0AD92E627617}.Release|Win64.Build.0 = Release Win64|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /03-sample-shadows/sample-shadows.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /03-sample-shadows/shaders/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.h": "glsl" 4 | } 5 | } -------------------------------------------------------------------------------- /03-sample-shadows/shaders/build-shaders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call :build raygen.rgen 4 | call :build chit.rchit 5 | call :build shadow-chit.rchit 6 | call :build miss.rmiss 7 | call :build shadow-miss.rmiss 8 | 9 | goto :eof 10 | 11 | :build 12 | %VULKAN_SDK%\bin\glslangValidator.exe -V %1 -o %1.spv 13 | goto :eof 14 | -------------------------------------------------------------------------------- /03-sample-shadows/shaders/chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(set = 1, binding = 0) readonly buffer NormalsBuffer { vec4 n[]; } Normals[]; 9 | layout(set = 2, binding = 0) readonly buffer IndicesBuffer { uint i[]; } Indices[]; 10 | 11 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 12 | 13 | hitAttributeNV vec2 HitAttribs; 14 | 15 | vec3 interpolate(vec3 a, vec3 b, vec3 c, vec3 barycentrics) 16 | { 17 | return a * barycentrics.x + 18 | b * barycentrics.y + 19 | c * barycentrics.z; 20 | } 21 | 22 | void main() 23 | { 24 | ivec3 ind = ivec3( 25 | Indices[nonuniformEXT(gl_InstanceCustomIndexNV)].i[3 * gl_PrimitiveID], 26 | Indices[nonuniformEXT(gl_InstanceCustomIndexNV)].i[3 * gl_PrimitiveID + 1], 27 | Indices[nonuniformEXT(gl_InstanceCustomIndexNV)].i[3 * gl_PrimitiveID + 2] 28 | ); 29 | 30 | vec3 barycentrics = vec3(1.0 - HitAttribs.x - HitAttribs.y, HitAttribs.x, HitAttribs.y); 31 | 32 | vec3 n0 = Normals[nonuniformEXT(gl_InstanceCustomIndexNV)].n[ind.x].xyz; 33 | vec3 n1 = Normals[nonuniformEXT(gl_InstanceCustomIndexNV)].n[ind.y].xyz; 34 | vec3 n2 = Normals[nonuniformEXT(gl_InstanceCustomIndexNV)].n[ind.z].xyz; 35 | 36 | vec3 N = normalize(interpolate(n0, n1, n2, barycentrics)); 37 | 38 | vec3 L = normalize(vec3(1., 1., 1.)); 39 | 40 | float ndotl = max(0., dot(N, L)); 41 | 42 | vec3 color = vec3(ndotl + 0.1); 43 | 44 | PrimaryRay.color_distance = vec4(color, gl_HitTNV); 45 | } 46 | 47 | -------------------------------------------------------------------------------- /03-sample-shadows/shaders/miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 8 | 9 | void main() 10 | { 11 | const vec3 backgroundColor = vec3(0., 1., 0.); 12 | PrimaryRay.color_distance = vec4(backgroundColor, -1.0); 13 | } 14 | -------------------------------------------------------------------------------- /03-sample-shadows/shaders/raygen.rgen: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 8 | layout(set = 0, binding = 1, rgba8) uniform image2D ResultImage; 9 | layout(set = 0, binding = 2, std140) uniform AppData { UniformParams Params; }; 10 | 11 | layout(location = 0) rayPayloadNV RayPayload PrimaryRay; 12 | layout(location = 1) rayPayloadNV ShadowRayPayload ShadowRay; 13 | 14 | void main() 15 | { 16 | // https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays 17 | vec2 pixelRaster = gl_LaunchIDNV.xy; 18 | vec2 imageSize = gl_LaunchSizeNV.xy; 19 | 20 | // Compute raytacing NDC (note range [0,1]) 21 | vec2 pixelNDC = (pixelRaster + vec2(0.5)) / imageSize; 22 | 23 | // Remap to range [-1, 1] 24 | vec2 pixelSS = pixelNDC * 2.0 - 1.0; 25 | 26 | // Y is reversed (since raster, NDC & screen space have pos Y pointing down) 27 | pixelSS.y = 1.0 - 2.0 * pixelNDC.y; 28 | 29 | // Compute camera/view space. proj has fov, near, far 30 | vec4 pixelCS = Params.projInverse * vec4(pixelSS.x, pixelSS.y, 0., 1.); 31 | 32 | // Camera is at origin in camera space. Compute direction to pixel in camera spce. 33 | vec4 originCS = vec4(0., 0., 0., 1.); 34 | vec4 directionCS = vec4(normalize((pixelCS - originCS).xyz), 0.); 35 | 36 | // Compute world space values 37 | vec4 directionWS = Params.viewInverse * directionCS; 38 | vec4 originWS = Params.viewInverse * vec4(0., 0., 0., 1.); 39 | 40 | uint rayFlags = gl_RayFlagsOpaqueNV; 41 | float tmin = 0.001; 42 | float tmax = 10000.0; 43 | 44 | traceNV(Scene, rayFlags, 0xFF, 45 | 0, // sbtRecordOffset 46 | 0, // sbtRecordStride 47 | 0, // missIndex 48 | originWS.xyz, 49 | tmin, directionWS.xyz, tmax, 50 | 0 // payload 51 | ); 52 | 53 | vec3 hitColor = PrimaryRay.color_distance.rgb; 54 | vec3 hitNormal = PrimaryRay.normal.xyz; 55 | float hitDistance = PrimaryRay.color_distance.w; 56 | 57 | if (hitDistance >= 0.) 58 | { 59 | vec3 hitPos = originWS.xyz + directionWS.xyz * hitDistance; 60 | 61 | vec3 toLight = normalize(vec3(1., 1., 1.)); 62 | vec3 shadowRayOrigin = hitPos;// + hitNormal * 0.001; 63 | uint shadowRayFlags = gl_RayFlagsOpaqueNV | gl_RayFlagsTerminateOnFirstHitNV; 64 | 65 | traceNV(Scene, shadowRayFlags, 0xFF, 66 | 1, // offset 1 (choose 2nd hit shader) 67 | 0, // stride ?? 68 | 1, // offset 1 (choose 2nd miss shader) 69 | shadowRayOrigin, 70 | 0.001, toLight, tmax, 71 | 1 // payload location 1 72 | ); 73 | 74 | if (ShadowRay.distance > 0.) 75 | { 76 | // In shadow 77 | hitColor *= 0.3; 78 | } 79 | } 80 | 81 | imageStore(ResultImage, ivec2(gl_LaunchIDNV.xy), vec4(hitColor, 0.)); 82 | } 83 | 84 | 85 | -------------------------------------------------------------------------------- /03-sample-shadows/shaders/shader-common.h: -------------------------------------------------------------------------------- 1 | 2 | // packed std140 3 | struct UniformParams 4 | { 5 | mat4 viewInverse; 6 | mat4 projInverse; 7 | }; 8 | 9 | struct RayPayload 10 | { 11 | vec4 color_distance; 12 | vec4 normal; 13 | }; 14 | 15 | struct ShadowRayPayload 16 | { 17 | float distance; 18 | }; 19 | 20 | 21 | -------------------------------------------------------------------------------- /03-sample-shadows/shaders/shadow-chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 9 | 10 | void main() 11 | { 12 | ShadowRay.distance = gl_HitTNV; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /03-sample-shadows/shaders/shadow-miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 8 | 9 | void main() 10 | { 11 | ShadowRay.distance = -1.0; 12 | } 13 | -------------------------------------------------------------------------------- /03-sample-shadows/src/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "camera.h" 4 | 5 | void cameraMove(Camera& camera, const glm::vec3& value) 6 | { 7 | glm::vec3 right = glm::normalize(glm::cross(camera.forward, camera.up)); 8 | 9 | camera.position += right * value.x; 10 | camera.position += camera.up * value.y; 11 | camera.position += camera.forward * value.z; 12 | } 13 | 14 | void cameraRotate(Camera& camera, const float angleX, const float angleY) 15 | { 16 | glm::vec3 right = glm::cross(camera.forward, camera.up); 17 | 18 | glm::quat pitch = glm::angleAxis(glm::radians(angleY), right); 19 | glm::quat heading = glm::angleAxis(glm::radians(angleX), camera.up); 20 | 21 | glm::quat combined = glm::normalize(pitch * heading); 22 | 23 | camera.forward = glm::normalize(glm::rotate(combined, camera.forward)); 24 | } 25 | 26 | void cameraRotate(Camera& camera, const glm::quat& rotation) 27 | { 28 | //camera.up = glm::rotate(rotation, camera.up); 29 | camera.forward = glm::rotate(rotation, camera.forward); 30 | } 31 | 32 | void cameraUpdateProjection(Camera& camera) 33 | { 34 | float left = camera.viewport[0]; 35 | float top = camera.viewport[1]; 36 | float right = camera.viewport[2]; 37 | float bottom = camera.viewport[3]; 38 | 39 | float aspect = float(right - left) / float(bottom - top); 40 | camera.projection = glm::perspectiveRH_ZO( 41 | glm::radians(camera.fovy), aspect, camera.nearz, camera.farz); 42 | } 43 | 44 | void cameraUpdateView(Camera& camera) 45 | { 46 | camera.view = glm::lookAtRH(camera.position, camera.position + camera.forward, camera.up); 47 | } 48 | -------------------------------------------------------------------------------- /03-sample-shadows/src/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Camera 4 | { 5 | std::array viewport; // left, top, right, bottom 6 | float fovy = 60.f; 7 | float nearz = 1.f; 8 | float farz = 1000.f; 9 | 10 | glm::vec3 position; 11 | glm::vec3 up; 12 | glm::vec3 forward; 13 | glm::mat4 projection; 14 | glm::mat4 view; 15 | }; 16 | 17 | void cameraMove(Camera& camera, const glm::vec3& value); 18 | void cameraRotate(Camera& camera, const float angleX, const float angleY); 19 | void cameraRotate(Camera& camera, const glm::quat& rotation); 20 | void cameraUpdateProjection(Camera& camera); 21 | void cameraUpdateView(Camera& camera); 22 | 23 | -------------------------------------------------------------------------------- /03-sample-shadows/src/DeviceVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VK_CHECK(_error) do { \ 4 | if (_error != VK_SUCCESS) { \ 5 | BASSERT(!#_error); \ 6 | } \ 7 | } while (false) 8 | 9 | 10 | struct BufferVulkan 11 | { 12 | VkDeviceSize size; 13 | VkBuffer buffer; 14 | VkDeviceMemory memory; 15 | }; 16 | 17 | struct BufferVulkanCreateInfo 18 | { 19 | VkDeviceSize size; 20 | VkBufferUsageFlags usage; 21 | VkMemoryPropertyFlags memoryProperties; 22 | const void* pSrc; 23 | }; 24 | 25 | struct ImageVulkan 26 | { 27 | VkImageType type; 28 | VkFormat format; 29 | VkExtent3D extent; 30 | VkImage image; 31 | VkDeviceMemory memory; 32 | VkImageView view; 33 | }; 34 | 35 | struct ImageVulkanCreateInfo 36 | { 37 | VkImageType imageType; 38 | VkFormat format; 39 | VkExtent3D extent; 40 | VkImageUsageFlags usage; 41 | VkMemoryPropertyFlags memoryProperties; 42 | }; 43 | 44 | struct AccelerationStructureVulkan 45 | { 46 | VkDeviceMemory memory; 47 | VkAccelerationStructureInfoNV accelerationStructureInfo; 48 | VkAccelerationStructureNV accelerationStructure; 49 | uint64_t handle; 50 | }; 51 | 52 | struct AccelerationStructureVulkanCreateInfo 53 | { 54 | VkAccelerationStructureTypeNV type; 55 | uint32_t geometryCount; 56 | uint32_t instanceCount; 57 | VkGeometryNV* pGeometries; 58 | }; 59 | 60 | struct DeviceVulkan 61 | { 62 | VkInstance instance; 63 | VkPhysicalDevice physicalDevice; 64 | VkDevice device; 65 | 66 | uint32_t queueIndex; 67 | VkQueue queue; 68 | 69 | VkPhysicalDeviceRayTracingPropertiesNV rtProps; 70 | 71 | VkSurfaceKHR surface; 72 | VkSurfaceFormatKHR surfaceFormat; 73 | VkSwapchainKHR swapchain; 74 | 75 | std::vector swapchainImages; 76 | std::vector swapchainImageViews; 77 | std::vector waitForFrameFences; 78 | 79 | VkCommandPool commandPool; 80 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 81 | std::vector commandBuffers; 82 | VkSemaphore semaphoreImageAcquired; 83 | VkSemaphore semaphoreRenderFinished; 84 | VkDebugReportCallbackEXT debugCallback; 85 | }; 86 | 87 | struct DeviceVulkanCreateInfo 88 | { 89 | void* hwnd; 90 | uint32_t windowWidth; 91 | uint32_t windowHeight; 92 | }; 93 | 94 | bool createDeviceVulkan(const DeviceVulkanCreateInfo& ci, DeviceVulkan* deviceVulkan); 95 | 96 | void destroyDeviceVulkan(DeviceVulkan& vk); 97 | 98 | uint32_t getMemoryTypeVulkan(const DeviceVulkan& vk, VkMemoryRequirements& memoryRequirements, VkMemoryPropertyFlags memoryProperties); 99 | 100 | bool createBufferVulkan(const DeviceVulkan& vk, const BufferVulkanCreateInfo& ci, BufferVulkan* pBuffer); 101 | 102 | void destroyBufferVulkan(const DeviceVulkan& vk, BufferVulkan& buffer); 103 | 104 | bool createImageVulkan(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, ImageVulkan* pImage); 105 | 106 | void destroyImageVulkan(const DeviceVulkan& vk, ImageVulkan& image); 107 | 108 | bool createShaderVulkan(const DeviceVulkan& vk, const char* filename, VkShaderModule* pShaderModule); 109 | 110 | bool createAccelerationStructureVulkan(const DeviceVulkan& vk, 111 | const AccelerationStructureVulkanCreateInfo& ci, 112 | AccelerationStructureVulkan* pAccelerationStructure); 113 | 114 | void destroyAccelerationStructure(const DeviceVulkan& vk, 115 | AccelerationStructureVulkan& as); 116 | 117 | -------------------------------------------------------------------------------- /03-sample-shadows/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "logging.h" 4 | 5 | void DebugPrint(const char* fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | size_t len = _vscprintf(fmt, args); 10 | std::vector buff(len); 11 | vsnprintf_s(buff.data(), len, _TRUNCATE, fmt, args); 12 | OutputDebugStringA(buff.data()); 13 | va_end(args); 14 | } 15 | -------------------------------------------------------------------------------- /03-sample-shadows/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void DebugPrint(const char* fmt, ...); 4 | 5 | #define BASSERT(expr) ((void)((!!(expr)) || \ 6 | ((DebugPrint("Error: %s, %s:%d\n", #expr, __FILE__, __LINE__),1) \ 7 | && (__debugbreak(),0)) )) 8 | 9 | 10 | -------------------------------------------------------------------------------- /03-sample-shadows/src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #define TINYGLTF_IMPLEMENTATION 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | // #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. 7 | #pragma warning(push) 8 | #pragma warning(disable : 4996) // printf unsafe 9 | #pragma warning(disable : 4267) // size_t -> uint32_t 10 | #include "tiny_gltf.h" 11 | #pragma warning(pop) 12 | -------------------------------------------------------------------------------- /03-sample-shadows/src/pch.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #pragma warning(push) 15 | #pragma warning(disable: 26812) 16 | #include 17 | #pragma warning(pop) 18 | 19 | #define GLFW_EXPOSE_NATIVE_WIN32 20 | #include 21 | #include 22 | 23 | #define GLM_ENABLE_EXPERIMENTAL 24 | #define GLM_FORCE_RADIANS 25 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | -------------------------------------------------------------------------------- /03-sample-shadows/update-proj.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | -------------------------------------------------------------------------------- /04-sample-materials/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | 3 | .vs/ 4 | bin/ 5 | obj/ 6 | 7 | *.spv 8 | 9 | -------------------------------------------------------------------------------- /04-sample-materials/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "sample-materials" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win64" } 4 | 5 | project "sample-materials" 6 | kind "ConsoleApp" 7 | language "C++" 8 | cppdialect "C++17" 9 | 10 | pchheader "pch.h" 11 | pchsource "src/pch.cpp" 12 | 13 | libdirs { 14 | "../external/glfw/lib-vc2019" 15 | } 16 | links { 17 | "glfw3" 18 | } 19 | 20 | defines { 21 | "VOLK_STATIC_DEFINES", 22 | "VK_USE_PLATFORM_WIN32_KHR" 23 | } 24 | 25 | includedirs { 26 | "../external/glfw/include", 27 | "../external/glm", 28 | "../external/volk", 29 | "../external/tinygltf", 30 | "$(VULKAN_SDK)/Include", 31 | "src" 32 | } 33 | 34 | files { 35 | "../external/glfw/include/**.h", 36 | "../external/glm/glm/**.hpp", 37 | "../external/glm/util/glm.natvis", 38 | "../external/volk/volk.h", 39 | "../external/volk/volk.c", 40 | "src/**.h", 41 | "src/**.cpp" 42 | } 43 | 44 | filter { 45 | "files:../external/volk/volk.c" 46 | } 47 | flags { "NoPCH" } 48 | 49 | 50 | 51 | filter "platforms:Win64" 52 | system "Windows" 53 | architecture "x64" 54 | 55 | filter "configurations:Debug" 56 | targetsuffix "_D" 57 | defines { "DEBUG" } 58 | symbols "On" 59 | 60 | filter "configurations:Release" 61 | defines { "NDEBUG" } 62 | optimize "On" 63 | 64 | -------------------------------------------------------------------------------- /04-sample-materials/sample-materials.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-materials", "sample-materials.vcxproj", "{76B3F7F8-62AC-164B-8BDE-FBCF7736F656}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win64 = Debug|Win64 9 | Release|Win64 = Release|Win64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {76B3F7F8-62AC-164B-8BDE-FBCF7736F656}.Debug|Win64.ActiveCfg = Debug Win64|x64 13 | {76B3F7F8-62AC-164B-8BDE-FBCF7736F656}.Debug|Win64.Build.0 = Debug Win64|x64 14 | {76B3F7F8-62AC-164B-8BDE-FBCF7736F656}.Release|Win64.ActiveCfg = Release Win64|x64 15 | {76B3F7F8-62AC-164B-8BDE-FBCF7736F656}.Release|Win64.Build.0 = Release Win64|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /04-sample-materials/sample-materials.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /04-sample-materials/shaders/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.h": "glsl" 4 | } 5 | } -------------------------------------------------------------------------------- /04-sample-materials/shaders/build-shaders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call :build raygen.rgen 4 | call :build chit.rchit 5 | call :build shadow-chit.rchit 6 | call :build miss.rmiss 7 | call :build shadow-miss.rmiss 8 | 9 | goto :eof 10 | 11 | :build 12 | %VULKAN_SDK%\bin\glslangValidator.exe -V %1 -o %1.spv 13 | goto :eof 14 | -------------------------------------------------------------------------------- /04-sample-materials/shaders/chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | struct InstanceData 9 | { 10 | int materialID; 11 | }; 12 | 13 | struct Material 14 | { 15 | vec4 baseColor; 16 | }; 17 | 18 | // BONI note: I can use this structure and the Face elements will get tightly packed 19 | // without padding. If I put a uvec3 within this struct, however, padding will be added. 20 | // struct Face 21 | // { 22 | // uint i0; 23 | // uint i1; 24 | // uint i2; 25 | // }; 26 | // layout(set = 2, binding = 0) readonly buffer IndicesBuffer { uint i[]; } Indices[]; 27 | 28 | layout(set = 1, binding = 0) readonly buffer NormalsBuffer { float n[]; } Normals[]; 29 | layout(set = 2, binding = 0) readonly buffer IndicesBuffer { uint i[]; } Indices[]; 30 | 31 | layout(set = 0, binding = 3) readonly buffer MeshInstanceDataBuffer { InstanceData d[]; } MeshInstanceData; 32 | layout(set = 0, binding = 4) readonly buffer MaterialsBuffer { Material m[]; } Materials; 33 | 34 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 35 | 36 | hitAttributeNV vec2 HitAttribs; 37 | 38 | vec3 interpolate(vec3 a, vec3 b, vec3 c, vec3 barycentrics) 39 | { 40 | return a * barycentrics.x + 41 | b * barycentrics.y + 42 | c * barycentrics.z; 43 | } 44 | 45 | vec3 getBarycentric() 46 | { 47 | vec3 b; 48 | b.x = 1.0 - HitAttribs.x - HitAttribs.y; 49 | b.y = HitAttribs.x; 50 | b.z = HitAttribs.y; 51 | return b; 52 | } 53 | 54 | uvec3 getFaceIndex() 55 | { 56 | // BONI TODO: when do we _need_ to use nonuniformEXT ? 57 | // ivec3 ind = ivec3( 58 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID], 59 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 1], 60 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 2] 61 | // ); 62 | 63 | uvec3 f; 64 | f.x = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 0]; 65 | f.y = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 1]; 66 | f.z = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 2]; 67 | return f; 68 | } 69 | 70 | vec3 getOneNormal(uint index) 71 | { 72 | // vec3 n0 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.x].xyz; 73 | // vec3 n1 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.y].xyz; 74 | // vec3 n2 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.z].xyz; 75 | 76 | vec3 n; 77 | n.x = Normals[gl_InstanceID].n[3 * index + 0]; 78 | n.y = Normals[gl_InstanceID].n[3 * index + 1]; 79 | n.z = Normals[gl_InstanceID].n[3 * index + 2]; 80 | return n; 81 | } 82 | 83 | vec3 getNormalWS(uvec3 faceIndex, vec3 barycentric) 84 | { 85 | vec3 n0 = getOneNormal(faceIndex.x); 86 | vec3 n1 = getOneNormal(faceIndex.y); 87 | vec3 n2 = getOneNormal(faceIndex.z); 88 | 89 | vec3 n = normalize(interpolate(n0, n1, n2, barycentric)); 90 | 91 | vec3 N = normalize(vec3(gl_ObjectToWorldNV * vec4(n, 0.))); 92 | 93 | return N; 94 | } 95 | 96 | void main() 97 | { 98 | uvec3 faceIndex = getFaceIndex(); 99 | vec3 barycentric = getBarycentric(); 100 | 101 | vec3 baseColor = vec3(0.); 102 | 103 | int materialID = MeshInstanceData.d[gl_InstanceID].materialID; 104 | 105 | if (materialID >= 0) 106 | { 107 | baseColor = Materials.m[materialID].baseColor.rgb; 108 | } 109 | 110 | vec3 N = getNormalWS(faceIndex, barycentric); 111 | 112 | vec3 L = normalize(vec3(1., 1., 1.)); 113 | 114 | float ndotl = max(0., dot(N, L)); 115 | 116 | vec3 color = vec3(ndotl * baseColor + 0.1); 117 | 118 | PrimaryRay.color_distance = vec4(color, gl_HitTNV); 119 | PrimaryRay.normal = vec4(N, 0.); 120 | } 121 | 122 | -------------------------------------------------------------------------------- /04-sample-materials/shaders/miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 8 | 9 | void main() 10 | { 11 | const vec3 skyBlue = vec3(0.529, 0.808, 0.922); 12 | PrimaryRay.color_distance = vec4(skyBlue, -1.0); 13 | } 14 | -------------------------------------------------------------------------------- /04-sample-materials/shaders/raygen.rgen: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 8 | layout(set = 0, binding = 1, rgba8) uniform image2D ResultImage; 9 | layout(set = 0, binding = 2, std140) uniform AppData { UniformParams Params; }; 10 | 11 | layout(location = 0) rayPayloadNV RayPayload PrimaryRay; 12 | layout(location = 1) rayPayloadNV ShadowRayPayload ShadowRay; 13 | 14 | void main() 15 | { 16 | // https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays 17 | vec2 pixelRaster = gl_LaunchIDNV.xy; 18 | vec2 imageSize = gl_LaunchSizeNV.xy; 19 | 20 | // Compute raytacing NDC (note range [0,1]) 21 | vec2 pixelNDC = (pixelRaster + vec2(0.5)) / imageSize; 22 | 23 | // Remap to range [-1, 1] 24 | vec2 pixelSS = pixelNDC * 2.0 - 1.0; 25 | 26 | // Y is reversed (since raster, NDC & screen space have pos Y pointing down) 27 | pixelSS.y = 1.0 - 2.0 * pixelNDC.y; 28 | 29 | // Compute camera/view space. proj has fov, near, far 30 | vec4 pixelCS = Params.projInverse * vec4(pixelSS.x, pixelSS.y, 0., 1.); 31 | 32 | // Camera is at origin in camera space. Compute direction to pixel in camera spce. 33 | vec4 originCS = vec4(0., 0., 0., 1.); 34 | vec4 directionCS = vec4(normalize((pixelCS - originCS).xyz), 0.); 35 | 36 | // Compute world space values 37 | vec4 directionWS = Params.viewInverse * directionCS; 38 | vec4 originWS = Params.viewInverse * vec4(0., 0., 0., 1.); 39 | 40 | uint rayFlags = gl_RayFlagsOpaqueNV; 41 | float tmin = 0.001; 42 | float tmax = 10000.0; 43 | 44 | traceNV(Scene, rayFlags, 0xFF, 45 | 0, // sbtRecordOffset 46 | 0, // sbtRecordStride 47 | 0, // missIndex 48 | originWS.xyz, 49 | tmin, directionWS.xyz, tmax, 50 | 0 // payload 51 | ); 52 | 53 | vec3 hitColor = PrimaryRay.color_distance.rgb; 54 | float hitDistance = PrimaryRay.color_distance.w; 55 | 56 | if (hitDistance >= 0.) 57 | { 58 | vec3 hitPos = originWS.xyz + directionWS.xyz * hitDistance; 59 | 60 | vec3 hitNormal = PrimaryRay.normal.xyz; 61 | 62 | vec3 toLight = normalize(vec3(1., 1., 1.)); 63 | vec3 shadowRayOrigin = hitPos;// + hitNormal * 0.01; 64 | uint shadowRayFlags = gl_RayFlagsOpaqueNV | gl_RayFlagsTerminateOnFirstHitNV; 65 | 66 | traceNV(Scene, shadowRayFlags, 0xFF, 67 | 1, // offset 1 (choose 2nd hit shader) 68 | 0, // stride ?? 69 | 1, // offset 1 (choose 2nd miss shader) 70 | shadowRayOrigin, 71 | 2, // ?? adjusted for colored-sphere scene 72 | toLight, tmax, 73 | 1 // payload location 1 74 | ); 75 | 76 | if (ShadowRay.distance > 0.) 77 | { 78 | // In shadow 79 | hitColor *= 0.3; 80 | } 81 | 82 | // hitColor = hitNormal; 83 | } 84 | 85 | 86 | imageStore(ResultImage, ivec2(gl_LaunchIDNV.xy), vec4(hitColor, 0.)); 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /04-sample-materials/shaders/shader-common.h: -------------------------------------------------------------------------------- 1 | 2 | // packed std140 3 | struct UniformParams 4 | { 5 | mat4 viewInverse; 6 | mat4 projInverse; 7 | }; 8 | 9 | struct RayPayload 10 | { 11 | vec4 color_distance; 12 | vec4 normal; 13 | }; 14 | 15 | struct ShadowRayPayload 16 | { 17 | float distance; 18 | }; 19 | 20 | 21 | -------------------------------------------------------------------------------- /04-sample-materials/shaders/shadow-chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 9 | 10 | void main() 11 | { 12 | ShadowRay.distance = gl_HitTNV; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /04-sample-materials/shaders/shadow-miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 8 | 9 | void main() 10 | { 11 | ShadowRay.distance = -1.0; 12 | } 13 | -------------------------------------------------------------------------------- /04-sample-materials/src/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DeviceVulkan.h" 4 | #include "camera.h" 5 | 6 | 7 | // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/chap33.html#acceleration-structure 8 | struct VkGeometryInstance 9 | { 10 | float transform[12]; 11 | uint32_t instanceCustomIndex : 24; // gl_InstanceCustomIndexNV 12 | uint32_t mask : 8; 13 | uint32_t instanceOffset : 24; 14 | uint32_t flags : 8; 15 | uint64_t accelerationStructureHandle; 16 | }; 17 | 18 | struct Mesh 19 | { 20 | uint32_t vertexCount; 21 | uint32_t indexCount; 22 | 23 | int materialID; 24 | 25 | BufferVulkan positions; 26 | BufferVulkan normals; 27 | BufferVulkan indices; 28 | 29 | AccelerationStructureVulkan blas; 30 | }; 31 | 32 | // BONI NOTE: keep this padded to 16 bytes 33 | struct Material 34 | { 35 | glm::vec4 baseColor; 36 | }; 37 | 38 | struct CameraUniformData 39 | { 40 | glm::mat4 viewInverse; 41 | glm::mat4 projInverse; 42 | }; 43 | 44 | struct SceneNode 45 | { 46 | std::string name; 47 | 48 | glm::vec3 translation; 49 | glm::vec3 scale; 50 | glm::quat rotation; 51 | 52 | glm::mat4 matrix; 53 | 54 | std::vector children; 55 | 56 | int meshID; 57 | bool matrixValid; 58 | }; 59 | 60 | struct MeshInstanceData 61 | { 62 | int materialID; 63 | }; 64 | 65 | struct Scene 66 | { 67 | std::vector nodes; 68 | 69 | std::vector meshes; 70 | 71 | std::vector normalsBufferInfos; 72 | std::vector indicesBufferInfos; 73 | 74 | BufferVulkan cameraBuffer; 75 | BufferVulkan meshInstanceDataBuffer; 76 | BufferVulkan materialsBuffer; 77 | 78 | Camera camera; 79 | 80 | AccelerationStructureVulkan topLevelStruct; 81 | }; 82 | 83 | struct App 84 | { 85 | GLFWwindow* window; 86 | 87 | ImageVulkan offscreenImage; 88 | 89 | VkShaderModule raygenShader; 90 | VkShaderModule chitShader; 91 | VkShaderModule shadowChitShader; 92 | VkShaderModule missShader; 93 | VkShaderModule shadowMissShader; 94 | 95 | BufferVulkan instancesBuffer; 96 | BufferVulkan sbtBuffer; 97 | 98 | VkPipelineLayout pipelineLayout; 99 | VkPipeline rtPipeline; 100 | 101 | VkDescriptorPool descriptorPool; 102 | std::vector descriptorSetLayouts; 103 | std::vector descriptorSets; 104 | 105 | bool keysDown[GLFW_KEY_LAST + 1]; 106 | bool mouseDown[GLFW_MOUSE_BUTTON_LAST + 1]; 107 | glm::vec2 cursorPos; 108 | 109 | Scene scene; 110 | }; 111 | 112 | -------------------------------------------------------------------------------- /04-sample-materials/src/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "camera.h" 4 | 5 | void cameraMove(Camera& camera, const glm::vec3& value) 6 | { 7 | glm::vec3 right = glm::normalize(glm::cross(camera.forward, camera.up)); 8 | 9 | camera.position += right * value.x; 10 | camera.position += camera.up * value.y; 11 | camera.position += camera.forward * value.z; 12 | } 13 | 14 | void cameraRotate(Camera& camera, const float angleX, const float angleY) 15 | { 16 | glm::vec3 right = glm::cross(camera.forward, camera.up); 17 | 18 | glm::quat pitch = glm::angleAxis(glm::radians(angleY), right); 19 | glm::quat heading = glm::angleAxis(glm::radians(angleX), camera.up); 20 | 21 | glm::quat combined = glm::normalize(pitch * heading); 22 | 23 | camera.forward = glm::normalize(glm::rotate(combined, camera.forward)); 24 | } 25 | 26 | void cameraRotate(Camera& camera, const glm::quat& rotation) 27 | { 28 | //camera.up = glm::rotate(rotation, camera.up); 29 | camera.forward = glm::rotate(rotation, camera.forward); 30 | } 31 | 32 | void cameraUpdateProjection(Camera& camera) 33 | { 34 | float left = camera.viewport[0]; 35 | float top = camera.viewport[1]; 36 | float right = camera.viewport[2]; 37 | float bottom = camera.viewport[3]; 38 | 39 | float aspect = float(right - left) / float(bottom - top); 40 | camera.projection = glm::perspectiveRH_ZO( 41 | glm::radians(camera.fovy), aspect, camera.nearz, camera.farz); 42 | } 43 | 44 | void cameraUpdateView(Camera& camera) 45 | { 46 | camera.view = glm::lookAtRH(camera.position, camera.position + camera.forward, camera.up); 47 | } 48 | -------------------------------------------------------------------------------- /04-sample-materials/src/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Camera 4 | { 5 | std::array viewport; // left, top, right, bottom 6 | float fovy = 60.f; 7 | float nearz = 1.f; 8 | float farz = 1000.f; 9 | 10 | glm::vec3 position; 11 | glm::vec3 up; 12 | glm::vec3 forward; 13 | glm::mat4 projection; 14 | glm::mat4 view; 15 | }; 16 | 17 | void cameraMove(Camera& camera, const glm::vec3& value); 18 | void cameraRotate(Camera& camera, const float angleX, const float angleY); 19 | void cameraRotate(Camera& camera, const glm::quat& rotation); 20 | void cameraUpdateProjection(Camera& camera); 21 | void cameraUpdateView(Camera& camera); 22 | 23 | -------------------------------------------------------------------------------- /04-sample-materials/src/DeviceVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VK_CHECK(_error) do { \ 4 | if (_error != VK_SUCCESS) { \ 5 | BASSERT(!#_error); \ 6 | } \ 7 | } while (false) 8 | 9 | 10 | struct BufferVulkan 11 | { 12 | VkDeviceSize size; 13 | VkBuffer buffer; 14 | VkDeviceMemory memory; 15 | }; 16 | 17 | struct BufferVulkanCreateInfo 18 | { 19 | VkDeviceSize size; 20 | VkBufferUsageFlags usage; 21 | VkMemoryPropertyFlags memoryProperties; 22 | const void* pSrc; 23 | }; 24 | 25 | struct ImageVulkan 26 | { 27 | VkImageType type; 28 | VkFormat format; 29 | VkExtent3D extent; 30 | VkImage image; 31 | VkDeviceMemory memory; 32 | VkImageView view; 33 | }; 34 | 35 | struct ImageVulkanCreateInfo 36 | { 37 | VkImageType imageType; 38 | VkFormat format; 39 | VkExtent3D extent; 40 | VkImageUsageFlags usage; 41 | VkMemoryPropertyFlags memoryProperties; 42 | }; 43 | 44 | struct AccelerationStructureVulkan 45 | { 46 | VkDeviceMemory memory; 47 | VkAccelerationStructureInfoNV accelerationStructureInfo; 48 | VkAccelerationStructureNV accelerationStructure; 49 | uint64_t handle; 50 | }; 51 | 52 | struct AccelerationStructureVulkanCreateInfo 53 | { 54 | VkAccelerationStructureTypeNV type; 55 | uint32_t geometryCount; 56 | uint32_t instanceCount; 57 | VkGeometryNV* pGeometries; 58 | }; 59 | 60 | struct DeviceVulkan 61 | { 62 | VkInstance instance; 63 | VkPhysicalDevice physicalDevice; 64 | VkDevice device; 65 | 66 | uint32_t queueIndex; 67 | VkQueue queue; 68 | 69 | VkPhysicalDeviceRayTracingPropertiesNV rtProps; 70 | 71 | VkSurfaceKHR surface; 72 | VkSurfaceFormatKHR surfaceFormat; 73 | VkSwapchainKHR swapchain; 74 | 75 | std::vector swapchainImages; 76 | std::vector swapchainImageViews; 77 | std::vector waitForFrameFences; 78 | 79 | VkCommandPool commandPool; 80 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 81 | std::vector commandBuffers; 82 | VkSemaphore semaphoreImageAcquired; 83 | VkSemaphore semaphoreRenderFinished; 84 | VkDebugReportCallbackEXT debugCallback; 85 | }; 86 | 87 | struct DeviceVulkanCreateInfo 88 | { 89 | void* hwnd; 90 | uint32_t windowWidth; 91 | uint32_t windowHeight; 92 | }; 93 | 94 | bool createDeviceVulkan(const DeviceVulkanCreateInfo& ci, DeviceVulkan* deviceVulkan); 95 | 96 | void destroyDeviceVulkan(DeviceVulkan& vk); 97 | 98 | uint32_t getMemoryTypeVulkan(const DeviceVulkan& vk, VkMemoryRequirements& memoryRequirements, VkMemoryPropertyFlags memoryProperties); 99 | 100 | bool createBufferVulkan(const DeviceVulkan& vk, const BufferVulkanCreateInfo& ci, BufferVulkan* pBuffer); 101 | 102 | void destroyBufferVulkan(const DeviceVulkan& vk, BufferVulkan& buffer); 103 | 104 | bool createImageVulkan(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, ImageVulkan* pImage); 105 | 106 | void destroyImageVulkan(const DeviceVulkan& vk, ImageVulkan& image); 107 | 108 | bool createShaderVulkan(const DeviceVulkan& vk, const char* filename, VkShaderModule* pShaderModule); 109 | 110 | bool createAccelerationStructureVulkan(const DeviceVulkan& vk, 111 | const AccelerationStructureVulkanCreateInfo& ci, 112 | AccelerationStructureVulkan* pAccelerationStructure); 113 | 114 | void destroyAccelerationStructure(const DeviceVulkan& vk, 115 | AccelerationStructureVulkan& as); 116 | 117 | -------------------------------------------------------------------------------- /04-sample-materials/src/gltfLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "App.h" 4 | #include "logging.h" 5 | #include "gltfLoader.h" 6 | 7 | static bool readVec3(const std::vector& src, glm::vec3* dst, 8 | const glm::vec3& defaultValue = glm::vec3(0.f)) 9 | { 10 | if (src.size() > 0) 11 | { 12 | *dst = glm::vec3((float)src[0], (float)src[1], (float)src[2]); 13 | return true; 14 | } 15 | else 16 | { 17 | *dst = defaultValue; 18 | return false; 19 | } 20 | } 21 | 22 | static bool readVec4(const std::vector& src, glm::vec4* dst, 23 | const glm::vec4& defaultValue = glm::vec4(0.f)) 24 | { 25 | if (src.size() > 0) 26 | { 27 | *dst = glm::vec4((float)src[0], (float)src[1], (float)src[2], (float)src[3]); 28 | return true; 29 | } 30 | else 31 | { 32 | *dst = defaultValue; 33 | return false; 34 | } 35 | } 36 | 37 | static bool readQuat(std::vector& src, glm::quat* dst, 38 | const glm::quat& defaultValue = glm::quat(1.f, 0.f, 0.f, 0.f)) 39 | { 40 | // glm uses w, x, y, z 41 | if (src.size() > 0) 42 | { 43 | *dst = glm::quat((float)src[3], (float)src[0], (float)src[1], (float)src[2]); 44 | return true; 45 | } 46 | else 47 | { 48 | *dst = defaultValue; 49 | return false; 50 | } 51 | }; 52 | 53 | static void loadMesh(DeviceVulkan& vk, tinygltf::Model& gltfModel, 54 | tinygltf::Mesh& gltfMesh, Mesh* pMesh) 55 | { 56 | // Only handle single triangle primitives (for now). 57 | BASSERT(gltfMesh.primitives.size() == 1); 58 | 59 | auto& primitive = gltfMesh.primitives[0]; 60 | 61 | BASSERT(primitive.mode == TINYGLTF_MODE_TRIANGLES); 62 | 63 | auto& attrs = primitive.attributes; 64 | 65 | int idPosition = attrs.count("POSITION") == 1 ? attrs["POSITION"] : -1; 66 | int idNormal = attrs.count("NORMAL") == 1 ? attrs["NORMAL"] : -1; 67 | int idTexcoord0 = attrs.count("TEXCOORD_0") == 1 ? attrs["TEXCOORD_0"] : -1; 68 | int idIndices = primitive.indices; 69 | int idMaterial = primitive.material; 70 | 71 | pMesh->materialID = idMaterial; 72 | 73 | BASSERT(idPosition >= 0); 74 | 75 | // Load positions 76 | { 77 | BASSERT(gltfModel.accessors[idPosition].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 78 | && gltfModel.accessors[idPosition].type == TINYGLTF_TYPE_VEC3); 79 | 80 | pMesh->vertexCount = (uint32_t)gltfModel.accessors[idPosition].count; 81 | 82 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idPosition].bufferView]; 83 | 84 | //std::vector dbgPositions(bv.byteLength / 12); 85 | //memcpy(dbgPositions.data(), 86 | // &gltfModel.buffers[bv.buffer].data[bv.byteOffset], bv.byteLength); 87 | 88 | createBufferVulkan(vk, { bv.byteLength, 89 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | 90 | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 91 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 92 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 93 | &pMesh->positions); 94 | } 95 | 96 | // Load normals 97 | { 98 | BASSERT(idNormal >= 0); 99 | 100 | BASSERT(gltfModel.accessors[idNormal].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 101 | && gltfModel.accessors[idNormal].type == TINYGLTF_TYPE_VEC3); 102 | 103 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idNormal].bufferView]; 104 | 105 | auto normalCount = gltfModel.accessors[idNormal].count; 106 | 107 | createBufferVulkan(vk, { bv.byteLength, 108 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 109 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 110 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 111 | &pMesh->normals); 112 | } 113 | 114 | // Load indices 115 | { 116 | BASSERT(gltfModel.accessors[idIndices].componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT 117 | && gltfModel.accessors[idIndices].type == TINYGLTF_TYPE_SCALAR); 118 | 119 | uint32_t indexCount = (uint32_t)gltfModel.accessors[idIndices].count; 120 | pMesh->indexCount = indexCount; 121 | 122 | std::vector indices16(indexCount); 123 | 124 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idIndices].bufferView]; 125 | 126 | memcpy(indices16.data(), &gltfModel.buffers[bv.buffer].data[bv.byteOffset], 127 | bv.byteLength); 128 | 129 | std::vector indices32(indices16.begin(), indices16.end()); 130 | 131 | createBufferVulkan(vk, { indexCount * sizeof(uint32_t), 132 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | 133 | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 134 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 135 | indices32.data() }, &pMesh->indices); 136 | } 137 | } 138 | 139 | static void loadMeshes(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 140 | { 141 | // Load meshes 142 | size_t meshCount = model.meshes.size(); 143 | BASSERT(meshCount > 0); 144 | 145 | pScene->meshes.resize(meshCount); 146 | 147 | for (size_t i = 0; i < model.meshes.size(); i++) 148 | loadMesh(vk, model, model.meshes[i], &pScene->meshes[i]); 149 | } 150 | 151 | static void loadSceneNodes(tinygltf::Model& model, Scene* pScene) 152 | { 153 | // Load scene nodes 154 | BASSERT(model.defaultScene == 0); 155 | tinygltf::Scene& gltfScene = model.scenes[model.defaultScene]; 156 | 157 | pScene->nodes.reserve(gltfScene.nodes.size()); 158 | 159 | for (auto i : gltfScene.nodes) 160 | { 161 | auto& srcNode = model.nodes[i]; 162 | 163 | if (srcNode.mesh == -1) 164 | { 165 | // might be a light or camera. 166 | 167 | if (srcNode.children.size()) 168 | { 169 | auto& childNode = model.nodes[srcNode.children[0]]; 170 | if (childNode.camera >= 0) 171 | { 172 | readVec3(srcNode.translation, &pScene->camera.position, glm::vec3(0.f)); 173 | 174 | glm::quat rot1, rot2; 175 | if (readQuat(srcNode.rotation, &rot1)) 176 | { 177 | if (readQuat(childNode.rotation, &rot2)) 178 | { 179 | cameraRotate(pScene->camera, rot1 * rot2); 180 | } 181 | } 182 | 183 | cameraUpdateView(pScene->camera); 184 | } 185 | } 186 | 187 | continue; 188 | } 189 | 190 | pScene->nodes.push_back({}); 191 | SceneNode& dstNode = pScene->nodes.back(); 192 | 193 | dstNode.name = srcNode.name; 194 | dstNode.meshID = srcNode.mesh; 195 | dstNode.children = srcNode.children; 196 | 197 | readVec3(srcNode.translation, &dstNode.translation, glm::vec3(0.f)); 198 | readVec3(srcNode.scale, &dstNode.scale, glm::vec3(1.f)); 199 | readQuat(srcNode.rotation, &dstNode.rotation); 200 | 201 | if (srcNode.matrix.size() > 0) 202 | { 203 | dstNode.matrixValid = true; 204 | memcpy(glm::value_ptr(dstNode.matrix), srcNode.matrix.data(), 205 | sizeof(float) * 16); 206 | } 207 | else 208 | { 209 | dstNode.matrixValid = false; 210 | dstNode.matrix = glm::mat4(1.f); 211 | } 212 | } 213 | } 214 | 215 | static void loadMeshInstanceData(DeviceVulkan& vk, Scene* pScene) 216 | { 217 | std::vector meshInstanceData; 218 | meshInstanceData.reserve(pScene->nodes.size()); 219 | 220 | for (auto& node : pScene->nodes) 221 | { 222 | MeshInstanceData mid = {}; 223 | mid.materialID = pScene->meshes[node.meshID].materialID; 224 | 225 | meshInstanceData.push_back(mid); 226 | } 227 | 228 | createBufferVulkan(vk, { sizeof(MeshInstanceData) * meshInstanceData.size(), 229 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 230 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 231 | meshInstanceData.data() }, &pScene->meshInstanceDataBuffer); 232 | } 233 | 234 | static void loadMaterials(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 235 | { 236 | // Note: Only loading PBR Metal/Roughness properties (not specular extension) 237 | std::vector materials; 238 | materials.reserve(model.materials.size()); 239 | 240 | for (auto& m : model.materials) 241 | { 242 | Material mat = {}; 243 | 244 | readVec4(m.pbrMetallicRoughness.baseColorFactor, &mat.baseColor); 245 | 246 | materials.push_back(mat); 247 | } 248 | 249 | createBufferVulkan(vk, { sizeof(Material) * materials.size(), 250 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 251 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 252 | materials.data() }, &pScene->materialsBuffer); 253 | } 254 | 255 | bool loadGltfFile(DeviceVulkan& vk, const char* fn, Scene* pScene) 256 | { 257 | tinygltf::Model model; 258 | tinygltf::TinyGLTF loader; 259 | 260 | std::string err; 261 | std::string warn; 262 | bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, fn); 263 | BASSERT(ret); 264 | 265 | if (ret == false) 266 | { 267 | DebugPrint("Error: could not load %s\n", fn); 268 | return false; 269 | } 270 | 271 | if (model.scenes.size() == 0) 272 | { 273 | DebugPrint("Error: no scene found in %s\n", fn); 274 | return false; 275 | } 276 | 277 | loadMeshes(vk, model, pScene); 278 | 279 | loadSceneNodes(model, pScene); 280 | 281 | loadMeshInstanceData(vk, pScene); 282 | 283 | loadMaterials(vk, model, pScene); 284 | 285 | return true; 286 | } 287 | 288 | 289 | -------------------------------------------------------------------------------- /04-sample-materials/src/gltfLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | bool loadGltfFile(DeviceVulkan& vk, const char* fn, Scene* pScene); 5 | 6 | -------------------------------------------------------------------------------- /04-sample-materials/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "logging.h" 4 | 5 | void DebugPrint(const char* fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | size_t len = _vscprintf(fmt, args); 10 | std::vector buff(len); 11 | vsnprintf_s(buff.data(), len, _TRUNCATE, fmt, args); 12 | OutputDebugStringA(buff.data()); 13 | va_end(args); 14 | } 15 | -------------------------------------------------------------------------------- /04-sample-materials/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void DebugPrint(const char* fmt, ...); 4 | 5 | #define BASSERT(expr) ((void)((!!(expr)) || \ 6 | ((DebugPrint("Error: %s, %s:%d\n", #expr, __FILE__, __LINE__),1) \ 7 | && (__debugbreak(),0)) )) 8 | 9 | 10 | -------------------------------------------------------------------------------- /04-sample-materials/src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #define TINYGLTF_IMPLEMENTATION 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | // #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. 7 | #pragma warning(push) 8 | #pragma warning(disable : 4996) // printf unsafe 9 | #pragma warning(disable : 4267) // size_t -> uint32_t 10 | #include "tiny_gltf.h" 11 | #pragma warning(pop) 12 | -------------------------------------------------------------------------------- /04-sample-materials/src/pch.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #pragma warning(push) 15 | #pragma warning(disable: 26812) 16 | #include 17 | #pragma warning(pop) 18 | 19 | #define GLFW_EXPOSE_NATIVE_WIN32 20 | #include 21 | #include 22 | 23 | #define GLM_ENABLE_EXPERIMENTAL 24 | #define GLM_FORCE_RADIANS 25 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | -------------------------------------------------------------------------------- /04-sample-materials/update-proj.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | -------------------------------------------------------------------------------- /05-sample-texture/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | 3 | .vs/ 4 | bin/ 5 | obj/ 6 | 7 | *.spv 8 | 9 | -------------------------------------------------------------------------------- /05-sample-texture/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "sample-texture" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win64" } 4 | 5 | project "sample-texture" 6 | kind "ConsoleApp" 7 | language "C++" 8 | cppdialect "C++17" 9 | 10 | pchheader "pch.h" 11 | pchsource "src/pch.cpp" 12 | 13 | libdirs { 14 | "../external/glfw/lib-vc2019" 15 | } 16 | links { 17 | "glfw3" 18 | } 19 | 20 | defines { 21 | "VOLK_STATIC_DEFINES", 22 | "VK_USE_PLATFORM_WIN32_KHR" 23 | } 24 | 25 | includedirs { 26 | "../external/glfw/include", 27 | "../external/glm", 28 | "../external/volk", 29 | "../external/tinygltf", 30 | "$(VULKAN_SDK)/Include", 31 | "src" 32 | } 33 | 34 | files { 35 | "../external/glfw/include/**.h", 36 | "../external/glm/glm/**.hpp", 37 | "../external/glm/util/glm.natvis", 38 | "../external/volk/volk.h", 39 | "../external/volk/volk.c", 40 | "src/**.h", 41 | "src/**.cpp" 42 | } 43 | 44 | filter { 45 | "files:../external/volk/volk.c" 46 | } 47 | flags { "NoPCH" } 48 | 49 | 50 | 51 | filter "platforms:Win64" 52 | system "Windows" 53 | architecture "x64" 54 | 55 | filter "configurations:Debug" 56 | targetsuffix "_D" 57 | defines { "DEBUG" } 58 | symbols "On" 59 | 60 | filter "configurations:Release" 61 | defines { "NDEBUG" } 62 | optimize "On" 63 | 64 | -------------------------------------------------------------------------------- /05-sample-texture/sample-texture.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-texture", "sample-texture.vcxproj", "{C5684AF4-B136-3EFA-9ACA-AE2086371A5F}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win64 = Debug|Win64 9 | Release|Win64 = Release|Win64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {C5684AF4-B136-3EFA-9ACA-AE2086371A5F}.Debug|Win64.ActiveCfg = Debug Win64|x64 13 | {C5684AF4-B136-3EFA-9ACA-AE2086371A5F}.Debug|Win64.Build.0 = Debug Win64|x64 14 | {C5684AF4-B136-3EFA-9ACA-AE2086371A5F}.Release|Win64.ActiveCfg = Release Win64|x64 15 | {C5684AF4-B136-3EFA-9ACA-AE2086371A5F}.Release|Win64.Build.0 = Release Win64|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /05-sample-texture/sample-texture.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /05-sample-texture/shaders/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.h": "glsl" 4 | } 5 | } -------------------------------------------------------------------------------- /05-sample-texture/shaders/build-shaders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call :build raygen.rgen 4 | call :build chit.rchit 5 | call :build shadow-chit.rchit 6 | call :build miss.rmiss 7 | call :build shadow-miss.rmiss 8 | 9 | goto :eof 10 | 11 | :build 12 | %VULKAN_SDK%\bin\glslangValidator.exe -V %1 -o %1.spv 13 | goto :eof 14 | -------------------------------------------------------------------------------- /05-sample-texture/shaders/chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | struct InstanceData 9 | { 10 | int materialID; 11 | }; 12 | 13 | struct Material 14 | { 15 | vec4 baseColorFactor; 16 | }; 17 | 18 | layout(set = 0, binding = 3) readonly buffer MeshInstanceDataBuffer { InstanceData d[]; } MeshInstanceData; 19 | layout(set = 0, binding = 4) readonly buffer MaterialsBuffer { Material m[]; } Materials; 20 | 21 | layout(set = 1, binding = 0) readonly buffer NormalsBuffer { float n[]; } Normals[]; 22 | layout(set = 2, binding = 0) readonly buffer UvsBuffer { vec2 uv[]; } Uvs[]; 23 | layout(set = 3, binding = 0) readonly buffer IndicesBuffer { uint i[]; } Indices[]; 24 | 25 | layout(set = 4, binding = 0) uniform sampler LinearSampler; 26 | layout(set = 4, binding = 1) uniform texture2D BaseColorTextures[]; 27 | 28 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 29 | 30 | hitAttributeNV vec2 HitAttribs; 31 | 32 | vec2 interpolate(vec2 a, vec2 b, vec2 c, vec3 barycentrics) 33 | { 34 | return a * barycentrics.x + 35 | b * barycentrics.y + 36 | c * barycentrics.z; 37 | } 38 | 39 | vec3 interpolate(vec3 a, vec3 b, vec3 c, vec3 barycentrics) 40 | { 41 | return a * barycentrics.x + 42 | b * barycentrics.y + 43 | c * barycentrics.z; 44 | } 45 | 46 | vec3 getBarycentric() 47 | { 48 | vec3 b; 49 | b.x = 1.0 - HitAttribs.x - HitAttribs.y; 50 | b.y = HitAttribs.x; 51 | b.z = HitAttribs.y; 52 | return b; 53 | } 54 | 55 | uvec3 getFaceIndex() 56 | { 57 | // BONI TODO: when do we _need_ to use nonuniformEXT ? 58 | // ivec3 ind = ivec3( 59 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID], 60 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 1], 61 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 2] 62 | // ); 63 | 64 | uvec3 f; 65 | f.x = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 0]; 66 | f.y = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 1]; 67 | f.z = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 2]; 68 | return f; 69 | } 70 | 71 | vec3 getOneNormal(uint index) 72 | { 73 | // vec3 n0 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.x].xyz; 74 | // vec3 n1 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.y].xyz; 75 | // vec3 n2 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.z].xyz; 76 | 77 | vec3 n; 78 | n.x = Normals[gl_InstanceID].n[3 * index + 0]; 79 | n.y = Normals[gl_InstanceID].n[3 * index + 1]; 80 | n.z = Normals[gl_InstanceID].n[3 * index + 2]; 81 | return n; 82 | } 83 | 84 | vec3 getNormalWS(uvec3 faceIndex, vec3 barycentric) 85 | { 86 | vec3 n0 = getOneNormal(faceIndex.x); 87 | vec3 n1 = getOneNormal(faceIndex.y); 88 | vec3 n2 = getOneNormal(faceIndex.z); 89 | 90 | vec3 n = normalize(interpolate(n0, n1, n2, barycentric)); 91 | 92 | vec3 N = normalize(vec3(gl_ObjectToWorldNV * vec4(n, 0.))); 93 | 94 | return N; 95 | } 96 | 97 | vec2 getUv(uvec3 faceIndex, vec3 barycentric) 98 | { 99 | vec2 uv0 = Uvs[gl_InstanceID].uv[faceIndex.x]; 100 | vec2 uv1 = Uvs[gl_InstanceID].uv[faceIndex.y]; 101 | vec2 uv2 = Uvs[gl_InstanceID].uv[faceIndex.z]; 102 | 103 | vec2 uv = interpolate(uv0, uv1, uv2, barycentric); 104 | return uv; 105 | } 106 | 107 | void main() 108 | { 109 | uvec3 faceIndex = getFaceIndex(); 110 | vec3 barycentric = getBarycentric(); 111 | 112 | vec3 baseColor = vec3(1., 1., 1.); 113 | 114 | int materialID = MeshInstanceData.d[gl_InstanceID].materialID; 115 | vec2 uv = getUv(faceIndex, barycentric); 116 | 117 | // BONI TODO: remove these if checks by having defaults 118 | if (materialID >= 0) 119 | { 120 | vec3 baseColorFactor = Materials.m[materialID].baseColorFactor.rgb; 121 | 122 | vec3 baseColorSample = texture(sampler2D(BaseColorTextures[materialID], LinearSampler), uv).rgb; 123 | 124 | baseColor = baseColorSample * baseColorFactor; 125 | } 126 | 127 | vec3 N = getNormalWS(faceIndex, barycentric); 128 | 129 | vec3 L = normalize(vec3(1., 1., 1.)); 130 | 131 | float ndotl = max(0., dot(N, L)); 132 | 133 | vec3 color = vec3(ndotl * baseColor + 0.1); 134 | 135 | PrimaryRay.color_distance = vec4(color, gl_HitTNV); 136 | PrimaryRay.normal = vec4(N, 0.); 137 | } 138 | 139 | -------------------------------------------------------------------------------- /05-sample-texture/shaders/miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 8 | 9 | void main() 10 | { 11 | const vec3 skyBlue = vec3(0.529, 0.808, 0.922); 12 | PrimaryRay.color_distance = vec4(skyBlue, -1.0); 13 | } 14 | -------------------------------------------------------------------------------- /05-sample-texture/shaders/raygen.rgen: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 8 | layout(set = 0, binding = 1, rgba8) uniform image2D ResultImage; 9 | layout(set = 0, binding = 2, std140) uniform AppData { UniformParams Params; }; 10 | 11 | layout(location = 0) rayPayloadNV RayPayload PrimaryRay; 12 | layout(location = 1) rayPayloadNV ShadowRayPayload ShadowRay; 13 | 14 | void main() 15 | { 16 | // https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays 17 | vec2 pixelRaster = gl_LaunchIDNV.xy; 18 | vec2 imageSize = gl_LaunchSizeNV.xy; 19 | 20 | // Compute raytacing NDC (note range [0,1]) 21 | vec2 pixelNDC = (pixelRaster + vec2(0.5)) / imageSize; 22 | 23 | // Remap to range [-1, 1] 24 | vec2 pixelSS = pixelNDC * 2.0 - 1.0; 25 | 26 | // Y is reversed (since raster, NDC & screen space have pos Y pointing down) 27 | pixelSS.y = 1.0 - 2.0 * pixelNDC.y; 28 | 29 | // Compute camera/view space. proj has fov, near, far 30 | vec4 pixelCS = Params.projInverse * vec4(pixelSS.x, pixelSS.y, 0., 1.); 31 | 32 | // Camera is at origin in camera space. Compute direction to pixel in camera spce. 33 | vec4 originCS = vec4(0., 0., 0., 1.); 34 | vec4 directionCS = vec4(normalize((pixelCS - originCS).xyz), 0.); 35 | 36 | // Compute world space values 37 | vec4 directionWS = Params.viewInverse * directionCS; 38 | vec4 originWS = Params.viewInverse * vec4(0., 0., 0., 1.); 39 | 40 | uint rayFlags = gl_RayFlagsOpaqueNV; 41 | float tmin = 0.001; 42 | float tmax = 10000.0; 43 | 44 | traceNV(Scene, rayFlags, 0xFF, 45 | 0, // sbtRecordOffset 46 | 0, // sbtRecordStride 47 | 0, // missIndex 48 | originWS.xyz, 49 | tmin, directionWS.xyz, tmax, 50 | 0 // payload 51 | ); 52 | 53 | vec3 hitColor = PrimaryRay.color_distance.rgb; 54 | float hitDistance = PrimaryRay.color_distance.w; 55 | 56 | if (hitDistance >= 0.) 57 | { 58 | vec3 hitPos = originWS.xyz + directionWS.xyz * hitDistance; 59 | 60 | vec3 hitNormal = PrimaryRay.normal.xyz; 61 | 62 | vec3 toLight = normalize(vec3(1., 1., 1.)); 63 | vec3 shadowRayOrigin = hitPos;// + hitNormal * 0.01; 64 | uint shadowRayFlags = gl_RayFlagsOpaqueNV | gl_RayFlagsTerminateOnFirstHitNV; 65 | 66 | traceNV(Scene, shadowRayFlags, 0xFF, 67 | 1, // offset 1 (choose 2nd hit shader) 68 | 0, // stride ?? 69 | 1, // offset 1 (choose 2nd miss shader) 70 | shadowRayOrigin, 71 | 2, // ?? adjusted for colored-sphere scene 72 | toLight, tmax, 73 | 1 // payload location 1 74 | ); 75 | 76 | if (ShadowRay.distance > 0.) 77 | { 78 | // In shadow 79 | hitColor *= 0.3; 80 | } 81 | 82 | // hitColor = hitNormal; 83 | } 84 | 85 | 86 | imageStore(ResultImage, ivec2(gl_LaunchIDNV.xy), vec4(hitColor, 0.)); 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /05-sample-texture/shaders/shader-common.h: -------------------------------------------------------------------------------- 1 | 2 | // packed std140 3 | struct UniformParams 4 | { 5 | mat4 viewInverse; 6 | mat4 projInverse; 7 | }; 8 | 9 | struct RayPayload 10 | { 11 | vec4 color_distance; 12 | vec4 normal; 13 | }; 14 | 15 | struct ShadowRayPayload 16 | { 17 | float distance; 18 | }; 19 | 20 | 21 | -------------------------------------------------------------------------------- /05-sample-texture/shaders/shadow-chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 9 | 10 | void main() 11 | { 12 | ShadowRay.distance = gl_HitTNV; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /05-sample-texture/shaders/shadow-miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 8 | 9 | void main() 10 | { 11 | ShadowRay.distance = -1.0; 12 | } 13 | -------------------------------------------------------------------------------- /05-sample-texture/src/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DeviceVulkan.h" 4 | #include "camera.h" 5 | 6 | 7 | // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/chap33.html#acceleration-structure 8 | struct VkGeometryInstance 9 | { 10 | float transform[12]; 11 | uint32_t instanceCustomIndex : 24; // gl_InstanceCustomIndexNV 12 | uint32_t mask : 8; 13 | uint32_t instanceOffset : 24; 14 | uint32_t flags : 8; 15 | uint64_t accelerationStructureHandle; 16 | }; 17 | 18 | struct Mesh 19 | { 20 | uint32_t vertexCount; 21 | uint32_t indexCount; 22 | 23 | int materialID; 24 | 25 | BufferVulkan positions; 26 | BufferVulkan normals; 27 | BufferVulkan uvs; 28 | BufferVulkan indices; 29 | 30 | AccelerationStructureVulkan blas; 31 | }; 32 | 33 | // BONI NOTE: keep this padded to 16 bytes 34 | struct Material 35 | { 36 | glm::vec4 baseColorFactor; 37 | }; 38 | 39 | struct CameraUniformData 40 | { 41 | glm::mat4 viewInverse; 42 | glm::mat4 projInverse; 43 | }; 44 | 45 | struct SceneNode 46 | { 47 | std::string name; 48 | 49 | glm::vec3 translation; 50 | glm::vec3 scale; 51 | glm::quat rotation; 52 | 53 | glm::mat4 matrix; 54 | 55 | std::vector children; 56 | 57 | int meshID; 58 | bool matrixValid; 59 | }; 60 | 61 | struct MeshInstanceData 62 | { 63 | int materialID; 64 | }; 65 | 66 | struct Scene 67 | { 68 | std::vector nodes; 69 | 70 | std::vector meshes; 71 | 72 | std::vector normalsBufferInfos; 73 | std::vector uvsBufferInfos; 74 | std::vector indicesBufferInfos; 75 | 76 | std::vector textures; 77 | 78 | std::vector baseColorTextureInfos; 79 | 80 | ImageVulkan fallbackTextureBlack; 81 | ImageVulkan fallbackTextureWhite; 82 | 83 | BufferVulkan cameraBuffer; 84 | BufferVulkan meshInstanceDataBuffer; 85 | BufferVulkan materialsBuffer; 86 | 87 | VkSampler linearSampler; 88 | 89 | Camera camera; 90 | 91 | AccelerationStructureVulkan topLevelStruct; 92 | }; 93 | 94 | struct App 95 | { 96 | GLFWwindow* window; 97 | 98 | ImageVulkan offscreenImage; 99 | 100 | VkShaderModule raygenShader; 101 | VkShaderModule chitShader; 102 | VkShaderModule shadowChitShader; 103 | VkShaderModule missShader; 104 | VkShaderModule shadowMissShader; 105 | 106 | BufferVulkan instancesBuffer; 107 | BufferVulkan sbtBuffer; 108 | 109 | VkPipelineLayout pipelineLayout; 110 | VkPipeline rtPipeline; 111 | 112 | VkDescriptorPool descriptorPool; 113 | std::vector descriptorSetLayouts; 114 | std::vector descriptorSets; 115 | 116 | bool keysDown[GLFW_KEY_LAST + 1]; 117 | bool mouseDown[GLFW_MOUSE_BUTTON_LAST + 1]; 118 | glm::vec2 cursorPos; 119 | 120 | Scene scene; 121 | }; 122 | 123 | -------------------------------------------------------------------------------- /05-sample-texture/src/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "camera.h" 4 | 5 | void cameraMove(Camera& camera, const glm::vec3& value) 6 | { 7 | glm::vec3 right = glm::normalize(glm::cross(camera.forward, camera.up)); 8 | 9 | camera.position += right * value.x; 10 | camera.position += camera.up * value.y; 11 | camera.position += camera.forward * value.z; 12 | } 13 | 14 | void cameraRotate(Camera& camera, const float angleX, const float angleY) 15 | { 16 | glm::vec3 right = glm::cross(camera.forward, camera.up); 17 | 18 | glm::quat pitch = glm::angleAxis(glm::radians(angleY), right); 19 | glm::quat heading = glm::angleAxis(glm::radians(angleX), camera.up); 20 | 21 | glm::quat combined = glm::normalize(pitch * heading); 22 | 23 | camera.forward = glm::normalize(glm::rotate(combined, camera.forward)); 24 | } 25 | 26 | void cameraRotate(Camera& camera, const glm::quat& rotation) 27 | { 28 | //camera.up = glm::rotate(rotation, camera.up); 29 | camera.forward = glm::rotate(rotation, camera.forward); 30 | } 31 | 32 | void cameraUpdateProjection(Camera& camera) 33 | { 34 | float left = camera.viewport[0]; 35 | float top = camera.viewport[1]; 36 | float right = camera.viewport[2]; 37 | float bottom = camera.viewport[3]; 38 | 39 | float aspect = float(right - left) / float(bottom - top); 40 | camera.projection = glm::perspectiveRH_ZO( 41 | glm::radians(camera.fovy), aspect, camera.nearz, camera.farz); 42 | } 43 | 44 | void cameraUpdateView(Camera& camera) 45 | { 46 | camera.view = glm::lookAtRH(camera.position, camera.position + camera.forward, camera.up); 47 | } 48 | -------------------------------------------------------------------------------- /05-sample-texture/src/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Camera 4 | { 5 | std::array viewport; // left, top, right, bottom 6 | float fovy = 60.f; 7 | float nearz = 1.f; 8 | float farz = 1000.f; 9 | 10 | glm::vec3 position; 11 | glm::vec3 up; 12 | glm::vec3 forward; 13 | glm::mat4 projection; 14 | glm::mat4 view; 15 | }; 16 | 17 | void cameraMove(Camera& camera, const glm::vec3& value); 18 | void cameraRotate(Camera& camera, const float angleX, const float angleY); 19 | void cameraRotate(Camera& camera, const glm::quat& rotation); 20 | void cameraUpdateProjection(Camera& camera); 21 | void cameraUpdateView(Camera& camera); 22 | 23 | -------------------------------------------------------------------------------- /05-sample-texture/src/DeviceVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VK_CHECK(_error) do { \ 4 | if (_error != VK_SUCCESS) { \ 5 | BASSERT(!#_error); \ 6 | } \ 7 | } while (false) 8 | 9 | 10 | struct BufferVulkan 11 | { 12 | VkDeviceSize size; 13 | VkBuffer buffer; 14 | VkDeviceMemory memory; 15 | }; 16 | 17 | struct BufferVulkanCreateInfo 18 | { 19 | VkDeviceSize size; 20 | VkBufferUsageFlags usage; 21 | VkMemoryPropertyFlags memoryProperties; 22 | const void* pSrc; 23 | }; 24 | 25 | struct ImageVulkan 26 | { 27 | VkImageType type; 28 | VkFormat format; 29 | VkExtent3D extent; 30 | 31 | VkImage image; 32 | VkImageView view; 33 | 34 | VkDeviceMemory memory; 35 | }; 36 | 37 | struct ImageVulkanCreateInfo 38 | { 39 | VkImageType imageType; 40 | VkFormat format; 41 | VkExtent3D extent; 42 | VkImageUsageFlags usage; 43 | VkMemoryPropertyFlags memoryProperties; 44 | }; 45 | 46 | struct AccelerationStructureVulkan 47 | { 48 | VkDeviceMemory memory; 49 | VkAccelerationStructureInfoNV accelerationStructureInfo; 50 | VkAccelerationStructureNV accelerationStructure; 51 | uint64_t handle; 52 | }; 53 | 54 | struct AccelerationStructureVulkanCreateInfo 55 | { 56 | VkAccelerationStructureTypeNV type; 57 | uint32_t geometryCount; 58 | uint32_t instanceCount; 59 | VkGeometryNV* pGeometries; 60 | }; 61 | 62 | struct DeviceVulkan 63 | { 64 | VkInstance instance; 65 | VkPhysicalDevice physicalDevice; 66 | VkDevice device; 67 | 68 | uint32_t queueIndex; 69 | VkQueue queue; 70 | 71 | VkPhysicalDeviceRayTracingPropertiesNV rtProps; 72 | 73 | VkSurfaceKHR surface; 74 | VkSurfaceFormatKHR surfaceFormat; 75 | VkSwapchainKHR swapchain; 76 | 77 | std::vector swapchainImages; 78 | std::vector swapchainImageViews; 79 | std::vector waitForFrameFences; 80 | 81 | VkCommandPool commandPool; 82 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 83 | std::vector commandBuffers; 84 | VkSemaphore semaphoreImageAcquired; 85 | VkSemaphore semaphoreRenderFinished; 86 | VkDebugReportCallbackEXT debugCallback; 87 | }; 88 | 89 | struct DeviceVulkanCreateInfo 90 | { 91 | void* hwnd; 92 | uint32_t windowWidth; 93 | uint32_t windowHeight; 94 | }; 95 | 96 | bool createDeviceVulkan(const DeviceVulkanCreateInfo& ci, DeviceVulkan* deviceVulkan); 97 | 98 | void destroyDeviceVulkan(DeviceVulkan& vk); 99 | 100 | uint32_t getMemoryTypeVulkan(const DeviceVulkan& vk, VkMemoryRequirements& memoryRequirements, VkMemoryPropertyFlags memoryProperties); 101 | 102 | bool createBufferVulkan(const DeviceVulkan& vk, const BufferVulkanCreateInfo& ci, BufferVulkan* pBuffer); 103 | 104 | void destroyBufferVulkan(const DeviceVulkan& vk, BufferVulkan& buffer); 105 | 106 | bool createImageVulkan(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, ImageVulkan* pImage); 107 | 108 | // Returns staging buffers which need to be freed by caller 109 | bool createImageVulkanLocal(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, 110 | VkCommandBuffer cmdBuffer, size_t size, const void* data, 111 | ImageVulkan* pImage, std::vector* pStagingBuffers); 112 | 113 | void destroyImageVulkan(const DeviceVulkan& vk, ImageVulkan& image); 114 | 115 | bool createShaderVulkan(const DeviceVulkan& vk, const char* filename, VkShaderModule* pShaderModule); 116 | 117 | bool createAccelerationStructureVulkan(const DeviceVulkan& vk, 118 | const AccelerationStructureVulkanCreateInfo& ci, 119 | AccelerationStructureVulkan* pAccelerationStructure); 120 | 121 | void destroyAccelerationStructure(const DeviceVulkan& vk, 122 | AccelerationStructureVulkan& as); 123 | 124 | VkCommandBuffer createOneTimeCommandBuffer(const DeviceVulkan& vk); 125 | void submitOneTimeCommandBuffer(const DeviceVulkan& vk, VkCommandBuffer cmdBuffer); 126 | 127 | -------------------------------------------------------------------------------- /05-sample-texture/src/gltfLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "App.h" 4 | #include "logging.h" 5 | #include "gltfLoader.h" 6 | 7 | static bool readVec3(const std::vector& src, glm::vec3* dst, 8 | const glm::vec3& defaultValue = glm::vec3(0.f)) 9 | { 10 | if (src.size() > 0) 11 | { 12 | *dst = glm::vec3((float)src[0], (float)src[1], (float)src[2]); 13 | return true; 14 | } 15 | else 16 | { 17 | *dst = defaultValue; 18 | return false; 19 | } 20 | } 21 | 22 | static bool readVec4(const std::vector& src, glm::vec4* dst, 23 | const glm::vec4& defaultValue = glm::vec4(0.f)) 24 | { 25 | if (src.size() > 0) 26 | { 27 | *dst = glm::vec4((float)src[0], (float)src[1], (float)src[2], (float)src[3]); 28 | return true; 29 | } 30 | else 31 | { 32 | *dst = defaultValue; 33 | return false; 34 | } 35 | } 36 | 37 | static bool readQuat(std::vector& src, glm::quat* dst, 38 | const glm::quat& defaultValue = glm::quat(1.f, 0.f, 0.f, 0.f)) 39 | { 40 | // glm uses w, x, y, z 41 | if (src.size() > 0) 42 | { 43 | *dst = glm::quat((float)src[3], (float)src[0], (float)src[1], (float)src[2]); 44 | return true; 45 | } 46 | else 47 | { 48 | *dst = defaultValue; 49 | return false; 50 | } 51 | }; 52 | 53 | static void loadMesh(DeviceVulkan& vk, tinygltf::Model& gltfModel, 54 | tinygltf::Mesh& gltfMesh, Mesh* pMesh) 55 | { 56 | // Only handle single triangle primitives (for now). 57 | BASSERT(gltfMesh.primitives.size() == 1); 58 | 59 | auto& primitive = gltfMesh.primitives[0]; 60 | 61 | BASSERT(primitive.mode == TINYGLTF_MODE_TRIANGLES); 62 | 63 | auto& attrs = primitive.attributes; 64 | 65 | int idPosition = attrs.count("POSITION") == 1 ? attrs["POSITION"] : -1; 66 | int idNormal = attrs.count("NORMAL") == 1 ? attrs["NORMAL"] : -1; 67 | int idTexcoord0 = attrs.count("TEXCOORD_0") == 1 ? attrs["TEXCOORD_0"] : -1; 68 | int idIndices = primitive.indices; 69 | int idMaterial = primitive.material; 70 | 71 | pMesh->materialID = idMaterial; 72 | 73 | BASSERT(idPosition >= 0); 74 | 75 | // Load positions 76 | { 77 | BASSERT(gltfModel.accessors[idPosition].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 78 | && gltfModel.accessors[idPosition].type == TINYGLTF_TYPE_VEC3); 79 | 80 | pMesh->vertexCount = (uint32_t)gltfModel.accessors[idPosition].count; 81 | 82 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idPosition].bufferView]; 83 | 84 | //std::vector dbgPositions(bv.byteLength / 12); 85 | //memcpy(dbgPositions.data(), 86 | // &gltfModel.buffers[bv.buffer].data[bv.byteOffset], bv.byteLength); 87 | 88 | createBufferVulkan(vk, { bv.byteLength, 89 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | 90 | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 91 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 92 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 93 | &pMesh->positions); 94 | } 95 | 96 | // Load normals 97 | { 98 | BASSERT(idNormal >= 0); 99 | 100 | BASSERT(gltfModel.accessors[idNormal].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 101 | && gltfModel.accessors[idNormal].type == TINYGLTF_TYPE_VEC3); 102 | 103 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idNormal].bufferView]; 104 | 105 | //auto normalCount = gltfModel.accessors[idNormal].count; 106 | 107 | createBufferVulkan(vk, { bv.byteLength, 108 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 109 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 110 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 111 | &pMesh->normals); 112 | } 113 | 114 | // Load uvs 115 | { 116 | BASSERT(idTexcoord0 >= 0); 117 | 118 | BASSERT(gltfModel.accessors[idTexcoord0].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 119 | && gltfModel.accessors[idTexcoord0].type == TINYGLTF_TYPE_VEC2); 120 | 121 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idTexcoord0].bufferView]; 122 | 123 | createBufferVulkan(vk, { bv.byteLength, 124 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 125 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 126 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 127 | &pMesh->uvs); 128 | } 129 | 130 | // Load indices 131 | { 132 | BASSERT(gltfModel.accessors[idIndices].componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT 133 | && gltfModel.accessors[idIndices].type == TINYGLTF_TYPE_SCALAR); 134 | 135 | uint32_t indexCount = (uint32_t)gltfModel.accessors[idIndices].count; 136 | pMesh->indexCount = indexCount; 137 | 138 | std::vector indices16(indexCount); 139 | 140 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idIndices].bufferView]; 141 | 142 | memcpy(indices16.data(), &gltfModel.buffers[bv.buffer].data[bv.byteOffset], 143 | bv.byteLength); 144 | 145 | std::vector indices32(indices16.begin(), indices16.end()); 146 | 147 | createBufferVulkan(vk, { indexCount * sizeof(uint32_t), 148 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | 149 | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 150 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 151 | indices32.data() }, &pMesh->indices); 152 | } 153 | } 154 | 155 | static void loadMeshes(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 156 | { 157 | // Load meshes 158 | size_t meshCount = model.meshes.size(); 159 | BASSERT(meshCount > 0); 160 | 161 | pScene->meshes.resize(meshCount); 162 | 163 | for (size_t i = 0; i < model.meshes.size(); i++) 164 | loadMesh(vk, model, model.meshes[i], &pScene->meshes[i]); 165 | } 166 | 167 | static void loadSceneNodes(tinygltf::Model& model, Scene* pScene) 168 | { 169 | // Load scene nodes 170 | BASSERT(model.defaultScene == 0); 171 | tinygltf::Scene& gltfScene = model.scenes[model.defaultScene]; 172 | 173 | pScene->nodes.reserve(gltfScene.nodes.size()); 174 | 175 | for (auto i : gltfScene.nodes) 176 | { 177 | auto& srcNode = model.nodes[i]; 178 | 179 | if (srcNode.mesh == -1) 180 | { 181 | // might be a light or camera. 182 | 183 | if (srcNode.children.size()) 184 | { 185 | auto& childNode = model.nodes[srcNode.children[0]]; 186 | if (childNode.camera >= 0) 187 | { 188 | readVec3(srcNode.translation, &pScene->camera.position, glm::vec3(0.f)); 189 | 190 | glm::quat rot1, rot2; 191 | if (readQuat(srcNode.rotation, &rot1)) 192 | { 193 | if (readQuat(childNode.rotation, &rot2)) 194 | { 195 | cameraRotate(pScene->camera, rot1 * rot2); 196 | } 197 | } 198 | 199 | cameraUpdateView(pScene->camera); 200 | } 201 | } 202 | 203 | continue; 204 | } 205 | 206 | pScene->nodes.push_back({}); 207 | SceneNode& dstNode = pScene->nodes.back(); 208 | 209 | dstNode.name = srcNode.name; 210 | dstNode.meshID = srcNode.mesh; 211 | dstNode.children = srcNode.children; 212 | 213 | readVec3(srcNode.translation, &dstNode.translation, glm::vec3(0.f)); 214 | readVec3(srcNode.scale, &dstNode.scale, glm::vec3(1.f)); 215 | readQuat(srcNode.rotation, &dstNode.rotation); 216 | 217 | if (srcNode.matrix.size() > 0) 218 | { 219 | dstNode.matrixValid = true; 220 | memcpy(glm::value_ptr(dstNode.matrix), srcNode.matrix.data(), 221 | sizeof(float) * 16); 222 | } 223 | else 224 | { 225 | dstNode.matrixValid = false; 226 | dstNode.matrix = glm::mat4(1.f); 227 | } 228 | } 229 | } 230 | 231 | static void loadMeshInstanceData(DeviceVulkan& vk, Scene* pScene) 232 | { 233 | std::vector meshInstanceData; 234 | meshInstanceData.reserve(pScene->nodes.size()); 235 | 236 | for (auto& node : pScene->nodes) 237 | { 238 | MeshInstanceData mid = {}; 239 | mid.materialID = pScene->meshes[node.meshID].materialID; 240 | 241 | meshInstanceData.push_back(mid); 242 | } 243 | 244 | createBufferVulkan(vk, { sizeof(MeshInstanceData) * meshInstanceData.size(), 245 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 246 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 247 | meshInstanceData.data() }, &pScene->meshInstanceDataBuffer); 248 | } 249 | 250 | static void loadMaterials(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 251 | { 252 | // Note: Only loading PBR Metal/Roughness properties (not specular extension) 253 | std::vector materials(model.materials.size()); 254 | pScene->baseColorTextureInfos.resize(model.materials.size()); 255 | 256 | auto& textures = pScene->textures; 257 | VkImageView fallbackBlackView = pScene->fallbackTextureBlack.view; 258 | VkImageView fallbackWhiteView = pScene->fallbackTextureWhite.view; 259 | 260 | for (size_t i = 0; i < model.materials.size(); i++) 261 | { 262 | auto& gltfMat = model.materials[i]; 263 | Material& mat = materials[i]; 264 | 265 | auto& pbr = gltfMat.pbrMetallicRoughness; 266 | 267 | readVec4(pbr.baseColorFactor, &mat.baseColorFactor, glm::vec4(1.f)); 268 | 269 | int baseColorID = pbr.baseColorTexture.index; 270 | 271 | VkImageView baseColorView = baseColorID >= 0 ? 272 | textures[baseColorID].view : fallbackWhiteView; 273 | 274 | auto& baseColorInfos = pScene->baseColorTextureInfos[i]; 275 | baseColorInfos.sampler = nullptr; 276 | baseColorInfos.imageView = baseColorView; 277 | baseColorInfos.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 278 | } 279 | 280 | createBufferVulkan(vk, { sizeof(Material) * materials.size(), 281 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 282 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 283 | materials.data() }, &pScene->materialsBuffer); 284 | } 285 | 286 | static void loadImages(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 287 | { 288 | if (model.images.size() == 0) 289 | return; 290 | 291 | VkCommandBuffer cmdBuffer = createOneTimeCommandBuffer(vk); 292 | 293 | pScene->textures.resize(model.images.size()); 294 | 295 | std::vector stagingBuffers; 296 | 297 | for (size_t i = 0; i < model.images.size(); i++) 298 | { 299 | auto& gltfImage = model.images[i]; 300 | auto& texture = pScene->textures[i]; 301 | 302 | createImageVulkanLocal(vk, { VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, 303 | { (uint32_t)gltfImage.width, (uint32_t)gltfImage.height, 1}, 304 | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 305 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT }, 306 | cmdBuffer, gltfImage.image.size(), gltfImage.image.data(), 307 | &texture, &stagingBuffers); 308 | 309 | // BONI TODO: generate mips 310 | } 311 | 312 | submitOneTimeCommandBuffer(vk, cmdBuffer); 313 | 314 | for (auto& b : stagingBuffers) 315 | destroyBufferVulkan(vk, b); 316 | } 317 | 318 | 319 | bool loadGltfFile(DeviceVulkan& vk, const char* fn, Scene* pScene) 320 | { 321 | tinygltf::Model model; 322 | tinygltf::TinyGLTF loader; 323 | 324 | std::string err; 325 | std::string warn; 326 | bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, fn); 327 | BASSERT(ret); 328 | 329 | if (ret == false) 330 | { 331 | DebugPrint("Error: could not load %s\n", fn); 332 | return false; 333 | } 334 | 335 | if (model.scenes.size() == 0) 336 | { 337 | DebugPrint("Error: no scene found in %s\n", fn); 338 | return false; 339 | } 340 | 341 | loadMeshes(vk, model, pScene); 342 | 343 | loadSceneNodes(model, pScene); 344 | 345 | loadMeshInstanceData(vk, pScene); 346 | 347 | loadImages(vk, model, pScene); 348 | 349 | loadMaterials(vk, model, pScene); 350 | 351 | return true; 352 | } 353 | 354 | 355 | -------------------------------------------------------------------------------- /05-sample-texture/src/gltfLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | bool loadGltfFile(DeviceVulkan& vk, const char* fn, Scene* pScene); 5 | 6 | -------------------------------------------------------------------------------- /05-sample-texture/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "logging.h" 4 | 5 | void DebugPrint(const char* fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | size_t len = _vscprintf(fmt, args); 10 | std::vector buff(len); 11 | vsnprintf_s(buff.data(), len, _TRUNCATE, fmt, args); 12 | OutputDebugStringA(buff.data()); 13 | va_end(args); 14 | } 15 | -------------------------------------------------------------------------------- /05-sample-texture/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void DebugPrint(const char* fmt, ...); 4 | 5 | #define BASSERT(expr) ((void)((!!(expr)) || \ 6 | ((DebugPrint("Error: %s, %s:%d\n", #expr, __FILE__, __LINE__),1) \ 7 | && (__debugbreak(),0)) )) 8 | 9 | 10 | -------------------------------------------------------------------------------- /05-sample-texture/src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #define TINYGLTF_IMPLEMENTATION 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | // #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. 7 | #pragma warning(push) 8 | #pragma warning(disable : 4996) // printf unsafe 9 | #pragma warning(disable : 4267) // size_t -> uint32_t 10 | #include "tiny_gltf.h" 11 | #pragma warning(pop) 12 | -------------------------------------------------------------------------------- /05-sample-texture/src/pch.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #pragma warning(push) 15 | #pragma warning(disable: 26812) 16 | #include 17 | #pragma warning(pop) 18 | 19 | #define GLFW_EXPOSE_NATIVE_WIN32 20 | #include 21 | #include 22 | 23 | #define GLM_ENABLE_EXPERIMENTAL 24 | #define GLM_FORCE_RADIANS 25 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | -------------------------------------------------------------------------------- /05-sample-texture/update-proj.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | -------------------------------------------------------------------------------- /06-sample-reflection/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | 3 | .vs/ 4 | bin/ 5 | obj/ 6 | 7 | *.spv 8 | 9 | -------------------------------------------------------------------------------- /06-sample-reflection/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "sample-reflection" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win64" } 4 | 5 | project "sample-reflection" 6 | kind "ConsoleApp" 7 | language "C++" 8 | cppdialect "C++17" 9 | 10 | pchheader "pch.h" 11 | pchsource "src/pch.cpp" 12 | 13 | libdirs { 14 | "../external/glfw/lib-vc2019" 15 | } 16 | links { 17 | "glfw3" 18 | } 19 | 20 | defines { 21 | "VOLK_STATIC_DEFINES", 22 | "VK_USE_PLATFORM_WIN32_KHR" 23 | } 24 | 25 | includedirs { 26 | "../external/glfw/include", 27 | "../external/glm", 28 | "../external/volk", 29 | "../external/tinygltf", 30 | "$(VULKAN_SDK)/Include", 31 | "src" 32 | } 33 | 34 | files { 35 | "../external/glfw/include/**.h", 36 | "../external/glm/glm/**.hpp", 37 | "../external/glm/util/glm.natvis", 38 | "../external/volk/volk.h", 39 | "../external/volk/volk.c", 40 | "src/**.h", 41 | "src/**.cpp" 42 | } 43 | 44 | filter { 45 | "files:../external/volk/volk.c" 46 | } 47 | flags { "NoPCH" } 48 | 49 | 50 | 51 | filter "platforms:Win64" 52 | system "Windows" 53 | architecture "x64" 54 | 55 | filter "configurations:Debug" 56 | targetsuffix "_D" 57 | defines { "DEBUG" } 58 | symbols "On" 59 | 60 | filter "configurations:Release" 61 | defines { "NDEBUG" } 62 | optimize "On" 63 | 64 | -------------------------------------------------------------------------------- /06-sample-reflection/sample-reflection.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-reflection", "sample-reflection.vcxproj", "{FF7B9D0E-6B92-9BA4-B409-27C6205F6C2C}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win64 = Debug|Win64 9 | Release|Win64 = Release|Win64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {FF7B9D0E-6B92-9BA4-B409-27C6205F6C2C}.Debug|Win64.ActiveCfg = Debug Win64|x64 13 | {FF7B9D0E-6B92-9BA4-B409-27C6205F6C2C}.Debug|Win64.Build.0 = Debug Win64|x64 14 | {FF7B9D0E-6B92-9BA4-B409-27C6205F6C2C}.Release|Win64.ActiveCfg = Release Win64|x64 15 | {FF7B9D0E-6B92-9BA4-B409-27C6205F6C2C}.Release|Win64.Build.0 = Release Win64|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /06-sample-reflection/sample-reflection.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /06-sample-reflection/shaders/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.h": "glsl" 4 | } 5 | } -------------------------------------------------------------------------------- /06-sample-reflection/shaders/build-shaders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call :build raygen.rgen 4 | call :build chit.rchit 5 | call :build shadow-chit.rchit 6 | call :build miss.rmiss 7 | call :build shadow-miss.rmiss 8 | 9 | goto :eof 10 | 11 | :build 12 | %VULKAN_SDK%\bin\glslangValidator.exe -V %1 -o %1.spv 13 | goto :eof 14 | -------------------------------------------------------------------------------- /06-sample-reflection/shaders/chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | const int kMaxDepth = 4; 9 | 10 | struct InstanceData 11 | { 12 | int materialID; 13 | }; 14 | 15 | struct Material 16 | { 17 | vec4 baseColorFactor; 18 | }; 19 | 20 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 21 | layout(set = 0, binding = 3) readonly buffer MeshInstanceDataBuffer { InstanceData d[]; } MeshInstanceData; 22 | layout(set = 0, binding = 4) readonly buffer MaterialsBuffer { Material m[]; } Materials; 23 | 24 | layout(set = 1, binding = 0) readonly buffer NormalsBuffer { float n[]; } Normals[]; 25 | layout(set = 2, binding = 0) readonly buffer UvsBuffer { vec2 uv[]; } Uvs[]; 26 | layout(set = 3, binding = 0) readonly buffer IndicesBuffer { uint i[]; } Indices[]; 27 | 28 | layout(set = 4, binding = 0) uniform sampler LinearSampler; 29 | layout(set = 4, binding = 1) uniform texture2D BaseColorTextures[]; 30 | 31 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 32 | 33 | hitAttributeNV vec2 HitAttribs; 34 | 35 | vec2 interpolate(vec2 a, vec2 b, vec2 c, vec3 barycentrics) 36 | { 37 | return a * barycentrics.x + 38 | b * barycentrics.y + 39 | c * barycentrics.z; 40 | } 41 | 42 | vec3 interpolate(vec3 a, vec3 b, vec3 c, vec3 barycentrics) 43 | { 44 | return a * barycentrics.x + 45 | b * barycentrics.y + 46 | c * barycentrics.z; 47 | } 48 | 49 | vec3 getBarycentric() 50 | { 51 | vec3 b; 52 | b.x = 1.0 - HitAttribs.x - HitAttribs.y; 53 | b.y = HitAttribs.x; 54 | b.z = HitAttribs.y; 55 | return b; 56 | } 57 | 58 | uvec3 getFaceIndex() 59 | { 60 | // BONI TODO: when do we _need_ to use nonuniformEXT ? 61 | // ivec3 ind = ivec3( 62 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID], 63 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 1], 64 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 2] 65 | // ); 66 | 67 | uvec3 f; 68 | f.x = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 0]; 69 | f.y = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 1]; 70 | f.z = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 2]; 71 | return f; 72 | } 73 | 74 | vec3 getOneNormal(uint index) 75 | { 76 | // vec3 n0 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.x].xyz; 77 | // vec3 n1 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.y].xyz; 78 | // vec3 n2 = Normals[nonuniformEXT(gl_InstanceID)].n[ind.z].xyz; 79 | 80 | vec3 n; 81 | n.x = Normals[gl_InstanceID].n[3 * index + 0]; 82 | n.y = Normals[gl_InstanceID].n[3 * index + 1]; 83 | n.z = Normals[gl_InstanceID].n[3 * index + 2]; 84 | return n; 85 | } 86 | 87 | vec3 getNormalWS(uvec3 faceIndex, vec3 barycentric) 88 | { 89 | vec3 n0 = getOneNormal(faceIndex.x); 90 | vec3 n1 = getOneNormal(faceIndex.y); 91 | vec3 n2 = getOneNormal(faceIndex.z); 92 | 93 | vec3 n = normalize(interpolate(n0, n1, n2, barycentric)); 94 | 95 | vec3 N = normalize(vec3(gl_ObjectToWorldNV * vec4(n, 0.))); 96 | 97 | return N; 98 | } 99 | 100 | vec2 getUv(uvec3 faceIndex, vec3 barycentric) 101 | { 102 | vec2 uv0 = Uvs[gl_InstanceID].uv[faceIndex.x]; 103 | vec2 uv1 = Uvs[gl_InstanceID].uv[faceIndex.y]; 104 | vec2 uv2 = Uvs[gl_InstanceID].uv[faceIndex.z]; 105 | 106 | vec2 uv = interpolate(uv0, uv1, uv2, barycentric); 107 | return uv; 108 | } 109 | 110 | void main() 111 | { 112 | uvec3 faceIndex = getFaceIndex(); 113 | vec3 barycentric = getBarycentric(); 114 | 115 | vec3 baseColor = vec3(1., 1., 1.); 116 | 117 | int materialID = MeshInstanceData.d[gl_InstanceID].materialID; 118 | vec2 uv = getUv(faceIndex, barycentric); 119 | 120 | // BONI TODO: remove these if checks by having defaults 121 | if (materialID >= 0) 122 | { 123 | vec3 baseColorFactor = Materials.m[materialID].baseColorFactor.rgb; 124 | 125 | vec3 baseColorSample = texture(sampler2D(BaseColorTextures[materialID], LinearSampler), uv).rgb; 126 | 127 | baseColorSample = srgbToLinear(baseColorSample); 128 | 129 | baseColor = baseColorSample * baseColorFactor; 130 | } 131 | 132 | vec3 N = getNormalWS(faceIndex, barycentric); 133 | 134 | vec3 L = normalize(vec3(1., 1., 1.)); 135 | 136 | float ndotl = max(0., dot(N, L)); 137 | 138 | vec3 color = vec3(ndotl * baseColor + 0.1); 139 | 140 | PrimaryRay.depth += 1; 141 | 142 | if (baseColor.r < 1.0 && PrimaryRay.depth < kMaxDepth) 143 | { 144 | vec3 hitPos = gl_WorldRayOriginNV + gl_WorldRayDirectionNV * gl_HitTNV; 145 | vec3 origin = hitPos + N * 0.001; 146 | vec3 dir = reflect(gl_WorldRayDirectionNV, N); 147 | 148 | uint flags = gl_RayFlagsOpaqueNV; 149 | 150 | traceNV(Scene, flags, 0xFF, 0, 0, 0, origin, 0.001, dir, 1000, 0); 151 | 152 | PrimaryRay.color_distance.rgb *= color; 153 | } 154 | else 155 | { 156 | PrimaryRay.color_distance = vec4(color, gl_HitTNV); 157 | PrimaryRay.normal = vec4(N, 0.); 158 | } 159 | 160 | PrimaryRay.depth -= 1; 161 | } 162 | 163 | -------------------------------------------------------------------------------- /06-sample-reflection/shaders/miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 8 | 9 | void main() 10 | { 11 | const vec3 skyBlue = vec3(0.529, 0.808, 0.922); 12 | PrimaryRay.color_distance = vec4(skyBlue, -1.0); 13 | } 14 | -------------------------------------------------------------------------------- /06-sample-reflection/shaders/raygen.rgen: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 8 | layout(set = 0, binding = 1, rgba8) uniform image2D ResultImage; 9 | layout(set = 0, binding = 2, std140) uniform AppData { UniformParams Params; }; 10 | 11 | layout(location = 0) rayPayloadNV RayPayload PrimaryRay; 12 | layout(location = 1) rayPayloadNV ShadowRayPayload ShadowRay; 13 | 14 | void main() 15 | { 16 | // https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays 17 | vec2 pixelRaster = gl_LaunchIDNV.xy; 18 | vec2 imageSize = gl_LaunchSizeNV.xy; 19 | 20 | // Compute raytacing NDC (note range [0,1]) 21 | vec2 pixelNDC = (pixelRaster + vec2(0.5)) / imageSize; 22 | 23 | // Remap to range [-1, 1] 24 | vec2 pixelSS = pixelNDC * 2.0 - 1.0; 25 | 26 | // Y is reversed (since raster, NDC & screen space have pos Y pointing down) 27 | pixelSS.y = 1.0 - 2.0 * pixelNDC.y; 28 | 29 | // Compute camera/view space. proj has fov, near, far 30 | vec4 pixelCS = Params.projInverse * vec4(pixelSS.x, pixelSS.y, 0., 1.); 31 | 32 | // Camera is at origin in camera space. Compute direction to pixel in camera spce. 33 | vec4 originCS = vec4(0., 0., 0., 1.); 34 | vec4 directionCS = vec4(normalize((pixelCS - originCS).xyz), 0.); 35 | 36 | // Compute world space values 37 | vec4 directionWS = Params.viewInverse * directionCS; 38 | vec4 originWS = Params.viewInverse * vec4(0., 0., 0., 1.); 39 | 40 | uint rayFlags = gl_RayFlagsOpaqueNV; 41 | float tmin = 0.001; 42 | float tmax = 10000.0; 43 | 44 | PrimaryRay.depth = 0; 45 | 46 | traceNV(Scene, rayFlags, 0xFF, 47 | 0, // sbtRecordOffset 48 | 0, // sbtRecordStride 49 | 0, // missIndex 50 | originWS.xyz, 51 | tmin, directionWS.xyz, tmax, 52 | 0 // payload 53 | ); 54 | 55 | vec3 hitColor = PrimaryRay.color_distance.rgb; 56 | float hitDistance = PrimaryRay.color_distance.w; 57 | 58 | if (hitDistance >= 0.) 59 | { 60 | vec3 hitPos = originWS.xyz + directionWS.xyz * hitDistance; 61 | 62 | vec3 hitNormal = PrimaryRay.normal.xyz; 63 | 64 | vec3 toLight = normalize(vec3(1., 1., 1.)); 65 | vec3 shadowRayOrigin = hitPos;// + hitNormal * 0.01; 66 | uint shadowRayFlags = gl_RayFlagsOpaqueNV | gl_RayFlagsTerminateOnFirstHitNV; 67 | 68 | traceNV(Scene, shadowRayFlags, 0xFF, 69 | 1, // offset 1 (choose 2nd hit shader) 70 | 0, // stride ?? 71 | 1, // offset 1 (choose 2nd miss shader) 72 | shadowRayOrigin, 73 | 2, // ?? adjusted for colored-sphere scene 74 | toLight, tmax, 75 | 1 // payload location 1 76 | ); 77 | 78 | if (ShadowRay.distance > 0.) 79 | { 80 | // In shadow 81 | hitColor *= 0.3; 82 | } 83 | 84 | // hitColor = hitNormal; 85 | } 86 | 87 | 88 | hitColor = linearToSrgb(hitColor); 89 | 90 | imageStore(ResultImage, ivec2(gl_LaunchIDNV.xy), vec4(hitColor, 0.)); 91 | } 92 | 93 | 94 | -------------------------------------------------------------------------------- /06-sample-reflection/shaders/shader-common.h: -------------------------------------------------------------------------------- 1 | 2 | // packed std140 3 | struct UniformParams 4 | { 5 | mat4 viewInverse; 6 | mat4 projInverse; 7 | }; 8 | 9 | struct RayPayload 10 | { 11 | vec4 color_distance; 12 | vec4 normal; 13 | int depth; 14 | }; 15 | 16 | struct ShadowRayPayload 17 | { 18 | float distance; 19 | }; 20 | 21 | vec3 srgbToLinear(vec3 c) 22 | { 23 | return pow(c, vec3(2.2)); 24 | } 25 | 26 | vec3 linearToSrgb(vec3 c) 27 | { 28 | return pow(c, vec3(1.0 / 2.2)); 29 | } 30 | -------------------------------------------------------------------------------- /06-sample-reflection/shaders/shadow-chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 9 | 10 | void main() 11 | { 12 | ShadowRay.distance = gl_HitTNV; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /06-sample-reflection/shaders/shadow-miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 8 | 9 | void main() 10 | { 11 | ShadowRay.distance = -1.0; 12 | } 13 | -------------------------------------------------------------------------------- /06-sample-reflection/src/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DeviceVulkan.h" 4 | #include "camera.h" 5 | 6 | 7 | // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/chap33.html#acceleration-structure 8 | struct VkGeometryInstance 9 | { 10 | float transform[12]; 11 | uint32_t instanceCustomIndex : 24; // gl_InstanceCustomIndexNV 12 | uint32_t mask : 8; 13 | uint32_t instanceOffset : 24; 14 | uint32_t flags : 8; 15 | uint64_t accelerationStructureHandle; 16 | }; 17 | 18 | struct Mesh 19 | { 20 | uint32_t vertexCount; 21 | uint32_t indexCount; 22 | 23 | int materialID; 24 | 25 | BufferVulkan positions; 26 | BufferVulkan normals; 27 | BufferVulkan uvs; 28 | BufferVulkan indices; 29 | 30 | AccelerationStructureVulkan blas; 31 | }; 32 | 33 | // BONI NOTE: keep this padded to 16 bytes 34 | struct Material 35 | { 36 | glm::vec4 baseColorFactor; 37 | }; 38 | 39 | struct CameraUniformData 40 | { 41 | glm::mat4 viewInverse; 42 | glm::mat4 projInverse; 43 | }; 44 | 45 | struct SceneNode 46 | { 47 | std::string name; 48 | 49 | glm::vec3 translation; 50 | glm::vec3 scale; 51 | glm::quat rotation; 52 | 53 | glm::mat4 matrix; 54 | 55 | std::vector children; 56 | 57 | int meshID; 58 | bool matrixValid; 59 | }; 60 | 61 | struct MeshInstanceData 62 | { 63 | int materialID; 64 | }; 65 | 66 | struct Scene 67 | { 68 | std::vector nodes; 69 | 70 | std::vector meshes; 71 | 72 | std::vector normalsBufferInfos; 73 | std::vector uvsBufferInfos; 74 | std::vector indicesBufferInfos; 75 | 76 | std::vector textures; 77 | 78 | std::vector baseColorTextureInfos; 79 | 80 | ImageVulkan fallbackTextureBlack; 81 | ImageVulkan fallbackTextureWhite; 82 | 83 | BufferVulkan cameraBuffer; 84 | BufferVulkan meshInstanceDataBuffer; 85 | BufferVulkan materialsBuffer; 86 | 87 | VkSampler linearSampler; 88 | 89 | Camera camera; 90 | 91 | AccelerationStructureVulkan topLevelStruct; 92 | }; 93 | 94 | struct App 95 | { 96 | GLFWwindow* window; 97 | 98 | ImageVulkan offscreenImage; 99 | 100 | VkShaderModule raygenShader; 101 | VkShaderModule chitShader; 102 | VkShaderModule shadowChitShader; 103 | VkShaderModule missShader; 104 | VkShaderModule shadowMissShader; 105 | 106 | BufferVulkan instancesBuffer; 107 | BufferVulkan sbtBuffer; 108 | 109 | VkPipelineLayout pipelineLayout; 110 | VkPipeline rtPipeline; 111 | 112 | VkDescriptorPool descriptorPool; 113 | std::vector descriptorSetLayouts; 114 | std::vector descriptorSets; 115 | 116 | bool keysDown[GLFW_KEY_LAST + 1]; 117 | bool mouseDown[GLFW_MOUSE_BUTTON_LAST + 1]; 118 | glm::vec2 cursorPos; 119 | 120 | Scene scene; 121 | }; 122 | 123 | -------------------------------------------------------------------------------- /06-sample-reflection/src/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "camera.h" 4 | 5 | void cameraMove(Camera& camera, const glm::vec3& value) 6 | { 7 | glm::vec3 right = glm::normalize(glm::cross(camera.forward, camera.up)); 8 | 9 | camera.position += right * value.x; 10 | camera.position += camera.up * value.y; 11 | camera.position += camera.forward * value.z; 12 | } 13 | 14 | void cameraRotate(Camera& camera, const float angleX, const float angleY) 15 | { 16 | glm::vec3 right = glm::cross(camera.forward, camera.up); 17 | 18 | glm::quat pitch = glm::angleAxis(glm::radians(angleY), right); 19 | glm::quat heading = glm::angleAxis(glm::radians(angleX), camera.up); 20 | 21 | glm::quat combined = glm::normalize(pitch * heading); 22 | 23 | camera.forward = glm::normalize(glm::rotate(combined, camera.forward)); 24 | } 25 | 26 | void cameraRotate(Camera& camera, const glm::quat& rotation) 27 | { 28 | //camera.up = glm::rotate(rotation, camera.up); 29 | camera.forward = glm::rotate(rotation, camera.forward); 30 | } 31 | 32 | void cameraUpdateProjection(Camera& camera) 33 | { 34 | float left = camera.viewport[0]; 35 | float top = camera.viewport[1]; 36 | float right = camera.viewport[2]; 37 | float bottom = camera.viewport[3]; 38 | 39 | float aspect = float(right - left) / float(bottom - top); 40 | camera.projection = glm::perspectiveRH_ZO( 41 | glm::radians(camera.fovy), aspect, camera.nearz, camera.farz); 42 | } 43 | 44 | void cameraUpdateView(Camera& camera) 45 | { 46 | camera.view = glm::lookAtRH(camera.position, camera.position + camera.forward, camera.up); 47 | } 48 | -------------------------------------------------------------------------------- /06-sample-reflection/src/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Camera 4 | { 5 | std::array viewport; // left, top, right, bottom 6 | float fovy = 60.f; 7 | float nearz = 1.f; 8 | float farz = 1000.f; 9 | 10 | glm::vec3 position; 11 | glm::vec3 up; 12 | glm::vec3 forward; 13 | glm::mat4 projection; 14 | glm::mat4 view; 15 | }; 16 | 17 | void cameraMove(Camera& camera, const glm::vec3& value); 18 | void cameraRotate(Camera& camera, const float angleX, const float angleY); 19 | void cameraRotate(Camera& camera, const glm::quat& rotation); 20 | void cameraUpdateProjection(Camera& camera); 21 | void cameraUpdateView(Camera& camera); 22 | 23 | -------------------------------------------------------------------------------- /06-sample-reflection/src/DeviceVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VK_CHECK(f) do { \ 4 | VkResult r = f; \ 5 | if (r != VK_SUCCESS) { \ 6 | DebugPrint("VK_CHECK result: %d\n", r); \ 7 | BASSERT(!#f); \ 8 | } \ 9 | } while (false) 10 | 11 | 12 | struct BufferVulkan 13 | { 14 | VkDeviceSize size; 15 | VkBuffer buffer; 16 | VkDeviceMemory memory; 17 | }; 18 | 19 | struct BufferVulkanCreateInfo 20 | { 21 | VkDeviceSize size; 22 | VkBufferUsageFlags usage; 23 | VkMemoryPropertyFlags memoryProperties; 24 | const void* pSrc; 25 | }; 26 | 27 | struct ImageVulkan 28 | { 29 | VkImageType type; 30 | VkFormat format; 31 | VkExtent3D extent; 32 | 33 | VkImage image; 34 | VkImageView view; 35 | 36 | VkDeviceMemory memory; 37 | }; 38 | 39 | struct ImageVulkanCreateInfo 40 | { 41 | VkImageType imageType; 42 | VkFormat format; 43 | VkExtent3D extent; 44 | VkImageUsageFlags usage; 45 | VkMemoryPropertyFlags memoryProperties; 46 | }; 47 | 48 | struct AccelerationStructureVulkan 49 | { 50 | VkDeviceMemory memory; 51 | VkAccelerationStructureInfoNV accelerationStructureInfo; 52 | VkAccelerationStructureNV accelerationStructure; 53 | uint64_t handle; 54 | }; 55 | 56 | struct AccelerationStructureVulkanCreateInfo 57 | { 58 | VkAccelerationStructureTypeNV type; 59 | uint32_t geometryCount; 60 | uint32_t instanceCount; 61 | VkGeometryNV* pGeometries; 62 | }; 63 | 64 | struct DeviceVulkan 65 | { 66 | VkInstance instance; 67 | VkPhysicalDevice physicalDevice; 68 | VkDevice device; 69 | 70 | uint32_t queueIndex; 71 | VkQueue queue; 72 | 73 | VkPhysicalDeviceRayTracingPropertiesNV rtProps; 74 | 75 | VkSurfaceKHR surface; 76 | VkSurfaceFormatKHR surfaceFormat; 77 | VkSwapchainKHR swapchain; 78 | 79 | std::vector swapchainImages; 80 | std::vector swapchainImageViews; 81 | std::vector waitForFrameFences; 82 | 83 | VkCommandPool commandPool; 84 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 85 | std::vector commandBuffers; 86 | VkSemaphore semaphoreImageAcquired; 87 | VkSemaphore semaphoreRenderFinished; 88 | VkDebugReportCallbackEXT debugCallback; 89 | }; 90 | 91 | struct DeviceVulkanCreateInfo 92 | { 93 | void* hwnd; 94 | uint32_t windowWidth; 95 | uint32_t windowHeight; 96 | bool vsync; 97 | }; 98 | 99 | bool createDeviceVulkan(const DeviceVulkanCreateInfo& ci, DeviceVulkan* deviceVulkan); 100 | 101 | void destroyDeviceVulkan(DeviceVulkan& vk); 102 | 103 | uint32_t getMemoryTypeVulkan(const DeviceVulkan& vk, VkMemoryRequirements& memoryRequirements, VkMemoryPropertyFlags memoryProperties); 104 | 105 | bool createBufferVulkan(const DeviceVulkan& vk, const BufferVulkanCreateInfo& ci, BufferVulkan* pBuffer); 106 | 107 | void destroyBufferVulkan(const DeviceVulkan& vk, BufferVulkan& buffer); 108 | 109 | bool createImageVulkan(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, ImageVulkan* pImage); 110 | 111 | // Returns staging buffers which need to be freed by caller 112 | bool createImageVulkanLocal(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, 113 | VkCommandBuffer cmdBuffer, size_t size, const void* data, 114 | ImageVulkan* pImage, std::vector* pStagingBuffers); 115 | 116 | void destroyImageVulkan(const DeviceVulkan& vk, ImageVulkan& image); 117 | 118 | bool createShaderVulkan(const DeviceVulkan& vk, const char* filename, VkShaderModule* pShaderModule); 119 | 120 | bool createAccelerationStructureVulkan(const DeviceVulkan& vk, 121 | const AccelerationStructureVulkanCreateInfo& ci, 122 | AccelerationStructureVulkan* pAccelerationStructure); 123 | 124 | void destroyAccelerationStructure(const DeviceVulkan& vk, 125 | AccelerationStructureVulkan& as); 126 | 127 | VkCommandBuffer createOneTimeCommandBuffer(const DeviceVulkan& vk); 128 | void submitOneTimeCommandBuffer(const DeviceVulkan& vk, VkCommandBuffer cmdBuffer); 129 | 130 | -------------------------------------------------------------------------------- /06-sample-reflection/src/gltfLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "App.h" 4 | #include "logging.h" 5 | #include "gltfLoader.h" 6 | 7 | static bool readVec3(const std::vector& src, glm::vec3* dst, 8 | const glm::vec3& defaultValue = glm::vec3(0.f)) 9 | { 10 | if (src.size() > 0) 11 | { 12 | *dst = glm::vec3((float)src[0], (float)src[1], (float)src[2]); 13 | return true; 14 | } 15 | else 16 | { 17 | *dst = defaultValue; 18 | return false; 19 | } 20 | } 21 | 22 | static bool readVec4(const std::vector& src, glm::vec4* dst, 23 | const glm::vec4& defaultValue = glm::vec4(0.f)) 24 | { 25 | if (src.size() > 0) 26 | { 27 | *dst = glm::vec4((float)src[0], (float)src[1], (float)src[2], (float)src[3]); 28 | return true; 29 | } 30 | else 31 | { 32 | *dst = defaultValue; 33 | return false; 34 | } 35 | } 36 | 37 | static bool readQuat(std::vector& src, glm::quat* dst, 38 | const glm::quat& defaultValue = glm::quat(1.f, 0.f, 0.f, 0.f)) 39 | { 40 | // glm uses w, x, y, z 41 | if (src.size() > 0) 42 | { 43 | *dst = glm::quat((float)src[3], (float)src[0], (float)src[1], (float)src[2]); 44 | return true; 45 | } 46 | else 47 | { 48 | *dst = defaultValue; 49 | return false; 50 | } 51 | }; 52 | 53 | static void loadMesh(DeviceVulkan& vk, tinygltf::Model& gltfModel, 54 | tinygltf::Mesh& gltfMesh, Mesh* pMesh) 55 | { 56 | // Only handle single triangle primitives (for now). 57 | BASSERT(gltfMesh.primitives.size() == 1); 58 | 59 | auto& primitive = gltfMesh.primitives[0]; 60 | 61 | BASSERT(primitive.mode == TINYGLTF_MODE_TRIANGLES); 62 | 63 | auto& attrs = primitive.attributes; 64 | 65 | int idPosition = attrs.count("POSITION") == 1 ? attrs["POSITION"] : -1; 66 | int idNormal = attrs.count("NORMAL") == 1 ? attrs["NORMAL"] : -1; 67 | int idTexcoord0 = attrs.count("TEXCOORD_0") == 1 ? attrs["TEXCOORD_0"] : -1; 68 | int idIndices = primitive.indices; 69 | int idMaterial = primitive.material; 70 | 71 | pMesh->materialID = idMaterial; 72 | 73 | BASSERT(idPosition >= 0); 74 | 75 | // Load positions 76 | { 77 | BASSERT(gltfModel.accessors[idPosition].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 78 | && gltfModel.accessors[idPosition].type == TINYGLTF_TYPE_VEC3); 79 | 80 | pMesh->vertexCount = (uint32_t)gltfModel.accessors[idPosition].count; 81 | 82 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idPosition].bufferView]; 83 | 84 | //std::vector dbgPositions(bv.byteLength / 12); 85 | //memcpy(dbgPositions.data(), 86 | // &gltfModel.buffers[bv.buffer].data[bv.byteOffset], bv.byteLength); 87 | 88 | createBufferVulkan(vk, { bv.byteLength, 89 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | 90 | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 91 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 92 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 93 | &pMesh->positions); 94 | } 95 | 96 | // Load normals 97 | { 98 | BASSERT(idNormal >= 0); 99 | 100 | BASSERT(gltfModel.accessors[idNormal].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 101 | && gltfModel.accessors[idNormal].type == TINYGLTF_TYPE_VEC3); 102 | 103 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idNormal].bufferView]; 104 | 105 | //auto normalCount = gltfModel.accessors[idNormal].count; 106 | 107 | createBufferVulkan(vk, { bv.byteLength, 108 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 109 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 110 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 111 | &pMesh->normals); 112 | } 113 | 114 | // Load uvs 115 | { 116 | BASSERT(idTexcoord0 >= 0); 117 | 118 | BASSERT(gltfModel.accessors[idTexcoord0].componentType == TINYGLTF_COMPONENT_TYPE_FLOAT 119 | && gltfModel.accessors[idTexcoord0].type == TINYGLTF_TYPE_VEC2); 120 | 121 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idTexcoord0].bufferView]; 122 | 123 | createBufferVulkan(vk, { bv.byteLength, 124 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 125 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 126 | &gltfModel.buffers[bv.buffer].data[bv.byteOffset] }, 127 | &pMesh->uvs); 128 | } 129 | 130 | // Load indices 131 | { 132 | BASSERT(gltfModel.accessors[idIndices].componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT 133 | && gltfModel.accessors[idIndices].type == TINYGLTF_TYPE_SCALAR); 134 | 135 | uint32_t indexCount = (uint32_t)gltfModel.accessors[idIndices].count; 136 | pMesh->indexCount = indexCount; 137 | 138 | std::vector indices16(indexCount); 139 | 140 | auto& bv = gltfModel.bufferViews[gltfModel.accessors[idIndices].bufferView]; 141 | 142 | memcpy(indices16.data(), &gltfModel.buffers[bv.buffer].data[bv.byteOffset], 143 | bv.byteLength); 144 | 145 | std::vector indices32(indices16.begin(), indices16.end()); 146 | 147 | createBufferVulkan(vk, { indexCount * sizeof(uint32_t), 148 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | 149 | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 150 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 151 | indices32.data() }, &pMesh->indices); 152 | } 153 | } 154 | 155 | static void loadMeshes(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 156 | { 157 | // Load meshes 158 | size_t meshCount = model.meshes.size(); 159 | BASSERT(meshCount > 0); 160 | 161 | pScene->meshes.resize(meshCount); 162 | 163 | for (size_t i = 0; i < model.meshes.size(); i++) 164 | loadMesh(vk, model, model.meshes[i], &pScene->meshes[i]); 165 | } 166 | 167 | static void loadSceneNodes(tinygltf::Model& model, Scene* pScene) 168 | { 169 | // Load scene nodes 170 | BASSERT(model.defaultScene == 0); 171 | tinygltf::Scene& gltfScene = model.scenes[model.defaultScene]; 172 | 173 | pScene->nodes.reserve(gltfScene.nodes.size()); 174 | 175 | for (auto i : gltfScene.nodes) 176 | { 177 | auto& srcNode = model.nodes[i]; 178 | 179 | if (srcNode.mesh == -1) 180 | { 181 | // might be a light or camera. 182 | 183 | if (srcNode.children.size()) 184 | { 185 | auto& childNode = model.nodes[srcNode.children[0]]; 186 | if (childNode.camera >= 0) 187 | { 188 | readVec3(srcNode.translation, &pScene->camera.position, glm::vec3(0.f)); 189 | 190 | glm::quat rot1, rot2; 191 | if (readQuat(srcNode.rotation, &rot1)) 192 | { 193 | if (readQuat(childNode.rotation, &rot2)) 194 | { 195 | cameraRotate(pScene->camera, rot1 * rot2); 196 | } 197 | } 198 | 199 | cameraUpdateView(pScene->camera); 200 | } 201 | } 202 | 203 | continue; 204 | } 205 | 206 | pScene->nodes.push_back({}); 207 | SceneNode& dstNode = pScene->nodes.back(); 208 | 209 | dstNode.name = srcNode.name; 210 | dstNode.meshID = srcNode.mesh; 211 | dstNode.children = srcNode.children; 212 | 213 | readVec3(srcNode.translation, &dstNode.translation, glm::vec3(0.f)); 214 | readVec3(srcNode.scale, &dstNode.scale, glm::vec3(1.f)); 215 | readQuat(srcNode.rotation, &dstNode.rotation); 216 | 217 | if (srcNode.matrix.size() > 0) 218 | { 219 | dstNode.matrixValid = true; 220 | memcpy(glm::value_ptr(dstNode.matrix), srcNode.matrix.data(), 221 | sizeof(float) * 16); 222 | } 223 | else 224 | { 225 | dstNode.matrixValid = false; 226 | dstNode.matrix = glm::mat4(1.f); 227 | } 228 | } 229 | } 230 | 231 | static void loadMeshInstanceData(DeviceVulkan& vk, Scene* pScene) 232 | { 233 | std::vector meshInstanceData; 234 | meshInstanceData.reserve(pScene->nodes.size()); 235 | 236 | for (auto& node : pScene->nodes) 237 | { 238 | MeshInstanceData mid = {}; 239 | mid.materialID = pScene->meshes[node.meshID].materialID; 240 | 241 | meshInstanceData.push_back(mid); 242 | } 243 | 244 | createBufferVulkan(vk, { sizeof(MeshInstanceData) * meshInstanceData.size(), 245 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 246 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 247 | meshInstanceData.data() }, &pScene->meshInstanceDataBuffer); 248 | } 249 | 250 | static void loadMaterials(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 251 | { 252 | // Note: Only loading PBR Metal/Roughness properties (not specular extension) 253 | std::vector materials(model.materials.size()); 254 | pScene->baseColorTextureInfos.resize(model.materials.size()); 255 | 256 | auto& textures = pScene->textures; 257 | VkImageView fallbackBlackView = pScene->fallbackTextureBlack.view; 258 | VkImageView fallbackWhiteView = pScene->fallbackTextureWhite.view; 259 | 260 | for (size_t i = 0; i < model.materials.size(); i++) 261 | { 262 | auto& gltfMat = model.materials[i]; 263 | Material& mat = materials[i]; 264 | 265 | auto& pbr = gltfMat.pbrMetallicRoughness; 266 | 267 | readVec4(pbr.baseColorFactor, &mat.baseColorFactor, glm::vec4(1.f)); 268 | 269 | int baseColorID = pbr.baseColorTexture.index; 270 | 271 | VkImageView baseColorView = baseColorID >= 0 ? 272 | textures[baseColorID].view : fallbackWhiteView; 273 | 274 | auto& baseColorInfos = pScene->baseColorTextureInfos[i]; 275 | baseColorInfos.sampler = nullptr; 276 | baseColorInfos.imageView = baseColorView; 277 | baseColorInfos.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 278 | } 279 | 280 | createBufferVulkan(vk, { sizeof(Material) * materials.size(), 281 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, 282 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 283 | materials.data() }, &pScene->materialsBuffer); 284 | } 285 | 286 | static void loadImages(DeviceVulkan& vk, tinygltf::Model& model, Scene* pScene) 287 | { 288 | if (model.images.size() == 0) 289 | return; 290 | 291 | VkCommandBuffer cmdBuffer = createOneTimeCommandBuffer(vk); 292 | 293 | pScene->textures.resize(model.images.size()); 294 | 295 | std::vector stagingBuffers; 296 | 297 | for (size_t i = 0; i < model.images.size(); i++) 298 | { 299 | auto& gltfImage = model.images[i]; 300 | auto& texture = pScene->textures[i]; 301 | 302 | createImageVulkanLocal(vk, { VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, 303 | { (uint32_t)gltfImage.width, (uint32_t)gltfImage.height, 1}, 304 | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 305 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT }, 306 | cmdBuffer, gltfImage.image.size(), gltfImage.image.data(), 307 | &texture, &stagingBuffers); 308 | 309 | // BONI TODO: generate mips 310 | } 311 | 312 | submitOneTimeCommandBuffer(vk, cmdBuffer); 313 | 314 | for (auto& b : stagingBuffers) 315 | destroyBufferVulkan(vk, b); 316 | } 317 | 318 | 319 | bool loadGltfFile(DeviceVulkan& vk, const char* fn, Scene* pScene) 320 | { 321 | tinygltf::Model model; 322 | tinygltf::TinyGLTF loader; 323 | 324 | std::string err; 325 | std::string warn; 326 | bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, fn); 327 | BASSERT(ret); 328 | 329 | if (ret == false) 330 | { 331 | DebugPrint("Error: could not load %s\n", fn); 332 | return false; 333 | } 334 | 335 | if (model.scenes.size() == 0) 336 | { 337 | DebugPrint("Error: no scene found in %s\n", fn); 338 | return false; 339 | } 340 | 341 | loadMeshes(vk, model, pScene); 342 | 343 | loadSceneNodes(model, pScene); 344 | 345 | loadMeshInstanceData(vk, pScene); 346 | 347 | loadImages(vk, model, pScene); 348 | 349 | loadMaterials(vk, model, pScene); 350 | 351 | return true; 352 | } 353 | 354 | 355 | -------------------------------------------------------------------------------- /06-sample-reflection/src/gltfLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | bool loadGltfFile(DeviceVulkan& vk, const char* fn, Scene* pScene); 5 | 6 | -------------------------------------------------------------------------------- /06-sample-reflection/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "logging.h" 4 | 5 | void DebugPrint(const char* fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | size_t len = _vscprintf(fmt, args) + 1; 10 | std::vector buff(len); 11 | vsnprintf_s(buff.data(), len, _TRUNCATE, fmt, args); 12 | OutputDebugStringA(buff.data()); 13 | va_end(args); 14 | } 15 | -------------------------------------------------------------------------------- /06-sample-reflection/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void DebugPrint(const char* fmt, ...); 4 | 5 | #define BASSERT(expr) ((void)((!!(expr)) || \ 6 | ((DebugPrint("Error: %s, %s:%d\n", #expr, __FILE__, __LINE__),1) \ 7 | && (__debugbreak(),0)) )) 8 | 9 | 10 | -------------------------------------------------------------------------------- /06-sample-reflection/src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #define TINYGLTF_IMPLEMENTATION 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | // #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. 7 | #pragma warning(push) 8 | #pragma warning(disable : 4996) // printf unsafe 9 | #pragma warning(disable : 4267) // size_t -> uint32_t 10 | #include "tiny_gltf.h" 11 | #pragma warning(pop) 12 | -------------------------------------------------------------------------------- /06-sample-reflection/src/pch.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #pragma warning(push) 15 | #pragma warning(disable: 26812) 16 | #include 17 | #pragma warning(pop) 18 | 19 | #define GLFW_EXPOSE_NATIVE_WIN32 20 | #include 21 | #include 22 | 23 | #define GLM_ENABLE_EXPERIMENTAL 24 | #define GLM_FORCE_RADIANS 25 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | -------------------------------------------------------------------------------- /06-sample-reflection/update-proj.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | -------------------------------------------------------------------------------- /07-sample-refraction/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | 3 | .vs/ 4 | bin/ 5 | obj/ 6 | 7 | *.spv 8 | 9 | -------------------------------------------------------------------------------- /07-sample-refraction/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "sample-refraction" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win64" } 4 | 5 | project "sample-refraction" 6 | kind "ConsoleApp" 7 | language "C++" 8 | cppdialect "C++17" 9 | 10 | pchheader "pch.h" 11 | pchsource "src/pch.cpp" 12 | 13 | libdirs { 14 | "../external/glfw/lib-vc2019" 15 | } 16 | links { 17 | "glfw3" 18 | } 19 | 20 | defines { 21 | "VOLK_STATIC_DEFINES", 22 | "VK_USE_PLATFORM_WIN32_KHR" 23 | } 24 | 25 | includedirs { 26 | "../external/glfw/include", 27 | "../external/glm", 28 | "../external/volk", 29 | "../external/tinygltf", 30 | "$(VULKAN_SDK)/Include", 31 | "src" 32 | } 33 | 34 | files { 35 | "../external/glfw/include/**.h", 36 | "../external/glm/glm/**.hpp", 37 | "../external/glm/util/glm.natvis", 38 | "../external/volk/volk.h", 39 | "../external/volk/volk.c", 40 | "src/**.h", 41 | "src/**.cpp" 42 | } 43 | 44 | filter { 45 | "files:../external/volk/volk.c" 46 | } 47 | flags { "NoPCH" } 48 | 49 | 50 | 51 | filter "platforms:Win64" 52 | system "Windows" 53 | architecture "x64" 54 | 55 | filter "configurations:Debug" 56 | targetsuffix "_D" 57 | defines { "DEBUG" } 58 | symbols "On" 59 | 60 | filter "configurations:Release" 61 | defines { "NDEBUG" } 62 | optimize "On" 63 | 64 | -------------------------------------------------------------------------------- /07-sample-refraction/sample-refraction.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-refraction", "sample-refraction.vcxproj", "{014626D3-6D5C-2469-B6D3-AF8A2229F5F0}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win64 = Debug|Win64 9 | Release|Win64 = Release|Win64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {014626D3-6D5C-2469-B6D3-AF8A2229F5F0}.Debug|Win64.ActiveCfg = Debug Win64|x64 13 | {014626D3-6D5C-2469-B6D3-AF8A2229F5F0}.Debug|Win64.Build.0 = Debug Win64|x64 14 | {014626D3-6D5C-2469-B6D3-AF8A2229F5F0}.Release|Win64.ActiveCfg = Release Win64|x64 15 | {014626D3-6D5C-2469-B6D3-AF8A2229F5F0}.Release|Win64.Build.0 = Release Win64|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /07-sample-refraction/sample-refraction.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /07-sample-refraction/shaders/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.h": "glsl" 4 | } 5 | } -------------------------------------------------------------------------------- /07-sample-refraction/shaders/build-shaders.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call :build raygen.rgen 4 | call :build chit.rchit 5 | call :build shadow-chit.rchit 6 | call :build miss.rmiss 7 | call :build shadow-miss.rmiss 8 | 9 | goto :eof 10 | 11 | :build 12 | %VULKAN_SDK%\bin\glslangValidator.exe -V %1 -o %1.spv 13 | goto :eof 14 | -------------------------------------------------------------------------------- /07-sample-refraction/shaders/chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | const int kMaxDepth = 8; 9 | 10 | struct InstanceData 11 | { 12 | int materialID; 13 | }; 14 | 15 | struct Material 16 | { 17 | vec4 baseColorFactor; 18 | float metalness; 19 | float roughness; 20 | float pad[2]; 21 | }; 22 | 23 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 24 | layout(set = 0, binding = 3) readonly buffer MeshInstanceDataBuffer { InstanceData d[]; } MeshInstanceData; 25 | layout(set = 0, binding = 4) readonly buffer MaterialsBuffer { Material m[]; } Materials; 26 | 27 | layout(set = 1, binding = 0) readonly buffer PositionsBuffer { float p[]; } Positions[]; 28 | layout(set = 2, binding = 0) readonly buffer NormalsBuffer { float n[]; } Normals[]; 29 | layout(set = 3, binding = 0) readonly buffer UvsBuffer { vec2 uv[]; } Uvs[]; 30 | layout(set = 4, binding = 0) readonly buffer IndicesBuffer { uint i[]; } Indices[]; 31 | 32 | layout(set = 5, binding = 0) uniform sampler LinearSampler; 33 | layout(set = 5, binding = 1) uniform texture2D BaseColorTextures[]; 34 | 35 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 36 | 37 | hitAttributeNV vec2 HitAttribs; 38 | 39 | vec2 interpolate(vec2 a, vec2 b, vec2 c, vec3 barycentrics) 40 | { 41 | return a * barycentrics.x + 42 | b * barycentrics.y + 43 | c * barycentrics.z; 44 | } 45 | 46 | vec3 interpolate(vec3 a, vec3 b, vec3 c, vec3 barycentrics) 47 | { 48 | return a * barycentrics.x + 49 | b * barycentrics.y + 50 | c * barycentrics.z; 51 | } 52 | 53 | vec3 getBarycentric() 54 | { 55 | vec3 b; 56 | b.x = 1.0 - HitAttribs.x - HitAttribs.y; 57 | b.y = HitAttribs.x; 58 | b.z = HitAttribs.y; 59 | return b; 60 | } 61 | 62 | uvec3 getFaceIndex() 63 | { 64 | // BONI TODO: when do we _need_ to use nonuniformEXT ? 65 | // ivec3 ind = ivec3( 66 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID], 67 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 1], 68 | // Indices[nonuniformEXT(gl_InstanceID)].i[3 * gl_PrimitiveID + 2] 69 | // ); 70 | 71 | uvec3 f; 72 | f.x = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 0]; 73 | f.y = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 1]; 74 | f.z = Indices[gl_InstanceID].i[3 * gl_PrimitiveID + 2]; 75 | return f; 76 | } 77 | 78 | vec3 getOnePosition(uint index) 79 | { 80 | vec3 p; 81 | p.x = Positions[gl_InstanceID].p[3 * index + 0]; 82 | p.y = Positions[gl_InstanceID].p[3 * index + 1]; 83 | p.z = Positions[gl_InstanceID].p[3 * index + 2]; 84 | return p; 85 | } 86 | 87 | vec3 getGeometricNormalWS(uvec3 faceIndex) 88 | { 89 | vec3 p0 = getOnePosition(faceIndex.x); 90 | vec3 p1 = getOnePosition(faceIndex.y); 91 | vec3 p2 = getOnePosition(faceIndex.z); 92 | 93 | vec3 geoN = normalize(cross(p1 - p0, p2 - p0)); 94 | 95 | return normalize(vec3(gl_ObjectToWorldNV * vec4(geoN, 0.))); 96 | } 97 | 98 | vec3 getOneNormal(uint index) 99 | { 100 | vec3 n; 101 | n.x = Normals[gl_InstanceID].n[3 * index + 0]; 102 | n.y = Normals[gl_InstanceID].n[3 * index + 1]; 103 | n.z = Normals[gl_InstanceID].n[3 * index + 2]; 104 | return n; 105 | } 106 | 107 | vec3 getNormalWS(uvec3 faceIndex, vec3 barycentric) 108 | { 109 | vec3 n0 = getOneNormal(faceIndex.x); 110 | vec3 n1 = getOneNormal(faceIndex.y); 111 | vec3 n2 = getOneNormal(faceIndex.z); 112 | 113 | vec3 n = normalize(interpolate(n0, n1, n2, barycentric)); 114 | 115 | vec3 N = normalize(vec3(gl_ObjectToWorldNV * vec4(n, 0.))); 116 | 117 | return N; 118 | } 119 | 120 | vec2 getUv(uvec3 faceIndex, vec3 barycentric) 121 | { 122 | vec2 uv0 = Uvs[gl_InstanceID].uv[faceIndex.x]; 123 | vec2 uv1 = Uvs[gl_InstanceID].uv[faceIndex.y]; 124 | vec2 uv2 = Uvs[gl_InstanceID].uv[faceIndex.z]; 125 | 126 | vec2 uv = interpolate(uv0, uv1, uv2, barycentric); 127 | return uv; 128 | } 129 | 130 | void main() 131 | { 132 | uvec3 faceIndex = getFaceIndex(); 133 | vec3 barycentric = getBarycentric(); 134 | 135 | vec3 baseColor = vec3(1., 1., 1.); 136 | 137 | int materialID = MeshInstanceData.d[gl_InstanceID].materialID; 138 | vec2 uv = getUv(faceIndex, barycentric); 139 | 140 | bool transmissive = false; 141 | 142 | // BONI TODO: remove these if checks by having defaults 143 | if (materialID >= 0) 144 | { 145 | vec3 baseColorSample = texture(sampler2D(BaseColorTextures[materialID], LinearSampler), uv).rgb; 146 | baseColorSample = srgbToLinear(baseColorSample); 147 | 148 | Material m = Materials.m[materialID]; 149 | baseColor = baseColorSample * m.baseColorFactor.rgb; 150 | 151 | // if (m.roughness == 0.) 152 | // baseColor = vec3(1,0,0); 153 | 154 | // Treat as transmissive 155 | if (m.baseColorFactor.a < 0.5) 156 | transmissive = true; 157 | } 158 | 159 | vec3 geoN = getGeometricNormalWS(faceIndex); 160 | 161 | vec3 N = getNormalWS(faceIndex, barycentric); 162 | 163 | bool inside = false; 164 | 165 | if (dot(geoN, gl_WorldRayDirectionNV) > 0) 166 | { 167 | N = -N; 168 | inside = true; 169 | } 170 | 171 | // if (inside) 172 | // { 173 | // PrimaryRay.color_distance = vec4(vec3(0,0,1), gl_HitTNV); 174 | // PrimaryRay.normal = vec4(N, 0.); 175 | // return; 176 | // } 177 | 178 | vec3 L = normalize(vec3(1., 1., 1.)); 179 | 180 | float ndotl = max(0., dot(N, L)); 181 | 182 | 183 | if (inside) 184 | { 185 | // color = vec3(0,0,1); 186 | ndotl = 1.0; 187 | } 188 | 189 | vec3 color = vec3(ndotl * baseColor + 0.1); 190 | 191 | PrimaryRay.depth += 1; 192 | 193 | if ((baseColor.r < 1.0 || transmissive) 194 | && PrimaryRay.depth < kMaxDepth) 195 | { 196 | vec3 hitPos = gl_WorldRayOriginNV + gl_WorldRayDirectionNV * gl_HitTNV; 197 | vec3 origin; 198 | 199 | vec3 dir; 200 | 201 | // BONI TODO: transmissive should compute both transmission and 202 | // reflection, but for now we'll just compute the transmissive portion 203 | if (transmissive) 204 | { 205 | // http://hyperphysics.phy-astr.gsu.edu/hbase/Tables/indrf.html 206 | // Air -> Heavy flint glass (1.0029 / 1.65 == 0.607818) 207 | // hmm ... I wonder if I can just use the opacity value as the 208 | // IOR ratio?? 209 | 210 | float eta = 1.0029 / 1.65; // air -> glass 211 | 212 | vec3 worldDir = normalize(gl_WorldRayDirectionNV); 213 | 214 | float dirDotN = dot(worldDir, N); 215 | 216 | eta = inside ? 1.0 / eta : eta; 217 | 218 | origin = hitPos; 219 | dir = refract(worldDir, N, eta); 220 | 221 | float chk = dot(dir, vec3(1)); 222 | 223 | if (abs(chk) > 0.) 224 | { 225 | uint flags = gl_RayFlagsOpaqueNV; 226 | traceNV(Scene, flags, 0xFF, 0, 0, 0, origin, 0.001, dir, 1000, 0); 227 | 228 | PrimaryRay.color_distance.rgb *= color; 229 | } 230 | else 231 | { 232 | // Total Internal Reflection 233 | PrimaryRay.color_distance.rgb = vec3(0); 234 | 235 | origin = hitPos + N * 0.01; 236 | dir = reflect(gl_WorldRayDirectionNV, N); 237 | 238 | uint flags = gl_RayFlagsOpaqueNV; 239 | traceNV(Scene, flags, 0xFF, 0, 0, 0, origin, 0.001, dir, 1000, 0); 240 | 241 | PrimaryRay.color_distance.rgb *= color; 242 | } 243 | } 244 | else 245 | { 246 | origin = hitPos + N * 0.01; 247 | dir = reflect(gl_WorldRayDirectionNV, N); 248 | 249 | uint flags = gl_RayFlagsOpaqueNV; 250 | traceNV(Scene, flags, 0xFF, 0, 0, 0, origin, 0.001, dir, 1000, 0); 251 | 252 | PrimaryRay.color_distance.rgb *= color; 253 | } 254 | } 255 | else 256 | { 257 | PrimaryRay.color_distance = vec4(color, gl_HitTNV); 258 | PrimaryRay.normal = vec4(N, 0.); 259 | } 260 | 261 | PrimaryRay.depth -= 1; 262 | } 263 | 264 | -------------------------------------------------------------------------------- /07-sample-refraction/shaders/miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 0) rayPayloadInNV RayPayload PrimaryRay; 8 | 9 | void main() 10 | { 11 | const vec3 skyBlue = vec3(0.529, 0.808, 0.922); 12 | PrimaryRay.color_distance = vec4(skyBlue, -1.0); 13 | } 14 | -------------------------------------------------------------------------------- /07-sample-refraction/shaders/raygen.rgen: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(set = 0, binding = 0) uniform accelerationStructureNV Scene; 8 | layout(set = 0, binding = 1, rgba8) uniform image2D ResultImage; 9 | layout(set = 0, binding = 2, std140) uniform AppData { UniformParams Params; }; 10 | 11 | layout(location = 0) rayPayloadNV RayPayload PrimaryRay; 12 | layout(location = 1) rayPayloadNV ShadowRayPayload ShadowRay; 13 | 14 | void main() 15 | { 16 | // https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays 17 | vec2 pixelRaster = gl_LaunchIDNV.xy; 18 | vec2 imageSize = gl_LaunchSizeNV.xy; 19 | 20 | // Compute raytacing NDC (note range [0,1]) 21 | vec2 pixelNDC = (pixelRaster + vec2(0.5)) / imageSize; 22 | 23 | // Remap to range [-1, 1] 24 | vec2 pixelSS = pixelNDC * 2.0 - 1.0; 25 | 26 | // Y is reversed (since raster, NDC & screen space have pos Y pointing down) 27 | pixelSS.y = 1.0 - 2.0 * pixelNDC.y; 28 | 29 | // Compute camera/view space. proj has fov, near, far 30 | vec4 pixelCS = Params.projInverse * vec4(pixelSS.x, pixelSS.y, 0., 1.); 31 | 32 | // Camera is at origin in camera space. Compute direction to pixel in camera spce. 33 | vec4 originCS = vec4(0., 0., 0., 1.); 34 | vec4 directionCS = vec4(normalize((pixelCS - originCS).xyz), 0.); 35 | 36 | // Compute world space values 37 | vec4 directionWS = Params.viewInverse * directionCS; 38 | vec4 originWS = Params.viewInverse * vec4(0., 0., 0., 1.); 39 | 40 | uint rayFlags = gl_RayFlagsOpaqueNV; 41 | float tmin = 0.001; 42 | float tmax = 10000.0; 43 | 44 | PrimaryRay.depth = 0; 45 | 46 | traceNV(Scene, rayFlags, 0xFF, 47 | 0, // sbtRecordOffset 48 | 0, // sbtRecordStride 49 | 0, // missIndex 50 | originWS.xyz, 51 | tmin, directionWS.xyz, tmax, 52 | 0 // payload 53 | ); 54 | 55 | vec3 hitColor = PrimaryRay.color_distance.rgb; 56 | float hitDistance = PrimaryRay.color_distance.w; 57 | 58 | if (hitDistance >= 0.) 59 | { 60 | vec3 hitPos = originWS.xyz + directionWS.xyz * hitDistance; 61 | 62 | vec3 hitNormal = PrimaryRay.normal.xyz; 63 | 64 | vec3 toLight = normalize(vec3(1., 1., 1.)); 65 | vec3 shadowRayOrigin = hitPos;// + hitNormal * 0.01; 66 | uint shadowRayFlags = gl_RayFlagsOpaqueNV | gl_RayFlagsTerminateOnFirstHitNV; 67 | 68 | traceNV(Scene, shadowRayFlags, 0xFF, 69 | 1, // offset 1 (choose 2nd hit shader) 70 | 0, // stride ?? 71 | 1, // offset 1 (choose 2nd miss shader) 72 | shadowRayOrigin, 73 | 2, // ?? adjusted for colored-sphere scene 74 | toLight, tmax, 75 | 1 // payload location 1 76 | ); 77 | 78 | if (ShadowRay.distance > 0.) 79 | { 80 | // In shadow 81 | hitColor *= 0.3; 82 | } 83 | 84 | // hitColor = hitNormal; 85 | } 86 | 87 | 88 | hitColor = linearToSrgb(hitColor); 89 | 90 | imageStore(ResultImage, ivec2(gl_LaunchIDNV.xy), vec4(hitColor, 0.)); 91 | } 92 | 93 | 94 | -------------------------------------------------------------------------------- /07-sample-refraction/shaders/shader-common.h: -------------------------------------------------------------------------------- 1 | 2 | // packed std140 3 | struct UniformParams 4 | { 5 | mat4 viewInverse; 6 | mat4 projInverse; 7 | }; 8 | 9 | struct RayPayload 10 | { 11 | vec4 color_distance; 12 | vec4 normal; 13 | int depth; 14 | }; 15 | 16 | struct ShadowRayPayload 17 | { 18 | float distance; 19 | }; 20 | 21 | vec3 srgbToLinear(vec3 c) 22 | { 23 | return pow(c, vec3(2.2)); 24 | } 25 | 26 | vec3 linearToSrgb(vec3 c) 27 | { 28 | return pow(c, vec3(1.0 / 2.2)); 29 | } 30 | -------------------------------------------------------------------------------- /07-sample-refraction/shaders/shadow-chit.rchit: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | #extension GL_EXT_nonuniform_qualifier : require 5 | 6 | #include "shader-common.h" 7 | 8 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 9 | 10 | void main() 11 | { 12 | ShadowRay.distance = gl_HitTNV; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /07-sample-refraction/shaders/shadow-miss.rmiss: -------------------------------------------------------------------------------- 1 | #version 460 2 | #extension GL_NV_ray_tracing : require 3 | #extension GL_GOOGLE_include_directive : require 4 | 5 | #include "shader-common.h" 6 | 7 | layout(location = 1) rayPayloadInNV ShadowRayPayload ShadowRay; 8 | 9 | void main() 10 | { 11 | ShadowRay.distance = -1.0; 12 | } 13 | -------------------------------------------------------------------------------- /07-sample-refraction/src/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DeviceVulkan.h" 4 | #include "camera.h" 5 | 6 | 7 | // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/chap33.html#acceleration-structure 8 | struct VkGeometryInstance 9 | { 10 | float transform[12]; 11 | uint32_t instanceCustomIndex : 24; // gl_InstanceCustomIndexNV 12 | uint32_t mask : 8; 13 | uint32_t instanceOffset : 24; 14 | uint32_t flags : 8; 15 | uint64_t accelerationStructureHandle; 16 | }; 17 | 18 | struct Mesh 19 | { 20 | uint32_t vertexCount; 21 | uint32_t indexCount; 22 | 23 | int materialID; 24 | 25 | // BONI TODO: combine these into VertexBuffer 26 | BufferVulkan positions; 27 | BufferVulkan normals; 28 | BufferVulkan uvs; 29 | 30 | BufferVulkan indices; 31 | 32 | AccelerationStructureVulkan blas; 33 | }; 34 | 35 | // Keep this padded to 16 bytes 36 | struct Material 37 | { 38 | glm::vec4 baseColorFactor; 39 | float metalness; 40 | float roughness; 41 | float pad[2]; 42 | }; 43 | 44 | struct CameraUniformData 45 | { 46 | glm::mat4 viewInverse; 47 | glm::mat4 projInverse; 48 | }; 49 | 50 | struct SceneNode 51 | { 52 | std::string name; 53 | 54 | glm::vec3 translation; 55 | glm::vec3 scale; 56 | glm::quat rotation; 57 | 58 | glm::mat4 matrix; 59 | 60 | std::vector children; 61 | 62 | int meshID; 63 | bool matrixValid; 64 | }; 65 | 66 | struct MeshInstanceData 67 | { 68 | int materialID; 69 | }; 70 | 71 | struct Scene 72 | { 73 | std::vector nodes; 74 | 75 | std::vector meshes; 76 | 77 | std::vector positionsBufferInfos; 78 | std::vector normalsBufferInfos; 79 | std::vector uvsBufferInfos; 80 | std::vector indicesBufferInfos; 81 | 82 | std::vector textures; 83 | 84 | std::vector baseColorTextureInfos; 85 | 86 | ImageVulkan fallbackTextureBlack; 87 | ImageVulkan fallbackTextureWhite; 88 | 89 | BufferVulkan cameraBuffer; 90 | BufferVulkan meshInstanceDataBuffer; 91 | BufferVulkan materialsBuffer; 92 | 93 | VkSampler linearSampler; 94 | 95 | Camera camera; 96 | 97 | AccelerationStructureVulkan topLevelStruct; 98 | }; 99 | 100 | struct App 101 | { 102 | GLFWwindow* window; 103 | 104 | ImageVulkan offscreenImage; 105 | 106 | VkShaderModule raygenShader; 107 | VkShaderModule chitShader; 108 | VkShaderModule shadowChitShader; 109 | VkShaderModule missShader; 110 | VkShaderModule shadowMissShader; 111 | 112 | BufferVulkan instancesBuffer; 113 | BufferVulkan sbtBuffer; 114 | 115 | VkPipelineLayout pipelineLayout; 116 | VkPipeline rtPipeline; 117 | 118 | VkDescriptorPool descriptorPool; 119 | std::vector descriptorSetLayouts; 120 | std::vector descriptorSets; 121 | 122 | bool keysDown[GLFW_KEY_LAST + 1]; 123 | bool mouseDown[GLFW_MOUSE_BUTTON_LAST + 1]; 124 | glm::vec2 cursorPos; 125 | 126 | Scene scene; 127 | }; 128 | 129 | -------------------------------------------------------------------------------- /07-sample-refraction/src/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "camera.h" 4 | 5 | void cameraMove(Camera& camera, const glm::vec3& value) 6 | { 7 | glm::vec3 right = glm::normalize(glm::cross(camera.forward, camera.up)); 8 | 9 | camera.position += right * value.x; 10 | camera.position += camera.up * value.y; 11 | camera.position += camera.forward * value.z; 12 | } 13 | 14 | void cameraRotate(Camera& camera, const float angleX, const float angleY) 15 | { 16 | glm::vec3 right = glm::cross(camera.forward, camera.up); 17 | 18 | glm::quat pitch = glm::angleAxis(glm::radians(angleY), right); 19 | glm::quat heading = glm::angleAxis(glm::radians(angleX), camera.up); 20 | 21 | glm::quat combined = glm::normalize(pitch * heading); 22 | 23 | camera.forward = glm::normalize(glm::rotate(combined, camera.forward)); 24 | } 25 | 26 | void cameraRotate(Camera& camera, const glm::quat& rotation) 27 | { 28 | //camera.up = glm::rotate(rotation, camera.up); 29 | camera.forward = glm::rotate(rotation, camera.forward); 30 | } 31 | 32 | void cameraUpdateProjection(Camera& camera) 33 | { 34 | float left = camera.viewport[0]; 35 | float top = camera.viewport[1]; 36 | float right = camera.viewport[2]; 37 | float bottom = camera.viewport[3]; 38 | 39 | float aspect = float(right - left) / float(bottom - top); 40 | camera.projection = glm::perspectiveRH_ZO( 41 | glm::radians(camera.fovy), aspect, camera.nearz, camera.farz); 42 | } 43 | 44 | void cameraUpdateView(Camera& camera) 45 | { 46 | camera.view = glm::lookAtRH(camera.position, camera.position + camera.forward, camera.up); 47 | } 48 | -------------------------------------------------------------------------------- /07-sample-refraction/src/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Camera 4 | { 5 | std::array viewport; // left, top, right, bottom 6 | float fovy = 60.f; 7 | float nearz = 1.f; 8 | float farz = 1000.f; 9 | 10 | glm::vec3 position; 11 | glm::vec3 up; 12 | glm::vec3 forward; 13 | glm::mat4 projection; 14 | glm::mat4 view; 15 | }; 16 | 17 | void cameraMove(Camera& camera, const glm::vec3& value); 18 | void cameraRotate(Camera& camera, const float angleX, const float angleY); 19 | void cameraRotate(Camera& camera, const glm::quat& rotation); 20 | void cameraUpdateProjection(Camera& camera); 21 | void cameraUpdateView(Camera& camera); 22 | 23 | -------------------------------------------------------------------------------- /07-sample-refraction/src/DeviceVulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VK_CHECK(f) do { \ 4 | VkResult r = f; \ 5 | if (r != VK_SUCCESS) { \ 6 | DebugPrint("VK_CHECK result: %d\n", r); \ 7 | BASSERT(!#f); \ 8 | } \ 9 | } while (false) 10 | 11 | 12 | struct BufferVulkan 13 | { 14 | VkDeviceSize size; 15 | VkBuffer buffer; 16 | VkDeviceMemory memory; 17 | }; 18 | 19 | struct BufferVulkanCreateInfo 20 | { 21 | VkDeviceSize size; 22 | VkBufferUsageFlags usage; 23 | VkMemoryPropertyFlags memoryProperties; 24 | const void* pSrc; 25 | }; 26 | 27 | struct ImageVulkan 28 | { 29 | VkImageType type; 30 | VkFormat format; 31 | VkExtent3D extent; 32 | 33 | VkImage image; 34 | VkImageView view; 35 | 36 | VkDeviceMemory memory; 37 | }; 38 | 39 | struct ImageVulkanCreateInfo 40 | { 41 | VkImageType imageType; 42 | VkFormat format; 43 | VkExtent3D extent; 44 | VkImageUsageFlags usage; 45 | VkMemoryPropertyFlags memoryProperties; 46 | }; 47 | 48 | struct AccelerationStructureVulkan 49 | { 50 | VkDeviceMemory memory; 51 | VkAccelerationStructureInfoNV accelerationStructureInfo; 52 | VkAccelerationStructureNV accelerationStructure; 53 | uint64_t handle; 54 | }; 55 | 56 | struct AccelerationStructureVulkanCreateInfo 57 | { 58 | VkAccelerationStructureTypeNV type; 59 | uint32_t geometryCount; 60 | uint32_t instanceCount; 61 | VkGeometryNV* pGeometries; 62 | }; 63 | 64 | struct DeviceVulkan 65 | { 66 | VkInstance instance; 67 | VkPhysicalDevice physicalDevice; 68 | VkDevice device; 69 | 70 | uint32_t queueIndex; 71 | VkQueue queue; 72 | 73 | VkPhysicalDeviceRayTracingPropertiesNV rtProps; 74 | 75 | VkSurfaceKHR surface; 76 | VkSurfaceFormatKHR surfaceFormat; 77 | VkSwapchainKHR swapchain; 78 | 79 | std::vector swapchainImages; 80 | std::vector swapchainImageViews; 81 | std::vector waitForFrameFences; 82 | 83 | VkCommandPool commandPool; 84 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 85 | std::vector commandBuffers; 86 | VkSemaphore semaphoreImageAcquired; 87 | VkSemaphore semaphoreRenderFinished; 88 | VkDebugReportCallbackEXT debugCallback; 89 | }; 90 | 91 | struct DeviceVulkanCreateInfo 92 | { 93 | void* hwnd; 94 | uint32_t windowWidth; 95 | uint32_t windowHeight; 96 | bool vsync; 97 | }; 98 | 99 | bool createDeviceVulkan(const DeviceVulkanCreateInfo& ci, DeviceVulkan* deviceVulkan); 100 | 101 | void destroyDeviceVulkan(DeviceVulkan& vk); 102 | 103 | uint32_t getMemoryTypeVulkan(const DeviceVulkan& vk, VkMemoryRequirements& memoryRequirements, VkMemoryPropertyFlags memoryProperties); 104 | 105 | bool createBufferVulkan(const DeviceVulkan& vk, const BufferVulkanCreateInfo& ci, BufferVulkan* pBuffer); 106 | 107 | void destroyBufferVulkan(const DeviceVulkan& vk, BufferVulkan& buffer); 108 | 109 | bool createImageVulkan(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, ImageVulkan* pImage); 110 | 111 | // Returns staging buffers which need to be freed by caller 112 | bool createImageVulkanLocal(const DeviceVulkan& vk, const ImageVulkanCreateInfo& ci, 113 | VkCommandBuffer cmdBuffer, size_t size, const void* data, 114 | ImageVulkan* pImage, std::vector* pStagingBuffers); 115 | 116 | void destroyImageVulkan(const DeviceVulkan& vk, ImageVulkan& image); 117 | 118 | bool createShaderVulkan(const DeviceVulkan& vk, const char* filename, VkShaderModule* pShaderModule); 119 | 120 | bool createAccelerationStructureVulkan(const DeviceVulkan& vk, 121 | const AccelerationStructureVulkanCreateInfo& ci, 122 | AccelerationStructureVulkan* pAccelerationStructure); 123 | 124 | void destroyAccelerationStructure(const DeviceVulkan& vk, 125 | AccelerationStructureVulkan& as); 126 | 127 | VkCommandBuffer createOneTimeCommandBuffer(const DeviceVulkan& vk); 128 | void submitOneTimeCommandBuffer(const DeviceVulkan& vk, VkCommandBuffer cmdBuffer); 129 | 130 | -------------------------------------------------------------------------------- /07-sample-refraction/src/gltfLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | bool loadGltfFile(DeviceVulkan& vk, const char* fn, Scene* pScene); 5 | 6 | -------------------------------------------------------------------------------- /07-sample-refraction/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "logging.h" 4 | 5 | void DebugPrint(const char* fmt, ...) 6 | { 7 | va_list args; 8 | va_start(args, fmt); 9 | size_t len = _vscprintf(fmt, args) + 1; 10 | std::vector buff(len); 11 | vsnprintf_s(buff.data(), len, _TRUNCATE, fmt, args); 12 | OutputDebugStringA(buff.data()); 13 | va_end(args); 14 | } 15 | -------------------------------------------------------------------------------- /07-sample-refraction/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void DebugPrint(const char* fmt, ...); 4 | 5 | #define BASSERT(expr) ((void)((!!(expr)) || \ 6 | ((DebugPrint("Error: %s, %s:%d\n", #expr, __FILE__, __LINE__),1) \ 7 | && (__debugbreak(),0)) )) 8 | 9 | 10 | -------------------------------------------------------------------------------- /07-sample-refraction/src/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #define TINYGLTF_IMPLEMENTATION 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | // #define TINYGLTF_NOEXCEPTION // optional. disable exception handling. 7 | #pragma warning(push) 8 | #pragma warning(disable : 4996) // printf unsafe 9 | #pragma warning(disable : 4267) // size_t -> uint32_t 10 | #include "tiny_gltf.h" 11 | #pragma warning(pop) 12 | -------------------------------------------------------------------------------- /07-sample-refraction/src/pch.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #pragma warning(push) 15 | #pragma warning(disable: 26812) 16 | #include 17 | #pragma warning(pop) 18 | 19 | #define GLFW_EXPOSE_NATIVE_WIN32 20 | #include 21 | #include 22 | 23 | #define GLM_ENABLE_EXPERIMENTAL 24 | #define GLM_FORCE_RADIANS 25 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | -------------------------------------------------------------------------------- /07-sample-refraction/update-proj.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Bonifacio Costiniano 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vulkan RTX samples 2 | 3 | ``` 4 | Update 12/21/20 5 | 6 | I plan to update these samples, migrating to the official extensions and cleaning up the code. 7 | 8 | For now I'm archiving this repo until I get to it. 9 | 10 | ``` 11 | 12 | 13 | | Sample | Screenshot | 14 | | ------------- | ------------- | 15 | | 01-sample-triangle

Simple triangle sample

Refs:
* https://github.com/iOrange/rtxON/tree/Version_2_2
* https://github.com/SaschaWillems/Vulkan
* https://developer.nvidia.com/rtx/raytracing/vkray
| ![image](https://user-images.githubusercontent.com/4008312/71532764-d79a0200-28a9-11ea-80ac-7d80a7b21106.png) | 16 | | 02-sample-gltf

Loads single-mesh gltf file.

| ![image](https://user-images.githubusercontent.com/4008312/71532798-fdbfa200-28a9-11ea-969d-45f0b62cb789.png) | 17 | | 03-sample-shadows

Adds another traceNV call to check if object is in shadow.
Also loads multi-mesh gltf.

Refs:
* [GLSL_NV_ray_tracing.txt](https://github.com/KhronosGroup/GLSL/blob/master/extensions/nv/GLSL_NV_ray_tracing.txt)
* [gtc 2018 s8521](http://on-demand.gputechconf.com/gtc/2018/presentation/s8521-advanced-graphics-extensions-for-vulkan.pdf) | ![image](https://user-images.githubusercontent.com/4008312/71532851-4f682c80-28aa-11ea-8bb6-297177abed2b.png) | 18 | | 04-sample-materials

Loads baseColorFactor from gltf.

Refs:
* https://github.com/nvpro-samples/vk_raytrace
* https://github.com/maierfelix/tiny-rtx | ![image](https://user-images.githubusercontent.com/4008312/71553072-9e52b680-29bd-11ea-80a4-24fb6354c16e.png) | 19 | | 05-sample-texture

Loads baseColor texture from gltf.

Refs:
General (and separate samplers/textures)
[GL_KHR_vulkan_glsl.txt](https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_vulkan_glsl.txt)
[Vulkan spec chap12](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/chap12.html)
[Image view/sampler](https://vulkan-tutorial.com/Texture_mapping/Image_view_and_sampler)

Understanding alignment
[GLSL spec variables-and-types](https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.html#variables-and-types)
[GLSL spec](https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf)

Textures
https://cc0textures.com | ![image](https://user-images.githubusercontent.com/4008312/71569766-48961100-2a86-11ea-95d0-27184f762d97.png) | 20 | | 06-sample-reflection

Adds a trace call from hit shader for non-red materials. | ![image](https://user-images.githubusercontent.com/4008312/71643191-28737700-2c6b-11ea-9ac0-506082b964ef.png) | 21 | | 07-sample-refraction

Refraction.
Spheres in image are glass balls.
Uses recursive traceNV calls which should go away in next sample.

Refs:
[SO Refract](https://stackoverflow.com/questions/20801561/glsl-refract-function-explanation-available)
[Ray Tracing Weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html#dielectrics)
[Reboot Red Vulkan RTX](https://github.com/GPSnoopy/RayTracingInVulkan
https://www.youtube.com/watch?v=xpxVAoXaVgg) | ![image](https://user-images.githubusercontent.com/4008312/72675907-0e45e100-3a40-11ea-9e80-4e1eff138dc8.png) | 22 | 23 | -------------------------------------------------------------------------------- /data/backface.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset" : { 3 | "generator" : "Khronos glTF Blender I/O v1.0.5", 4 | "version" : "2.0" 5 | }, 6 | "scene" : 0, 7 | "scenes" : [ 8 | { 9 | "name" : "Scene", 10 | "nodes" : [ 11 | 0, 12 | 2, 13 | 3, 14 | 4, 15 | 5 16 | ] 17 | } 18 | ], 19 | "nodes" : [ 20 | { 21 | "name" : "Light", 22 | "rotation" : [ 23 | 0.16907575726509094, 24 | 0.7558803558349609, 25 | -0.27217137813568115, 26 | 0.570947527885437 27 | ], 28 | "translation" : [ 29 | 4.076245307922363, 30 | 5.903861999511719, 31 | -1.0054539442062378 32 | ] 33 | }, 34 | { 35 | "camera" : 0, 36 | "name" : "Camera_Orientation", 37 | "rotation" : [ 38 | -0.7071067690849304, 39 | 0, 40 | 0, 41 | 0.7071067690849304 42 | ] 43 | }, 44 | { 45 | "children" : [ 46 | 1 47 | ], 48 | "name" : "Camera", 49 | "rotation" : [ 50 | 0.6121924519538879, 51 | 0.009045721963047981, 52 | -0.01602472923696041, 53 | 0.7904946804046631 54 | ], 55 | "translation" : [ 56 | 0.3318600654602051, 57 | 3.0111618041992188, 58 | 8.042500495910645 59 | ] 60 | }, 61 | { 62 | "mesh" : 0, 63 | "name" : "Plane", 64 | "scale" : [ 65 | 6.345885753631592, 66 | 6.345885753631592, 67 | 6.345885753631592 68 | ] 69 | }, 70 | { 71 | "mesh" : 1, 72 | "name" : "Plane.001", 73 | "rotation" : [ 74 | 0.7071067690849304, 75 | 0, 76 | 0, 77 | -0.7071067690849304 78 | ], 79 | "translation" : [ 80 | 0, 81 | 1.0021426677703857, 82 | 0 83 | ] 84 | }, 85 | { 86 | "mesh" : 2, 87 | "name" : "Plane.002", 88 | "rotation" : [ 89 | 0.7071067690849304, 90 | 0, 91 | 0, 92 | -0.7071067690849304 93 | ] 94 | } 95 | ], 96 | "cameras" : [ 97 | { 98 | "name" : "Camera", 99 | "perspective" : { 100 | "yfov" : 0.39959652046304894, 101 | "zfar" : 100, 102 | "znear" : 0.10000000149011612 103 | }, 104 | "type" : "perspective" 105 | } 106 | ], 107 | "materials" : [ 108 | { 109 | "doubleSided" : true, 110 | "name" : "Material.001", 111 | "pbrMetallicRoughness" : { 112 | "baseColorFactor" : [ 113 | 0.8000000715255737, 114 | 0.20708942413330078, 115 | 0.02779129147529602, 116 | 1 117 | ], 118 | "metallicFactor" : 0, 119 | "roughnessFactor" : 0.5 120 | } 121 | } 122 | ], 123 | "meshes" : [ 124 | { 125 | "name" : "Plane", 126 | "primitives" : [ 127 | { 128 | "attributes" : { 129 | "POSITION" : 0, 130 | "NORMAL" : 1, 131 | "TEXCOORD_0" : 2 132 | }, 133 | "indices" : 3, 134 | "material" : 0 135 | } 136 | ] 137 | }, 138 | { 139 | "name" : "Plane.001", 140 | "primitives" : [ 141 | { 142 | "attributes" : { 143 | "POSITION" : 4, 144 | "NORMAL" : 5, 145 | "TEXCOORD_0" : 6 146 | }, 147 | "indices" : 3 148 | } 149 | ] 150 | }, 151 | { 152 | "name" : "Plane.002", 153 | "primitives" : [ 154 | { 155 | "attributes" : { 156 | "POSITION" : 7, 157 | "NORMAL" : 8, 158 | "TEXCOORD_0" : 9 159 | }, 160 | "indices" : 10 161 | } 162 | ] 163 | } 164 | ], 165 | "accessors" : [ 166 | { 167 | "bufferView" : 0, 168 | "componentType" : 5126, 169 | "count" : 4, 170 | "max" : [ 171 | 1, 172 | 0, 173 | 1 174 | ], 175 | "min" : [ 176 | -1, 177 | 0, 178 | -1 179 | ], 180 | "type" : "VEC3" 181 | }, 182 | { 183 | "bufferView" : 1, 184 | "componentType" : 5126, 185 | "count" : 4, 186 | "type" : "VEC3" 187 | }, 188 | { 189 | "bufferView" : 2, 190 | "componentType" : 5126, 191 | "count" : 4, 192 | "type" : "VEC2" 193 | }, 194 | { 195 | "bufferView" : 3, 196 | "componentType" : 5123, 197 | "count" : 6, 198 | "type" : "SCALAR" 199 | }, 200 | { 201 | "bufferView" : 4, 202 | "componentType" : 5126, 203 | "count" : 4, 204 | "max" : [ 205 | 1, 206 | 0, 207 | 1 208 | ], 209 | "min" : [ 210 | -1, 211 | 0, 212 | -1 213 | ], 214 | "type" : "VEC3" 215 | }, 216 | { 217 | "bufferView" : 5, 218 | "componentType" : 5126, 219 | "count" : 4, 220 | "type" : "VEC3" 221 | }, 222 | { 223 | "bufferView" : 6, 224 | "componentType" : 5126, 225 | "count" : 4, 226 | "type" : "VEC2" 227 | }, 228 | { 229 | "bufferView" : 7, 230 | "componentType" : 5126, 231 | "count" : 8, 232 | "max" : [ 233 | 2.4306046962738037, 234 | 1.0235594511032104, 235 | 2.0021426677703857 236 | ], 237 | "min" : [ 238 | -2.4306046962738037, 239 | 1.0235594511032104, 240 | 0.002142667770385742 241 | ], 242 | "type" : "VEC3" 243 | }, 244 | { 245 | "bufferView" : 8, 246 | "componentType" : 5126, 247 | "count" : 8, 248 | "type" : "VEC3" 249 | }, 250 | { 251 | "bufferView" : 9, 252 | "componentType" : 5126, 253 | "count" : 8, 254 | "type" : "VEC2" 255 | }, 256 | { 257 | "bufferView" : 10, 258 | "componentType" : 5123, 259 | "count" : 12, 260 | "type" : "SCALAR" 261 | } 262 | ], 263 | "bufferViews" : [ 264 | { 265 | "buffer" : 0, 266 | "byteLength" : 48, 267 | "byteOffset" : 0 268 | }, 269 | { 270 | "buffer" : 0, 271 | "byteLength" : 48, 272 | "byteOffset" : 48 273 | }, 274 | { 275 | "buffer" : 0, 276 | "byteLength" : 32, 277 | "byteOffset" : 96 278 | }, 279 | { 280 | "buffer" : 0, 281 | "byteLength" : 12, 282 | "byteOffset" : 128 283 | }, 284 | { 285 | "buffer" : 0, 286 | "byteLength" : 48, 287 | "byteOffset" : 140 288 | }, 289 | { 290 | "buffer" : 0, 291 | "byteLength" : 48, 292 | "byteOffset" : 188 293 | }, 294 | { 295 | "buffer" : 0, 296 | "byteLength" : 32, 297 | "byteOffset" : 236 298 | }, 299 | { 300 | "buffer" : 0, 301 | "byteLength" : 96, 302 | "byteOffset" : 268 303 | }, 304 | { 305 | "buffer" : 0, 306 | "byteLength" : 96, 307 | "byteOffset" : 364 308 | }, 309 | { 310 | "buffer" : 0, 311 | "byteLength" : 64, 312 | "byteOffset" : 460 313 | }, 314 | { 315 | "buffer" : 0, 316 | "byteLength" : 24, 317 | "byteOffset" : 524 318 | } 319 | ], 320 | "buffers" : [ 321 | { 322 | "byteLength" : 548, 323 | "uri" : "data:application/octet-stream;base64,AACAPwAAAAAAAIA/AACAPwAAAAAAAIC/AACAvwAAAAAAAIC/AACAvwAAAAAAAIA/AAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAEAAgAAAAIAAwAAAIA/AAAAAAAAgD8AAIA/AAAAAAAAgL8AAIC/AAAAAAAAgL8AAIC/AAAAAAAAgD8AAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAAAAAACAPwAAAIAAAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPzh43D7/A4M/GyMAQDh43D7/A4M/AGwMOwePG0D/A4M/AGwMOwePG0D/A4M/GyMAQAePG8D/A4M/GyMAQAePG8D/A4M/AGwMOzh43L7/A4M/AGwMOzh43L7/A4M/GyMAQAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAEAAgAAAAIAAwAEAAUABgAEAAYABwA=" 324 | } 325 | ] 326 | } 327 | -------------------------------------------------------------------------------- /data/christmas-spheres/ChristmasTreeOrnament05_col.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonizz/bz-rtx/c4607b760fdfe7446982073e0a7f4e4e821d381c/data/christmas-spheres/ChristmasTreeOrnament05_col.png -------------------------------------------------------------------------------- /data/christmas-spheres/christmas-sphere.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonizz/bz-rtx/c4607b760fdfe7446982073e0a7f4e4e821d381c/data/christmas-spheres/christmas-sphere.bin -------------------------------------------------------------------------------- /data/christmas-spheres/christmas-sphere.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset" : { 3 | "generator" : "Khronos glTF Blender I/O v1.0.5", 4 | "version" : "2.0" 5 | }, 6 | "scene" : 0, 7 | "scenes" : [ 8 | { 9 | "name" : "Scene", 10 | "nodes" : [ 11 | 0, 12 | 2, 13 | 3, 14 | 4 15 | ] 16 | } 17 | ], 18 | "nodes" : [ 19 | { 20 | "name" : "Light", 21 | "rotation" : [ 22 | 0.16907575726509094, 23 | 0.7558803558349609, 24 | -0.27217137813568115, 25 | 0.570947527885437 26 | ], 27 | "translation" : [ 28 | 4.076245307922363, 29 | 5.903861999511719, 30 | -1.0054539442062378 31 | ] 32 | }, 33 | { 34 | "camera" : 0, 35 | "name" : "Camera_Orientation", 36 | "rotation" : [ 37 | -0.7071067690849304, 38 | 0, 39 | 0, 40 | 0.7071067690849304 41 | ] 42 | }, 43 | { 44 | "children" : [ 45 | 1 46 | ], 47 | "name" : "Camera", 48 | "rotation" : [ 49 | 0.6566792726516724, 50 | 0.09700826555490494, 51 | -0.09450583159923553, 52 | 0.7419099807739258 53 | ], 54 | "translation" : [ 55 | 0.6718006134033203, 56 | 2.4209558963775635, 57 | 4.6765642166137695 58 | ] 59 | }, 60 | { 61 | "mesh" : 0, 62 | "name" : "Plane", 63 | "scale" : [ 64 | -9.361367225646973, 65 | -9.361367225646973, 66 | -9.361367225646973 67 | ] 68 | }, 69 | { 70 | "mesh" : 1, 71 | "name" : "Sphere", 72 | "translation" : [ 73 | -1.0127153396606445, 74 | 1.6676708459854126, 75 | -1.340914249420166 76 | ] 77 | } 78 | ], 79 | "cameras" : [ 80 | { 81 | "name" : "Camera", 82 | "perspective" : { 83 | "yfov" : 0.39959652046304894, 84 | "zfar" : 100, 85 | "znear" : 0.10000000149011612 86 | }, 87 | "type" : "perspective" 88 | } 89 | ], 90 | "materials" : [ 91 | { 92 | "doubleSided" : true, 93 | "name" : "Material.001", 94 | "pbrMetallicRoughness" : { 95 | "baseColorTexture" : { 96 | "index" : 0, 97 | "texCoord" : 0 98 | }, 99 | "metallicFactor" : 0, 100 | "roughnessFactor" : 0.5 101 | } 102 | } 103 | ], 104 | "meshes" : [ 105 | { 106 | "name" : "Plane", 107 | "primitives" : [ 108 | { 109 | "attributes" : { 110 | "POSITION" : 0, 111 | "NORMAL" : 1, 112 | "TEXCOORD_0" : 2 113 | }, 114 | "indices" : 3 115 | } 116 | ] 117 | }, 118 | { 119 | "name" : "Sphere", 120 | "primitives" : [ 121 | { 122 | "attributes" : { 123 | "POSITION" : 4, 124 | "NORMAL" : 5, 125 | "TEXCOORD_0" : 6 126 | }, 127 | "indices" : 7, 128 | "material" : 0 129 | } 130 | ] 131 | } 132 | ], 133 | "textures" : [ 134 | { 135 | "source" : 0 136 | } 137 | ], 138 | "images" : [ 139 | { 140 | "mimeType" : "image/png", 141 | "name" : "ChristmasTreeOrnament05_col", 142 | "uri" : "ChristmasTreeOrnament05_col.png" 143 | } 144 | ], 145 | "accessors" : [ 146 | { 147 | "bufferView" : 0, 148 | "componentType" : 5126, 149 | "count" : 4, 150 | "max" : [ 151 | 1, 152 | 0, 153 | 1 154 | ], 155 | "min" : [ 156 | -1, 157 | 0, 158 | -1 159 | ], 160 | "type" : "VEC3" 161 | }, 162 | { 163 | "bufferView" : 1, 164 | "componentType" : 5126, 165 | "count" : 4, 166 | "type" : "VEC3" 167 | }, 168 | { 169 | "bufferView" : 2, 170 | "componentType" : 5126, 171 | "count" : 4, 172 | "type" : "VEC2" 173 | }, 174 | { 175 | "bufferView" : 3, 176 | "componentType" : 5123, 177 | "count" : 6, 178 | "type" : "SCALAR" 179 | }, 180 | { 181 | "bufferView" : 4, 182 | "componentType" : 5126, 183 | "count" : 559, 184 | "max" : [ 185 | 1.000000238418579, 186 | 1, 187 | 1.0000003576278687 188 | ], 189 | "min" : [ 190 | -0.9999998211860657, 191 | -1, 192 | -1 193 | ], 194 | "type" : "VEC3" 195 | }, 196 | { 197 | "bufferView" : 5, 198 | "componentType" : 5126, 199 | "count" : 559, 200 | "type" : "VEC3" 201 | }, 202 | { 203 | "bufferView" : 6, 204 | "componentType" : 5126, 205 | "count" : 559, 206 | "type" : "VEC2" 207 | }, 208 | { 209 | "bufferView" : 7, 210 | "componentType" : 5123, 211 | "count" : 2880, 212 | "type" : "SCALAR" 213 | } 214 | ], 215 | "bufferViews" : [ 216 | { 217 | "buffer" : 0, 218 | "byteLength" : 48, 219 | "byteOffset" : 0 220 | }, 221 | { 222 | "buffer" : 0, 223 | "byteLength" : 48, 224 | "byteOffset" : 48 225 | }, 226 | { 227 | "buffer" : 0, 228 | "byteLength" : 32, 229 | "byteOffset" : 96 230 | }, 231 | { 232 | "buffer" : 0, 233 | "byteLength" : 12, 234 | "byteOffset" : 128 235 | }, 236 | { 237 | "buffer" : 0, 238 | "byteLength" : 6708, 239 | "byteOffset" : 140 240 | }, 241 | { 242 | "buffer" : 0, 243 | "byteLength" : 6708, 244 | "byteOffset" : 6848 245 | }, 246 | { 247 | "buffer" : 0, 248 | "byteLength" : 4472, 249 | "byteOffset" : 13556 250 | }, 251 | { 252 | "buffer" : 0, 253 | "byteLength" : 5760, 254 | "byteOffset" : 18028 255 | } 256 | ], 257 | "buffers" : [ 258 | { 259 | "byteLength" : 23788, 260 | "uri" : "christmas-sphere.bin" 261 | } 262 | ] 263 | } 264 | -------------------------------------------------------------------------------- /external/glfw/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2006 Marcus Geelnard 2 | Copyright (c) 2006-2016 Camilla Löwy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would 15 | be appreciated but is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, and must not 18 | be misrepresented as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any source 21 | distribution. 22 | 23 | -------------------------------------------------------------------------------- /external/glfw/lib-vc2019/glfw3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonizz/bz-rtx/c4607b760fdfe7446982073e0a7f4e4e821d381c/external/glfw/lib-vc2019/glfw3.dll -------------------------------------------------------------------------------- /external/glfw/lib-vc2019/glfw3.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonizz/bz-rtx/c4607b760fdfe7446982073e0a7f4e4e821d381c/external/glfw/lib-vc2019/glfw3.lib -------------------------------------------------------------------------------- /external/glfw/lib-vc2019/glfw3dll.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonizz/bz-rtx/c4607b760fdfe7446982073e0a7f4e4e821d381c/external/glfw/lib-vc2019/glfw3dll.lib --------------------------------------------------------------------------------