Compare commits

..

4 Commits

11 changed files with 1048 additions and 141 deletions

View File

@@ -12,16 +12,12 @@ namespace dae
*/ */
static ColorRGB Lambert(float kd, const ColorRGB& cd) static ColorRGB Lambert(float kd, const ColorRGB& cd)
{ {
//todo: W3 return (kd * cd) / PI;
throw std::runtime_error("Not Implemented Yet");
return {};
} }
static ColorRGB Lambert(const ColorRGB& kd, const ColorRGB& cd) static ColorRGB Lambert(const ColorRGB& kd, const ColorRGB& cd)
{ {
//todo: W3 return (kd * cd) / PI;
throw std::runtime_error("Not Implemented Yet");
return {};
} }
/** /**
@@ -35,9 +31,13 @@ namespace dae
*/ */
static ColorRGB Phong(float ks, float exp, const Vector3& l, const Vector3& v, const Vector3& n) static ColorRGB Phong(float ks, float exp, const Vector3& l, const Vector3& v, const Vector3& n)
{ {
//todo: W3 Vector3 reflect = l - 2 * n * Vector3::Dot(n, l);
throw std::runtime_error("Not Implemented Yet");
return {}; float cosa{ std::max(Vector3::Dot(reflect, v), 0.f) };
float PhongSpecReflec = ks * (std::pow(cosa, exp));
return ColorRGB(PhongSpecReflec, PhongSpecReflec, PhongSpecReflec);
} }
/** /**
@@ -49,9 +49,7 @@ namespace dae
*/ */
static ColorRGB FresnelFunction_Schlick(const Vector3& h, const Vector3& v, const ColorRGB& f0) static ColorRGB FresnelFunction_Schlick(const Vector3& h, const Vector3& v, const ColorRGB& f0)
{ {
//todo: W3 return ColorRGB{ f0 + (ColorRGB{1,1,1} - f0) * std::pow((1 - (Vector3::Dot(h, v))) , 5) };
throw std::runtime_error("Not Implemented Yet");
return {};
} }
/** /**
@@ -63,9 +61,10 @@ namespace dae
*/ */
static float NormalDistribution_GGX(const Vector3& n, const Vector3& h, float roughness) static float NormalDistribution_GGX(const Vector3& n, const Vector3& h, float roughness)
{ {
//todo: W3 float nhdot = Vector3::Dot(n, h);
throw std::runtime_error("Not Implemented Yet"); float roughnessQuartic = std::pow(roughness,4);
return {}; float denominator = (nhdot * nhdot) * (roughnessQuartic - 1) + 1;
return ((roughnessQuartic)/ (PI * (denominator * denominator)));
} }
@@ -78,9 +77,10 @@ namespace dae
*/ */
static float GeometryFunction_SchlickGGX(const Vector3& n, const Vector3& v, float roughness) static float GeometryFunction_SchlickGGX(const Vector3& n, const Vector3& v, float roughness)
{ {
//todo: W3 float roughnessSqr = roughness * roughness;
throw std::runtime_error("Not Implemented Yet"); float nvdot = Vector3::Dot(n, v);
return {}; float kdirect = ((roughnessSqr + 1) * (roughnessSqr + 1)) / 8;
return (nvdot / ((nvdot) * (1 - kdirect) + kdirect));
} }
/** /**
@@ -93,9 +93,7 @@ namespace dae
*/ */
static float GeometryFunction_Smith(const Vector3& n, const Vector3& v, const Vector3& l, float roughness) static float GeometryFunction_Smith(const Vector3& n, const Vector3& v, const Vector3& l, float roughness)
{ {
//todo: W3 return GeometryFunction_SchlickGGX(n, v, roughness) * GeometryFunction_SchlickGGX(n, l, roughness);
throw std::runtime_error("Not Implemented Yet");
return {};
} }
} }

View File

@@ -1,8 +1,10 @@
#pragma once #pragma once
#include <iostream>
#include <SDL_keyboard.h> #include <SDL_keyboard.h>
#include <SDL_mouse.h> #include <SDL_mouse.h>
#include "Maths.h" #include "Maths.h"
#include "SDL_events.h"
#include "Timer.h" #include "Timer.h"
namespace dae namespace dae
@@ -19,7 +21,11 @@ namespace dae
Vector3 origin{}; Vector3 origin{};
float fovAngle{ 90.f }; float fovAngle{ 45.f };
float previousfovAngle{ fovAngle };
float FOV{ tan((fovAngle * (PI / 180)) / 2) };
float rotSpeed{10};
float movSpeed{ 11 };
Vector3 forward{ Vector3::UnitZ }; Vector3 forward{ Vector3::UnitZ };
Vector3 up{ Vector3::UnitY }; Vector3 up{ Vector3::UnitY };
@@ -33,25 +39,111 @@ namespace dae
Matrix CalculateCameraToWorld() Matrix CalculateCameraToWorld()
{ {
//todo: W2 right = Vector3::Cross(Vector3::UnitY,forward).Normalized();
throw std::runtime_error("Not Implemented Yet"); up = Vector3::Cross(forward, right).Normalized();
return {};
return Matrix(right, up, forward, origin);
} }
void Update(Timer* pTimer) void Update(Timer* pTimer)
{ {
SDL_SetRelativeMouseMode(SDL_TRUE);
if (fovAngle != previousfovAngle)
{
FOV = tan ((fovAngle * (PI / 180)) / 2);
previousfovAngle = fovAngle;
}
SDL_Event event;
const float deltaTime = pTimer->GetElapsed(); const float deltaTime = pTimer->GetElapsed();
//Keyboard Input //Keyboard Input
const uint8_t* pKeyboardState = SDL_GetKeyboardState(nullptr); const uint8_t* pKeyboardState = SDL_GetKeyboardState(nullptr);
//Mouse Input //Mouse Input
int mouseX{}, mouseY{}; int mouseX{}, mouseY{};
const uint32_t mouseState = SDL_GetRelativeMouseState(&mouseX, &mouseY); const uint32_t mouseState = SDL_GetRelativeMouseState(&mouseX, &mouseY);
//todo: W2 // Process mouse movements (relative to the last frame)
//throw std::runtime_error("Not Implemented Yet"); if (mouseState & SDL_BUTTON(SDL_BUTTON_RIGHT))
{
if (mouseX != 0 || mouseY != 0)
{
totalPitch = mouseY / rotSpeed * deltaTime;
totalYaw = mouseX / rotSpeed * deltaTime;
if (forward.z < 0)
{
forward = Matrix::CreateRotation(-totalPitch, totalYaw, 0).TransformVector(forward).Normalized();
}
else
{
forward = Matrix::CreateRotation(totalPitch, totalYaw, 0).TransformVector(forward).Normalized();
}
}
}
Vector3 forwardVec = forward.Normalized() * movSpeed * deltaTime;
Vector3 rightVector = Vector3{}.Cross(up , forward).Normalized() * movSpeed * deltaTime;
Vector3 upVector = Vector3{}.Cross(forward,right).Normalized() * movSpeed * deltaTime;
if (pKeyboardState[SDL_SCANCODE_W])
{
origin += forwardVec;
}
if (pKeyboardState[SDL_SCANCODE_S])
{
origin -= forwardVec;
}
if (pKeyboardState[SDL_SCANCODE_D])
{
origin += rightVector;
}
if (pKeyboardState[SDL_SCANCODE_A])
{
origin -= rightVector;
}
if (pKeyboardState[SDL_SCANCODE_SPACE])
{
if (forward.z < 0)
{
origin -= upVector;
}
else
{
origin += upVector;
}
}
if (pKeyboardState[SDL_SCANCODE_LSHIFT])
{
if (forward.z < 0)
{
origin += upVector;
}
else
{
origin -= upVector;
}
}
} }
}; };
} }

