Working thread impl
This commit is contained in:
parent
61e6cf17fd
commit
ade12df080
1 changed files with 88 additions and 53 deletions
|
@ -3,6 +3,8 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include <glm/matrix.hpp>
|
#include <glm/matrix.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
@ -316,74 +318,107 @@ Ex02::RT::Image Ex02::RT::renderColorsWithSpheres(
|
||||||
lights[2].falloffStart = 3.0f;
|
lights[2].falloffStart = 3.0f;
|
||||||
lights[2].falloffEnd = 7.0f;
|
lights[2].falloffEnd = 7.0f;
|
||||||
|
|
||||||
if(threadCount <= 1) {
|
const auto yIteration = [&spheres, &lights, &image, outputWidth, outputHeight, rayPos] (unsigned int j, std::mutex *mutex) {
|
||||||
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{
|
||||||
glm::vec3 rayDir{
|
offsetX,
|
||||||
offsetX,
|
offsetY,
|
||||||
offsetY,
|
-(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO};
|
||||||
-(float)outputHeight * EX02_RAY_TRACER_VIEW_RATIO};
|
glm::vec3 rayDirUnit = rayDir / std::sqrt(
|
||||||
glm::vec3 rayDirUnit = rayDir / std::sqrt(
|
rayDir.x * rayDir.x
|
||||||
rayDir.x * rayDir.x
|
+ rayDir.y * rayDir.y
|
||||||
+ rayDir.y * rayDir.y
|
+ rayDir.z * rayDir.z);
|
||||||
+ rayDir.z * rayDir.z);
|
|
||||||
|
|
||||||
// cast ray to all spheres, finding closest result
|
// cast ray to all spheres, finding closest result
|
||||||
std::optional<std::tuple<glm::vec3, float, unsigned int>> closestResult;
|
std::optional<std::tuple<glm::vec3, float, unsigned int>> closestResult;
|
||||||
for(unsigned int idx = 0; idx < spheres.size(); ++idx) {
|
for(unsigned int idx = 0; idx < spheres.size(); ++idx) {
|
||||||
auto result = spheres[idx].rayToSphere(rayPos, rayDirUnit);
|
auto result = spheres[idx].rayToSphere(rayPos, rayDirUnit);
|
||||||
if(result) {
|
if(result) {
|
||||||
float dist = Internal::distBetweenPositions(
|
float dist = Internal::distBetweenPositions(
|
||||||
rayPos, spheres[idx].pos);
|
rayPos, spheres[idx].pos);
|
||||||
if(closestResult) {
|
if(closestResult) {
|
||||||
if(dist < std::get<1>(*closestResult)) {
|
if(dist < std::get<1>(*closestResult)) {
|
||||||
closestResult = {{*result, dist, idx}};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
closestResult = {{*result, dist, idx}};
|
closestResult = {{*result, dist, idx}};
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
closestResult = {{*result, dist, idx}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!closestResult) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cast ray to each light checking if colliding with other
|
// at this point, it is known that no spheres blocks ray
|
||||||
// spheres
|
// to light
|
||||||
for(const auto &light : lights) {
|
if(mutex) {
|
||||||
glm::vec3 toLight = light.pos - std::get<0>(*closestResult);
|
std::lock_guard<std::mutex> lock(*mutex);
|
||||||
glm::vec3 toLightUnit = toLight / std::sqrt(
|
light.applyLight(
|
||||||
toLight.x * toLight.x
|
std::get<0>(*closestResult),
|
||||||
+ toLight.y * toLight.y
|
image.getPixel(i, j));
|
||||||
+ toLight.z * toLight.z);
|
} else {
|
||||||
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(
|
light.applyLight(
|
||||||
std::get<0>(*closestResult),
|
std::get<0>(*closestResult),
|
||||||
image.getPixel(i, j));
|
image.getPixel(i, j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
return image;
|
||||||
|
|
Loading…
Reference in a new issue