├── .editorconfig ├── threads-cpp-smallpt ├── cpp-smallpt │ └── src │ │ ├── targetver.hpp │ │ ├── task.hpp │ │ ├── windows.hpp │ │ ├── math.hpp │ │ ├── imageio.hpp │ │ ├── sampling.hpp │ │ ├── rng.hpp │ │ ├── geometry.hpp │ │ ├── specular.hpp │ │ ├── task.cpp │ │ ├── sphere.hpp │ │ ├── lock.cpp │ │ ├── cpp-smallpt.cpp │ │ ├── vector.hpp │ │ └── lock.hpp ├── Properties │ ├── x64_Debug.props │ ├── x86_Debug.props │ ├── x64_Release.props │ └── x86_Release.props ├── cpp-smallpt.sln ├── cpp-smallpt.vcxproj.filters └── cpp-smallpt.vcxproj ├── README.md ├── appveyor.yml ├── LICENSE.txt ├── cpp-smallpt ├── Properties │ ├── x64_Debug.props │ ├── x86_Debug.props │ ├── x64_Release.props │ └── x86_Release.props ├── cpp-smallpt │ └── src │ │ ├── math.hpp │ │ ├── imageio.hpp │ │ ├── sampling.hpp │ │ ├── rng.hpp │ │ ├── geometry.hpp │ │ ├── specular.hpp │ │ ├── sphere.hpp │ │ ├── cpp-smallpt.cpp │ │ └── vector.hpp ├── cpp-smallpt.sln ├── cpp-smallpt.vcxproj.filters └── cpp-smallpt.vcxproj ├── openmp-cpp-smallpt ├── cpp-smallpt │ └── src │ │ ├── math.hpp │ │ ├── imageio.hpp │ │ ├── sampling.hpp │ │ ├── rng.hpp │ │ ├── geometry.hpp │ │ ├── specular.hpp │ │ ├── sphere.hpp │ │ ├── cpp-smallpt.cpp │ │ └── vector.hpp ├── Properties │ ├── x64_Debug.props │ ├── x86_Debug.props │ ├── x64_Release.props │ └── x86_Release.props ├── cpp-smallpt.sln ├── cpp-smallpt.vcxproj.filters └── cpp-smallpt.vcxproj ├── .gitignore └── .gitattributes /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | indent_style = tab 4 | indent_size = 4 5 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/targetver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | // Targetting the highest available Windows platform. 9 | #include 10 | 11 | #pragma endregion -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status][s1]][av] [![License][s2]][li] 2 | 3 | [s1]: https://ci.appveyor.com/api/projects/status/7aoq8afvybx4efr8?svg=true 4 | [s2]: https://img.shields.io/badge/license-MIT-blue.svg 5 | 6 | [av]: https://ci.appveyor.com/project/matt77hias/cpp-smallpt 7 | [li]: https://raw.githubusercontent.com/matt77hias/cpp-smallpt/master/LICENSE.txt 8 | 9 | # cpp-smallpt 10 | 11 | ## About 12 | C++ modification of Kevin Baeson's [99 line C++ path tracer](http://www.kevinbeason.com/smallpt/) 13 | 14 | **Note**: I deliberately chose for the same software design for [all programming languages](https://github.com/matt77hias/smallpt) out of clarity and performance reasons (this can conflict with the nature of declarative/functional programming languages). 15 | 16 |