View File

@@ -124,20 +124,46 @@ namespace dae
void CalculateNormals() void CalculateNormals()
{ {
throw std::runtime_error("Not Implemented Yet"); normals.clear();
normals.reserve(indices.size() / 3);
for (int idx{0};idx < indices.size();idx += 3)
{
int i0 = indices[idx];
int i1 = indices[idx+1];
int i2 = indices[idx+2];
Vector3 a {positions[i0],positions[i1]};
Vector3 b {positions[i0],positions[i2]};
normals.push_back(Vector3::Cross(a, b).Normalized());
}
} }
void UpdateTransforms() void UpdateTransforms()
{ {
throw std::runtime_error("Not Implemented Yet"); transformedPositions.clear();
//Calculate Final Transform transformedNormals.clear();
//const auto finalTransform = ...
transformedPositions.reserve(positions.size());
transformedNormals.reserve(normals.size());
Matrix FullTransformMatrix = scaleTransform * rotationTransform * translationTransform ;
for (int idx{0};idx < positions.size();++idx)
{
transformedPositions.push_back(FullTransformMatrix.TransformPoint(positions[idx]));
}
for (int idx{ 0 }; idx < normals.size(); ++idx)
{
transformedNormals.push_back(FullTransformMatrix.TransformVector(normals[idx]));
}
//Transform Positions (positions > transformedPositions)
//...
//Transform Normals (normals > transformedNormals)
//...
} }
}; };
#pragma endregion #pragma endregion

View File

@@ -59,9 +59,7 @@ namespace dae
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
{ {
//todo: W3 return BRDF::Lambert(m_DiffuseReflectance, m_DiffuseColor);
throw std::runtime_error("Not Implemented Yet");
return {};
} }
private: private:
@@ -84,9 +82,8 @@ namespace dae
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
{ {
//todo: W3 return BRDF::Lambert(m_DiffuseReflectance,m_DiffuseColor) +
throw std::runtime_error("Not Implemented Yet"); BRDF::Phong(m_SpecularReflectance, m_PhongExponent, l, v, hitRecord.normal);
return {};
} }
private: private:
@@ -109,9 +106,48 @@ namespace dae
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
{ {
//todo: W3 Vector3 h = (-v+l).Normalized();
throw std::runtime_error("Not Implemented Yet"); ColorRGB f0{};
return {}; ColorRGB kd{};
if (m_Metalness == 0)
{
f0 = ColorRGB( 0.04f,0.04f, 0.04f );
kd = ColorRGB(1,1,1) - BRDF::FresnelFunction_Schlick(h, -v,f0);
}
else
{
f0 = m_Albedo;
kd = ColorRGB(0,0,0);
}
//NORMAL DISTRIBUTION
//float normaldistribution = BRDF::NormalDistribution_GGX(hitRecord.normal, h, m_Roughness);
//return ColorRGB(normaldistribution, normaldistribution, normaldistribution);
//GEOMETRIC FUNCTION SMITH
//float geoFuncSmith = BRDF::GeometryFunction_Smith(hitRecord.normal, -v, l, m_Roughness);
//return ColorRGB(geoFuncSmith, geoFuncSmith, geoFuncSmith);
//FRESNEL FUNCTION SCHLICK
//return BRDF::FresnelFunction_Schlick(h, -v, f0);
//COOK TORRANCE SPECULAR
ColorRGB fcolor (BRDF::NormalDistribution_GGX(hitRecord.normal,h,m_Roughness) * BRDF::FresnelFunction_Schlick(h, -v, f0) * BRDF::GeometryFunction_Smith(hitRecord.normal, -v, l, m_Roughness));
fcolor = fcolor / (4 * Vector3::Dot(-v, hitRecord.normal) * Vector3::Dot(l, hitRecord.normal));
//return fcolor;
//COOK TORRANCE DIFFUSE
//return BRDF::Lambert(kd, m_Albedo);
//FINAL COOK
return BRDF::Lambert(kd, m_Albedo) + fcolor;
} }
private: private:

View File

