From 1269b8dce77b78a7f5037a9f93ff6b5ff1824a25 Mon Sep 17 00:00:00 2001 From: Bram Verhulst Date: Wed, 16 Oct 2024 10:15:16 +0200 Subject: [PATCH] Fix shit --- project/src/BRDFs.h | 175 +++++++++++++++---------------- project/src/Camera.h | 11 +- project/src/ColorRGB.h | 7 +- project/src/Material.h | 40 +++++-- project/src/Renderer.cpp | 219 +++++++++++++++++++++++++++++++++++---- project/src/Renderer.h | 22 +++- project/src/Scene.cpp | 35 +++++++ project/src/Scene.h | 15 +++ project/src/Utils.h | 15 ++- project/src/main.cpp | 30 +++++- 10 files changed, 437 insertions(+), 132 deletions(-) diff --git a/project/src/BRDFs.h b/project/src/BRDFs.h index 9dfde07..d7d42b6 100644 --- a/project/src/BRDFs.h +++ b/project/src/BRDFs.h @@ -1,102 +1,93 @@ #pragma once + #include "Maths.h" -namespace dae -{ - namespace BRDF - { - /** - * \param kd Diffuse Reflection Coefficient - * \param cd Diffuse Color - * \return Lambert Diffuse Color - */ - static ColorRGB Lambert(float kd, const ColorRGB& cd) - { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } +namespace dae { + namespace BRDF { + /** + * \param kd Diffuse Reflection Coefficient + * \param cd Diffuse Color + * \return Lambert Diffuse Color + */ + static ColorRGB Lambert(float kd, const ColorRGB &cd) { + return (kd / PI) * cd; + } - static ColorRGB Lambert(const ColorRGB& kd, const ColorRGB& cd) - { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } + static ColorRGB Lambert(const ColorRGB &kd, const ColorRGB &cd) { + return (kd * PI) * cd; + } - /** - * \brief todo - * \param ks Specular Reflection Coefficient - * \param exp Phong Exponent - * \param l Incoming (incident) Light Direction - * \param v View Direction - * \param n Normal of the Surface - * \return Phong Specular Color - */ - static ColorRGB Phong(float ks, float exp, const Vector3& l, const Vector3& v, const Vector3& n) - { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } - - /** - * \brief BRDF Fresnel Function >> Schlick - * \param h Normalized Halfvector between View and Light directions - * \param v Normalized View direction - * \param f0 Base reflectivity of a surface based on IOR (Indices Of Refrection), this is different for Dielectrics (Non-Metal) and Conductors (Metal) - * \return - */ - static ColorRGB FresnelFunction_Schlick(const Vector3& h, const Vector3& v, const ColorRGB& f0) - { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } - - /** - * \brief BRDF NormalDistribution >> Trowbridge-Reitz GGX (UE4 implemetation - squared(roughness)) - * \param n Surface normal - * \param h Normalized half vector - * \param roughness Roughness of the material - * \return BRDF Normal Distribution Term using Trowbridge-Reitz GGX - */ - static float NormalDistribution_GGX(const Vector3& n, const Vector3& h, float roughness) - { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } + /** + * \brief todo + * \param ks Specular Reflection Coefficient + * \param exp Phong Exponent + * \param l Incoming (incident) Light Direction + * \param v View Direction + * \param n Normal of the Surface + * \return Phong Specular Color + */ + static ColorRGB Phong(float ks, float exp, const Vector3 &l, const Vector3 &v, const Vector3 &n) { + Vector3 reflect{l - 2 * Vector3::Dot(n, l) * n}; + float cosAngle{Vector3::Dot(reflect, v)}; + return {ks * powf(std::max(0.f, cosAngle), exp) * colors::White}; + } - /** - * \brief BRDF Geometry Function >> Schlick GGX (Direct Lighting + UE4 implementation - squared(roughness)) - * \param n Normal of the surface - * \param v Normalized view direction - * \param roughness Roughness of the material - * \return BRDF Geometry Term using SchlickGGX - */ - static float GeometryFunction_SchlickGGX(const Vector3& n, const Vector3& v, float roughness) - { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } + /** + * \brief BRDF Fresnel Function >> Schlick + * \param h Normalized Halfvector between View and Light directions + * \param v Normalized View direction + * \param f0 Base reflectivity of a surface based on IOR (Indices Of Refrection), this is different for Dielectrics (Non-Metal) and Conductors (Metal) + * \return + */ + static ColorRGB FresnelFunction_Schlick(const Vector3 &h, const Vector3 &v, const ColorRGB &f0) { + const float base = std::pow(1 - Vector3::Dot(h, v), 5); + auto returnValue{f0 + (colors::White - f0) * base}; + return returnValue; + } - /** - * \brief BRDF Geometry Function >> Smith (Direct Lighting) - * \param n Normal of the surface - * \param v Normalized view direction - * \param l Normalized light direction - * \param roughness Roughness of the material - * \return BRDF Geometry Term using Smith (> SchlickGGX(n,v,roughness) * SchlickGGX(n,l,roughness)) - */ - static float GeometryFunction_Smith(const Vector3& n, const Vector3& v, const Vector3& l, float roughness) - { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } + /** + * \brief BRDF NormalDistribution >> Trowbridge-Reitz GGX (UE4 implemetation - squared(roughness)) + * \param n Surface normal + * \param h Normalized half vector + * \param roughness Roughness of the material + * \return BRDF Normal Distribution Term using Trowbridge-Reitz GGX + */ + static float NormalDistribution_GGX(const Vector3 &n, const Vector3 &h, float roughness) { + const float a = roughness * roughness; + const float a2 = a * a; - } + const float dot{Vector3::Dot(n, h)}; + const float div{dot * dot * (a2 - 1) + 1}; + return a2 / (M_PI * div * div); + } + + + /** + * \brief BRDF Geometry Function >> Schlick GGX (Direct Lighting + UE4 implementation - squared(roughness)) + * \param n Normal of the surface + * \param v Normalized view direction + * \param roughness Roughness of the material + * \return BRDF Geometry Term using SchlickGGX + */ + static float GeometryFunction_SchlickGGX(const Vector3 &n, const Vector3 &v, float roughness) { + float cosAngle{ Vector3::Dot(n,v) }; + float k{ (roughness + 1) * (roughness + 1) / 8 }; + + return {cosAngle / (cosAngle * (1 - k) + k) }; + } + + /** + * \brief BRDF Geometry Function >> Smith (Direct Lighting) + * \param n Normal of the surface + * \param v Normalized view direction + * \param l Normalized light direction + * \param roughness Roughness of the material + * \return BRDF Geometry Term using Smith (> SchlickGGX(n,v,roughness) * SchlickGGX(n,l,roughness)) + */ + static float GeometryFunction_Smith(const Vector3 &n, const Vector3 &v, const Vector3 &l, float roughness) { + return { GeometryFunction_SchlickGGX(n,v,roughness) * GeometryFunction_SchlickGGX(n,l,roughness) }; + } + + } } \ No newline at end of file diff --git a/project/src/Camera.h b/project/src/Camera.h index 78c802c..39a7afa 100644 --- a/project/src/Camera.h +++ b/project/src/Camera.h @@ -30,6 +30,10 @@ namespace dae Matrix cameraToWorld{}; + void SetFOV(float fov) + { + fovAngle = fov; + } Matrix CalculateCameraToWorld() { @@ -49,9 +53,14 @@ namespace dae { const float deltaTime = pTimer->GetElapsed(); + + //Keyboard Input const uint8_t* pKeyboardState = SDL_GetKeyboardState(nullptr); { + + + float speed{10.f}; if (pKeyboardState[SDL_SCANCODE_W]) { @@ -98,7 +107,7 @@ namespace dae if(dirty) { Matrix rotMat{ - Matrix::CreateRotationX(TO_RADIANS * totalPitch) * Matrix::CreateRotationY(TO_RADIANS * totalYaw) + Matrix::CreateRotationX(-TO_RADIANS * totalPitch) * Matrix::CreateRotationY(-TO_RADIANS * totalYaw) }; forward = rotMat.TransformVector(Vector3::UnitZ); diff --git a/project/src/ColorRGB.h b/project/src/ColorRGB.h index f02f6ce..e21bfb6 100644 --- a/project/src/ColorRGB.h +++ b/project/src/ColorRGB.h @@ -50,9 +50,10 @@ namespace dae return *this; } - const ColorRGB& operator-(const ColorRGB& c) + const ColorRGB operator-(const ColorRGB& c) { - return *this -= c; + return { r - c.r, g - c.g, b - c.b }; + //TODO: fixed this } ColorRGB operator-(const ColorRGB& c) const @@ -142,7 +143,7 @@ namespace dae static ColorRGB Yellow{ 1,1,0 }; static ColorRGB Cyan{ 0,1,1 }; static ColorRGB Magenta{ 1,0,1 }; - static ColorRGB White{ 1,1,1 }; + static ColorRGB White{ 1.f,1.f,1.f }; static ColorRGB Black{ 0,0,0 }; static ColorRGB Gray{ 0.5f,0.5f,0.5f }; } diff --git a/project/src/Material.h b/project/src/Material.h index 21fc399..427c4ea 100644 --- a/project/src/Material.h +++ b/project/src/Material.h @@ -59,9 +59,7 @@ namespace dae ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; + return BRDF::Lambert(m_DiffuseReflectance, m_DiffuseColor); } private: @@ -84,10 +82,10 @@ namespace dae ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; - } + return BRDF::Lambert(m_DiffuseReflectance, m_DiffuseColor) + + BRDF::Phong(m_SpecularReflectance, m_PhongExponent, l, v, hitRecord.normal); + //W Rizz + } private: ColorRGB m_DiffuseColor{ colors::White }; @@ -109,9 +107,31 @@ namespace dae ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override { - //todo: W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; + Vector3 invV{ -v }; + Vector3 h{ ((invV + l) / (invV + l).Magnitude()) }; + + ColorRGB dielectricAlbedo{ 0.04f, 0.04f, 0.04f }; + ColorRGB f0{ (m_Metalness <= 0.f) ? dielectricAlbedo : m_Albedo }; + + Vector3 n{ hitRecord.normal }; + + ColorRGB fresnel{ BRDF::FresnelFunction_Schlick(h, invV, f0) }; + float normalDistribution{ BRDF::NormalDistribution_GGX(n, h, m_Roughness) }; + float geometryFunction{ BRDF::GeometryFunction_Smith(n, invV, l, m_Roughness) }; +// return ColorRGB{geometryFunction, geometryFunction, geometryFunction}; + // TODO: these dots should be passed around, not recalculated + const ColorRGB specular{ + fresnel * normalDistribution * geometryFunction / + (4.f * Vector3::Dot(invV, n) * Vector3::Dot(l, n)) + }; + + if(m_Metalness) + return specular; + + ColorRGB kd{ ColorRGB(1, 1, 1) - fresnel}; + ColorRGB diffuse{ BRDF::Lambert(kd, f0) }; + + return diffuse + specular; } private: diff --git a/project/src/Renderer.cpp b/project/src/Renderer.cpp index 03f2bff..4f9d047 100644 --- a/project/src/Renderer.cpp +++ b/project/src/Renderer.cpp @@ -1,4 +1,5 @@ //External includes +#include #include "SDL.h" #include "SDL_surface.h" @@ -19,6 +20,11 @@ Renderer::Renderer(SDL_Window *pWindow) : SDL_GetWindowSize(pWindow, &m_Width, &m_Height); m_pBufferPixels = static_cast(m_pBuffer->pixels); + m_xvalues.reserve(m_Width); + for (uint16_t x{}; x < m_Width; ++x) { + m_xvalues.push_back(x); + } + } void Renderer::Render(Scene *pScene) const { @@ -30,9 +36,15 @@ void Renderer::Render(Scene *pScene) const { float apsectRatio = static_cast(m_Width) / m_Height; float fov = tan((camera.fovAngle * (PI / 180.f)) / 2); - for (int px{}; px < m_Width; ++px) { - for (int py{}; py < m_Height; ++py) { - float NDCx = ((2 * ((px + 0.5) / m_Width) - 1) * apsectRatio) * fov; + for (int px{}; px < m_Width; px += 1) { + for (int py{}; py < m_Height; py += 1) { + + int actualPx = px; +// if (py % 2 != 0) { +// actualPx = px + 1; +// } + + float NDCx = ((2 * ((actualPx + 0.5) / m_Width) - 1) * apsectRatio) * fov; float NDCy = (1 - 2 * ((py + 0.5) / m_Height)) * fov; @@ -49,43 +61,208 @@ void Renderer::Render(Scene *pScene) const { HitRecord closestHit{}; pScene->GetClosestHit(ray, closestHit); + if (closestHit.didHit) { - finalColor = materials[closestHit.materialIndex]->Shade(); + for (const Light &light: lights) { + Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)}; + float rayMaxValue = lightDirection.Normalize(); + Ray lightRay = Ray{closestHit.origin + closestHit.normal * 0.01f, lightDirection, 0.0001f, + rayMaxValue}; + bool doesLightHit = pScene->DoesHit(lightRay); - for(const Light& light : lights) - { - Vector3 lightDirection{ LightUtils::GetDirectionToLight(light, closestHit.origin) }; - const float lightDistance = lightDirection.Normalize(); - const Ray lightRay{ - closestHit.origin + closestHit.normal * 0.01f, - lightDirection, 0.0001f, lightDistance - }; + if (m_CurrentLightingMode == LightingMode::Radiance) { + if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) { + auto radiance = LightUtils::GetRadiance(light, closestHit.origin); + finalColor += radiance; + } - if(pScene->DoesHit(lightRay)) - { - finalColor *= 0.5; - break; + + } else if (m_CurrentLightingMode == LightingMode::ObservedArea) { + if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) { +// float observedArea = std::clamp( +// LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f); +// finalColor.r += observedArea; +// finalColor.g += observedArea; +// finalColor.b += observedArea; + } + } else if (m_CurrentLightingMode == LightingMode::Combined) { + if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) { + auto radiance = LightUtils::GetRadiance(light, closestHit.origin); + float observedArea = std::clamp( + LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f); + + finalColor += radiance * observedArea * + materials[closestHit.materialIndex]->Shade(closestHit, lightDirection, + rayDir); + } + } else if (m_CurrentLightingMode == LightingMode::BRDF) { + if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) { + auto radiance = LightUtils::GetRadiance(light, closestHit.origin); + float observedArea = std::clamp( + LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f); + + finalColor += materials[closestHit.materialIndex]->Shade(closestHit, lightDirection, ray.direction); + } } - } + } } + +// if (m_CurrentLightingMode == LightingMode::ObservedArea) { +// if (closestHit.didHit) { +// for (const Light &light: lights) { +// Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)}; +// const float lightDistance = lightDirection.Normalize(); +// +// float law = std::clamp(LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f); +//// finalColor += materials[closestHit.materialIndex]->Shade() * law; +// finalColor += ColorRGB{law, law, law}; +// +// } +// } +// } +// +// if (m_ShadowsEnabled) { +// +// if (closestHit.didHit) { +//// finalColor = materials[closestHit.materialIndex]->Shade(); +// if (m_ShadowsEnabled) { +// for (const Light &light: lights) { +// Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)}; +// const float lightDistance = lightDirection.Normalize(); +// +// const Ray lightRay{ +// closestHit.origin + closestHit.normal * 0.01f, +// lightDirection, 0.0001f, lightDistance +// }; +// +// if (pScene->DoesHit(lightRay)) { +// finalColor *= 0.5; +// continue; +// } +// } +// } +// } +// } + finalColor.MaxToOne(); - m_pBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBuffer->format, - static_cast(finalColor.r * 255), - static_cast(finalColor.g * 255), - static_cast(finalColor.b * 255)); + m_pBufferPixels[actualPx + (py * m_Width)] = SDL_MapRGB(m_pBuffer->format, + static_cast(finalColor.r * 255), + static_cast(finalColor.g * 255), + static_cast(finalColor.b * 255)); } } + // go over the pixels and avg the pixels i skipped +// for (int px2{1}; px2 < m_Width; px2 += 2) { +// for (int py{1}; py < m_Height; py += 1) { +// if (px2 == m_Width - 1 || py == m_Height - 1) continue; +// if (px2 == 0 || py == 0) continue; +// +// int px = px2; +// if (py % 2 != 0) { +// px = px2 + 1; +// } +// +// +// uint8_t r = 0; +// uint8_t g = 0; +// uint8_t b = 0; +// SDL_GetRGB(m_pBufferPixels[px + (py * m_Width)], m_pBuffer->format, &r, &g, &b); +// ColorRGB currentColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f}; +// +// SDL_GetRGB(m_pBufferPixels[(px - 1) + (py * m_Width)], m_pBuffer->format, &r, &g, &b); +// ColorRGB leftColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f}; +// +// SDL_GetRGB(m_pBufferPixels[(px + 1) + (py * m_Width)], m_pBuffer->format, &r, &g, &b); +// ColorRGB rightColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f}; +// +// SDL_GetRGB(m_pBufferPixels[px + ((py - 1) * m_Width)], m_pBuffer->format, &r, &g, &b); +// ColorRGB upColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f}; +// +// SDL_GetRGB(m_pBufferPixels[px + ((py + 1) * m_Width)], m_pBuffer->format, &r, &g, &b); +// ColorRGB downColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f}; +// +// float avgR = (leftColor.r + rightColor.r + upColor.r + downColor.r) / 4; +// float avgG = (leftColor.g + rightColor.g + upColor.g + downColor.g) / 4; +// float avgB = (leftColor.b + rightColor.b + upColor.b + downColor.b) / 4; +// ColorRGB avgColor = ColorRGB{avgR, avgG, avgB}; +// +// m_pBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBuffer->format, +// static_cast(avgColor.r * 255), +// static_cast(avgColor.g * 255), +// static_cast(avgColor.b * 255)); +// } +// } + //@END //Update SDL Surface SDL_UpdateWindowSurface(m_pWindow); } +ColorRGB Renderer::Raytrace(const dae::Ray &viewRay, dae::Scene *pScene) const { + ColorRGB finalColor{0.f, 0.f, 0.f}; + + auto &materials = pScene->GetMaterials(); + Camera &camera = pScene->GetCamera(); + auto &lights = pScene->GetLights(); + + HitRecord closestHit{}; + pScene->GetClosestHit(viewRay, closestHit); + + if (closestHit.didHit) { + + for (const Light &light: lights) { + + Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)}; + const float lightDistance = lightDirection.Normalize(); + + const Ray lightRay{ + closestHit.origin + closestHit.normal * 0.0001f, + lightDirection, 0.0001f, lightDistance + }; + + if (m_ShadowsEnabled && pScene->DoesHit(lightRay)) + continue; + + float cosAngle = LightUtils::LambertCosineLaw(closestHit.normal, lightDirection); + + + return finalColor; + } + + + } +} + + bool Renderer::SaveBufferToImage() const { return SDL_SaveBMP(m_pBuffer, "RayTracing_Buffer.bmp"); } + + +void Renderer::CycleLightingMode() { + switch (m_CurrentLightingMode) { + case LightingMode::ObservedArea: + m_CurrentLightingMode = LightingMode::Radiance; + std::cout << "Radiance" << std::endl; + break; + case LightingMode::Radiance: + m_CurrentLightingMode = LightingMode::BRDF; + std::cout << "BRDF" << std::endl; + break; + case LightingMode::BRDF: + m_CurrentLightingMode = LightingMode::Combined; + std::cout << "Combined" << std::endl; + break; + case LightingMode::Combined: + m_CurrentLightingMode = LightingMode::ObservedArea; + std::cout << "Observed Area" << std::endl; + break; + } + +} diff --git a/project/src/Renderer.h b/project/src/Renderer.h index 03e541a..8936b02 100644 --- a/project/src/Renderer.h +++ b/project/src/Renderer.h @@ -2,6 +2,7 @@ #include #include "Camera.h" +#include "DataTypes.h" struct SDL_Window; struct SDL_Surface; @@ -24,12 +25,27 @@ namespace dae void Render(Scene* pScene) const; bool SaveBufferToImage() const; + void CycleLightingMode(); + void ToggleShadows() { m_ShadowsEnabled = !m_ShadowsEnabled; } + private: + enum class LightingMode { + ObservedArea, + Radiance, + BRDF, + Combined + }; + LightingMode m_CurrentLightingMode{ LightingMode::Combined }; + bool m_ShadowsEnabled{ true }; + + + SDL_Window* m_pWindow{}; SDL_Surface* m_pBuffer{}; uint32_t* m_pBufferPixels{}; + int m_Width{}; int m_Height{}; @@ -37,5 +53,9 @@ namespace dae Camera m_Camera{}; - }; + ColorRGB Raytrace(const Ray& viewRay, Scene* pScene) const; + + std::vector m_xvalues; + + }; } diff --git a/project/src/Scene.cpp b/project/src/Scene.cpp index ea1a9e2..f2e217a 100644 --- a/project/src/Scene.cpp +++ b/project/src/Scene.cpp @@ -179,4 +179,39 @@ namespace dae { AddPointLight({0.f, 5.f, -5.f}, 70.f, colors::White); } + + void Scene_W3::Initialize() + { + sceneName = "Week 3"; + m_Camera.origin = { 0,3,-9 }; + m_Camera.SetFOV(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 }, .0f, 1.f)); + const auto matCT_GrayMediumPlastic = AddMaterial(new Material_CookTorrence({ .75f, .75f, .75f }, .0f, .6f)); + const auto matCT_GraySmoothPlastic = AddMaterial(new Material_CookTorrence({ .75f, .75f, .75f }, .0f, .1f)); + + const auto matLambert_GrayBlue = AddMaterial(new Material_Lambert({ .49f, 0.57f, 0.57f }, 1.f)); + + 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 + + AddSphere(Vector3{ -1.75f, 1.f, 0.f }, .75f, matCT_GrayRoughMetal); + AddSphere(Vector3{ 0.f, 1.f, 0.f }, .75f, matCT_GrayMediumMetal); + AddSphere(Vector3{ 1.75f, 1.f, 0.f }, .75f, matCT_GraySmoothMetal); + AddSphere(Vector3{ -1.75f, 3.f, 0.f }, .75f, matCT_GrayRoughPlastic); + AddSphere(Vector3{ 0.f, 3.f, 0.f }, .75f, matCT_GrayMediumPlastic); + AddSphere(Vector3{ 1.75f, 3.f, 0.f }, .75f, matCT_GraySmoothPlastic); + + + + 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 }); + } } diff --git a/project/src/Scene.h b/project/src/Scene.h index be4cbe4..1abb68a 100644 --- a/project/src/Scene.h +++ b/project/src/Scene.h @@ -93,4 +93,19 @@ namespace dae void Initialize() override; }; + + + class Scene_W3 final : public Scene + { + public: + Scene_W3() = default; + ~Scene_W3() override = default; + + Scene_W3(const Scene_W1&) = delete; + Scene_W3(Scene_W1&&) noexcept = delete; + Scene_W3& operator=(const Scene_W1&) = delete; + Scene_W3& operator=(Scene_W1&&) noexcept = delete; + + void Initialize() override; + }; } diff --git a/project/src/Utils.h b/project/src/Utils.h index e4381cd..1a7b5dc 100644 --- a/project/src/Utils.h +++ b/project/src/Utils.h @@ -119,10 +119,19 @@ namespace dae inline ColorRGB GetRadiance(const Light& light, const Vector3& target) { - //todo W3 - throw std::runtime_error("Not Implemented Yet"); - return {}; + switch(light.type) + { + case LightType::Point: + return light.color * light.intensity / (light.origin - target).SqrMagnitude(); + case LightType::Directional: + return light.color * light.intensity; + } } + + inline float LambertCosineLaw(const Vector3& normal, const Vector3& lightDirection) + { + return Vector3::Dot(normal, lightDirection); + } } namespace Utils diff --git a/project/src/main.cpp b/project/src/main.cpp index 46d144c..e560d46 100644 --- a/project/src/main.cpp +++ b/project/src/main.cpp @@ -47,7 +47,7 @@ int main(int argc, char* args[]) const auto pTimer = new Timer(); const auto pRenderer = new Renderer(pWindow); - const auto pScene = new Scene_W2(); + const auto pScene = new Scene_W3(); pScene->Initialize(); //Start loop @@ -59,6 +59,7 @@ int main(int argc, char* args[]) float printTimer = 0.f; bool isLooping = true; bool takeScreenshot = false; + bool mouseLocked = false; while (isLooping) { //--------- Get input events --------- @@ -74,6 +75,33 @@ int main(int argc, char* args[]) if (e.key.keysym.scancode == SDL_SCANCODE_X) takeScreenshot = true; break; + case SDL_KEYDOWN: + 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_ESCAPE) + { + //release the mouse + if(mouseLocked) + { + SDL_SetRelativeMouseMode(SDL_FALSE); + mouseLocked = false; + } else { + SDL_SetRelativeMouseMode(SDL_TRUE); + mouseLocked = true; + } + } + + break; + //on focus lock mouse + case SDL_WINDOWEVENT: + if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) + SDL_SetRelativeMouseMode(SDL_TRUE); + mouseLocked = true; + break; + } }