From 254a796fac1f3f3f8dc6e5e3bc345ca5b0e6639e Mon Sep 17 00:00:00 2001 From: Bram Verhulst Date: Wed, 25 Sep 2024 16:29:49 +0200 Subject: [PATCH] Finish Week 1 (Could be a bug) --- project/src/Renderer.cpp | 37 +++++++++++++++++++--------- project/src/Scene.cpp | 17 +++++++++++-- project/src/Utils.h | 52 +++++++++++++++++++++++++++++++++++----- project/src/Vector3.cpp | 8 ++----- project/src/Vector4.cpp | 4 +--- project/src/main.cpp | 2 +- 6 files changed, 91 insertions(+), 29 deletions(-) diff --git a/project/src/Renderer.cpp b/project/src/Renderer.cpp index cfc44b0..5352e12 100644 --- a/project/src/Renderer.cpp +++ b/project/src/Renderer.cpp @@ -20,30 +20,45 @@ Renderer::Renderer(SDL_Window * pWindow) : SDL_GetWindowSize(pWindow, &m_Width, &m_Height); m_pBufferPixels = static_cast(m_pBuffer->pixels); } - void Renderer::Render(Scene* pScene) const { Camera& camera = pScene->GetCamera(); auto& materials = pScene->GetMaterials(); auto& lights = pScene->GetLights(); + float apsectRatio = static_cast(m_Width) / m_Height; + for (int px{}; px < m_Width; ++px) { for (int py{}; py < m_Height; ++py) { - float gradient = px / static_cast(m_Width); - gradient += py / static_cast(m_Width); - gradient /= 2.0f; + float NDCx = (2 * ((px + 0.5) / m_Width) - 1) * apsectRatio; + float NDCy = 1 - 2 * ((py + 0.5) / m_Height); - ColorRGB finalColor{ gradient, gradient, gradient }; + Vector3 rayDir = Vector3{ NDCx, NDCy, 1 }; + Ray ray{ Vector3(0, 0, 0), rayDir }; - //Update Color in Buffer - finalColor.MaxToOne(); + //set the color based on the ray direction + ColorRGB finalColor{ 0.f, 0.f, 0.f }; + + HitRecord closestHit{}; + pScene->GetClosestHit(ray, closestHit); + + if(closestHit.didHit){ + finalColor = materials[closestHit.materialIndex]->Shade(); +// finalColor = ColorRGB(closestHit.normal.x, closestHit.normal.y, closestHit.normal.z); +// const float scaled_t = (closestHit.t - 50.f) / 40.f; +// 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(finalColor.r * 255), + static_cast(finalColor.g * 255), + static_cast(finalColor.b * 255)); - 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)); } } diff --git a/project/src/Scene.cpp b/project/src/Scene.cpp index 468d827..136915d 100644 --- a/project/src/Scene.cpp +++ b/project/src/Scene.cpp @@ -28,8 +28,21 @@ namespace dae { void dae::Scene::GetClosestHit(const Ray& ray, HitRecord& closestHit) const { - //todo W1 - throw std::runtime_error("Not Implemented Yet"); + closestHit.t = FLT_MAX; + + for (const Sphere& sphere : m_SphereGeometries){ + HitRecord hitRecord{}; + if (GeometryUtils::HitTest_Sphere(sphere, ray, hitRecord) && hitRecord.t < closestHit.t){ + closestHit = hitRecord; + } + } + + for (const Plane& plane : m_PlaneGeometries){ + HitRecord hitRecord{}; + if(GeometryUtils::HitTest_Plane(plane, ray, hitRecord) && hitRecord.t < closestHit.t){ + closestHit = hitRecord; + } + } } bool Scene::DoesHit(const Ray& ray) const diff --git a/project/src/Utils.h b/project/src/Utils.h index 4f4eeff..d7c7897 100644 --- a/project/src/Utils.h +++ b/project/src/Utils.h @@ -11,9 +11,34 @@ namespace dae //SPHERE HIT-TESTS inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false) { - //todo W1 - throw std::runtime_error("Not Implemented Yet"); - return false; + const float radius2 = sphere.radius * sphere.radius; + const Vector3 CameraToOrigin = sphere.origin - ray.origin; + const float tInSphere = Vector3::Dot(CameraToOrigin, ray.direction); + + if(tInSphere < 0) return false; //Looking away from sphere + + const float od2 = std::pow(Vector3::Reject(CameraToOrigin, ray.direction).Magnitude(),2); + const float thc = std::sqrt(radius2 - od2); + + float t0 = tInSphere - thc; + float t1 = tInSphere + thc; + + if(t0 < 0 && t1 < 0) return false; //Both intersections are behind the camera + + if(t0 < 0) t0 = t1; //If t0 is behind the camera, use t1 + + if (!ignoreHitRecord && t0 < hitRecord.t){ + hitRecord.t = t0; + hitRecord.origin = ray.origin + ray.direction * t0; + hitRecord.normal = (hitRecord.origin - sphere.origin).Normalized(); + hitRecord.materialIndex = sphere.materialIndex; + hitRecord.didHit = true; + + return true; + } + + return false; + } inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray) @@ -26,9 +51,24 @@ namespace dae //PLANE HIT-TESTS inline bool HitTest_Plane(const Plane& plane, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false) { - //todo W1 - throw std::runtime_error("Not Implemented Yet"); - return false; + float dot = Vector3::Dot(plane.normal, ray.direction); + if(dot < 0) { + float t = Vector3::Dot(plane.origin - ray.origin, plane.normal) / dot; + + bool hit = t >= 0; + + if(hit && !ignoreHitRecord){ + hitRecord.t = t; + hitRecord.origin = ray.origin + ray.direction * t; + hitRecord.normal = plane.normal; + hitRecord.materialIndex = plane.materialIndex; + hitRecord.didHit = true; + } + + return hit; + } + + return false; } inline bool HitTest_Plane(const Plane& plane, const Ray& ray) diff --git a/project/src/Vector3.cpp b/project/src/Vector3.cpp index b0cab24..f7f4dcf 100644 --- a/project/src/Vector3.cpp +++ b/project/src/Vector3.cpp @@ -49,16 +49,12 @@ namespace dae { float Vector3::Dot(const Vector3& v1, const Vector3& v2) { - //todo W1 - throw std::runtime_error("Not Implemented Yet"); - return {}; + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2) { - //todo W1 - throw std::runtime_error("Not Implemented Yet"); - return {}; + return { v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x }; } Vector3 Vector3::Project(const Vector3& v1, const Vector3& v2) diff --git a/project/src/Vector4.cpp b/project/src/Vector4.cpp index ac45b59..fc07acf 100644 --- a/project/src/Vector4.cpp +++ b/project/src/Vector4.cpp @@ -42,9 +42,7 @@ namespace dae float Vector4::Dot(const Vector4& v1, const Vector4& v2) { - //todo W1 - throw std::runtime_error("Not Implemented Yet"); - return {}; + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w; } #pragma region Operator Overloads diff --git a/project/src/main.cpp b/project/src/main.cpp index 953031e..fdc1d6e 100644 --- a/project/src/main.cpp +++ b/project/src/main.cpp @@ -35,7 +35,7 @@ int main(int argc, char* args[]) const uint32_t height = 480; SDL_Window* pWindow = SDL_CreateWindow( - "RayTracer - **Insert Name**", + "RayTracer - Bram", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, 0);