@@ -103,9 +103,14 @@ namespace dae {
Matrix Matrix::CreateTranslation(float x, float y, float z) Matrix Matrix::CreateTranslation(float x, float y, float z)
{ {
//todo W2
throw std::runtime_error("Not Implemented Yet"); Matrix tMatrix{ Vector4{1,0,0,0},
return {}; Vector4{0,1,0,0},
Vector4{0,0,1,0},
Vector4{x,y,z,1} };
return tMatrix;
} }
Matrix Matrix::CreateTranslation(const Vector3& t) Matrix Matrix::CreateTranslation(const Vector3& t)
@@ -115,30 +120,47 @@ namespace dae {
Matrix Matrix::CreateRotationX(float pitch) Matrix Matrix::CreateRotationX(float pitch)
{ {
//todo W2
throw std::runtime_error("Not Implemented Yet"); Matrix rMatrix{ Vector4{1,0,0,0},
return {}; Vector4{0,cos(pitch),sin(pitch),0},
Vector4{0,-sin(pitch),cos(pitch),0},
Vector4{0,0,0,1}};
return rMatrix;
} }
Matrix Matrix::CreateRotationY(float yaw) Matrix Matrix::CreateRotationY(float yaw)
{ {
//todo W2
throw std::runtime_error("Not Implemented Yet"); Matrix rMatrix{ Vector4{cos(yaw),0,-sin(yaw),0},
return {}; Vector4{0,1,0,0},
Vector4{sin(yaw),0,cos(yaw),0},
Vector4{0,0,0,1} };
return rMatrix;
} }
Matrix Matrix::CreateRotationZ(float roll) Matrix Matrix::CreateRotationZ(float roll)
{ {
//todo W2
throw std::runtime_error("Not Implemented Yet"); Matrix rMatrix{ Vector4{cos(roll),sin(roll),0,0},
return {}; Vector4{-sin(roll),cos(roll),0,0},
Vector4{0,0,1,0},
Vector4{0,0,0,1} };
return rMatrix;
} }
Matrix Matrix::CreateRotation(const Vector3& r) Matrix Matrix::CreateRotation(const Vector3& r)
{ {
//todo W2
throw std::runtime_error("Not Implemented Yet"); Matrix rMatrix{ CreateRotationX(r.x) * CreateRotationY(r.y) * CreateRotationZ(r.z)};
return {};
return rMatrix;
} }
Matrix Matrix::CreateRotation(float pitch, float yaw, float roll) Matrix Matrix::CreateRotation(float pitch, float yaw, float roll)
@@ -148,9 +170,14 @@ namespace dae {
Matrix Matrix::CreateScale(float sx, float sy, float sz) Matrix Matrix::CreateScale(float sx, float sy, float sz)
{ {
//todo W2
throw std::runtime_error("Not Implemented Yet"); Matrix sMatrix{ Vector4{sx,0,0,0},
return {}; Vector4{0,sy,0,0},
Vector4{0,0,sz,0},
Vector4{0,0,0,1} };
return sMatrix;
} }
Matrix Matrix::CreateScale(const Vector3& s) Matrix Matrix::CreateScale(const Vector3& s)

View File

@@ -5,6 +5,7 @@
//Project includes //Project includes
#include "Renderer.h" #include "Renderer.h"
#include <execution>
#include <iostream> #include <iostream>
#include "Maths.h" #include "Maths.h"
@@ -23,6 +24,12 @@ Renderer::Renderer(SDL_Window * pWindow) :
SDL_GetWindowSize(pWindow, &m_Width, &m_Height); SDL_GetWindowSize(pWindow, &m_Width, &m_Height);
m_AspectRatio = (m_Width / float(m_Height)) ; m_AspectRatio = (m_Width / float(m_Height)) ;
m_pBufferPixels = static_cast<uint32_t*>(m_pBuffer->pixels); 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 void Renderer::Render(Scene* pScene) const
@@ -31,38 +38,160 @@ void Renderer::Render(Scene* pScene) const
auto& materials = pScene->GetMaterials(); auto& materials = pScene->GetMaterials();
auto& lights = pScene->GetLights(); auto& lights = pScene->GetLights();
for (int px{}; px < m_Width; ++px) const Matrix cameraToWorld = camera.CalculateCameraToWorld();
if (m_IsMultiThreadingEnabled)
{ {
for (int py{}; py < m_Height; ++py) 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)
{ {
//float gradient = px / static_cast<float>(m_Width);
//gradient += py / static_cast<float>(m_Width);
//gradient /= 2.0f;
//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),float(1 - 2 * ((py + 0.5) / m_Height)),1};
rayDirection.Normalize();
//Creates a Ray from origin to the point where the current pixel in loop is
Ray viewRay{ {0,0,0},rayDirection};
//Sets screen to black //Sets screen to black
ColorRGB finalColor{ }; 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{}; HitRecord closestHit{};
pScene->GetClosestHit(viewRay, closestHit); pScene->GetClosestHit(viewRay, closestHit);
////Makes a tempSphere if (closestHit.didHit)
//Sphere testSphere{ {0.f,0.f,100.f},50.f,0 }; {
////Perform Sphere HitTest for (int idx{ 0 }; idx < lights.size(); idx++)
//GeometryUtils::HitTest_Sphere(testSphere, viewRay, closestHit); {
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));
});
});
}
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) if (closestHit.didHit)
{ {
finalColor = materials[closestHit.materialIndex]->Shade();
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 //const float scaled_t = (closestHit.t - 50.f) / 40.f; //shades spheres based on proximity
//finalColor = { scaled_t,scaled_t,scaled_t }; //finalColor = { scaled_t,scaled_t,scaled_t };
@@ -78,6 +207,7 @@ void Renderer::Render(Scene* pScene) const
static_cast<uint8_t>(finalColor.b * 255)); static_cast<uint8_t>(finalColor.b * 255));
} }
} }
}
//@END //@END
//Update SDL Surface //Update SDL Surface

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <vector>
struct SDL_Window; struct SDL_Window;
struct SDL_Surface; struct SDL_Surface;
@@ -22,8 +23,39 @@ namespace dae
void Render(Scene* pScene) const; void Render(Scene* pScene) const;
bool SaveBufferToImage() const; bool SaveBufferToImage() const;
void CycleLightingMode()
{
// Cast the current mode to int to check if it's the last mode
if (static_cast<int>(m_CurrentLightingMode) == 3)
{
// Set the mode back to the first one
m_CurrentLightingMode = LightingMode::ObservedArea;
}
else
{
// Move to the next mode by incrementing the current one
m_CurrentLightingMode = static_cast<LightingMode>(static_cast<int>(m_CurrentLightingMode) + 1);
}
};
void ToggleShadows() { m_ShadowsEnabled = !m_ShadowsEnabled; }
void ToggleMultiThreading() { m_IsMultiThreadingEnabled = !m_IsMultiThreadingEnabled; }
private: private:
enum class LightingMode
{
ObservedArea,
Radiance,
BRDF,
Combined //ObservedArea * Radiance * BRDF
};
LightingMode m_CurrentLightingMode{LightingMode::Combined};
bool m_ShadowsEnabled{true};
bool m_IsMultiThreadingEnabled{ true };
SDL_Window* m_pWindow{}; SDL_Window* m_pWindow{};
SDL_Surface* m_pBuffer{}; SDL_Surface* m_pBuffer{};
@@ -32,5 +64,7 @@ namespace dae
int m_Width{}; int m_Width{};
int m_Height{}; int m_Height{};
float m_AspectRatio{}; float m_AspectRatio{};
std::vector<uint32_t> m_HorizontalIterator, m_VerticalIterator;
}; };
} }

