Added multithreading and Scene Toggling
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@
|
||||
//Project includes
|
||||
#include "Renderer.h"
|
||||
|
||||
#include <execution>
|
||||
#include <iostream>
|
||||
|
||||
#include "Maths.h"
|
||||
@@ -24,7 +25,11 @@ Renderer::Renderer(SDL_Window * pWindow) :
|
||||
m_AspectRatio = (m_Width / float(m_Height)) ;
|
||||
m_pBufferPixels = static_cast<uint32_t*>(m_pBuffer->pixels);
|
||||
|
||||
m_HorizontalIterator.resize(m_Width);
|
||||
m_VerticalIterator.resize(m_Height);
|
||||
|
||||
for (uint32_t i = 0; i < m_Width; i++) m_HorizontalIterator[i] = i;
|
||||
for (uint32_t i = 0; i < m_Height; i++) m_VerticalIterator[i] = i;
|
||||
}
|
||||
|
||||
void Renderer::Render(Scene* pScene) const
|
||||
@@ -35,16 +40,18 @@ void Renderer::Render(Scene* pScene) const
|
||||
|
||||
const Matrix cameraToWorld = camera.CalculateCameraToWorld();
|
||||
|
||||
for (int px{}; px < m_Width; ++px)
|
||||
{
|
||||
for (int py{}; py < m_Height; ++py)
|
||||
{
|
||||
|
||||
if (m_IsMultiThreadingEnabled)
|
||||
{
|
||||
std::for_each(std::execution::par ,m_HorizontalIterator.begin(), m_HorizontalIterator.end(), [this, camera, cameraToWorld, materials, lights, pScene](uint32_t px)
|
||||
{
|
||||
std::for_each(std::execution::par,m_VerticalIterator.begin(), m_VerticalIterator.end(), [this, px, camera, cameraToWorld, materials, lights, pScene](uint32_t py)
|
||||
{
|
||||
//Sets screen to black
|
||||
ColorRGB finalColor{ };
|
||||
|
||||
//creates a vector that holds a coordinate in 3D space dependent on which pixel the loop is on
|
||||
Vector3 rayDirection{ float((2 * ((px + 0.5) / m_Width) - 1) * m_AspectRatio * camera.FOV),float((1 - 2 * ((py + 0.5) / m_Height)) * camera.FOV),1};
|
||||
Vector3 rayDirection{ float((2 * ((px + 0.5) / m_Width) - 1) * m_AspectRatio * camera.FOV),float((1 - 2 * ((py + 0.5) / m_Height)) * camera.FOV),1 };
|
||||
rayDirection.Normalize();
|
||||
rayDirection = cameraToWorld.TransformVector(rayDirection);
|
||||
|
||||
@@ -87,7 +94,7 @@ void Renderer::Render(Scene* pScene) const
|
||||
|
||||
if (m_CurrentLightingMode == LightingMode::Combined)
|
||||
{
|
||||
ColorRGB ObservedArea = ColorRGB{ observedArea, observedArea,observedArea};
|
||||
ColorRGB ObservedArea = ColorRGB{ observedArea, observedArea,observedArea };
|
||||
|
||||
ColorRGB Radiance = LightUtils::GetRadiance(lights[idx], closestHit.origin);
|
||||
|
||||
@@ -115,6 +122,90 @@ void Renderer::Render(Scene* pScene) const
|
||||
static_cast<uint8_t>(finalColor.r * 255),
|
||||
static_cast<uint8_t>(finalColor.g * 255),
|
||||
static_cast<uint8_t>(finalColor.b * 255));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
for (int px{}; px < m_Width; ++px)
|
||||
{
|
||||
for (int py{}; py < m_Height; ++py)
|
||||
{
|
||||
//Sets screen to black
|
||||
ColorRGB finalColor{ };
|
||||
|
||||
//creates a vector that holds a coordinate in 3D space dependent on which pixel the loop is on
|
||||
Vector3 rayDirection{ float((2 * ((px + 0.5) / m_Width) - 1) * m_AspectRatio * camera.FOV),float((1 - 2 * ((py + 0.5) / m_Height)) * camera.FOV),1 };
|
||||
rayDirection.Normalize();
|
||||
rayDirection = cameraToWorld.TransformVector(rayDirection);
|
||||
|
||||
//Creates a Ray from origin to the point where the current pixel in loop is
|
||||
Ray viewRay{ camera.origin,rayDirection };
|
||||
|
||||
HitRecord closestHit{};
|
||||
pScene->GetClosestHit(viewRay, closestHit);
|
||||
|
||||
if (closestHit.didHit)
|
||||
{
|
||||
|
||||
for (int idx{ 0 }; idx < lights.size(); idx++)
|
||||
{
|
||||
Vector3 lightVec = LightUtils::GetDirectionToLight(lights[idx], closestHit.origin);
|
||||
float maxRayLenght = lightVec.Normalize();
|
||||
Ray shadowRay(closestHit.origin + closestHit.normal * 0.0001f, lightVec, 0.0001f, maxRayLenght);
|
||||
bool shadowDoesHit = pScene->DoesHit(shadowRay);
|
||||
float observedArea = Vector3::Dot(closestHit.normal, lightVec);
|
||||
|
||||
if (observedArea > 0.f)
|
||||
{
|
||||
|
||||
if (!m_ShadowsEnabled or (m_ShadowsEnabled && !shadowDoesHit))
|
||||
{
|
||||
if (m_CurrentLightingMode == LightingMode::ObservedArea)
|
||||
{
|
||||
finalColor += ColorRGB{ observedArea,observedArea,observedArea };
|
||||
}
|
||||
|
||||
if (m_CurrentLightingMode == LightingMode::Radiance)
|
||||
{
|
||||
finalColor += LightUtils::GetRadiance(lights[idx], closestHit.origin);
|
||||
}
|
||||
|
||||
if (m_CurrentLightingMode == LightingMode::BRDF)
|
||||
{
|
||||
finalColor += materials[closestHit.materialIndex]->Shade(closestHit, lightVec, viewRay.direction);
|
||||
}
|
||||
|
||||
if (m_CurrentLightingMode == LightingMode::Combined)
|
||||
{
|
||||
ColorRGB ObservedArea = ColorRGB{ observedArea, observedArea,observedArea };
|
||||
|
||||
ColorRGB Radiance = LightUtils::GetRadiance(lights[idx], closestHit.origin);
|
||||
|
||||
ColorRGB BRDF = materials[closestHit.materialIndex]->Shade(closestHit, lightVec, viewRay.direction);
|
||||
|
||||
finalColor += Radiance * BRDF * ObservedArea;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//const float scaled_t = (closestHit.t - 50.f) / 40.f; //shades spheres based on proximity
|
||||
//finalColor = { scaled_t,scaled_t,scaled_t };
|
||||
|
||||
//const float scaled_t = (closestHit.t) / 500.f; //shades planes based on proximity
|
||||
//finalColor = { scaled_t,scaled_t,scaled_t };
|
||||
}
|
||||
//Update Color in Buffer
|
||||
finalColor.MaxToOne();
|
||||
|
||||
m_pBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBuffer->format,
|
||||
static_cast<uint8_t>(finalColor.r * 255),
|
||||
static_cast<uint8_t>(finalColor.g * 255),
|
||||
static_cast<uint8_t>(finalColor.b * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
struct SDL_Window;
|
||||
struct SDL_Surface;
|
||||
@@ -39,6 +40,8 @@ namespace dae
|
||||
|
||||
};
|
||||
void ToggleShadows() { m_ShadowsEnabled = !m_ShadowsEnabled; }
|
||||
void ToggleMultiThreading() { m_IsMultiThreadingEnabled = !m_IsMultiThreadingEnabled; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -52,6 +55,7 @@ namespace dae
|
||||
|
||||
LightingMode m_CurrentLightingMode{LightingMode::Combined};
|
||||
bool m_ShadowsEnabled{true};
|
||||
bool m_IsMultiThreadingEnabled{ true };
|
||||
SDL_Window* m_pWindow{};
|
||||
|
||||
SDL_Surface* m_pBuffer{};
|
||||
@@ -60,5 +64,7 @@ namespace dae
|
||||
int m_Width{};
|
||||
int m_Height{};
|
||||
float m_AspectRatio{};
|
||||
|
||||
std::vector<uint32_t> m_HorizontalIterator, m_VerticalIterator;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ namespace dae {
|
||||
}
|
||||
|
||||
|
||||
void Scene_W4::Initialize()
|
||||
void Scene_W4_Bunny::Initialize()
|
||||
{
|
||||
m_Camera.origin = { 0.f, 1.f, -5.f };
|
||||
m_Camera.fovAngle = 45.f;
|
||||
@@ -366,7 +366,7 @@ namespace dae {
|
||||
|
||||
|
||||
pMesh = AddTriangleMesh(TriangleCullMode::BackFaceCulling, matLambert_White);
|
||||
Utils::ParseOBJ("Resources/Warlock.obj",
|
||||
Utils::ParseOBJ("Resources/lowpoly_bunny.obj",
|
||||
pMesh->positions,
|
||||
pMesh->normals,
|
||||
pMesh->indices);
|
||||
@@ -382,18 +382,18 @@ namespace dae {
|
||||
|
||||
//pMesh->CalculateNormals();
|
||||
//pMesh->Translate({ 0.f,1.5f,0.f });
|
||||
pMesh->RotateY(90);
|
||||
pMesh->RotateY(60);
|
||||
pMesh->UpdateTransforms();
|
||||
|
||||
|
||||
|
||||
// Light
|
||||
AddPointLight({ 0.f, 5.f, 5.f }, 50.f, ColorRGB{ 1.f, .61f, .45f }); // Backlight
|
||||
//AddPointLight({ -2.5f, 5.f, -5.f }, 70.f, ColorRGB{ 1.f, .8f, .45f }); // Front Light Left
|
||||
//AddPointLight({ 2.5f, 5.f, -5.f }, 50.f, ColorRGB{ .34f, .47f, .68f }); // Front Light Right
|
||||
AddPointLight({ -2.5f, 5.f, -5.f }, 70.f, ColorRGB{ 1.f, .8f, .45f }); // Front Light Left
|
||||
AddPointLight({ 2.5f, 5.f, -5.f }, 50.f, ColorRGB{ .34f, .47f, .68f }); // Front Light Right
|
||||
}
|
||||
|
||||
void Scene_W4::Update(dae::Timer* pTimer)
|
||||
void Scene_W4_Bunny::Update(dae::Timer* pTimer)
|
||||
{
|
||||
Scene::Update(pTimer);
|
||||
}
|
||||
|
||||
@@ -112,17 +112,17 @@ namespace dae
|
||||
void Initialize() override;
|
||||
};
|
||||
|
||||
//WEEK 4 Test Scene
|
||||
class Scene_W4 final : public Scene
|
||||
//WEEK 4 Bunny Scene
|
||||
class Scene_W4_Bunny final : public Scene
|
||||
{
|
||||
public:
|
||||
Scene_W4() = default;
|
||||
~Scene_W4() override = default;
|
||||
Scene_W4_Bunny() = default;
|
||||
~Scene_W4_Bunny() override = default;
|
||||
|
||||
Scene_W4(const Scene_W4&) = delete;
|
||||
Scene_W4(Scene_W4&&) noexcept = delete;
|
||||
Scene_W4& operator=(const Scene_W4&) = delete;
|
||||
Scene_W4& operator=(Scene_W4&&) noexcept = delete;
|
||||
Scene_W4_Bunny(const Scene_W4_Bunny&) = delete;
|
||||
Scene_W4_Bunny(Scene_W4_Bunny&&) noexcept = delete;
|
||||
Scene_W4_Bunny& operator=(const Scene_W4_Bunny&) = delete;
|
||||
Scene_W4_Bunny& operator=(Scene_W4_Bunny&&) noexcept = delete;
|
||||
|
||||
void Initialize() override;
|
||||
void Update(dae::Timer* pTimer) override;
|
||||
@@ -132,7 +132,7 @@ namespace dae
|
||||
};
|
||||
|
||||
|
||||
//WEEK 4 Test Scene
|
||||
//WEEK 4 Reference Scene
|
||||
class Scene_W4_ReferenceScene final : public Scene
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -48,7 +48,9 @@ int main(int argc, char* args[])
|
||||
const auto pRenderer = new Renderer(pWindow);
|
||||
|
||||
const auto pScene = new Scene_W4_ReferenceScene();
|
||||
const auto pScene2 = new Scene_W4_Bunny();
|
||||
pScene->Initialize();
|
||||
pScene2->Initialize();
|
||||
|
||||
|
||||
//Start loop
|
||||
@@ -60,6 +62,7 @@ int main(int argc, char* args[])
|
||||
float printTimer = 0.f;
|
||||
bool isLooping = true;
|
||||
bool takeScreenshot = false;
|
||||
bool isBunnyScene = false;
|
||||
while (isLooping)
|
||||
{
|
||||
//--------- Get input events ---------
|
||||
@@ -82,6 +85,14 @@ int main(int argc, char* args[])
|
||||
{
|
||||
pRenderer->CycleLightingMode();
|
||||
}
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_F4)
|
||||
{
|
||||
pRenderer->ToggleMultiThreading();
|
||||
}
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_F5)
|
||||
{
|
||||
isBunnyScene = !isBunnyScene;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -91,10 +102,26 @@ int main(int argc, char* args[])
|
||||
|
||||
|
||||
//--------- Update ---------
|
||||
if (isBunnyScene)
|
||||
{
|
||||
pScene2->Update(pTimer);
|
||||
}
|
||||
else
|
||||
{
|
||||
pScene->Update(pTimer);
|
||||
}
|
||||
|
||||
|
||||
//--------- Render ---------
|
||||
if (isBunnyScene)
|
||||
{
|
||||
pRenderer->Render(pScene2);
|
||||
}
|
||||
else
|
||||
{
|
||||
pRenderer->Render(pScene);
|
||||
}
|
||||
|
||||
|
||||
//--------- Timer ---------
|
||||
pTimer->Update();
|
||||
@@ -119,6 +146,7 @@ int main(int argc, char* args[])
|
||||
|
||||
//Shutdown "framework"
|
||||
delete pScene;
|
||||
delete pScene2;
|
||||
delete pRenderer;
|
||||
delete pTimer;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user