diff --git a/example02_threaded_raytracing/.clang-format b/example02_threaded_raytracing/.clang-format new file mode 100644 index 0000000..dfe786c --- /dev/null +++ b/example02_threaded_raytracing/.clang-format @@ -0,0 +1,166 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +StatementAttributeLikeMacros: + - Q_EMIT +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/example02_threaded_raytracing/src/argParse.cpp b/example02_threaded_raytracing/src/argParse.cpp index 6187e6c..7f26892 100644 --- a/example02_threaded_raytracing/src/argParse.cpp +++ b/example02_threaded_raytracing/src/argParse.cpp @@ -2,34 +2,36 @@ #include -Ex02::ArgParse::ParseResult Ex02::ArgParse::parseArgs( - int argc, - char **argv, - const Ex02::ArgParse::ArgsType &singleArgs, - const Ex02::ArgParse::ArgsType &doubleArgs) { - ParseResult result; - bool found; - --argc; ++argv; - while(argc > 0) { - found = false; - for(const std::string &singleArg : singleArgs) { - if(std::strcmp(argv[0], singleArg.c_str()) == 0) { - result.insert({singleArg, EX02_ARG_PARSE_SINGLE_ARG_PLACEHOLDER}); - found = true; - break; - } - } - if(!found && argc > 1) { - for(const std::string &doubleArg: doubleArgs) { - if(std::strcmp(argv[0], doubleArg.c_str()) == 0) { - result.insert({doubleArg, argv[1]}); - --argc; ++argv; - break; - } - } - } - --argc; ++argv; +Ex02::ArgParse::ParseResult +Ex02::ArgParse::parseArgs(int argc, char **argv, + const Ex02::ArgParse::ArgsType &singleArgs, + const Ex02::ArgParse::ArgsType &doubleArgs) { + ParseResult result; + bool found; + --argc; + ++argv; + while (argc > 0) { + found = false; + for (const std::string &singleArg : singleArgs) { + if (std::strcmp(argv[0], singleArg.c_str()) == 0) { + result.insert({singleArg, EX02_ARG_PARSE_SINGLE_ARG_PLACEHOLDER}); + found = true; + break; + } } + if (!found && argc > 1) { + for (const std::string &doubleArg : doubleArgs) { + if (std::strcmp(argv[0], doubleArg.c_str()) == 0) { + result.insert({doubleArg, argv[1]}); + --argc; + ++argv; + break; + } + } + } + --argc; + ++argv; + } - return result; + return result; } diff --git a/example02_threaded_raytracing/src/argParse.hpp b/example02_threaded_raytracing/src/argParse.hpp index f7d6aab..d128712 100644 --- a/example02_threaded_raytracing/src/argParse.hpp +++ b/example02_threaded_raytracing/src/argParse.hpp @@ -4,16 +4,17 @@ #define EX02_ARG_PARSE_SINGLE_ARG_PLACEHOLDER "SINGLE_ARG_PLACEHOLDER" #include -#include #include +#include namespace Ex02 { namespace ArgParse { -typedef std::unordered_set ArgsType; -typedef std::unordered_map ParseResult; + typedef std::unordered_set ArgsType; + typedef std::unordered_map ParseResult; -ParseResult parseArgs(int argc, char **argv, const ArgsType &singleArgs, const ArgsType &doubleArgs); + ParseResult parseArgs(int argc, char **argv, const ArgsType &singleArgs, + const ArgsType &doubleArgs); } // namespace ArgParse } // namespace Ex02 diff --git a/example02_threaded_raytracing/src/main.cpp b/example02_threaded_raytracing/src/main.cpp index 2a69ba0..c37f393 100644 --- a/example02_threaded_raytracing/src/main.cpp +++ b/example02_threaded_raytracing/src/main.cpp @@ -5,129 +5,126 @@ #include "rayTracer.hpp" void printHelp() { - std::cout << "Usage:\n" - "-h | --help Display this help message\n" - "-t \n" - " | --threads Set the number of threads to use (default 1)\n" - "--width Set the width of the output image\n" - "--height Set the height of the output image\n" - "-o \n" - " | --output Set the output filename for the image" - << std::endl; + std::cout + << "Usage:\n" + "-h | --help Display this help message\n" + "-t \n" + " | --threads Set the number of threads to use " + "(default 1)\n" + "--width Set the width of the output image\n" + "--height Set the height of the output image\n" + "-o \n" + " | --output Set the output filename for the image" + << std::endl; } int main(int argc, char **argv) { - int threadCount = 1; - unsigned int outputWidth = 1600; - unsigned int outputHeight = 1600; - std::string outputFile = "raytrace_out"; + int threadCount = 1; + unsigned int outputWidth = 1600; + unsigned int outputHeight = 1600; + std::string outputFile = "raytrace_out"; - { - auto results = Ex02::ArgParse::parseArgs( - argc, - argv, - { // single args - "-h", - "--help", - }, - { // double args - "-t", - "--threads", - "--width", - "--height", - "-o", - "--output", - }); + { + auto results = Ex02::ArgParse::parseArgs(argc, argv, + { + // single args + "-h", + "--help", + }, + { + // double args + "-t", + "--threads", + "--width", + "--height", + "-o", + "--output", + }); - if(auto iter = results.find("-h"); iter != results.end()) { - printHelp(); - return 0; - } else if(auto iter = results.find("--help"); iter != results.end()) { - printHelp(); - return 0; - } - - const auto setThreadCount = [&threadCount] (auto iter) { - try { - threadCount = std::stoi(iter->second); - } catch (const std::invalid_argument &e) { - std::cout << "ERROR: Failed to parse thread count (invalid)" - << std::endl; - return 1; - } catch (const std::out_of_range &e) { - std::cout << "ERROR: Failed to parse thread count (out of range)" - << std::endl; - return 2; - } - return 0; - }; - if(auto iter = results.find("-t"); iter != results.end()) { - if(int result = setThreadCount(iter); result != 0) { - return result; - } - } else if(auto iter = results.find("--threads"); iter != results.end()) { - if(int result = setThreadCount(iter); result != 0) { - return result; - } - } - if(threadCount <= 0) { - std::cout << "ERROR: Thread count set to invalid value (" - << threadCount - << ')' - << std::endl; - return 3; - } - if(auto iter = results.find("--width"); iter != results.end()) { - try { - outputWidth = std::stoul(iter->second); - } catch (const std::invalid_argument &e) { - std::cout << "ERROR: Failed to parse width (invalid)" - << std::endl; - return 3; - } catch (const std::out_of_range &e) { - std::cout << "ERROR: Failed to parse width (out of range)" - << std::endl; - return 4; - } - } - if(outputWidth == 0) { - std::cout << "ERROR: width cannot be 0" << std::endl; - return 7; - } - if(auto iter = results.find("--height"); iter != results.end()) { - try { - outputHeight = std::stoul(iter->second); - } catch (const std::invalid_argument &e) { - std::cout << "ERROR: Failed to parse height (invalid)" - << std::endl; - return 5; - } catch (const std::out_of_range &e) { - std::cout << "ERROR: Failed to parse height (out of range)" - << std::endl; - return 6; - } - } - if(outputHeight == 0) { - std::cout << "ERROR: height cannot be 0" << std::endl; - return 8; - } - if(auto iter = results.find("-o"); iter != results.end()) { - outputFile = iter->second; - } else if(auto iter = results.find("--output"); iter != results.end()) { - outputFile = iter->second; - } - if(outputFile.empty()) { - std::cout << "ERROR: Output filename is empty" << std::endl; - return 12; - } + if (auto iter = results.find("-h"); iter != results.end()) { + printHelp(); + return 0; + } else if (auto iter = results.find("--help"); iter != results.end()) { + printHelp(); + return 0; } -// auto pixels = Ex02::RT::renderGraySphere( -// outputWidth, outputHeight, threadCount); - auto pixels = Ex02::RT::renderColorsWithSpheres( - outputWidth, outputHeight, threadCount); + const auto setThreadCount = [&threadCount](auto iter) { + try { + threadCount = std::stoi(iter->second); + } catch (const std::invalid_argument &e) { + std::cout << "ERROR: Failed to parse thread count (invalid)" + << std::endl; + return 1; + } catch (const std::out_of_range &e) { + std::cout << "ERROR: Failed to parse thread count (out of range)" + << std::endl; + return 2; + } + return 0; + }; + if (auto iter = results.find("-t"); iter != results.end()) { + if (int result = setThreadCount(iter); result != 0) { + return result; + } + } else if (auto iter = results.find("--threads"); iter != results.end()) { + if (int result = setThreadCount(iter); result != 0) { + return result; + } + } + if (threadCount <= 0) { + std::cout << "ERROR: Thread count set to invalid value (" << threadCount + << ')' << std::endl; + return 3; + } + if (auto iter = results.find("--width"); iter != results.end()) { + try { + outputWidth = std::stoul(iter->second); + } catch (const std::invalid_argument &e) { + std::cout << "ERROR: Failed to parse width (invalid)" << std::endl; + return 3; + } catch (const std::out_of_range &e) { + std::cout << "ERROR: Failed to parse width (out of range)" << std::endl; + return 4; + } + } + if (outputWidth == 0) { + std::cout << "ERROR: width cannot be 0" << std::endl; + return 7; + } + if (auto iter = results.find("--height"); iter != results.end()) { + try { + outputHeight = std::stoul(iter->second); + } catch (const std::invalid_argument &e) { + std::cout << "ERROR: Failed to parse height (invalid)" << std::endl; + return 5; + } catch (const std::out_of_range &e) { + std::cout << "ERROR: Failed to parse height (out of range)" + << std::endl; + return 6; + } + } + if (outputHeight == 0) { + std::cout << "ERROR: height cannot be 0" << std::endl; + return 8; + } + if (auto iter = results.find("-o"); iter != results.end()) { + outputFile = iter->second; + } else if (auto iter = results.find("--output"); iter != results.end()) { + outputFile = iter->second; + } + if (outputFile.empty()) { + std::cout << "ERROR: Output filename is empty" << std::endl; + return 12; + } + } - pixels.writeToFile(outputFile); + // auto pixels = Ex02::RT::renderGraySphere( + // outputWidth, outputHeight, threadCount); + auto pixels = + Ex02::RT::renderColorsWithSpheres(outputWidth, outputHeight, threadCount); - return 0; + pixels.writeToFile(outputFile); + + return 0; } diff --git a/example02_threaded_raytracing/src/rayTracer.cpp b/example02_threaded_raytracing/src/rayTracer.cpp index 2b1a121..c11ddc1 100644 --- a/example02_threaded_raytracing/src/rayTracer.cpp +++ b/example02_threaded_raytracing/src/rayTracer.cpp @@ -1,51 +1,43 @@ #include "rayTracer.hpp" +#include #include #include -#include #include -#include -#include #include +#include +#include const float PI = std::acos(-1.0f); -Ex02::RT::Pixel::Pixel() : - r(0), - g(0), - b(0) -{} +Ex02::RT::Pixel::Pixel() : r(0), g(0), b(0) {} -Ex02::RT::Image::Image(unsigned int width, unsigned int height) : - width(width) -{ - data.resize(width * height); +Ex02::RT::Image::Image(unsigned int width, unsigned int height) : width(width) { + data.resize(width * height); } -Ex02::RT::Pixel& Ex02::RT::Image::getPixel( - unsigned int x, unsigned int y) { - return data.at(x + y * width); +Ex02::RT::Pixel &Ex02::RT::Image::getPixel(unsigned int x, unsigned int y) { + return data.at(x + y * width); } -const Ex02::RT::Pixel& Ex02::RT::Image::getPixel( - unsigned int x, unsigned int y) const { - return data.at(x + y * width); +const Ex02::RT::Pixel &Ex02::RT::Image::getPixel(unsigned int x, + unsigned int y) const { + return data.at(x + y * width); } void Ex02::RT::Image::writeToFile(const std::string &filename) const { - std::ofstream out(filename + ".ppm"); - out << "P3\n" << width << ' ' << data.size() / width << " 255" - << '\n'; + std::ofstream out(filename + ".ppm"); + out << "P3\n" << width << ' ' << data.size() / width << " 255" << '\n'; - for(unsigned int j = 0; j < data.size() / width; ++j) { - for(unsigned int i = 0; i < width; ++i) { - out << (int)data.at(i + j * width).r << ' ' - << (int)data.at(i + j * width).g << ' ' - << (int)data.at(i + j * width).b << ' '; - } - out << '\n'; + for (unsigned int j = 0; j < data.size() / width; ++j) { + for (unsigned int i = 0; i < width; ++i) { + out << (int)data.at(i + j * width).r << ' ' + << (int)data.at(i + j * width).g << ' ' + << (int)data.at(i + j * width).b << ' '; } + out << '\n'; + } } /* @@ -57,7 +49,7 @@ glm::mat4x4 Ex02::RT::Internal::defaultMVP() { EX02_RAY_TRACER_DEFAULT_FAR_PLANE); mvp *= glm::lookAt( - glm::vec3{0.0f, 0.0f, 0.0f}, + glm::vec3{0.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, -1.0f}, glm::vec3{0.0f, 1.0f, 0.0f}); @@ -70,420 +62,385 @@ glm::mat4x4 Ex02::RT::Internal::defaultMVP() { } */ -Ex02::RT::Internal::LightSource::LightSource() : - pos{0.0f, 0.0f, 0.0f}, - falloffStart(2.0f), - falloffEnd(7.0f), - color{1.0f, 1.0f, 1.0f} -{} +Ex02::RT::Internal::LightSource::LightSource() + : pos{0.0f, 0.0f, 0.0f}, falloffStart(2.0f), + falloffEnd(7.0f), color{1.0f, 1.0f, 1.0f} {} -void Ex02::RT::Internal::LightSource::applyLight( - glm::vec3 pos, Pixel &pixelOut) const { - pos = this->pos - pos; - float dist = std::sqrt( - pos.x * pos.x - + pos.y * pos.y - + pos.z * pos.z); - if(dist < falloffStart) { - const auto applyColor = [] (auto *color, unsigned char *out) { - unsigned int temp = (unsigned int)*out - + (unsigned int)(*color * 255.0f); - if(temp > 255) { - *out = 255; - } else { - *out = temp; - } - }; - applyColor(&color.x, &pixelOut.r); - applyColor(&color.y, &pixelOut.g); - applyColor(&color.z, &pixelOut.b); - } else if(dist >= falloffStart && dist <= falloffEnd) { - const auto applyFalloffColor = [] (auto *color, unsigned char *out, float f) { - unsigned int temp = (unsigned int)*out - + (unsigned int)(*color * 255.0f * f); - if(temp > 255) { - *out = 255; - } else { - *out = temp; - } - }; - float f = (1.0f - (dist - falloffStart) / (falloffEnd - falloffStart)); - applyFalloffColor(&color.x, &pixelOut.r, f); - applyFalloffColor(&color.y, &pixelOut.g, f); - applyFalloffColor(&color.z, &pixelOut.b, f); - } +void Ex02::RT::Internal::LightSource::applyLight(glm::vec3 pos, + Pixel &pixelOut) const { + pos = this->pos - pos; + float dist = std::sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z); + if (dist < falloffStart) { + const auto applyColor = [](auto *color, unsigned char *out) { + unsigned int temp = (unsigned int)*out + (unsigned int)(*color * 255.0f); + if (temp > 255) { + *out = 255; + } else { + *out = temp; + } + }; + applyColor(&color.x, &pixelOut.r); + applyColor(&color.y, &pixelOut.g); + applyColor(&color.z, &pixelOut.b); + } else if (dist >= falloffStart && dist <= falloffEnd) { + const auto applyFalloffColor = [](auto *color, unsigned char *out, + float f) { + unsigned int temp = + (unsigned int)*out + (unsigned int)(*color * 255.0f * f); + if (temp > 255) { + *out = 255; + } else { + *out = temp; + } + }; + float f = (1.0f - (dist - falloffStart) / (falloffEnd - falloffStart)); + applyFalloffColor(&color.x, &pixelOut.r, f); + applyFalloffColor(&color.y, &pixelOut.g, f); + applyFalloffColor(&color.z, &pixelOut.b, f); + } } -void Ex02::RT::Internal::LightSource::applyLight( - glm::vec3 pos, Pixel &pixelOut, std::mutex* mutex) const { - pos = this->pos - pos; - float dist = std::sqrt( - pos.x * pos.x - + pos.y * pos.y - + pos.z * pos.z); - if(dist < falloffStart) { - const auto applyColor = [] (auto *color, unsigned char *out) { - unsigned int temp = (unsigned int)*out - + (unsigned int)(*color * 255.0f); - if(temp > 255) { - *out = 255; - } else { - *out = temp; - } - }; - if(mutex) { - std::lock_guard lock(*mutex); - applyColor(&color.x, &pixelOut.r); - applyColor(&color.y, &pixelOut.g); - applyColor(&color.z, &pixelOut.b); - } else { - applyColor(&color.x, &pixelOut.r); - applyColor(&color.y, &pixelOut.g); - applyColor(&color.z, &pixelOut.b); - } - } else if(dist >= falloffStart && dist <= falloffEnd) { - const auto applyFalloffColor = [] (auto *color, unsigned char *out, float f) { - unsigned int temp = (unsigned int)*out - + (unsigned int)(*color * 255.0f * f); - if(temp > 255) { - *out = 255; - } else { - *out = temp; - } - }; - float f = (1.0f - (dist - falloffStart) / (falloffEnd - falloffStart)); - if(mutex) { - std::lock_guard lock(*mutex); - applyFalloffColor(&color.x, &pixelOut.r, f); - applyFalloffColor(&color.y, &pixelOut.g, f); - applyFalloffColor(&color.z, &pixelOut.b, f); - } else { - applyFalloffColor(&color.x, &pixelOut.r, f); - applyFalloffColor(&color.y, &pixelOut.g, f); - applyFalloffColor(&color.z, &pixelOut.b, f); - } - } -} - -Ex02::RT::Internal::Sphere::Sphere() : - pos{0.0f, 0.0f, 0.0f}, - radius(2.5f) -{} - -std::optional Ex02::RT::Internal::Sphere::rayToSphere( - glm::vec3 rayPos, glm::vec3 rayDirUnit) const { - return Ex02::RT::Internal::rayToSphere(rayPos, rayDirUnit, pos, radius); -} - -Ex02::RT::Internal::RTSVisibleType Ex02::RT::Internal::Sphere::rayToSphereVisible( - glm::vec3 rayPos, glm::vec3 rayDirUnit, - const LightSource &light) const { - return Ex02::RT::Internal::rayToSphereVisible( - rayPos, rayDirUnit, pos, radius, light.pos); -} - -std::optional Ex02::RT::Internal::rayToSphere( - glm::vec3 rayPos, - glm::vec3 rayDirUnit, - glm::vec3 spherePos, - float sphereRadius) { - // check if there is collision - glm::vec3 tempVec = rayPos - spherePos; - float temp = - rayDirUnit.x * tempVec.x - + rayDirUnit.y * tempVec.y - + rayDirUnit.z * tempVec.z; - float delta = temp * temp; - temp = - tempVec.x * tempVec.x - + tempVec.y * tempVec.y - + tempVec.z * tempVec.z - - sphereRadius * sphereRadius; - delta -= temp; - - if(delta < 0.0f) { - return {}; +void Ex02::RT::Internal::LightSource::applyLight(glm::vec3 pos, Pixel &pixelOut, + std::mutex *mutex) const { + pos = this->pos - pos; + float dist = std::sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z); + if (dist < falloffStart) { + const auto applyColor = [](auto *color, unsigned char *out) { + unsigned int temp = (unsigned int)*out + (unsigned int)(*color * 255.0f); + if (temp > 255) { + *out = 255; + } else { + *out = temp; + } + }; + if (mutex) { + std::lock_guard lock(*mutex); + applyColor(&color.x, &pixelOut.r); + applyColor(&color.y, &pixelOut.g); + applyColor(&color.z, &pixelOut.b); } else { - temp = - rayDirUnit.x * tempVec.x - + rayDirUnit.y * tempVec.y - + rayDirUnit.z * tempVec.z; - float dist = -temp - std::sqrt(delta); - float dist2 = -temp + std::sqrt(delta); - float min = dist > dist2 ? dist2 : dist; - float max = dist > dist2 ? dist : dist2; - if(min < 0.0f) { - if(max < 0.0f) { - return {}; - } else { - return {rayPos + rayDirUnit * max}; - } - } else { - return {rayPos + rayDirUnit * min}; - } + applyColor(&color.x, &pixelOut.r); + applyColor(&color.y, &pixelOut.g); + applyColor(&color.z, &pixelOut.b); } + } else if (dist >= falloffStart && dist <= falloffEnd) { + const auto applyFalloffColor = [](auto *color, unsigned char *out, + float f) { + unsigned int temp = + (unsigned int)*out + (unsigned int)(*color * 255.0f * f); + if (temp > 255) { + *out = 255; + } else { + *out = temp; + } + }; + float f = (1.0f - (dist - falloffStart) / (falloffEnd - falloffStart)); + if (mutex) { + std::lock_guard lock(*mutex); + applyFalloffColor(&color.x, &pixelOut.r, f); + applyFalloffColor(&color.y, &pixelOut.g, f); + applyFalloffColor(&color.z, &pixelOut.b, f); + } else { + applyFalloffColor(&color.x, &pixelOut.r, f); + applyFalloffColor(&color.y, &pixelOut.g, f); + applyFalloffColor(&color.z, &pixelOut.b, f); + } + } +} + +Ex02::RT::Internal::Sphere::Sphere() : pos{0.0f, 0.0f, 0.0f}, radius(2.5f) {} + +std::optional +Ex02::RT::Internal::Sphere::rayToSphere(glm::vec3 rayPos, + glm::vec3 rayDirUnit) const { + return Ex02::RT::Internal::rayToSphere(rayPos, rayDirUnit, pos, radius); +} + +Ex02::RT::Internal::RTSVisibleType +Ex02::RT::Internal::Sphere::rayToSphereVisible(glm::vec3 rayPos, + glm::vec3 rayDirUnit, + const LightSource &light) const { + return Ex02::RT::Internal::rayToSphereVisible(rayPos, rayDirUnit, pos, radius, + light.pos); +} + +std::optional Ex02::RT::Internal::rayToSphere(glm::vec3 rayPos, + glm::vec3 rayDirUnit, + glm::vec3 spherePos, + float sphereRadius) { + // check if there is collision + glm::vec3 tempVec = rayPos - spherePos; + float temp = rayDirUnit.x * tempVec.x + rayDirUnit.y * tempVec.y + + rayDirUnit.z * tempVec.z; + float delta = temp * temp; + temp = tempVec.x * tempVec.x + tempVec.y * tempVec.y + tempVec.z * tempVec.z - + sphereRadius * sphereRadius; + delta -= temp; + + if (delta < 0.0f) { + return {}; + } else { + temp = rayDirUnit.x * tempVec.x + rayDirUnit.y * tempVec.y + + rayDirUnit.z * tempVec.z; + float dist = -temp - std::sqrt(delta); + float dist2 = -temp + std::sqrt(delta); + float min = dist > dist2 ? dist2 : dist; + float max = dist > dist2 ? dist : dist2; + if (min < 0.0f) { + if (max < 0.0f) { + return {}; + } else { + return {rayPos + rayDirUnit * max}; + } + } else { + return {rayPos + rayDirUnit * min}; + } + } } float Ex02::RT::Internal::angleBetweenRays(glm::vec3 a, glm::vec3 b) { - float dot = a.x * b.x + a.y * b.y + a.z * b.z; - float amag = std::sqrt(a.x * a.x + a.y * a.y + a.z * a.z); - float bmag = std::sqrt(b.x * b.x + b.y * b.y + b.z * b.z); + float dot = a.x * b.x + a.y * b.y + a.z * b.z; + float amag = std::sqrt(a.x * a.x + a.y * a.y + a.z * a.z); + float bmag = std::sqrt(b.x * b.x + b.y * b.y + b.z * b.z); - return std::acos(dot / amag / bmag); + return std::acos(dot / amag / bmag); } float Ex02::RT::Internal::distBetweenPositions(glm::vec3 a, glm::vec3 b) { - a = a - b; - return std::sqrt(a.x * a.x + a.y * a.y + a.z * a.z); + a = a - b; + return std::sqrt(a.x * a.x + a.y * a.y + a.z * a.z); } -Ex02::RT::Internal::RTSVisibleType Ex02::RT::Internal::rayToSphereVisible( - glm::vec3 rayPos, - glm::vec3 rayDirUnit, - glm::vec3 spherePos, - float sphereRadius, - glm::vec3 lightPos) { - auto collPos = rayToSphere(rayPos, rayDirUnit, spherePos, sphereRadius); - if(collPos) { - glm::vec3 toLight = lightPos - *collPos; - glm::vec3 toLightUnit = toLight / std::sqrt( - toLight.x * toLight.x - + toLight.y * toLight.y - + toLight.z * toLight.z); - glm::vec3 toLightPos = *collPos + toLight / 3.0f; - auto collResult = Internal::rayToSphere( - toLightPos, toLightUnit, spherePos, sphereRadius); - if(collResult) { - return {}; - } else { - return {{*collPos, toLight}}; - } +Ex02::RT::Internal::RTSVisibleType +Ex02::RT::Internal::rayToSphereVisible(glm::vec3 rayPos, glm::vec3 rayDirUnit, + glm::vec3 spherePos, float sphereRadius, + glm::vec3 lightPos) { + auto collPos = rayToSphere(rayPos, rayDirUnit, spherePos, sphereRadius); + if (collPos) { + glm::vec3 toLight = lightPos - *collPos; + glm::vec3 toLightUnit = + toLight / std::sqrt(toLight.x * toLight.x + toLight.y * toLight.y + + toLight.z * toLight.z); + glm::vec3 toLightPos = *collPos + toLight / 3.0f; + auto collResult = + Internal::rayToSphere(toLightPos, toLightUnit, spherePos, sphereRadius); + if (collResult) { + return {}; } else { - return {}; + return {{*collPos, toLight}}; } + } else { + return {}; + } } -Ex02::RT::Image Ex02::RT::renderGraySphere( - unsigned int outputWidth, - unsigned int outputHeight, - unsigned int threadCount) { - const glm::vec3 spherePos{0.0f, 0.0f, -2.5f}; - const glm::vec3 lightPos{4.0f, 4.0f, 0.0f}; - Image image(outputWidth, outputHeight); - const glm::vec3 rayPos{0.0f, 0.0f, 0.0f}; - const float lightFalloffStart = 4.5f; - const float lightFalloffEnd = 7.0f; -// if(threadCount <= 1) { - for(unsigned int j = 0; j < outputHeight; ++j) { - float offsetY = ((float)j + 0.5f - ((float)outputHeight / 2.0f)); - for(unsigned int i = 0; i < outputWidth; ++i) { - float offsetX = ((float)i + 0.5f - ((float)outputWidth / 2.0f)); - glm::vec3 rayDir{ - offsetX, - offsetY, - -(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO}; - glm::vec3 rayDirUnit = rayDir / std::sqrt( - rayDir.x * rayDir.x - + rayDir.y * rayDir.y - + rayDir.z * rayDir.z); - auto rayResult = Internal::rayToSphereVisible( - rayPos, rayDirUnit, - spherePos, EX02_RAY_TRACER_GRAY_SPHERE_RADIUS, - lightPos); - if(rayResult) { - glm::vec3 *toLight = &std::get<1>(rayResult.value()); - float dist = std::sqrt( - toLight->x * toLight->x - + toLight->y * toLight->y - + toLight->z * toLight->z); - if(dist < lightFalloffStart) { - image.getPixel(i, j).r = 255; - image.getPixel(i, j).g = 255; - image.getPixel(i, j).b = 255; - } else if(dist >= lightFalloffStart && dist <= lightFalloffEnd) { - image.getPixel(i, j).r = - (1.0f - (dist - lightFalloffStart) - / (lightFalloffEnd - lightFalloffStart)) - * 255.0f; - image.getPixel(i, j).g = image.getPixel(i, j).r; - image.getPixel(i, j).b = image.getPixel(i, j).r; - } - } - } - } -// } else { -// } - - return image; -} - -Ex02::RT::Image Ex02::RT::renderColorsWithSpheres( - unsigned int outputWidth, - unsigned int outputHeight, - unsigned int threadCount) { - Image image(outputWidth, outputHeight); - const glm::vec3 rayPos{0.0f, 0.0f, 0.0f}; - std::array spheres; - std::array lights; - - spheres[0].pos.x = 2.0f; - spheres[0].pos.y = -2.0f; - spheres[0].pos.z = -4.5f; - spheres[0].radius = 1.0f; - - spheres[1].pos.x = -2.0f; - spheres[1].pos.y = 2.0f; - spheres[1].pos.z = -4.5f; - spheres[1].radius = 1.0f; - - spheres[2].pos.x = 0.0f; - spheres[2].pos.y = 0.0f; - spheres[2].pos.z = -6.0f; - spheres[2].radius = 2.0f; - - spheres[3].pos.x = 2.0f; - spheres[3].pos.y = 2.0f; - spheres[3].pos.z = -2.5; - spheres[3].radius = 1.0f; - - spheres[4].pos.x = -2.0f; - spheres[4].pos.y = -2.0f; - spheres[4].pos.z = -2.5; - spheres[4].radius = 1.0f; - - spheres[5].pos.x = -0.7f; - spheres[5].pos.y = -0.7f; - spheres[5].pos.z = -4.0f; - spheres[5].radius = -0.7f; - - spheres[6].pos.x = 0.7f; - spheres[6].pos.y = 0.7f; - spheres[6].pos.z = -4.0f; - spheres[6].radius = -0.7f; - - lights[0].color.r = 1.0f; - lights[0].color.g = 0.0f; - lights[0].color.b = 0.0f; - lights[0].pos.x = 0.0f; - lights[0].pos.y = -1.0f; - lights[0].pos.z = 0.0f; - lights[0].falloffStart = 3.0f; - lights[0].falloffEnd = 7.0f; - - lights[1].color.r = 0.0f; - lights[1].color.g = 1.0f; - lights[1].color.b = 0.0f; - lights[1].pos.x = std::cos(PI / 3.0f); - lights[1].pos.y = std::sin(PI / 3.0f); - lights[1].pos.z = 0.0f; - lights[1].falloffStart = 3.0f; - lights[1].falloffEnd = 7.0f; - - lights[2].color.r = 0.0f; - lights[2].color.g = 0.0f; - lights[2].color.b = 1.0f; - lights[2].pos.x = std::cos(PI * 2.0 / 3.0f); - lights[2].pos.y = std::sin(PI * 2.0 / 3.0f); - lights[2].pos.z = 0.0f; - lights[2].falloffStart = 3.0f; - lights[2].falloffEnd = 7.0f; - - const auto yIteration = [&spheres, &lights, &image, outputWidth, outputHeight, rayPos] (unsigned int j, std::mutex *mutex) { - float offsetY = ((float)j + 0.5f - ((float)outputHeight / 2.0f)); - for(unsigned int i = 0; i < outputWidth; ++i) { - float offsetX = ((float)i + 0.5f - ((float)outputWidth / 2.0f)); - glm::vec3 rayDir{ - offsetX, - offsetY, - -(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO}; - glm::vec3 rayDirUnit = rayDir / std::sqrt( - rayDir.x * rayDir.x - + rayDir.y * rayDir.y - + rayDir.z * rayDir.z); - - // cast ray to all spheres, finding closest result - std::optional> closestResult; - for(unsigned int idx = 0; idx < spheres.size(); ++idx) { - auto result = spheres[idx].rayToSphere(rayPos, rayDirUnit); - if(result) { - float dist = Internal::distBetweenPositions( - rayPos, spheres[idx].pos); - if(closestResult) { - if(dist < std::get<1>(*closestResult)) { - closestResult = {{*result, dist, idx}}; - } - } else { - closestResult = {{*result, dist, idx}}; - } - } - } - - if(!closestResult) { - continue; - } - - // cast ray to each light checking if colliding with other - // spheres - for(const auto &light : lights) { - glm::vec3 toLight = light.pos - std::get<0>(*closestResult); - glm::vec3 toLightUnit = toLight / std::sqrt( - toLight.x * toLight.x - + toLight.y * toLight.y - + toLight.z * toLight.z); - bool isBlocked = false; - for(unsigned int idx = 0; idx < spheres.size(); ++idx) { - if(idx == std::get<2>(*closestResult)) { - continue; - } - auto result = spheres[idx].rayToSphere( - std::get<0>(*closestResult), - toLightUnit); - if(result) { - isBlocked = true; - break; - } - } - if(isBlocked) { - continue; - } - - // at this point, it is known that no spheres blocks ray - // to light - light.applyLight( - std::get<0>(*closestResult), - image.getPixel(i, j), - mutex); - } - } - }; - - if(threadCount <= 1) { - for(unsigned int j = 0; j < outputHeight; ++j) { - yIteration(j, nullptr); - } - } else { - std::vector threads; - std::mutex mutex; - unsigned int range = outputHeight / threadCount; - for(unsigned int threadIdx = 0; threadIdx < threadCount; ++threadIdx) { - unsigned int start = range * threadIdx; - unsigned int end = range * (threadIdx + 1); - if(threadIdx + 1 == threadCount) { - end = outputHeight; - } - threads.emplace_back(std::thread([&yIteration] (unsigned int start, unsigned int end, std::mutex *mutex) { - for(unsigned int y = start; y < end; ++y) { - yIteration(y, mutex); - } - }, - start, - end, - &mutex)); - } - for(std::thread &thread : threads) { - thread.join(); +Ex02::RT::Image Ex02::RT::renderGraySphere(unsigned int outputWidth, + unsigned int outputHeight, + unsigned int threadCount) { + const glm::vec3 spherePos{0.0f, 0.0f, -2.5f}; + const glm::vec3 lightPos{4.0f, 4.0f, 0.0f}; + Image image(outputWidth, outputHeight); + const glm::vec3 rayPos{0.0f, 0.0f, 0.0f}; + const float lightFalloffStart = 4.5f; + const float lightFalloffEnd = 7.0f; + // if(threadCount <= 1) { + for (unsigned int j = 0; j < outputHeight; ++j) { + float offsetY = ((float)j + 0.5f - ((float)outputHeight / 2.0f)); + for (unsigned int i = 0; i < outputWidth; ++i) { + float offsetX = ((float)i + 0.5f - ((float)outputWidth / 2.0f)); + glm::vec3 rayDir{offsetX, offsetY, + -(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO}; + glm::vec3 rayDirUnit = + rayDir / std::sqrt(rayDir.x * rayDir.x + rayDir.y * rayDir.y + + rayDir.z * rayDir.z); + auto rayResult = Internal::rayToSphereVisible( + rayPos, rayDirUnit, spherePos, EX02_RAY_TRACER_GRAY_SPHERE_RADIUS, + lightPos); + if (rayResult) { + glm::vec3 *toLight = &std::get<1>(rayResult.value()); + float dist = + std::sqrt(toLight->x * toLight->x + toLight->y * toLight->y + + toLight->z * toLight->z); + if (dist < lightFalloffStart) { + image.getPixel(i, j).r = 255; + image.getPixel(i, j).g = 255; + image.getPixel(i, j).b = 255; + } else if (dist >= lightFalloffStart && dist <= lightFalloffEnd) { + image.getPixel(i, j).r = + (1.0f - (dist - lightFalloffStart) / + (lightFalloffEnd - lightFalloffStart)) * + 255.0f; + image.getPixel(i, j).g = image.getPixel(i, j).r; + image.getPixel(i, j).b = image.getPixel(i, j).r; } + } } + } + // } else { + // } - return image; + return image; +} + +Ex02::RT::Image Ex02::RT::renderColorsWithSpheres(unsigned int outputWidth, + unsigned int outputHeight, + unsigned int threadCount) { + Image image(outputWidth, outputHeight); + const glm::vec3 rayPos{0.0f, 0.0f, 0.0f}; + std::array spheres; + std::array lights; + + spheres[0].pos.x = 2.0f; + spheres[0].pos.y = -2.0f; + spheres[0].pos.z = -4.5f; + spheres[0].radius = 1.0f; + + spheres[1].pos.x = -2.0f; + spheres[1].pos.y = 2.0f; + spheres[1].pos.z = -4.5f; + spheres[1].radius = 1.0f; + + spheres[2].pos.x = 0.0f; + spheres[2].pos.y = 0.0f; + spheres[2].pos.z = -6.0f; + spheres[2].radius = 2.0f; + + spheres[3].pos.x = 2.0f; + spheres[3].pos.y = 2.0f; + spheres[3].pos.z = -2.5; + spheres[3].radius = 1.0f; + + spheres[4].pos.x = -2.0f; + spheres[4].pos.y = -2.0f; + spheres[4].pos.z = -2.5; + spheres[4].radius = 1.0f; + + spheres[5].pos.x = -0.7f; + spheres[5].pos.y = -0.7f; + spheres[5].pos.z = -4.0f; + spheres[5].radius = -0.7f; + + spheres[6].pos.x = 0.7f; + spheres[6].pos.y = 0.7f; + spheres[6].pos.z = -4.0f; + spheres[6].radius = -0.7f; + + lights[0].color.r = 1.0f; + lights[0].color.g = 0.0f; + lights[0].color.b = 0.0f; + lights[0].pos.x = 0.0f; + lights[0].pos.y = -1.0f; + lights[0].pos.z = 0.0f; + lights[0].falloffStart = 3.0f; + lights[0].falloffEnd = 7.0f; + + lights[1].color.r = 0.0f; + lights[1].color.g = 1.0f; + lights[1].color.b = 0.0f; + lights[1].pos.x = std::cos(PI / 3.0f); + lights[1].pos.y = std::sin(PI / 3.0f); + lights[1].pos.z = 0.0f; + lights[1].falloffStart = 3.0f; + lights[1].falloffEnd = 7.0f; + + lights[2].color.r = 0.0f; + lights[2].color.g = 0.0f; + lights[2].color.b = 1.0f; + lights[2].pos.x = std::cos(PI * 2.0 / 3.0f); + lights[2].pos.y = std::sin(PI * 2.0 / 3.0f); + lights[2].pos.z = 0.0f; + lights[2].falloffStart = 3.0f; + lights[2].falloffEnd = 7.0f; + + const auto yIteration = [&spheres, &lights, &image, outputWidth, outputHeight, + rayPos](unsigned int j, std::mutex *mutex) { + float offsetY = ((float)j + 0.5f - ((float)outputHeight / 2.0f)); + for (unsigned int i = 0; i < outputWidth; ++i) { + float offsetX = ((float)i + 0.5f - ((float)outputWidth / 2.0f)); + glm::vec3 rayDir{offsetX, offsetY, + -(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO}; + glm::vec3 rayDirUnit = + rayDir / std::sqrt(rayDir.x * rayDir.x + rayDir.y * rayDir.y + + rayDir.z * rayDir.z); + + // cast ray to all spheres, finding closest result + std::optional> closestResult; + for (unsigned int idx = 0; idx < spheres.size(); ++idx) { + auto result = spheres[idx].rayToSphere(rayPos, rayDirUnit); + if (result) { + float dist = Internal::distBetweenPositions(rayPos, spheres[idx].pos); + if (closestResult) { + if (dist < std::get<1>(*closestResult)) { + closestResult = {{*result, dist, idx}}; + } + } else { + closestResult = {{*result, dist, idx}}; + } + } + } + + if (!closestResult) { + continue; + } + + // cast ray to each light checking if colliding with other + // spheres + for (const auto &light : lights) { + glm::vec3 toLight = light.pos - std::get<0>(*closestResult); + glm::vec3 toLightUnit = + toLight / std::sqrt(toLight.x * toLight.x + toLight.y * toLight.y + + toLight.z * toLight.z); + bool isBlocked = false; + for (unsigned int idx = 0; idx < spheres.size(); ++idx) { + if (idx == std::get<2>(*closestResult)) { + continue; + } + auto result = spheres[idx].rayToSphere(std::get<0>(*closestResult), + toLightUnit); + if (result) { + isBlocked = true; + break; + } + } + if (isBlocked) { + continue; + } + + // at this point, it is known that no spheres blocks ray + // to light + light.applyLight(std::get<0>(*closestResult), image.getPixel(i, j), + mutex); + } + } + }; + + if (threadCount <= 1) { + for (unsigned int j = 0; j < outputHeight; ++j) { + yIteration(j, nullptr); + } + } else { + std::vector threads; + std::mutex mutex; + unsigned int range = outputHeight / threadCount; + for (unsigned int threadIdx = 0; threadIdx < threadCount; ++threadIdx) { + unsigned int start = range * threadIdx; + unsigned int end = range * (threadIdx + 1); + if (threadIdx + 1 == threadCount) { + end = outputHeight; + } + threads.emplace_back(std::thread( + [&yIteration](unsigned int start, unsigned int end, + std::mutex *mutex) { + for (unsigned int y = start; y < end; ++y) { + yIteration(y, mutex); + } + }, + start, end, &mutex)); + } + for (std::thread &thread : threads) { + thread.join(); + } + } + + return image; } diff --git a/example02_threaded_raytracing/src/rayTracer.hpp b/example02_threaded_raytracing/src/rayTracer.hpp index 0102e9c..0f89c5e 100644 --- a/example02_threaded_raytracing/src/rayTracer.hpp +++ b/example02_threaded_raytracing/src/rayTracer.hpp @@ -7,103 +7,88 @@ #define EX02_RAY_TRACER_COLL_INCREMENT 2.0f #define EX02_RAY_TRACER_GRAY_SPHERE_RADIUS 1.5f -#include +#include #include #include #include -#include +#include -#include #include #include +#include namespace Ex02 { namespace RT { -struct Pixel { + struct Pixel { Pixel(); - unsigned char r,g,b; -}; + unsigned char r, g, b; + }; -class Image { -public: + class Image { + public: Image(unsigned int width, unsigned int height); - Pixel& getPixel(unsigned int x, unsigned int y); - const Pixel& getPixel(unsigned int x, unsigned int y) const; + Pixel &getPixel(unsigned int x, unsigned int y); + const Pixel &getPixel(unsigned int x, unsigned int y) const; void writeToFile(const std::string &filename) const; -private: + private: unsigned int width; std::vector data; -}; + }; -namespace Internal { + namespace Internal { typedef std::optional> RTSVisibleType; struct LightSource { - LightSource(); + LightSource(); - glm::vec3 pos; - float falloffStart; - float falloffEnd; - glm::vec3 color; + glm::vec3 pos; + float falloffStart; + float falloffEnd; + glm::vec3 color; - void applyLight(glm::vec3 pos, Pixel &pixelOut) const; - void applyLight(glm::vec3 pos, Pixel &pixelOut, std::mutex *mutex) const; + void applyLight(glm::vec3 pos, Pixel &pixelOut) const; + void applyLight(glm::vec3 pos, Pixel &pixelOut, std::mutex *mutex) const; }; struct Sphere { - Sphere(); + Sphere(); - glm::vec3 pos; - float radius; + glm::vec3 pos; + float radius; - std::optional rayToSphere( - glm::vec3 rayPos, glm::vec3 rayDirUnit) const; + std::optional rayToSphere(glm::vec3 rayPos, + glm::vec3 rayDirUnit) const; - RTSVisibleType rayToSphereVisible( - glm::vec3 rayPos, glm::vec3 rayDirUnit, - const LightSource &light) const; + RTSVisibleType rayToSphereVisible(glm::vec3 rayPos, glm::vec3 rayDirUnit, + const LightSource &light) const; }; // returns pos of collision - std::optional rayToSphere( - glm::vec3 rayPos, - glm::vec3 rayDirUnit, - glm::vec3 spherePos, - float sphereRadius); + std::optional rayToSphere(glm::vec3 rayPos, glm::vec3 rayDirUnit, + glm::vec3 spherePos, + float sphereRadius); - float angleBetweenRays( - glm::vec3 a, - glm::vec3 b); + float angleBetweenRays(glm::vec3 a, glm::vec3 b); - float distBetweenPositions( - glm::vec3 a, - glm::vec3 b); + float distBetweenPositions(glm::vec3 a, glm::vec3 b); // first vec3 is result from rayToSphere(), second is ray to light source - RTSVisibleType rayToSphereVisible( - glm::vec3 rayPos, - glm::vec3 rayDirUnit, - glm::vec3 spherePos, - float sphereRadius, - glm::vec3 lightPos); -} + RTSVisibleType rayToSphereVisible(glm::vec3 rayPos, glm::vec3 rayDirUnit, + glm::vec3 spherePos, float sphereRadius, + glm::vec3 lightPos); + } // namespace Internal -Image renderGraySphere( - unsigned int outputWidth, - unsigned int outputHeight, - unsigned int threadCount = 1 -); + Image renderGraySphere(unsigned int outputWidth, unsigned int outputHeight, + unsigned int threadCount = 1); -Image renderColorsWithSpheres( - unsigned int outputWidth, - unsigned int outputHeight, - unsigned int threadCount = 1 -); + Image renderColorsWithSpheres(unsigned int outputWidth, + unsigned int outputHeight, + unsigned int threadCount = 1); } // namespace RT } // namespace Ex02