View File

@@ -28,16 +28,18 @@ namespace dae {
void dae::Scene::GetClosestHit(const Ray& ray, HitRecord& closestHit) const void dae::Scene::GetClosestHit(const Ray& ray, HitRecord& closestHit) const
{ {
HitRecord tempHit {};
//Checks through all the sphere //Checks through all the sphere
for (int idx{0};m_SphereGeometries.size() > idx;idx++) for (int idx{0};m_SphereGeometries.size() > idx;idx++)
{ {
HitRecord tempHit;
if (GeometryUtils::HitTest_Sphere(m_SphereGeometries[idx], ray, tempHit)) // Check if there's a hit from spheres if (GeometryUtils::HitTest_Sphere(m_SphereGeometries[idx], ray, tempHit)) // Check if there's a hit from spheres
{ {
if (tempHit.t < closestHit.t) if (tempHit.t < closestHit.t)
{ {
closestHit = tempHit; closestHit = tempHit;
} }
} }
@@ -46,8 +48,6 @@ namespace dae {
//Checks through all the planes //Checks through all the planes
for (int idx{ 0 }; m_PlaneGeometries.size() > idx; idx++) for (int idx{ 0 }; m_PlaneGeometries.size() > idx; idx++)
{ {
HitRecord tempHit;
if (GeometryUtils::HitTest_Plane(m_PlaneGeometries[idx],ray,tempHit)) // Check if there's a hit from planes if (GeometryUtils::HitTest_Plane(m_PlaneGeometries[idx],ray,tempHit)) // Check if there's a hit from planes
{ {
if (tempHit.t < closestHit.t) if (tempHit.t < closestHit.t)
@@ -56,12 +56,74 @@ namespace dae {
} }
} }
} }
//Checks through all the Triangles
for (int idx{ 0 }; m_Triangles.size() > idx; idx++)
{
if (GeometryUtils::HitTest_Triangle(m_Triangles[idx], ray, tempHit)) // Check if there's a hit from planes
{
if (tempHit.t < closestHit.t)
{
closestHit = tempHit;
}
}
}
//Checks through all the Triangles Meshes
for (int idx{ 0 }; m_TriangleMeshGeometries.size() > idx; idx++)
{
if (GeometryUtils::HitTest_TriangleMesh(m_TriangleMeshGeometries[idx], ray, tempHit)) // Check if there's a hit from planes
{
if (tempHit.t < closestHit.t)
{
closestHit = tempHit;
}
}
}
tempHit = closestHit;
} }
bool Scene::DoesHit(const Ray& ray) const bool Scene::DoesHit(const Ray& ray) const
{ {
//todo W2 //Checks through all the sphere
throw std::runtime_error("Not Implemented Yet"); for (int idx{ 0 }; idx < m_SphereGeometries.size() ; ++idx)
{
if (GeometryUtils::HitTest_Sphere(m_SphereGeometries[idx], ray)) // Check if there's a hit from spheres
{
return true;
}
}
for (int idx{ 0 }; idx < m_PlaneGeometries.size(); ++idx)
{
if (GeometryUtils::HitTest_Plane(m_PlaneGeometries[idx], ray)) // Check if there's a hit from planes
{
return true;
}
}
//Checks through all the Triangles
for (int idx{ 0 }; idx < m_Triangles.size(); ++idx)
{
if (GeometryUtils::HitTest_Triangle(m_Triangles[idx], ray))
{
return true;
}
}
//Checks through all the Triangles Meshes
for (int idx{ 0 };idx < m_TriangleMeshGeometries.size(); idx++)
{
if (GeometryUtils::HitTest_TriangleMesh(m_TriangleMeshGeometries[idx], ray)) // Check if there's a hit from planes
{
return true;
}
}
return false; return false;
} }
@@ -153,4 +215,258 @@ namespace dae {
AddPlane({ 0.f, 0.f, 125.f }, { 0.f, 0.f,-1.f }, matId_Solid_Magenta); AddPlane({ 0.f, 0.f, 125.f }, { 0.f, 0.f,-1.f }, matId_Solid_Magenta);
} }
#pragma endregion #pragma endregion
void Scene_W2::Initialize()
{
m_Camera.origin = { 0.f,3.f,-9.f };
m_Camera.fovAngle = 45.f;
//default: Material id0 >> SolidColorMaterial (RED)
constexpr unsigned char matId_Solid_Red = 0;
const unsigned char matId_Solid_Blue = AddMaterial(new Material_SolidColor{ colors::Blue });
const unsigned char matId_Solid_Yellow = AddMaterial(new Material_SolidColor{ colors::Yellow });
const unsigned char matId_Solid_Green = AddMaterial(new Material_SolidColor{ colors::Green });
const unsigned char matId_Solid_Magenta = AddMaterial(new Material_SolidColor{ colors::Magenta });
const unsigned char matId_Solid_Porple = AddMaterial(new Material_SolidColor{ ColorRGB(207, 159, 255)});
//Plane
AddPlane({ -5.f,0.f,0.f }, { 1.f,0.f,0.f }, matId_Solid_Green);
AddPlane({ 5.f,0.f,0.f }, { -1.f,0.f,0.f }, matId_Solid_Green);
AddPlane({ 0.f,0.f,0.f }, { 0.f,1.f,0.f }, matId_Solid_Yellow);
AddPlane({ 0.f,10.f,0.f }, { 0.f,-1.f,0.f }, matId_Solid_Yellow);
AddPlane({ 0.f,0.f,10.f }, { 0.f,0.f,-1.f }, matId_Solid_Magenta);
//Spheres
AddSphere({-1.75f,1.f,0.f}, .75f, matId_Solid_Red);
AddSphere({0.f,1.f,0.f}, .75f, matId_Solid_Blue);
AddSphere({ 1.75f,1.f,0.f }, .75f, matId_Solid_Red);
AddSphere({ -1.75f,3.f,0.f }, .75f, matId_Solid_Blue);
AddSphere({ 0.f,3.f,0.f }, .75f, matId_Solid_Red);
AddSphere({ 1.75f,3.f,0.f }, .75f, matId_Solid_Blue);
/*AddSphere({ 0.f,5.f,0.f }, .75f, matId_Solid_Porple);*/
//Light
AddPointLight({ 0.f,5.f,-5.f }, 70.f, colors::White);
}
void Scene_W3::Initialize()
{
m_Camera.origin = { 0.f,3.f,-9.f };
m_Camera.fovAngle = 45.f;
const auto matCT_GrayRoughMetal = AddMaterial(new Material_CookTorrence({.972f,.960f,.915f},1.f,1.f));
const auto matCT_GrayMediumMetal = AddMaterial(new Material_CookTorrence({ .972f,.960f,.915f }, 1.f, .6f));
const auto matCT_GraySmoothMetal = AddMaterial(new Material_CookTorrence({ .972f,.960f,.915f }, 1.f, .1f));
const auto matCT_GrayRoughPlastic = AddMaterial(new Material_CookTorrence({ .75f,.75f,.75f },0.f, 1.f));
const auto matCT_GrayMediumPlastic = AddMaterial(new Material_CookTorrence({ .75f,.75f,.75f },0.f, .6f));
const auto matCT_GraySmoothPlastic = AddMaterial(new Material_CookTorrence({ .75f,.75f,.75f },0.f, .1f));
const auto matLambert_GrayBlue = AddMaterial(new Material_Lambert({ .49f,.57f,.57f }, 1.f));
//Plane
AddPlane(Vector3{0.f,0.f,10.f}, Vector3{0.f,0.f,-1.f},matLambert_GrayBlue);//Back
AddPlane(Vector3{0.f,0.f,0.f}, Vector3{0.f,1.f,0.f},matLambert_GrayBlue);//Bottom
AddPlane(Vector3{0.f,10.f,0.f}, Vector3{0.f,-1.f,0.f},matLambert_GrayBlue);//Top
AddPlane(Vector3{ 5.f,0.f,0.f}, Vector3{-1.f,0.f,0.f},matLambert_GrayBlue);//Right
AddPlane(Vector3{-5.f,0.f,0.f}, Vector3{ 1.f,0.f,0.f},matLambert_GrayBlue);//Left
//Temporary Lambert-Phong Spheres & Materials
//const auto matLambertPhong1 = AddMaterial(new Material_LambertPhong(colors::Blue, 0.5, 0.5, 3.f));
//const auto matLambertPhong2 = AddMaterial(new Material_LambertPhong(colors::Blue, 0.5, 0.5, 15.f));
//const auto matLambertPhong3 = AddMaterial(new Material_LambertPhong(colors::Blue, 0.5, 0.5, 50.f));
//AddSphere({ -1.75f,1.f,0.f }, .75f, matLambertPhong1);
//AddSphere({ 0.f,1.f,0.f }, .75f, matLambertPhong2);
//AddSphere({ 1.75f,1.f,0.f }, .75f, matLambertPhong3);
//Spheres
AddSphere({ -1.75f,1.f,0.f },.75f, matCT_GrayRoughMetal);
AddSphere({ 0.f,1.f,0.f }, .75f, matCT_GrayMediumMetal);
AddSphere({ 1.75f,1.f,0.f }, .75f, matCT_GraySmoothMetal);
AddSphere({ -1.75f,3.f,0.f },.75f, matCT_GrayRoughPlastic);
AddSphere({ 0.f,3.f,0.f }, .75f, matCT_GrayMediumPlastic);
AddSphere({ 1.75f,3.f,0.f }, .75f, matCT_GraySmoothPlastic);
//Light
AddPointLight(Vector3{ 0.f,5.f,5.f }, 50.f, ColorRGB{ 1.f,.61f,.45f }); //Backlight
AddPointLight(Vector3{-2.5f,5.f,-5.f }, 70.f, ColorRGB{ 1.f,.8f,.45f }); //Front Light Left
AddPointLight(Vector3{2.5f,2.5f,-5.f }, 50.f, ColorRGB{ .34f,.47f,.68f }); //Front Light Right
//PHONG TEST SCENE
//m_Camera.origin = { 0.f,1.f,-5.f };
//m_Camera.fovAngle = 45.f;
////Materials
//const auto matLambert_Red = AddMaterial(new Material_Lambert(colors::Red,1.f));
//const auto matLambert_Blue = AddMaterial(new Material_LambertPhong(colors::Blue,1.f,1.f,60.f));
//const auto matLambert_Yellow = AddMaterial(new Material_Lambert(colors::Yellow, 1.f));
////Spheres
//AddSphere({ -.75f,1.f,.0f }, 1.f, matLambert_Red);
//AddSphere({ .75f,1.f,.0f }, 1.f, matLambert_Blue);
////Plane
//AddPlane({ 0.f,0.f,0.f }, { 0.f,1.f,0.f }, matLambert_Yellow);
////Light
//AddPointLight({ 0.f,5.f,5.f }, 25.f,colors::White);
//AddPointLight({ 0.f,2.5f,-5.f },25.f,colors::White);
}
void Scene_W4_Bunny::Initialize()
{
m_Camera.origin = { 0.f, 1.f, -5.f };
m_Camera.fovAngle = 45.f;
// Materials
const auto matLambert_GrayBlue = AddMaterial(new Material_Lambert({ 0.49f, 0.57f, 0.57f }, 1.f));
const auto matLambert_White = AddMaterial(new Material_Lambert(colors::White, 1.f));
// Planes
AddPlane({ 0.f, 0.f, 10.f },{ 0.f, 0.f, -1.f }, matLambert_GrayBlue); // BACK
AddPlane({ 0.f, 0.f, 0.f }, { 0.f, 1.f, 0.f }, matLambert_GrayBlue); // BOTTOM
AddPlane({ 0.f, 10.f, 0.f },{ 0.f, -1.f, 0.f }, matLambert_GrayBlue); // TOP
AddPlane({ 5.f, 0.f, 0.f }, { -1.f, 0.f, 0.f }, matLambert_GrayBlue); // RIGHT
AddPlane({ -5.f, 0.f, 0.f },{ 1.f, 0.f, 0.f }, matLambert_GrayBlue); // LEFT
// Triangle (Temp)
//auto triangle = Triangle{ { -.75f, .5f, 0.f }, { -.75f, 2.f, 0.f }, { .75f, .5f, 0.f } };
//triangle.cullMode = TriangleCullMode::FrontFaceCulling;
//triangle.materialIndex = matLambert_White;
//m_Triangles.emplace_back(triangle);
//const auto triangleMesh = AddTriangleMesh(TriangleCullMode::NoCulling, matLambert_White);
//triangleMesh->positions = { { -0.75f, -1.f, 0.f}, { -0.75f, 1.f, 0.f},
// { 0.75f, 1.f, 1.f}, { 0.75f, -1.f, 0.f} };
//triangleMesh->indices = {
// 0, 1, 2, // Triangle 1
// 0, 2, 3 // Triangle 2
//};
//triangleMesh->CalculateNormals();
//triangleMesh->Translate({ 0.f,1.5f,0.f });
//triangleMesh->RotateY(45);
//triangleMesh->UpdateTransforms();
pMesh = AddTriangleMesh(TriangleCullMode::BackFaceCulling, matLambert_White);
Utils::ParseOBJ("Resources/lowpoly_bunny.obj",
pMesh->positions,
pMesh->normals,
pMesh->indices);
//pMesh->positions = { { -0.75f, -1.f, 0.f}, //v0
// { -0.75f, 1.f, 0.f}, //v1
// { 0.75f, 1.f, 1.f}, //v2
// { 0.75f, -1.f, 0.f} };//v3
//pMesh->indices = {
// 0, 1, 2, // Triangle 1
// 0, 2, 3 // Triangle 2
//};
//pMesh->CalculateNormals();
//pMesh->Translate({ 0.f,1.5f,0.f });
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
}
void Scene_W4_Bunny::Update(dae::Timer* pTimer)
{
Scene::Update(pTimer);
}
void Scene_W4_ReferenceScene::Initialize()
{
sceneName = "Reference Scene";
m_Camera.origin = { 0.f, 3.f, -9.f };
m_Camera.fovAngle = 45.f;
// Materials
const auto matCT_GrayRoughMetal = AddMaterial(new Material_CookTorrence({ 0.972f, 0.960f, 0.915f }, 1.f, 1.0f));
const auto matCT_GrayMediumMetal = AddMaterial(new Material_CookTorrence({ 0.972f, 0.960f, 0.915f }, 1.f, 0.6f));
const auto matCT_GraySmoothMetal = AddMaterial(new Material_CookTorrence({ 0.972f, 0.960f, 0.915f }, 1.f, 0.1f));
const auto matCT_GrayRoughPlastic = AddMaterial(new Material_CookTorrence({ 0.75f , 0.75f , 0.75f }, 0.f, 1.0f));
const auto matCT_GrayMediumPlastic = AddMaterial(new Material_CookTorrence({ 0.75f , 0.75f , 0.75f }, 0.f, 0.6f));
const auto matCT_GraySmoothPlastic = AddMaterial(new Material_CookTorrence({ 0.75f , 0.75f , 0.75f }, 0.f, 0.1f));
const auto matLambert_GrayBlue = AddMaterial(new Material_Lambert({ 0.49f, 0.57f, 0.57f }, 1.f));
const auto matLambert_White = AddMaterial(new Material_Lambert(colors::White, 1.f));
// Plane
AddPlane(Vector3{ 0.f, 0.f, 10.f }, Vector3{ 0.f, 0.f, -1.f }, matLambert_GrayBlue); // BACK
AddPlane(Vector3{ 0.f, 0.f, 0.f }, Vector3{ 0.f, 1.f, 0.f }, matLambert_GrayBlue); // BOTTOM
AddPlane(Vector3{ 0.f, 10.f, 0.f }, Vector3{ 0.f, -1.f, 0.f }, matLambert_GrayBlue); // TOP
AddPlane(Vector3{ 5.f, 0.f, 0.f }, Vector3{ -1.f, 0.f, 0.f }, matLambert_GrayBlue); // RIGHT
AddPlane(Vector3{ -5.f, 0.f, 0.f }, Vector3{ 1.f, 0.f, 0.f }, matLambert_GrayBlue); // LEFT
// Spheres
AddSphere({ -1.75f, 1.f, 0.f, }, 0.75f, matCT_GrayRoughMetal);
AddSphere({ 0.f , 1.f, 0.f, }, 0.75f, matCT_GrayMediumMetal);
AddSphere({ 1.75f, 1.f, 0.f, }, 0.75f, matCT_GraySmoothMetal);
AddSphere({ -1.75f, 3.f, 0.f, }, 0.75f, matCT_GrayRoughPlastic);
AddSphere({ 0.f , 3.f, 0.f, }, 0.75f, matCT_GrayMediumPlastic);
AddSphere({ 1.75f, 3.f, 0.f, }, 0.75f, matCT_GraySmoothPlastic);
// Triangle
const Triangle baseTriangle = { Vector3(-0.75f, 1.5f, 0.f) //v0
, Vector3(0.75f, 0.0f, 0.f) //v1
, Vector3(-0.75f, 0.0f, 0.f) }; //v2
// Triangle Meshes
m_Meshes[0] = AddTriangleMesh(TriangleCullMode::BackFaceCulling, matLambert_White);
m_Meshes[0]->AppendTriangle(baseTriangle, true);
m_Meshes[0]->Translate({ -1.75f, 4.5f, 0.f });
m_Meshes[0]->UpdateTransforms();
m_Meshes[1] = AddTriangleMesh(TriangleCullMode::FrontFaceCulling, matLambert_White);
m_Meshes[1]->AppendTriangle(baseTriangle, true);
m_Meshes[1]->Translate({ 0.f, 4.5f, 0.f });
m_Meshes[1]->UpdateTransforms();
m_Meshes[2] = AddTriangleMesh(TriangleCullMode::NoCulling, matLambert_White);
m_Meshes[2]->AppendTriangle(baseTriangle, true);
m_Meshes[2]->Translate({ 1.75f, 4.5f, 0.f });
m_Meshes[2]->UpdateTransforms();
// Light
AddPointLight({ 0.f , 5.f , 5.f }, 50.f, ColorRGB{ 1.f , 0.61f, 0.45f }); // BackLight
AddPointLight({ -2.5f , 5.f , -5.f }, 70.f, ColorRGB{ 1.f , 0.8f , 0.45f }); // Front Light Left
AddPointLight({ 2.5f , 2.5f, -5.f }, 50.f, ColorRGB{ 0.34f, 0.47f, 0.68f });
}
void Scene_W4_ReferenceScene::Update(dae::Timer* pTimer)
{
Scene::Update(pTimer);
const auto yawAngle = (cos(pTimer->GetTotal()) + 1.f) / 2.f * PI_2;
for (const auto m : m_Meshes)
{
m->RotateY(yawAngle);
m->UpdateTransforms();
}
}
} }