17 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/task.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "windows.hpp" 7 | 8 | namespace smallpt { 9 | 10 | [[nodiscard]] 11 | inline std::size_t NumberOfSystemCores() noexcept { 12 | SYSTEM_INFO system_info; 13 | GetSystemInfo(&system_info); 14 | return static_cast< std::size_t >(system_info.dwNumberOfProcessors); 15 | } 16 | 17 | class Task { 18 | 19 | public: 20 | 21 | Task() = default; 22 | Task(const Task& task) = default; 23 | Task(Task&& task) = default; 24 | virtual ~Task() = default; 25 | 26 | Task& operator=(const Task& task) = default; 27 | Task& operator=(Task&& task) = default; 28 | 29 | virtual void Run() noexcept = 0; 30 | }; 31 | 32 | void TasksInit(); 33 | void TasksCleanup(); 34 | 35 | void EnqueueTasks(const std::vector< Task* >& tasks); 36 | void WaitForAllTasks(); 37 | } -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # General Configuration 3 | ############################################################################### 4 | version: 2.0.{build} 5 | 6 | ############################################################################### 7 | # Environment Configuration 8 | ############################################################################### 9 | image: Visual Studio 2019 10 | 11 | configuration: 12 | - Release 13 | - Debug 14 | platform: 15 | - x64 16 | - x86 17 | environment: 18 | matrix: 19 | - solution_name: cpp-smallpt/cpp-smallpt.sln 20 | - solution_name: openmp-cpp-smallpt/cpp-smallpt.sln 21 | - solution_name: threads-cpp-smallpt/cpp-smallpt.sln 22 | 23 | ############################################################################### 24 | # Build Configuration 25 | ############################################################################### 26 | build: 27 | parallel: true 28 | verbosity: normal 29 | 30 | build_script: 31 | - msbuild %solution_name% 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Matthias Moulin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 6 | software and associated documentation files (the "Software"), to deal in the Software 7 | without restriction, including without limitation the rights to use, copy, modify, 8 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies 13 | or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 16 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 17 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 18 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 19 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/windows.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Defines 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | // Exclude APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets. 9 | #define WIN32_LEAN_AND_MEAN 10 | 11 | // Inhibit definitions: macros min(a,b) and max(a,b). 12 | #define NOMINMAX 13 | 14 | // Inhibit definitions: DrawText() and DT_*. 15 | #define NODRAWTEXT 16 | 17 | // Inhibit definitions: all GDI defines and routines. 18 | #define NOGDI 19 | 20 | // Inhibit definitions 21 | #define NOBITMAP 22 | 23 | // Inhibit definitions: typedef MSG and associated routines. 24 | #define NOMCX 25 | 26 | // Inhibit definitions: all Service Controller routines, SERVICE_ equates, etc. 27 | #define NOSERVICE 28 | 29 | // Inhibit definitions: help engine interface. 30 | #define NOHELP 31 | 32 | #pragma endregion 33 | 34 | //----------------------------------------------------------------------------- 35 | // System Includes 36 | //----------------------------------------------------------------------------- 37 | #pragma region 38 | 39 | #include 40 | 41 | #pragma endregion -------------------------------------------------------------------------------- /cpp-smallpt/Properties/x64_Debug.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x64\$(Configuration)\ 7 | $(ProjectName)\tmp\x64\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | 10 | 11 | 12 | Level4 13 | true 14 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 15 | true 16 | stdcpplatest 17 | $(ProjectName)\doc\ 18 | Fast 19 | 20 | 21 | true 22 | Console 23 | 24 | 25 | $(ProjectName)\doc\$(TargetName).xml 26 | 27 | 28 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/Properties/x64_Debug.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x64\$(Configuration)\ 7 | $(ProjectName)\tmp\x64\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | 10 | 11 | 12 | Level4 13 | true 14 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 15 | true 16 | stdcpplatest 17 | $(ProjectName)\doc\ 18 | Fast 19 | 20 | 21 | true 22 | Console 23 | 24 | 25 | $(ProjectName)\doc\$(TargetName).xml 26 | 27 | 28 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/math.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #pragma endregion 14 | 15 | //----------------------------------------------------------------------------- 16 | // Declarations and Definitions 17 | //----------------------------------------------------------------------------- 18 | namespace smallpt { 19 | 20 | //------------------------------------------------------------------------- 21 | // Constants 22 | //------------------------------------------------------------------------- 23 | 24 | constexpr double g_pi = 3.14159265358979323846; 25 | 26 | //------------------------------------------------------------------------- 27 | // Utilities 28 | //------------------------------------------------------------------------- 29 | 30 | [[nodiscard]] 31 | inline std::uint8_t ToByte(double color, double gamma = 2.2) noexcept { 32 | const double gcolor = std::pow(color, 1.0 / gamma); 33 | return static_cast< std::uint8_t >(std::clamp(255.0 * gcolor, 34 | 0.0, 255.0)); 35 | } 36 | } -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/math.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #pragma endregion 14 | 15 | //----------------------------------------------------------------------------- 16 | // Declarations and Definitions 17 | //----------------------------------------------------------------------------- 18 | namespace smallpt { 19 | 20 | //------------------------------------------------------------------------- 21 | // Constants 22 | //------------------------------------------------------------------------- 23 | 24 | constexpr double g_pi = 3.14159265358979323846; 25 | 26 | //------------------------------------------------------------------------- 27 | // Utilities 28 | //------------------------------------------------------------------------- 29 | 30 | [[nodiscard]] 31 | inline std::uint8_t ToByte(double color, double gamma = 2.2) noexcept { 32 | const double gcolor = std::pow(color, 1.0 / gamma); 33 | return static_cast< std::uint8_t >(std::clamp(255.0 * gcolor, 34 | 0.0, 255.0)); 35 | } 36 | } -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/math.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #pragma endregion 14 | 15 | //----------------------------------------------------------------------------- 16 | // Declarations and Definitions 17 | //----------------------------------------------------------------------------- 18 | namespace smallpt { 19 | 20 | //------------------------------------------------------------------------- 21 | // Constants 22 | //------------------------------------------------------------------------- 23 | 24 | constexpr double g_pi = 3.14159265358979323846; 25 | 26 | //------------------------------------------------------------------------- 27 | // Utilities 28 | //------------------------------------------------------------------------- 29 | 30 | [[nodiscard]] 31 | inline std::uint8_t ToByte(double color, double gamma = 2.2) noexcept { 32 | const double gcolor = std::pow(color, 1.0 / gamma); 33 | return static_cast< std::uint8_t >(std::clamp(255.0 * gcolor, 34 | 0.0, 255.0)); 35 | } 36 | } -------------------------------------------------------------------------------- /openmp-cpp-smallpt/Properties/x64_Debug.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x64\$(Configuration)\ 7 | $(ProjectName)\tmp\x64\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | 10 | 11 | 12 | Level4 13 | true 14 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 15 | true 16 | stdcpplatest 17 | $(ProjectName)\doc\ 18 | Fast 19 | true 20 | 21 | 22 | true 23 | Console 24 | 25 | 26 | $(ProjectName)\doc\$(TargetName).xml 27 | 28 | 29 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/imageio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // System Includes 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #include 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | inline void WritePPM(std::uint32_t w, 27 | std::uint32_t h, 28 | const Vector3* Ls, 29 | const char* fname = "cpp-image.ppm") noexcept { 30 | 31 | FILE* fp; 32 | 33 | fopen_s(&fp, fname, "w"); 34 | 35 | std::fprintf(fp, "P3\n%u %u\n%u\n", w, h, 255u); 36 | for (std::size_t i = 0; i < w * h; ++i) { 37 | std::fprintf(fp, "%u %u %u ", 38 | ToByte(Ls[i].m_x), 39 | ToByte(Ls[i].m_y), 40 | ToByte(Ls[i].m_z)); 41 | } 42 | 43 | std::fclose(fp); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /cpp-smallpt/Properties/x86_Debug.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x86\$(Configuration)\ 7 | $(ProjectName)\tmp\x86\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | 10 | 11 | 12 | Level4 13 | true 14 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 15 | true 16 | stdcpplatest 17 | $(ProjectName)\doc\ 18 | Fast 19 | 20 | 21 | MachineX86 22 | 23 | 24 | true 25 | Console 26 | 27 | 28 | $(ProjectName)\doc\$(TargetName).xml 29 | 30 | 31 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.156 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpp-smallpt", "cpp-smallpt.vcxproj", "{1F717F97-896D-4209-A4FD-CE11DB062C45}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x64.ActiveCfg = Debug|x64 17 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x64.Build.0 = Debug|x64 18 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x86.ActiveCfg = Debug|Win32 19 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x86.Build.0 = Debug|Win32 20 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x64.ActiveCfg = Release|x64 21 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x64.Build.0 = Release|x64 22 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x86.ActiveCfg = Release|Win32 23 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/imageio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // System Includes 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #include 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | inline void WritePPM(std::uint32_t w, 27 | std::uint32_t h, 28 | const Vector3* Ls, 29 | const char* fname = "openmp-cpp-image.ppm") noexcept { 30 | 31 | FILE* fp; 32 | 33 | fopen_s(&fp, fname, "w"); 34 | 35 | std::fprintf(fp, "P3\n%u %u\n%u\n", w, h, 255u); 36 | for (std::size_t i = 0; i < w * h; ++i) { 37 | std::fprintf(fp, "%u %u %u ", 38 | ToByte(Ls[i].m_x), 39 | ToByte(Ls[i].m_y), 40 | ToByte(Ls[i].m_z)); 41 | } 42 | 43 | std::fclose(fp); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/imageio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // System Includes 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #include 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | inline void WritePPM(std::uint32_t w, 27 | std::uint32_t h, 28 | const Vector3* Ls, 29 | const char* fname = "threads-cpp-image.ppm") noexcept { 30 | 31 | FILE* fp; 32 | 33 | fopen_s(&fp, fname, "w"); 34 | 35 | std::fprintf(fp, "P3\n%u %u\n%u\n", w, h, 255u); 36 | for (std::size_t i = 0; i < w * h; ++i) { 37 | std::fprintf(fp, "%u %u %u ", 38 | ToByte(Ls[i].m_x), 39 | ToByte(Ls[i].m_y), 40 | ToByte(Ls[i].m_z)); 41 | } 42 | 43 | std::fclose(fp); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.156 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpp-smallpt", "cpp-smallpt.vcxproj", "{1F717F97-896D-4209-A4FD-CE11DB062C45}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x64.ActiveCfg = Debug|x64 17 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x64.Build.0 = Debug|x64 18 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x86.ActiveCfg = Debug|Win32 19 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x86.Build.0 = Debug|Win32 20 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x64.ActiveCfg = Release|x64 21 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x64.Build.0 = Release|x64 22 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x86.ActiveCfg = Release|Win32 23 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/Properties/x86_Debug.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x86\$(Configuration)\ 7 | $(ProjectName)\tmp\x86\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | 10 | 11 | 12 | Level4 13 | true 14 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 15 | true 16 | stdcpplatest 17 | $(ProjectName)\doc\ 18 | Fast 19 | 20 | 21 | MachineX86 22 | 23 | 24 | true 25 | Console 26 | 27 | 28 | $(ProjectName)\doc\$(TargetName).xml 29 | 30 | 31 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.156 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpp-smallpt", "cpp-smallpt.vcxproj", "{1F717F97-896D-4209-A4FD-CE11DB062C45}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x64.ActiveCfg = Debug|x64 17 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x64.Build.0 = Debug|x64 18 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x86.ActiveCfg = Debug|Win32 19 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Debug|x86.Build.0 = Debug|Win32 20 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x64.ActiveCfg = Release|x64 21 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x64.Build.0 = Release|x64 22 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x86.ActiveCfg = Release|Win32 23 | {1F717F97-896D-4209-A4FD-CE11DB062C45}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/Properties/x86_Debug.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x86\$(Configuration)\ 7 | $(ProjectName)\tmp\x86\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | 10 | 11 | 12 | Level4 13 | true 14 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 15 | true 16 | stdcpplatest 17 | $(ProjectName)\doc\ 18 | Fast 19 | true 20 | 21 | 22 | MachineX86 23 | 24 | 25 | true 26 | Console 27 | 28 | 29 | $(ProjectName)\doc\$(TargetName).xml 30 | 31 | 32 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/sampling.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Declarations and Definitions 14 | //----------------------------------------------------------------------------- 15 | namespace smallpt { 16 | 17 | [[nodiscard]] 18 | inline const Vector3 UniformSampleOnSphere(double u1, 19 | double u2) noexcept { 20 | 21 | const double cos_theta = 1.0 - 2.0 * u1; 22 | const double sin_theta = std::sqrt(std::max(0.0, 1.0 - cos_theta * cos_theta)); 23 | const double phi = 2.0 * g_pi * u2; 24 | return { 25 | std::cos(phi) * sin_theta, 26 | std::sin(phi) * sin_theta, 27 | cos_theta 28 | }; 29 | } 30 | 31 | [[nodiscard]] 32 | inline const Vector3 UniformSampleOnHemisphere(double u1, 33 | double u2) noexcept { 34 | 35 | // u1 := cos_theta 36 | const double sin_theta = std::sqrt(std::max(0.0, 1.0 - u1 * u1)); 37 | const double phi = 2.0 * g_pi * u2; 38 | return { 39 | std::cos(phi) * sin_theta, 40 | std::sin(phi) * sin_theta, 41 | u1 42 | }; 43 | } 44 | 45 | [[nodiscard]] 46 | inline const Vector3 CosineWeightedSampleOnHemisphere(double u1, 47 | double u2) noexcept { 48 | 49 | const double cos_theta = sqrt(1.0 - u1); 50 | const double sin_theta = sqrt(u1); 51 | const double phi = 2.0 * g_pi * u2; 52 | return { 53 | std::cos(phi) * sin_theta, 54 | std::sin(phi) * sin_theta, 55 | cos_theta 56 | }; 57 | } 58 | } -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/sampling.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Declarations and Definitions 14 | //----------------------------------------------------------------------------- 15 | namespace smallpt { 16 | 17 | [[nodiscard]] 18 | inline const Vector3 UniformSampleOnSphere(double u1, 19 | double u2) noexcept { 20 | 21 | const double cos_theta = 1.0 - 2.0 * u1; 22 | const double sin_theta = std::sqrt(std::max(0.0, 1.0 - cos_theta * cos_theta)); 23 | const double phi = 2.0 * g_pi * u2; 24 | return { 25 | std::cos(phi) * sin_theta, 26 | std::sin(phi) * sin_theta, 27 | cos_theta 28 | }; 29 | } 30 | 31 | [[nodiscard]] 32 | inline const Vector3 UniformSampleOnHemisphere(double u1, 33 | double u2) noexcept { 34 | 35 | // u1 := cos_theta 36 | const double sin_theta = std::sqrt(std::max(0.0, 1.0 - u1 * u1)); 37 | const double phi = 2.0 * g_pi * u2; 38 | return { 39 | std::cos(phi) * sin_theta, 40 | std::sin(phi) * sin_theta, 41 | u1 42 | }; 43 | } 44 | 45 | [[nodiscard]] 46 | inline const Vector3 CosineWeightedSampleOnHemisphere(double u1, 47 | double u2) noexcept { 48 | 49 | const double cos_theta = sqrt(1.0 - u1); 50 | const double sin_theta = sqrt(u1); 51 | const double phi = 2.0 * g_pi * u2; 52 | return { 53 | std::cos(phi) * sin_theta, 54 | std::sin(phi) * sin_theta, 55 | cos_theta 56 | }; 57 | } 58 | } -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/sampling.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Declarations and Definitions 14 | //----------------------------------------------------------------------------- 15 | namespace smallpt { 16 | 17 | [[nodiscard]] 18 | inline const Vector3 UniformSampleOnSphere(double u1, 19 | double u2) noexcept { 20 | 21 | const double cos_theta = 1.0 - 2.0 * u1; 22 | const double sin_theta = std::sqrt(std::max(0.0, 1.0 - cos_theta * cos_theta)); 23 | const double phi = 2.0 * g_pi * u2; 24 | return { 25 | std::cos(phi) * sin_theta, 26 | std::sin(phi) * sin_theta, 27 | cos_theta 28 | }; 29 | } 30 | 31 | [[nodiscard]] 32 | inline const Vector3 UniformSampleOnHemisphere(double u1, 33 | double u2) noexcept { 34 | 35 | // u1 := cos_theta 36 | const double sin_theta = std::sqrt(std::max(0.0, 1.0 - u1 * u1)); 37 | const double phi = 2.0 * g_pi * u2; 38 | return { 39 | std::cos(phi) * sin_theta, 40 | std::sin(phi) * sin_theta, 41 | u1 42 | }; 43 | } 44 | 45 | [[nodiscard]] 46 | inline const Vector3 CosineWeightedSampleOnHemisphere(double u1, 47 | double u2) noexcept { 48 | 49 | const double cos_theta = sqrt(1.0 - u1); 50 | const double sin_theta = sqrt(u1); 51 | const double phi = 2.0 * g_pi * u2; 52 | return { 53 | std::cos(phi) * sin_theta, 54 | std::sin(phi) * sin_theta, 55 | cos_theta 56 | }; 57 | } 58 | } -------------------------------------------------------------------------------- /cpp-smallpt/Properties/x64_Release.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x64\$(Configuration)\ 7 | $(ProjectName)\tmp\x64\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | false 10 | 11 | 12 | 13 | Level4 14 | true 15 | Full 16 | AnySuitable 17 | true 18 | Speed 19 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 20 | true 21 | true 22 | stdcpplatest 23 | $(ProjectName)\doc\ 24 | Fast 25 | AdvancedVectorExtensions2 26 | 27 | 28 | true 29 | true 30 | true 31 | Console 32 | 33 | 34 | $(ProjectName)\doc\$(TargetName).xml 35 | 36 | 37 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/Properties/x64_Release.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x64\$(Configuration)\ 7 | $(ProjectName)\tmp\x64\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | false 10 | 11 | 12 | 13 | Level4 14 | true 15 | Full 16 | AnySuitable 17 | true 18 | Speed 19 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 20 | true 21 | true 22 | stdcpplatest 23 | $(ProjectName)\doc\ 24 | Fast 25 | AdvancedVectorExtensions2 26 | 27 | 28 | true 29 | true 30 | true 31 | Console 32 | 33 | 34 | $(ProjectName)\doc\$(TargetName).xml 35 | 36 | 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # User-Specific Files 3 | ############################################################################### 4 | *.suo 5 | *.user 6 | 7 | ############################################################################### 8 | # Intermediate Results 9 | ############################################################################### 10 | [Tt]emp/ 11 | [Tt]mp/ 12 | 13 | ############################################################################### 14 | # Build Results 15 | ############################################################################### 16 | [Dd]ebug/ 17 | [Rr]elease/ 18 | x64/ 19 | x86/ 20 | [Bb]in/ 21 | [Oo]bj/ 22 | [Ll]og/ 23 | 24 | ############################################################################### 25 | # Visual Studio Cache/Options Directory 26 | ############################################################################### 27 | .vs/ 28 | 29 | ############################################################################### 30 | # Visual Studio Cache Files 31 | ############################################################################### 32 | # files ending in .cache can be ignored 33 | *.[Cc]ache 34 | # but keep track of directories ending in .cache 35 | !*.[Cc]ache/ 36 | 37 | ############################################################################### 38 | # Visual C++ Cache Files 39 | ############################################################################### 40 | ipch/ 41 | *.aps 42 | *.cachefile 43 | *.ncb 44 | *.opendb 45 | *.opensdf 46 | *.sdf 47 | *.VC.db 48 | *.VC.VC.opendb 49 | 50 | ############################################################################### 51 | # Visual Studio Profiler 52 | ############################################################################### 53 | *.diagsession 54 | *.psess 55 | *.sap 56 | *.vsp 57 | *.vspx 58 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/Properties/x64_Release.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x64\$(Configuration)\ 7 | $(ProjectName)\tmp\x64\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | false 10 | 11 | 12 | 13 | Level4 14 | true 15 | Full 16 | AnySuitable 17 | true 18 | Speed 19 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 20 | true 21 | true 22 | stdcpplatest 23 | $(ProjectName)\doc\ 24 | Fast 25 | AdvancedVectorExtensions2 26 | true 27 | 28 | 29 | true 30 | true 31 | true 32 | Console 33 | 34 | 35 | $(ProjectName)\doc\$(TargetName).xml 36 | 37 | 38 | -------------------------------------------------------------------------------- /cpp-smallpt/Properties/x86_Release.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x86\$(Configuration)\ 7 | $(ProjectName)\tmp\x86\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | false 10 | 11 | 12 | 13 | Level4 14 | true 15 | Full 16 | AnySuitable 17 | true 18 | Speed 19 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 20 | true 21 | true 22 | stdcpplatest 23 | $(ProjectName)\doc\ 24 | Fast 25 | AdvancedVectorExtensions2 26 | 27 | 28 | MachineX86 29 | 30 | 31 | true 32 | true 33 | true 34 | Console 35 | 36 | 37 | $(ProjectName)\doc\$(TargetName).xml 38 | 39 | 40 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/Properties/x86_Release.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x86\$(Configuration)\ 7 | $(ProjectName)\tmp\x86\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | false 10 | 11 | 12 | 13 | Level4 14 | true 15 | Full 16 | AnySuitable 17 | true 18 | Speed 19 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 20 | true 21 | true 22 | stdcpplatest 23 | $(ProjectName)\doc\ 24 | Fast 25 | AdvancedVectorExtensions2 26 | 27 | 28 | MachineX86 29 | 30 | 31 | true 32 | true 33 | true 34 | Console 35 | 36 | 37 | $(ProjectName)\doc\$(TargetName).xml 38 | 39 | 40 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/Properties/x86_Release.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProjectName)\bin\x86\$(Configuration)\ 7 | $(ProjectName)\tmp\x86\$(Configuration)\ 8 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 9 | false 10 | 11 | 12 | 13 | Level4 14 | true 15 | Full 16 | AnySuitable 17 | true 18 | Speed 19 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 20 | true 21 | true 22 | stdcpplatest 23 | $(ProjectName)\doc\ 24 | Fast 25 | AdvancedVectorExtensions2 26 | true 27 | 28 | 29 | MachineX86 30 | 31 | 32 | true 33 | true 34 | true 35 | Console 36 | 37 | 38 | $(ProjectName)\doc\$(TargetName).xml 39 | 40 | 41 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Auto detect text files and perform LF normalization 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Explicitly declare CRLF normalization for the following files 8 | ############################################################################### 9 | 10 | # Header Files 11 | *.h text eol=crlf 12 | *.hpp text eol=crlf 13 | *.h++ text eol=crlf 14 | *.inc text eol=crlf 15 | *.inl text eol=crlf 16 | 17 | # Source Files 18 | *.c text eol=crlf 19 | *.cc text eol=crlf 20 | *.cpp text eol=crlf 21 | *.c++ text eol=crlf 22 | 23 | # Resource Files 24 | *.rc text eol=crlf 25 | 26 | ############################################################################### 27 | # Explicitly declare programming languages for the following files 28 | ############################################################################### 29 | 30 | # Header Files 31 | *.h linguist-language=C++ 32 | *.hpp linguist-language=C++ 33 | *.h++ linguist-language=C++ 34 | *.inc linguist-language=C++ 35 | *.inl linguist-language=C++ 36 | 37 | # Source Files 38 | *.c linguist-language=C 39 | *.cc linguist-language=C++ 40 | *.cpp linguist-language=C++ 41 | *.c++ linguist-language=C++ 42 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/rng.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include 9 | #include 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // Declarations and Definitions 15 | //----------------------------------------------------------------------------- 16 | namespace smallpt { 17 | 18 | class RNG { 19 | 20 | public: 21 | 22 | //--------------------------------------------------------------------- 23 | // Constructors and Destructors 24 | //--------------------------------------------------------------------- 25 | 26 | explicit RNG(std::uint32_t seed = 606418532u) noexcept 27 | : m_generator(), 28 | m_distribution() { 29 | 30 | Seed(seed); 31 | } 32 | RNG(const RNG &rng) noexcept = default; 33 | RNG(RNG &&rng) noexcept = default; 34 | ~RNG() = default; 35 | 36 | //--------------------------------------------------------------------- 37 | // Assignment Operators 38 | //--------------------------------------------------------------------- 39 | 40 | RNG &operator=(const RNG &rng) = delete; 41 | RNG &operator=(RNG &&rng) = delete; 42 | 43 | //--------------------------------------------------------------------- 44 | // Member Methods 45 | //--------------------------------------------------------------------- 46 | 47 | void Seed(uint32_t seed) noexcept { 48 | m_generator.seed(seed); 49 | } 50 | 51 | double Uniform() noexcept { 52 | return m_distribution(m_generator); 53 | } 54 | 55 | private: 56 | 57 | //--------------------------------------------------------------------- 58 | // Member Variables 59 | //--------------------------------------------------------------------- 60 | 61 | std::default_random_engine m_generator; 62 | std::uniform_real_distribution< double > m_distribution; 63 | }; 64 | } -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;tpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {7e28e46c-79a8-40f5-bea9-3672b61de19b} 14 | 15 | 16 | {48732053-90d6-41a6-922b-62a6714b1f94} 17 | 18 | 19 | 20 | 21 | Header Files\src 22 | 23 | 24 | Header Files\src 25 | 26 | 27 | Header Files\src 28 | 29 | 30 | Header Files\src 31 | 32 | 33 | Header Files\src 34 | 35 | 36 | Header Files\src 37 | 38 | 39 | Header Files\src 40 | 41 | 42 | Header Files\src 43 | 44 | 45 | 46 | 47 | Source Files\src 48 | 49 | 50 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;tpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {7e28e46c-79a8-40f5-bea9-3672b61de19b} 14 | 15 | 16 | {48732053-90d6-41a6-922b-62a6714b1f94} 17 | 18 | 19 | 20 | 21 | Header Files\src 22 | 23 | 24 | Header Files\src 25 | 26 | 27 | Header Files\src 28 | 29 | 30 | Header Files\src 31 | 32 | 33 | Header Files\src 34 | 35 | 36 | Header Files\src 37 | 38 | 39 | Header Files\src 40 | 41 | 42 | Header Files\src 43 | 44 | 45 | 46 | 47 | Source Files\src 48 | 49 | 50 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/rng.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include 9 | #include 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // Declarations and Definitions 15 | //----------------------------------------------------------------------------- 16 | namespace smallpt { 17 | 18 | class RNG { 19 | 20 | public: 21 | 22 | //--------------------------------------------------------------------- 23 | // Constructors and Destructors 24 | //--------------------------------------------------------------------- 25 | 26 | explicit RNG(std::uint32_t seed = 606418532u) noexcept 27 | : m_generator(), 28 | m_distribution() { 29 | 30 | Seed(seed); 31 | } 32 | RNG(const RNG &rng) noexcept = default; 33 | RNG(RNG &&rng) noexcept = default; 34 | ~RNG() = default; 35 | 36 | //--------------------------------------------------------------------- 37 | // Assignment Operators 38 | //--------------------------------------------------------------------- 39 | 40 | RNG &operator=(const RNG &rng) = delete; 41 | RNG &operator=(RNG &&rng) = delete; 42 | 43 | //--------------------------------------------------------------------- 44 | // Member Methods 45 | //--------------------------------------------------------------------- 46 | 47 | void Seed(uint32_t seed) noexcept { 48 | m_generator.seed(seed); 49 | } 50 | 51 | double Uniform() noexcept { 52 | return m_distribution(m_generator); 53 | } 54 | 55 | private: 56 | 57 | //--------------------------------------------------------------------- 58 | // Member Variables 59 | //--------------------------------------------------------------------- 60 | 61 | std::default_random_engine m_generator; 62 | std::uniform_real_distribution< double > m_distribution; 63 | }; 64 | } -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/rng.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include 9 | #include 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // Declarations and Definitions 15 | //----------------------------------------------------------------------------- 16 | namespace smallpt { 17 | 18 | class RNG { 19 | 20 | public: 21 | 22 | //--------------------------------------------------------------------- 23 | // Constructors and Destructors 24 | //--------------------------------------------------------------------- 25 | 26 | explicit RNG(std::uint32_t seed = 606418532u) noexcept 27 | : m_generator(), 28 | m_distribution() { 29 | 30 | Seed(seed); 31 | } 32 | RNG(const RNG &rng) noexcept = default; 33 | RNG(RNG &&rng) noexcept = default; 34 | ~RNG() = default; 35 | 36 | //--------------------------------------------------------------------- 37 | // Assignment Operators 38 | //--------------------------------------------------------------------- 39 | 40 | RNG &operator=(const RNG &rng) = delete; 41 | RNG &operator=(RNG &&rng) = delete; 42 | 43 | //--------------------------------------------------------------------- 44 | // Member Methods 45 | //--------------------------------------------------------------------- 46 | 47 | void Seed(uint32_t seed) noexcept { 48 | m_generator.seed(seed); 49 | } 50 | 51 | double Uniform() noexcept { 52 | return m_distribution(m_generator); 53 | } 54 | 55 | private: 56 | 57 | //--------------------------------------------------------------------- 58 | // Member Variables 59 | //--------------------------------------------------------------------- 60 | 61 | std::default_random_engine m_generator; 62 | std::uniform_real_distribution< double > m_distribution; 63 | }; 64 | } -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/geometry.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Declarations and Definitions 14 | //----------------------------------------------------------------------------- 15 | namespace smallpt { 16 | 17 | struct Ray { 18 | 19 | public: 20 | 21 | //--------------------------------------------------------------------- 22 | // Constructors and Destructors 23 | //--------------------------------------------------------------------- 24 | 25 | constexpr explicit Ray(Vector3 o, 26 | Vector3 d, 27 | double tmin = 0.0, 28 | double tmax = std::numeric_limits< double >::infinity(), 29 | std::uint32_t depth = 0u) noexcept 30 | : m_o(std::move(o)), 31 | m_d(std::move(d)), 32 | m_tmin(tmin), 33 | m_tmax(tmax), 34 | m_depth(depth) {}; 35 | constexpr Ray(const Ray& ray) noexcept = default; 36 | constexpr Ray(Ray&& ray) noexcept = default; 37 | ~Ray() = default; 38 | 39 | //--------------------------------------------------------------------- 40 | // Assignment Operators 41 | //--------------------------------------------------------------------- 42 | 43 | Ray& operator=(const Ray& ray) = default; 44 | Ray& operator=(Ray&& ray) = default; 45 | 46 | //--------------------------------------------------------------------- 47 | // Member Methods 48 | //--------------------------------------------------------------------- 49 | 50 | [[nodiscard]] 51 | constexpr const Vector3 operator()(double t) const noexcept { 52 | return m_o + m_d * t; 53 | } 54 | 55 | //--------------------------------------------------------------------- 56 | // Member Variables 57 | //--------------------------------------------------------------------- 58 | 59 | Vector3 m_o, m_d; 60 | mutable double m_tmin, m_tmax; 61 | std::uint32_t m_depth; 62 | }; 63 | 64 | inline std::ostream &operator<<(std::ostream& os, const Ray& r) { 65 | os << "o: " << r.m_o << std::endl; 66 | os << "d: " << r.m_d << std::endl; 67 | return os; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/geometry.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Declarations and Definitions 14 | //----------------------------------------------------------------------------- 15 | namespace smallpt { 16 | 17 | struct Ray { 18 | 19 | public: 20 | 21 | //--------------------------------------------------------------------- 22 | // Constructors and Destructors 23 | //--------------------------------------------------------------------- 24 | 25 | constexpr explicit Ray(Vector3 o, 26 | Vector3 d, 27 | double tmin = 0.0, 28 | double tmax = std::numeric_limits< double >::infinity(), 29 | std::uint32_t depth = 0u) noexcept 30 | : m_o(std::move(o)), 31 | m_d(std::move(d)), 32 | m_tmin(tmin), 33 | m_tmax(tmax), 34 | m_depth(depth) {}; 35 | constexpr Ray(const Ray& ray) noexcept = default; 36 | constexpr Ray(Ray&& ray) noexcept = default; 37 | ~Ray() = default; 38 | 39 | //--------------------------------------------------------------------- 40 | // Assignment Operators 41 | //--------------------------------------------------------------------- 42 | 43 | Ray& operator=(const Ray& ray) = default; 44 | Ray& operator=(Ray&& ray) = default; 45 | 46 | //--------------------------------------------------------------------- 47 | // Member Methods 48 | //--------------------------------------------------------------------- 49 | 50 | [[nodiscard]] 51 | constexpr const Vector3 operator()(double t) const noexcept { 52 | return m_o + m_d * t; 53 | } 54 | 55 | //--------------------------------------------------------------------- 56 | // Member Variables 57 | //--------------------------------------------------------------------- 58 | 59 | Vector3 m_o, m_d; 60 | mutable double m_tmin, m_tmax; 61 | std::uint32_t m_depth; 62 | }; 63 | 64 | inline std::ostream &operator<<(std::ostream& os, const Ray& r) { 65 | os << "o: " << r.m_o << std::endl; 66 | os << "d: " << r.m_d << std::endl; 67 | return os; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/geometry.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "vector.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Declarations and Definitions 14 | //----------------------------------------------------------------------------- 15 | namespace smallpt { 16 | 17 | struct Ray { 18 | 19 | public: 20 | 21 | //--------------------------------------------------------------------- 22 | // Constructors and Destructors 23 | //--------------------------------------------------------------------- 24 | 25 | constexpr explicit Ray(Vector3 o, 26 | Vector3 d, 27 | double tmin = 0.0, 28 | double tmax = std::numeric_limits< double >::infinity(), 29 | std::uint32_t depth = 0u) noexcept 30 | : m_o(std::move(o)), 31 | m_d(std::move(d)), 32 | m_tmin(tmin), 33 | m_tmax(tmax), 34 | m_depth(depth) {}; 35 | constexpr Ray(const Ray& ray) noexcept = default; 36 | constexpr Ray(Ray&& ray) noexcept = default; 37 | ~Ray() = default; 38 | 39 | //--------------------------------------------------------------------- 40 | // Assignment Operators 41 | //--------------------------------------------------------------------- 42 | 43 | Ray& operator=(const Ray& ray) = default; 44 | Ray& operator=(Ray&& ray) = default; 45 | 46 | //--------------------------------------------------------------------- 47 | // Member Methods 48 | //--------------------------------------------------------------------- 49 | 50 | [[nodiscard]] 51 | constexpr const Vector3 operator()(double t) const noexcept { 52 | return m_o + m_d * t; 53 | } 54 | 55 | //--------------------------------------------------------------------- 56 | // Member Variables 57 | //--------------------------------------------------------------------- 58 | 59 | Vector3 m_o, m_d; 60 | mutable double m_tmin, m_tmax; 61 | std::uint32_t m_depth; 62 | }; 63 | 64 | inline std::ostream &operator<<(std::ostream& os, const Ray& r) { 65 | os << "o: " << r.m_o << std::endl; 66 | os << "d: " << r.m_d << std::endl; 67 | return os; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/specular.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "rng.hpp" 9 | #include "vector.hpp" 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // Declarations and Definitions 15 | //----------------------------------------------------------------------------- 16 | namespace smallpt { 17 | 18 | [[nodiscard]] 19 | constexpr double Reflectance0(double n1, double n2) noexcept { 20 | const double sqrt_R0 = (n1 - n2) / (n1 + n2); 21 | return sqrt_R0 * sqrt_R0; 22 | } 23 | 24 | [[nodiscard]] 25 | constexpr double SchlickReflectance(double n1, double n2, double c) noexcept { 26 | const double R0 = Reflectance0(n1, n2); 27 | return R0 + (1.0 - R0) * c * c * c * c * c; 28 | } 29 | 30 | [[nodiscard]] 31 | constexpr const Vector3 IdealSpecularReflect(const Vector3& d, 32 | const Vector3& n) noexcept { 33 | return d - 2.0 * n.Dot(d) * n; 34 | } 35 | 36 | [[nodiscard]] 37 | inline const Vector3 IdealSpecularTransmit(const Vector3& d, 38 | const Vector3& n, 39 | double n_out, 40 | double n_in, 41 | double& pr, 42 | RNG& rng) noexcept { 43 | 44 | const Vector3 d_Re = IdealSpecularReflect(d, n); 45 | 46 | const bool out_to_in = (0.0 > n.Dot(d)); 47 | const Vector3 nl = out_to_in ? n : -n; 48 | const double nn = out_to_in ? n_out / n_in : n_in / n_out; 49 | const double cos_theta = d.Dot(nl); 50 | const double cos2_phi = 1.0 - nn * nn * (1.0 - cos_theta * cos_theta); 51 | 52 | // Total Internal Reflection 53 | if (0.0 > cos2_phi) { 54 | pr = 1.0; 55 | return d_Re; 56 | } 57 | 58 | const Vector3 d_Tr = Normalize(nn * d - nl * (nn * cos_theta + sqrt(cos2_phi))); 59 | const double c = 1.0 - (out_to_in ? -cos_theta : d_Tr.Dot(n)); 60 | 61 | const double Re = SchlickReflectance(n_out, n_in, c); 62 | const double p_Re = 0.25 + 0.5 * Re; 63 | if (rng.Uniform() < p_Re) { 64 | pr = (Re / p_Re); 65 | return d_Re; 66 | } 67 | else { 68 | const double Tr = 1.0 - Re; 69 | const double p_Tr = 1.0 - p_Re; 70 | pr = (Tr / p_Tr); 71 | return d_Tr; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/specular.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "rng.hpp" 9 | #include "vector.hpp" 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // Declarations and Definitions 15 | //----------------------------------------------------------------------------- 16 | namespace smallpt { 17 | 18 | [[nodiscard]] 19 | constexpr double Reflectance0(double n1, double n2) noexcept { 20 | const double sqrt_R0 = (n1 - n2) / (n1 + n2); 21 | return sqrt_R0 * sqrt_R0; 22 | } 23 | 24 | [[nodiscard]] 25 | constexpr double SchlickReflectance(double n1, double n2, double c) noexcept { 26 | const double R0 = Reflectance0(n1, n2); 27 | return R0 + (1.0 - R0) * c * c * c * c * c; 28 | } 29 | 30 | [[nodiscard]] 31 | constexpr const Vector3 IdealSpecularReflect(const Vector3& d, 32 | const Vector3& n) noexcept { 33 | return d - 2.0 * n.Dot(d) * n; 34 | } 35 | 36 | [[nodiscard]] 37 | inline const Vector3 IdealSpecularTransmit(const Vector3& d, 38 | const Vector3& n, 39 | double n_out, 40 | double n_in, 41 | double& pr, 42 | RNG& rng) noexcept { 43 | 44 | const Vector3 d_Re = IdealSpecularReflect(d, n); 45 | 46 | const bool out_to_in = (0.0 > n.Dot(d)); 47 | const Vector3 nl = out_to_in ? n : -n; 48 | const double nn = out_to_in ? n_out / n_in : n_in / n_out; 49 | const double cos_theta = d.Dot(nl); 50 | const double cos2_phi = 1.0 - nn * nn * (1.0 - cos_theta * cos_theta); 51 | 52 | // Total Internal Reflection 53 | if (0.0 > cos2_phi) { 54 | pr = 1.0; 55 | return d_Re; 56 | } 57 | 58 | const Vector3 d_Tr = Normalize(nn * d - nl * (nn * cos_theta + sqrt(cos2_phi))); 59 | const double c = 1.0 - (out_to_in ? -cos_theta : d_Tr.Dot(n)); 60 | 61 | const double Re = SchlickReflectance(n_out, n_in, c); 62 | const double p_Re = 0.25 + 0.5 * Re; 63 | if (rng.Uniform() < p_Re) { 64 | pr = (Re / p_Re); 65 | return d_Re; 66 | } 67 | else { 68 | const double Tr = 1.0 - Re; 69 | const double p_Tr = 1.0 - p_Re; 70 | pr = (Tr / p_Tr); 71 | return d_Tr; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/specular.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "rng.hpp" 9 | #include "vector.hpp" 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // Declarations and Definitions 15 | //----------------------------------------------------------------------------- 16 | namespace smallpt { 17 | 18 | [[nodiscard]] 19 | constexpr double Reflectance0(double n1, double n2) noexcept { 20 | const double sqrt_R0 = (n1 - n2) / (n1 + n2); 21 | return sqrt_R0 * sqrt_R0; 22 | } 23 | 24 | [[nodiscard]] 25 | constexpr double SchlickReflectance(double n1, double n2, double c) noexcept { 26 | const double R0 = Reflectance0(n1, n2); 27 | return R0 + (1.0 - R0) * c * c * c * c * c; 28 | } 29 | 30 | [[nodiscard]] 31 | constexpr const Vector3 IdealSpecularReflect(const Vector3& d, 32 | const Vector3& n) noexcept { 33 | return d - 2.0 * n.Dot(d) * n; 34 | } 35 | 36 | [[nodiscard]] 37 | inline const Vector3 IdealSpecularTransmit(const Vector3& d, 38 | const Vector3& n, 39 | double n_out, 40 | double n_in, 41 | double& pr, 42 | RNG& rng) noexcept { 43 | 44 | const Vector3 d_Re = IdealSpecularReflect(d, n); 45 | 46 | const bool out_to_in = (0.0 > n.Dot(d)); 47 | const Vector3 nl = out_to_in ? n : -n; 48 | const double nn = out_to_in ? n_out / n_in : n_in / n_out; 49 | const double cos_theta = d.Dot(nl); 50 | const double cos2_phi = 1.0 - nn * nn * (1.0 - cos_theta * cos_theta); 51 | 52 | // Total Internal Reflection 53 | if (0.0 > cos2_phi) { 54 | pr = 1.0; 55 | return d_Re; 56 | } 57 | 58 | const Vector3 d_Tr = Normalize(nn * d - nl * (nn * cos_theta + sqrt(cos2_phi))); 59 | const double c = 1.0 - (out_to_in ? -cos_theta : d_Tr.Dot(n)); 60 | 61 | const double Re = SchlickReflectance(n_out, n_in, c); 62 | const double p_Re = 0.25 + 0.5 * Re; 63 | if (rng.Uniform() < p_Re) { 64 | pr = (Re / p_Re); 65 | return d_Re; 66 | } 67 | else { 68 | const double Tr = 1.0 - Re; 69 | const double p_Tr = 1.0 - p_Re; 70 | pr = (Tr / p_Tr); 71 | return d_Tr; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;tpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {7e28e46c-79a8-40f5-bea9-3672b61de19b} 14 | 15 | 16 | {48732053-90d6-41a6-922b-62a6714b1f94} 17 | 18 | 19 | 20 | 21 | Header Files\src 22 | 23 | 24 | Header Files\src 25 | 26 | 27 | Header Files\src 28 | 29 | 30 | Header Files\src 31 | 32 | 33 | Header Files\src 34 | 35 | 36 | Header Files\src 37 | 38 | 39 | Header Files\src 40 | 41 | 42 | Header Files\src 43 | 44 | 45 | Header Files\src 46 | 47 | 48 | Header Files\src 49 | 50 | 51 | Header Files\src 52 | 53 | 54 | Header Files\src 55 | 56 | 57 | 58 | 59 | Source Files\src 60 | 61 | 62 | Source Files\src 63 | 64 | 65 | Source Files\src 66 | 67 | 68 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/task.cpp: -------------------------------------------------------------------------------- 1 | #include "lock.hpp" 2 | #include "task.hpp" 3 | 4 | namespace smallpt { 5 | 6 | static HANDLE* s_threads; 7 | static Mutex s_s_task_queue_mutex; 8 | static std::vector< Task* > s_task_queue; 9 | static Semaphore* s_worker_semaphore; 10 | static size_t s_nb_unfinished_tasks; 11 | static ConditionVariable* s_tasks_running_condition; 12 | 13 | static DWORD WINAPI task_entry([[maybe_unused]] LPVOID lpParameter) { 14 | while (true) { 15 | s_worker_semaphore->Wait(); 16 | 17 | Task* task = nullptr; 18 | { 19 | MutexLock lock(s_s_task_queue_mutex); 20 | if (s_task_queue.empty()) { 21 | break; 22 | } 23 | task = s_task_queue.back(); 24 | s_task_queue.pop_back(); 25 | } 26 | 27 | task->Run(); 28 | 29 | s_tasks_running_condition->Lock(); 30 | --s_nb_unfinished_tasks; 31 | if (0u == s_nb_unfinished_tasks) { 32 | s_tasks_running_condition->Signal(); 33 | } 34 | s_tasks_running_condition->Unlock(); 35 | } 36 | return 0; 37 | } 38 | 39 | void TasksInit() { 40 | static const std::size_t nb_s_threads = NumberOfSystemCores(); 41 | s_worker_semaphore = new Semaphore(); 42 | s_tasks_running_condition = new ConditionVariable(); 43 | 44 | s_threads = new HANDLE[nb_s_threads]; 45 | for (std::size_t i = 0u; i < nb_s_threads; ++i) { 46 | s_threads[i] = CreateThread(nullptr, 0, task_entry, reinterpret_cast< void * >(i), 0, nullptr); 47 | } 48 | } 49 | 50 | void TasksCleanup() { 51 | if (!s_worker_semaphore) { 52 | return; 53 | } 54 | 55 | static const std::size_t nb_s_threads = NumberOfSystemCores(); 56 | if (s_worker_semaphore) { 57 | s_worker_semaphore->Signal(static_cast(nb_s_threads)); 58 | } 59 | 60 | if (s_threads) { 61 | WaitForMultipleObjects(static_cast< DWORD >(nb_s_threads), s_threads, TRUE, INFINITE); 62 | 63 | for (std::size_t i = 0u; i < nb_s_threads; ++i) { 64 | CloseHandle(s_threads[i]); 65 | } 66 | 67 | delete[] s_threads; 68 | s_threads = nullptr; 69 | } 70 | } 71 | 72 | void EnqueueTasks(const std::vector< Task* >& tasks) { 73 | if (!s_threads) { 74 | TasksInit(); 75 | } 76 | 77 | { 78 | MutexLock lock(s_s_task_queue_mutex); 79 | for (std::size_t i = 0u; i < tasks.size(); ++i) { 80 | s_task_queue.push_back(tasks[i]); 81 | } 82 | } 83 | 84 | s_tasks_running_condition->Lock(); 85 | s_nb_unfinished_tasks += tasks.size(); 86 | s_tasks_running_condition->Unlock(); 87 | 88 | s_worker_semaphore->Signal(static_cast(tasks.size())); 89 | } 90 | 91 | void WaitForAllTasks() { 92 | if (!s_tasks_running_condition) { 93 | return; 94 | } 95 | 96 | s_tasks_running_condition->Lock(); 97 | while (0u < s_nb_unfinished_tasks) { 98 | s_tasks_running_condition->Wait(); 99 | } 100 | s_tasks_running_condition->Unlock(); 101 | } 102 | }; -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/sphere.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "geometry.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Defines 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #define EPSILON_SPHERE 1e-4 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | //------------------------------------------------------------------------- 27 | // Declarations and Definitions: Reflection_t 28 | //------------------------------------------------------------------------- 29 | 30 | enum struct Reflection_t : std::uint8_t { 31 | Diffuse = 0u, 32 | Specular, 33 | Refractive 34 | }; 35 | 36 | //------------------------------------------------------------------------- 37 | // Declarations and Definitions: Sphere 38 | //------------------------------------------------------------------------- 39 | 40 | struct Sphere { 41 | 42 | //--------------------------------------------------------------------- 43 | // Constructors and Destructors 44 | //--------------------------------------------------------------------- 45 | 46 | constexpr explicit Sphere(double r, 47 | Vector3 p, 48 | Vector3 e, 49 | Vector3 f, 50 | Reflection_t reflection_t) noexcept 51 | : m_r(r), 52 | m_p(std::move(p)), 53 | m_e(std::move(e)), 54 | m_f(std::move(f)), 55 | m_reflection_t(reflection_t) {} 56 | constexpr Sphere(const Sphere& sphere) noexcept = default; 57 | constexpr Sphere(Sphere&& sphere) noexcept = default; 58 | ~Sphere() = default; 59 | 60 | //--------------------------------------------------------------------- 61 | // Assignment Operators 62 | //--------------------------------------------------------------------- 63 | 64 | Sphere& operator=(const Sphere& sphere) = default; 65 | Sphere& operator=(Sphere&& sphere) = default; 66 | 67 | //--------------------------------------------------------------------- 68 | // Member Methods 69 | //--------------------------------------------------------------------- 70 | 71 | [[nodiscard]] 72 | constexpr bool Intersect(const Ray& ray) const noexcept { 73 | // (o + t*d - p) . (o + t*d - p) - r*r = 0 74 | // <=> (d . d) * t^2 + 2 * d . (o - p) * t + (o - p) . (o - p) - r*r = 0 75 | // 76 | // Discriminant check 77 | // (2 * d . (o - p))^2 - 4 * (d . d) * ((o - p) . (o - p) - r*r) (d . (o - p))^2 - (d . d) * ((o - p) . (o - p) - r*r) (d . op)^2 - 1 * (op . op - r*r) b^2 - (op . op) + r*r D t = dop +- sqrt(D) 86 | 87 | const Vector3 op = m_p - ray.m_o; 88 | const double dop = ray.m_d.Dot(op); 89 | const double D = dop * dop - op.Dot(op) + m_r * m_r; 90 | 91 | if (0.0 > D) { 92 | return false; 93 | } 94 | 95 | const double sqrtD = sqrt(D); 96 | 97 | const double tmin = dop - sqrtD; 98 | if (ray.m_tmin < tmin && tmin < ray.m_tmax) { 99 | ray.m_tmax = tmin; 100 | return true; 101 | } 102 | 103 | const double tmax = dop + sqrtD; 104 | if (ray.m_tmin < tmax && tmax < ray.m_tmax) { 105 | ray.m_tmax = tmax; 106 | return true; 107 | } 108 | 109 | return false; 110 | } 111 | 112 | //--------------------------------------------------------------------- 113 | // Member Variables 114 | //--------------------------------------------------------------------- 115 | 116 | double m_r; 117 | Vector3 m_p; // position 118 | Vector3 m_e; // emission 119 | Vector3 m_f; // reflection 120 | Reflection_t m_reflection_t; 121 | }; 122 | } 123 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/sphere.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "geometry.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Defines 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #define EPSILON_SPHERE 1e-4 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | //------------------------------------------------------------------------- 27 | // Declarations and Definitions: Reflection_t 28 | //------------------------------------------------------------------------- 29 | 30 | enum struct Reflection_t : std::uint8_t { 31 | Diffuse = 0u, 32 | Specular, 33 | Refractive 34 | }; 35 | 36 | //------------------------------------------------------------------------- 37 | // Declarations and Definitions: Sphere 38 | //------------------------------------------------------------------------- 39 | 40 | struct Sphere { 41 | 42 | //--------------------------------------------------------------------- 43 | // Constructors and Destructors 44 | //--------------------------------------------------------------------- 45 | 46 | constexpr explicit Sphere(double r, 47 | Vector3 p, 48 | Vector3 e, 49 | Vector3 f, 50 | Reflection_t reflection_t) noexcept 51 | : m_r(r), 52 | m_p(std::move(p)), 53 | m_e(std::move(e)), 54 | m_f(std::move(f)), 55 | m_reflection_t(reflection_t) {} 56 | constexpr Sphere(const Sphere& sphere) noexcept = default; 57 | constexpr Sphere(Sphere&& sphere) noexcept = default; 58 | ~Sphere() = default; 59 | 60 | //--------------------------------------------------------------------- 61 | // Assignment Operators 62 | //--------------------------------------------------------------------- 63 | 64 | Sphere& operator=(const Sphere& sphere) = default; 65 | Sphere& operator=(Sphere&& sphere) = default; 66 | 67 | //--------------------------------------------------------------------- 68 | // Member Methods 69 | //--------------------------------------------------------------------- 70 | 71 | [[nodiscard]] 72 | constexpr bool Intersect(const Ray& ray) const noexcept { 73 | // (o + t*d - p) . (o + t*d - p) - r*r = 0 74 | // <=> (d . d) * t^2 + 2 * d . (o - p) * t + (o - p) . (o - p) - r*r = 0 75 | // 76 | // Discriminant check 77 | // (2 * d . (o - p))^2 - 4 * (d . d) * ((o - p) . (o - p) - r*r) (d . (o - p))^2 - (d . d) * ((o - p) . (o - p) - r*r) (d . op)^2 - 1 * (op . op - r*r) b^2 - (op . op) + r*r D t = dop +- sqrt(D) 86 | 87 | const Vector3 op = m_p - ray.m_o; 88 | const double dop = ray.m_d.Dot(op); 89 | const double D = dop * dop - op.Dot(op) + m_r * m_r; 90 | 91 | if (0.0 > D) { 92 | return false; 93 | } 94 | 95 | const double sqrtD = sqrt(D); 96 | 97 | const double tmin = dop - sqrtD; 98 | if (ray.m_tmin < tmin && tmin < ray.m_tmax) { 99 | ray.m_tmax = tmin; 100 | return true; 101 | } 102 | 103 | const double tmax = dop + sqrtD; 104 | if (ray.m_tmin < tmax && tmax < ray.m_tmax) { 105 | ray.m_tmax = tmax; 106 | return true; 107 | } 108 | 109 | return false; 110 | } 111 | 112 | //--------------------------------------------------------------------- 113 | // Member Variables 114 | //--------------------------------------------------------------------- 115 | 116 | double m_r; 117 | Vector3 m_p; // position 118 | Vector3 m_e; // emission 119 | Vector3 m_f; // reflection 120 | Reflection_t m_reflection_t; 121 | }; 122 | } 123 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/sphere.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "geometry.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // Defines 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #define EPSILON_SPHERE 1e-4 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | //------------------------------------------------------------------------- 27 | // Declarations and Definitions: Reflection_t 28 | //------------------------------------------------------------------------- 29 | 30 | enum struct Reflection_t : std::uint8_t { 31 | Diffuse = 0u, 32 | Specular, 33 | Refractive 34 | }; 35 | 36 | //------------------------------------------------------------------------- 37 | // Declarations and Definitions: Sphere 38 | //------------------------------------------------------------------------- 39 | 40 | struct Sphere { 41 | 42 | //--------------------------------------------------------------------- 43 | // Constructors and Destructors 44 | //--------------------------------------------------------------------- 45 | 46 | constexpr explicit Sphere(double r, 47 | Vector3 p, 48 | Vector3 e, 49 | Vector3 f, 50 | Reflection_t reflection_t) noexcept 51 | : m_r(r), 52 | m_p(std::move(p)), 53 | m_e(std::move(e)), 54 | m_f(std::move(f)), 55 | m_reflection_t(reflection_t) {} 56 | constexpr Sphere(const Sphere& sphere) noexcept = default; 57 | constexpr Sphere(Sphere&& sphere) noexcept = default; 58 | ~Sphere() = default; 59 | 60 | //--------------------------------------------------------------------- 61 | // Assignment Operators 62 | //--------------------------------------------------------------------- 63 | 64 | Sphere& operator=(const Sphere& sphere) = default; 65 | Sphere& operator=(Sphere&& sphere) = default; 66 | 67 | //--------------------------------------------------------------------- 68 | // Member Methods 69 | //--------------------------------------------------------------------- 70 | 71 | [[nodiscard]] 72 | constexpr bool Intersect(const Ray& ray) const noexcept { 73 | // (o + t*d - p) . (o + t*d - p) - r*r = 0 74 | // <=> (d . d) * t^2 + 2 * d . (o - p) * t + (o - p) . (o - p) - r*r = 0 75 | // 76 | // Discriminant check 77 | // (2 * d . (o - p))^2 - 4 * (d . d) * ((o - p) . (o - p) - r*r) (d . (o - p))^2 - (d . d) * ((o - p) . (o - p) - r*r) (d . op)^2 - 1 * (op . op - r*r) b^2 - (op . op) + r*r D t = dop +- sqrt(D) 86 | 87 | const Vector3 op = m_p - ray.m_o; 88 | const double dop = ray.m_d.Dot(op); 89 | const double D = dop * dop - op.Dot(op) + m_r * m_r; 90 | 91 | if (0.0 > D) { 92 | return false; 93 | } 94 | 95 | const double sqrtD = sqrt(D); 96 | 97 | const double tmin = dop - sqrtD; 98 | if (ray.m_tmin < tmin && tmin < ray.m_tmax) { 99 | ray.m_tmax = tmin; 100 | return true; 101 | } 102 | 103 | const double tmax = dop + sqrtD; 104 | if (ray.m_tmin < tmax && tmax < ray.m_tmax) { 105 | ray.m_tmax = tmax; 106 | return true; 107 | } 108 | 109 | return false; 110 | } 111 | 112 | //--------------------------------------------------------------------- 113 | // Member Variables 114 | //--------------------------------------------------------------------- 115 | 116 | double m_r; 117 | Vector3 m_p; // position 118 | Vector3 m_e; // emission 119 | Vector3 m_f; // reflection 120 | Reflection_t m_reflection_t; 121 | }; 122 | } 123 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {1F717F97-896D-4209-A4FD-CE11DB062C45} 36 | Win32Proj 37 | cppsmallpt 38 | 10.0.17763.0 39 | 40 | 41 | 42 | Application 43 | true 44 | v142 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | Application 56 | true 57 | v142 58 | Unicode 59 | 60 | 61 | Application 62 | false 63 | v142 64 | true 65 | Unicode 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 91 | $(VC_SourcePath); 92 | 93 | 94 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 95 | $(VC_SourcePath); 96 | 97 | 98 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 99 | $(VC_SourcePath); 100 | 101 | 102 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 103 | $(VC_SourcePath); 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | {1F717F97-896D-4209-A4FD-CE11DB062C45} 42 | Win32Proj 43 | cppsmallpt 44 | 10.0.17763.0 45 | 46 | 47 | 48 | Application 49 | true 50 | v142 51 | Unicode 52 | 53 | 54 | Application 55 | false 56 | v142 57 | true 58 | Unicode 59 | 60 | 61 | Application 62 | true 63 | v142 64 | Unicode 65 | 66 | 67 | Application 68 | false 69 | v142 70 | true 71 | Unicode 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 97 | $(VC_SourcePath); 98 | 99 | 100 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 101 | $(VC_SourcePath); 102 | 103 | 104 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 105 | $(VC_SourcePath); 106 | 107 | 108 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 109 | $(VC_SourcePath); 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/cpp-smallpt.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // Includes 3 | //----------------------------------------------------------------------------- 4 | #pragma region 5 | 6 | #include "imageio.hpp" 7 | #include "sampling.hpp" 8 | #include "specular.hpp" 9 | #include "sphere.hpp" 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // System Includes 15 | //----------------------------------------------------------------------------- 16 | #pragma region 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #pragma endregion 23 | 24 | //----------------------------------------------------------------------------- 25 | // Defines 26 | //----------------------------------------------------------------------------- 27 | #pragma region 28 | 29 | #define REFRACTIVE_INDEX_OUT 1.0 30 | #define REFRACTIVE_INDEX_IN 1.5 31 | 32 | #pragma endregion 33 | 34 | //----------------------------------------------------------------------------- 35 | // Declarations and Definitions 36 | //----------------------------------------------------------------------------- 37 | namespace smallpt { 38 | 39 | constexpr Sphere g_spheres[] = { 40 | Sphere(1e5, Vector3(1e5 + 1, 40.8, 81.6), Vector3(), Vector3(0.75,0.25,0.25), Reflection_t::Diffuse), //Left 41 | Sphere(1e5, Vector3(-1e5 + 99, 40.8, 81.6), Vector3(), Vector3(0.25,0.25,0.75), Reflection_t::Diffuse), //Right 42 | Sphere(1e5, Vector3(50, 40.8, 1e5), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Back 43 | Sphere(1e5, Vector3(50, 40.8, -1e5 + 170), Vector3(), Vector3(), Reflection_t::Diffuse), //Front 44 | Sphere(1e5, Vector3(50, 1e5, 81.6), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Bottom 45 | Sphere(1e5, Vector3(50, -1e5 + 81.6, 81.6), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Top 46 | Sphere(16.5, Vector3(27, 16.5, 47), Vector3(), Vector3(0.999), Reflection_t::Specular), //Mirror 47 | Sphere(16.5, Vector3(73, 16.5, 78), Vector3(), Vector3(0.999), Reflection_t::Refractive),//Glass 48 | Sphere(600, Vector3(50, 681.6 - .27, 81.6), Vector3(12), Vector3(), Reflection_t::Diffuse) //Light 49 | }; 50 | 51 | [[nodiscard]] 52 | constexpr std::optional< std::size_t > Intersect(const Ray& ray) noexcept { 53 | std::optional< size_t > hit; 54 | for (std::size_t i = 0u; i < std::size(g_spheres); ++i) { 55 | if (g_spheres[i].Intersect(ray)) { 56 | hit = i; 57 | } 58 | } 59 | 60 | return hit; 61 | } 62 | 63 | [[nodiscard]] 64 | static const Vector3 Radiance(const Ray& ray, RNG& rng) noexcept { 65 | Ray r = ray; 66 | Vector3 L; 67 | Vector3 F(1.0); 68 | 69 | while (true) { 70 | const auto hit = Intersect(r); 71 | if (!hit) { 72 | return L; 73 | } 74 | 75 | const Sphere& shape = g_spheres[hit.value()]; 76 | const Vector3 p = r(r.m_tmax); 77 | const Vector3 n = Normalize(p - shape.m_p); 78 | 79 | L += F * shape.m_e; 80 | F *= shape.m_f; 81 | 82 | // Russian roulette 83 | if (4u < r.m_depth) { 84 | const double continue_probability = shape.m_f.Max(); 85 | if (rng.Uniform() >= continue_probability) { 86 | return L; 87 | } 88 | F /= continue_probability; 89 | } 90 | 91 | // Next path segment 92 | switch (shape.m_reflection_t) { 93 | 94 | case Reflection_t::Specular: { 95 | const Vector3 d = IdealSpecularReflect(r.m_d, n); 96 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 97 | break; 98 | } 99 | 100 | case Reflection_t::Refractive: { 101 | double pr; 102 | const Vector3 d = IdealSpecularTransmit(r.m_d, n, REFRACTIVE_INDEX_OUT, REFRACTIVE_INDEX_IN, pr, rng); 103 | F *= pr; 104 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 105 | break; 106 | } 107 | 108 | default: { 109 | const Vector3 w = (0.0 > n.Dot(r.m_d)) ? n : -n; 110 | const Vector3 u = Normalize((std::abs(w.m_x) > 0.1 ? Vector3(0.0, 1.0, 0.0) : Vector3(1.0, 0.0, 0.0)).Cross(w)); 111 | const Vector3 v = w.Cross(u); 112 | 113 | const Vector3 sample_d = CosineWeightedSampleOnHemisphere(rng.Uniform(), rng.Uniform()); 114 | const Vector3 d = Normalize(sample_d.m_x * u + sample_d.m_y * v + sample_d.m_z * w); 115 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 116 | break; 117 | } 118 | 119 | } 120 | } 121 | } 122 | 123 | static void Render(std::uint32_t nb_samples) noexcept { 124 | RNG rng; 125 | 126 | const std::uint32_t w = 1024u; 127 | const std::uint32_t h = 768u; 128 | 129 | const Vector3 eye = { 50.0, 52.0, 295.6 }; 130 | const Vector3 gaze = Normalize(Vector3(0.0, -0.042612, -1.0)); 131 | const double fov = 0.5135; 132 | const Vector3 cx = { w * fov / h, 0.0, 0.0 }; 133 | const Vector3 cy = Normalize(cx.Cross(gaze)) * fov; 134 | 135 | std::unique_ptr< Vector3[] > Ls(new Vector3[w * h]); 136 | 137 | #pragma omp parallel for schedule(static) 138 | for (int y = 0; y < static_cast< int >(h); ++y) { // pixel row 139 | 140 | for (std::size_t x = 0u; x < w; ++x) { // pixel column 141 | 142 | for (std::size_t sy = 0u, i = (h - 1u - y) * w + x; sy < 2u; ++sy) { // 2 subpixel row 143 | 144 | for (std::size_t sx = 0u; sx < 2u; ++sx) { // 2 subpixel column 145 | 146 | Vector3 L; 147 | 148 | for (std::size_t s = 0u; s < nb_samples; ++s) { // samples per subpixel 149 | 150 | const double u1 = 2.0 * rng.Uniform(); 151 | const double u2 = 2.0 * rng.Uniform(); 152 | const double dx = u1 < 1.0 ? sqrt(u1) - 1.0 : 1.0 - sqrt(2.0 - u1); 153 | const double dy = u2 < 1.0 ? sqrt(u2) - 1.0 : 1.0 - sqrt(2.0 - u2); 154 | const Vector3 d = cx * (((sx + 0.5 + dx) * 0.5 + x) / w - 0.5) + 155 | cy * (((sy + 0.5 + dy) * 0.5 + y) / h - 0.5) + gaze; 156 | 157 | L += Radiance(Ray(eye + d * 130.0, Normalize(d), EPSILON_SPHERE), rng) * (1.0 / nb_samples); 158 | } 159 | 160 | Ls[i] += 0.25 * Clamp(L); 161 | } 162 | } 163 | } 164 | } 165 | 166 | WritePPM(w, h, Ls.get()); 167 | } 168 | } 169 | 170 | int main(int argc, char* argv[]) { 171 | const std::uint32_t nb_samples = (2 == argc) ? atoi(argv[1]) / 4 : 1; 172 | smallpt::Render(nb_samples); 173 | 174 | return 0; 175 | } -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/cpp-smallpt.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // Includes 3 | //----------------------------------------------------------------------------- 4 | #pragma region 5 | 6 | #include "imageio.hpp" 7 | #include "sampling.hpp" 8 | #include "specular.hpp" 9 | #include "sphere.hpp" 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // System Includes 15 | //----------------------------------------------------------------------------- 16 | #pragma region 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #pragma endregion 23 | 24 | //----------------------------------------------------------------------------- 25 | // Defines 26 | //----------------------------------------------------------------------------- 27 | #pragma region 28 | 29 | #define REFRACTIVE_INDEX_OUT 1.0 30 | #define REFRACTIVE_INDEX_IN 1.5 31 | 32 | #pragma endregion 33 | 34 | //----------------------------------------------------------------------------- 35 | // Declarations and Definitions 36 | //----------------------------------------------------------------------------- 37 | namespace smallpt { 38 | 39 | constexpr Sphere g_spheres[] = { 40 | Sphere(1e5, Vector3(1e5 + 1, 40.8, 81.6), Vector3(), Vector3(0.75,0.25,0.25), Reflection_t::Diffuse), //Left 41 | Sphere(1e5, Vector3(-1e5 + 99, 40.8, 81.6), Vector3(), Vector3(0.25,0.25,0.75), Reflection_t::Diffuse), //Right 42 | Sphere(1e5, Vector3(50, 40.8, 1e5), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Back 43 | Sphere(1e5, Vector3(50, 40.8, -1e5 + 170), Vector3(), Vector3(), Reflection_t::Diffuse), //Front 44 | Sphere(1e5, Vector3(50, 1e5, 81.6), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Bottom 45 | Sphere(1e5, Vector3(50, -1e5 + 81.6, 81.6), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Top 46 | Sphere(16.5, Vector3(27, 16.5, 47), Vector3(), Vector3(0.999), Reflection_t::Specular), //Mirror 47 | Sphere(16.5, Vector3(73, 16.5, 78), Vector3(), Vector3(0.999), Reflection_t::Refractive),//Glass 48 | Sphere(600, Vector3(50, 681.6 - .27, 81.6), Vector3(12), Vector3(), Reflection_t::Diffuse) //Light 49 | }; 50 | 51 | [[nodiscard]] 52 | constexpr std::optional< std::size_t > Intersect(const Ray& ray) noexcept { 53 | std::optional< size_t > hit; 54 | for (std::size_t i = 0u; i < std::size(g_spheres); ++i) { 55 | if (g_spheres[i].Intersect(ray)) { 56 | hit = i; 57 | } 58 | } 59 | 60 | return hit; 61 | } 62 | 63 | [[nodiscard]] 64 | static const Vector3 Radiance(const Ray& ray, RNG& rng) noexcept { 65 | Ray r = ray; 66 | Vector3 L; 67 | Vector3 F(1.0); 68 | 69 | while (true) { 70 | const auto hit = Intersect(r); 71 | if (!hit) { 72 | return L; 73 | } 74 | 75 | const Sphere& shape = g_spheres[hit.value()]; 76 | const Vector3 p = r(r.m_tmax); 77 | const Vector3 n = Normalize(p - shape.m_p); 78 | 79 | L += F * shape.m_e; 80 | F *= shape.m_f; 81 | 82 | // Russian roulette 83 | if (4u < r.m_depth) { 84 | const double continue_probability = shape.m_f.Max(); 85 | if (rng.Uniform() >= continue_probability) { 86 | return L; 87 | } 88 | F /= continue_probability; 89 | } 90 | 91 | // Next path segment 92 | switch (shape.m_reflection_t) { 93 | 94 | case Reflection_t::Specular: { 95 | const Vector3 d = IdealSpecularReflect(r.m_d, n); 96 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 97 | break; 98 | } 99 | 100 | case Reflection_t::Refractive: { 101 | double pr; 102 | const Vector3 d = IdealSpecularTransmit(r.m_d, n, REFRACTIVE_INDEX_OUT, REFRACTIVE_INDEX_IN, pr, rng); 103 | F *= pr; 104 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 105 | break; 106 | } 107 | 108 | default: { 109 | const Vector3 w = (0.0 > n.Dot(r.m_d)) ? n : -n; 110 | const Vector3 u = Normalize((std::abs(w.m_x) > 0.1 ? Vector3(0.0, 1.0, 0.0) : Vector3(1.0, 0.0, 0.0)).Cross(w)); 111 | const Vector3 v = w.Cross(u); 112 | 113 | const Vector3 sample_d = CosineWeightedSampleOnHemisphere(rng.Uniform(), rng.Uniform()); 114 | const Vector3 d = Normalize(sample_d.m_x * u + sample_d.m_y * v + sample_d.m_z * w); 115 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 116 | break; 117 | } 118 | 119 | } 120 | } 121 | } 122 | 123 | static void Render(std::uint32_t nb_samples) noexcept { 124 | RNG rng; 125 | 126 | const std::uint32_t w = 1024u; 127 | const std::uint32_t h = 768u; 128 | 129 | const Vector3 eye = { 50.0, 52.0, 295.6 }; 130 | const Vector3 gaze = Normalize(Vector3(0.0, -0.042612, -1.0)); 131 | const double fov = 0.5135; 132 | const Vector3 cx = { w * fov / h, 0.0, 0.0 }; 133 | const Vector3 cy = Normalize(cx.Cross(gaze)) * fov; 134 | 135 | std::unique_ptr< Vector3[] > Ls(new Vector3[w * h]); 136 | 137 | for (std::size_t y = 0u; y < h; ++y) { // pixel row 138 | 139 | fprintf(stderr, "\rRendering (%u spp) %5.2f%%", nb_samples * 4, 100.0 * y / (h - 1)); 140 | 141 | for (std::size_t x = 0u; x < w; ++x) { // pixel column 142 | 143 | for (std::size_t sy = 0u, i = (h - 1u - y) * w + x; sy < 2u; ++sy) { // 2 subpixel row 144 | 145 | for (std::size_t sx = 0u; sx < 2u; ++sx) { // 2 subpixel column 146 | 147 | Vector3 L; 148 | 149 | for (std::size_t s = 0u; s < nb_samples; ++s) { // samples per subpixel 150 | 151 | const double u1 = 2.0 * rng.Uniform(); 152 | const double u2 = 2.0 * rng.Uniform(); 153 | const double dx = u1 < 1.0 ? sqrt(u1) - 1.0 : 1.0 - sqrt(2.0 - u1); 154 | const double dy = u2 < 1.0 ? sqrt(u2) - 1.0 : 1.0 - sqrt(2.0 - u2); 155 | const Vector3 d = cx * (((sx + 0.5 + dx) * 0.5 + x) / w - 0.5) + 156 | cy * (((sy + 0.5 + dy) * 0.5 + y) / h - 0.5) + gaze; 157 | 158 | L += Radiance(Ray(eye + d * 130.0, Normalize(d), EPSILON_SPHERE), rng) * (1.0 / nb_samples); 159 | } 160 | 161 | Ls[i] += 0.25 * Clamp(L); 162 | } 163 | } 164 | } 165 | } 166 | 167 | WritePPM(w, h, Ls.get()); 168 | } 169 | } 170 | 171 | int main(int argc, char* argv[]) { 172 | const std::uint32_t nb_samples = (2 == argc) ? atoi(argv[1]) / 4 : 1; 173 | smallpt::Render(nb_samples); 174 | 175 | return 0; 176 | } 177 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/lock.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // Includes 3 | //----------------------------------------------------------------------------- 4 | #pragma region 5 | 6 | #include "lock.hpp" 7 | 8 | #pragma endregion 9 | 10 | //----------------------------------------------------------------------------- 11 | // System Includes 12 | //----------------------------------------------------------------------------- 13 | #pragma region 14 | 15 | #include 16 | 17 | #pragma endregion 18 | 19 | //----------------------------------------------------------------------------- 20 | // Definitions 21 | //----------------------------------------------------------------------------- 22 | namespace smallpt { 23 | 24 | //------------------------------------------------------------------------- 25 | // Mutex 26 | //------------------------------------------------------------------------- 27 | Mutex::Mutex() { 28 | // Initialize a critical section object. 29 | InitializeCriticalSection(&m_critical_section); 30 | } 31 | 32 | Mutex::~Mutex() { 33 | // Release all resources used by an unowned critical section object. 34 | DeleteCriticalSection(&m_critical_section); 35 | } 36 | 37 | //------------------------------------------------------------------------- 38 | // MutexLock 39 | //------------------------------------------------------------------------- 40 | MutexLock::MutexLock(Mutex& mutex) 41 | : m_mutex(mutex) { 42 | // Wait for ownership of the specified critical section object. 43 | // The function returns when the calling thread is granted ownership. 44 | EnterCriticalSection(&m_mutex.m_critical_section); 45 | } 46 | 47 | MutexLock::~MutexLock() { 48 | // Release ownership of the specified critical section object. 49 | LeaveCriticalSection(&m_mutex.m_critical_section); 50 | } 51 | 52 | //------------------------------------------------------------------------- 53 | // Semaphore 54 | //------------------------------------------------------------------------- 55 | Semaphore::Semaphore() 56 | : m_handle(nullptr) { 57 | // Creates or opens an unnamed semaphore object. 58 | // 1. The returned handle cannot be inherited by child processes. 59 | // 2. The initial count for the semaphore object. 60 | // 3. The maximum count for the semaphore object. 61 | // 4. The semaphore object is created without a name. 62 | m_handle = CreateSemaphore(nullptr, 0, LONG_MAX, nullptr); 63 | } 64 | 65 | Semaphore::~Semaphore() { 66 | // Closes an open object handle. 67 | CloseHandle(m_handle); 68 | } 69 | 70 | void Semaphore::Signal(std::uint32_t count) noexcept { 71 | // Increases the count of the specified semaphore object. 72 | // 1. A handle to the semaphore object. 73 | // 2. The amount by which the semaphore object's current count is to be increased. 74 | // 3. A pointer to a variable to receive the previous count for the semaphore. 75 | ReleaseSemaphore(m_handle, count, nullptr); 76 | } 77 | 78 | void Semaphore::Wait() noexcept { 79 | // Waits until the specified object is in the signaled state or the time-out interval elapses. 80 | // 1. The object handle. 81 | // 2. The function will return only when the specified object is signaled. 82 | WaitForSingleObject(m_handle, INFINITE); 83 | } 84 | 85 | [[nodiscard]] 86 | bool Semaphore::TryWait() noexcept { 87 | // Waits until the specified object is in the signaled state or the time-out interval elapses. 88 | // 1. The object handle. 89 | // 2. The function does not enter a wait state if the object is not signaled. 90 | // it always returns immediately. 91 | return (WaitForSingleObject(m_handle, 0L) == WAIT_OBJECT_0); 92 | } 93 | 94 | //------------------------------------------------------------------------- 95 | // ConditionVariable 96 | //------------------------------------------------------------------------- 97 | ConditionVariable::ConditionVariable() 98 | : m_nb_waiters(0u) { 99 | 100 | // Initialize the critical section objects 101 | // for the number of waiters and condition. 102 | InitializeCriticalSection(&m_nb_waiters_mutex); 103 | InitializeCriticalSection(&m_condition_mutex); 104 | 105 | // Creates or opens a named or unnamed event object. 106 | // On success, a handle to the event object is returned. 107 | m_events[SIGNAL] = CreateEvent( 108 | nullptr, // no security 109 | FALSE, // auto-reset event object 110 | FALSE, // non-signaled initial state 111 | nullptr); // unnamed event object 112 | m_events[BROADCAST] = CreateEvent( 113 | nullptr, // no security 114 | TRUE, // manual-reset event object 115 | FALSE, // non-signaled initial state 116 | nullptr); // unnamed event object 117 | } 118 | 119 | ConditionVariable::~ConditionVariable() { 120 | // Release all resources used by an unowned critical section object. 121 | DeleteCriticalSection(&m_nb_waiters_mutex); 122 | DeleteCriticalSection(&m_condition_mutex); 123 | 124 | // Close the open event handles. 125 | CloseHandle(m_events[SIGNAL]); 126 | CloseHandle(m_events[BROADCAST]); 127 | } 128 | 129 | void ConditionVariable::Lock() noexcept { 130 | // Wait for ownership of the specified critical section object. 131 | // The function returns when the calling thread is granted ownership. 132 | EnterCriticalSection(&m_condition_mutex); 133 | } 134 | 135 | void ConditionVariable::Unlock() noexcept { 136 | // Release ownership of the specified critical section object. 137 | LeaveCriticalSection(&m_condition_mutex); 138 | } 139 | 140 | void ConditionVariable::Signal() noexcept { 141 | // Retrieve if there are waiters. 142 | EnterCriticalSection(&m_nb_waiters_mutex); 143 | const bool has_waiters = (0u < m_nb_waiters); 144 | LeaveCriticalSection(&m_nb_waiters_mutex); 145 | 146 | if (has_waiters) { 147 | // Sets the SIGNAL event object to the signaled state. 148 | SetEvent(m_events[SIGNAL]); 149 | } 150 | } 151 | 152 | void ConditionVariable::Wait() noexcept { 153 | // Increase the number of waiters. 154 | EnterCriticalSection(&m_nb_waiters_mutex); 155 | ++m_nb_waiters; 156 | LeaveCriticalSection(&m_nb_waiters_mutex); 157 | 158 | // It is ok to release the here since Win32 159 | // manual-reset events maintain state when used with . 160 | // This avoids the "lost wakeup" bug... 161 | LeaveCriticalSection(&m_condition_mutex); 162 | 163 | // Wait until one or all of the specified objects are 164 | // in the signaled state (available for use) or the time-out interval elapses. 165 | // 1. The number of object handles. 166 | // 2. An array of object handles. 167 | // 3. The function returns when the state of any one object is signaled. 168 | // 4. The function will return only when the specified objects are signaled. 169 | const int result = WaitForMultipleObjects(2, m_events, FALSE, INFINITE); 170 | 171 | // Decrease the number of waiters. 172 | EnterCriticalSection(&m_nb_waiters_mutex); 173 | --m_nb_waiters; 174 | // WAIT_OBJECT_0: The state of the specified object is signaled. 175 | const int last_waiter = (result == WAIT_OBJECT_0 + BROADCAST) && (m_nb_waiters == 0); 176 | LeaveCriticalSection(&m_nb_waiters_mutex); 177 | 178 | if (last_waiter) { 179 | // We are the last waiter to be notified or to stop waiting, so reset the manual event. 180 | // Sets the specified event object to the nonsignaled state. 181 | ResetEvent(m_events[BROADCAST]); 182 | } 183 | 184 | EnterCriticalSection(&m_condition_mutex); 185 | } 186 | } -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {1F717F97-896D-4209-A4FD-CE11DB062C45} 36 | Win32Proj 37 | cppsmallpt 38 | 10.0.17763.0 39 | 40 | 41 | 42 | Application 43 | true 44 | v142 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | Application 56 | true 57 | v142 58 | Unicode 59 | 60 | 61 | Application 62 | false 63 | v142 64 | true 65 | Unicode 66 | 67 | 68 | 69 | Application 70 | true 71 | v142 72 | Unicode 73 | 74 | 75 | Application 76 | false 77 | v142 78 | true 79 | Unicode 80 | 81 | 82 | Application 83 | true 84 | v142 85 | Unicode 86 | 87 | 88 | Application 89 | false 90 | v142 91 | true 92 | Unicode 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | /Zc:twoPhase- %(AdditionalOptions) 118 | 119 | 120 | 121 | 122 | /Zc:twoPhase- %(AdditionalOptions) 123 | 124 | 125 | 126 | 127 | /Zc:twoPhase- %(AdditionalOptions) 128 | 129 | 130 | 131 | 132 | /Zc:twoPhase- %(AdditionalOptions) 133 | 134 | 135 | 136 | 137 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 138 | $(VC_SourcePath); 139 | 140 | 141 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 142 | $(VC_SourcePath); 143 | 144 | 145 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 146 | $(VC_SourcePath); 147 | 148 | 149 | $(ProjectName)\src\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 150 | $(VC_SourcePath); 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/cpp-smallpt.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // Includes 3 | //----------------------------------------------------------------------------- 4 | #pragma region 5 | 6 | #include "targetver.hpp" 7 | #include "imageio.hpp" 8 | #include "sampling.hpp" 9 | #include "specular.hpp" 10 | #include "sphere.hpp" 11 | #include "task.hpp" 12 | 13 | #pragma endregion 14 | 15 | //----------------------------------------------------------------------------- 16 | // System Includes 17 | //----------------------------------------------------------------------------- 18 | #pragma region 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #pragma endregion 25 | 26 | //----------------------------------------------------------------------------- 27 | // Defines 28 | //----------------------------------------------------------------------------- 29 | #pragma region 30 | 31 | #define REFRACTIVE_INDEX_OUT 1.0 32 | #define REFRACTIVE_INDEX_IN 1.5 33 | 34 | #pragma endregion 35 | 36 | //----------------------------------------------------------------------------- 37 | // Declarations and Definitions 38 | //----------------------------------------------------------------------------- 39 | namespace smallpt { 40 | 41 | constexpr Sphere g_spheres[] = { 42 | Sphere(1e5, Vector3(1e5 + 1, 40.8, 81.6), Vector3(), Vector3(0.75,0.25,0.25), Reflection_t::Diffuse), //Left 43 | Sphere(1e5, Vector3(-1e5 + 99, 40.8, 81.6), Vector3(), Vector3(0.25,0.25,0.75), Reflection_t::Diffuse), //Right 44 | Sphere(1e5, Vector3(50, 40.8, 1e5), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Back 45 | Sphere(1e5, Vector3(50, 40.8, -1e5 + 170), Vector3(), Vector3(), Reflection_t::Diffuse), //Front 46 | Sphere(1e5, Vector3(50, 1e5, 81.6), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Bottom 47 | Sphere(1e5, Vector3(50, -1e5 + 81.6, 81.6), Vector3(), Vector3(0.75), Reflection_t::Diffuse), //Top 48 | Sphere(16.5, Vector3(27, 16.5, 47), Vector3(), Vector3(0.999), Reflection_t::Specular), //Mirror 49 | Sphere(16.5, Vector3(73, 16.5, 78), Vector3(), Vector3(0.999), Reflection_t::Refractive),//Glass 50 | Sphere(600, Vector3(50, 681.6 - .27, 81.6), Vector3(12), Vector3(), Reflection_t::Diffuse) //Light 51 | }; 52 | 53 | [[nodiscard]] 54 | constexpr std::optional< std::size_t > Intersect(const Ray& ray) noexcept { 55 | std::optional< size_t > hit; 56 | for (std::size_t i = 0u; i < std::size(g_spheres); ++i) { 57 | if (g_spheres[i].Intersect(ray)) { 58 | hit = i; 59 | } 60 | } 61 | 62 | return hit; 63 | } 64 | 65 | [[nodiscard]] 66 | static const Vector3 Radiance(const Ray& ray, RNG& rng) noexcept { 67 | Ray r = ray; 68 | Vector3 L; 69 | Vector3 F(1.0); 70 | 71 | while (true) { 72 | const auto hit = Intersect(r); 73 | if (!hit) { 74 | return L; 75 | } 76 | 77 | const Sphere& shape = g_spheres[hit.value()]; 78 | const Vector3 p = r(r.m_tmax); 79 | const Vector3 n = Normalize(p - shape.m_p); 80 | 81 | L += F * shape.m_e; 82 | F *= shape.m_f; 83 | 84 | // Russian roulette 85 | if (4u < r.m_depth) { 86 | const double continue_probability = shape.m_f.Max(); 87 | if (rng.Uniform() >= continue_probability) { 88 | return L; 89 | } 90 | F /= continue_probability; 91 | } 92 | 93 | // Next path segment 94 | switch (shape.m_reflection_t) { 95 | 96 | case Reflection_t::Specular: { 97 | const Vector3 d = IdealSpecularReflect(r.m_d, n); 98 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 99 | break; 100 | } 101 | 102 | case Reflection_t::Refractive: { 103 | double pr; 104 | const Vector3 d = IdealSpecularTransmit(r.m_d, n, REFRACTIVE_INDEX_OUT, REFRACTIVE_INDEX_IN, pr, rng); 105 | F *= pr; 106 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 107 | break; 108 | } 109 | 110 | default: { 111 | const Vector3 w = (0.0 > n.Dot(r.m_d)) ? n : -n; 112 | const Vector3 u = Normalize((std::abs(w.m_x) > 0.1 ? Vector3(0.0, 1.0, 0.0) : Vector3(1.0, 0.0, 0.0)).Cross(w)); 113 | const Vector3 v = w.Cross(u); 114 | 115 | const Vector3 sample_d = CosineWeightedSampleOnHemisphere(rng.Uniform(), rng.Uniform()); 116 | const Vector3 d = Normalize(sample_d.m_x * u + sample_d.m_y * v + sample_d.m_z * w); 117 | r = Ray(p, d, EPSILON_SPHERE, INFINITY, r.m_depth + 1u); 118 | break; 119 | } 120 | 121 | } 122 | } 123 | } 124 | 125 | 126 | //------------------------------------------------------------------------- 127 | // Declarations and Definitions: RenderTask 128 | //------------------------------------------------------------------------- 129 | 130 | class RenderTask : public Task { 131 | 132 | public: 133 | 134 | //--------------------------------------------------------------------- 135 | // Constructors and Destructors 136 | //--------------------------------------------------------------------- 137 | 138 | explicit RenderTask(std::uint32_t y, 139 | std::uint32_t w, 140 | std::uint32_t h, 141 | std::uint32_t nb_samples, 142 | const Vector3& eye, 143 | const Vector3& gaze, 144 | const Vector3& cx, 145 | const Vector3& cy, 146 | Vector3* Ls) noexcept 147 | : m_y(y), 148 | m_w(w), 149 | m_h(h), 150 | m_nb_samples(nb_samples), 151 | m_eye(eye), 152 | m_gaze(gaze), 153 | m_cx(cx), 154 | m_cy(cy), 155 | m_rng(y), 156 | m_Ls(Ls) {} 157 | RenderTask(const RenderTask& task) noexcept = default; 158 | RenderTask(RenderTask&& task) noexcept = default; 159 | virtual ~RenderTask() = default; 160 | 161 | //--------------------------------------------------------------------- 162 | // Assignment Operators 163 | //--------------------------------------------------------------------- 164 | 165 | RenderTask& operator=(const RenderTask& task) = delete; 166 | RenderTask& operator=(RenderTask&& task) = delete; 167 | 168 | //--------------------------------------------------------------------- 169 | // Member Methods 170 | //--------------------------------------------------------------------- 171 | 172 | virtual void Run() noexcept final override { 173 | for (std::size_t x = 0u; x < m_w; ++x) { // pixel column 174 | 175 | for (std::size_t sy = 0u, i = (m_h - 1u - m_y) * m_w + x; sy < 2u; ++sy) { // 2 subpixel row 176 | 177 | for (std::size_t sx = 0u; sx < 2u; ++sx) { // 2 subpixel column 178 | 179 | Vector3 L; 180 | 181 | for (std::size_t s = 0u; s < m_nb_samples; ++s) { // samples per subpixel 182 | const double u1 = 2.0 * m_rng.Uniform(); 183 | const double u2 = 2.0 * m_rng.Uniform(); 184 | const double dx = u1 < 1.0 ? sqrt(u1) - 1.0 : 1.0 - sqrt(2.0 - u1); 185 | const double dy = u2 < 1.0 ? sqrt(u2) - 1.0 : 1.0 - sqrt(2.0 - u2); 186 | const Vector3 d = m_cx * (((sx + 0.5 + dx) * 0.5 + x) / m_w - 0.5) + 187 | m_cy * (((sy + 0.5 + dy) * 0.5 + m_y) / m_h - 0.5) + m_gaze; 188 | L += Radiance(Ray(m_eye + d * 130.0, Normalize(d), EPSILON_SPHERE), m_rng) * (1.0 / m_nb_samples); 189 | } 190 | 191 | m_Ls[i] += 0.25 * Clamp(L); 192 | } 193 | } 194 | } 195 | } 196 | 197 | private: 198 | 199 | //--------------------------------------------------------------------- 200 | // Member Variables 201 | //--------------------------------------------------------------------- 202 | 203 | uint32_t m_y; 204 | uint32_t m_w; 205 | uint32_t m_h; 206 | uint32_t m_nb_samples; 207 | 208 | Vector3 m_eye; 209 | Vector3 m_gaze; 210 | Vector3 m_cx; 211 | Vector3 m_cy; 212 | 213 | RNG m_rng; 214 | 215 | Vector3* m_Ls; 216 | }; 217 | 218 | static void Render(std::uint32_t nb_samples) noexcept { 219 | const std::uint32_t w = 1024u; 220 | const std::uint32_t h = 768u; 221 | 222 | const Vector3 eye = { 50.0, 52.0, 295.6 }; 223 | const Vector3 gaze = Normalize(Vector3(0.0, -0.042612, -1.0)); 224 | const double fov = 0.5135; 225 | const Vector3 cx = { w * fov / h, 0.0, 0.0 }; 226 | const Vector3 cy = Normalize(cx.Cross(gaze)) * fov; 227 | 228 | std::unique_ptr< Vector3[] > Ls(new Vector3[w * h]); 229 | 230 | std::vector< Task* > render_tasks; 231 | render_tasks.reserve(h); 232 | for (std::uint32_t y = 0u; y < h; ++y) { // pixel row 233 | render_tasks.push_back(new RenderTask(y, w, h, nb_samples, eye, gaze, cx, cy, Ls.get())); 234 | } 235 | 236 | EnqueueTasks(render_tasks); 237 | WaitForAllTasks(); 238 | for (std::size_t y = 0; y < render_tasks.size(); ++y) { 239 | delete render_tasks[y]; 240 | } 241 | TasksCleanup(); 242 | 243 | WritePPM(w, h, Ls.get()); 244 | } 245 | } 246 | 247 | int main(int argc, char* argv[]) { 248 | const std::uint32_t nb_samples = (2 == argc) ? atoi(argv[1]) / 4 : 1; 249 | smallpt::Render(nb_samples); 250 | 251 | return 0; 252 | } 253 | -------------------------------------------------------------------------------- /cpp-smallpt/cpp-smallpt/src/vector.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "math.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // System Includes 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #include 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | //------------------------------------------------------------------------- 27 | // Vector3 28 | //------------------------------------------------------------------------- 29 | 30 | struct Vector3 { 31 | 32 | public: 33 | 34 | //--------------------------------------------------------------------- 35 | // Constructors and Destructors 36 | //--------------------------------------------------------------------- 37 | 38 | constexpr explicit Vector3(double xyz = 0.0) noexcept 39 | : Vector3(xyz, xyz, xyz) {} 40 | constexpr Vector3(double x, double y, double z) noexcept 41 | : m_x(x), m_y(y), m_z(z) {} 42 | constexpr Vector3(const Vector3& v) noexcept = default; 43 | constexpr Vector3(Vector3&& v) noexcept = default; 44 | ~Vector3() = default; 45 | 46 | //--------------------------------------------------------------------- 47 | // Assignment Operators 48 | //--------------------------------------------------------------------- 49 | 50 | Vector3& operator=(const Vector3& v) = default; 51 | Vector3& operator=(Vector3&& v) = default; 52 | 53 | //--------------------------------------------------------------------- 54 | // Member Methods 55 | //--------------------------------------------------------------------- 56 | 57 | [[nodiscard]] 58 | bool HasNaNs() const noexcept { 59 | return std::isnan(m_x) || std::isnan(m_y) || std::isnan(m_z); 60 | } 61 | 62 | [[nodiscard]] 63 | constexpr const Vector3 operator-() const noexcept { 64 | return { -m_x, -m_y, -m_z }; 65 | } 66 | 67 | [[nodiscard]] 68 | constexpr const Vector3 operator+(const Vector3& v) const noexcept { 69 | return { m_x + v.m_x, m_y + v.m_y, m_z + v.m_z }; 70 | } 71 | 72 | [[nodiscard]] 73 | constexpr const Vector3 operator-(const Vector3& v) const noexcept { 74 | return { m_x - v.m_x, m_y - v.m_y, m_z - v.m_z }; 75 | } 76 | 77 | [[nodiscard]] 78 | constexpr const Vector3 operator*(const Vector3& v) const noexcept { 79 | return { m_x * v.m_x, m_y * v.m_y, m_z * v.m_z }; 80 | } 81 | 82 | [[nodiscard]] 83 | constexpr const Vector3 operator/(const Vector3& v) const noexcept { 84 | return { m_x / v.m_x, m_y / v.m_y, m_z / v.m_z }; 85 | } 86 | 87 | [[nodiscard]] 88 | constexpr const Vector3 operator+(double a) const noexcept { 89 | return { m_x + a, m_y + a, m_z + a }; 90 | } 91 | 92 | [[nodiscard]] 93 | constexpr const Vector3 operator-(double a) const noexcept { 94 | return { m_x - a, m_y - a, m_z - a }; 95 | } 96 | 97 | [[nodiscard]] 98 | constexpr const Vector3 operator*(double a) const noexcept { 99 | return { m_x * a, m_y * a, m_z * a }; 100 | } 101 | 102 | [[nodiscard]] 103 | constexpr const Vector3 operator/(double a) const noexcept { 104 | const double inv_a = 1.0 / a; 105 | return { m_x * inv_a, m_y * inv_a, m_z * inv_a }; 106 | } 107 | 108 | Vector3& operator+=(const Vector3& v) noexcept { 109 | m_x += v.m_x; 110 | m_y += v.m_y; 111 | m_z += v.m_z; 112 | return *this; 113 | } 114 | 115 | Vector3& operator-=(const Vector3& v) noexcept { 116 | m_x -= v.m_x; 117 | m_y -= v.m_y; 118 | m_z -= v.m_z; 119 | return *this; 120 | } 121 | 122 | Vector3& operator*=(const Vector3& v) noexcept { 123 | m_x *= v.m_x; 124 | m_y *= v.m_y; 125 | m_z *= v.m_z; 126 | return *this; 127 | } 128 | 129 | Vector3& operator/=(const Vector3& v) noexcept { 130 | m_x /= v.m_x; 131 | m_y /= v.m_y; 132 | m_z /= v.m_z; 133 | return *this; 134 | } 135 | 136 | Vector3& operator+=(double a) noexcept { 137 | m_x += a; 138 | m_y += a; 139 | m_z += a; 140 | return *this; 141 | } 142 | 143 | Vector3& operator-=(double a) noexcept { 144 | m_x -= a; 145 | m_y -= a; 146 | m_z -= a; 147 | return *this; 148 | } 149 | 150 | Vector3& operator*=(double a) noexcept { 151 | m_x *= a; 152 | m_y *= a; 153 | m_z *= a; 154 | return *this; 155 | } 156 | 157 | Vector3& operator/=(double a) noexcept { 158 | const double inv_a = 1.0 / a; 159 | m_x *= inv_a; 160 | m_y *= inv_a; 161 | m_z *= inv_a; 162 | return *this; 163 | } 164 | 165 | [[nodiscard]] 166 | constexpr double Dot(const Vector3& v) const noexcept { 167 | return m_x * v.m_x + m_y * v.m_y + m_z * v.m_z; 168 | } 169 | 170 | [[nodiscard]] 171 | constexpr const Vector3 Cross(const Vector3& v) const noexcept { 172 | return { 173 | m_y * v.m_z - m_z * v.m_y, 174 | m_z * v.m_x - m_x * v.m_z, 175 | m_x * v.m_y - m_y * v.m_x 176 | }; 177 | } 178 | 179 | [[nodiscard]] 180 | constexpr bool operator==(const Vector3& rhs) const { 181 | return m_x == rhs.m_x && m_y == rhs.m_y && m_z == rhs.m_z; 182 | } 183 | 184 | [[nodiscard]] 185 | constexpr bool operator!=(const Vector3& rhs) const { 186 | return !(*this == rhs); 187 | } 188 | 189 | [[nodiscard]] 190 | double& operator[](std::size_t i) noexcept { 191 | return (&m_x)[i]; 192 | } 193 | 194 | [[nodiscard]] 195 | constexpr double operator[](std::size_t i) const noexcept { 196 | return (&m_x)[i]; 197 | } 198 | 199 | [[nodiscard]] 200 | constexpr std::size_t MinDimension() const noexcept { 201 | return (m_x < m_y && m_x < m_z) ? 0u : ((m_y < m_z) ? 1u : 2u); 202 | } 203 | 204 | [[nodiscard]] 205 | constexpr std::size_t MaxDimension() const noexcept { 206 | return (m_x > m_y && m_x > m_z) ? 0u : ((m_y > m_z) ? 1u : 2u); 207 | } 208 | 209 | [[nodiscard]] 210 | constexpr double Min() const noexcept { 211 | return std::min(m_x, std::min(m_y, m_z)); 212 | } 213 | [[nodiscard]] 214 | constexpr double Max() const noexcept { 215 | return std::max(m_x, std::max(m_y, m_z)); 216 | } 217 | 218 | [[nodiscard]] 219 | constexpr double Norm2_squared() const noexcept { 220 | return m_x * m_x + m_y * m_y + m_z * m_z; 221 | } 222 | 223 | [[nodiscard]] 224 | double Norm2() const noexcept { 225 | return std::sqrt(Norm2_squared()); 226 | } 227 | 228 | void Normalize() noexcept { 229 | const double a = 1.0 / Norm2(); 230 | m_x *= a; 231 | m_y *= a; 232 | m_z *= a; 233 | } 234 | 235 | //--------------------------------------------------------------------- 236 | // Member Variables 237 | //--------------------------------------------------------------------- 238 | 239 | double m_x, m_y, m_z; 240 | }; 241 | 242 | //------------------------------------------------------------------------- 243 | // Vector3 Utilities 244 | //------------------------------------------------------------------------- 245 | 246 | std::ostream& operator<<(std::ostream& os, const Vector3& v) { 247 | os << '[' << v.m_x << ' ' << v.m_y << ' ' << v.m_z << ']'; 248 | return os; 249 | } 250 | 251 | [[nodiscard]] 252 | constexpr const Vector3 operator+(double a, const Vector3& v) noexcept { 253 | return { a + v.m_x, a + v.m_y, a + v.m_z }; 254 | } 255 | 256 | [[nodiscard]] 257 | constexpr const Vector3 operator-(double a, const Vector3& v) noexcept { 258 | return { a - v.m_x, a - v.m_y, a - v.m_z }; 259 | } 260 | 261 | [[nodiscard]] 262 | constexpr const Vector3 operator*(double a, const Vector3& v) noexcept { 263 | return { a * v.m_x, a * v.m_y, a * v.m_z }; 264 | } 265 | 266 | [[nodiscard]] 267 | constexpr const Vector3 operator/(double a, const Vector3& v) noexcept { 268 | return { a / v.m_x, a / v.m_y, a / v.m_z }; 269 | } 270 | 271 | [[nodiscard]] 272 | inline const Vector3 Sqrt(const Vector3& v) noexcept { 273 | return { 274 | std::sqrt(v.m_x), 275 | std::sqrt(v.m_y), 276 | std::sqrt(v.m_z) 277 | }; 278 | } 279 | 280 | [[nodiscard]] 281 | inline const Vector3 Pow(const Vector3& v, double a) noexcept { 282 | return { 283 | std::pow(v.m_x, a), 284 | std::pow(v.m_y, a), 285 | std::pow(v.m_z, a) 286 | }; 287 | } 288 | 289 | [[nodiscard]] 290 | inline const Vector3 Abs(const Vector3& v) noexcept { 291 | return { 292 | std::abs(v.m_x), 293 | std::abs(v.m_y), 294 | std::abs(v.m_z) 295 | }; 296 | } 297 | 298 | [[nodiscard]] 299 | constexpr const Vector3 Min(const Vector3& v1, const Vector3& v2) noexcept { 300 | return { 301 | std::min(v1.m_x, v2.m_x), 302 | std::min(v1.m_y, v2.m_y), 303 | std::min(v1.m_z, v2.m_z) 304 | }; 305 | } 306 | 307 | [[nodiscard]] 308 | constexpr const Vector3 Max(const Vector3& v1, const Vector3& v2) noexcept { 309 | return { 310 | std::max(v1.m_x, v2.m_x), 311 | std::max(v1.m_y, v2.m_y), 312 | std::max(v1.m_z, v2.m_z) 313 | }; 314 | } 315 | 316 | [[nodiscard]] 317 | inline const Vector3 Round(const Vector3& v) noexcept { 318 | return { 319 | std::round(v.m_x), 320 | std::round(v.m_y), 321 | std::round(v.m_z) 322 | }; 323 | } 324 | 325 | [[nodiscard]] 326 | inline const Vector3 Floor(const Vector3& v) noexcept { 327 | return { 328 | std::floor(v.m_x), 329 | std::floor(v.m_y), 330 | std::floor(v.m_z) 331 | }; 332 | } 333 | 334 | [[nodiscard]] 335 | inline const Vector3 Ceil(const Vector3& v) noexcept { 336 | return { 337 | std::ceil(v.m_x), 338 | std::ceil(v.m_y), 339 | std::ceil(v.m_z) 340 | }; 341 | } 342 | 343 | [[nodiscard]] 344 | inline const Vector3 Trunc(const Vector3& v) noexcept { 345 | return { 346 | std::trunc(v.m_x), 347 | std::trunc(v.m_y), 348 | std::trunc(v.m_z) 349 | }; 350 | } 351 | 352 | [[nodiscard]] 353 | constexpr const Vector3 Clamp(const Vector3& v, 354 | double low = 0.0, 355 | double high = 1.0) noexcept { 356 | 357 | return { 358 | std::clamp(v.m_x, low, high), 359 | std::clamp(v.m_y, low, high), 360 | std::clamp(v.m_z, low, high) } 361 | ; 362 | } 363 | [[nodiscard]] 364 | constexpr const Vector3 Lerp(double a, 365 | const Vector3& v1, 366 | const Vector3& v2) noexcept { 367 | 368 | return v1 + a * (v2 - v1); 369 | } 370 | 371 | template< std::size_t X, std::size_t Y, std::size_t Z > 372 | [[nodiscard]] 373 | constexpr const Vector3 Permute(const Vector3& v) noexcept { 374 | return { v[X], v[Y], v[Z] }; 375 | } 376 | 377 | [[nodiscard]] 378 | inline const Vector3 Normalize(const Vector3& v) noexcept { 379 | const double a = 1.0 / v.Norm2(); 380 | return a * v; 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /openmp-cpp-smallpt/cpp-smallpt/src/vector.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "math.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // System Includes 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #include 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | //------------------------------------------------------------------------- 27 | // Vector3 28 | //------------------------------------------------------------------------- 29 | 30 | struct Vector3 { 31 | 32 | public: 33 | 34 | //--------------------------------------------------------------------- 35 | // Constructors and Destructors 36 | //--------------------------------------------------------------------- 37 | 38 | constexpr explicit Vector3(double xyz = 0.0) noexcept 39 | : Vector3(xyz, xyz, xyz) {} 40 | constexpr Vector3(double x, double y, double z) noexcept 41 | : m_x(x), m_y(y), m_z(z) {} 42 | constexpr Vector3(const Vector3& v) noexcept = default; 43 | constexpr Vector3(Vector3&& v) noexcept = default; 44 | ~Vector3() = default; 45 | 46 | //--------------------------------------------------------------------- 47 | // Assignment Operators 48 | //--------------------------------------------------------------------- 49 | 50 | Vector3& operator=(const Vector3& v) = default; 51 | Vector3& operator=(Vector3&& v) = default; 52 | 53 | //--------------------------------------------------------------------- 54 | // Member Methods 55 | //--------------------------------------------------------------------- 56 | 57 | [[nodiscard]] 58 | bool HasNaNs() const noexcept { 59 | return std::isnan(m_x) || std::isnan(m_y) || std::isnan(m_z); 60 | } 61 | 62 | [[nodiscard]] 63 | constexpr const Vector3 operator-() const noexcept { 64 | return { -m_x, -m_y, -m_z }; 65 | } 66 | 67 | [[nodiscard]] 68 | constexpr const Vector3 operator+(const Vector3& v) const noexcept { 69 | return { m_x + v.m_x, m_y + v.m_y, m_z + v.m_z }; 70 | } 71 | 72 | [[nodiscard]] 73 | constexpr const Vector3 operator-(const Vector3& v) const noexcept { 74 | return { m_x - v.m_x, m_y - v.m_y, m_z - v.m_z }; 75 | } 76 | 77 | [[nodiscard]] 78 | constexpr const Vector3 operator*(const Vector3& v) const noexcept { 79 | return { m_x * v.m_x, m_y * v.m_y, m_z * v.m_z }; 80 | } 81 | 82 | [[nodiscard]] 83 | constexpr const Vector3 operator/(const Vector3& v) const noexcept { 84 | return { m_x / v.m_x, m_y / v.m_y, m_z / v.m_z }; 85 | } 86 | 87 | [[nodiscard]] 88 | constexpr const Vector3 operator+(double a) const noexcept { 89 | return { m_x + a, m_y + a, m_z + a }; 90 | } 91 | 92 | [[nodiscard]] 93 | constexpr const Vector3 operator-(double a) const noexcept { 94 | return { m_x - a, m_y - a, m_z - a }; 95 | } 96 | 97 | [[nodiscard]] 98 | constexpr const Vector3 operator*(double a) const noexcept { 99 | return { m_x * a, m_y * a, m_z * a }; 100 | } 101 | 102 | [[nodiscard]] 103 | constexpr const Vector3 operator/(double a) const noexcept { 104 | const double inv_a = 1.0 / a; 105 | return { m_x * inv_a, m_y * inv_a, m_z * inv_a }; 106 | } 107 | 108 | Vector3& operator+=(const Vector3& v) noexcept { 109 | m_x += v.m_x; 110 | m_y += v.m_y; 111 | m_z += v.m_z; 112 | return *this; 113 | } 114 | 115 | Vector3& operator-=(const Vector3& v) noexcept { 116 | m_x -= v.m_x; 117 | m_y -= v.m_y; 118 | m_z -= v.m_z; 119 | return *this; 120 | } 121 | 122 | Vector3& operator*=(const Vector3& v) noexcept { 123 | m_x *= v.m_x; 124 | m_y *= v.m_y; 125 | m_z *= v.m_z; 126 | return *this; 127 | } 128 | 129 | Vector3& operator/=(const Vector3& v) noexcept { 130 | m_x /= v.m_x; 131 | m_y /= v.m_y; 132 | m_z /= v.m_z; 133 | return *this; 134 | } 135 | 136 | Vector3& operator+=(double a) noexcept { 137 | m_x += a; 138 | m_y += a; 139 | m_z += a; 140 | return *this; 141 | } 142 | 143 | Vector3& operator-=(double a) noexcept { 144 | m_x -= a; 145 | m_y -= a; 146 | m_z -= a; 147 | return *this; 148 | } 149 | 150 | Vector3& operator*=(double a) noexcept { 151 | m_x *= a; 152 | m_y *= a; 153 | m_z *= a; 154 | return *this; 155 | } 156 | 157 | Vector3& operator/=(double a) noexcept { 158 | const double inv_a = 1.0 / a; 159 | m_x *= inv_a; 160 | m_y *= inv_a; 161 | m_z *= inv_a; 162 | return *this; 163 | } 164 | 165 | [[nodiscard]] 166 | constexpr double Dot(const Vector3& v) const noexcept { 167 | return m_x * v.m_x + m_y * v.m_y + m_z * v.m_z; 168 | } 169 | 170 | [[nodiscard]] 171 | constexpr const Vector3 Cross(const Vector3& v) const noexcept { 172 | return { 173 | m_y * v.m_z - m_z * v.m_y, 174 | m_z * v.m_x - m_x * v.m_z, 175 | m_x * v.m_y - m_y * v.m_x 176 | }; 177 | } 178 | 179 | [[nodiscard]] 180 | constexpr bool operator==(const Vector3& rhs) const { 181 | return m_x == rhs.m_x && m_y == rhs.m_y && m_z == rhs.m_z; 182 | } 183 | 184 | [[nodiscard]] 185 | constexpr bool operator!=(const Vector3& rhs) const { 186 | return !(*this == rhs); 187 | } 188 | 189 | [[nodiscard]] 190 | double& operator[](std::size_t i) noexcept { 191 | return (&m_x)[i]; 192 | } 193 | 194 | [[nodiscard]] 195 | constexpr double operator[](std::size_t i) const noexcept { 196 | return (&m_x)[i]; 197 | } 198 | 199 | [[nodiscard]] 200 | constexpr std::size_t MinDimension() const noexcept { 201 | return (m_x < m_y && m_x < m_z) ? 0u : ((m_y < m_z) ? 1u : 2u); 202 | } 203 | 204 | [[nodiscard]] 205 | constexpr std::size_t MaxDimension() const noexcept { 206 | return (m_x > m_y && m_x > m_z) ? 0u : ((m_y > m_z) ? 1u : 2u); 207 | } 208 | 209 | [[nodiscard]] 210 | constexpr double Min() const noexcept { 211 | return std::min(m_x, std::min(m_y, m_z)); 212 | } 213 | [[nodiscard]] 214 | constexpr double Max() const noexcept { 215 | return std::max(m_x, std::max(m_y, m_z)); 216 | } 217 | 218 | [[nodiscard]] 219 | constexpr double Norm2_squared() const noexcept { 220 | return m_x * m_x + m_y * m_y + m_z * m_z; 221 | } 222 | 223 | [[nodiscard]] 224 | double Norm2() const noexcept { 225 | return std::sqrt(Norm2_squared()); 226 | } 227 | 228 | void Normalize() noexcept { 229 | const double a = 1.0 / Norm2(); 230 | m_x *= a; 231 | m_y *= a; 232 | m_z *= a; 233 | } 234 | 235 | //--------------------------------------------------------------------- 236 | // Member Variables 237 | //--------------------------------------------------------------------- 238 | 239 | double m_x, m_y, m_z; 240 | }; 241 | 242 | //------------------------------------------------------------------------- 243 | // Vector3 Utilities 244 | //------------------------------------------------------------------------- 245 | 246 | std::ostream& operator<<(std::ostream& os, const Vector3& v) { 247 | os << '[' << v.m_x << ' ' << v.m_y << ' ' << v.m_z << ']'; 248 | return os; 249 | } 250 | 251 | [[nodiscard]] 252 | constexpr const Vector3 operator+(double a, const Vector3& v) noexcept { 253 | return { a + v.m_x, a + v.m_y, a + v.m_z }; 254 | } 255 | 256 | [[nodiscard]] 257 | constexpr const Vector3 operator-(double a, const Vector3& v) noexcept { 258 | return { a - v.m_x, a - v.m_y, a - v.m_z }; 259 | } 260 | 261 | [[nodiscard]] 262 | constexpr const Vector3 operator*(double a, const Vector3& v) noexcept { 263 | return { a * v.m_x, a * v.m_y, a * v.m_z }; 264 | } 265 | 266 | [[nodiscard]] 267 | constexpr const Vector3 operator/(double a, const Vector3& v) noexcept { 268 | return { a / v.m_x, a / v.m_y, a / v.m_z }; 269 | } 270 | 271 | [[nodiscard]] 272 | inline const Vector3 Sqrt(const Vector3& v) noexcept { 273 | return { 274 | std::sqrt(v.m_x), 275 | std::sqrt(v.m_y), 276 | std::sqrt(v.m_z) 277 | }; 278 | } 279 | 280 | [[nodiscard]] 281 | inline const Vector3 Pow(const Vector3& v, double a) noexcept { 282 | return { 283 | std::pow(v.m_x, a), 284 | std::pow(v.m_y, a), 285 | std::pow(v.m_z, a) 286 | }; 287 | } 288 | 289 | [[nodiscard]] 290 | inline const Vector3 Abs(const Vector3& v) noexcept { 291 | return { 292 | std::abs(v.m_x), 293 | std::abs(v.m_y), 294 | std::abs(v.m_z) 295 | }; 296 | } 297 | 298 | [[nodiscard]] 299 | constexpr const Vector3 Min(const Vector3& v1, const Vector3& v2) noexcept { 300 | return { 301 | std::min(v1.m_x, v2.m_x), 302 | std::min(v1.m_y, v2.m_y), 303 | std::min(v1.m_z, v2.m_z) 304 | }; 305 | } 306 | 307 | [[nodiscard]] 308 | constexpr const Vector3 Max(const Vector3& v1, const Vector3& v2) noexcept { 309 | return { 310 | std::max(v1.m_x, v2.m_x), 311 | std::max(v1.m_y, v2.m_y), 312 | std::max(v1.m_z, v2.m_z) 313 | }; 314 | } 315 | 316 | [[nodiscard]] 317 | inline const Vector3 Round(const Vector3& v) noexcept { 318 | return { 319 | std::round(v.m_x), 320 | std::round(v.m_y), 321 | std::round(v.m_z) 322 | }; 323 | } 324 | 325 | [[nodiscard]] 326 | inline const Vector3 Floor(const Vector3& v) noexcept { 327 | return { 328 | std::floor(v.m_x), 329 | std::floor(v.m_y), 330 | std::floor(v.m_z) 331 | }; 332 | } 333 | 334 | [[nodiscard]] 335 | inline const Vector3 Ceil(const Vector3& v) noexcept { 336 | return { 337 | std::ceil(v.m_x), 338 | std::ceil(v.m_y), 339 | std::ceil(v.m_z) 340 | }; 341 | } 342 | 343 | [[nodiscard]] 344 | inline const Vector3 Trunc(const Vector3& v) noexcept { 345 | return { 346 | std::trunc(v.m_x), 347 | std::trunc(v.m_y), 348 | std::trunc(v.m_z) 349 | }; 350 | } 351 | 352 | [[nodiscard]] 353 | constexpr const Vector3 Clamp(const Vector3& v, 354 | double low = 0.0, 355 | double high = 1.0) noexcept { 356 | 357 | return { 358 | std::clamp(v.m_x, low, high), 359 | std::clamp(v.m_y, low, high), 360 | std::clamp(v.m_z, low, high) } 361 | ; 362 | } 363 | [[nodiscard]] 364 | constexpr const Vector3 Lerp(double a, 365 | const Vector3& v1, 366 | const Vector3& v2) noexcept { 367 | 368 | return v1 + a * (v2 - v1); 369 | } 370 | 371 | template< std::size_t X, std::size_t Y, std::size_t Z > 372 | [[nodiscard]] 373 | constexpr const Vector3 Permute(const Vector3& v) noexcept { 374 | return { v[X], v[Y], v[Z] }; 375 | } 376 | 377 | [[nodiscard]] 378 | inline const Vector3 Normalize(const Vector3& v) noexcept { 379 | const double a = 1.0 / v.Norm2(); 380 | return a * v; 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/vector.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include "math.hpp" 9 | 10 | #pragma endregion 11 | 12 | //----------------------------------------------------------------------------- 13 | // System Includes 14 | //----------------------------------------------------------------------------- 15 | #pragma region 16 | 17 | #include 18 | 19 | #pragma endregion 20 | 21 | //----------------------------------------------------------------------------- 22 | // Declarations and Definitions 23 | //----------------------------------------------------------------------------- 24 | namespace smallpt { 25 | 26 | //------------------------------------------------------------------------- 27 | // Vector3 28 | //------------------------------------------------------------------------- 29 | 30 | struct Vector3 { 31 | 32 | public: 33 | 34 | //--------------------------------------------------------------------- 35 | // Constructors and Destructors 36 | //--------------------------------------------------------------------- 37 | 38 | constexpr explicit Vector3(double xyz = 0.0) noexcept 39 | : Vector3(xyz, xyz, xyz) {} 40 | constexpr Vector3(double x, double y, double z) noexcept 41 | : m_x(x), m_y(y), m_z(z) {} 42 | constexpr Vector3(const Vector3& v) noexcept = default; 43 | constexpr Vector3(Vector3&& v) noexcept = default; 44 | ~Vector3() = default; 45 | 46 | //--------------------------------------------------------------------- 47 | // Assignment Operators 48 | //--------------------------------------------------------------------- 49 | 50 | Vector3& operator=(const Vector3& v) = default; 51 | Vector3& operator=(Vector3&& v) = default; 52 | 53 | //--------------------------------------------------------------------- 54 | // Member Methods 55 | //--------------------------------------------------------------------- 56 | 57 | [[nodiscard]] 58 | bool HasNaNs() const noexcept { 59 | return std::isnan(m_x) || std::isnan(m_y) || std::isnan(m_z); 60 | } 61 | 62 | [[nodiscard]] 63 | constexpr const Vector3 operator-() const noexcept { 64 | return { -m_x, -m_y, -m_z }; 65 | } 66 | 67 | [[nodiscard]] 68 | constexpr const Vector3 operator+(const Vector3& v) const noexcept { 69 | return { m_x + v.m_x, m_y + v.m_y, m_z + v.m_z }; 70 | } 71 | 72 | [[nodiscard]] 73 | constexpr const Vector3 operator-(const Vector3& v) const noexcept { 74 | return { m_x - v.m_x, m_y - v.m_y, m_z - v.m_z }; 75 | } 76 | 77 | [[nodiscard]] 78 | constexpr const Vector3 operator*(const Vector3& v) const noexcept { 79 | return { m_x * v.m_x, m_y * v.m_y, m_z * v.m_z }; 80 | } 81 | 82 | [[nodiscard]] 83 | constexpr const Vector3 operator/(const Vector3& v) const noexcept { 84 | return { m_x / v.m_x, m_y / v.m_y, m_z / v.m_z }; 85 | } 86 | 87 | [[nodiscard]] 88 | constexpr const Vector3 operator+(double a) const noexcept { 89 | return { m_x + a, m_y + a, m_z + a }; 90 | } 91 | 92 | [[nodiscard]] 93 | constexpr const Vector3 operator-(double a) const noexcept { 94 | return { m_x - a, m_y - a, m_z - a }; 95 | } 96 | 97 | [[nodiscard]] 98 | constexpr const Vector3 operator*(double a) const noexcept { 99 | return { m_x * a, m_y * a, m_z * a }; 100 | } 101 | 102 | [[nodiscard]] 103 | constexpr const Vector3 operator/(double a) const noexcept { 104 | const double inv_a = 1.0 / a; 105 | return { m_x * inv_a, m_y * inv_a, m_z * inv_a }; 106 | } 107 | 108 | Vector3& operator+=(const Vector3& v) noexcept { 109 | m_x += v.m_x; 110 | m_y += v.m_y; 111 | m_z += v.m_z; 112 | return *this; 113 | } 114 | 115 | Vector3& operator-=(const Vector3& v) noexcept { 116 | m_x -= v.m_x; 117 | m_y -= v.m_y; 118 | m_z -= v.m_z; 119 | return *this; 120 | } 121 | 122 | Vector3& operator*=(const Vector3& v) noexcept { 123 | m_x *= v.m_x; 124 | m_y *= v.m_y; 125 | m_z *= v.m_z; 126 | return *this; 127 | } 128 | 129 | Vector3& operator/=(const Vector3& v) noexcept { 130 | m_x /= v.m_x; 131 | m_y /= v.m_y; 132 | m_z /= v.m_z; 133 | return *this; 134 | } 135 | 136 | Vector3& operator+=(double a) noexcept { 137 | m_x += a; 138 | m_y += a; 139 | m_z += a; 140 | return *this; 141 | } 142 | 143 | Vector3& operator-=(double a) noexcept { 144 | m_x -= a; 145 | m_y -= a; 146 | m_z -= a; 147 | return *this; 148 | } 149 | 150 | Vector3& operator*=(double a) noexcept { 151 | m_x *= a; 152 | m_y *= a; 153 | m_z *= a; 154 | return *this; 155 | } 156 | 157 | Vector3& operator/=(double a) noexcept { 158 | const double inv_a = 1.0 / a; 159 | m_x *= inv_a; 160 | m_y *= inv_a; 161 | m_z *= inv_a; 162 | return *this; 163 | } 164 | 165 | [[nodiscard]] 166 | constexpr double Dot(const Vector3& v) const noexcept { 167 | return m_x * v.m_x + m_y * v.m_y + m_z * v.m_z; 168 | } 169 | 170 | [[nodiscard]] 171 | constexpr const Vector3 Cross(const Vector3& v) const noexcept { 172 | return { 173 | m_y * v.m_z - m_z * v.m_y, 174 | m_z * v.m_x - m_x * v.m_z, 175 | m_x * v.m_y - m_y * v.m_x 176 | }; 177 | } 178 | 179 | [[nodiscard]] 180 | constexpr bool operator==(const Vector3& rhs) const { 181 | return m_x == rhs.m_x && m_y == rhs.m_y && m_z == rhs.m_z; 182 | } 183 | 184 | [[nodiscard]] 185 | constexpr bool operator!=(const Vector3& rhs) const { 186 | return !(*this == rhs); 187 | } 188 | 189 | [[nodiscard]] 190 | double& operator[](std::size_t i) noexcept { 191 | return (&m_x)[i]; 192 | } 193 | 194 | [[nodiscard]] 195 | constexpr double operator[](std::size_t i) const noexcept { 196 | return (&m_x)[i]; 197 | } 198 | 199 | [[nodiscard]] 200 | constexpr std::size_t MinDimension() const noexcept { 201 | return (m_x < m_y && m_x < m_z) ? 0u : ((m_y < m_z) ? 1u : 2u); 202 | } 203 | 204 | [[nodiscard]] 205 | constexpr std::size_t MaxDimension() const noexcept { 206 | return (m_x > m_y && m_x > m_z) ? 0u : ((m_y > m_z) ? 1u : 2u); 207 | } 208 | 209 | [[nodiscard]] 210 | constexpr double Min() const noexcept { 211 | return std::min(m_x, std::min(m_y, m_z)); 212 | } 213 | [[nodiscard]] 214 | constexpr double Max() const noexcept { 215 | return std::max(m_x, std::max(m_y, m_z)); 216 | } 217 | 218 | [[nodiscard]] 219 | constexpr double Norm2_squared() const noexcept { 220 | return m_x * m_x + m_y * m_y + m_z * m_z; 221 | } 222 | 223 | [[nodiscard]] 224 | double Norm2() const noexcept { 225 | return std::sqrt(Norm2_squared()); 226 | } 227 | 228 | void Normalize() noexcept { 229 | const double a = 1.0 / Norm2(); 230 | m_x *= a; 231 | m_y *= a; 232 | m_z *= a; 233 | } 234 | 235 | //--------------------------------------------------------------------- 236 | // Member Variables 237 | //--------------------------------------------------------------------- 238 | 239 | double m_x, m_y, m_z; 240 | }; 241 | 242 | //------------------------------------------------------------------------- 243 | // Vector3 Utilities 244 | //------------------------------------------------------------------------- 245 | 246 | std::ostream& operator<<(std::ostream& os, const Vector3& v) { 247 | os << '[' << v.m_x << ' ' << v.m_y << ' ' << v.m_z << ']'; 248 | return os; 249 | } 250 | 251 | [[nodiscard]] 252 | constexpr const Vector3 operator+(double a, const Vector3& v) noexcept { 253 | return { a + v.m_x, a + v.m_y, a + v.m_z }; 254 | } 255 | 256 | [[nodiscard]] 257 | constexpr const Vector3 operator-(double a, const Vector3& v) noexcept { 258 | return { a - v.m_x, a - v.m_y, a - v.m_z }; 259 | } 260 | 261 | [[nodiscard]] 262 | constexpr const Vector3 operator*(double a, const Vector3& v) noexcept { 263 | return { a * v.m_x, a * v.m_y, a * v.m_z }; 264 | } 265 | 266 | [[nodiscard]] 267 | constexpr const Vector3 operator/(double a, const Vector3& v) noexcept { 268 | return { a / v.m_x, a / v.m_y, a / v.m_z }; 269 | } 270 | 271 | [[nodiscard]] 272 | inline const Vector3 Sqrt(const Vector3& v) noexcept { 273 | return { 274 | std::sqrt(v.m_x), 275 | std::sqrt(v.m_y), 276 | std::sqrt(v.m_z) 277 | }; 278 | } 279 | 280 | [[nodiscard]] 281 | inline const Vector3 Pow(const Vector3& v, double a) noexcept { 282 | return { 283 | std::pow(v.m_x, a), 284 | std::pow(v.m_y, a), 285 | std::pow(v.m_z, a) 286 | }; 287 | } 288 | 289 | [[nodiscard]] 290 | inline const Vector3 Abs(const Vector3& v) noexcept { 291 | return { 292 | std::abs(v.m_x), 293 | std::abs(v.m_y), 294 | std::abs(v.m_z) 295 | }; 296 | } 297 | 298 | [[nodiscard]] 299 | constexpr const Vector3 Min(const Vector3& v1, const Vector3& v2) noexcept { 300 | return { 301 | std::min(v1.m_x, v2.m_x), 302 | std::min(v1.m_y, v2.m_y), 303 | std::min(v1.m_z, v2.m_z) 304 | }; 305 | } 306 | 307 | [[nodiscard]] 308 | constexpr const Vector3 Max(const Vector3& v1, const Vector3& v2) noexcept { 309 | return { 310 | std::max(v1.m_x, v2.m_x), 311 | std::max(v1.m_y, v2.m_y), 312 | std::max(v1.m_z, v2.m_z) 313 | }; 314 | } 315 | 316 | [[nodiscard]] 317 | inline const Vector3 Round(const Vector3& v) noexcept { 318 | return { 319 | std::round(v.m_x), 320 | std::round(v.m_y), 321 | std::round(v.m_z) 322 | }; 323 | } 324 | 325 | [[nodiscard]] 326 | inline const Vector3 Floor(const Vector3& v) noexcept { 327 | return { 328 | std::floor(v.m_x), 329 | std::floor(v.m_y), 330 | std::floor(v.m_z) 331 | }; 332 | } 333 | 334 | [[nodiscard]] 335 | inline const Vector3 Ceil(const Vector3& v) noexcept { 336 | return { 337 | std::ceil(v.m_x), 338 | std::ceil(v.m_y), 339 | std::ceil(v.m_z) 340 | }; 341 | } 342 | 343 | [[nodiscard]] 344 | inline const Vector3 Trunc(const Vector3& v) noexcept { 345 | return { 346 | std::trunc(v.m_x), 347 | std::trunc(v.m_y), 348 | std::trunc(v.m_z) 349 | }; 350 | } 351 | 352 | [[nodiscard]] 353 | constexpr const Vector3 Clamp(const Vector3& v, 354 | double low = 0.0, 355 | double high = 1.0) noexcept { 356 | 357 | return { 358 | std::clamp(v.m_x, low, high), 359 | std::clamp(v.m_y, low, high), 360 | std::clamp(v.m_z, low, high) } 361 | ; 362 | } 363 | [[nodiscard]] 364 | constexpr const Vector3 Lerp(double a, 365 | const Vector3& v1, 366 | const Vector3& v2) noexcept { 367 | 368 | return v1 + a * (v2 - v1); 369 | } 370 | 371 | template< std::size_t X, std::size_t Y, std::size_t Z > 372 | [[nodiscard]] 373 | constexpr const Vector3 Permute(const Vector3& v) noexcept { 374 | return { v[X], v[Y], v[Z] }; 375 | } 376 | 377 | [[nodiscard]] 378 | inline const Vector3 Normalize(const Vector3& v) noexcept { 379 | const double a = 1.0 / v.Norm2(); 380 | return a * v; 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /threads-cpp-smallpt/cpp-smallpt/src/lock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //----------------------------------------------------------------------------- 4 | // System Includes 5 | //----------------------------------------------------------------------------- 6 | #pragma region 7 | 8 | #include 9 | #include "windows.hpp" 10 | 11 | #pragma endregion 12 | 13 | //----------------------------------------------------------------------------- 14 | // Declarations and Definitions 15 | //----------------------------------------------------------------------------- 16 | namespace smallpt { 17 | 18 | /** 19 | A class of mutexes. 20 | */ 21 | class Mutex final { 22 | 23 | public: 24 | 25 | friend class MutexLock; 26 | 27 | //--------------------------------------------------------------------- 28 | // Constructors and Destructors 29 | //--------------------------------------------------------------------- 30 | 31 | /** 32 | Constructs a mutex. 33 | */ 34 | Mutex(); 35 | 36 | /** 37 | Constructs a mutex from the given mutex. 38 | 39 | @param[in] mutex 40 | A reference to the mutex to copy. 41 | */ 42 | Mutex(const Mutex& mutex) = delete; 43 | 44 | /** 45 | Constructs a mutex by moving the given mutex. 46 | 47 | @param[in] mutex 48 | A reference to the mutex to move. 49 | */ 50 | Mutex(Mutex&& mutex) = default; 51 | 52 | /** 53 | Destructs this mutex. 54 | */ 55 | ~Mutex(); 56 | 57 | //--------------------------------------------------------------------- 58 | // Assignment Operators 59 | //--------------------------------------------------------------------- 60 | 61 | /** 62 | Copies the given mutex to this mutex. 63 | 64 | @param[in] mutex 65 | A reference to the mutex to copy. 66 | @return A reference to the copy of the given mutex 67 | (i.e. this mutex). 68 | */ 69 | Mutex& operator=(const Mutex& mutex) = delete; 70 | 71 | /** 72 | Moves the given mutex to this mutex. 73 | 74 | @param[in] mutex 75 | A reference to the mutex to move. 76 | @return A reference to the moved mutex 77 | (i.e. this mutex). 78 | */ 79 | Mutex& operator=(Mutex&& mutex) = delete; 80 | 81 | private: 82 | 83 | //--------------------------------------------------------------------- 84 | // Member Variables 85 | //--------------------------------------------------------------------- 86 | 87 | /** 88 | The critical section object of this mutex. 89 | */ 90 | CRITICAL_SECTION m_critical_section; 91 | }; 92 | 93 | /** 94 | A class of mutex locks. 95 | */ 96 | class MutexLock final { 97 | 98 | public: 99 | 100 | //--------------------------------------------------------------------- 101 | // Constructors and Destructors 102 | //--------------------------------------------------------------------- 103 | 104 | /** 105 | Constructs a mutex lock for the given mutex. 106 | 107 | @param[in] mutex 108 | A reference to the mutex. 109 | */ 110 | explicit MutexLock(Mutex& mutex); 111 | 112 | /** 113 | Constructs a mutex lock from the given mutex lock. 114 | 115 | @param[in] mutex_lock 116 | A reference to the mutex lock to copy. 117 | */ 118 | MutexLock(const MutexLock& mutex_lock) = delete; 119 | 120 | /** 121 | Constructs a mutex lock by moving the given mutex lock. 122 | 123 | @param[in] mutex_lock 124 | A reference to the mutex lock to move. 125 | */ 126 | MutexLock(MutexLock&& mutex_lock) = default; 127 | 128 | /** 129 | Destructs this mutex lock. 130 | */ 131 | ~MutexLock(); 132 | 133 | //--------------------------------------------------------------------- 134 | // Assignment Operators 135 | //--------------------------------------------------------------------- 136 | 137 | /** 138 | Copies the given mutex lock to this mutex lock. 139 | 140 | @param[in] mutex_lock 141 | A reference to the mutex lock to copy. 142 | @return A reference to the copy of the given mutex lock 143 | (i.e. this mutex lock) 144 | */ 145 | MutexLock& operator=(const MutexLock& mutex_lock) = delete; 146 | 147 | /** 148 | Moves the given mutex lock to this mutex lock. 149 | 150 | @param[in] mutex_lock 151 | A reference to the mutex lock to move. 152 | @return A reference to the moved mutex lock 153 | (i.e. this mutex lock) 154 | */ 155 | MutexLock& operator=(MutexLock&& mutex_lock) = delete; 156 | 157 | private: 158 | 159 | //--------------------------------------------------------------------- 160 | // Member Methods 161 | //--------------------------------------------------------------------- 162 | 163 | /** 164 | A reference to the mutex of this mutex lock. 165 | */ 166 | Mutex& m_mutex; 167 | }; 168 | 169 | /** 170 | A class of semaphores. 171 | */ 172 | class Semaphore final { 173 | 174 | public: 175 | 176 | //--------------------------------------------------------------------- 177 | // Constructors and Destructors 178 | //--------------------------------------------------------------------- 179 | 180 | /** 181 | Constructs a semaphore. 182 | */ 183 | Semaphore(); 184 | 185 | /** 186 | Constructs a semaphore from the given semaphore. 187 | 188 | @param[in] semaphore 189 | A reference to the semaphore to copy. 190 | */ 191 | Semaphore(const Semaphore& semaphore) = delete; 192 | 193 | /** 194 | Constructs a semaphore by moving the given semaphore. 195 | 196 | @param[in] semaphore 197 | A reference to the semaphore to move. 198 | */ 199 | Semaphore(Semaphore&& semaphore) = default; 200 | 201 | /** 202 | Destructs this semaphore. 203 | */ 204 | ~Semaphore(); 205 | 206 | //--------------------------------------------------------------------- 207 | // Assignment Operators 208 | //--------------------------------------------------------------------- 209 | 210 | /** 211 | Copies the given semaphore to this semaphore. 212 | 213 | @param[in] semaphore 214 | A reference to the semaphore to copy. 215 | @return A reference to the copy of the given semaphore 216 | (i.e. this semaphore) 217 | */ 218 | Semaphore& operator=(const Semaphore& semaphore) = delete; 219 | 220 | /** 221 | Copies the given semaphore to this semaphore. 222 | 223 | @param[in] semaphore 224 | A reference to the semaphore to move. 225 | @return A reference to the moved semaphore 226 | (i.e. this semaphore) 227 | */ 228 | Semaphore& operator=(Semaphore&& semaphore) = delete; 229 | 230 | //--------------------------------------------------------------------- 231 | // Member Methods 232 | //--------------------------------------------------------------------- 233 | 234 | /** 235 | Increments the value of this semaphore variable by the given value. 236 | 237 | If the initial value of the semaphore is negative, the waiting queue is not 238 | empty and thus one blocked process can be transferred to the ready queue. 239 | 240 | @param[in] count 241 | The increment value. 242 | */ 243 | void Signal(std::uint32_t count = 1u) noexcept; 244 | 245 | /** 246 | Decrements the value of this semaphore variable by one. 247 | 248 | The process executing wait is blocked until the value of the semaphore 249 | is greater or equal to 1. 250 | */ 251 | void Wait() noexcept; 252 | 253 | /** 254 | Checks whether waiting for this semaphore would be necessary. 255 | 256 | @return @c true if waiting for this semaphore would be necessary. 257 | @c false otherwise. 258 | */ 259 | [[nodiscard]] 260 | bool TryWait() noexcept; 261 | 262 | private: 263 | 264 | //--------------------------------------------------------------------- 265 | // Member Variables 266 | //--------------------------------------------------------------------- 267 | 268 | /** 269 | The handle of this semaphore. 270 | */ 271 | HANDLE m_handle; 272 | }; 273 | 274 | /** 275 | A class of condition variables. 276 | */ 277 | class ConditionVariable final { 278 | 279 | public: 280 | 281 | //--------------------------------------------------------------------- 282 | // Constructors and Destructors 283 | //--------------------------------------------------------------------- 284 | 285 | /** 286 | Constructs a condition variable. 287 | */ 288 | ConditionVariable(); 289 | 290 | /** 291 | Constructs a condition variable from the given condition variable. 292 | 293 | @param[in] condition_variable 294 | A reference to the condition variable to copy. 295 | */ 296 | ConditionVariable(const ConditionVariable& condition_variable) = delete; 297 | 298 | /** 299 | Constructs a condition variable by moving the given condition variable. 300 | 301 | @param[in] condition_variable 302 | A reference to the condition variable to move. 303 | */ 304 | ConditionVariable(ConditionVariable&& condition_variable) = default; 305 | 306 | /** 307 | Destructs this condition variable. 308 | */ 309 | ~ConditionVariable(); 310 | 311 | //--------------------------------------------------------------------- 312 | // Assignment Operators 313 | //--------------------------------------------------------------------- 314 | 315 | /** 316 | Copies the given condition variable to this condition variable. 317 | 318 | @param[in] condition_variable 319 | A reference to the condition variable to copy. 320 | @return A reference to the copy of the given condition variable 321 | (i.e. this condition variable) 322 | */ 323 | ConditionVariable& operator=(const ConditionVariable& condition_variable) = delete; 324 | 325 | /** 326 | Moves the given condition variable to this condition variable. 327 | 328 | @param[in] condition_variable 329 | A reference to the condition variable to move. 330 | @return A reference to the moved condition variable 331 | (i.e. this condition variable) 332 | */ 333 | ConditionVariable& operator=(ConditionVariable&& condition_variable) = delete; 334 | 335 | //--------------------------------------------------------------------- 336 | // Member Methods 337 | //--------------------------------------------------------------------- 338 | 339 | /** 340 | Locks this condition variable. 341 | */ 342 | void Lock() noexcept; 343 | 344 | /** 345 | Unlocks this condition variable. 346 | */ 347 | void Unlock() noexcept; 348 | 349 | /** 350 | Signals a condition change. 351 | */ 352 | void Signal() noexcept; 353 | 354 | /** 355 | Waits for a signal indicating a condition change. 356 | */ 357 | void Wait() noexcept; 358 | 359 | private: 360 | 361 | //--------------------------------------------------------------------- 362 | // Member Variables 363 | //--------------------------------------------------------------------- 364 | 365 | /** 366 | The number of waiters of this condition variable. 367 | */ 368 | std::uint32_t m_nb_waiters; 369 | 370 | /** 371 | The critical section object for the mutex guarding @c m_nb_waiters 372 | of this condition variable. 373 | */ 374 | CRITICAL_SECTION m_nb_waiters_mutex; 375 | 376 | /** 377 | The critical section object for the mutex guarding the condition 378 | of this condition variable. 379 | */ 380 | CRITICAL_SECTION m_condition_mutex; 381 | 382 | /** 383 | An enumeration of the different types of events of this condition variable. 384 | */ 385 | enum Event { 386 | SIGNAL = 0, 387 | BROADCAST = 1, 388 | COUNT = 2 389 | }; 390 | 391 | /** 392 | The signal and broadcast event handles of this condition variable. 393 | */ 394 | HANDLE m_events[COUNT]; 395 | }; 396 | } --------------------------------------------------------------------------------