├── .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
|  |
16 | | 02-sample-gltf
Loads single-mesh gltf file.
|  |
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) |  |
18 | | 04-sample-materials
Loads baseColorFactor from gltf.
Refs:
* https://github.com/nvpro-samples/vk_raytrace
* https://github.com/maierfelix/tiny-rtx |  |
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 |  |
20 | | 06-sample-reflection
Adds a trace call from hit shader for non-red materials. |  |
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) |  |
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
--------------------------------------------------------------------------------