View File

@@ -51,8 +51,12 @@ namespace dae
std::vector<Light> m_Lights{}; std::vector<Light> m_Lights{};
std::vector<Material*> m_Materials{}; std::vector<Material*> m_Materials{};
//Temp (Individual Triangle Test)
std::vector<Triangle> m_Triangles{};
Camera m_Camera{}; Camera m_Camera{};
Sphere* AddSphere(const Vector3& origin, float radius, unsigned char materialIndex = 0); Sphere* AddSphere(const Vector3& origin, float radius, unsigned char materialIndex = 0);
Plane* AddPlane(const Vector3& origin, const Vector3& normal, unsigned char materialIndex = 0); Plane* AddPlane(const Vector3& origin, const Vector3& normal, unsigned char materialIndex = 0);
TriangleMesh* AddTriangleMesh(TriangleCullMode cullMode, unsigned char materialIndex = 0); TriangleMesh* AddTriangleMesh(TriangleCullMode cullMode, unsigned char materialIndex = 0);
@@ -77,4 +81,74 @@ namespace dae
void Initialize() override; void Initialize() override;
}; };
//WEEK 2 Test Scene
class Scene_W2 final : public Scene
{
public:
Scene_W2() = default;
~Scene_W2() override = default;
Scene_W2(const Scene_W2&) = delete;
Scene_W2(Scene_W2&&) noexcept = delete;
Scene_W2& operator=(const Scene_W2&) = delete;
Scene_W2& operator=(Scene_W2&&) noexcept = delete;
void Initialize() override;
};
//WEEK 3 Test Scene
class Scene_W3 final : public Scene
{
public:
Scene_W3() = default;
~Scene_W3() override = default;
Scene_W3(const Scene_W3&) = delete;
Scene_W3(Scene_W3&&) noexcept = delete;
Scene_W3& operator=(const Scene_W3&) = delete;
Scene_W3& operator=(Scene_W3&&) noexcept = delete;
void Initialize() override;
};
//WEEK 4 Bunny Scene
class Scene_W4_Bunny final : public Scene
{
public:
Scene_W4_Bunny() = default;
~Scene_W4_Bunny() override = default;
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;
private:
TriangleMesh* pMesh{ nullptr };
};
//WEEK 4 Reference Scene
class Scene_W4_ReferenceScene final : public Scene
{
public:
Scene_W4_ReferenceScene() = default;
~Scene_W4_ReferenceScene() override = default;
Scene_W4_ReferenceScene(const Scene_W4_ReferenceScene&) = delete;
Scene_W4_ReferenceScene(Scene_W4_ReferenceScene&&) noexcept = delete;
Scene_W4_ReferenceScene& operator=(const Scene_W4_ReferenceScene&) = delete;
Scene_W4_ReferenceScene& operator=(Scene_W4_ReferenceScene&&) noexcept = delete;
void Initialize() override;
void Update(dae::Timer* pTimer) override;
private:
TriangleMesh* m_Meshes[3]{ };
};
} }

