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>
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;
}

View file

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

View file

@ -5,129 +5,126 @@
#include "rayTracer.hpp"
void printHelp() {
std::cout << "Usage:\n"
"-h | --help Display this help message\n"
"-t <integer>\n"
" | --threads <integer> Set the number of threads to use (default 1)\n"
"--width <integer> Set the width of the output image\n"
"--height <integer> Set the height of the output image\n"
"-o <filename>\n"
" | --output <filename> Set the output filename for the image"
<< std::endl;
std::cout
<< "Usage:\n"
"-h | --help Display this help message\n"
"-t <integer>\n"
" | --threads <integer> Set the number of threads to use "
"(default 1)\n"
"--width <integer> Set the width of the output image\n"
"--height <integer> Set the height of the output image\n"
"-o <filename>\n"
" | --output <filename> 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;
}

View file

@ -1,51 +1,43 @@
#include "rayTracer.hpp"
#include <array>
#include <cmath>
#include <fstream>
#include <array>
#include <thread>
#include <glm/matrix.hpp>
#include <glm/gtc/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);
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';
}
}
/*
@ -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<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 {};
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<std::mutex> 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<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 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<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();
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<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_GRAY_SPHERE_RADIUS 1.5f
#include <vector>
#include <mutex>
#include <optional>
#include <string>
#include <tuple>
#include <mutex>
#include <vector>
#include <glm/vec3.hpp>
#include <glm/mat4x4.hpp>
#include <glm/matrix.hpp>
#include <glm/vec3.hpp>
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<Pixel> data;
};
};
namespace Internal {
namespace Internal {
typedef std::optional<std::tuple<glm::vec3, glm::vec3>> 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<glm::vec3> rayToSphere(
glm::vec3 rayPos, glm::vec3 rayDirUnit) const;
std::optional<glm::vec3> 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<glm::vec3> rayToSphere(
glm::vec3 rayPos,
glm::vec3 rayDirUnit,
glm::vec3 spherePos,
float sphereRadius);
std::optional<glm::vec3> 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