Use clang-format to reformat sources

This commit is contained in:
Stephen Seo 2021-08-24 12:42:18 +09:00
parent 2d439c3232
commit eec1c251a3
6 changed files with 736 additions and 628 deletions

View file

@ -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
...

View file

@ -2,34 +2,36 @@
#include <cstring> #include <cstring>
Ex02::ArgParse::ParseResult Ex02::ArgParse::parseArgs( Ex02::ArgParse::ParseResult
int argc, Ex02::ArgParse::parseArgs(int argc, char **argv,
char **argv, const Ex02::ArgParse::ArgsType &singleArgs,
const Ex02::ArgParse::ArgsType &singleArgs, const Ex02::ArgParse::ArgsType &doubleArgs) {
const Ex02::ArgParse::ArgsType &doubleArgs) { ParseResult result;
ParseResult result; bool found;
bool found; --argc;
--argc; ++argv; ++argv;
while(argc > 0) { while (argc > 0) {
found = false; found = false;
for(const std::string &singleArg : singleArgs) { for (const std::string &singleArg : singleArgs) {
if(std::strcmp(argv[0], singleArg.c_str()) == 0) { if (std::strcmp(argv[0], singleArg.c_str()) == 0) {
result.insert({singleArg, EX02_ARG_PARSE_SINGLE_ARG_PLACEHOLDER}); result.insert({singleArg, EX02_ARG_PARSE_SINGLE_ARG_PLACEHOLDER});
found = true; found = true;
break; 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;
} }
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;
} }

View file

@ -4,16 +4,17 @@
#define EX02_ARG_PARSE_SINGLE_ARG_PLACEHOLDER "SINGLE_ARG_PLACEHOLDER" #define EX02_ARG_PARSE_SINGLE_ARG_PLACEHOLDER "SINGLE_ARG_PLACEHOLDER"
#include <string> #include <string>
#include <unordered_set>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
namespace Ex02 { namespace Ex02 {
namespace ArgParse { namespace ArgParse {
typedef std::unordered_set<std::string> ArgsType; typedef std::unordered_set<std::string> ArgsType;
typedef std::unordered_map<std::string, std::string> ParseResult; typedef std::unordered_map<std::string, std::string> 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 ArgParse
} // namespace Ex02 } // namespace Ex02

View file

@ -5,129 +5,126 @@
#include "rayTracer.hpp" #include "rayTracer.hpp"
void printHelp() { void printHelp() {
std::cout << "Usage:\n" std::cout
"-h | --help Display this help message\n" << "Usage:\n"
"-t <integer>\n" "-h | --help Display this help message\n"
" | --threads <integer> Set the number of threads to use (default 1)\n" "-t <integer>\n"
"--width <integer> Set the width of the output image\n" " | --threads <integer> Set the number of threads to use "
"--height <integer> Set the height of the output image\n" "(default 1)\n"
"-o <filename>\n" "--width <integer> Set the width of the output image\n"
" | --output <filename> Set the output filename for the image" "--height <integer> Set the height of the output image\n"
<< std::endl; "-o <filename>\n"
" | --output <filename> Set the output filename for the image"
<< std::endl;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int threadCount = 1; int threadCount = 1;
unsigned int outputWidth = 1600; unsigned int outputWidth = 1600;
unsigned int outputHeight = 1600; unsigned int outputHeight = 1600;
std::string outputFile = "raytrace_out"; std::string outputFile = "raytrace_out";
{ {
auto results = Ex02::ArgParse::parseArgs( auto results = Ex02::ArgParse::parseArgs(argc, argv,
argc, {
argv, // single args
{ // single args "-h",
"-h", "--help",
"--help", },
}, {
{ // double args // double args
"-t", "-t",
"--threads", "--threads",
"--width", "--width",
"--height", "--height",
"-o", "-o",
"--output", "--output",
}); });
if(auto iter = results.find("-h"); iter != results.end()) { if (auto iter = results.find("-h"); iter != results.end()) {
printHelp(); printHelp();
return 0; return 0;
} else if(auto iter = results.find("--help"); iter != results.end()) { } else if (auto iter = results.find("--help"); iter != results.end()) {
printHelp(); printHelp();
return 0; 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;
}
} }
// auto pixels = Ex02::RT::renderGraySphere( const auto setThreadCount = [&threadCount](auto iter) {
// outputWidth, outputHeight, threadCount); try {
auto pixels = Ex02::RT::renderColorsWithSpheres( threadCount = std::stoi(iter->second);
outputWidth, outputHeight, threadCount); } 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;
} }

View file

@ -1,51 +1,43 @@
#include "rayTracer.hpp" #include "rayTracer.hpp"
#include <array>
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#include <array>
#include <thread> #include <thread>
#include <glm/matrix.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/matrix.hpp>
const float PI = std::acos(-1.0f); const float PI = std::acos(-1.0f);
Ex02::RT::Pixel::Pixel() : Ex02::RT::Pixel::Pixel() : r(0), g(0), b(0) {}
r(0),
g(0),
b(0)
{}
Ex02::RT::Image::Image(unsigned int width, unsigned int height) : Ex02::RT::Image::Image(unsigned int width, unsigned int height) : width(width) {
width(width) data.resize(width * height);
{
data.resize(width * height);
} }
Ex02::RT::Pixel& Ex02::RT::Image::getPixel( Ex02::RT::Pixel &Ex02::RT::Image::getPixel(unsigned int x, unsigned int y) {
unsigned int x, unsigned int y) { return data.at(x + y * width);
return data.at(x + y * width);
} }
const Ex02::RT::Pixel& Ex02::RT::Image::getPixel( const Ex02::RT::Pixel &Ex02::RT::Image::getPixel(unsigned int x,
unsigned int x, unsigned int y) const { unsigned int y) const {
return data.at(x + y * width); return data.at(x + y * width);
} }
void Ex02::RT::Image::writeToFile(const std::string &filename) const { void Ex02::RT::Image::writeToFile(const std::string &filename) const {
std::ofstream out(filename + ".ppm"); std::ofstream out(filename + ".ppm");
out << "P3\n" << width << ' ' << data.size() / width << " 255" out << "P3\n" << width << ' ' << data.size() / width << " 255" << '\n';
<< '\n';
for(unsigned int j = 0; j < data.size() / width; ++j) { for (unsigned int j = 0; j < data.size() / width; ++j) {
for(unsigned int i = 0; i < width; ++i) { for (unsigned int i = 0; i < width; ++i) {
out << (int)data.at(i + j * width).r << ' ' out << (int)data.at(i + j * width).r << ' '
<< (int)data.at(i + j * width).g << ' ' << (int)data.at(i + j * width).g << ' '
<< (int)data.at(i + j * width).b << ' '; << (int)data.at(i + j * width).b << ' ';
}
out << '\n';
} }
out << '\n';
}
} }
/* /*
@ -57,7 +49,7 @@ glm::mat4x4 Ex02::RT::Internal::defaultMVP() {
EX02_RAY_TRACER_DEFAULT_FAR_PLANE); EX02_RAY_TRACER_DEFAULT_FAR_PLANE);
mvp *= glm::lookAt( 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, 0.0f, -1.0f},
glm::vec3{0.0f, 1.0f, 0.0f}); glm::vec3{0.0f, 1.0f, 0.0f});
@ -70,420 +62,385 @@ glm::mat4x4 Ex02::RT::Internal::defaultMVP() {
} }
*/ */
Ex02::RT::Internal::LightSource::LightSource() : Ex02::RT::Internal::LightSource::LightSource()
pos{0.0f, 0.0f, 0.0f}, : pos{0.0f, 0.0f, 0.0f}, falloffStart(2.0f),
falloffStart(2.0f), falloffEnd(7.0f), color{1.0f, 1.0f, 1.0f} {}
falloffEnd(7.0f),
color{1.0f, 1.0f, 1.0f}
{}
void Ex02::RT::Internal::LightSource::applyLight( void Ex02::RT::Internal::LightSource::applyLight(glm::vec3 pos,
glm::vec3 pos, Pixel &pixelOut) const { Pixel &pixelOut) const {
pos = this->pos - pos; pos = this->pos - pos;
float dist = std::sqrt( float dist = std::sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z);
pos.x * pos.x if (dist < falloffStart) {
+ pos.y * pos.y const auto applyColor = [](auto *color, unsigned char *out) {
+ pos.z * pos.z); unsigned int temp = (unsigned int)*out + (unsigned int)(*color * 255.0f);
if(dist < falloffStart) { if (temp > 255) {
const auto applyColor = [] (auto *color, unsigned char *out) { *out = 255;
unsigned int temp = (unsigned int)*out } else {
+ (unsigned int)(*color * 255.0f); *out = temp;
if(temp > 255) { }
*out = 255; };
} else { applyColor(&color.x, &pixelOut.r);
*out = temp; applyColor(&color.y, &pixelOut.g);
} applyColor(&color.z, &pixelOut.b);
}; } else if (dist >= falloffStart && dist <= falloffEnd) {
applyColor(&color.x, &pixelOut.r); const auto applyFalloffColor = [](auto *color, unsigned char *out,
applyColor(&color.y, &pixelOut.g); float f) {
applyColor(&color.z, &pixelOut.b); unsigned int temp =
} else if(dist >= falloffStart && dist <= falloffEnd) { (unsigned int)*out + (unsigned int)(*color * 255.0f * f);
const auto applyFalloffColor = [] (auto *color, unsigned char *out, float f) { if (temp > 255) {
unsigned int temp = (unsigned int)*out *out = 255;
+ (unsigned int)(*color * 255.0f * f); } else {
if(temp > 255) { *out = temp;
*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);
float f = (1.0f - (dist - falloffStart) / (falloffEnd - falloffStart)); applyFalloffColor(&color.z, &pixelOut.b, f);
applyFalloffColor(&color.x, &pixelOut.r, f); }
applyFalloffColor(&color.y, &pixelOut.g, f);
applyFalloffColor(&color.z, &pixelOut.b, f);
}
} }
void Ex02::RT::Internal::LightSource::applyLight( void Ex02::RT::Internal::LightSource::applyLight(glm::vec3 pos, Pixel &pixelOut,
glm::vec3 pos, Pixel &pixelOut, std::mutex* mutex) const { std::mutex *mutex) const {
pos = this->pos - pos; pos = this->pos - pos;
float dist = std::sqrt( float dist = std::sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z);
pos.x * pos.x if (dist < falloffStart) {
+ pos.y * pos.y const auto applyColor = [](auto *color, unsigned char *out) {
+ pos.z * pos.z); unsigned int temp = (unsigned int)*out + (unsigned int)(*color * 255.0f);
if(dist < falloffStart) { if (temp > 255) {
const auto applyColor = [] (auto *color, unsigned char *out) { *out = 255;
unsigned int temp = (unsigned int)*out } else {
+ (unsigned int)(*color * 255.0f); *out = temp;
if(temp > 255) { }
*out = 255; };
} else { if (mutex) {
*out = temp; std::lock_guard<std::mutex> lock(*mutex);
} applyColor(&color.x, &pixelOut.r);
}; applyColor(&color.y, &pixelOut.g);
if(mutex) { applyColor(&color.z, &pixelOut.b);
std::lock_guard<std::mutex> 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<std::mutex> 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<glm::vec3> 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<glm::vec3> 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 { } else {
temp = applyColor(&color.x, &pixelOut.r);
rayDirUnit.x * tempVec.x applyColor(&color.y, &pixelOut.g);
+ rayDirUnit.y * tempVec.y applyColor(&color.z, &pixelOut.b);
+ 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};
}
} }
} 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<std::mutex> 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<glm::vec3>
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<glm::vec3> 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 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 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 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 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) { float Ex02::RT::Internal::distBetweenPositions(glm::vec3 a, glm::vec3 b) {
a = a - b; a = a - b;
return std::sqrt(a.x * a.x + a.y * a.y + a.z * a.z); return std::sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
} }
Ex02::RT::Internal::RTSVisibleType Ex02::RT::Internal::rayToSphereVisible( Ex02::RT::Internal::RTSVisibleType
glm::vec3 rayPos, Ex02::RT::Internal::rayToSphereVisible(glm::vec3 rayPos, glm::vec3 rayDirUnit,
glm::vec3 rayDirUnit, glm::vec3 spherePos, float sphereRadius,
glm::vec3 spherePos, glm::vec3 lightPos) {
float sphereRadius, auto collPos = rayToSphere(rayPos, rayDirUnit, spherePos, sphereRadius);
glm::vec3 lightPos) { if (collPos) {
auto collPos = rayToSphere(rayPos, rayDirUnit, spherePos, sphereRadius); glm::vec3 toLight = lightPos - *collPos;
if(collPos) { glm::vec3 toLightUnit =
glm::vec3 toLight = lightPos - *collPos; toLight / std::sqrt(toLight.x * toLight.x + toLight.y * toLight.y +
glm::vec3 toLightUnit = toLight / std::sqrt( toLight.z * toLight.z);
toLight.x * toLight.x glm::vec3 toLightPos = *collPos + toLight / 3.0f;
+ toLight.y * toLight.y auto collResult =
+ toLight.z * toLight.z); Internal::rayToSphere(toLightPos, toLightUnit, spherePos, sphereRadius);
glm::vec3 toLightPos = *collPos + toLight / 3.0f; if (collResult) {
auto collResult = Internal::rayToSphere( return {};
toLightPos, toLightUnit, spherePos, sphereRadius);
if(collResult) {
return {};
} else {
return {{*collPos, toLight}};
}
} else { } else {
return {}; return {{*collPos, toLight}};
} }
} else {
return {};
}
} }
Ex02::RT::Image Ex02::RT::renderGraySphere( Ex02::RT::Image Ex02::RT::renderGraySphere(unsigned int outputWidth,
unsigned int outputWidth, unsigned int outputHeight,
unsigned int outputHeight, unsigned int threadCount) {
unsigned int threadCount) { const glm::vec3 spherePos{0.0f, 0.0f, -2.5f};
const glm::vec3 spherePos{0.0f, 0.0f, -2.5f}; const glm::vec3 lightPos{4.0f, 4.0f, 0.0f};
const glm::vec3 lightPos{4.0f, 4.0f, 0.0f}; Image image(outputWidth, outputHeight);
Image image(outputWidth, outputHeight); const glm::vec3 rayPos{0.0f, 0.0f, 0.0f};
const glm::vec3 rayPos{0.0f, 0.0f, 0.0f}; const float lightFalloffStart = 4.5f;
const float lightFalloffStart = 4.5f; const float lightFalloffEnd = 7.0f;
const float lightFalloffEnd = 7.0f; // if(threadCount <= 1) {
// if(threadCount <= 1) { for (unsigned int j = 0; j < outputHeight; ++j) {
for(unsigned int j = 0; j < outputHeight; ++j) { float offsetY = ((float)j + 0.5f - ((float)outputHeight / 2.0f));
float offsetY = ((float)j + 0.5f - ((float)outputHeight / 2.0f)); for (unsigned int i = 0; i < outputWidth; ++i) {
for(unsigned int i = 0; i < outputWidth; ++i) { float offsetX = ((float)i + 0.5f - ((float)outputWidth / 2.0f));
float offsetX = ((float)i + 0.5f - ((float)outputWidth / 2.0f)); glm::vec3 rayDir{offsetX, offsetY,
glm::vec3 rayDir{ -(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO};
offsetX, glm::vec3 rayDirUnit =
offsetY, rayDir / std::sqrt(rayDir.x * rayDir.x + rayDir.y * rayDir.y +
-(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO}; rayDir.z * rayDir.z);
glm::vec3 rayDirUnit = rayDir / std::sqrt( auto rayResult = Internal::rayToSphereVisible(
rayDir.x * rayDir.x rayPos, rayDirUnit, spherePos, EX02_RAY_TRACER_GRAY_SPHERE_RADIUS,
+ rayDir.y * rayDir.y lightPos);
+ rayDir.z * rayDir.z); if (rayResult) {
auto rayResult = Internal::rayToSphereVisible( glm::vec3 *toLight = &std::get<1>(rayResult.value());
rayPos, rayDirUnit, float dist =
spherePos, EX02_RAY_TRACER_GRAY_SPHERE_RADIUS, std::sqrt(toLight->x * toLight->x + toLight->y * toLight->y +
lightPos); toLight->z * toLight->z);
if(rayResult) { if (dist < lightFalloffStart) {
glm::vec3 *toLight = &std::get<1>(rayResult.value()); image.getPixel(i, j).r = 255;
float dist = std::sqrt( image.getPixel(i, j).g = 255;
toLight->x * toLight->x image.getPixel(i, j).b = 255;
+ toLight->y * toLight->y } else if (dist >= lightFalloffStart && dist <= lightFalloffEnd) {
+ toLight->z * toLight->z); image.getPixel(i, j).r =
if(dist < lightFalloffStart) { (1.0f - (dist - lightFalloffStart) /
image.getPixel(i, j).r = 255; (lightFalloffEnd - lightFalloffStart)) *
image.getPixel(i, j).g = 255; 255.0f;
image.getPixel(i, j).b = 255; image.getPixel(i, j).g = image.getPixel(i, j).r;
} else if(dist >= lightFalloffStart && dist <= lightFalloffEnd) { image.getPixel(i, j).b = image.getPixel(i, j).r;
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<Internal::Sphere, 7> spheres;
std::array<Internal::LightSource, 3> 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<std::tuple<glm::vec3, float, unsigned int>> 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<std::thread> 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();
} }
}
} }
}
// } 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<Internal::Sphere, 7> spheres;
std::array<Internal::LightSource, 3> 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<std::tuple<glm::vec3, float, unsigned int>> 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<std::thread> 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;
} }

View file

@ -7,103 +7,88 @@
#define EX02_RAY_TRACER_COLL_INCREMENT 2.0f #define EX02_RAY_TRACER_COLL_INCREMENT 2.0f
#define EX02_RAY_TRACER_GRAY_SPHERE_RADIUS 1.5f #define EX02_RAY_TRACER_GRAY_SPHERE_RADIUS 1.5f
#include <vector> #include <mutex>
#include <optional> #include <optional>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <mutex> #include <vector>
#include <glm/vec3.hpp>
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
#include <glm/matrix.hpp> #include <glm/matrix.hpp>
#include <glm/vec3.hpp>
namespace Ex02 { namespace Ex02 {
namespace RT { namespace RT {
struct Pixel { struct Pixel {
Pixel(); Pixel();
unsigned char r,g,b; unsigned char r, g, b;
}; };
class Image { class Image {
public: public:
Image(unsigned int width, unsigned int height); Image(unsigned int width, unsigned int height);
Pixel& getPixel(unsigned int x, unsigned int y); Pixel &getPixel(unsigned int x, unsigned int y);
const Pixel& getPixel(unsigned int x, unsigned int y) const; const Pixel &getPixel(unsigned int x, unsigned int y) const;
void writeToFile(const std::string &filename) const; void writeToFile(const std::string &filename) const;
private: private:
unsigned int width; unsigned int width;
std::vector<Pixel> data; std::vector<Pixel> data;
}; };
namespace Internal { namespace Internal {
typedef std::optional<std::tuple<glm::vec3, glm::vec3>> RTSVisibleType; typedef std::optional<std::tuple<glm::vec3, glm::vec3>> RTSVisibleType;
struct LightSource { struct LightSource {
LightSource(); LightSource();
glm::vec3 pos; glm::vec3 pos;
float falloffStart; float falloffStart;
float falloffEnd; float falloffEnd;
glm::vec3 color; glm::vec3 color;
void applyLight(glm::vec3 pos, Pixel &pixelOut) const; 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, std::mutex *mutex) const;
}; };
struct Sphere { struct Sphere {
Sphere(); Sphere();
glm::vec3 pos; glm::vec3 pos;
float radius; float radius;
std::optional<glm::vec3> rayToSphere( std::optional<glm::vec3> rayToSphere(glm::vec3 rayPos,
glm::vec3 rayPos, glm::vec3 rayDirUnit) const; glm::vec3 rayDirUnit) const;
RTSVisibleType rayToSphereVisible( RTSVisibleType rayToSphereVisible(glm::vec3 rayPos, glm::vec3 rayDirUnit,
glm::vec3 rayPos, glm::vec3 rayDirUnit, const LightSource &light) const;
const LightSource &light) const;
}; };
// returns pos of collision // returns pos of collision
std::optional<glm::vec3> rayToSphere( std::optional<glm::vec3> rayToSphere(glm::vec3 rayPos, glm::vec3 rayDirUnit,
glm::vec3 rayPos, glm::vec3 spherePos,
glm::vec3 rayDirUnit, float sphereRadius);
glm::vec3 spherePos,
float sphereRadius);
float angleBetweenRays( float angleBetweenRays(glm::vec3 a, glm::vec3 b);
glm::vec3 a,
glm::vec3 b);
float distBetweenPositions( float distBetweenPositions(glm::vec3 a, glm::vec3 b);
glm::vec3 a,
glm::vec3 b);
// first vec3 is result from rayToSphere(), second is ray to light source // first vec3 is result from rayToSphere(), second is ray to light source
RTSVisibleType rayToSphereVisible( RTSVisibleType rayToSphereVisible(glm::vec3 rayPos, glm::vec3 rayDirUnit,
glm::vec3 rayPos, glm::vec3 spherePos, float sphereRadius,
glm::vec3 rayDirUnit, glm::vec3 lightPos);
glm::vec3 spherePos, } // namespace Internal
float sphereRadius,
glm::vec3 lightPos);
}
Image renderGraySphere( Image renderGraySphere(unsigned int outputWidth, unsigned int outputHeight,
unsigned int outputWidth, unsigned int threadCount = 1);
unsigned int outputHeight,
unsigned int threadCount = 1
);
Image renderColorsWithSpheres( Image renderColorsWithSpheres(unsigned int outputWidth,
unsigned int outputWidth, unsigned int outputHeight,
unsigned int outputHeight, unsigned int threadCount = 1);
unsigned int threadCount = 1
);
} // namespace RT } // namespace RT
} // namespace Ex02 } // namespace Ex02