View File

@@ -28,25 +28,24 @@ namespace dae
float thc{ float(sqrt(sphere.radius*sphere.radius - od)) }; float thc{ float(sqrt(sphere.radius*sphere.radius - od)) };
float t0 = tca - thc; float t = tca - thc;
float t1 = tca + thc;
Vector3 point{ ray.origin + t0 * ray.direction }; if (t < ray.min || t > ray.max)
Vector3 point2{ ray.origin + t1 * ray.direction };
if (Vector3(ray.direction,point).SqrMagnitude() > Vector3(ray.direction, point2).SqrMagnitude())
{ {
hitRecord.origin = Vector3(ray.direction, point2); t = tca + thc;
hitRecord.normal = Vector3(sphere.origin, Vector3(ray.direction, point2)).Normalized(); if (t < ray.min || t > ray.max) return false;
hitRecord.t = t1;
return true;
} }
hitRecord.origin = Vector3(ray.direction, point); if (!ignoreHitRecord)
hitRecord.normal = Vector3(sphere.origin, Vector3(ray.direction, point)).Normalized(); {
hitRecord.t = t0; hitRecord.t = t;
return true; hitRecord.didHit = true;
hitRecord.origin = ray.origin + hitRecord.t * ray.direction;
hitRecord.normal = (hitRecord.origin - sphere.origin).Normalized();
hitRecord.materialIndex = sphere.materialIndex;
}
return true;
} }
@@ -56,21 +55,24 @@ namespace dae
HitRecord temp{}; HitRecord temp{};
return HitTest_Sphere(sphere, ray, temp, true); return HitTest_Sphere(sphere, ray, temp, true);
} }
#pragma endregion #pragma endregion
#pragma region Plane HitTest #pragma region Plane HitTest
//PLANE HIT-TESTS //PLANE HIT-TESTS
inline bool HitTest_Plane(const Plane& plane, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false) inline bool HitTest_Plane(const Plane& plane, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
{ {
float t = Vector3::Dot(plane.origin - ray.origin, plane.normal) / Vector3::Dot(ray.direction ,plane.normal); float t = Vector3::Dot(plane.origin - ray.origin, plane.normal) / Vector3::Dot(ray.direction ,plane.normal);
if (t >= 0) if (t >= ray.min && t <= ray.max)
{ {
Vector3 p{ ray.origin + t * ray.direction };
hitRecord.didHit = true; hitRecord.didHit = true;
hitRecord.t = t; hitRecord.t = t;
hitRecord.materialIndex = plane.materialIndex; hitRecord.materialIndex = plane.materialIndex;
hitRecord.normal = plane.normal; hitRecord.normal = plane.normal;
Vector3 p{ ray.origin + t * ray.direction };
hitRecord.origin = p; hitRecord.origin = p;
return true; return true;
} }
@@ -86,27 +88,155 @@ namespace dae
return HitTest_Plane(plane, ray, temp, true); return HitTest_Plane(plane, ray, temp, true);
} }
#pragma endregion #pragma endregion
#pragma region Triangle HitTest #pragma region Triangle HitTest
//TRIANGLE HIT-TESTS //TRIANGLE HIT-TESTS
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false) inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
{ {
//todo W5
throw std::runtime_error("Not Implemented Yet"); float nv(Vector3::Dot(triangle.normal, ray.direction));
if ( nv < 0.001 && nv > -0.001)
{
return false; return false;
} }
Vector3 a(triangle.v0, triangle.v1);
Vector3 b(triangle.v1, triangle.v2);
Vector3 c(triangle.v2, triangle.v0);
float t = Vector3::Dot(triangle.v0 - ray.origin, triangle.normal) / Vector3::Dot(ray.direction, triangle.normal);
if (t >= ray.min && t <= ray.max)
{
Vector3 P{ ray.origin + t * ray.direction };
const Vector3* triangleV[3] = { &triangle.v0,&triangle.v1,&triangle.v2 };
const Vector3* triangleEdges[3]{ &a,&b,&c };
for (int idx{ 0 }; idx < 3; idx++)
{
Vector3 p(*triangleV[idx], P);
if (Vector3::Dot(Vector3::Cross(*triangleEdges[idx], p), triangle.normal) < 0)
{
return false;
}
}
if (triangle.cullMode == TriangleCullMode::NoCulling)
{
if (ignoreHitRecord == false)
{
hitRecord.normal = triangle.normal;
hitRecord.didHit = true;
hitRecord.materialIndex = triangle.materialIndex;
hitRecord.origin = P;
hitRecord.t = t;
}
return true;
}
else if (triangle.cullMode == TriangleCullMode::BackFaceCulling)
{
if (ignoreHitRecord == false)
{
if (nv > 0.001)
{
return false;
}
hitRecord.normal = triangle.normal;
hitRecord.didHit = true;
hitRecord.materialIndex = triangle.materialIndex;
hitRecord.origin = P;
hitRecord.t = t;
return true;
}
if (nv > 0.001)
{
return true;
}
return false;
}
else if (triangle.cullMode == TriangleCullMode::FrontFaceCulling)
{
if (ignoreHitRecord == false)
{
if (nv < 0.001)
{
return false;
}
hitRecord.normal = triangle.normal;
hitRecord.didHit = true;
hitRecord.materialIndex = triangle.materialIndex;
hitRecord.origin = P;
hitRecord.t = t;
return true;
}
if (nv < 0.001)
{
return true;
}
return false;
}
}
return false;
}
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray) inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray)
{ {
HitRecord temp{}; HitRecord temp{};
return HitTest_Triangle(triangle, ray, temp, true); return HitTest_Triangle(triangle, ray, temp, true);
} }
#pragma endregion #pragma endregion
#pragma region TriangeMesh HitTest #pragma region TriangeMesh HitTest
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false) inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
{ {
//todo W5 HitRecord tempHit = {};
throw std::runtime_error("Not Implemented Yet");
return false; for (int idx{ 0 }; idx < mesh.indices.size(); idx += 3)
{
int i0 = mesh.indices[idx];
int i1 = mesh.indices[idx + 1];
int i2 = mesh.indices[idx + 2];
Triangle triangle{ mesh.transformedPositions[i0],mesh.transformedPositions[i1],mesh.transformedPositions[i2],mesh.transformedNormals[idx / 3] };
triangle.materialIndex = mesh.materialIndex;
triangle.cullMode = mesh.cullMode;
HitTest_Triangle(triangle, ray, tempHit);
if (tempHit.didHit)
{
if (tempHit.t < hitRecord.t)
{
hitRecord = tempHit;
}
}
}
return hitRecord.didHit;
} }
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray) inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray)
@@ -122,16 +252,19 @@ namespace dae
//Direction from target to light //Direction from target to light
inline Vector3 GetDirectionToLight(const Light& light, const Vector3 origin) inline Vector3 GetDirectionToLight(const Light& light, const Vector3 origin)
{ {
//todo W3 Vector3 lightVec(origin, light.origin);
throw std::runtime_error("Not Implemented Yet"); return lightVec;
return {};
} }
inline ColorRGB GetRadiance(const Light& light, const Vector3& target) inline ColorRGB GetRadiance(const Light& light, const Vector3& target)
{ {
//todo W3 if (light.type == LightType::Directional)
throw std::runtime_error("Not Implemented Yet"); {
return {}; return ColorRGB { light.color * light.intensity };
}
return ColorRGB{ light.color * (light.intensity / (Vector3(target,light.origin).SqrMagnitude()) ) };
} }
} }

