├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── ReSTIRSSS
├── .clang-format
├── .clang-tidy
├── CMakeLists.txt
├── include
│ ├── denoiser
│ │ └── DenoiserOptiX.h
│ └── restirsss
│ │ ├── Raydata.h
│ │ ├── Rayscenes.h
│ │ ├── Raystructs.h
│ │ ├── ReSTIRSSS.h
│ │ ├── ReSTIRSSSEvaluation.h
│ │ ├── ReSTIRSSSEvaluationTiming.h
│ │ ├── ReSTIRSSSVideo.h
│ │ └── passes
│ │ ├── PassDebug.h
│ │ ├── PassGBuffer.h
│ │ ├── PassPathtrace.h
│ │ ├── PassSurface.h
│ │ ├── PassTonemapper.h
│ │ ├── ReSTIRSSSPassCandidateGeneration.h
│ │ ├── ReSTIRSSSPassShade.h
│ │ ├── ReSTIRSSSPassSpatialReuse.h
│ │ └── ReSTIRSSSPassTemporalReuse.h
├── resources
│ ├── environment
│ │ └── white.png
│ ├── scenes
│ │ ├── ajax.xml
│ │ ├── ajaxmanylights.xml
│ │ ├── asiandragon.xml
│ │ ├── flattest.xml
│ │ └── lteorb.xml
│ └── shaders
│ │ ├── arealight.glsl
│ │ ├── bxdf
│ │ ├── bsdf
│ │ │ ├── bsdf.glsl
│ │ │ ├── disney_bsdf.glsl
│ │ │ ├── disney_diffuse.glsl
│ │ │ └── disney_metal.glsl
│ │ ├── diffusion
│ │ │ ├── sss_diffusion_profile.glsl
│ │ │ ├── sss_diffusion_profile_burley.glsl
│ │ │ ├── sss_sampling.glsl
│ │ │ └── sss_sampling_disk.glsl
│ │ └── disney.glsl
│ │ ├── defines.glsl
│ │ ├── environment.glsl
│ │ ├── main
│ │ ├── gbuffer.glsl
│ │ ├── passes
│ │ │ ├── pass_debug.comp
│ │ │ ├── pass_gbuffer.comp
│ │ │ ├── pass_pathtrace.comp
│ │ │ ├── pass_surface.comp
│ │ │ ├── pass_tonemapper.comp
│ │ │ ├── restirsss_pass_candidate_generation.comp
│ │ │ ├── restirsss_pass_shade.comp
│ │ │ ├── restirsss_pass_spatial_reuse.comp
│ │ │ └── restirsss_pass_temporal_reuse.comp
│ │ └── restirsss
│ │ │ ├── probinversetest
│ │ │ ├── restirsss_shift_test.glsl
│ │ │ └── restirsss_target_function_test.glsl
│ │ │ ├── restirsss_defines.glsl
│ │ │ ├── restirsss_disney_bsdf.glsl
│ │ │ ├── restirsss_disney_bssrdf.glsl
│ │ │ ├── restirsss_mis.glsl
│ │ │ ├── restirsss_pixel_info.glsl
│ │ │ ├── restirsss_reservoir.glsl
│ │ │ ├── restirsss_shift.glsl
│ │ │ ├── restirsss_shift_hybrid_criterion.glsl
│ │ │ ├── restirsss_spatial_kernel.glsl
│ │ │ └── restirsss_target_function.glsl
│ │ ├── material.glsl
│ │ ├── raycommon.glsl
│ │ ├── raystructs.glsl
│ │ ├── trace
│ │ ├── trace.glsl
│ │ └── trace_rayquery.glsl
│ │ ├── utility
│ │ ├── colormap.glsl
│ │ ├── constants.glsl
│ │ ├── normal_mapping.glsl
│ │ └── random.glsl
│ │ └── visibility
│ │ └── visibility.glsl
└── src
│ ├── bin
│ └── main.cpp
│ ├── denoiser
│ └── DenoiserOptiX.cpp
│ └── restirsss
│ ├── ReSTIRSSS.cpp
│ ├── ReSTIRSSSEvaluation.cpp
│ ├── ReSTIRSSSEvaluationTiming.cpp
│ └── ReSTIRSSSVideo.cpp
├── VkRaven
├── .clang-format
├── .clang-tidy
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake
│ ├── find
│ │ └── FindOptix.cmake
│ └── setup.cmake
├── lib
│ ├── CMakeLists.txt
│ └── main.cpp
└── raven
│ ├── CMakeLists.txt
│ ├── include
│ └── raven
│ │ ├── RavenInclude.h
│ │ ├── core
│ │ ├── AccelerationStructure.h
│ │ ├── Application.h
│ │ ├── Buffer.h
│ │ ├── GPUContext.h
│ │ ├── HeadlessApplication.h
│ │ ├── Image.h
│ │ ├── Queues.h
│ │ ├── RavenVkDynamicLoader.h
│ │ ├── Renderer.h
│ │ ├── Shader.h
│ │ ├── SwapChain.h
│ │ ├── Texture.h
│ │ ├── TimingHeadlessApplication.h
│ │ ├── Uniform.h
│ │ ├── VideoHeadlessApplication.h
│ │ └── VkDebugUtils.h
│ │ ├── passes
│ │ ├── ImGuiPass.h
│ │ ├── Pass.h
│ │ ├── PassCompute.h
│ │ ├── PassShader.h
│ │ ├── PassShaderCompute.h
│ │ └── PassShaderRayTracing.h
│ │ ├── rendergraph
│ │ ├── RenderGraph.h
│ │ ├── RenderGraphPass.h
│ │ └── RenderGraphResource.h
│ │ ├── scene
│ │ ├── ISceneLoader.h
│ │ ├── RavenLight.h
│ │ ├── RavenMaterial.h
│ │ ├── RavenScene.h
│ │ ├── RavenSceneNode.h
│ │ ├── RavenSceneObject.h
│ │ ├── RavenTexture.h
│ │ └── loader
│ │ │ └── GLTFLoader.h
│ │ └── util
│ │ ├── AABB.h
│ │ ├── Camera.h
│ │ ├── ImagePFM.h
│ │ ├── Paths.h
│ │ ├── Trajectory.h
│ │ ├── animation
│ │ └── BSpline.h
│ │ └── sampling
│ │ └── AliasTable.h
│ └── src
│ └── raven
│ └── core
│ ├── Application.cpp
│ ├── GPUContext.cpp
│ ├── HeadlessApplication.cpp
│ ├── Queues.cpp
│ ├── RavenVkDynamicLoader.cpp
│ ├── TimingHeadlessApplication.cpp
│ └── VideoHeadlessApplication.cpp
├── screenshot.png
└── teaser.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # JetBrains IDE
2 | .idea/*
3 | **/.idea/*
4 | *.iws
5 | *.iml
6 | *.eml
7 |
8 | /build/*
9 | **/cmake-build-*/*
10 |
11 | # Visual Studio
12 | /out/
13 | **/out/
14 | CmakeSettings.json
15 | /.vs/
16 | **/.vs/
17 |
18 | # Shaders
19 | *.spv
20 |
21 | # assets
22 | **/resources/assets/*
23 | **/resources/environment/*
24 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "VkRaven/lib/stb"]
2 | path = VkRaven/lib/stb
3 | url = git@github.com:nothings/stb.git
4 | [submodule "VkRaven/lib/tinyobjloader"]
5 | path = VkRaven/lib/tinyobjloader
6 | url = git@github.com:tinyobjloader/tinyobjloader.git
7 | [submodule "VkRaven/lib/SPIRV-Reflect"]
8 | path = VkRaven/lib/SPIRV-Reflect
9 | url = git@github.com:KhronosGroup/SPIRV-Reflect.git
10 | [submodule "VkRaven/lib/tinygltf"]
11 | path = VkRaven/lib/tinygltf
12 | url = git@github.com:syoyo/tinygltf.git
13 | [submodule "VkRaven/lib/glfw"]
14 | path = VkRaven/lib/glfw
15 | url = git@github.com:glfw/glfw.git
16 | [submodule "VkRaven/lib/glm"]
17 | path = VkRaven/lib/glm
18 | url = git@github.com:g-truc/glm.git
19 | [submodule "VkRaven/lib/imgui"]
20 | path = VkRaven/lib/imgui
21 | url = git@github.com:ocornut/imgui.git
22 | [submodule "VkRaven/lib/pugixml"]
23 | path = VkRaven/lib/pugixml
24 | url = git@github.com:zeux/pugixml.git
25 | [submodule "VkRaven/lib/argparse"]
26 | path = VkRaven/lib/argparse
27 | url = git@github.com:p-ranav/argparse.git
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Mirco Werner
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 | # ReSTIR Subsurface Scattering for Real-Time Path Tracing (ReSTIR SSS)
2 | 
3 |
4 | ## Introduction
5 | This repository contains the source code for the HPG 2024 paper:
6 |
7 | > [**ReSTIR Subsurface Scattering for Real-Time Path Tracing**](https://doi.org/10.1145/3675372)
8 | > [Mirco Werner](https://github.com/MircoWerner), [Vincent Schüßler](https://cg.ivd.kit.edu/schuessler/staff_index.php), and [Carsten Dachsbacher](https://cg.ivd.kit.edu/dachsbacher/staff_index.php)
9 |
10 | > *Abstract* Subsurface scattering is an important visual cue and in real-time rendering it is often approximated using screen-space algorithms. Path tracing with the diffusion approximation can easily overcome the limitations of these algorithms, but increases image noise. We improve its efficiency by applying reservoir-based spatio-temporal importance resampling (ReSTIR) to subsurface light transport paths. For this, we adopt BSSRDF importance sampling for generating candidates. Further, spatiotemporal reuse requires shifting paths between domains. We observe that different image regions benefit most from either reconnecting through the translucent object (reconnection shift), or one vertex later (delayed reconnection shift). We first introduce a local subsurface scattering specific criterion for a hybrid shift that deterministically selects one of the two shifts for a path. Due to the locality, it cannot always choose the most efficient shift, e.g. near shadow boundaries. Therefore, we additionally propose a novel sequential shift to combine multiple shift mappings: We execute subsequent resampling passes, each one using a different shift, which does not require to deterministically choose a shift for a path. Instead, resampling can pick the most successful shift implicitly. Our method achieves real-time performance and significantly reduces noise and denoising artifacts in regions with visible subsurface scattering compared to standard path tracing with equal render time.
11 |
12 | ## Structure of the Repository
13 | [`ReSTIRSSS/resources/shaders/main/`](./ReSTIRSSS/resources/shaders/main) contains the GLSL shaders for ReSTIR SSS.
14 | - ReSTIR SSS passes: [`restirsss_pass_candidate_generation`](./ReSTIRSSS/resources/shaders/main/passes/restirsss_pass_candidate_generation.comp), [`restirsss_pass_temporal_reuse`](./ReSTIRSSS/resources/shaders/main/passes/restirsss_pass_temporal_reuse.comp), [`restirsss_pass_spatial_reuse`](./ReSTIRSSS/resources/shaders/main/passes/restirsss_pass_spatial_reuse.comp), and [`restirsss_pass_shade`](./ReSTIRSSS/resources/shaders/main/passes/restirsss_pass_shade.comp)
15 | - ReSTIR SSS reservoir: [`restirsss_reservoir`](./ReSTIRSSS/resources/shaders/main/restirsss/restirsss_reservoir.glsl)
16 | - ReSTIR SSS target function: [`restirsss_target_function`](./ReSTIRSSS/resources/shaders/main/restirsss/restirsss_target_function.glsl)
17 | - ReSTIR SSS shifts (reconnection, delayed reconnection, hybrid, sequential) and their Jacobians: [`restirsss_shift`](./ReSTIRSSS/resources/shaders/main/restirsss/restirsss_shift.glsl)
18 | - MIS weights (generalized balance heuristic, streaming pairwise MIS): [`restirsss_mis`](./ReSTIRSSS/resources/shaders/main/restirsss/restirsss_mis.glsl)
19 |
20 | Our sequential shift strategy uses *probabilistic inversion* to draw new random numbers before applying random replay when shifting a path with delayed reconnection (see paper Sec. 4.3 for details).
21 | We also demonstrate the possibility to use probabilistic inversion in ReSTIR in general to use both path and primary sample space shifts for a certain sample by implementing it in a surface reflection case with a path of length 3 (see supplemental document Sec. 3 for details).
22 | This demonstration can be enabled in [`restirsss_defines`](./ReSTIRSSS/resources/shaders/main/restirsss/restirsss_defines.glsl) using the `RESTIRSSS_PROBINVERSETEST_L3PATH` macro.
23 | Also see [`probinversetest`](./ReSTIRSSS/resources/shaders/main/restirsss/probinversetest).
24 |
25 | ## Requirements
26 | - Vulkan 1.3
27 | - GPU with ray tracing support
28 | - (optional) [OptiX](https://developer.nvidia.com/designworks/optix/download) 8.0.0 or higher and [CUDA Toolkit](https://developer.nvidia.com/cuda-downloads) for [denoising](https://developer.nvidia.com/optix-denoiser)
29 |
30 | Other dependencies are included as submodules in [`VkRaven/lib/`](./VkRaven/lib).
31 |
32 | ## Running the Code
33 | Tested on Linux with GCC 14.1.1 and NVIDIA RTX 3070 GPU.
34 |
35 | Windows is not officially supported, however, we get it to run using MinGW and disabling OptiX support in the [CMake configuration](./ReSTIRSSS/CMakeLists.txt).
36 |
37 | ### Clone and Build
38 | ```bash
39 | git clone --recursive git@github.com:MircoWerner/ReSTIR-SSS.git
40 | cd ReSTIR-SSS/ReSTIRSSS
41 | mkdir build
42 | cd build
43 | cmake ..
44 | make
45 | ```
46 | ### Download Assets
47 | See [ReSTIR SSS Assets](https://github.com/MircoWerner/ReSTIR-SSS-Assets) repository for more details.
48 | ```bash
49 | cd ReSTIR-SSS/ReSTIRSSS/resources
50 | git clone git@github.com:MircoWerner/ReSTIR-SSS-Assets.git assets
51 | cd assets/asiandragon
52 | tar -xf dragon.tar.xz # unpack large file
53 | ```
54 | ### Run
55 | ```bash
56 | cd ReSTIR-SSS/ReSTIRSSS/build
57 | ./restirsss ajax
58 | ```
59 | - The provided scenes can be found in [`ReSTIRSSS/resources/scenes/`](./ReSTIRSSS/resources/scenes): `ajax`, `ajaxmanylights`, `asiandragon`, `lteorb`, `flattest`.
60 | - Use `--preset ...` to select the initial rendering mode. This can also be changed during runtime in the UI.
61 | - Use `--evaluate ...` to start the automatic evaluation to generate renderings (to measure errors) or timings as shown in the paper. The video option generates the frames for our short video.
62 | ```
63 | Usage: restirsss [--help] [--version] [--preset VAR] [--evaluate VAR] scene
64 |
65 | Positional arguments:
66 | scene name of the scene (in resources/scenes/.xml) [required]
67 |
68 | Optional arguments:
69 | -h, --help shows help message and exits
70 | -v, --version prints version information and exits
71 | --preset pathtracing, hybrid, sequential [default: "hybrid"]
72 | --evaluate renderings, timing, video
73 | ```
74 |
75 | ### Controls
76 | - `WASD` to move the camera
77 | - `Space` or `E` to move the camera up
78 | - `Shift` or `Q` to move the camera down
79 | - Hold `Ctrl` to move faster
80 | - Hold `Right Mouse Button` to look around
81 | - `Esc` to close the application
82 |
83 | ## Acknowledgements
84 | We would like to thank the creators and authors of the used assets and libraries:
85 | - Ajax Bust by Jotero, [Asian Dragon](http://graphics.stanford.edu/data/3Dscanrep/) by XYZ RGB Inc, and [LTE Orb](https://github.com/lighttransport/lighttransportequation-orb) by Yasutoshi Mori (@MirageYM).
86 | - [argsparse](https://github.com/p-ranav/argparse), [glfw](https://github.com/glfw/glfw), [glm](https://github.com/g-truc/glm), [imgui](https://github.com/ocornut/imgui), [pugixml](https://github.com/zeux/pugixml), [SPIRV-Reflect](https://github.com/KhronosGroup/SPIRV-Reflect), [stb](https://github.com/nothings/stb), [tinygltf](https://github.com/syoyo/tinygltf), [tinyobjloader](https://github.com/tinyobjloader/tinyobjloader), and [OptiX](https://developer.nvidia.com/optix-denoiser).
87 |
88 | 
--------------------------------------------------------------------------------
/ReSTIRSSS/.clang-format:
--------------------------------------------------------------------------------
1 | # Generated from CLion C/C++ Code Style settings
2 | BasedOnStyle: LLVM
3 | AccessModifierOffset: -4
4 | AlignAfterOpenBracket: Align
5 | AlignConsecutiveAssignments: None
6 | AlignOperands: Align
7 | AllowAllArgumentsOnNextLine: false
8 | AllowAllConstructorInitializersOnNextLine: false
9 | AllowAllParametersOfDeclarationOnNextLine: false
10 | AllowShortBlocksOnASingleLine: Never
11 | AllowShortCaseLabelsOnASingleLine: false
12 | AllowShortFunctionsOnASingleLine: All
13 | AllowShortIfStatementsOnASingleLine: Never
14 | AllowShortLambdasOnASingleLine: All
15 | AllowShortLoopsOnASingleLine: true
16 | AlwaysBreakAfterReturnType: None
17 | AlwaysBreakTemplateDeclarations: Yes
18 | BreakBeforeBraces: Custom
19 | BraceWrapping:
20 | AfterCaseLabel: false
21 | AfterClass: false
22 | AfterControlStatement: Never
23 | AfterEnum: false
24 | AfterFunction: false
25 | AfterNamespace: false
26 | AfterUnion: false
27 | BeforeCatch: false
28 | BeforeElse: false
29 | IndentBraces: false
30 | SplitEmptyFunction: false
31 | SplitEmptyRecord: true
32 | BreakBeforeBinaryOperators: None
33 | BreakBeforeTernaryOperators: true
34 | BreakConstructorInitializers: BeforeColon
35 | BreakInheritanceList: BeforeColon
36 | ColumnLimit: 0
37 | CompactNamespaces: false
38 | ContinuationIndentWidth: 8
39 | IndentCaseLabels: true
40 | IndentPPDirectives: None
41 | IndentWidth: 4
42 | KeepEmptyLinesAtTheStartOfBlocks: true
43 | MaxEmptyLinesToKeep: 2
44 | NamespaceIndentation: All
45 | ObjCSpaceAfterProperty: false
46 | ObjCSpaceBeforeProtocolList: true
47 | PointerAlignment: Right
48 | ReflowComments: false
49 | SpaceAfterCStyleCast: true
50 | SpaceAfterLogicalNot: false
51 | SpaceAfterTemplateKeyword: false
52 | SpaceBeforeAssignmentOperators: true
53 | SpaceBeforeCpp11BracedList: false
54 | SpaceBeforeCtorInitializerColon: true
55 | SpaceBeforeInheritanceColon: true
56 | SpaceBeforeParens: ControlStatements
57 | SpaceBeforeRangeBasedForLoopColon: false
58 | SpaceInEmptyParentheses: false
59 | SpacesBeforeTrailingComments: 1
60 | SpacesInAngles: false
61 | SpacesInCStyleCastParentheses: false
62 | SpacesInContainerLiterals: false
63 | SpacesInParentheses: false
64 | SpacesInSquareBrackets: false
65 | TabWidth: 4
66 | UseTab: Never
67 |
--------------------------------------------------------------------------------
/ReSTIRSSS/.clang-tidy:
--------------------------------------------------------------------------------
1 | # Generated from CLion Inspection settings
2 | ---
3 | Checks: '-*,
4 | bugprone-argument-comment,
5 | bugprone-assert-side-effect,
6 | bugprone-bad-signal-to-kill-thread,
7 | bugprone-branch-clone,
8 | bugprone-copy-constructor-init,
9 | bugprone-dangling-handle,
10 | bugprone-dynamic-static-initializers,
11 | bugprone-fold-init-type,
12 | bugprone-forward-declaration-namespace,
13 | bugprone-forwarding-reference-overload,
14 | bugprone-inaccurate-erase,
15 | bugprone-incorrect-roundings,
16 | bugprone-integer-division,
17 | bugprone-lambda-function-name,
18 | bugprone-macro-parentheses,
19 | bugprone-macro-repeated-side-effects,
20 | bugprone-misplaced-operator-in-strlen-in-alloc,
21 | bugprone-misplaced-pointer-arithmetic-in-alloc,
22 | bugprone-misplaced-widening-cast,
23 | bugprone-move-forwarding-reference,
24 | bugprone-multiple-statement-macro,
25 | bugprone-no-escape,
26 | bugprone-not-null-terminated-result,
27 | bugprone-parent-virtual-call,
28 | bugprone-posix-return,
29 | bugprone-reserved-identifier,
30 | bugprone-sizeof-container,
31 | bugprone-sizeof-expression,
32 | bugprone-spuriously-wake-up-functions,
33 | bugprone-string-constructor,
34 | bugprone-string-integer-assignment,
35 | bugprone-string-literal-with-embedded-nul,
36 | bugprone-suspicious-enum-usage,
37 | bugprone-suspicious-include,
38 | bugprone-suspicious-memset-usage,
39 | bugprone-suspicious-missing-comma,
40 | bugprone-suspicious-semicolon,
41 | bugprone-suspicious-string-compare,
42 | bugprone-suspicious-memory-comparison,
43 | bugprone-suspicious-realloc-usage,
44 | bugprone-swapped-arguments,
45 | bugprone-terminating-continue,
46 | bugprone-throw-keyword-missing,
47 | bugprone-too-small-loop-variable,
48 | bugprone-undefined-memory-manipulation,
49 | bugprone-undelegated-constructor,
50 | bugprone-unhandled-self-assignment,
51 | bugprone-unused-raii,
52 | bugprone-unused-return-value,
53 | bugprone-use-after-move,
54 | bugprone-virtual-near-miss,
55 | cert-dcl21-cpp,
56 | cert-dcl58-cpp,
57 | cert-err34-c,
58 | cert-err52-cpp,
59 | cert-err60-cpp,
60 | cert-flp30-c,
61 | cert-msc50-cpp,
62 | cert-msc51-cpp,
63 | cert-str34-c,
64 | cppcoreguidelines-interfaces-global-init,
65 | cppcoreguidelines-narrowing-conversions,
66 | cppcoreguidelines-pro-type-member-init,
67 | cppcoreguidelines-pro-type-static-cast-downcast,
68 | cppcoreguidelines-slicing,
69 | google-default-arguments,
70 | google-explicit-constructor,
71 | google-runtime-operator,
72 | hicpp-exception-baseclass,
73 | hicpp-multiway-paths-covered,
74 | misc-misplaced-const,
75 | misc-new-delete-overloads,
76 | misc-no-recursion,
77 | misc-non-copyable-objects,
78 | misc-throw-by-value-catch-by-reference,
79 | misc-unconventional-assign-operator,
80 | misc-uniqueptr-reset-release,
81 | modernize-avoid-bind,
82 | modernize-concat-nested-namespaces,
83 | modernize-deprecated-headers,
84 | modernize-deprecated-ios-base-aliases,
85 | modernize-loop-convert,
86 | modernize-make-shared,
87 | modernize-make-unique,
88 | modernize-pass-by-value,
89 | modernize-raw-string-literal,
90 | modernize-redundant-void-arg,
91 | modernize-replace-auto-ptr,
92 | modernize-replace-disallow-copy-and-assign-macro,
93 | modernize-replace-random-shuffle,
94 | modernize-return-braced-init-list,
95 | modernize-shrink-to-fit,
96 | modernize-unary-static-assert,
97 | modernize-use-auto,
98 | modernize-use-bool-literals,
99 | modernize-use-emplace,
100 | modernize-use-equals-default,
101 | modernize-use-equals-delete,
102 | modernize-use-nodiscard,
103 | modernize-use-noexcept,
104 | modernize-use-nullptr,
105 | modernize-use-override,
106 | modernize-use-transparent-functors,
107 | modernize-use-uncaught-exceptions,
108 | mpi-buffer-deref,
109 | mpi-type-mismatch,
110 | openmp-use-default-none,
111 | performance-faster-string-find,
112 | performance-for-range-copy,
113 | performance-implicit-conversion-in-loop,
114 | performance-inefficient-algorithm,
115 | performance-inefficient-string-concatenation,
116 | performance-inefficient-vector-operation,
117 | performance-move-const-arg,
118 | performance-move-constructor-init,
119 | performance-no-automatic-move,
120 | performance-noexcept-move-constructor,
121 | performance-trivially-destructible,
122 | performance-type-promotion-in-math-fn,
123 | performance-unnecessary-copy-initialization,
124 | performance-unnecessary-value-param,
125 | portability-simd-intrinsics,
126 | readability-avoid-const-params-in-decls,
127 | readability-const-return-type,
128 | readability-container-size-empty,
129 | readability-convert-member-functions-to-static,
130 | readability-delete-null-pointer,
131 | readability-deleted-default,
132 | readability-inconsistent-declaration-parameter-name,
133 | readability-make-member-function-const,
134 | readability-misleading-indentation,
135 | readability-misplaced-array-index,
136 | readability-non-const-parameter,
137 | readability-redundant-control-flow,
138 | readability-redundant-declaration,
139 | readability-redundant-function-ptr-dereference,
140 | readability-redundant-smartptr-get,
141 | readability-redundant-string-cstr,
142 | readability-redundant-string-init,
143 | readability-simplify-subscript-expr,
144 | readability-static-accessed-through-instance,
145 | readability-static-definition-in-anonymous-namespace,
146 | readability-string-compare,
147 | readability-uniqueptr-delete-release,
148 | readability-use-anyofallof'
--------------------------------------------------------------------------------
/ReSTIRSSS/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.18)
2 | project(restirsss VERSION 0.1.0 DESCRIPTION "ReSTIR Subsurface Scattering" LANGUAGES CXX)
3 |
4 | set(CMAKE_CXX_STANDARD 20)
5 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
6 |
7 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
8 |
9 | find_package(Vulkan REQUIRED)
10 |
11 | #set(GCC_COVERAGE_COMPILE_FLAGS "-fpermissive")
12 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
13 |
14 | message(STATUS "Compiler Version: ${CMAKE_CXX_COMPILER_ID}")
15 | message(STATUS "Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}")
16 |
17 | # VkRaven Core
18 | if(NOT RAVEN_BASE_DIRECTORY)
19 | message(${CMAKE_CURRENT_SOURCE_DIR})
20 | find_path(RAVEN_BASE_DIRECTORY
21 | NAMES VkRaven/cmake/setup.cmake
22 | PATHS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../..
23 | REQUIRED
24 | DOC "Directory containing VkRaven"
25 | )
26 | endif()
27 | if(EXISTS ${RAVEN_BASE_DIRECTORY}/VkRaven)
28 | add_subdirectory(${RAVEN_BASE_DIRECTORY}/VkRaven ${CMAKE_CURRENT_BINARY_DIR}/VkRaven)
29 | else()
30 | message(FATAL_ERROR "Could not find base directory, please set RAVEN_BASE_DIRECTORY to folder containing VkRaven")
31 | endif()
32 | set(RAVEN_CORE_DIR ${RAVEN_BASE_DIRECTORY}/VkRaven)
33 |
34 | SET(ENABLE_OPTIX ON)
35 | if (ENABLE_OPTIX)
36 | find_package(CUDAToolkit)
37 | if (CUDAToolkit_FOUND)
38 | _add_package_Optix()
39 | else()
40 | message(STATUS "CudaToolkit: Not found")
41 | message(STATUS "OptiX: Disabled")
42 | endif ()
43 | endif ()
44 |
45 | set(RAVENPROJECT_HEADERS
46 | include/restirsss/Raystructs.h include/restirsss/Raydata.h include/restirsss/Rayscenes.h
47 | include/restirsss/passes/PassTonemapper.h
48 | include/denoiser/DenoiserOptiX.h
49 | include/restirsss/ReSTIRSSS.h
50 | include/restirsss/passes/PassGBuffer.h include/restirsss/passes/PassDebug.h include/restirsss/passes/PassSurface.h include/restirsss/passes/PassPathtrace.h
51 | include/restirsss/passes/ReSTIRSSSPassCandidateGeneration.h include/restirsss/passes/ReSTIRSSSPassTemporalReuse.h include/restirsss/passes/ReSTIRSSSPassSpatialReuse.h include/restirsss/passes/ReSTIRSSSPassShade.h
52 | include/restirsss/ReSTIRSSSEvaluation.h include/restirsss/ReSTIRSSSEvaluationTiming.h include/restirsss/ReSTIRSSSVideo.h
53 | )
54 |
55 | set(RAVENPROJECT_SOURCES
56 | src/bin/main.cpp
57 | src/denoiser/DenoiserOptiX.cpp
58 | src/restirsss/ReSTIRSSS.cpp src/restirsss/ReSTIRSSSEvaluation.cpp src/restirsss/ReSTIRSSSEvaluationTiming.cpp src/restirsss/ReSTIRSSSVideo.cpp
59 | )
60 |
61 | add_executable(${CMAKE_PROJECT_NAME} ${RAVENPROJECT_HEADERS} ${RAVENPROJECT_SOURCES})
62 |
63 | target_link_libraries(${CMAKE_PROJECT_NAME} glm Vulkan::Vulkan imgui stb tinyobjloader tinygltf spirv-reflect ravencore glfw pugixml argparse)
64 | if (CUDAToolkit_FOUND)
65 | target_link_libraries(${CMAKE_PROJECT_NAME} CUDA::cudart CUDA::cuda_driver)
66 | endif ()
67 |
68 | target_include_directories(${CMAKE_PROJECT_NAME}
69 | PUBLIC
70 | $
71 | $
72 | PRIVATE
73 | ${CMAKE_CURRENT_SOURCE_DIR}/src
74 | )
75 | if (OPTIX_FOUND)
76 | target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${OPTIX_INCLUDE_DIR})
77 | endif ()
78 |
79 | target_include_directories(${PROJECT_NAME} PRIVATE ${OPTIX_INCLUDE_DIR})
80 |
81 | target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE -DVULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1 -DVULKAN_HPP_STORAGE_SHARED=1)
82 |
83 | SET(RESOURCE_DIRECTORY_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/resources\")
84 | if (RESOURCE_DIRECTORY_PATH)
85 | target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE RESOURCE_DIRECTORY_PATH=${RESOURCE_DIRECTORY_PATH})
86 | endif ()
87 |
88 | add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
89 | COMMAND ${CMAKE_COMMAND} -E copy_directory
90 | "${PROJECT_BINARY_DIR}/VkRaven/lib"
91 | "${PROJECT_BINARY_DIR}")
92 | add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
93 | COMMAND ${CMAKE_COMMAND} -E copy_directory
94 | "${PROJECT_BINARY_DIR}/VkRaven/raven"
95 | "${PROJECT_BINARY_DIR}")
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/Raystructs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace raven {
6 | struct ObjectDescriptor {
7 | uint64_t vertexAddress{};
8 | uint64_t indexAddress{};
9 | uint32_t materialId = 0;
10 |
11 | glm::mat4 modelMatrix = glm::mat4(1.f);
12 | glm::mat4 objectToWorldNormal = glm::mat4(1.f);
13 | };
14 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/ReSTIRSSSEvaluation.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ReSTIRSSS.h"
4 | #include "raven/core/HeadlessApplication.h"
5 |
6 | #include
7 |
8 | namespace raven {
9 | class ReSTIRSSSEvaluation {
10 | #ifdef WIN32
11 | #define DEVICE_EXTENSIONS \
12 | { VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME }
13 | #else
14 | #define DEVICE_EXTENSIONS \
15 | { VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME }
16 | #endif
17 |
18 | public:
19 | int run() {
20 | if (!initialize()) {
21 | return EXIT_FAILURE;
22 | }
23 | if (!evaluate()) {
24 | return EXIT_FAILURE;
25 | }
26 | return EXIT_SUCCESS;
27 | }
28 |
29 | private:
30 | std::string m_directory;
31 |
32 | const bool m_groundTruth = true;
33 | const bool m_png = true;
34 | const bool m_nonSSSObject = true;
35 |
36 | bool initialize() {
37 | const auto t = std::time(nullptr);
38 | const auto tm = *std::localtime(&t);
39 | std::ostringstream oss;
40 | oss << std::put_time(&tm, "evaluation/%Y-%m-%d-%H-%M-%S");
41 | m_directory = oss.str();
42 |
43 | return std::filesystem::create_directories(m_directory);
44 | }
45 |
46 | [[nodiscard]] bool evaluateAjax() const;
47 |
48 | [[nodiscard]] bool evaluateAjaxManyLights() const;
49 |
50 | [[nodiscard]] bool evaluateAjaxIntersectionCount() const;
51 |
52 | [[nodiscard]] bool evaluateAsianDragon(uint32_t sceneMode) const;
53 |
54 | [[nodiscard]] bool evaluateLTEOrb(uint32_t sceneMode) const;
55 |
56 | [[nodiscard]] bool evaluateSpatioTemporalConvergenceAjax() const;
57 | [[nodiscard]] bool evaluateSpatioTemporalConvergenceLTEOrb(uint32_t sceneMode) const;
58 |
59 | [[nodiscard]] bool evaluate() const {
60 | if (!evaluateAjax()) {
61 | return false;
62 | }
63 |
64 | if (!evaluateAjaxManyLights()) {
65 | return false;
66 | }
67 |
68 | if (!evaluateAjaxIntersectionCount()) {
69 | return false;
70 | }
71 |
72 | for (uint32_t i = 0; i < 4; i++) {
73 | if (!evaluateAsianDragon(i)) {
74 | return false;
75 | }
76 | }
77 |
78 | for (uint32_t i = 0; i < 11; i++) {
79 | if (i == 5 || i == 6 || i == 8 || i == 9 || i == 10) {
80 | if (!evaluateLTEOrb(i)) {
81 | return false;
82 | }
83 | }
84 | }
85 |
86 | // if (!evaluateSpatioTemporalConvergenceAjax()) {
87 | // return false;
88 | // }
89 | // if (!evaluateSpatioTemporalConvergenceLTEOrb(6)) {
90 | // return false;
91 | // }
92 |
93 | return true;
94 | }
95 |
96 | static void writeRMSECompare(std::ofstream &compareScript, const std::string &namePrefix, const std::string &nameSuffix) {
97 | compareScript << "printf \"" << namePrefix << nameSuffix << ".png\\n\" 2>&1 | tee -a rmse.txt\n";
98 | compareScript << "compare -metric RMSE " << namePrefix << "ground_truth.png " << namePrefix << nameSuffix << ".png null: 2>&1 | tee -a rmse.txt\n";
99 | compareScript << "printf \"\\n\" 2>&1 | tee -a rmse.txt\n";
100 | }
101 |
102 | static void writeHDRRMSECompare(std::ofstream &compareScript, const std::string &namePrefix, const std::string &nameSuffix) {
103 | compareScript << "printf \"" << namePrefix << nameSuffix << ".hdr\\n\" 2>&1 | tee -a hdr_rmse.txt\n";
104 | compareScript << "./hdr_rmse.sh " << namePrefix << "ground_truth.hdr " << namePrefix << nameSuffix << ".hdr null: 2>&1 | tee -a hdr_rmse.txt\n";
105 | compareScript << "printf \"\\n\" 2>&1 | tee -a hdr_rmse.txt\n";
106 | }
107 |
108 | static void writeMSECompare(std::ofstream &compareScript, const std::string &namePrefix, const std::string &nameSuffix) {
109 | compareScript << "printf \"" << namePrefix << nameSuffix << ".png\\n\" 2>&1 | tee -a mse.txt\n";
110 | compareScript << "compare -metric MSE " << namePrefix << "ground_truth.png " << namePrefix << nameSuffix << ".png null: 2>&1 | tee -a mse.txt\n";
111 | compareScript << "printf \"\\n\" 2>&1 | tee -a mse.txt\n";
112 | }
113 |
114 | static void writeFLIPCompare(std::ofstream &compareScript, const std::string &namePrefix, const std::string &nameSuffix) {
115 | compareScript << "printf \"" << namePrefix << nameSuffix << ".png\\n\" 2>&1 | tee -a flip.txt\n";
116 | compareScript << "./flip.sh " << namePrefix << "ground_truth.png " << namePrefix << nameSuffix << ".png 2>&1 | tee -a flip.txt\n";
117 | compareScript << "printf \"\\n\" 2>&1 | tee -a flip.txt\n";
118 | }
119 | };
120 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/ReSTIRSSSEvaluationTiming.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ReSTIRSSS.h"
4 | #include "raven/core/TimingHeadlessApplication.h"
5 |
6 | namespace raven {
7 | class ReSTIRSSSEvaluationTiming {
8 | #ifdef WIN32
9 | #define DEVICE_EXTENSIONS \
10 | { VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME }
11 | #else
12 | #define DEVICE_EXTENSIONS \
13 | { VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME }
14 | #endif
15 |
16 | public:
17 | int run() {
18 | if (!initialize()) {
19 | return EXIT_FAILURE;
20 | }
21 | if (!evaluate()) {
22 | return EXIT_FAILURE;
23 | }
24 | return EXIT_SUCCESS;
25 | }
26 |
27 | private:
28 | std::string m_directory;
29 |
30 | bool initialize() {
31 | const auto t = std::time(nullptr);
32 | const auto tm = *std::localtime(&t);
33 | std::ostringstream oss;
34 | oss << std::put_time(&tm, "evaluation-timing/%Y-%m-%d-%H-%M-%S");
35 | m_directory = oss.str();
36 |
37 | return std::filesystem::create_directories(m_directory);
38 | }
39 |
40 | [[nodiscard]] bool evaluateAjax() const;
41 |
42 | [[nodiscard]] bool evaluateAjaxManyLights() const;
43 |
44 | [[nodiscard]] bool evaluateAsianDragon(uint32_t sceneMode) const;
45 |
46 | [[nodiscard]] bool evaluateLTEOrb(uint32_t sceneMode) const;
47 |
48 | [[nodiscard]] bool evaluate() const {
49 | if (!evaluateAjax()) {
50 | return false;
51 | }
52 |
53 | if (!evaluateAjaxManyLights()) {
54 | return false;
55 | }
56 |
57 | for (uint32_t i = 0; i < 4; i++) {
58 | if (!evaluateAsianDragon(i)) {
59 | return false;
60 | }
61 | }
62 |
63 | for (uint32_t i = 0; i < 11; i++) {
64 | if (i == 5 || i == 6 || i == 8 || i == 9 || i == 10) {
65 | if (!evaluateLTEOrb(i)) {
66 | return false;
67 | }
68 | }
69 | }
70 |
71 | return true;
72 | }
73 | };
74 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/ReSTIRSSSVideo.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ReSTIRSSS.h"
4 |
5 | #include
6 |
7 | namespace raven {
8 | class ReSTIRSSSVideo {
9 | #ifdef WIN32
10 | #define DEVICE_EXTENSIONS \
11 | { VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME }
12 | #else
13 | #define DEVICE_EXTENSIONS \
14 | { VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME }
15 | #endif
16 |
17 | public:
18 | int run() {
19 | if (!initialize()) {
20 | return EXIT_FAILURE;
21 | }
22 | if (!evaluate()) {
23 | return EXIT_FAILURE;
24 | }
25 | return EXIT_SUCCESS;
26 | }
27 |
28 | private:
29 | std::string m_directory;
30 |
31 | bool initialize() {
32 | const auto t = std::time(nullptr);
33 | const auto tm = *std::localtime(&t);
34 | std::ostringstream oss;
35 | oss << std::put_time(&tm, "video/%Y-%m-%d-%H-%M-%S");
36 | m_directory = oss.str();
37 |
38 | return std::filesystem::create_directories(m_directory);
39 | }
40 |
41 | [[nodiscard]] bool videoAjaxReference() const;
42 | [[nodiscard]] bool videoAjaxPT1SPP() const;
43 | [[nodiscard]] bool videoAjaxPT1SPPDenoised() const;
44 | [[nodiscard]] bool videoAjaxPT6SPP() const;
45 | [[nodiscard]] bool videoAjaxPT6SPPDenoised() const;
46 | [[nodiscard]] bool videoAjaxPT12SPP() const;
47 | [[nodiscard]] bool videoAjaxPT12SPPDenoised() const;
48 | [[nodiscard]] bool videoAjaxSequential() const;
49 | [[nodiscard]] bool videoAjaxSequentialDenoised() const;
50 |
51 | [[nodiscard]] bool videoAsianDragonSpatiotemporalSequential() const;
52 |
53 | [[nodiscard]] bool evaluate() const {
54 | if (!videoAjaxReference()) {
55 | return false;
56 | }
57 | if (!videoAjaxPT1SPP()) {
58 | return false;
59 | }
60 | if (!videoAjaxPT1SPPDenoised()) {
61 | return false;
62 | }
63 | // if (!videoAjaxPT6SPP()) {
64 | // return false;
65 | // }
66 | // if (!videoAjaxPT6SPPDenoised()) {
67 | // return false;
68 | // }
69 | // if (!videoAjaxPT12SPP()) {
70 | // return false;
71 | // }
72 | // if (!videoAjaxPT12SPPDenoised()) {
73 | // return false;
74 | // }
75 | if (!videoAjaxSequential()) {
76 | return false;
77 | }
78 | if (!videoAjaxSequentialDenoised()) {
79 | return false;
80 | }
81 |
82 | // if (!videoAsianDragonSpatiotemporalSequential()) {
83 | // return false;
84 | // }
85 |
86 | return true;
87 | }
88 | };
89 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/PassDebug.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class PassDebug final : public PassShaderCompute {
8 | public:
9 | explicit PassDebug(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "PassDebug") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | protected:
30 | std::vector> createShaders() override {
31 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
32 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
36 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "pass_debug.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
37 | }
38 |
39 | uint32_t getPushConstantRangeSize() override {
40 | return sizeof(PushConstants);
41 | }
42 | };
43 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/PassGBuffer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class PassGBuffer final : public PassShaderCompute {
8 | public:
9 | explicit PassGBuffer(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "PassGBuffer") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | protected:
30 | std::vector> createShaders() override {
31 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
32 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
36 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "pass_gbuffer.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
37 | }
38 |
39 | uint32_t getPushConstantRangeSize() override {
40 | return sizeof(PushConstants);
41 | }
42 | };
43 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/PassPathtrace.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class PassPathtrace final : public PassShaderCompute {
8 | public:
9 | explicit PassPathtrace(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "PassPathtrace") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | protected:
30 | std::vector> createShaders() override {
31 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
32 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
36 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "pass_pathtrace.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
37 | }
38 |
39 | uint32_t getPushConstantRangeSize() override {
40 | return sizeof(PushConstants);
41 | }
42 | };
43 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/PassSurface.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class PassSurface final : public PassShaderCompute {
8 | public:
9 | explicit PassSurface(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "PassSurface") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | protected:
30 | std::vector> createShaders() override {
31 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
32 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
36 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "pass_surface.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
37 | }
38 |
39 | uint32_t getPushConstantRangeSize() override {
40 | return sizeof(PushConstants);
41 | }
42 | };
43 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/PassTonemapper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class PassTonemapper final : public PassShaderCompute {
8 | public:
9 | explicit PassTonemapper(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "PassTonemapper") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | uint32_t g_tonemapper;
16 | };
17 |
18 | PushConstants m_pushConstants = {};
19 |
20 | protected:
21 | std::vector> createShaders() override {
22 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
23 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
24 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
25 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
26 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
27 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "pass_tonemapper.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
28 | }
29 |
30 | uint32_t getPushConstantRangeSize() override {
31 | return sizeof(PushConstants);
32 | }
33 | };
34 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/ReSTIRSSSPassCandidateGeneration.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class ReSTIRSSSPassCandidateGeneration final : public PassShaderCompute {
8 | public:
9 | explicit ReSTIRSSSPassCandidateGeneration(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "ReSTIRSSSPassCandidateGeneration") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | protected:
30 | std::vector> createShaders() override {
31 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
32 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
36 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "restirsss_pass_candidate_generation.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
37 | }
38 |
39 | uint32_t getPushConstantRangeSize() override {
40 | return sizeof(PushConstants);
41 | }
42 | };
43 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/ReSTIRSSSPassShade.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class ReSTIRSSSPassShade final : public PassShaderCompute {
8 | public:
9 | explicit ReSTIRSSSPassShade(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "ReSTIRSSSPassShade") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | protected:
30 | std::vector> createShaders() override {
31 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
32 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
36 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "restirsss_pass_shade.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
37 | }
38 |
39 | uint32_t getPushConstantRangeSize() override {
40 | return sizeof(PushConstants);
41 | }
42 | };
43 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/ReSTIRSSSPassSpatialReuse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class ReSTIRSSSPassSpatialReuse final : public PassShaderCompute {
8 | public:
9 | explicit ReSTIRSSSPassSpatialReuse(GPUContext *gpuContext, const uint32_t spatialCount) : PassShaderCompute(gpuContext, "ReSTIRSSSPassSpatialReuse"), m_spatialCount(spatialCount) {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | void updateSpecializationConstant3(const uint32_t value) {
30 | m_spatialCount = value;
31 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
32 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{3, 12, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth, m_spatialCount};
36 | updateSpecializationConstants(0, specializationMapEntries, specializationData);
37 | }
38 |
39 | protected:
40 | const vk::Extent3D workGroupSize = vk::Extent3D{8, 8, 1};
41 | uint32_t m_spatialCount = 0;
42 |
43 | std::vector> createShaders() override {
44 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
45 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
46 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)},
47 | vk::SpecializationMapEntry{3, 12, sizeof(uint32_t)}};
48 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth, m_spatialCount};
49 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "restirsss_pass_spatial_reuse.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
50 | }
51 |
52 | uint32_t getPushConstantRangeSize() override {
53 | return sizeof(PushConstants);
54 | }
55 | };
56 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/include/restirsss/passes/ReSTIRSSSPassTemporalReuse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "raven/passes/PassShaderCompute.h"
4 | #include "raven/util/Paths.h"
5 |
6 | namespace raven {
7 | class ReSTIRSSSPassTemporalReuse final : public PassShaderCompute {
8 | public:
9 | explicit ReSTIRSSSPassTemporalReuse(GPUContext *gpuContext) : PassShaderCompute(gpuContext, "ReSTIRSSSPassTemporalReuse") {
10 | }
11 |
12 | struct PushConstants {
13 | glm::ivec2 g_pixels;
14 |
15 | glm::vec3 g_ray_origin;
16 | glm::vec3 g_ray_left_bottom;
17 | glm::vec3 g_ray_left_top;
18 | glm::vec3 g_ray_right_bottom;
19 | glm::vec3 g_ray_right_top;
20 |
21 | uint32_t g_frame = 0;
22 |
23 | uint32_t g_rng_init;
24 | uint32_t g_rng_init_offset;
25 | };
26 |
27 | PushConstants m_pushConstants = {};
28 |
29 | protected:
30 | std::vector> createShaders() override {
31 | constexpr auto workGroupSize = vk::Extent3D{8, 8, 1};
32 | auto specializationMapEntries = std::vector{vk::SpecializationMapEntry{0, 0, sizeof(uint32_t)},
33 | vk::SpecializationMapEntry{1, 4, sizeof(uint32_t)},
34 | vk::SpecializationMapEntry{2, 8, sizeof(uint32_t)}};
35 | auto specializationData = std::vector{workGroupSize.width, workGroupSize.height, workGroupSize.depth};
36 | return {std::make_shared(m_gpuContext, Paths::m_resourceDirectoryPath + "/shaders/main/passes", "restirsss_pass_temporal_reuse.comp", vk::ShaderStageFlagBits::eCompute, workGroupSize, specializationMapEntries, specializationData)};
37 | }
38 |
39 | uint32_t getPushConstantRangeSize() override {
40 | return sizeof(PushConstants);
41 | }
42 | };
43 | } // namespace raven
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/environment/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MircoWerner/ReSTIR-SSS/c209f2b72b85cc51aa2577c14534952154ae4313/ReSTIRSSS/resources/environment/white.png
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/scenes/ajax.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/scenes/ajaxmanylights.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/scenes/asiandragon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/scenes/flattest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/scenes/lteorb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/arealight.glsl:
--------------------------------------------------------------------------------
1 | #ifndef AREALIGHT_GLSL
2 | #define AREALIGHT_GLSL
3 |
4 | float arealight_areaTriangle(in const vec3 p0, in const vec3 p1, in const vec3 p2) {
5 | return 0.5 * length(cross(p1 - p0, p2 - p0));
6 | }
7 |
8 | float arealight_pdf_vam(in const float numLights, in const vec3 p0World, in const vec3 p1World, in const vec3 p2World) {
9 | // pdf in solid angle by dividing by the geometry term
10 | return 1.0 / (numLights * arealight_areaTriangle(p0World, p1World, p2World));
11 | }
12 |
13 | void arealight_sample_vam(in const uint xi1, in const float xi2, in const float xi3, in const vec3 vertexPositionWorld, out int objectDescriptorId, out int triangleId, out vec2 barycentrics, out vec3 position, out vec3 normal, out vec3 emission, out float pdf) {
14 | const Light light = g_lights[xi1];// introduces 1 / numLights pdf
15 |
16 | objectDescriptorId = int(light.objectDescriptorId);
17 | triangleId = int(light.triangleId);
18 |
19 | ObjectDescriptor objDesc = g_objectDescriptors[light.objectDescriptorId];
20 | Indices indices = Indices(objDesc.indexAddress);
21 | Vertices vertices = Vertices(objDesc.vertexAddress);
22 |
23 | const ivec3 ind = indices.i[light.triangleId];
24 | const Vertex v0 = vertices.v[ind.x];
25 | const Vertex v1 = vertices.v[ind.y];
26 | const Vertex v2 = vertices.v[ind.z];
27 |
28 | const vec3 p0 = vec3(v0.position_x, v0.position_y, v0.position_z);
29 | const vec3 p1 = vec3(v1.position_x, v1.position_y, v1.position_z);
30 | const vec3 p2 = vec3(v2.position_x, v2.position_y, v2.position_z);
31 |
32 | const vec3 p0World = (objDesc.objectToWorld * vec4(p0, 1.0)).xyz;
33 | const vec3 p1World = (objDesc.objectToWorld * vec4(p1, 1.0)).xyz;
34 | const vec3 p2World = (objDesc.objectToWorld * vec4(p2, 1.0)).xyz;
35 |
36 | // generate point on the triangle
37 | const float s = 1 - sqrt(1 - xi2);
38 | const float t = (1 - s) * xi3;
39 | position = p0World + s * (p1World - p0World) + t * (p2World - p0World);
40 |
41 | const vec3 normalWorld = normalize(cross(p1World - p0World, p2World - p0World));
42 | normal = dot(normalWorld, normalize(vertexPositionWorld - position)) >= 0.0 ? normalWorld : -normalWorld;// align normal in correct direction
43 |
44 | emission = light.emission;
45 |
46 | // pdf in area measure
47 | pdf = arealight_pdf_vam(g_num_lights, p0World, p1World, p2World);
48 |
49 | // barycentrics from positions
50 | const float area = arealight_areaTriangle(p0World, p1World, p2World);
51 | barycentrics.x = arealight_areaTriangle(p0World, position, p2World) / area;// barycentricsY
52 | barycentrics.y = arealight_areaTriangle(p0World, p1World, position) / area;// barycentricsZ
53 | }
54 |
55 | void arealight_sample_vam(in const uint xi1, in const float xi2, in const float xi3, out int objectDescriptorId, out int triangleId, out vec2 barycentrics, out vec3 position, out vec3 unalignedNormal, out vec3 emission, out float pdf) {
56 | const Light light = g_lights[xi1];// introduces 1 / numLights pdf
57 |
58 | objectDescriptorId = int(light.objectDescriptorId);
59 | triangleId = int(light.triangleId);
60 |
61 | ObjectDescriptor objDesc = g_objectDescriptors[light.objectDescriptorId];
62 | Indices indices = Indices(objDesc.indexAddress);
63 | Vertices vertices = Vertices(objDesc.vertexAddress);
64 |
65 | const ivec3 ind = indices.i[light.triangleId];
66 | const Vertex v0 = vertices.v[ind.x];
67 | const Vertex v1 = vertices.v[ind.y];
68 | const Vertex v2 = vertices.v[ind.z];
69 |
70 | const vec3 p0 = vec3(v0.position_x, v0.position_y, v0.position_z);
71 | const vec3 p1 = vec3(v1.position_x, v1.position_y, v1.position_z);
72 | const vec3 p2 = vec3(v2.position_x, v2.position_y, v2.position_z);
73 |
74 | const vec3 p0World = (objDesc.objectToWorld * vec4(p0, 1.0)).xyz;
75 | const vec3 p1World = (objDesc.objectToWorld * vec4(p1, 1.0)).xyz;
76 | const vec3 p2World = (objDesc.objectToWorld * vec4(p2, 1.0)).xyz;
77 |
78 | // generate point on the triangle
79 | const float s = 1 - sqrt(1 - xi2);
80 | const float t = (1 - s) * xi3;
81 | position = p0World + s * (p1World - p0World) + t * (p2World - p0World);
82 |
83 | unalignedNormal = normalize(cross(p1World - p0World, p2World - p0World));
84 |
85 | emission = light.emission;
86 |
87 | // pdf in area measure
88 | pdf = arealight_pdf_vam(g_num_lights, p0World, p1World, p2World);
89 |
90 | // barycentrics from positions
91 | const float area = arealight_areaTriangle(p0World, p1World, p2World);
92 | barycentrics.x = arealight_areaTriangle(p0World, position, p2World) / area;// barycentricsY
93 | barycentrics.y = arealight_areaTriangle(p0World, p1World, position) / area;// barycentricsZ
94 | }
95 |
96 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/bxdf/bsdf/bsdf.glsl:
--------------------------------------------------------------------------------
1 | #ifndef BSDF_GLSL
2 | #define BSDF_GLSL
3 |
4 | #include "../../utility/constants.glsl"
5 | #include "../../material.glsl"
6 | #include "../diffusion/sss_diffusion_profile.glsl"
7 |
8 | struct BSDFVertex {
9 | // vec3 position;
10 | vec3 geometricNormal;
11 | };
12 |
13 | struct BSDFFrame {
14 | vec3 t;
15 | vec3 b;
16 | vec3 n;
17 | };
18 |
19 | struct BSDFMaterial {
20 | vec3 baseColor;
21 | float roughness;
22 | float anisotropic;
23 | float metallic;
24 | float subsurface;
25 | vec3 scatterDistance;
26 | };
27 |
28 | BSDFMaterial bsdfMaterialInit(in const Material material, in const vec2 uv) {
29 | BSDFMaterial bsdfMaterial;
30 | bsdfMaterial.baseColor = material_getAlbedo(material, uv);
31 | bsdfMaterial.roughness = material_getRoughness(material, uv);
32 | bsdfMaterial.anisotropic = 0.0;
33 | bsdfMaterial.metallic = material_getMetallic(material, uv);
34 | bsdfMaterial.subsurface = material.subsurface;
35 | bsdfMaterial.scatterDistance = material.subsurface * material.meanFreePath / sss_diffusion_profile_scatterDistance(bsdfMaterial.baseColor);
36 | return bsdfMaterial;
37 | }
38 |
39 | /// Project a vector to a frame's local coordinates.
40 | vec3 toLocal(in const BSDFFrame frame, in const vec3 v) {
41 | return vec3(dot(v, frame.t), dot(v, frame.b), dot(v, frame.n));
42 | }
43 |
44 | /// Convert a vector in a frame's local coordinates to the reference coordinate the frame is in.
45 | vec3 toWorld(in const BSDFFrame frame, in const vec3 v) {
46 | return frame.t * v[0] + frame.b * v[1] + frame.n * v[2];
47 | }
48 |
49 | /// Given a vector n, outputs two vectors such that all three vectors are
50 | /// orthogonal to each other.
51 | /// The approach here is based on Frisvad's paper
52 | /// "Building an Orthonormal Basis from a 3D Unit Vector Without Normalization"
53 | /// https://backend.orbit.dtu.dk/ws/portalfiles/portal/126824972/onb_frisvad_jgt2012_v2.pdf
54 | BSDFFrame coordinateSystem(in const vec3 n) {
55 | BSDFFrame frame;
56 | frame.n = n;
57 | if (n[2] < (-1 + 1e-6)) {
58 | frame.t = vec3(0, -1, 0);
59 | frame.b = vec3(-1, 0, 0);
60 | } else {
61 | float a = 1 / (1 + n[2]);
62 | float b = -n[0] * n[1] * a;
63 | frame.t = vec3(1 - n[0] * n[0] * a, b, -n[0]);
64 | frame.b = vec3(b, 1 - n[1] * n[1] * a, -n[1]);
65 | }
66 | return frame;
67 | }
68 |
69 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/bxdf/bsdf/disney_bsdf.glsl:
--------------------------------------------------------------------------------
1 | #ifndef BSDF_DISNEYA_GLSL
2 | #define BSDF_DISNEYA_GLSL
3 |
4 | #include "bsdf.glsl"
5 | #include "disney_diffuse.glsl"
6 | #include "disney_metal.glsl"
7 |
8 | float bsdf_disney_lobe_weight(in const BSDFMaterial material, in const float rndLobe) {
9 | const float metallic = material.metallic;
10 | const float diffuseWeight = 1.0 - metallic;
11 | const float metalWeight = metallic;
12 | const float sumWeights = diffuseWeight + metalWeight;
13 |
14 | if (rndLobe < diffuseWeight / sumWeights) {
15 | return diffuseWeight / sumWeights;
16 | } else {
17 | return metalWeight / sumWeights;
18 | }
19 | }
20 |
21 | uint bsdf_disney_lobe_index(in const BSDFMaterial material, in const float rndLobe) {
22 | const float metallic = material.metallic;
23 | const float diffuseWeight = 1.0 - metallic;
24 | const float metalWeight = metallic;
25 | const float sumWeights = diffuseWeight + metalWeight;
26 |
27 | if (rndLobe < diffuseWeight / sumWeights) {
28 | return 0;
29 | } else {
30 | return 1;
31 | }
32 | }
33 |
34 | vec3 bsdf_disney_evaluate(in const BSDFVertex vertex, in const BSDFFrame frame, in const BSDFMaterial material, in const vec3 dirIn, in const vec3 dirOut) {
35 | const vec3 diffuse = bsdf_disney_diffuse_evaluate(vertex, frame, material, dirIn, dirOut);
36 | const vec3 metal = bsdf_disney_metal_evaluate(vertex, frame, material, dirIn, dirOut);
37 |
38 | const float metallic = material.metallic;
39 |
40 | return (1.0 - metallic) * diffuse + metallic * metal;
41 | }
42 |
43 | bool bsdf_disney_sample(in const BSDFVertex vertex, in const BSDFFrame frame, in const BSDFMaterial material, in const vec3 dirIn, out vec3 dirOut, in const uint lobe, in const vec2 rndParam) {
44 | if (lobe == 0) {
45 | return bsdf_disney_diffuse_sample(vertex, frame, material, dirIn, dirOut, rndParam);
46 | } else {
47 | return bsdf_disney_metal_sample(vertex, frame, material, dirIn, dirOut, rndParam);
48 | }
49 | }
50 |
51 | float bsdf_disney_pdf(in const BSDFVertex vertex, in const BSDFFrame frame, in const BSDFMaterial material, in const vec3 dirIn, in const vec3 dirOut) {
52 | const float diffusePDF = bsdf_disney_diffuse_pdf(vertex, frame, material, dirIn, dirOut);
53 | const float metalPDF = bsdf_disney_metal_pdf(vertex, frame, material, dirIn, dirOut);
54 |
55 | const float metallic = material.metallic;
56 | const float diffuseWeight = 1.0 - metallic;
57 | const float metalWeight = metallic;
58 | const float sumWeights = diffuseWeight + metalWeight;
59 |
60 | return (diffuseWeight * diffusePDF + metalWeight * metalPDF) / sumWeights;
61 | }
62 |
63 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/bxdf/bsdf/disney_diffuse.glsl:
--------------------------------------------------------------------------------
1 | #ifndef BSDF_DISNEY_DIFFUSE_GLSL
2 | #define BSDF_DISNEY_DIFFUSE_GLSL
3 |
4 | #include "bsdf.glsl"
5 |
6 | float fresnelDiffuse90(in const float roughness, in const vec3 dirOut, in const vec3 halfVector) {
7 | return 0.5 + 2.0 * roughness * dot(halfVector, dirOut) * dot(halfVector, dirOut);
8 | }
9 |
10 | float fresnelDiffuse(in const float fd90, in const BSDFFrame frame, in const vec3 omega) {
11 | return 1.0 + (fd90 - 1.0) * pow(1.0 - max(dot(frame.n, omega), 0), 5);
12 | }
13 |
14 | vec3 sampleCosHemisphere(in const vec2 rndParam) {
15 | // float tmp = sqrt(clamp(1 - rndParam[0], 0, 1));
16 | // float phi = TWO_PI * rndParam[1];
17 | // return vec3(cos(phi) * tmp, sin(phi) * tmp, sqrt(clamp(rndParam[0], 0, 1)));
18 | float theta = acos(sqrt(1 - rndParam[0]));
19 | float phi = TWO_PI * rndParam[1];
20 | vec3 omegaLocal = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
21 | return omegaLocal;
22 | }
23 |
24 | vec2 reverseSampleCosHemisphere(in const vec3 omegaLocal) {
25 | float cosTheta = omegaLocal.z;
26 | const float reverseXi1 = 1 - cosTheta * cosTheta;
27 | float sinTheta = sqrt(1 - cosTheta * cosTheta);
28 | float sinPhi = omegaLocal.y / sinTheta;
29 | float cosPhi = omegaLocal.x / sinTheta;
30 | // get angle in [0,2Pi]
31 | float reversePhi = atan(sinPhi, cosPhi);
32 | reversePhi = reversePhi >= 0 ? reversePhi : reversePhi + 2 * PI;
33 | const float reverseXi2 = reversePhi / (2 * PI);
34 | return vec2(reverseXi1, reverseXi2);
35 | }
36 |
37 | //#undef ALPHA
38 | //#define ALPHA 2
39 | //vec3 sampleCosHemisphere(in vec2 rndParam) {
40 | // // float tmp = sqrt(clamp(1 - rndParam[0], 0, 1));
41 | // // float phi = TWO_PI * rndParam[1];
42 | // // return vec3(cos(phi) * tmp, sin(phi) * tmp, sqrt(clamp(rndParam[0], 0, 1)));
43 | // float theta = acos(pow(1 - rndParam[0], 1.0 / (ALPHA + 1.0)));
44 | // float phi = TWO_PI * rndParam[1];
45 | // vec3 omegaLocal = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
46 | // return omegaLocal;
47 | //}
48 | //
49 | //vec2 reverseSampleCosHemisphere(in vec3 omegaLocal) {
50 | // float cosTheta = omegaLocal.z;
51 | // const float reverseXi1 = 1 - pow(cosTheta, ALPHA + 1);
52 | // float sinTheta = sqrt(1 - pow(cosTheta, ALPHA + 1));
53 | // float sinPhi = omegaLocal.y / sinTheta;
54 | // float cosPhi = omegaLocal.x / sinTheta;
55 | // // get angle in [0,2Pi]
56 | // float reversePhi = atan(sinPhi, cosPhi);
57 | // reversePhi = reversePhi >= 0 ? reversePhi : reversePhi + 2 * PI;
58 | // const float reverseXi2 = reversePhi / (2 * PI);
59 | // return vec2(reverseXi1, reverseXi2);
60 | //}
61 |
62 | vec3 bsdf_disney_diffuse_evaluate(in const BSDFVertex vertex, in BSDFFrame frame, in const BSDFMaterial material, in const vec3 dirIn, in const vec3 dirOut) {
63 | if (dot(vertex.geometricNormal, dirIn) < 0 ||
64 | dot(vertex.geometricNormal, dirOut) < 0) {
65 | // No light below the surface
66 | return vec3(0);
67 | }
68 |
69 | // Flip the shading frame if it is inconsistent with the geometry normal
70 | if (dot(frame.n, dirIn) < 0) {
71 | frame.t = -frame.t;
72 | frame.b = -frame.b;
73 | frame.n = -frame.n;
74 | }
75 |
76 | const vec3 halfVector = normalize(dirIn + dirOut);
77 |
78 | // base diffuse
79 | const float fd90 = fresnelDiffuse90(material.roughness, dirOut, halfVector);
80 | const vec3 baseDiffuse = material.baseColor / PI
81 | * fresnelDiffuse(fd90, frame, dirIn) * fresnelDiffuse(fd90, frame, dirOut)
82 | * max(dot(frame.n, dirOut), 0);
83 |
84 | return baseDiffuse;
85 | }
86 |
87 | bool bsdf_disney_diffuse_sample(in const BSDFVertex vertex, in BSDFFrame frame, in const BSDFMaterial material, in const vec3 dirIn, out vec3 dirOut, in const vec2 rndParam) {
88 | if (dot(vertex.geometricNormal, dirIn) < 0) {
89 | // No light below the surface
90 | return false;
91 | }
92 |
93 | // Flip the shading frame if it is inconsistent with the geometry normal
94 | if (dot(frame.n, dirIn) < 0) {
95 | frame.t = -frame.t;
96 | frame.b = -frame.b;
97 | frame.n = -frame.n;
98 | }
99 |
100 | dirOut = toWorld(frame, sampleCosHemisphere(rndParam));
101 | return true;
102 | }
103 |
104 | float bsdf_disney_diffuse_pdf(in const BSDFVertex vertex, in BSDFFrame frame, in const BSDFMaterial material, in const vec3 dirIn, in const vec3 dirOut) {
105 | if (dot(vertex.geometricNormal, dirIn) < 0 ||
106 | dot(vertex.geometricNormal, dirOut) < 0) {
107 | // No light below the surface
108 | return 0;
109 | }
110 |
111 | // Flip the shading frame if it is inconsistent with the geometry normal
112 | if (dot(frame.n, dirIn) < 0) {
113 | frame.t = -frame.t;
114 | frame.b = -frame.b;
115 | frame.n = -frame.n;
116 | }
117 |
118 | return max(dot(frame.n, dirOut), 0) / PI;
119 | // return (ALPHA + 1.0) * pow(max(0, dot(dirOut, frame.n)), ALPHA) / (2.0 * PI);
120 | }
121 |
122 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/bxdf/diffusion/sss_diffusion_profile.glsl:
--------------------------------------------------------------------------------
1 | #ifndef SSS_DIFFUSION_PROFILE_GLSL
2 | #define SSS_DIFFUSION_PROFILE_GLSL
3 |
4 | vec3 sss_diffusion_profile_scatterDistance(in const vec3 surfaceAlbedo);
5 |
6 | vec3 sss_diffusion_profile_evaluate(in const float radius, in const vec3 scatterDistance);
7 |
8 | float sss_diffusion_profile_pdf(in const float radius, in const float scatterDistance);
9 | vec3 sss_diffusion_profile_pdf_vectorized(in const float radius, in const vec3 scatterDistance);
10 |
11 | float sss_diffusion_profile_sample(in const float xi, in const float scatterDistance);
12 |
13 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/bxdf/diffusion/sss_diffusion_profile_burley.glsl:
--------------------------------------------------------------------------------
1 | #ifndef SSS_DIFFUSION_PROFILE_BURLEY_GLSL
2 | #define SSS_DIFFUSION_PROFILE_BURLEY_GLSL
3 |
4 | #include "sss_diffusion_profile.glsl"
5 |
6 | // d = l / s <- mfp / scaling
7 | float sss_diffusion_profile_burley_cdfDiffusion(in const float r, in const float d) {
8 | return 1.0 - 0.25 * exp(-r / d) - 0.75 * exp(-r / (3.0 * d));
9 | }
10 |
11 | float sss_diffusion_profile_burley_cdfFirstDerivativeDiffusion(in const float r, in const float d) {
12 | return 0.25 / d * (exp(-r / d) + exp(-r / (3.0 * d)));
13 | }
14 |
15 | float sss_diffusion_profile_burley_cdfSecondDerivativeDiffusion(in const float r, in const float d) {
16 | return -0.25 / (d * d) * (exp(-r / d) + exp(-r / (3.0 * d)) / 3.0);
17 | }
18 |
19 | vec3 sss_diffusion_profile_scatterDistance(in const vec3 surfaceAlbedo) {
20 | const vec3 a = surfaceAlbedo - vec3(0.8);
21 | return 1.9 - surfaceAlbedo + 3.5 * a * a;
22 | }
23 |
24 | vec3 sss_diffusion_profile_evaluate(in const float radius, in const vec3 scatterDistance) {
25 | if (radius <= 0) {
26 | return vec3(0.25 / PI) / max(vec3(0.000001), scatterDistance);
27 | }
28 | const vec3 rd = radius / scatterDistance;
29 | return (exp(-rd) + exp(-rd / 3.0)) / max(vec3(0.000001), (8.0 * PI * scatterDistance * radius));
30 | }
31 |
32 | float sss_diffusion_profile_pdf(in const float radius, in const float scatterDistance) {
33 | if (radius <= 0) {
34 | return (0.25 / PI) / max(0.000001, scatterDistance);
35 | }
36 | const float rd = radius / scatterDistance;
37 | return (exp(-rd) + exp(-rd / 3.0)) / max(0.000001, (8.0 * PI * scatterDistance * radius));// divide by r to convert from polar to cartesian
38 | }
39 |
40 | vec3 sss_diffusion_profile_pdf_vectorized(in const float radius, in const vec3 scatterDistance) {
41 | if (radius <= 0) {
42 | return (0.25 / PI) / max(vec3(0.000001), scatterDistance);
43 | }
44 | const vec3 rd = radius / scatterDistance;
45 | return (exp(-rd) + exp(-rd / 3.0)) / max(vec3(0.000001), (8.0 * PI * scatterDistance * radius));// divide by r to convert from polar to cartesian
46 | }
47 |
48 | #define LOG2_E 1.44269504089
49 | //// https://zero-radiance.github.io/post/sampling-diffusion/
50 | //// Performs sampling of a Normalized Burley diffusion profile in polar coordinates.
51 | //// 'u' is the random number (the value of the CDF): [0, 1).
52 | //// rcp(s) = 1 / ShapeParam = ScatteringDistance.
53 | //// 'r' is the sampled radial distance, s.t. (u = 0 -> r = 0) and (u = 1 -> r = Inf).
54 | //// rcp(Pdf) is the reciprocal of the corresponding PDF value.
55 | float sampleBurleyDiffusionProfileAnalytical(in float u, in const float rcpS) {
56 | u = 1 - u;// Convert CDF to CCDF; the resulting value of (u != 0)
57 |
58 | const float g = 1 + (4 * u) * (2 * u + sqrt(1 + (4 * u) * u));
59 | const float n = exp2(log2(g) * (-1.0/3.0));// g^(-1/3)
60 | const float p = (g * n) * n;// g^(+1/3)
61 | const float c = 1 + p + n;// 1 + g^(+1/3) + g^(-1/3)
62 | const float x = (3 / LOG2_E) * log2(c / (4 * u));// 3 * Log[c / (4 * u)]
63 |
64 | // x = s * r
65 | // exp_13 = Exp[-x/3] = Exp[-1/3 * 3 * Log[c / (4 * u)]]
66 | // exp_13 = Exp[-Log[c / (4 * u)]] = (4 * u) / c
67 | // exp_1 = Exp[-x] = exp_13 * exp_13 * exp_13
68 | // expSum = exp_1 + exp_13 = exp_13 * (1 + exp_13 * exp_13)
69 | // rcpExp = rcp(expSum) = c^3 / ((4 * u) * (c^2 + 16 * u^2))
70 | const float rcpExp = ((c * c) * c) / ((4 * u) * ((c * c) + (4 * u) * (4 * u)));
71 |
72 | return x * rcpS; // r
73 | }
74 |
75 |
76 | float sss_diffusion_profile_sample(in const float xi, in const float scatterDistance) {
77 | return sampleBurleyDiffusionProfileAnalytical(xi, scatterDistance);
78 |
79 | // SOLVE for r: xi = cdf(r,d)
80 | // use Halley's method to perform numerical inversion (converges in 2-4 iterations) -> https://en.wikipedia.org/wiki/Halley%27s_method
81 | // this is suggested by https://advances.realtimerendering.com/s2018/Efficient%20screen%20space%20subsurface%20scattering%20Siggraph%202018.pdf
82 |
83 | // // xi = cdf(r,d) <=> 0 = cdf(r,d) - xi =: f
84 | // float r = 0.0;
85 | // for (int i = 0; i < 4; i++) {
86 | // float f = sss_diffusion_profile_burley_cdfDiffusion(r, scatterDistance) - xi;
87 | // float df = sss_diffusion_profile_burley_cdfFirstDerivativeDiffusion(r, scatterDistance);
88 | // float ddf = sss_diffusion_profile_burley_cdfSecondDerivativeDiffusion(r, scatterDistance);
89 | //
90 | // r = r - 2.0 * f * df / (2.0 * df * df - f * ddf);
91 | // }
92 | //
93 | // return r;
94 | }
95 |
96 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/bxdf/diffusion/sss_sampling.glsl:
--------------------------------------------------------------------------------
1 | #ifndef SSS_SAMPLING_GLSL
2 | #define SSS_SAMPLING_GLSL
3 |
4 | struct SSSInfo {
5 | vec3 position;
6 |
7 | int objectDescriptorId;
8 |
9 | vec3 scatterDistance;
10 |
11 | uint intersection;
12 | };
13 |
14 | struct SSSSample {
15 | int objectDescriptorId;
16 | int triangleId;
17 | vec2 barycentrics;
18 |
19 | vec3 position;
20 | vec3 geometricNormal;
21 | vec3 normal;
22 |
23 | uint intersection;
24 | };
25 |
26 | bool sss_sampling(inout uint rngState, in const SSSInfo sssInfo, out SSSSample sssSample, out float pdf);
27 |
28 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/bxdf/disney.glsl:
--------------------------------------------------------------------------------
1 | #ifndef BSDF_DISNEY_GLSL
2 | #define BSDF_DISNEY_GLSL
3 |
4 | #include "diffusion/sss_diffusion_profile_burley.glsl"
5 | #include "diffusion/sss_sampling_disk.glsl"
6 |
7 | #include "bsdf/bsdf.glsl"
8 | #include "bsdf/disney_bsdf.glsl"
9 |
10 | #define SCATTERING_TYPE_BSDF 0x1
11 | #define SCATTERING_TYPE_BSSRDF 0x2
12 |
13 | // === SCATTERING TYPE ===
14 | uint disney_sampleScatteringType(inout uint rngState, in const bool sss, in const uint bounce, in const float sssFactor, out float pdf) {
15 | if (!sss || bounce > 0) {
16 | pdf = 1.0;
17 | return SCATTERING_TYPE_BSDF;
18 | }
19 | if (sssFactor > 0) {
20 | pdf = 1.0;
21 | return SCATTERING_TYPE_BSSRDF;
22 | }
23 | pdf = 1.0;
24 | return SCATTERING_TYPE_BSDF;
25 | }
26 |
27 | uint disney_sampleScatteringTypeWOSSS(inout uint rngState, in const bool sss, in const uint bounce, in const float sssFactor, out float pdf) {
28 | pdf = 1.0;
29 | return SCATTERING_TYPE_BSDF;
30 | }
31 |
32 | // === UTILITY ===
33 | float disney_schlickWeight(in const float a) {
34 | const float b = clamp(1.0 - a, 0.0, 1.0);
35 | const float bb = b * b;
36 | return bb * bb * b;
37 | }
38 |
39 | float disney_diffuseLambertWeight(in const float fv, in const float fl) {
40 | return (1.0 - 0.5 * fl) * (1.0 - 0.5 * fv);
41 | }
42 |
43 | float disney_diffuseLambertWeightSingle(in const float f) {
44 | return 1.0 - 0.5 * f;
45 | }
46 |
47 | // === BSSRDF ===
48 | vec3 disney_bssrdf_fresnel_evaluate(in const vec3 normal, in const vec3 direction) {
49 | // return vec3(1); // setting this to 1 ensures smooth transition to Lambert diffuse
50 |
51 | const float dotND = dot(normal, direction);
52 | const float schlick = disney_schlickWeight(dotND);
53 | const float lambertWeight = disney_diffuseLambertWeightSingle(schlick);
54 | return vec3(lambertWeight);
55 | }
56 |
57 | void disney_bssrdf_evaluate(in const vec3 normal, in const vec3 v, in const float distance, in const vec3 scatterDistance, in const vec3 surfaceAlbedo, out vec3 bssrdf) {
58 | const vec3 diffusionProfile = surfaceAlbedo * sss_diffusion_profile_evaluate(distance, scatterDistance);
59 |
60 | bssrdf = diffusionProfile / PI * disney_bssrdf_fresnel_evaluate(normal, v);
61 | }
62 |
63 | void disney_bssrdf_evaluate(in const vec3 normal, in const vec3 v, in const vec3 normalSample, in const vec3 l, in const float distance, in const vec3 scatterDistance, in const vec3 surfaceAlbedo, out vec3 bssrdf, out vec3 bsdf) {
64 | const vec3 diffusionProfile = surfaceAlbedo * sss_diffusion_profile_evaluate(distance, scatterDistance);
65 |
66 | bssrdf = diffusionProfile / PI * disney_bssrdf_fresnel_evaluate(normal, v);
67 | bsdf = disney_bssrdf_fresnel_evaluate(normalSample, l);
68 | }
69 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/defines.glsl:
--------------------------------------------------------------------------------
1 | #ifndef DEFINES_GLSL
2 | #define DEFINES_GLSL
3 |
4 | #define NUM_TEXTURES 8
5 | //#define GEOMETRIC_NORMAL
6 |
7 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/environment.glsl:
--------------------------------------------------------------------------------
1 | #ifndef ENVIRONMENT_GLSL
2 | #define ENVIRONMENT_GLSL
3 |
4 | vec3 environment_evaluate(in const vec3 direction) {
5 | if (g_environment_map == 0) {
6 | return g_sky_color;
7 | }
8 | const vec2 longitudeLatitude = vec2((atan(direction.x, direction.z) / PI + 1.0) * 0.5 + g_environment_map_rotation.x, asin(-direction.y) / PI + 0.5 + g_environment_map_rotation.y);
9 | return texture(textureEnvironment, longitudeLatitude).rgb;
10 | }
11 |
12 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/gbuffer.glsl:
--------------------------------------------------------------------------------
1 | #ifndef GBUFFER_GLSL
2 | #define GBUFFER_GLSL
3 |
4 | #include "../defines.glsl"
5 | #include "../utility/normal_mapping.glsl"
6 | #include "../material.glsl"
7 | #include "../trace/trace.glsl"
8 |
9 | bool pixelInfoFromGBuffer(in const vec3 origin, in const GBuffer gBuffer, out ReSTIRPixelInfo pixelInfo) {
10 | // handle error or sky hit
11 | if (gBuffer.objectDescriptorId == GBUFFER_NULL || gBuffer.triangleId == GBUFFER_NULL) {
12 | return false;
13 | }
14 |
15 | // intersection info
16 | const HitPayload payload = HitPayload(int(gBuffer.objectDescriptorId), int(gBuffer.triangleId), 0, vec2(gBuffer.barycentricsY, gBuffer.barycentricsZ), gl_HitKindFrontFacingTriangleEXT);
17 | intersectionInfo(payload, origin, pixelInfo.position, pixelInfo.geometricNormal, pixelInfo.normal, pixelInfo.material);
18 | pixelInfo.v = normalize(origin - pixelInfo.position);
19 |
20 | return true;
21 | }
22 |
23 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/passes/pass_surface.comp:
--------------------------------------------------------------------------------
1 | #version 460
2 | #extension GL_GOOGLE_include_directive: enable
3 | #extension GL_EXT_nonuniform_qualifier: enable
4 | #extension GL_EXT_scalar_block_layout: enable
5 | #extension GL_EXT_shader_explicit_arithmetic_types_int64: require
6 | #extension GL_EXT_buffer_reference2: require
7 | #extension GL_EXT_ray_query : require
8 |
9 | #include "../../defines.glsl"
10 |
11 | #include "../../utility/constants.glsl"
12 | #include "../../utility/random.glsl"
13 | #include "../../raystructs.glsl"
14 | #include "../../raycommon.glsl"
15 |
16 | layout (local_size_x_id = 0, local_size_y_id = 1, local_size_z_id = 2) in;
17 |
18 | layout (push_constant, std430) uniform PushConstants {
19 | int g_pixels_x;
20 | int g_pixels_y;
21 |
22 | float g_ray_origin_x;
23 | float g_ray_origin_y;
24 | float g_ray_origin_z;
25 | float g_ray_left_bottom_x;
26 | float g_ray_left_bottom_y;
27 | float g_ray_left_bottom_z;
28 | float g_ray_left_top_x;
29 | float g_ray_left_top_y;
30 | float g_ray_left_top_z;
31 | float g_ray_right_bottom_x;
32 | float g_ray_right_bottom_y;
33 | float g_ray_right_bottom_z;
34 | float g_ray_right_top_x;
35 | float g_ray_right_top_y;
36 | float g_ray_right_top_z;
37 |
38 | uint g_frame;
39 |
40 | uint g_rng_init;
41 | uint g_rng_init_offset;
42 | };
43 |
44 | layout (set = 0, binding = 0) uniform accelerationStructureEXT topLevelAS;
45 | layout (set = 0, binding = 1, rgba32f) uniform image2D framebuffer;
46 | layout (set = 0, binding = 2, rgba32f) uniform image2D accumulationBuffer;
47 |
48 | layout (std430, set = 0, binding = 3) uniform options_pass_surface {
49 | uint g_num_lights;
50 |
51 | uint g_normal_mapping;
52 | uint g_sss;
53 | };
54 |
55 | // SCENE
56 | layout (set = 0, binding = 10, scalar) readonly buffer buffer_object_descriptor { ObjectDescriptor g_objectDescriptors[]; };
57 | layout (set = 0, binding = 11, scalar) readonly buffer buffer_material { Material g_materials[]; };
58 | layout (set = 0, binding = 12, scalar) readonly buffer buffer_light { Light g_lights[]; };
59 |
60 | layout (buffer_reference, scalar) readonly buffer Indices { ivec3 i[]; };
61 | layout (buffer_reference, scalar) readonly buffer Vertices { Vertex v[]; };
62 |
63 | layout (set = 0, binding = 20) uniform sampler2D textures[NUM_TEXTURES];
64 | layout (set = 0, binding = 21) uniform sampler2D textureEnvironment;
65 |
66 | // G-BUFFER
67 | //layout (set = 0, binding = 30, scalar) readonly buffer buffer_g_buffers { GBuffer g_gBuffers[]; };
68 | layout (set = 0, binding = 30, rgba32f) readonly uniform image2D g_gBuffers;
69 |
70 | #include "../restirsss/restirsss_pixel_info.glsl"
71 |
72 | #include "../gbuffer.glsl"
73 | #include "../../arealight.glsl"
74 | #include "../../visibility/visibility.glsl"
75 | #include "../../bxdf/disney.glsl"
76 |
77 | vec3 generateSampleBSDFWithLightSourceSampling(inout uint rngState, in ReSTIRPixelInfo pixelInfo) {
78 | // sample light candidate
79 | int lightObjectDescriptor;
80 | int lightTriangleId;
81 | vec2 lightBarycentrics;
82 | vec3 lightPosition;
83 | vec3 lightNormalUnaligned;
84 | vec3 lightEmission;
85 | float lightPDFVAM;
86 | arealight_sample_vam(nextUInt(rngState, g_num_lights - 1), nextFloat(rngState), nextFloat(rngState), lightObjectDescriptor, lightTriangleId, lightBarycentrics, lightPosition, lightNormalUnaligned, lightEmission, lightPDFVAM);
87 |
88 | const vec3 lightToSurface = pixelInfo.position - lightPosition;
89 | const vec3 lightToSurfaceNormalized = normalize(lightToSurface);
90 | const vec3 lightNormal = dot(lightNormalUnaligned, lightToSurfaceNormalized) >= 0.0 ? lightNormalUnaligned : -lightNormalUnaligned;// align normal in correct direction
91 | const float cosAtLight = max(0, dot(lightNormal, lightToSurfaceNormalized));
92 | const float geometryTermSolidAngle = cosAtLight / dot(lightToSurface, lightToSurface);
93 | const float lightPDF = lightPDFVAM / geometryTermSolidAngle;
94 | if (lightPDF <= 0.0) {
95 | return vec3(0);
96 | }
97 |
98 | if (!visibility_shadowRay(pixelInfo.position, pixelInfo.geometricNormal, -lightToSurfaceNormalized, length(lightToSurface), lightObjectDescriptor, lightTriangleId)) {
99 | return vec3(0);
100 | }
101 |
102 | // evaluate bsdf
103 | const BSDFVertex vertex = BSDFVertex(pixelInfo.geometricNormal);
104 | const BSDFFrame frame = coordinateSystem(pixelInfo.normal);
105 | const vec3 bsdf = bsdf_disney_evaluate(vertex, frame, pixelInfo.material, pixelInfo.v, -lightToSurfaceNormalized);
106 |
107 | const float cosAtSurface = max(0, dot(pixelInfo.normal, -lightToSurfaceNormalized));
108 |
109 | return bsdf * cosAtSurface * lightEmission / lightPDF;
110 | }
111 |
112 | vec3 pathtraceSingle(inout uint rngState, in const ReSTIRPixelInfo pixelInfo) {
113 | if (g_num_lights <= 0) {
114 | return vec3(0);
115 | }
116 |
117 | // bsdf
118 | return generateSampleBSDFWithLightSourceSampling(rngState, pixelInfo);
119 | }
120 |
121 | void shade(inout uint rngState, in const ivec2 pixel) {
122 | const int pixelIndex = pixel.y * g_pixels_x + pixel.x;
123 |
124 | // load g-buffer
125 | // const GBuffer gBuffer = g_gBuffers[pixelIndex];
126 | const vec4 gBufferRaw = imageLoad(g_gBuffers, pixel);
127 | const GBuffer gBuffer = GBuffer(uint(gBufferRaw[0]), uint(gBufferRaw[1]), gBufferRaw[2], gBufferRaw[3]);
128 |
129 | // pixel info
130 | ReSTIRPixelInfo pixelInfo;
131 | if (!pixelInfoFromGBuffer(vec3(g_ray_origin_x, g_ray_origin_y, g_ray_origin_z), gBuffer, pixelInfo)) {
132 | return;
133 | }
134 |
135 | const bool pathSSS = restirsss_pixel_info_isSSS(pixelInfo);
136 | if (pathSSS) {
137 | return;
138 | }
139 |
140 | const vec3 color = pathtraceSingle(rngState, pixelInfo);
141 |
142 | // accumulate and write framebuffer
143 | const vec3 newColor = mix(imageLoad(accumulationBuffer, pixel).rgb, color, 1.0 / float(g_frame + 1));
144 | imageStore(accumulationBuffer, pixel, vec4(newColor, 1.0));
145 | imageStore(framebuffer, pixel, vec4(newColor, 1.0));
146 | }
147 |
148 | void main() {
149 | const ivec2 pixel = ivec2(gl_GlobalInvocationID.xy);
150 | if (any(greaterThanEqual(pixel, ivec2(g_pixels_x, g_pixels_y)))) {
151 | return;
152 | }
153 |
154 | // load rng
155 | uint rngState = (g_rng_init + 1) * g_pixels_x * (pixel.y + 1) + pixel.x + g_rng_init_offset;// add offset to avoid same seed as other passes (otherwise, visible artifacts possible)
156 |
157 | shade(rngState, pixel);
158 | }
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/passes/pass_tonemapper.comp:
--------------------------------------------------------------------------------
1 | #version 460
2 | #extension GL_GOOGLE_include_directive: enable
3 |
4 | layout (local_size_x_id = 0, local_size_y_id = 1, local_size_z_id = 2) in;
5 |
6 | layout (push_constant, std430) uniform PushConstants {
7 | int g_pixels_x;
8 | int g_pixels_y;
9 |
10 | uint g_tonemapper;
11 | };
12 |
13 | layout (set = 0, binding = 0, rgba32f) uniform image2D image;
14 |
15 | #define TONEMAPPER_OFF 0
16 | #define TONEMAPPER_GAMMA 1
17 |
18 | void main() {
19 | if (g_tonemapper == TONEMAPPER_OFF) {
20 | return;
21 | }
22 |
23 | const ivec2 pixel = ivec2(gl_GlobalInvocationID.xy);
24 | if (any(greaterThanEqual(pixel, ivec2(g_pixels_x, g_pixels_y)))) {
25 | return;
26 | }
27 |
28 | const vec3 colorIn = imageLoad(image, pixel).rgb;
29 |
30 | vec3 colorOut = colorIn;
31 | if (g_tonemapper == TONEMAPPER_GAMMA) {
32 | // colorOut = pow(colorIn, vec3(1.0 / 2.2));
33 | colorOut = /*colorIn == vec3(1) ? vec3(1) :*/ pow(colorIn / (colorIn + vec3(1.0)), vec3(1.0 / 2.2)); // we use reinhard tonemapping here
34 | }
35 |
36 | imageStore(image, pixel, vec4(colorOut, 1.0));
37 | }
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/restirsss/probinversetest/restirsss_target_function_test.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RESTIRSSS_TARGET_FUNCTION_TEST_GLSL
2 | #define RESTIRSSS_TARGET_FUNCTION_TEST_GLSL
3 |
4 | float restirsss_target_function_evaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample);
5 |
6 | /**
7 | * Used to combine multiple reservoirs.
8 | * Either the same as the default restir_target_function_evaluate or include additional checks, e.g. visibility check for ReSTIR DI, to stay unbiased.
9 | */
10 | float restirsss_target_function_resampleEvaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample, in const bool visibilityCheck);
11 |
12 | // PRIVATE
13 | #include "../../bxdf/disney.glsl"
14 | #include "../../visibility/visibility.glsl"
15 | #include "../../material.glsl"
16 |
17 | vec3 restirsss_target_function_unshadowedLightContribution(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample) {
18 | if (restirsss_reservoir_isNullSample(evalSample)) {
19 | return vec3(0);
20 | }
21 |
22 | const vec3 x1x2 = evalSample.samplePosition - pixelInfo.position;// visibile point -> x2
23 | const vec3 x1x2Normalized = normalize(x1x2);
24 | const vec3 x2x3 = evalSample.lightPosition - evalSample.samplePosition;// x2 -> light source
25 | const vec3 x2x3Normalized = normalize(x2x3);
26 |
27 | vec3 unshadowedLightContribution = vec3(1);
28 |
29 | const BSDFVertex vertex = BSDFVertex(pixelInfo.geometricNormal);
30 | const BSDFFrame frame = coordinateSystem(pixelInfo.normal);
31 | // bsdf at x1
32 | unshadowedLightContribution *= bsdf_disney_evaluate(vertex, frame, pixelInfo.material, pixelInfo.v, x1x2Normalized);
33 |
34 | // bsdf at x2
35 | BSDFVertex vertexAtX2;
36 | BSDFFrame frameAtX2;
37 | BSDFMaterial materialAtX2;
38 | {
39 | const ObjectDescriptor objDesc = g_objectDescriptors[evalSample.sampleObjectDescriptor];
40 | Indices indices = Indices(objDesc.indexAddress);
41 | Vertices vertices = Vertices(objDesc.vertexAddress);
42 | const Material material = g_materials[objDesc.materialId];
43 |
44 | const ivec3 ind = indices.i[evalSample.sampleTriangleId];
45 | const Vertex v0 = vertices.v[ind.x];
46 | const Vertex v1 = vertices.v[ind.y];
47 | const Vertex v2 = vertices.v[ind.z];
48 |
49 | const vec2 uv0 = vec2(v0.texCoord_u, v0.texCoord_v);
50 | const vec2 uv1 = vec2(v1.texCoord_u, v1.texCoord_v);
51 | const vec2 uv2 = vec2(v2.texCoord_u, v2.texCoord_v);
52 |
53 | const vec3 barycentrics = vec3(1.0 - evalSample.sampleBarycentrics.x - evalSample.sampleBarycentrics.y, evalSample.sampleBarycentrics.x, evalSample.sampleBarycentrics.y);
54 |
55 | // UV
56 | const vec2 uv = uv0 * barycentrics.x + uv1 * barycentrics.y + uv2 * barycentrics.z;
57 |
58 | vertexAtX2 = BSDFVertex(evalSample.sampleGeometricNormal);
59 | frameAtX2 = coordinateSystem(evalSample.sampleNormal);
60 | materialAtX2 = bsdfMaterialInit(material, uv);
61 | }
62 | unshadowedLightContribution *= bsdf_disney_evaluate(vertexAtX2, frameAtX2, materialAtX2, -x1x2Normalized, x2x3Normalized);
63 |
64 | // light
65 | const float cosAtSurface = max(0, dot(evalSample.sampleNormal, x2x3Normalized));
66 | // float cosAtLight = max(0, dot(evalSample.lightNormal, -x2x3Normalized));
67 | // float geometryTerm = cosAtSurface * cosAtLight / dot(x2x3, x2x3);
68 | unshadowedLightContribution *= evalSample.lightEmission;// * cosAtSurface /** geometryTerm*/;
69 |
70 | return unshadowedLightContribution;
71 | }
72 |
73 | vec3 restirsss_measurementContributionFunction(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample) {
74 | const vec3 color = restirsss_target_function_unshadowedLightContribution(pixelInfo, evalSample);
75 |
76 | // if (g_restir_visibility == 0) {
77 | // // no visibility pass, check if chosen light is visible from the chosen sample position
78 | // vec3 surfaceToLightNormalized = normalize(evalSample.lightPosition - evalSample.samplePosition);
79 | // color *= visibility_shadowRay(evalSample.samplePosition, evalSample.sampleGeometricNormal, surfaceToLightNormalized, evalSample.lightObjectDescriptor, evalSample.lightTriangleId);
80 | // }
81 | return color;
82 | }
83 |
84 | float calcLuminance(in const vec3 color) {
85 | return dot(color.xyz, vec3(0.299f, 0.587f, 0.114f));
86 | }
87 |
88 | // implement "base class"
89 | float restirsss_target_function_evaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample) {
90 | const vec3 unshadowedLightContribution = restirsss_target_function_unshadowedLightContribution(pixelInfo, evalSample);
91 |
92 | // float targetFunction = length(unshadowedLightContribution);// ^p(X_i)
93 | // targetFunction = (isnan(targetFunction) || isinf(targetFunction)) ? 0 : targetFunction;
94 | const float targetFunction = calcLuminance(unshadowedLightContribution);
95 |
96 | return targetFunction;
97 | }
98 |
99 | // implement "base class"
100 | float restirsss_target_function_resampleEvaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample, in const bool visibilityCheck) {
101 | if (restirsss_reservoir_isNullSample(evalSample)) {
102 | return 0;
103 | }
104 |
105 | /*if (g_restir_shift == RESTIRSSS_SHIFT_RECONNECTION || g_restir_shift == RESTIRSSS_SHIFT_SEQUENTIAL_RECONNECTION)*/ /* unoptimized but ok for this debug case */ {
106 | // the proposal function ensures that [x1,x2] is visible, so we have to ensure this for resampling as well to stay unbiased
107 | const vec3 surfaceToX2 = evalSample.samplePosition - pixelInfo.position;
108 | const vec3 surfaceToX2Normalized = normalize(surfaceToX2);
109 | if (!visibility_shadowRay(pixelInfo.position, pixelInfo.geometricNormal, surfaceToX2Normalized, length(surfaceToX2), evalSample.sampleObjectDescriptor, evalSample.sampleTriangleId)) {
110 | return 0;
111 | }
112 | }
113 | if (visibilityCheck) {
114 | const vec3 surfaceToLight = evalSample.lightPosition - evalSample.samplePosition;
115 | const vec3 surfaceToLightNormalized = normalize(surfaceToLight);
116 | if (!visibility_shadowRay(evalSample.samplePosition, evalSample.sampleGeometricNormal, surfaceToLightNormalized, length(surfaceToLight), evalSample.lightObjectDescriptor, evalSample.lightTriangleId)) {
117 | return 0;
118 | }
119 | }
120 | return restirsss_target_function_evaluate(pixelInfo, evalSample);
121 | }
122 |
123 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/restirsss/restirsss_defines.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RESTIRSSS_DEFINES_GLSL
2 | #define RESTIRSSS_DEFINES_GLSL
3 |
4 | // shifts
5 | #define RESTIRSSS_SHIFT_RECONNECTION 0
6 | #define RESTIRSSS_SHIFT_DELAYED_RECONNECTION 1
7 |
8 | #define RESTIRSSS_SHIFT_HYBRID 2
9 |
10 | #define RESTIRSSS_SHIFT_SEQUENTIAL_RECONNECTION 3
11 | #define RESTIRSSS_SHIFT_SEQUENTIAL_DELAYED_RECONNECTION 4
12 |
13 | // sequential shift performance optimization (introduces small bias): calculate intersection id for the selected sample only after the resampling pass and possibly set intersection id to an unknown state (see paper Sec. 4.3 for details)
14 | #define RESTIRSSS_RECONNECTION_INTERSECTIONID_DELAYED
15 |
16 | // sample a light source per candidate and share between all intersections (performance) or sample light source for each found intersection (less variance possible)
17 | #define RESTIRSSS_LIGHT_PER_CANDIDATE
18 |
19 | //#define RESTIRSSS_PROBINVERSETEST_L3PATH
20 |
21 | //#define RESTIRSSS_WRITE_DEBUG_IMAGES
22 |
23 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/restirsss/restirsss_pixel_info.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RESTIR_RESERVOIR_GLSL
2 | #define RESTIR_RESERVOIR_GLSL
3 |
4 | #include "../../utility/random.glsl"
5 | #include "../../bxdf/bsdf/bsdf.glsl"
6 |
7 | struct ReSTIRPixelInfo {
8 | BSDFMaterial material;
9 | vec3 v;// inverse ray direction, i.e. from surface to camera or previous bounce
10 | vec3 position;
11 | vec3 geometricNormal;
12 | vec3 normal;
13 | };
14 |
15 | bool restirsss_pixel_info_isSSS(in const ReSTIRPixelInfo pixelInfo) {
16 | return g_sss > 0 && pixelInfo.material.subsurface > 0;
17 | }
18 |
19 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/restirsss/restirsss_shift_hybrid_criterion.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RESTIRSSS_SHIFT_HYBRID_CRITERION_GLSL
2 | #define RESTIRSSS_SHIFT_HYBRID_CRITERION_GLSL
3 |
4 | // true if vertex x_2 is connectable from vertex x_1 (or y_1)
5 | bool restirsss_shift_connectable(in const vec3 x1Position, in const vec3 x1Normal, in const vec3 x2Position, in const vec3 x2Normal, in const vec3 scatterDistance) {
6 | // connectable if the angle between the normals is less than 60 degrees or the distance is greater than 2 times the maximum scatter distance
7 | return dot(x1Normal, x2Normal) <= 0.5 || distance(x1Position, x2Position) >= 2.0 * max(scatterDistance.r, max(scatterDistance.g, scatterDistance.b));
8 | }
9 |
10 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/restirsss/restirsss_spatial_kernel.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RESTIR_SPATIAL_KERNEL_GLSL
2 | #define RESTIR_SPATIAL_KERNEL_GLSL
3 |
4 | #include "../../utility/random.glsl"
5 | #include "../../utility/constants.glsl"
6 | #include "../../bxdf/diffusion/sss_diffusion_profile.glsl"
7 |
8 | ivec2 restirsss_spatial_kernel_uniform(inout uint rngState, in const float maxRadius) {
9 | const float radius = maxRadius * sqrt(nextFloat(rngState));
10 | const float angle = 2.0 * PI * nextFloat(rngState);
11 |
12 | const vec2 offset = vec2(radius * cos(angle), radius * sin(angle));
13 |
14 | return ivec2(round(offset));
15 | }
16 |
17 | float restirsss_spatial_kernel_maxSearchRadiusDiffusion(in const vec3 scatterDistance, in const vec3 position, in const ivec2 pixel, in const vec2 size) {
18 | const float maxRadius = 2.0 * max(scatterDistance.r, max(scatterDistance.g, scatterDistance.b));
19 |
20 | const mat4 g_view_to_world_space = inverse(g_world_to_view_space);
21 | // transform screen space axes into world space
22 | const vec3 worldSpaceE1 = (g_view_to_world_space * vec4(1.0, 0.0, 0.0, 0.0)).xyz;
23 | const vec3 worldSpaceE2 = (g_view_to_world_space * vec4(0.0, 1.0, 0.0, 0.0)).xyz;
24 |
25 | // maximum offset positions in world space
26 | const vec3 worldSpaceOffsetPositionRight = position + maxRadius * worldSpaceE1;
27 | const vec3 worldSpaceOffsetPositionUp = position + maxRadius * worldSpaceE2;
28 | // transform back to screen space
29 | const vec3 screenSpaceOffsetPositionRight = (g_world_to_view_space * vec4(worldSpaceOffsetPositionRight, 1.0)).xyz;
30 | const vec3 screenSpaceOffsetPositionUp = (g_world_to_view_space * vec4(worldSpaceOffsetPositionUp, 1.0)).xyz;
31 | // project to clip space
32 | const vec3 clipSpaceOffsetPositionRight = (g_view_to_clip_space * vec4(screenSpaceOffsetPositionRight, 1.0)).xyz; // [-1,1]
33 | const vec3 clipSpaceOffsetPositionUp = (g_view_to_clip_space * vec4(screenSpaceOffsetPositionUp, 1.0)).xyz; // [-1,1]
34 | const vec2 clipSpaceProjectedOffsetPositionRight = clipSpaceOffsetPositionRight.xy / clipSpaceOffsetPositionRight.z;
35 | const vec2 clipSpaceProjectedOffsetPositionUp = clipSpaceOffsetPositionUp.xy / clipSpaceOffsetPositionUp.z;
36 | // convert to NDC
37 | const vec2 ndcOffsetPositionRight = clipSpaceProjectedOffsetPositionRight * 0.5 + 0.5; // [0,1]
38 | const vec2 ndcOffsetPositionUp = clipSpaceProjectedOffsetPositionUp * 0.5 + 0.5; // [0,1]
39 |
40 | const vec2 pixelRight = round(ndcOffsetPositionRight * vec2(size));
41 | const vec2 pixelUp = round(ndcOffsetPositionUp * vec2(size));
42 |
43 | const float searchRadiusRight = distance(vec2(pixel), pixelRight);
44 | const float searchRadiusUp = distance(vec2(pixel), pixelUp);
45 |
46 | return clamp(max(searchRadiusRight, searchRadiusUp), 5, 30);
47 | }
48 |
49 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/main/restirsss/restirsss_target_function.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RESTIRSSS_TARGET_FUNCTION_GLSL
2 | #define RESTIRSSS_TARGET_FUNCTION_GLSL
3 |
4 | float restirsss_target_function_evaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample);
5 |
6 | /**
7 | * Used to combine multiple reservoirs.
8 | * Either the same as the default restir_target_function_evaluate or include additional checks, e.g. visibility check for ReSTIR DI, to stay unbiased.
9 | */
10 | float restirsss_target_function_resampleEvaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample, in const bool visibilityCheck);
11 |
12 | // PRIVATE
13 | #include "../../bxdf/disney.glsl"
14 | #include "../../visibility/visibility.glsl"
15 |
16 | vec3 restirsss_target_function_unshadowedLightContribution(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample) {
17 | if (restirsss_reservoir_isNullSample(evalSample)) {
18 | return vec3(0);
19 | }
20 |
21 | vec3 unshadowedLightContribution = vec3(1);
22 |
23 | if (restirsss_pixel_info_isSSS(pixelInfo)) {
24 | // bssrdf
25 | const float actualDistance = distance(pixelInfo.position, evalSample.samplePosition);
26 |
27 | const vec3 surfaceToLight = evalSample.lightPosition - evalSample.samplePosition;
28 | const vec3 surfaceToLightNormalized = normalize(surfaceToLight);
29 |
30 | vec3 bssrdf;
31 | vec3 bsdf;
32 | disney_bssrdf_evaluate(pixelInfo.normal, pixelInfo.v, evalSample.sampleNormal, surfaceToLightNormalized, actualDistance, pixelInfo.material.scatterDistance, pixelInfo.material.baseColor, bssrdf, bsdf);
33 |
34 | const float cosAtSurface = max(0, dot(evalSample.sampleNormal, surfaceToLightNormalized));
35 |
36 | unshadowedLightContribution *= bssrdf * bsdf * cosAtSurface * evalSample.lightEmission;
37 | } else {
38 | // bsdf
39 | const vec3 surfaceToLight = evalSample.lightPosition - pixelInfo.position;
40 | const vec3 surfaceToLightNormalized = normalize(surfaceToLight);
41 |
42 | const BSDFVertex vertex = BSDFVertex(pixelInfo.geometricNormal);
43 | const BSDFFrame frame = coordinateSystem(pixelInfo.normal);
44 | const vec3 bsdf = bsdf_disney_evaluate(vertex, frame, pixelInfo.material, pixelInfo.v, surfaceToLightNormalized);
45 |
46 | const float cosAtSurface = max(0, dot(pixelInfo.normal, surfaceToLightNormalized));
47 |
48 | unshadowedLightContribution *= bsdf * cosAtSurface * evalSample.lightEmission;
49 | }
50 |
51 | // unshadowedLightContribution *= visibility_shadowRay(evalSample.samplePosition, evalSample.sampleGeometricNormal, surfaceToLightNormalized, evalSample.lightObjectDescriptor, evalSample.lightTriangleId);
52 |
53 | return unshadowedLightContribution;
54 | }
55 |
56 | vec3 restirsss_measurementContributionFunction(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample) {
57 | const vec3 color = restirsss_target_function_unshadowedLightContribution(pixelInfo, evalSample);
58 |
59 | // if (g_restir_visibility == 0) {
60 | // // no visibility pass, check if chosen light is visible from the chosen sample position
61 | // vec3 surfacePosition;
62 | // vec3 surfaceGeometricNormal;
63 | // vec3 surfaceToLightNormalized;
64 | // if (restirsss_pixel_info_isSSS(pixelInfo)) {
65 | // surfacePosition = evalSample.samplePosition;
66 | // surfaceGeometricNormal = evalSample.sampleGeometricNormal;
67 | // surfaceToLightNormalized = normalize(evalSample.lightPosition - evalSample.samplePosition);
68 | // } else {
69 | // surfacePosition = pixelInfo.position;
70 | // surfaceGeometricNormal = pixelInfo.geometricNormal;
71 | // surfaceToLightNormalized = normalize(evalSample.lightPosition - pixelInfo.position);
72 | // }
73 | // color *= visibility_shadowRay(surfacePosition, surfaceGeometricNormal, surfaceToLightNormalized, evalSample.lightObjectDescriptor, evalSample.lightTriangleId);
74 | // }
75 | return color;
76 | }
77 |
78 | float calcLuminance(in const vec3 color) {
79 | return dot(color.xyz, vec3(0.299f, 0.587f, 0.114f));
80 | }
81 |
82 | // implement "base class"
83 | float restirsss_target_function_evaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample) {
84 | const vec3 unshadowedLightContribution = restirsss_target_function_unshadowedLightContribution(pixelInfo, evalSample);
85 |
86 | // float targetFunction = length(unshadowedLightContribution);// ^p(X_i)
87 | // targetFunction = (isnan(targetFunction) || isinf(targetFunction)) ? 0 : targetFunction;
88 | const float targetFunction = calcLuminance(unshadowedLightContribution);
89 |
90 | return targetFunction;
91 | }
92 |
93 | // implement "base class"
94 | float restirsss_target_function_resampleEvaluate(in const ReSTIRPixelInfo pixelInfo, in const ReSTIRSSSSample evalSample, in const bool visibilityCheck) {
95 | if (visibilityCheck) {
96 | vec3 surfacePosition;
97 | vec3 surfaceGeometricNormal;
98 | vec3 surfaceToLightNormalized;
99 | float tMax = 0;
100 | if (restirsss_pixel_info_isSSS(pixelInfo)) {
101 | surfacePosition = evalSample.samplePosition;
102 | surfaceGeometricNormal = evalSample.sampleGeometricNormal;
103 | const vec3 d = evalSample.lightPosition - evalSample.samplePosition;
104 | surfaceToLightNormalized = normalize(d);
105 | tMax = length(d);
106 | } else {
107 | surfacePosition = pixelInfo.position;
108 | surfaceGeometricNormal = pixelInfo.geometricNormal;
109 | const vec3 d = evalSample.lightPosition - pixelInfo.position;
110 | surfaceToLightNormalized = normalize(d);
111 | tMax = length(d);
112 | }
113 | if (!visibility_shadowRay(surfacePosition, surfaceGeometricNormal, surfaceToLightNormalized, tMax, evalSample.lightObjectDescriptor, evalSample.lightTriangleId)) {
114 | return 0;
115 | }
116 | }
117 | return restirsss_target_function_evaluate(pixelInfo, evalSample);
118 | }
119 |
120 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/material.glsl:
--------------------------------------------------------------------------------
1 | #ifndef MATERIAL_GLSL
2 | #define MATERIAL_GLSL
3 |
4 | vec3 material_getAlbedo(in const Material material, in const vec2 uv) {
5 | return material.baseColorTexture >= 0 ? texture(textures[material.baseColorTexture], uv).rgb : material.baseColorFactor.rgb;
6 | }
7 |
8 | float material_getMetallic(in const Material material, in const vec2 uv) {
9 | return material.metallicRoughnessTexture >= 0 ? texture(textures[material.metallicRoughnessTexture], uv).b : material.metallicFactor;
10 | }
11 |
12 | float material_getRoughness(in const Material material, in const vec2 uv) {
13 | return material.metallicRoughnessTexture >= 0 ? texture(textures[material.metallicRoughnessTexture], uv).g : material.roughnessFactor;
14 | }
15 |
16 | bool material_isLightSource(in const Material material) {
17 | return any(greaterThan(material.emission, vec3(0)));
18 | }
19 |
20 | bool material_isTranslucent(in const Material material) {
21 | return material.subsurface > 0.0;
22 | }
23 |
24 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/raycommon.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RAYCOMMON_GLSL
2 | #define RAYCOMMON_GLSL
3 |
4 | struct HitPayload {
5 | int objectDescriptorId; // gl_InstanceCustomIndexEXT
6 | int triangleId; // gl_PrimitiveID
7 | float t; // distance
8 | vec2 barycentrics; // encodes vec3(1.0 - barycentrics.x - barycentrics.y, barycentrics.x, barycentrics.y)
9 | uint face; // gl_HitKindFrontFacingTriangleEXT or gl_HitKindBackFacingTriangleEXT
10 | };
11 |
12 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/raystructs.glsl:
--------------------------------------------------------------------------------
1 | #ifndef RAYSTRUCTS_GLSL
2 | #define RAYSTRUCTS_GLSL
3 |
4 | struct ObjectDescriptor {
5 | uint64_t vertexAddress;
6 | uint64_t indexAddress;
7 | uint materialId;
8 |
9 | mat4 objectToWorld;
10 | mat4 objectToWorldNormal; // == transpose(inverse(objectToWorld))
11 | };
12 |
13 | struct Vertex {
14 | float position_x;
15 | float position_y;
16 | float position_z;
17 | float normal_x;
18 | float normal_y;
19 | float normal_z;
20 | float tangent_x;
21 | float tangent_y;
22 | float tangent_z;
23 | float tangent_w;
24 | float texCoord_u;
25 | float texCoord_v;
26 | };
27 |
28 | struct Material {
29 | vec3 baseColorFactor;
30 | int baseColorTexture;
31 | float metallicFactor;
32 | float roughnessFactor;
33 | int metallicRoughnessTexture;
34 |
35 | int normalTexture;
36 |
37 | vec3 emission;
38 |
39 | float subsurface;
40 | vec3 meanFreePath;
41 | };
42 |
43 | struct Light {
44 | uint type;
45 |
46 | uint objectDescriptorId;
47 | uint triangleId;
48 |
49 | vec3 position;
50 | vec3 emission;
51 | };
52 |
53 | #define GBUFFER_NULL 0xFFFFFFFFu
54 |
55 | struct GBuffer {
56 | uint objectDescriptorId; // gl_InstanceCustomIndexEXT
57 | uint triangleId; // gl_PrimitiveID
58 | float barycentricsY; // encodes vec3(1.0 - barycentricsY - barycentricsZ, barycentricsY, barycentricsZ)
59 | float barycentricsZ; // encodes vec3(1.0 - barycentricsY - barycentricsZ, barycentricsY, barycentricsZ)
60 | };
61 |
62 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/trace/trace_rayquery.glsl:
--------------------------------------------------------------------------------
1 | #ifndef TRACE_RAYQUERY_GLSL
2 | #define TRACE_RAYQUERY_GLSL
3 |
4 | #include "../raycommon.glsl"
5 | #include "trace.glsl"
6 |
7 | bool trace(in const vec3 origin, in const vec3 direction, in const float tMin, in const float tMax, out HitPayload hitPayload) {
8 | rayQueryEXT rayQuery;
9 | rayQueryInitializeEXT(rayQuery,
10 | topLevelAS,
11 | gl_RayFlagsOpaqueEXT,
12 | 0xFF,
13 | origin,
14 | tMin + 0.001,
15 | direction,
16 | tMax);
17 |
18 | while(rayQueryProceedEXT(rayQuery)){
19 | }
20 |
21 | if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT) {
22 | return false;
23 | }
24 |
25 | hitPayload.objectDescriptorId = rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true);
26 | hitPayload.triangleId = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
27 | hitPayload.t = rayQueryGetIntersectionTEXT(rayQuery, true);
28 | hitPayload.barycentrics = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true);
29 | hitPayload.face = rayQueryGetIntersectionFrontFaceEXT(rayQuery, true) ? gl_HitKindFrontFacingTriangleEXT : gl_HitKindBackFacingTriangleEXT;
30 | return true;
31 | }
32 |
33 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/utility/colormap.glsl:
--------------------------------------------------------------------------------
1 | #ifndef UTILITY_COLORMAP_GLSL
2 | #define UTILITY_COLORMAP_GLSL
3 |
4 | // https://www.shadertoy.com/view/WlfXRN
5 |
6 | vec3 colormap_viridis(in const float t) {
7 | const vec3 c0 = vec3(0.2777273272234177, 0.005407344544966578, 0.3340998053353061);
8 | const vec3 c1 = vec3(0.1050930431085774, 1.404613529898575, 1.384590162594685);
9 | const vec3 c2 = vec3(-0.3308618287255563, 0.214847559468213, 0.09509516302823659);
10 | const vec3 c3 = vec3(-4.634230498983486, -5.799100973351585, -19.33244095627987);
11 | const vec3 c4 = vec3(6.228269936347081, 14.17993336680509, 56.69055260068105);
12 | const vec3 c5 = vec3(4.776384997670288, -13.74514537774601, -65.35303263337234);
13 | const vec3 c6 = vec3(-5.435455855934631, 4.645852612178535, 26.3124352495832);
14 |
15 | return c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6)))));
16 | }
17 |
18 | vec3 colormap_plasma(in const float t) {
19 | const vec3 c0 = vec3(0.05873234392399702, 0.02333670892565664, 0.5433401826748754);
20 | const vec3 c1 = vec3(2.176514634195958, 0.2383834171260182, 0.7539604599784036);
21 | const vec3 c2 = vec3(-2.689460476458034, -7.455851135738909, 3.110799939717086);
22 | const vec3 c3 = vec3(6.130348345893603, 42.3461881477227, -28.51885465332158);
23 | const vec3 c4 = vec3(-11.10743619062271, -82.66631109428045, 60.13984767418263);
24 | const vec3 c5 = vec3(10.02306557647065, 71.41361770095349, -54.07218655560067);
25 | const vec3 c6 = vec3(-3.658713842777788, -22.93153465461149, 18.19190778539828);
26 |
27 | return c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6)))));
28 | }
29 |
30 | vec3 colormap_magma(in const float t) {
31 | const vec3 c0 = vec3(-0.002136485053939582, -0.000749655052795221, -0.005386127855323933);
32 | const vec3 c1 = vec3(0.2516605407371642, 0.6775232436837668, 2.494026599312351);
33 | const vec3 c2 = vec3(8.353717279216625, -3.577719514958484, 0.3144679030132573);
34 | const vec3 c3 = vec3(-27.66873308576866, 14.26473078096533, -13.64921318813922);
35 | const vec3 c4 = vec3(52.17613981234068, -27.94360607168351, 12.94416944238394);
36 | const vec3 c5 = vec3(-50.76852536473588, 29.04658282127291, 4.23415299384598);
37 | const vec3 c6 = vec3(18.65570506591883, -11.48977351997711, -5.601961508734096);
38 |
39 | return c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6)))));
40 | }
41 |
42 | vec3 colormap_inferno(in const float t) {
43 | const vec3 c0 = vec3(0.0002189403691192265, 0.001651004631001012, -0.01948089843709184);
44 | const vec3 c1 = vec3(0.1065134194856116, 0.5639564367884091, 3.932712388889277);
45 | const vec3 c2 = vec3(11.60249308247187, -3.972853965665698, -15.9423941062914);
46 | const vec3 c3 = vec3(-41.70399613139459, 17.43639888205313, 44.35414519872813);
47 | const vec3 c4 = vec3(77.162935699427, -33.40235894210092, -81.80730925738993);
48 | const vec3 c5 = vec3(-71.31942824499214, 32.62606426397723, 73.20951985803202);
49 | const vec3 c6 = vec3(25.13112622477341, -12.24266895238567, -23.07032500287172);
50 |
51 | return c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6)))));
52 | }
53 |
54 | vec3 colormap_inverse_tonemapper_gamma(in vec3 color) {
55 | color = pow(color, vec3(2.2));
56 | return color / (1 - color);
57 | }
58 |
59 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/utility/constants.glsl:
--------------------------------------------------------------------------------
1 | #ifndef UTILITY_CONSTANTS_GLSL
2 | #define UTILITY_CONSTANTS_GLSL
3 |
4 | #define PI 3.14159265359
5 | #define TWO_PI 6.28318530718
6 | #define INV_PI 0.31830988618
7 |
8 | #define INFINITY 1000000000.0
9 |
10 | #define INVALID_UINT_VALUE 0xFFFFFFFFu
11 | #define ERROR_UINT_VALUE 0xFFFFFFFEu
12 |
13 | #define RENDER_MODE_POSITION 0
14 | #define RENDER_MODE_NORMAL 1
15 | #define RENDER_MODE_GEOMETRIC_NORMAL 2
16 | #define RENDER_MODE_UV 3
17 | #define RENDER_MODE_BASE_COLOR 4
18 | #define RENDER_MODE_NORMAL_MAP 5
19 | #define RENDER_MODE_TANGENT 6
20 | #define RENDER_MODE_BI_TANGENT 7
21 | #define RENDER_MODE_OBJECT_DESCRIPTOR 8
22 | #define RENDER_MODE_TRIANGLE 9
23 | #define RENDER_MODE_MOTION 10
24 | #define RENDER_MODE_FACE 11
25 | #define RENDER_MODE_COLORMAP 12
26 | #define RENDER_MODE_DISK_BASED_SAMPLING_INTERSECTIONS 13
27 | #define RENDER_MODE_RESTIRSSS_SEARCH_RADIUS 14
28 |
29 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/utility/normal_mapping.glsl:
--------------------------------------------------------------------------------
1 | #ifndef UTILITY_NORMAL_MAPPING_GLSL
2 | #define UTILITY_NORMAL_MAPPING_GLSL
3 |
4 | mat3 tangentSpaceMatrix(in const vec3 tangent, in const vec3 bitangent, in const vec3 normal) {
5 | return transpose(inverse(mat3(tangent, bitangent, normal)));
6 | // return mat3(tangent, bitangent, normal);
7 | }
8 |
9 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/utility/random.glsl:
--------------------------------------------------------------------------------
1 | #ifndef UTILITY_RANDOM_GLSL
2 | #define UTILITY_RANDOM_GLSL
3 |
4 | #include "constants.glsl"
5 |
6 | /**
7 | * Random number in [0,1].
8 | * https://www.shadertoy.com/view/XlGcRh
9 | */
10 | float pcg(inout uint state) {
11 | state = state * 747796405u + 2891336453u;
12 | uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
13 | word = (word >> 22u) ^ word;
14 | return word / 4294967295.0;
15 | }
16 |
17 | // https://github.com/nvpro-samples/vk_mini_path_tracer/blob/main/vk_mini_path_tracer/shaders/raytrace.comp.glsl#L25
18 | // Steps the RNG and returns a floating-point value between 0 and 1 inclusive.
19 | float nextFloat(inout uint rngState) {
20 | // Condensed version of pcg_output_rxs_m_xs_32_32, with simple conversion to floating-point [0,1].
21 | rngState = rngState * 747796405 + 1;
22 | uint word = ((rngState >> ((rngState >> 28) + 4)) ^ rngState) * 277803737;
23 | word = (word >> 22) ^ word;
24 | return float(word) / 4294967295.0f;
25 | }
26 |
27 | // [0, maxUInt]
28 | // maxUInt inclusive!
29 | uint nextUInt(inout uint rngState, uint maxUInt) {
30 | rngState = rngState * 747796405 + 1;
31 | uint word = ((rngState >> ((rngState >> 28) + 4)) ^ rngState) * 277803737;
32 | word = (word >> 22) ^ word;
33 | return word % (maxUInt + 1);
34 | }
35 |
36 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/resources/shaders/visibility/visibility.glsl:
--------------------------------------------------------------------------------
1 | #ifndef VISIBILITY_GLSL
2 | #define VISIBILITY_GLSL
3 |
4 | bool visibility_shadowRay(in const vec3 positionWorld, in const vec3 geometricNormalWorld, in const vec3 lightDirection, in const float tMax, in const uint objectDescriptor, in const uint triangleId) {
5 | rayQueryEXT rayQuery;
6 | rayQueryInitializeEXT(rayQuery,
7 | topLevelAS,
8 | // gl_RayFlagsOpaqueEXT,
9 | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT,
10 | 0xFF,
11 | positionWorld,
12 | 0.001,
13 | lightDirection,
14 | tMax - 0.001);
15 |
16 | // while(rayQueryProceedEXT(rayQuery)){
17 | // }
18 | //
19 | // bool hit = (rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT);
20 | // if (!hit || rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) == objectDescriptor && rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true) == triangleId) {
21 | // return 1.0;
22 | // }
23 | // return 0.0;
24 | rayQueryProceedEXT(rayQuery);
25 | return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT;
26 | }
27 |
28 | #endif
--------------------------------------------------------------------------------
/ReSTIRSSS/src/bin/main.cpp:
--------------------------------------------------------------------------------
1 | #define STB_IMAGE_IMPLEMENTATION
2 | #define STB_IMAGE_WRITE_IMPLEMENTATION
3 | #define TINYOBJLOADER_IMPLEMENTATION
4 |
5 | #include "raven/core/RavenVkDynamicLoader.h"
6 |
7 | #include "raven/core/Application.h"
8 | #include "raven/core/HeadlessApplication.h"
9 | #include "raven/util/Paths.h"
10 |
11 | #include "restirsss/ReSTIRSSS.h"
12 | #include "restirsss/ReSTIRSSSEvaluation.h"
13 | #include "restirsss/ReSTIRSSSEvaluationTiming.h"
14 | #include "restirsss/ReSTIRSSSVideo.h"
15 |
16 | #include "argparse/include/argparse/argparse.hpp"
17 |
18 | int main(const int argc, char *argv[]) {
19 | #ifdef RESOURCE_DIRECTORY_PATH
20 | raven::Paths::m_resourceDirectoryPath = RESOURCE_DIRECTORY_PATH;
21 | #endif
22 |
23 | argparse::ArgumentParser program("restirsss");
24 | program.add_argument("scene")
25 | .help("name of the scene (in resources/scenes/.xml)")
26 | .required();
27 | program.add_argument("--preset")
28 | .nargs(1)
29 | .help("pathtracing, hybrid, sequential")
30 | .choices("pathtracing", "hybrid", "sequential")
31 | .default_value("hybrid");
32 | program.add_argument("--evaluate")
33 | .nargs(1)
34 | .help("renderings, timing, video")
35 | .choices("renderings", "timing", "video");
36 |
37 | try {
38 | program.parse_args(argc, argv);
39 | } catch (const std::exception &err) {
40 | std::cerr << err.what() << std::endl;
41 | std::cerr << program;
42 | return 1;
43 | }
44 |
45 | if (program.present("--evaluate")) {
46 | if (program.get("--evaluate") == "renderings") {
47 | return raven::ReSTIRSSSEvaluation().run();
48 | }
49 | if (program.get("--evaluate") == "timing") {
50 | return raven::ReSTIRSSSEvaluationTiming().run();
51 | }
52 | if (program.get("--evaluate") == "video") {
53 | return raven::ReSTIRSSSVideo().run();
54 | }
55 | }
56 |
57 | auto rendererSettings = raven::ReSTIRSSS::ReSTIRSSSSettings{.m_scene = raven::Rayscenes::UNDEFINED};
58 | const auto renderer = std::make_shared(rendererSettings, program.get("scene"), program.get("--preset"));
59 | std::string appName = "ReSTIR Subsurface Scattering for Real-Time Path Tracing";
60 |
61 | #ifdef WIN32
62 | auto settings = raven::Application::ApplicationSettings{.m_msaaSamples = vk::SampleCountFlagBits::e1,
63 | .m_deviceExtensions = {VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME,
64 | VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME}};
65 | #else
66 | auto settings = raven::Application::ApplicationSettings{.m_msaaSamples = vk::SampleCountFlagBits::e1,
67 | .m_deviceExtensions = {VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, VK_KHR_RAY_QUERY_EXTENSION_NAME,
68 | VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME}};
69 | #endif
70 | raven::Application app(appName, settings, renderer, raven::Queues::QueueFamilies::COMPUTE_FAMILY | raven::Queues::QueueFamilies::GRAPHICS_FAMILY | raven::Queues::TRANSFER_FAMILY);
71 | app.setVSync(true);
72 |
73 | try {
74 | app.run();
75 | } catch (const std::exception &e) {
76 | std::cerr << e.what() << std::endl;
77 | return EXIT_FAILURE;
78 | }
79 |
80 | return EXIT_SUCCESS;
81 | }
--------------------------------------------------------------------------------
/VkRaven/.clang-format:
--------------------------------------------------------------------------------
1 | # Generated from CLion C/C++ Code Style settings
2 | BasedOnStyle: LLVM
3 | AccessModifierOffset: -4
4 | AlignAfterOpenBracket: Align
5 | AlignConsecutiveAssignments: None
6 | AlignOperands: Align
7 | AllowAllArgumentsOnNextLine: false
8 | AllowAllConstructorInitializersOnNextLine: false
9 | AllowAllParametersOfDeclarationOnNextLine: false
10 | AllowShortBlocksOnASingleLine: Never
11 | AllowShortCaseLabelsOnASingleLine: false
12 | AllowShortFunctionsOnASingleLine: All
13 | AllowShortIfStatementsOnASingleLine: Never
14 | AllowShortLambdasOnASingleLine: All
15 | AllowShortLoopsOnASingleLine: true
16 | AlwaysBreakAfterReturnType: None
17 | AlwaysBreakTemplateDeclarations: Yes
18 | BreakBeforeBraces: Custom
19 | BraceWrapping:
20 | AfterCaseLabel: false
21 | AfterClass: false
22 | AfterControlStatement: Never
23 | AfterEnum: false
24 | AfterFunction: false
25 | AfterNamespace: false
26 | AfterUnion: false
27 | BeforeCatch: false
28 | BeforeElse: false
29 | IndentBraces: false
30 | SplitEmptyFunction: false
31 | SplitEmptyRecord: true
32 | BreakBeforeBinaryOperators: None
33 | BreakBeforeTernaryOperators: true
34 | BreakConstructorInitializers: BeforeColon
35 | BreakInheritanceList: BeforeColon
36 | ColumnLimit: 0
37 | CompactNamespaces: false
38 | ContinuationIndentWidth: 8
39 | IndentCaseLabels: true
40 | IndentPPDirectives: None
41 | IndentWidth: 4
42 | KeepEmptyLinesAtTheStartOfBlocks: true
43 | MaxEmptyLinesToKeep: 2
44 | NamespaceIndentation: All
45 | ObjCSpaceAfterProperty: false
46 | ObjCSpaceBeforeProtocolList: true
47 | PointerAlignment: Right
48 | ReflowComments: false
49 | SpaceAfterCStyleCast: true
50 | SpaceAfterLogicalNot: false
51 | SpaceAfterTemplateKeyword: false
52 | SpaceBeforeAssignmentOperators: true
53 | SpaceBeforeCpp11BracedList: false
54 | SpaceBeforeCtorInitializerColon: true
55 | SpaceBeforeInheritanceColon: true
56 | SpaceBeforeParens: ControlStatements
57 | SpaceBeforeRangeBasedForLoopColon: false
58 | SpaceInEmptyParentheses: false
59 | SpacesBeforeTrailingComments: 1
60 | SpacesInAngles: false
61 | SpacesInCStyleCastParentheses: false
62 | SpacesInContainerLiterals: false
63 | SpacesInParentheses: false
64 | SpacesInSquareBrackets: false
65 | TabWidth: 4
66 | UseTab: Never
67 |
--------------------------------------------------------------------------------
/VkRaven/.clang-tidy:
--------------------------------------------------------------------------------
1 | # Generated from CLion Inspection settings
2 | ---
3 | Checks: '-*,
4 | bugprone-argument-comment,
5 | bugprone-assert-side-effect,
6 | bugprone-bad-signal-to-kill-thread,
7 | bugprone-branch-clone,
8 | bugprone-copy-constructor-init,
9 | bugprone-dangling-handle,
10 | bugprone-dynamic-static-initializers,
11 | bugprone-fold-init-type,
12 | bugprone-forward-declaration-namespace,
13 | bugprone-forwarding-reference-overload,
14 | bugprone-inaccurate-erase,
15 | bugprone-incorrect-roundings,
16 | bugprone-integer-division,
17 | bugprone-lambda-function-name,
18 | bugprone-macro-parentheses,
19 | bugprone-macro-repeated-side-effects,
20 | bugprone-misplaced-operator-in-strlen-in-alloc,
21 | bugprone-misplaced-pointer-arithmetic-in-alloc,
22 | bugprone-misplaced-widening-cast,
23 | bugprone-move-forwarding-reference,
24 | bugprone-multiple-statement-macro,
25 | bugprone-no-escape,
26 | bugprone-not-null-terminated-result,
27 | bugprone-parent-virtual-call,
28 | bugprone-posix-return,
29 | bugprone-reserved-identifier,
30 | bugprone-sizeof-container,
31 | bugprone-sizeof-expression,
32 | bugprone-spuriously-wake-up-functions,
33 | bugprone-string-constructor,
34 | bugprone-string-integer-assignment,
35 | bugprone-string-literal-with-embedded-nul,
36 | bugprone-suspicious-enum-usage,
37 | bugprone-suspicious-include,
38 | bugprone-suspicious-memset-usage,
39 | bugprone-suspicious-missing-comma,
40 | bugprone-suspicious-semicolon,
41 | bugprone-suspicious-string-compare,
42 | bugprone-suspicious-memory-comparison,
43 | bugprone-suspicious-realloc-usage,
44 | bugprone-swapped-arguments,
45 | bugprone-terminating-continue,
46 | bugprone-throw-keyword-missing,
47 | bugprone-too-small-loop-variable,
48 | bugprone-undefined-memory-manipulation,
49 | bugprone-undelegated-constructor,
50 | bugprone-unhandled-self-assignment,
51 | bugprone-unused-raii,
52 | bugprone-unused-return-value,
53 | bugprone-use-after-move,
54 | bugprone-virtual-near-miss,
55 | cert-dcl21-cpp,
56 | cert-dcl58-cpp,
57 | cert-err34-c,
58 | cert-err52-cpp,
59 | cert-err60-cpp,
60 | cert-flp30-c,
61 | cert-msc50-cpp,
62 | cert-msc51-cpp,
63 | cert-str34-c,
64 | cppcoreguidelines-interfaces-global-init,
65 | cppcoreguidelines-narrowing-conversions,
66 | cppcoreguidelines-pro-type-member-init,
67 | cppcoreguidelines-pro-type-static-cast-downcast,
68 | cppcoreguidelines-slicing,
69 | google-default-arguments,
70 | google-explicit-constructor,
71 | google-runtime-operator,
72 | hicpp-exception-baseclass,
73 | hicpp-multiway-paths-covered,
74 | misc-misplaced-const,
75 | misc-new-delete-overloads,
76 | misc-no-recursion,
77 | misc-non-copyable-objects,
78 | misc-throw-by-value-catch-by-reference,
79 | misc-unconventional-assign-operator,
80 | misc-uniqueptr-reset-release,
81 | modernize-avoid-bind,
82 | modernize-concat-nested-namespaces,
83 | modernize-deprecated-headers,
84 | modernize-deprecated-ios-base-aliases,
85 | modernize-loop-convert,
86 | modernize-make-shared,
87 | modernize-make-unique,
88 | modernize-pass-by-value,
89 | modernize-raw-string-literal,
90 | modernize-redundant-void-arg,
91 | modernize-replace-auto-ptr,
92 | modernize-replace-disallow-copy-and-assign-macro,
93 | modernize-replace-random-shuffle,
94 | modernize-return-braced-init-list,
95 | modernize-shrink-to-fit,
96 | modernize-unary-static-assert,
97 | modernize-use-auto,
98 | modernize-use-bool-literals,
99 | modernize-use-emplace,
100 | modernize-use-equals-default,
101 | modernize-use-equals-delete,
102 | modernize-use-nodiscard,
103 | modernize-use-noexcept,
104 | modernize-use-nullptr,
105 | modernize-use-override,
106 | modernize-use-transparent-functors,
107 | modernize-use-uncaught-exceptions,
108 | mpi-buffer-deref,
109 | mpi-type-mismatch,
110 | openmp-use-default-none,
111 | performance-faster-string-find,
112 | performance-for-range-copy,
113 | performance-implicit-conversion-in-loop,
114 | performance-inefficient-algorithm,
115 | performance-inefficient-string-concatenation,
116 | performance-inefficient-vector-operation,
117 | performance-move-const-arg,
118 | performance-move-constructor-init,
119 | performance-no-automatic-move,
120 | performance-noexcept-move-constructor,
121 | performance-trivially-destructible,
122 | performance-type-promotion-in-math-fn,
123 | performance-unnecessary-copy-initialization,
124 | performance-unnecessary-value-param,
125 | portability-simd-intrinsics,
126 | readability-avoid-const-params-in-decls,
127 | readability-const-return-type,
128 | readability-container-size-empty,
129 | readability-convert-member-functions-to-static,
130 | readability-delete-null-pointer,
131 | readability-deleted-default,
132 | readability-inconsistent-declaration-parameter-name,
133 | readability-make-member-function-const,
134 | readability-misleading-indentation,
135 | readability-misplaced-array-index,
136 | readability-non-const-parameter,
137 | readability-redundant-control-flow,
138 | readability-redundant-declaration,
139 | readability-redundant-function-ptr-dereference,
140 | readability-redundant-smartptr-get,
141 | readability-redundant-string-cstr,
142 | readability-redundant-string-init,
143 | readability-simplify-subscript-expr,
144 | readability-static-accessed-through-instance,
145 | readability-static-definition-in-anonymous-namespace,
146 | readability-string-compare,
147 | readability-uniqueptr-delete-release,
148 | readability-use-anyofallof'
--------------------------------------------------------------------------------
/VkRaven/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.18)
2 | project(raven VERSION 0.1.0 DESCRIPTION "VkRaven - Vulkan Render and Visualization Engine" LANGUAGES C CXX)
3 |
4 | set(CMAKE_CXX_STANDARD 20)
5 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
6 |
7 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
8 |
9 | find_package(Vulkan REQUIRED)
10 |
11 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/find/" PARENT_SCOPE)
12 | include(cmake/setup.cmake)
13 |
14 | if (MSVC)
15 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:mainCRTStartup" PARENT_SCOPE)
16 | endif ()
17 |
18 | add_subdirectory(lib)
19 | add_subdirectory(raven)
20 |
--------------------------------------------------------------------------------
/VkRaven/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Mirco Werner
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 |
--------------------------------------------------------------------------------
/VkRaven/README.md:
--------------------------------------------------------------------------------
1 | # VkRaven
2 | **V**ul**k**an **R**ender **a**nd **V**isualization **En**gine
3 |
--------------------------------------------------------------------------------
/VkRaven/cmake/find/FindOptix.cmake:
--------------------------------------------------------------------------------
1 | # taken from https://github.com/nvpro-samples/nvpro_core/blob/master/cmake/find/FindOptix7.cmake, adjusted
2 |
3 | # Try to find OptiX project dll/so and headers
4 | #
5 |
6 | # outputs
7 | unset(OPTIX_DLL CACHE)
8 | unset(OPTIX_LIB CACHE)
9 | unset(OPTIX_FOUND CACHE)
10 | unset(OPTIX_INCLUDE_DIR CACHE)
11 |
12 | # OPTIX_LOCATION can be setup to search versions somewhere else
13 |
14 | macro(folder_list result curdir substring)
15 | FILE(GLOB children RELATIVE ${curdir} ${curdir}/*${substring}*)
16 | SET(dirlist "")
17 | foreach (child ${children})
18 | IF (IS_DIRECTORY ${curdir}/${child})
19 | LIST(APPEND dirlist ${child})
20 | ENDIF ()
21 | ENDFOREACH ()
22 | SET(${result} ${dirlist})
23 | ENDMACRO()
24 |
25 | macro(_find_version_path targetVersion targetPath rootName searchList)
26 | unset(targetVersion)
27 | unset(targetPath)
28 | SET(bestver "0.0.0")
29 | SET(bestpath "")
30 | foreach (basedir ${searchList})
31 | folder_list(dirList ${basedir} ${rootName})
32 | foreach (checkdir ${dirList})
33 | string(REGEX MATCH "${rootName}(.*)([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)$" result "${checkdir}")
34 | if ("${result}" STREQUAL "${checkdir}")
35 | # found a path with versioning
36 | SET(ver "${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${CMAKE_MATCH_4}")
37 | if (ver VERSION_GREATER bestver)
38 | SET(bestver ${ver})
39 | SET(bestmajorver ${CMAKE_MATCH_2})
40 | SET(bestminorver ${CMAKE_MATCH_3})
41 | SET(bestpath "${basedir}/${checkdir}")
42 | endif ()
43 | endif ()
44 | endforeach ()
45 | endforeach ()
46 | if ("${bestver}" STREQUAL "0.0.0")
47 | foreach (basedir ${searchList})
48 | if (EXISTS "${basedir}/optix/include/optix.h")
49 | SET(bestver "unknown")
50 | SET(bestpath "${basedir}/optix")
51 | endif ()
52 | endforeach ()
53 | endif ()
54 | SET(${targetVersion} "${bestver}")
55 | SET(${targetPath} "${bestpath}")
56 | endmacro()
57 |
58 | macro(_find_files targetVar incDir dllName dllName64 folder)
59 | unset(fileList)
60 | if (ARCH STREQUAL "x86")
61 | file(GLOB fileList "${${incDir}}/../${folder}${dllName}")
62 | list(LENGTH fileList NUMLIST)
63 | if (NUMLIST EQUAL 0)
64 | file(GLOB fileList "${${incDir}}/${folder}${dllName}")
65 | endif ()
66 | else ()
67 | file(GLOB fileList "${${incDir}}/../${folder}${dllName64}")
68 | list(LENGTH fileList NUMLIST)
69 | if (NUMLIST EQUAL 0)
70 | file(GLOB fileList "${${incDir}}/${folder}${dllName64}")
71 | endif ()
72 | endif ()
73 | list(LENGTH fileList NUMLIST)
74 | if (NUMLIST EQUAL 0)
75 | message(STATUS "MISSING: unable to find ${targetVar} files (${folder}${dllName}, ${folder}${dllName64})")
76 | set(${targetVar} "NOTFOUND")
77 | endif ()
78 | list(APPEND ${targetVar} ${fileList})
79 |
80 | # message ( "File list: ${${targetVar}}" ) #-- debugging
81 | endmacro()
82 |
83 | if (DEFINED OPTIX_LOCATION OR DEFINED ENV{OPTIX_LOCATION})
84 | Message(STATUS "OptiX: Using OPTIX_LOCATION (${OPTIX_LOCATION})...")
85 | if (NOT DEFINED OPTIX_LOCATION)
86 | if (DEFINED ENV{OPTIX_LOCATION})
87 | set(OPTIX_LOCATION $ENV{OPTIX_LOCATION})
88 | endif ()
89 | endif ()
90 | # Locate by version failed. Handle user override for OPTIX_LOCATION.
91 | string(REGEX MATCH ".*([0-9]+).([0-9]+).([0-9]+)(.*)$" result "${OPTIX_LOCATION}")
92 | if ("${result}" STREQUAL "${OPTIX_LOCATION}")
93 | SET(bestver "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
94 | SET(bestmajorver ${CMAKE_MATCH_1})
95 | SET(bestminorver ${CMAKE_MATCH_2})
96 | Message(STATUS "OptiX: Version ${bestver}")
97 | SET(OPTIX_VERSION "${bestver}")
98 | else ()
99 | Message(WARNING "Could NOT extract the version from OPTIX folder : ${result}")
100 | endif ()
101 | find_path(OPTIX_INCLUDE_DIR optix.h ${OPTIX_LOCATION}/include)
102 | if (OPTIX_INCLUDE_DIR)
103 | set(OPTIX_ROOT_DIR ${OPTIX_INCLUDE_DIR}/../)
104 | endif ()
105 | endif ()
106 | if (NOT DEFINED OPTIX_ROOT_DIR)
107 | # Locate OptiX by version
108 | set(SEARCH_PATHS
109 | $ENV{OPTIX_LOCATION}
110 | ${OPTIX_LOCATION}
111 | ${PROJECT_SOURCE_DIR}/../LocalPackages/Optix
112 | ${PROJECT_SOURCE_DIR}/../../LocalPackages/Optix
113 | ${PROJECT_SOURCE_DIR}/../../../LocalPackages/Optix
114 | C:/ProgramData/NVIDIA\ Corporation
115 | /opt
116 | )
117 |
118 | _find_version_path(OPTIX_VERSION OPTIX_ROOT_DIR "OptiX" "${SEARCH_PATHS}")
119 |
120 | message(STATUS "OptiX version: ${OPTIX_VERSION}")
121 | endif ()
122 |
123 | if (OPTIX_ROOT_DIR)
124 | #-------- Locate HEADERS
125 | _find_files(OPTIX_HEADERS OPTIX_ROOT_DIR "optix.h" "optix.h" "include/")
126 |
127 | include(FindPackageHandleStandardArgs)
128 |
129 | SET(OPTIX_INCLUDE_DIR "${OPTIX_ROOT_DIR}/include" CACHE PATH "path")
130 | add_definitions("-DOPTIX_PATH=R\"(${OPTIX_ROOT_DIR})\"")
131 | # add_definitions("-DOPTIX_VERSION=\"${OPTIX_VERSION}\"")
132 |
133 | else (OPTIX_ROOT_DIR)
134 |
135 | message(WARNING "
136 | OPTIX not found.
137 | The OPTIX folder you would specify with OPTIX_LOCATION should contain:
138 | - lib[64] folder: containing the Optix[64_]*.dll or *.so
139 | - include folder: containing the include files"
140 | )
141 | endif (OPTIX_ROOT_DIR)
142 |
143 | find_package_handle_standard_args(Optix DEFAULT_MSG OPTIX_ROOT_DIR)
144 | mark_as_advanced(OPTIX_FOUND)
--------------------------------------------------------------------------------
/VkRaven/cmake/setup.cmake:
--------------------------------------------------------------------------------
1 | macro(_add_package_Optix)
2 | find_package(Optix)
3 | if (OPTIX_FOUND)
4 | Message(STATUS "OptiX: Enabled")
5 | add_definitions(-DOPTIX_SUPPORT)
6 | include_directories(${OPTIX_INCLUDE_DIR})
7 | LIST(APPEND PACKAGE_SOURCE_FILES ${OPTIX_HEADERS})
8 | source_group(OPTIX FILES ${OPTIX_HEADERS})
9 | set(USING_OPTIX "YES")
10 | else ()
11 | Message(STATUS "OptiX: Disabled")
12 | endif ()
13 | endmacro()
--------------------------------------------------------------------------------
/VkRaven/lib/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ### GLFW ###
2 | set(GLFW_BUILD_DOCS OFF CACHE BOOL "GLFW lib only")
3 | set(GLFW_INSTALL OFF CACHE BOOL "GLFW lib only")
4 | add_subdirectory(glfw)
5 |
6 | ### glm ###
7 | add_subdirectory(glm)
8 |
9 | ### imgui ###
10 | if (WIN32)
11 | add_library(imgui STATIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imconfig.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_demo.cpp
12 | ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_draw.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_glfw.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_glfw.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_vulkan.cpp
13 | ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_vulkan.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_internal.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_tables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_widgets.cpp
14 | ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imstb_rectpack.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imstb_textedit.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imstb_truetype.h
15 | main.cpp)
16 | else ()
17 | add_library(imgui SHARED ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imconfig.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_demo.cpp
18 | ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_draw.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_glfw.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_glfw.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_vulkan.cpp
19 | ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/imgui_impl_vulkan.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_internal.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_tables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_widgets.cpp
20 | ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imstb_rectpack.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imstb_textedit.h ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imstb_truetype.h
21 | main.cpp)
22 | endif ()
23 | set_target_properties(imgui PROPERTIES LINKER_LANGUAGE CXX)
24 | target_include_directories(imgui
25 | PUBLIC
26 | $
27 | ${CMAKE_CURRENT_SOURCE_DIR}/imgui
28 | )
29 | target_link_libraries(imgui Vulkan::Vulkan glfw)
30 | install(TARGETS imgui LIBRARY DESTINATION lib)
31 |
32 | ### stb ###
33 | add_library(stb SHARED ${CMAKE_CURRENT_SOURCE_DIR}/stb/stb_image.h ${CMAKE_CURRENT_SOURCE_DIR}/stb/stb_image_write.h main.cpp)
34 | set_target_properties(stb PROPERTIES LINKER_LANGUAGE CXX)
35 | install(TARGETS stb LIBRARY DESTINATION lib)
36 |
37 | ### tinyobjloader ###
38 | add_library(tinyobjloader SHARED ${CMAKE_CURRENT_SOURCE_DIR}/tinyobjloader/tiny_obj_loader.h main.cpp)
39 | set_target_properties(tinyobjloader PROPERTIES LINKER_LANGUAGE CXX)
40 | install(TARGETS tinyobjloader LIBRARY DESTINATION lib)
41 |
42 | ### tinygltf ###
43 | add_library(tinygltf SHARED ${CMAKE_CURRENT_SOURCE_DIR}/tinygltf/tiny_gltf.h ${CMAKE_CURRENT_SOURCE_DIR}/tinygltf/tiny_gltf.cc)
44 | set_target_properties(tinygltf PROPERTIES LINKER_LANGUAGE CXX)
45 | install(TARGETS tinygltf LIBRARY DESTINATION lib)
46 |
47 | ### SPIRV-Reflect ###
48 | add_library(spirv-reflect SHARED ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Reflect/spirv_reflect.h ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Reflect/spirv_reflect.cpp)
49 | set_target_properties(spirv-reflect PROPERTIES LINKER_LANGUAGE CXX)
50 | install(TARGETS spirv-reflect LIBRARY DESTINATION lib)
51 |
52 | ### pugixml ###
53 | add_library(pugixml SHARED ${CMAKE_CURRENT_SOURCE_DIR}/pugixml/src/pugiconfig.hpp ${CMAKE_CURRENT_SOURCE_DIR}/pugixml/src/pugixml.hpp ${CMAKE_CURRENT_SOURCE_DIR}/pugixml/src/pugixml.cpp)
54 | set_target_properties(pugixml PROPERTIES LINKER_LANGUAGE CXX)
55 | install(TARGETS pugixml LIBRARY DESTINATION lib)
56 |
57 | ### argparse ###
58 | add_library(argparse SHARED ${CMAKE_CURRENT_SOURCE_DIR}/argparse/include/argparse/argparse.hpp main.cpp)
59 | set_target_properties(argparse PROPERTIES LINKER_LANGUAGE CXX)
60 | install(TARGETS argparse LIBRARY DESTINATION lib)
--------------------------------------------------------------------------------
/VkRaven/lib/main.cpp:
--------------------------------------------------------------------------------
1 | int main() {
2 | return 0;
3 | }
--------------------------------------------------------------------------------
/VkRaven/raven/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.18)
2 | project(ravencore VERSION 0.1.0 DESCRIPTION "VkRaven Core - Vulkan Render and Visualization Engine Core" LANGUAGES CXX)
3 |
4 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
5 |
6 | find_package(Vulkan REQUIRED)
7 |
8 | set(RAVENCORE_HEADERS
9 | include/raven/RavenInclude.h
10 | include/raven/core/Renderer.h
11 | include/raven/core/Application.h include/raven/core/HeadlessApplication.h include/raven/core/TimingHeadlessApplication.h include/raven/core/VideoHeadlessApplication.h
12 | include/raven/core/GPUContext.h include/raven/core/Queues.h include/raven/core/Shader.h
13 | include/raven/core/RavenVkDynamicLoader.h
14 | include/raven/util/AABB.h include/raven/util/Paths.h include/raven/core/Buffer.h include/raven/core/Image.h include/raven/core/Texture.h include/raven/passes/ImGuiPass.h include/raven/core/Uniform.h
15 | include/raven/core/SwapChain.h include/raven/util/Camera.h include/raven/core/VkDebugUtils.h include/raven/core/AccelerationStructure.h
16 | include/raven/scene/RavenScene.h include/raven/scene/RavenSceneNode.h include/raven/scene/RavenSceneObject.h include/raven/scene/RavenMaterial.h include/raven/scene/RavenLight.h include/raven/scene/RavenTexture.h include/raven/scene/ISceneLoader.h include/raven/scene/loader/GLTFLoader.h
17 | include/raven/rendergraph/RenderGraph.h
18 | include/raven/rendergraph/RenderGraphPass.h
19 | include/raven/rendergraph/RenderGraphResource.h
20 | include/raven/util/sampling/AliasTable.h
21 | include/raven/passes/PassShader.h include/raven/passes/PassShaderCompute.h include/raven/passes/PassShaderRayTracing.h
22 | include/raven/passes/Pass.h include/raven/passes/PassCompute.h
23 | include/raven/util/Trajectory.h
24 | include/raven/util/ImagePFM.h
25 | include/raven/util/animation/BSpline.h
26 | include/raven/RavenInclude.h
27 | )
28 |
29 | set(RAVENCORE_SOURCES
30 | src/raven/core/Application.cpp src/raven/core/HeadlessApplication.cpp src/raven/core/TimingHeadlessApplication.cpp src/raven/core/VideoHeadlessApplication.cpp
31 | src/raven/core/GPUContext.cpp src/raven/core/Queues.cpp src/raven/core/RavenVkDynamicLoader.cpp
32 | )
33 |
34 | add_library(ravencore SHARED ${RAVENCORE_HEADERS} ${RAVENCORE_SOURCES})
35 | add_library(ravencore::ravencore ALIAS ravencore)
36 |
37 | set_target_properties(ravencore PROPERTIES LINKER_LANGUAGE CXX)
38 |
39 | target_compile_definitions(ravencore PRIVATE -DVULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1)
40 | target_compile_definitions(ravencore PRIVATE -DVULKAN_HPP_STORAGE_SHARED_EXPORT=1)
41 | target_compile_definitions(ravencore PRIVATE -DVULKAN_HPP_STORAGE_SHARED=1)
42 |
43 | target_include_directories(ravencore
44 | PUBLIC
45 | $
46 | $
47 | $
48 | $
49 | $
50 | PRIVATE
51 | ${CMAKE_CURRENT_SOURCE_DIR}/src
52 | )
53 |
54 | target_link_libraries(ravencore Vulkan::Vulkan glfw imgui stb)
55 |
56 | install(TARGETS ravencore LIBRARY DESTINATION raven)
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/RavenInclude.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifdef WIN32
4 | #include
5 | #define VK_USE_PLATFORM_WIN32_KHR
6 | #include
7 | #include
8 | #include
9 | #else
10 | #include
11 | #endif
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/GPUContext.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "raven/RavenInclude.h"
12 |
13 | //#include "raven/core/VkExtensions.h"
14 |
15 | #include "Queues.h"
16 | #include "VkDebugUtils.h"
17 | #include "raven/util/Camera.h"
18 |
19 | namespace raven {
20 | class GPUContext {
21 | public:
22 | explicit GPUContext(uint32_t requiredQueueFamilies);
23 |
24 | virtual void init();
25 |
26 | virtual void shutdown();
27 |
28 | vk::PhysicalDevice m_physicalDevice = VK_NULL_HANDLE; // will be destroyed implicitly when instance is destroyed
29 |
30 | vk::Device m_device{};
31 | std::shared_ptr m_queues;
32 |
33 | uint32_t m_activeIndex = 0;
34 |
35 | [[nodiscard]] uint32_t getMultiBufferedCount() const {
36 | return MAX_FRAMES_IN_FLIGHT;
37 | }
38 |
39 | [[nodiscard]] uint32_t getActiveIndex() const {
40 | return m_activeIndex;
41 | }
42 |
43 | vk::CommandPool m_graphicsCommandPool{};
44 | vk::CommandPool m_computeCommandPool{};
45 | vk::CommandPool m_transferCommandPool{};
46 |
47 | void executeCommands(const std::function &recordCommands, Queues::Queue queue = Queues::Queue::TRANSFER, uint32_t awaitBeforeExecutionCount = 0, vk::Semaphore *awaitBeforeExecution = nullptr, vk::PipelineStageFlags *awaitBeforeExecutionStages = nullptr) {
48 | vk::CommandBuffer commandBuffer;
49 | switch (queue) {
50 | case Queues::GRAPHICS:
51 | commandBuffer = m_graphicsCommandBuffers[m_activeIndex];
52 | break;
53 | case Queues::COMPUTE:
54 | commandBuffer = m_computeCommandBuffers[m_activeIndex];
55 | break;
56 | case Queues::TRANSFER:
57 | commandBuffer = m_transferCommandBuffers[m_activeIndex];
58 | break;
59 | default:
60 | throw std::runtime_error("Execute command does not support other queues!");
61 | }
62 |
63 | vk::CommandBufferBeginInfo beginInfo{};
64 | beginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
65 |
66 | if (commandBuffer.begin(&beginInfo) != vk::Result::eSuccess) {
67 | throw std::runtime_error("Failed to begin command buffer!");
68 | }
69 |
70 | recordCommands(commandBuffer);
71 |
72 | vkEndCommandBuffer(commandBuffer);
73 |
74 | vk::SubmitInfo submitInfo{};
75 | submitInfo.commandBufferCount = 1;
76 | submitInfo.pCommandBuffers = &commandBuffer;
77 |
78 | submitInfo.waitSemaphoreCount = awaitBeforeExecutionCount;
79 | submitInfo.pWaitSemaphores = awaitBeforeExecution;
80 | submitInfo.pWaitDstStageMask = awaitBeforeExecutionStages;
81 |
82 | if (m_queues->getQueue(queue).submit(1, &submitInfo, VK_NULL_HANDLE) != vk::Result::eSuccess) {
83 | throw std::runtime_error("Failed to submit command buffer to queue!");
84 | }
85 | m_queues->getQueue(queue).waitIdle();
86 | }
87 |
88 | [[nodiscard]] VkDebugUtils *getDebug() const {
89 | return m_debug.get();
90 | }
91 |
92 | virtual Camera *getCamera() {
93 | return nullptr;
94 | }
95 |
96 | PFN_vkVoidFunction getDeviceFunction(const char *name) const {
97 | return m_device.getProcAddr(name);
98 | }
99 |
100 | [[nodiscard]] float getDeviceLimitsTimestampPeriod() const {
101 | return m_deviceLimitsTimestampPeriod;
102 | }
103 |
104 | virtual void resizeWindow(int width, int height) {}
105 |
106 | float incrementAndReturnDeltaTime() {
107 | const auto currentTime = std::chrono::high_resolution_clock::now();
108 | const float time = std::chrono::duration(currentTime - m_time).count();
109 | m_time = currentTime;
110 | return time;
111 | }
112 |
113 | protected:
114 | vk::Instance m_instance{};
115 | vk::DebugUtilsMessengerEXT m_debugMessenger{};
116 |
117 | std::vector m_graphicsCommandBuffers;
118 | std::vector m_computeCommandBuffers;
119 | std::vector m_transferCommandBuffers;
120 |
121 | virtual void getDeviceExtensions(std::vector &extensions) const;
122 | virtual void getInstanceExtensions(std::vector &extensions) const;
123 |
124 | void incrementActiveIndex() {
125 | m_activeIndex = (m_activeIndex + 1) % MAX_FRAMES_IN_FLIGHT;
126 | }
127 |
128 | std::chrono::time_point m_time = std::chrono::high_resolution_clock::now();
129 |
130 | private:
131 | #ifdef NDEBUG
132 | const bool enableValidationLayers = true;
133 | #else
134 | const bool enableValidationLayers = true;
135 | #endif
136 | const std::vector validationLayers = {
137 | "VK_LAYER_KHRONOS_validation"};
138 |
139 | void initVulkan();
140 | void releaseVulkan();
141 |
142 | void createInstance();
143 | bool checkValidationLayerSupport();
144 | static void populateDebugMessengerCreateInfo(vk::DebugUtilsMessengerCreateInfoEXT &createInfo);
145 | static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData);
146 | void setupDebugMessenger();
147 | static vk::Result createDebugUtilsMessengerEXT(vk::Instance instance, const vk::DebugUtilsMessengerCreateInfoEXT *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::DebugUtilsMessengerEXT *pDebugMessenger);
148 | static void destroyDebugUtilsMessengerEXT(vk::Instance instance, vk::DebugUtilsMessengerEXT debugMessenger, const vk::AllocationCallbacks *pAllocator);
149 | void pickPhysicalDevice();
150 | void queryPhysicalDeviceProperties();
151 |
152 | void createLogicalDevice();
153 |
154 | void createCommandPool();
155 | void createCommandBuffers();
156 |
157 | std::shared_ptr m_debug;
158 |
159 | const uint32_t MAX_FRAMES_IN_FLIGHT = 1; // TODO
160 |
161 | float m_deviceLimitsTimestampPeriod = 0.f;
162 | };
163 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/HeadlessApplication.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "Buffer.h"
6 | #include "GPUContext.h"
7 | #include "Renderer.h"
8 | #include "Texture.h"
9 | #include "raven/util/Camera.h"
10 |
11 | namespace raven {
12 | class HeadlessApplication : public GPUContext {
13 | public:
14 | struct ApplicationSettings {
15 | vk::SampleCountFlagBits m_msaaSamples = vk::SampleCountFlagBits::e1;
16 |
17 | /*
18 | * RayTracing
19 | * VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME
20 | */
21 | std::vector m_deviceExtensions = {};
22 |
23 | int32_t m_width = 1920;
24 | int32_t m_height = 1080;
25 |
26 | uint32_t m_rendererExecutions = 1;
27 |
28 | std::string m_directory;
29 | std::string m_name;
30 |
31 | std::function m_executeAfterInit = [](GPUContext *) {};
32 |
33 | bool m_png;
34 | };
35 |
36 | HeadlessApplication(std::string &appName, ApplicationSettings appSettings, std::shared_ptr renderer, uint32_t requiredQueueFamilies);
37 |
38 | virtual void run();
39 |
40 | Camera *getCamera() override {
41 | return m_camera.get();
42 | }
43 |
44 | protected:
45 | virtual void getDeviceExtensions(std::vector &extensions) const override;
46 |
47 | std::string m_appName;
48 | ApplicationSettings m_applicationSettings;
49 |
50 | std::shared_ptr m_camera;
51 |
52 | std::shared_ptr m_renderer;
53 |
54 | Image *m_image = nullptr;
55 |
56 | void init() override;
57 |
58 | virtual void loop();
59 | virtual void finish();
60 | virtual void render();
61 |
62 | void shutdown() override;
63 |
64 | void assertMSAASamplesSupported(vk::SampleCountFlagBits msaaSamples);
65 |
66 | uint32_t m_queueFamilyIndex{};
67 |
68 | uint32_t findQueueFamilyIndex() {
69 | Queues::QueueFamilyIndices queueFamilyIndices = m_queues->findQueueFamilies(m_physicalDevice);
70 | return queueFamilyIndices.graphicsFamily.value();
71 | }
72 |
73 | [[nodiscard]] std::string prefix() const {
74 | return "[" + m_applicationSettings.m_name + "] ";
75 | }
76 | };
77 | } // namespace raven
78 |
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/Queues.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "raven/RavenInclude.h"
10 |
11 | namespace raven {
12 | class Queues {
13 | public:
14 | enum QueueFamilies {
15 | GRAPHICS_FAMILY = 0x00000001,
16 | COMPUTE_FAMILY = 0x00000002,
17 | TRANSFER_FAMILY = 0x00000004,
18 | };
19 |
20 | enum Queue {
21 | GRAPHICS = 0,
22 | COMPUTE = 1,
23 | TRANSFER = 2,
24 | };
25 |
26 | explicit Queues(uint32_t requiredQueueFamilies) : m_requiredQueueFamilies(requiredQueueFamilies){};
27 |
28 | struct QueueFamilyIndices {
29 | std::optional graphicsFamily;
30 | std::optional computeFamily;
31 | std::optional transferFamily;
32 |
33 | [[nodiscard]] bool isComplete(uint32_t requiredQueueFamilies) const {
34 | uint32_t graphics = GRAPHICS_FAMILY & requiredQueueFamilies;
35 | uint32_t compute = COMPUTE_FAMILY & requiredQueueFamilies;
36 | uint32_t transfer = TRANSFER_FAMILY & requiredQueueFamilies;
37 | return (!graphics || graphicsFamily.has_value()) && (!compute || computeFamily.has_value()) && (!transfer || transferFamily.has_value());
38 | }
39 |
40 | void generateQueueCreateInfos(std::vector *queueCreateInfos, float *queuePriorities) {
41 | std::set uniqueQueueFamilies;
42 | if (graphicsFamily.has_value()) {
43 | uniqueQueueFamilies.emplace(graphicsFamily.value());
44 | }
45 | if (computeFamily.has_value()) {
46 | uniqueQueueFamilies.emplace(computeFamily.value());
47 | }
48 | if (transferFamily.has_value()) {
49 | uniqueQueueFamilies.emplace(transferFamily.value());
50 | }
51 |
52 | for (uint32_t queueFamily: uniqueQueueFamilies) { // queue create infos for all required queues
53 | vk::DeviceQueueCreateInfo queueCreateInfo{};
54 | queueCreateInfo.queueFamilyIndex = queueFamily;
55 | queueCreateInfo.queueCount = 1;
56 | queueCreateInfo.pQueuePriorities = queuePriorities;
57 | queueCreateInfos->push_back(queueCreateInfo);
58 | }
59 | }
60 |
61 | static bool requireGraphicsFamily(uint32_t requiredQueueFamilies) {
62 | return GRAPHICS_FAMILY & requiredQueueFamilies;
63 | }
64 | static bool requireComputeFamily(uint32_t requiredQueueFamilies) {
65 | return COMPUTE_FAMILY & requiredQueueFamilies;
66 | }
67 | static bool requireTransferFamily(uint32_t requiredQueueFamilies) {
68 | return TRANSFER_FAMILY & requiredQueueFamilies;
69 | }
70 | };
71 |
72 | [[nodiscard]] QueueFamilyIndices findQueueFamilies(vk::PhysicalDevice physicalDevice) const;
73 |
74 | void generateQueueCreateInfos(vk::PhysicalDevice physicalDevice, std::vector *queueCreateInfos, float *queuePriorities) const;
75 |
76 | void createQueues(vk::Device device, vk::PhysicalDevice physicalDevice);
77 |
78 | vk::Queue getQueue(Queue queue);
79 |
80 | private:
81 | uint32_t m_requiredQueueFamilies;
82 | std::array m_queues{}; // destroyed implicitly with the device
83 |
84 | [[nodiscard]] bool isFamilyRequired(QueueFamilies queueFamily) const;
85 |
86 | static uint32_t getQueueFamilyIndex(std::vector &queueFamilyProperties, vk::QueueFlags queueFlags) {
87 | // dedicated compute queue
88 | // if (queueFlags & vk::QueueFlagBits::eCompute) {
89 | // for (uint32_t i = 0; i < queueFamilyProperties.size(); i++) {
90 | // if ((queueFamilyProperties[i].queueFlags & queueFlags) && !(queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics)) {
91 | // return i;
92 | // }
93 | // }
94 | // }
95 | //
96 | // // dedicated transfer queue
97 | // if (queueFlags & vk::QueueFlagBits::eTransfer) {
98 | // for (uint32_t i = 0; i < queueFamilyProperties.size(); i++) {
99 | // if ((queueFamilyProperties[i].queueFlags & queueFlags) && !(queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics) && !(queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eCompute)) {
100 | // return i;
101 | // }
102 | // }
103 | // }
104 |
105 | // graphics queue or fallback
106 | for (uint32_t i = 0; i < queueFamilyProperties.size(); i++) {
107 | if (queueFamilyProperties[i].queueFlags & queueFlags) {
108 | return i;
109 | }
110 | }
111 |
112 | throw std::runtime_error("Cannot find matching queue family index!");
113 | }
114 | };
115 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/RavenVkDynamicLoader.h:
--------------------------------------------------------------------------------
1 | #pragma once
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/Renderer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "GPUContext.h"
4 | #include "raven/util/Camera.h"
5 | #include "raven/core/Image.h"
6 |
7 | namespace raven {
8 | class Renderer {
9 | public:
10 | struct RendererResult {
11 | Image *m_image = nullptr;
12 |
13 | vk::Semaphore m_waitTimelineSemaphore{};
14 | uint64_t m_waitTimelineSemaphoreValue = 0U;
15 | };
16 |
17 | virtual ~Renderer() = default;
18 |
19 | virtual void initResources(GPUContext *gpuContext) = 0; // called only once on startup
20 | virtual void initShaderResources(GPUContext *gpuContext) = 0; // called whenever the shaders are reloaded
21 | virtual void initSwapchainResources(GPUContext *gpuContext, vk::Extent2D extent) = 0; // called whenever the swapchain size changes
22 |
23 | virtual void recordImGui(GPUContext *gpuContext, Camera *camera) = 0;
24 |
25 | virtual void update(GPUContext *gpuContext, Camera *camera, float deltaTime) = 0;
26 | virtual void render(GPUContext *gpuContext, Camera *camera, uint32_t activeIndex, RendererResult *rendererResult) = 0;
27 |
28 | virtual void releaseResources() = 0;
29 | virtual void releaseShaderResources() = 0;
30 | virtual void releaseSwapchainResources() = 0;
31 | };
32 | } // namespace raven
33 |
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/TimingHeadlessApplication.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "Buffer.h"
6 | #include "GPUContext.h"
7 | #include "HeadlessApplication.h"
8 | #include "Renderer.h"
9 | #include "Texture.h"
10 | #include "raven/util/Camera.h"
11 |
12 | namespace raven {
13 | class TimingHeadlessApplication : public HeadlessApplication {
14 | public:
15 | struct TimingApplicationSettings {
16 | uint32_t m_timingExecutions = 1;
17 |
18 | uint32_t m_startupExecutions = 64;
19 |
20 | std::function m_executeAfterStartupExecutions = [](GPUContext *) {};
21 | std::function m_executeQueryTiming = [](std::ofstream &) {};
22 | std::function m_executeEachFrame = [](uint32_t) {};
23 | };
24 |
25 | TimingHeadlessApplication(std::string &appName, ApplicationSettings appSettings, TimingApplicationSettings timingAppSettings, std::shared_ptr renderer, uint32_t requiredQueueFamilies);
26 |
27 | void run() override;
28 |
29 | protected:
30 | TimingApplicationSettings m_timingApplicationSettings;
31 |
32 | void loop() override;
33 | void finish() override;
34 | void render() override;
35 |
36 | private:
37 | uint32_t m_timingExecution = 0;
38 | };
39 | } // namespace raven
40 |
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/Uniform.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Buffer.h"
4 | #include "GPUContext.h"
5 | #include "SPIRV-Reflect/spirv_reflect.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | namespace raven {
12 | class Uniform {
13 | public:
14 | explicit Uniform(GPUContext *gpuContext) : m_gpuContext(gpuContext) {
15 | }
16 |
17 | static std::shared_ptr reflect(GPUContext *gpuContext, const SpvReflectDescriptorBinding &binding) {
18 | assert(static_cast(binding.descriptor_type) == vk::DescriptorType::eUniformBuffer);
19 |
20 | auto uniform = std::make_shared(gpuContext);
21 |
22 | uniform->m_name = binding.type_description->type_name;
23 | uniform->m_set = binding.set;
24 | uniform->m_binding = binding.binding;
25 |
26 | uniform->m_variables.resize(binding.type_description->member_count);
27 |
28 | for (uint32_t i = 0; i < binding.type_description->member_count; i++) {
29 | // const auto &member = binding.type_description->members[i];
30 | const auto &memberBlock = binding.block.members[i];
31 |
32 | auto &variable = uniform->m_variables[i];
33 |
34 | variable.name = memberBlock.name;
35 | // variable.type = member.type_flags;
36 | variable.bytes = memberBlock.size;
37 | variable.bytesPadded = memberBlock.padded_size;
38 |
39 | variable.data.resize(variable.bytes);
40 |
41 | // uint32_t bytes;
42 | // switch (member.type_flags) {
43 | // case SPV_REFLECT_TYPE_FLAG_INT:
44 | // case SPV_REFLECT_TYPE_FLAG_FLOAT:
45 | // bytes = member.traits.numeric.scalar.width / 8;
46 | // break;
47 | // case SPV_REFLECT_TYPE_FLAG_VECTOR | SPV_REFLECT_TYPE_FLAG_INT:
48 | // case SPV_REFLECT_TYPE_FLAG_VECTOR | SPV_REFLECT_TYPE_FLAG_FLOAT:
49 | // bytes = member.traits.numeric.vector.component_count * member.traits.numeric.scalar.width / 8;
50 | // break;
51 | // case SPV_REFLECT_TYPE_FLAG_MATRIX | SPV_REFLECT_TYPE_FLAG_VECTOR | SPV_REFLECT_TYPE_FLAG_INT:
52 | // case SPV_REFLECT_TYPE_FLAG_MATRIX | SPV_REFLECT_TYPE_FLAG_VECTOR | SPV_REFLECT_TYPE_FLAG_FLOAT:
53 | // bytes = member.traits.numeric.matrix.column_count * member.traits.numeric.matrix.row_count * member.traits.numeric.scalar.width / 8;
54 | // break;
55 | // default:
56 | // throw std::runtime_error("Unsupported uniform type!");
57 | // }
58 | // variable.bytes = bytes;
59 |
60 | // std::cout << variable.name << std::endl;
61 | // std::cout << bytes << " " << memberBlock.size << " " << memberBlock.padded_size << std::endl;
62 | // assert(bytes == memberBlock.size);
63 | }
64 |
65 | return uniform;
66 | }
67 |
68 | void create() {
69 | m_buffers.resize(m_gpuContext->getMultiBufferedCount());
70 | for (size_t i = 0; i < m_gpuContext->getMultiBufferedCount(); i++) {
71 | std::stringstream ss;
72 | ss << "[Uniform]_" << m_name << "[" << i << "]";
73 | auto settings = Buffer::BufferSettings{.m_sizeBytes = getBytes(), .m_bufferUsages = vk::BufferUsageFlagBits::eUniformBuffer, .m_memoryProperties = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, .m_name=ss.str()};
74 | m_buffers[i] = std::make_shared(m_gpuContext, settings);
75 | }
76 | }
77 |
78 | void release() {
79 | for (size_t i = 0; i < m_gpuContext->getMultiBufferedCount(); i++) {
80 | m_buffers[i]->release();
81 | }
82 | }
83 |
84 | [[nodiscard]] uint32_t getSet() const {
85 | return m_set;
86 | }
87 |
88 | [[nodiscard]] uint32_t getBinding() const {
89 | return m_binding;
90 | }
91 |
92 | [[nodiscard]] uint32_t getBytes() const {
93 | uint32_t bytes = 0;
94 | for (const auto &variable: m_variables) {
95 | bytes += variable.bytesPadded;
96 | }
97 | return bytes;
98 | }
99 |
100 | void generateBufferInfo(vk::DescriptorBufferInfo *bufferInfo, uint32_t index) {
101 | bufferInfo->buffer = m_buffers[index]->getBuffer();
102 | bufferInfo->offset = 0;
103 | bufferInfo->range = m_buffers[index]->getSizeBytes();
104 | }
105 |
106 | void upload(uint32_t index) {
107 | uint32_t bytes = getBytes();
108 | std::vector data(bytes, 0);
109 |
110 | uint32_t pointer = 0;
111 | for (uint32_t i = 0; i < m_variables.size(); i++) {
112 | const auto &variable = m_variables[i];
113 | data.insert(data.begin() + pointer, variable.data.begin(), variable.data.end());
114 | pointer += variable.bytesPadded;
115 | }
116 |
117 | m_buffers[index]->updateHostMemory(bytes, data.data());
118 | }
119 |
120 | template
121 | void setVariable(const std::string &name, T value) {
122 | UniformVariable *variable = getVariable(name);
123 | uint32_t bytes = sizeof(T);
124 | assert(bytes == variable->bytes);
125 | char *bytePointer = (char *)(&value);
126 | for (uint32_t i = 0; i < bytes; i++) {
127 | variable->data[i] = bytePointer[i];
128 | }
129 | }
130 |
131 |
132 | private:
133 | struct UniformVariable {
134 | std::string name;
135 | // SpvReflectTypeFlags type;
136 | uint32_t bytes{};
137 | uint32_t bytesPadded{};
138 |
139 | std::vector data; // TODO(Mirco): use one long data vector for all variables in the uniform
140 | };
141 |
142 | uint32_t m_set{};
143 | uint32_t m_binding{};
144 |
145 | std::string m_name;
146 |
147 | std::vector m_variables;
148 |
149 | GPUContext *m_gpuContext;
150 |
151 | std::vector> m_buffers;
152 |
153 | UniformVariable *getVariable(const std::string &name) {
154 | for (uint32_t i = 0; i < m_variables.size(); i++) {
155 | if (strcmp(m_variables[i].name.c_str(), name.c_str()) == 0) {
156 | return &m_variables[i];
157 | }
158 | }
159 | throw std::runtime_error("Unknown uniform variable " + name + ".");
160 | }
161 | };
162 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/VideoHeadlessApplication.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "Buffer.h"
6 | #include "GPUContext.h"
7 | #include "HeadlessApplication.h"
8 | #include "Renderer.h"
9 | #include "Texture.h"
10 | #include "raven/util/Camera.h"
11 |
12 | namespace raven {
13 | class VideoHeadlessApplication : public HeadlessApplication {
14 | public:
15 | struct VideoApplicationSettings {
16 | std::function m_executeAfterStartupExecutions = [](GPUContext *) {};
17 | std::function m_executeEachFrame = [](uint32_t) {};
18 |
19 | uint32_t m_framePerExecution = 1;
20 | };
21 |
22 | VideoHeadlessApplication(std::string &appName, ApplicationSettings appSettings, VideoApplicationSettings videoAppSettings, std::shared_ptr renderer, uint32_t requiredQueueFamilies);
23 |
24 | void run() override;
25 |
26 | protected:
27 | VideoApplicationSettings m_videoApplicationSettings;
28 |
29 | void loop() override;
30 | void finish() override;
31 | void render() override;
32 |
33 | private:
34 | void storeImage(uint32_t execution);
35 | };
36 | } // namespace raven
37 |
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/core/VkDebugUtils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "raven/RavenInclude.h"
6 |
7 | namespace raven {
8 | class VkDebugUtils {
9 | public:
10 | VkDebugUtils(vk::Device device, bool enabled) : m_device(device), m_enabled(enabled) {
11 | }
12 |
13 | static std::string getExtensionName() {
14 | return VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
15 | }
16 |
17 | void setObjectName(vk::ObjectType objectType, uint64_t objectHandle, const char *name) {
18 | if (!m_enabled) {
19 | return;
20 | }
21 | vk::DebugUtilsObjectNameInfoEXT nameInfo;
22 | nameInfo.objectType = objectType;
23 | nameInfo.objectHandle = objectHandle;
24 | nameInfo.pObjectName = name;
25 | if (m_device.setDebugUtilsObjectNameEXT(&nameInfo) != vk::Result::eSuccess) {
26 | throw std::runtime_error("Failed to set debug object name!");
27 | }
28 | }
29 |
30 | void setName(vk::ShaderModule object, const std::string &name) {
31 | setObjectName(vk::ObjectType::eShaderModule, (uint64_t) static_cast(object), ("[ShaderModule]_" + name).c_str());
32 | }
33 |
34 | void setName(vk::DeviceMemory object, const std::string &name) {
35 | setObjectName(vk::ObjectType::eDeviceMemory, (uint64_t) static_cast(object), ("[DeviceMemory]_" + name).c_str());
36 | }
37 |
38 | void setName(vk::Image object, const std::string &name) {
39 | setObjectName(vk::ObjectType::eImage, (uint64_t) static_cast(object), ("[Image]_" + name).c_str());
40 | }
41 | void setName(vk::ImageView object, const std::string &name) {
42 | setObjectName(vk::ObjectType::eImageView, (uint64_t) static_cast(object), ("[ImageView]_" + name).c_str());
43 | }
44 | void setName(vk::Sampler object, const std::string &name) {
45 | setObjectName(vk::ObjectType::eSampler, (uint64_t) static_cast(object), ("[Sampler]_" + name).c_str());
46 | }
47 | void setName(vk::Buffer object, const std::string &name) {
48 | setObjectName(vk::ObjectType::eBuffer, (uint64_t) static_cast(object), ("[Buffer]_" + name).c_str());
49 | }
50 |
51 | private:
52 | vk::Device m_device;
53 |
54 | bool m_enabled = false;
55 | };
56 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/passes/Pass.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "PassShader.h"
3 |
4 | #include
5 |
6 | namespace raven {
7 | #define RAVEN_PASS_RELEASE(pass) \
8 | if (pass) \
9 | pass->release()
10 |
11 | class Pass {
12 | public:
13 | struct PassSettings {
14 | std::string m_name = "undefined";
15 |
16 | bool m_semaphoreExportFlag = false;
17 | };
18 |
19 | Pass(GPUContext *gpuContext, PassSettings settings) : m_gpuContext(gpuContext), m_passSettings(std::move(settings)) {}
20 |
21 | virtual ~Pass() = default;
22 |
23 | virtual void create() {
24 | findQueueFamily();
25 | createCommandPool();
26 | createCommandBuffers();
27 | createSyncObjects();
28 | }
29 |
30 | virtual void release() {
31 | releaseSyncObjects();
32 | vkDestroyCommandPool(m_gpuContext->m_device, m_commandPool, nullptr);
33 | }
34 |
35 | void recreateSyncObjects() {
36 | releaseSyncObjects();
37 | createSyncObjects();
38 | }
39 |
40 | virtual void execute(const std::function &updateStorageBuffers,
41 | const std::function &updateUniforms,
42 | const std::function &recordCommandBuffer,
43 | const uint32_t waitTimelineSemaphoreCount, const vk::Semaphore *waitTimelineSemaphore, const uint64_t *waitTimelineSemaphoreValue, vk::PipelineStageFlags *waitDstStageMask) {
44 | {
45 | // wait for the previous frame to finish
46 | vk::SemaphoreWaitInfo waitInfo{};
47 | waitInfo.semaphoreCount = 1;
48 | waitInfo.pSemaphores = &m_timelineSemaphore;
49 | waitInfo.pValues = &m_timelineSemaphoreValue;
50 | if (m_gpuContext->m_device.waitSemaphores(&waitInfo, UINT64_MAX) != vk::Result::eSuccess) {
51 | throw std::runtime_error("Failed to wait for timeline semaphore!");
52 | }
53 | }
54 |
55 | updateStorageBuffers();
56 | updateUniforms();
57 |
58 | auto &commandBuffer = m_commandBuffer;
59 | commandBuffer.reset();
60 | constexpr vk::CommandBufferBeginInfo beginInfo{};
61 | if (commandBuffer.begin(&beginInfo) != vk::Result::eSuccess) {
62 | throw std::runtime_error("Failed to begin recording command buffer!");
63 | }
64 | recordCommandBuffer(commandBuffer);
65 | commandBuffer.end();
66 |
67 | m_timelineSemaphoreValue++;
68 | vk::TimelineSemaphoreSubmitInfo timelineSubmitInfo{};
69 | timelineSubmitInfo.waitSemaphoreValueCount = waitTimelineSemaphoreCount;
70 | timelineSubmitInfo.pWaitSemaphoreValues = waitTimelineSemaphoreValue;
71 | timelineSubmitInfo.signalSemaphoreValueCount = 1;
72 | timelineSubmitInfo.pSignalSemaphoreValues = &m_timelineSemaphoreValue;
73 |
74 | vk::SubmitInfo submitInfo{};
75 | submitInfo.pNext = &timelineSubmitInfo;
76 | submitInfo.waitSemaphoreCount = waitTimelineSemaphoreCount;
77 | submitInfo.pWaitSemaphores = waitTimelineSemaphore;
78 | submitInfo.pWaitDstStageMask = waitDstStageMask;
79 | submitInfo.signalSemaphoreCount = 1;
80 | submitInfo.pSignalSemaphores = &m_timelineSemaphore;
81 | submitInfo.commandBufferCount = 1;
82 | submitInfo.pCommandBuffers = &m_commandBuffer;
83 |
84 | if (m_gpuContext->m_queues->getQueue(m_queueType).submit(1, &submitInfo, VK_NULL_HANDLE) != vk::Result::eSuccess) {
85 | throw std::runtime_error("Failed to submit command buffer!");
86 | }
87 | };
88 |
89 | std::string getName() const { return m_passSettings.m_name; }
90 |
91 | [[nodiscard]] vk::Semaphore getTimelineSemaphore() const { return m_timelineSemaphore; }
92 | [[nodiscard]] uint64_t getTimelineSemaphoreValue() const { return m_timelineSemaphoreValue; }
93 |
94 | protected:
95 | GPUContext *m_gpuContext;
96 |
97 | PassSettings m_passSettings;
98 |
99 | uint32_t m_queueFamilyIndex{};
100 | Queues::Queue m_queueType = Queues::GRAPHICS;
101 |
102 | vk::CommandPool m_commandPool{};
103 | vk::CommandBuffer m_commandBuffer; // destroyed implicitly with the command pool
104 |
105 | vk::Semaphore m_timelineSemaphore{};
106 | uint64_t m_timelineSemaphoreValue = 0U;
107 |
108 | virtual void findQueueFamily() = 0;
109 |
110 | private:
111 | void createCommandPool() {
112 | vk::CommandPoolCreateInfo poolInfo{};
113 | poolInfo.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
114 | poolInfo.queueFamilyIndex = m_queueFamilyIndex;
115 |
116 | if (m_gpuContext->m_device.createCommandPool(&poolInfo, nullptr, &m_commandPool) != vk::Result::eSuccess) {
117 | throw std::runtime_error("Failed to create command pool!");
118 | }
119 | }
120 |
121 | void createCommandBuffers() {
122 | vk::CommandBufferAllocateInfo allocInfo{};
123 | allocInfo.commandPool = m_commandPool;
124 | allocInfo.level = vk::CommandBufferLevel::ePrimary;
125 | allocInfo.commandBufferCount = 1;
126 |
127 | if (m_gpuContext->m_device.allocateCommandBuffers(&allocInfo, &m_commandBuffer) != vk::Result::eSuccess) {
128 | throw std::runtime_error("Failed to allocate command buffers!");
129 | }
130 | }
131 |
132 | void createSyncObjects() {
133 | m_timelineSemaphoreValue = 0U;
134 |
135 | vk::SemaphoreTypeCreateInfo timelineCreateInfo{};
136 | timelineCreateInfo.semaphoreType = vk::SemaphoreType::eTimeline;
137 | timelineCreateInfo.initialValue = 0;
138 |
139 | vk::ExportSemaphoreCreateInfo esci{};
140 | if (m_passSettings.m_semaphoreExportFlag) {
141 | #ifdef WIN32
142 | auto handleType = vk::ExternalSemaphoreHandleTypeFlagBits::eOpaqueWin32;
143 | #else
144 | auto handleType = vk::ExternalSemaphoreHandleTypeFlagBits::eOpaqueFd;
145 | #endif
146 | esci.handleTypes = handleType;
147 | timelineCreateInfo.pNext = &esci;
148 | }
149 |
150 | vk::SemaphoreCreateInfo semaphoreInfo{};
151 | semaphoreInfo.pNext = &timelineCreateInfo;
152 |
153 | if (m_gpuContext->m_device.createSemaphore(&semaphoreInfo, nullptr, &m_timelineSemaphore) != vk::Result::eSuccess) {
154 | throw std::runtime_error("Failed to create timeline semaphore!");
155 | }
156 | }
157 |
158 | void releaseSyncObjects() const {
159 | m_gpuContext->m_device.destroySemaphore(m_timelineSemaphore, nullptr);
160 | }
161 | };
162 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/passes/PassCompute.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Pass.h"
4 |
5 | namespace raven {
6 | class PassCompute final : public Pass {
7 | public:
8 | PassCompute(GPUContext *gpuContext, PassSettings settings) : Pass(gpuContext, std::move(settings)) {}
9 |
10 | protected:
11 | void findQueueFamily() override {
12 | Queues::QueueFamilyIndices queueFamilyIndices = m_gpuContext->m_queues->findQueueFamilies(m_gpuContext->m_physicalDevice);
13 | m_queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
14 | m_queueType = Queues::GRAPHICS;
15 | }
16 |
17 | private:
18 | };
19 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/passes/PassShaderCompute.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "PassShader.h"
4 |
5 | namespace raven {
6 | class PassShaderCompute : public PassShader {
7 | public:
8 | PassShaderCompute(GPUContext *gpuContext, std::string name) : PassShader(gpuContext, std::move(name)) {}
9 |
10 | void create() override { PassShader::create(); }
11 |
12 | void release() override { PassShader::release(); }
13 |
14 | void setWorkGroupCount(const uint32_t x, const uint32_t y, const uint32_t z) {
15 | m_workGroupCount = vk::Extent3D{x, y, z};
16 | }
17 |
18 | virtual void setGlobalInvocationSize(const uint32_t width, const uint32_t height, const uint32_t depth) {
19 | const vk::Extent3D workGroupSize = m_shaders[0]->getWorkGroupSize();
20 | m_workGroupCount = getDispatchSize(width, height, depth, workGroupSize);
21 | }
22 |
23 | static vk::Extent3D getDispatchSize(const uint32_t width, const uint32_t height, const uint32_t depth, const vk::Extent3D workGroupSize) {
24 | const uint32_t x = (width + workGroupSize.width - 1) / workGroupSize.width;
25 | const uint32_t y = (height + workGroupSize.height - 1) / workGroupSize.height;
26 | const uint32_t z = (depth + workGroupSize.depth - 1) / workGroupSize.depth;
27 | return vk::Extent3D{x, y, z};
28 | }
29 |
30 | void execute(const std::function &recordPushConstants,
31 | const std::function &recordPipelineBarriers,
32 | vk::CommandBuffer &commandBuffer) override {
33 | assert(m_workGroupCount.width >= 1 && m_workGroupCount.height >= 1 && m_workGroupCount.depth >= 1 && "Global invocation size must be set before executing PassShaderCompute!");
34 |
35 | queryTimeFromGPU();
36 |
37 | commandBuffer.resetQueryPool(m_queryPoolTimestamps, 0, static_cast(m_timestamps.size()));
38 |
39 | recordPushConstants(commandBuffer, m_pipelineLayout);
40 |
41 | commandBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_pipeline);
42 |
43 | std::vector descriptorSets;
44 | getDescriptorSets(descriptorSets);
45 | commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_pipelineLayout, 0, descriptorSets.size(), descriptorSets.data(), 0, nullptr);
46 |
47 | commandBuffer.writeTimestamp(vk::PipelineStageFlagBits::eComputeShader, m_queryPoolTimestamps, 0);
48 | vk::DebugUtilsLabelEXT label{};
49 | label.pLabelName = m_name.c_str();
50 | commandBuffer.beginDebugUtilsLabelEXT(&label);
51 | commandBuffer.dispatch(m_workGroupCount.width, m_workGroupCount.height, m_workGroupCount.depth);
52 | commandBuffer.endDebugUtilsLabelEXT();
53 | commandBuffer.writeTimestamp(vk::PipelineStageFlagBits::eComputeShader, m_queryPoolTimestamps, 1);
54 |
55 | recordPipelineBarriers(commandBuffer);
56 | }
57 |
58 | protected:
59 | void createPipeline() override {
60 | assert(m_shaders.size() == 1 && "Only one shader is allowed for PassShaderCompute!");
61 |
62 | const vk::PipelineShaderStageCreateInfo shaderStage = m_shaders[0]->generateShaderStageCreateInfo();
63 |
64 | vk::ComputePipelineCreateInfo pipelineInfo{};
65 | pipelineInfo.layout = m_pipelineLayout;
66 | pipelineInfo.stage = shaderStage;
67 |
68 | if (m_gpuContext->m_device.createComputePipelines(m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline) != vk::Result::eSuccess) {
69 | throw std::runtime_error("Failed to create compute pipeline!");
70 | }
71 | }
72 |
73 | bool getPushConstantRange(vk::PushConstantRange &pushConstantRange) override {
74 | pushConstantRange.stageFlags = getPushConstantStage();
75 | pushConstantRange.offset = 0;
76 | pushConstantRange.size = getPushConstantRangeSize();
77 | return pushConstantRange.size > 0;
78 | }
79 |
80 | vk::ShaderStageFlagBits getPushConstantStage() override {
81 | return vk::ShaderStageFlagBits::eCompute;
82 | }
83 |
84 | private:
85 | vk::Extent3D m_workGroupCount = {0, 0, 0};
86 | };
87 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/rendergraph/RenderGraphPass.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "raven/rendergraph/RenderGraphResource.h"
13 |
14 | namespace raven {
15 | enum RenderGraphPassType {
16 | GRAPHICS,
17 | COMPUTE,
18 | TRANSFER
19 | };
20 |
21 | class RenderGraphPass {
22 | public:
23 | void execute() const {
24 | m_executeFunction();
25 | }
26 |
27 | friend std::ostream &operator<<(std::ostream &stream, const RenderGraphPass &object) {
28 | stream << "RenderGraphPass{ name=" << object.m_name << " type=" << object.m_type << " root=" << object.m_root << "\n dependencies={ \n";
29 | for (const auto &dependency: object.m_dependencies) {
30 | stream << " " << dependency << "\n";
31 | }
32 | stream << " }"
33 | << "\n }";
34 | return stream;
35 | }
36 |
37 | private:
38 | friend class RenderGraphPassBuilder;
39 | friend class RenderGraph;
40 |
41 | RenderGraphPass(std::string name, const RenderGraphPassType type, const bool root) : m_name(std::move(name)), m_type(type), m_root(root) {}
42 |
43 | std::string m_name;
44 | RenderGraphPassType m_type;
45 | bool m_root = false;
46 |
47 | bool m_visited = false;
48 | std::vector m_dependencies{};
49 |
50 | std::function m_executeFunction = []() { throw std::runtime_error("RenderGraphPass::m_executeFunction not set."); };
51 |
52 | [[nodiscard]] bool hasReadDependencies(const std::unordered_map &resourceVersions) const {
53 | bool hasReadDependencies = false;
54 | for (const auto &dependency: m_dependencies) {
55 | if (dependency.m_type == RenderGraphResourceDependency::READ) {
56 | const auto resourceVersion = resourceVersions.at(dependency.m_name);
57 | if (resourceVersion > dependency.m_version) {
58 | throw std::runtime_error("This render pass should have been executed already.");
59 | }
60 | if (resourceVersion < dependency.m_version) {
61 | hasReadDependencies = true;
62 | break;
63 | }
64 | }
65 | }
66 | return hasReadDependencies;
67 | }
68 |
69 | [[nodiscard]] bool isFutureExecutionPossible(const std::unordered_map &resourceVersions) const {
70 | for (const auto &dependency: m_dependencies) {
71 | if (dependency.m_type == RenderGraphResourceDependency::READ) {
72 | const auto resourceVersion = resourceVersions.at(dependency.m_name);
73 | if (resourceVersion > dependency.m_version) {
74 | return false;
75 | }
76 | }
77 | }
78 | return true;
79 | }
80 | };
81 |
82 | class RenderGraphPassBuilder {
83 | public:
84 | RenderGraphPassBuilder(const std::string &name, const RenderGraphPassType type, bool root = false) : m_renderGraphPass{new RenderGraphPass(name, type, root)} {
85 | }
86 |
87 | [[nodiscard]] RenderGraphPass build() const {
88 | return std::move(*m_renderGraphPass);
89 | }
90 |
91 | RenderGraphPassBuilder &readResource(RenderGraphResource &renderResource) {
92 | m_renderGraphPass->m_dependencies.emplace_back(renderResource.m_name, renderResource.m_version, RenderGraphResourceDependency::READ);
93 | renderResource.m_dependencies.emplace_back(m_renderGraphPass->m_name, renderResource.m_version, RenderGraphResourceDependency::READ);
94 | return *this;
95 | }
96 |
97 | RenderGraphPassBuilder &writeResource(RenderGraphResource &renderResource) {
98 | m_renderGraphPass->m_dependencies.emplace_back(renderResource.m_name, renderResource.m_version, RenderGraphResourceDependency::WRITE);
99 | renderResource.m_dependencies.emplace_back(m_renderGraphPass->m_name, renderResource.m_version, RenderGraphResourceDependency::WRITE);
100 | renderResource.m_version++;
101 | return *this;
102 | }
103 |
104 | RenderGraphPassBuilder &execute(std::function executeFunction) {
105 | m_renderGraphPass->m_executeFunction = std::move(executeFunction);
106 | return *this;
107 | }
108 |
109 | private:
110 | std::unique_ptr m_renderGraphPass;
111 | };
112 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/rendergraph/RenderGraphResource.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace raven {
10 | struct RenderGraphResourceDependency {
11 | enum RenderGraphResourceDependencyType {
12 | READ,
13 | WRITE
14 | };
15 |
16 | std::string m_name; // either name of related resource or render pass
17 | uint32_t m_version;
18 | RenderGraphResourceDependencyType m_type;
19 |
20 | friend std::ostream &operator<<(std::ostream &stream, const RenderGraphResourceDependency &object) {
21 | stream << "RenderGraphResourceDependency{ name=" << object.m_name << " version=" << object.m_version << " type=" << (object.m_type == READ ? "R" : "W") << " }";
22 | return stream;
23 | }
24 | };
25 |
26 | class RenderGraphResource {
27 | public:
28 | explicit RenderGraphResource(std::string name) : m_name(std::move(name)) {}
29 |
30 | private:
31 | std::string m_name;
32 | uint32_t m_version = 0;
33 |
34 | std::vector m_dependencies{};
35 |
36 | friend std::ostream &operator<<(std::ostream &stream, const RenderGraphResource &object) {
37 | stream << "RenderGraphResource{ name=" << object.m_name << " nextVersion=" << object.m_version << "\n dependencies={ \n";
38 | for (const auto &dependency: object.m_dependencies) {
39 | stream << " " << dependency << "\n";
40 | }
41 | stream << " }"
42 | << "\n }";
43 | return stream;
44 | }
45 |
46 | friend class RenderGraphPass;
47 | friend class RenderGraphPassBuilder;
48 | friend class RenderGraph;
49 | };
50 | } // namespace raven
51 |
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/scene/ISceneLoader.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "RavenLight.h"
3 | #include "RavenMaterial.h"
4 | #include "RavenSceneNode.h"
5 | #include "RavenTexture.h"
6 |
7 |
8 | #include
9 |
10 | namespace raven {
11 | class ISceneLoader {
12 | protected:
13 | ~ISceneLoader() = default;
14 |
15 | public:
16 | virtual std::shared_ptr loadScene(std::function&)> registerMaterial,
17 | std::function&)> registerTexture,
18 | std::function&)> registerLight) = 0;
19 | };
20 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/scene/RavenLight.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace raven {
4 | class RavenLight {
5 | public:
6 | #define LIGHT_TYPE_AREA 0
7 | #define LIGHT_TYPE_POINT 1
8 | struct Light {
9 | uint32_t type = LIGHT_TYPE_AREA;
10 |
11 | uint32_t objectDescriptorId = 0;
12 | uint32_t triangleId = 0;
13 |
14 | glm::vec3 position = glm::vec3(0);
15 | glm::vec3 emission = glm::vec3(1);
16 | };
17 |
18 | std::string m_key{};
19 | std::string m_name = "RavenLight";
20 | Light m_light{};
21 | };
22 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/scene/RavenMaterial.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace raven {
7 | class RavenMaterial {
8 | public:
9 | struct Material {
10 | glm::vec3 baseColorFactor = glm::vec4(1.f);
11 | int32_t baseColorTexture = -1;
12 | float metallicFactor = 1.f;
13 | float roughnessFactor = 1.f;
14 | int32_t metallicRoughnessTexture = -1;
15 |
16 | int32_t normalTexture = -1;
17 |
18 | glm::vec3 emission = glm::vec3(0.f);
19 |
20 | float subsurface = 0.f; // [0,1], 0 no sss, 1 only sss
21 | glm::vec3 meanFreePath = glm::vec3(0.f); // l
22 |
23 | [[nodiscard]] bool isEmissive() const {
24 | return glm::any(glm::greaterThan(emission, glm::vec3(0.f)));
25 | }
26 |
27 | void mfpFromVolumetricCoefficients(glm::vec3 scatteringCoefficient, glm::vec3 absorptionCoefficient) {
28 | glm::vec3 extinctionCoefficient = scatteringCoefficient + absorptionCoefficient;
29 | meanFreePath = 1.f / extinctionCoefficient;
30 | }
31 |
32 | [[nodiscard]] glm::vec3 scatteringScaling(glm::vec3 surfaceAlbedo) const {
33 | glm::vec3 a = surfaceAlbedo - glm::vec3(0.8f);
34 | return 1.9f - surfaceAlbedo + 3.5f * a * a;
35 | }
36 |
37 | [[nodiscard]] glm::vec3 scatteringDistance(glm::vec3 surfaceAlbedo) const {
38 | return subsurface * meanFreePath / scatteringScaling(surfaceAlbedo);
39 | }
40 | };
41 |
42 | std::string m_key{};
43 | std::string m_name = "RavenMaterial";
44 | Material m_material{};
45 | glm::vec3 m_emissiveFactor = glm::vec3(0.f);
46 | float m_emissiveStrength = 0.f;
47 |
48 | void setEmission(const glm::vec3 emissiveFactor, const float emissiveStrength) {
49 | m_emissiveFactor = emissiveFactor;
50 | m_emissiveStrength = emissiveStrength;
51 | updateEmission();
52 | }
53 | void setEmission(const glm::vec3 emissiveFactor) {
54 | m_emissiveFactor = emissiveFactor;
55 | updateEmission();
56 | }
57 | void setEmission(const float emissiveStrength) {
58 | m_emissiveStrength = emissiveStrength;
59 | updateEmission();
60 | }
61 | void updateEmission() {
62 | m_material.emission = m_emissiveFactor * m_emissiveStrength;
63 | }
64 |
65 | std
66 | ::string m_baseColorTexture{};
67 | std::string m_metallicRoughnessTexture{};
68 | std::string m_normalTexture{};
69 |
70 | void updateTextureIds(const std::function &textureIdFromName) {
71 | m_material.baseColorTexture = textureIdFromName(m_baseColorTexture);
72 | m_material.metallicRoughnessTexture = textureIdFromName(m_metallicRoughnessTexture);
73 | m_material.normalTexture = textureIdFromName(m_normalTexture);
74 | }
75 | };
76 | } // namespace RavenMaterial
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/scene/RavenSceneNode.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "RavenSceneObject.h"
3 |
4 |
5 | #include
6 | #include
7 |
8 | namespace raven {
9 | class RavenSceneNode {
10 | public:
11 | std::string m_name = "RavenSceneNode";
12 |
13 | std::optional m_transformation;
14 |
15 | std::vector> m_children;
16 | std::shared_ptr m_object = nullptr;
17 |
18 |
19 | };
20 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/scene/RavenSceneObject.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "raven/core/AccelerationStructure.h"
3 | #include "raven/util/AABB.h"
4 |
5 |
6 | #include
7 |
8 | namespace raven {
9 | class RavenSceneObject {
10 | public:
11 | std::string m_name = "RavenSceneObject";
12 |
13 | struct Vertex {
14 | float position_x;
15 | float position_y;
16 | float position_z;
17 | float normal_x;
18 | float normal_y;
19 | float normal_z;
20 | float tangent_x;
21 | float tangent_y;
22 | float tangent_z;
23 | float tangent_w; // bitangent sign
24 | float texCoord_u;
25 | float texCoord_v;
26 | };
27 |
28 | AABB m_aabb;
29 |
30 | std::vector m_vertices;
31 | std::vector m_indices;
32 |
33 | std::string m_material{};
34 |
35 | // GPU
36 | struct GPUSceneObject {
37 | std::shared_ptr m_vertexBuffer = nullptr;
38 | std::shared_ptr m_indexBuffer = nullptr;
39 | uint32_t m_materialId = 0;
40 |
41 | uint32_t m_numPrimitives = 0;
42 |
43 | std::shared_ptr m_blas = nullptr;
44 |
45 | glm::mat4 m_modelMatrix{};
46 |
47 | glm::mat4 m_globalTransformation{};
48 |
49 | AABB m_abbb{};
50 |
51 | RavenSceneObject *m_sceneObject = nullptr;
52 | };
53 |
54 | GPUSceneObject gpu(GPUContext *gpuContext, uint32_t materialId, const glm::mat4 &transformation, const glm::mat4 &globalTransformation) {
55 | GPUSceneObject gpuSceneObject{};
56 |
57 | // if (m_material.isEmissive()) {
58 | // for (uint32_t lId = 0; lId < getNumPrimitives(); lId++) {
59 | // info.m_lights.push_back({lId + numPrimitives});
60 | // }
61 | // }
62 |
63 | gpuSceneObject.m_vertexBuffer = Buffer::fillDeviceWithStagingBuffer(gpuContext,
64 | {.m_sizeBytes = static_cast(m_vertices.size() * sizeof(Vertex)), .m_bufferUsages = vk::BufferUsageFlagBits::eShaderDeviceAddress | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eAccelerationStructureBuildInputReadOnlyKHR, .m_memoryProperties = vk::MemoryPropertyFlagBits::eDeviceLocal, .m_memoryAllocateFlagBits = vk::MemoryAllocateFlagBits::eDeviceAddress, .m_name = "vertex0"},
65 | reinterpret_cast(m_vertices.data()));
66 | gpuSceneObject.m_indexBuffer = Buffer::fillDeviceWithStagingBuffer(gpuContext,
67 | {.m_sizeBytes = static_cast(m_indices.size() * sizeof(uint32_t)), .m_bufferUsages = vk::BufferUsageFlagBits::eShaderDeviceAddress | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eAccelerationStructureBuildInputReadOnlyKHR, .m_memoryProperties = vk::MemoryPropertyFlagBits::eDeviceLocal, .m_memoryAllocateFlagBits = vk::MemoryAllocateFlagBits::eDeviceAddress, .m_name = "index0"},
68 | reinterpret_cast(m_indices.data()));
69 |
70 | gpuSceneObject.m_materialId = materialId;
71 |
72 | gpuSceneObject.m_numPrimitives = m_indices.size() / 3;
73 |
74 | gpuSceneObject.m_blas = std::make_shared(gpuContext, gpuSceneObject.m_vertexBuffer->getDeviceAddress(), static_cast(m_vertices.size()), sizeof(Vertex), gpuSceneObject.m_indexBuffer->getDeviceAddress(), m_indices.size() / 3);
75 | gpuSceneObject.m_blas->transform(transformation);
76 | gpuSceneObject.m_blas->build();
77 |
78 | gpuSceneObject.m_modelMatrix = transformation;
79 |
80 | gpuSceneObject.m_globalTransformation = globalTransformation;
81 |
82 | gpuSceneObject.m_abbb.expand(m_aabb.m_min);
83 | gpuSceneObject.m_abbb.expand(m_aabb.m_max);
84 |
85 | gpuSceneObject.m_sceneObject = this;
86 |
87 | return gpuSceneObject;
88 | }
89 | };
90 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/scene/RavenTexture.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace raven {
4 | class RavenTexture {
5 | public:
6 | std::string m_key{};
7 | std::string m_name = "RavenTexture";
8 |
9 | std::string m_directory;
10 | std::string m_uri;
11 | };
12 | }
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/util/AABB.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace raven {
6 |
7 | struct AABB {
8 | glm::vec3 m_min = glm::vec3(FLT_MAX);
9 | glm::vec3 m_max = glm::vec3(-FLT_MAX);
10 |
11 | void expand(const glm::vec3 vec) {
12 | if (m_min.x > vec.x) {
13 | m_min.x = vec.x;
14 | }
15 | if (m_min.y > vec.y) {
16 | m_min.y = vec.y;
17 | }
18 | if (m_min.z > vec.z) {
19 | m_min.z = vec.z;
20 | }
21 |
22 | if (m_max.x < vec.x) {
23 | m_max.x = vec.x;
24 | }
25 | if (m_max.y < vec.y) {
26 | m_max.y = vec.y;
27 | }
28 | if (m_max.z < vec.z) {
29 | m_max.z = vec.z;
30 | }
31 | }
32 |
33 | [[nodiscard]] float calculateVolume() const {
34 | if (m_min.x >= m_max.x || m_min.y >= m_max.y || m_min.z >= m_max.z) {
35 | return 0.f;
36 | }
37 | return (m_max.x - m_min.x) * (m_max.y - m_min.y) * (m_max.z - m_min.z);
38 | }
39 |
40 | [[nodiscard]] float m_maxExtent() const { return glm::max(0.f, glm::max(m_max.x - m_min.x, glm::max(m_max.y - m_min.y, m_max.z - m_min.z))); };
41 |
42 | [[nodiscard]] float m_maxExtentAxis() const {
43 | const float xExtent = m_max.x - m_min.x;
44 | const float yExtent = m_max.y - m_min.y;
45 | const float zExtent = m_max.z - m_min.z;
46 | if (xExtent > yExtent && xExtent > zExtent) {
47 | return 0.f;
48 | }
49 | return yExtent > zExtent ? 1 : 2;
50 | }
51 |
52 | [[nodiscard]] float maxElement() const { return glm::max(m_max.x, glm::max(m_max.y, m_max.z)); }
53 |
54 | [[nodiscard]] float minElement() const { return glm::min(m_min.x, glm::min(m_min.y, m_min.z)); }
55 |
56 | [[nodiscard]] glm::vec3 center() const {
57 | return .5f * (m_min + m_max);
58 | }
59 |
60 | [[nodiscard]] glm::vec3 halfSize() const {
61 | return .5f * (m_max - m_min);
62 | }
63 |
64 | friend std::ostream &operator<<(std::ostream &stream, const AABB &aabb) {
65 | stream << "AABB{ m_min=(" << aabb.m_min.x << "," << aabb.m_min.y << "," << aabb.m_min.z << "), m_max=(" << aabb.m_max.x << "," << aabb.m_max.y << "," << aabb.m_max.z << ") }";
66 | return stream;
67 | }
68 | };
69 |
70 | struct iAABB {
71 | glm::ivec3 m_min = glm::ivec3(INT32_MAX);
72 | glm::ivec3 m_max = glm::ivec3(INT32_MIN);
73 |
74 | void expand(const glm::ivec3 vec) {
75 | if (m_min.x > vec.x) {
76 | m_min.x = vec.x;
77 | }
78 | if (m_min.y > vec.y) {
79 | m_min.y = vec.y;
80 | }
81 | if (m_min.z > vec.z) {
82 | m_min.z = vec.z;
83 | }
84 |
85 | if (m_max.x < vec.x) {
86 | m_max.x = vec.x;
87 | }
88 | if (m_max.y < vec.y) {
89 | m_max.y = vec.y;
90 | }
91 | if (m_max.z < vec.z) {
92 | m_max.z = vec.z;
93 | }
94 | }
95 |
96 | [[nodiscard]] int32_t calculateVolume() const {
97 | if (m_min.x >= m_max.x || m_min.y >= m_max.y || m_min.z >= m_max.z) {
98 | return 0;
99 | }
100 | return (m_max.x - m_min.x) * (m_max.y - m_min.y) * (m_max.z - m_min.z);
101 | }
102 |
103 | [[nodiscard]] uint32_t maxExtent() const { return glm::max(0, glm::max(m_max.x - m_min.x, glm::max(m_max.y - m_min.y, m_max.z - m_min.z))); };
104 |
105 | [[nodiscard]] int32_t maxExtentAxis() const {
106 | const int32_t xExtent = m_max.x - m_min.x;
107 | const int32_t yExtent = m_max.y - m_min.y;
108 | const int32_t zExtent = m_max.z - m_min.z;
109 | if (xExtent > yExtent && xExtent > zExtent) {
110 | return 0;
111 | }
112 | return yExtent > zExtent ? 1 : 2;
113 | }
114 |
115 | [[nodiscard]] int32_t maxElement() const { return glm::max(m_max.x, glm::max(m_max.y, m_max.z)); }
116 |
117 | [[nodiscard]] int32_t minElement() const { return glm::min(m_min.x, glm::min(m_min.y, m_min.z)); }
118 |
119 | [[nodiscard]] glm::vec3 center() const {
120 | return .5f * glm::vec3(m_min + m_max);
121 | }
122 |
123 | [[nodiscard]] glm::vec3 halfSize() const {
124 | return .5f * glm::vec3(m_max - m_min);
125 | }
126 |
127 | friend std::ostream &operator<<(std::ostream &stream, const iAABB &aabb) {
128 | stream << "iAABB{ m_min=(" << aabb.m_min.x << "," << aabb.m_min.y << "," << aabb.m_min.z << "), m_max=(" << aabb.m_max.x << "," << aabb.m_max.y << "," << aabb.m_max.z << ") }";
129 | return stream;
130 | }
131 | };
132 |
133 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/util/Paths.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | namespace raven {
5 | class Paths {
6 | public:
7 | inline static std::string m_resourceDirectoryPath;
8 |
9 | private:
10 | Paths() = default;
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/util/Trajectory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | namespace raven {
5 | class Trajectory {
6 | public:
7 | Trajectory() = default;
8 |
9 | void init(glm::vec3 start, glm::vec3 end, uint32_t steps) {
10 | m_start = start;
11 | m_end = end;
12 | m_steps = steps;
13 | m_stepCount = 0;
14 | }
15 |
16 | bool step(glm::vec3 *position) {
17 | if (m_stepCount >= m_steps) {
18 | return false;
19 | }
20 |
21 | m_stepCount++;
22 |
23 | float t = static_cast(m_stepCount) / static_cast(m_steps);
24 | *position = m_start + t * (m_end - m_start);
25 |
26 | return true;
27 | }
28 |
29 | private:
30 | glm::vec3 m_start{};
31 | glm::vec3 m_end{};
32 | uint32_t m_steps{};
33 |
34 | uint32_t m_stepCount = 0;
35 | };
36 | }
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/util/animation/BSpline.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace raven {
7 | class BSpline {
8 | public:
9 | [[nodiscard]] glm::vec3 evaluate(float u) const {
10 | const int interval = static_cast(glm::floor(u));
11 | const float t = glm::fract(u);
12 |
13 | assert(interval >= 0 && interval < m_controlPoints.size() - 3);
14 |
15 | const glm::vec3 p0 = m_controlPoints[interval];
16 | const glm::vec3 p1 = m_controlPoints[interval + 1];
17 | const glm::vec3 p2 = m_controlPoints[interval + 2];
18 | const glm::vec3 p3 = m_controlPoints[interval + 3];
19 |
20 | const float t2 = t * t;
21 | const float t3 = t2 * t;
22 |
23 | return 1.f / 6.f * ((-p0 + 3.f * p1 - 3.f * p2 + p3) * t3 + (3.f * p0 - 6.f * p1 + 3.f * p2) * t2 + (-3.f * p0 + 3.f * p2) * t + (p0 + 4.f * p1 + p2));
24 | }
25 |
26 | [[nodiscard]] float getMaxU() const {
27 | return static_cast(static_cast(m_controlPoints.size()) - 3);
28 | }
29 |
30 | std::vector m_controlPoints;
31 | };
32 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/include/raven/util/sampling/AliasTable.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | namespace raven {
8 | class AliasTable {
9 | public:
10 | explicit AliasTable(std::vector weights) : m_bins(weights.size()) {
11 | // Normalize _weights_ to compute alias table PDF
12 | const float sum = std::accumulate(weights.begin(), weights.end(), 0.);
13 | assert(sum > 0);
14 | for (size_t i = 0; i < weights.size(); ++i)
15 | m_bins[i].p = weights[i] / sum;
16 |
17 | // Create alias table work lists
18 | struct Outcome {
19 | float pHat;
20 | size_t index;
21 | };
22 | std::vector under, over;
23 | for (size_t i = 0; i < m_bins.size(); ++i) {
24 | // Add outcome _i_ to an alias table work list
25 | const float pHat = m_bins[i].p * m_bins.size();
26 | if (pHat < 1)
27 | under.push_back(Outcome{pHat, i});
28 | else
29 | over.push_back(Outcome{pHat, i});
30 | }
31 |
32 | // Process under and over work item together
33 | while (!under.empty() && !over.empty()) {
34 | // Remove items _un_ and _ov_ from the alias table work lists
35 | const Outcome un = under.back(), ov = over.back();
36 | under.pop_back();
37 | over.pop_back();
38 |
39 | // Initialize probability and alias for _un_
40 | m_bins[un.index].q = un.pHat;
41 | m_bins[un.index].alias = ov.index;
42 |
43 | // Push excess probability on to work list
44 | const float pExcess = un.pHat + ov.pHat - 1;
45 | if (pExcess < 1)
46 | under.push_back(Outcome{pExcess, ov.index});
47 | else
48 | over.push_back(Outcome{pExcess, ov.index});
49 | }
50 |
51 | // Handle remaining alias table work items
52 | while (!over.empty()) {
53 | const Outcome ov = over.back();
54 | over.pop_back();
55 | m_bins[ov.index].q = 1;
56 | m_bins[ov.index].alias = -1;
57 | }
58 | while (!under.empty()) {
59 | const Outcome un = under.back();
60 | under.pop_back();
61 | m_bins[un.index].q = 1;
62 | m_bins[un.index].alias = -1;
63 | }
64 | }
65 |
66 | int32_t sample(float xi, float *pdf) const {
67 | // Compute alias table _offset_ and remapped random sample _up_
68 | const int offset = std::min(xi * m_bins.size(), m_bins.size() - 1);
69 | const float up = std::min(xi * m_bins.size() - offset, 0x1.fffffep-1);
70 |
71 | if (up < m_bins[offset].q) {
72 | // Return sample for alias table at _offset_
73 | assert(m_bins[offset].p > 0);
74 | if (pdf)
75 | *pdf = m_bins[offset].p;
76 | return offset;
77 | } else {
78 | // Return sample for alias table at _alias[offset]_
79 | const int alias = m_bins[offset].alias;
80 | assert(alias >= 0);
81 | assert(m_bins[alias].p > 0);
82 | if (pdf)
83 | *pdf = m_bins[alias].p;
84 | return alias;
85 | }
86 | }
87 |
88 | // private:
89 | struct Bin {
90 | float q, p;
91 | int32_t alias;
92 | };
93 |
94 | std::vector m_bins;
95 | };
96 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/src/raven/core/Queues.cpp:
--------------------------------------------------------------------------------
1 | #include "raven/core/Queues.h"
2 |
3 | namespace raven {
4 |
5 | Queues::QueueFamilyIndices Queues::findQueueFamilies(vk::PhysicalDevice physicalDevice) const {
6 | QueueFamilyIndices familyIndices;
7 |
8 | uint32_t queueFamilyCount = 0;
9 | vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
10 | std::vector queueFamilies(queueFamilyCount);
11 | physicalDevice.getQueueFamilyProperties(&queueFamilyCount, queueFamilies.data());
12 |
13 | // graphics queue
14 | if (raven::Queues::QueueFamilyIndices::requireGraphicsFamily(m_requiredQueueFamilies)) {
15 | familyIndices.graphicsFamily = getQueueFamilyIndex(queueFamilies, vk::QueueFlagBits::eGraphics);
16 | }
17 |
18 | // dedicated compute queue
19 | if (raven::Queues::QueueFamilyIndices::requireComputeFamily(m_requiredQueueFamilies)) {
20 | familyIndices.computeFamily = getQueueFamilyIndex(queueFamilies, vk::QueueFlagBits::eCompute);
21 | }
22 |
23 | // dedicated transfer queue
24 | if (raven::Queues::QueueFamilyIndices::requireTransferFamily(m_requiredQueueFamilies)) {
25 | familyIndices.transferFamily = getQueueFamilyIndex(queueFamilies, vk::QueueFlagBits::eTransfer);
26 | }
27 |
28 | return familyIndices;
29 | }
30 |
31 | void Queues::generateQueueCreateInfos(vk::PhysicalDevice physicalDevice, std::vector *queueCreateInfos, float *queuePriorities) const {
32 | QueueFamilyIndices familyIndices = findQueueFamilies(physicalDevice);
33 | familyIndices.generateQueueCreateInfos(queueCreateInfos, queuePriorities);
34 | }
35 |
36 | void Queues::createQueues(vk::Device device, vk::PhysicalDevice physicalDevice) {
37 | QueueFamilyIndices familyIndices = findQueueFamilies(physicalDevice);
38 | if (isFamilyRequired(GRAPHICS_FAMILY)) {
39 | device.getQueue(familyIndices.graphicsFamily.value(), 0, &m_queues[GRAPHICS]);
40 | }
41 | if (isFamilyRequired(COMPUTE_FAMILY)) {
42 | device.getQueue(familyIndices.computeFamily.value(), 0, &m_queues[COMPUTE]);
43 | }
44 | if (isFamilyRequired(TRANSFER_FAMILY)) {
45 | device.getQueue(familyIndices.transferFamily.value(), 0, &m_queues[TRANSFER]);
46 | }
47 | }
48 |
49 | vk::Queue Queues::getQueue(Queues::Queue queue) {
50 | return m_queues[queue];
51 | }
52 |
53 | bool Queues::isFamilyRequired(Queues::QueueFamilies queueFamily) const {
54 | return m_requiredQueueFamilies & queueFamily;
55 | }
56 | } // namespace raven
--------------------------------------------------------------------------------
/VkRaven/raven/src/raven/core/RavenVkDynamicLoader.cpp:
--------------------------------------------------------------------------------
1 | #include "raven/RavenInclude.h"
2 |
3 | #if (VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1)
4 | VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
5 | #endif
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MircoWerner/ReSTIR-SSS/c209f2b72b85cc51aa2577c14534952154ae4313/screenshot.png
--------------------------------------------------------------------------------
/teaser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MircoWerner/ReSTIR-SSS/c209f2b72b85cc51aa2577c14534952154ae4313/teaser.png
--------------------------------------------------------------------------------