View File

@@ -47,8 +47,11 @@ int main(int argc, char* args[])
const auto pTimer = new Timer(); const auto pTimer = new Timer();
const auto pRenderer = new Renderer(pWindow); const auto pRenderer = new Renderer(pWindow);
const auto pScene = new Scene_W1(); const auto pScene = new Scene_W4_ReferenceScene();
const auto pScene2 = new Scene_W4_Bunny();
pScene->Initialize(); pScene->Initialize();
pScene2->Initialize();
//Start loop //Start loop
pTimer->Start(); pTimer->Start();
@@ -59,6 +62,7 @@ int main(int argc, char* args[])
float printTimer = 0.f; float printTimer = 0.f;
bool isLooping = true; bool isLooping = true;
bool takeScreenshot = false; bool takeScreenshot = false;
bool isBunnyScene = false;
while (isLooping) while (isLooping)
{ {
//--------- Get input events --------- //--------- Get input events ---------
@@ -73,15 +77,51 @@ int main(int argc, char* args[])
case SDL_KEYUP: case SDL_KEYUP:
if (e.key.keysym.scancode == SDL_SCANCODE_X) if (e.key.keysym.scancode == SDL_SCANCODE_X)
takeScreenshot = true; takeScreenshot = true;
if (e.key.keysym.scancode == SDL_SCANCODE_F2)
{
pRenderer->ToggleShadows();
}
if (e.key.keysym.scancode == SDL_SCANCODE_F3)
{
pRenderer->CycleLightingMode();
}
if (e.key.keysym.scancode == SDL_SCANCODE_F4)
{
pRenderer->ToggleMultiThreading();
}
if (e.key.keysym.scancode == SDL_SCANCODE_F5)
{
isBunnyScene = !isBunnyScene;
}
break; break;
} }
} }
//--------- Update --------- //--------- Update ---------
if (isBunnyScene)
{
pScene2->Update(pTimer);
}
else
{
pScene->Update(pTimer); pScene->Update(pTimer);
}
//--------- Render --------- //--------- Render ---------
if (isBunnyScene)
{
pRenderer->Render(pScene2);
}
else
{
pRenderer->Render(pScene); pRenderer->Render(pScene);
}
//--------- Timer --------- //--------- Timer ---------
pTimer->Update(); pTimer->Update();
@@ -106,6 +146,7 @@ int main(int argc, char* args[])
//Shutdown "framework" //Shutdown "framework"
delete pScene; delete pScene;
delete pScene2;
delete pRenderer; delete pRenderer;
delete pTimer; delete pTimer;