diff --git a/PathTracer/imgui.ini b/PathTracer/imgui.ini index 1c9f000..87a1eb4 100644 --- a/PathTracer/imgui.ini +++ b/PathTracer/imgui.ini @@ -1,6 +1,6 @@ [Window][DockSpace Demo] Pos=0,0 -Size=1920,1046 +Size=1600,900 Collapsed=0 [Window][Debug##Default] @@ -20,24 +20,24 @@ Collapsed=0 [Window][ViewPort] Pos=0,26 -Size=1608,1020 +Size=1288,874 Collapsed=0 DockId=0x00000001,0 [Window][Settings] -Pos=1610,512 -Size=310,534 +Pos=1290,443 +Size=310,457 Collapsed=0 DockId=0x00000004,0 [Window][Scene] -Pos=1610,26 -Size=310,484 +Pos=1290,26 +Size=310,415 Collapsed=0 DockId=0x00000003,0 [Docking][Data] -DockSpace ID=0xF2944C7F Window=0x4647B76E Pos=0,60 Size=1920,1020 Split=X +DockSpace ID=0xF2944C7F Window=0x4647B76E Pos=125,185 Size=1600,874 Split=X DockNode ID=0x00000001 Parent=0xF2944C7F SizeRef=1288,874 CentralNode=1 Selected=0xEAE40D5D DockNode ID=0x00000002 Parent=0xF2944C7F SizeRef=310,874 Split=Y Selected=0x54723243 DockNode ID=0x00000003 Parent=0x00000002 SizeRef=310,484 Selected=0xE192E354 diff --git a/PathTracer/src/Renderer.cpp b/PathTracer/src/Renderer.cpp index 2625bb3..36f1d87 100644 --- a/PathTracer/src/Renderer.cpp +++ b/PathTracer/src/Renderer.cpp @@ -19,6 +19,7 @@ namespace Utilities { void Renderer::OnResize(uint32_t width, uint32_t height) { + if (m_FinalImage) { // There was no need for any resizes @@ -37,15 +38,14 @@ void Renderer::OnResize(uint32_t width, uint32_t height) { void Renderer::Render(const Scene& scene, const Camera& camera) { //std::for_each() + activeCamera = &camera; + activeScene = &scene; const glm::vec3& rayOrigin = camera.GetPosition(); - Ray ray; - ray.Origin = camera.GetPosition(); + for (uint32_t y = 0; y < m_FinalImage->GetHeight(); y++) { for (uint32_t x = 0; x < m_FinalImage->GetWidth(); x++) { - - ray.Direction = camera.GetRayDirections()[x + y * m_FinalImage->GetWidth()]; - glm::vec4 color = TraceRay(scene, ray); + glm::vec4 color = RayGeneration(x, y); color = glm::clamp(color, glm::vec4(0.0f), glm::vec4(1.0f)); @@ -59,18 +59,61 @@ void Renderer::Render(const Scene& scene, const Camera& camera) { } +glm::vec4 Renderer::RayGeneration(uint32_t x, uint32_t y) +{ + Ray ray; + ray.Origin = activeCamera->GetPosition(); + ray.Direction = activeCamera->GetRayDirections()[x + y * m_FinalImage->GetWidth()]; + + glm::vec3 finalColor(0.0f); + + int bounces = 2; + float multiplier = 1.0f; + for (int i = 0; i < bounces; i++) + { + Renderer::HitPayload payload = TraceRay(ray); + if (payload.hitTValue < 0.0f) { + glm::vec3 skyColor = glm::vec3(0.0f, 0.0f, 0.0f); + finalColor += skyColor * multiplier; + break; + } + + const Sphere& sphere = activeScene->spheres[payload.ObjectIndex]; + glm::vec3 sphereColor = sphere.albedo; + glm::vec3 lighting(0.0f); + for (const auto& light : activeScene->lights) + { + if (light.lightColor == glm::vec3(0.0f)) continue; + glm::vec3 lightDir = glm::normalize(-light.lightDirection); + float NdotL = glm::max(glm::dot(payload.worldNormal, lightDir), 0.0f); + lighting += sphere.albedo * light.lightColor * light.intensity * NdotL; + } + if (lighting == glm::vec3(0.0f)) + { + finalColor += glm::vec3(0.0f); + break; + } + + sphereColor = lighting; + finalColor += sphereColor * multiplier; + multiplier *= 0.5f; + ray.Origin = payload.worldPos - 0.001f * payload.worldNormal; + ray.Direction = glm::normalize(glm::reflect(ray.Direction, payload.worldNormal)); + } + return glm::vec4(finalColor, 1.0f); +} -glm::vec4 Renderer::TraceRay(const Scene& scene, const Ray& ray) +Renderer::HitPayload Renderer::TraceRay(const Ray& ray) { - glm::vec3 lightDir(-2.0f, -1.0f, -2.0f); - lightDir = glm::normalize(lightDir); + - if (scene.spheres.size() == 0) return glm::vec4(0, 0, 0, 1); - const Sphere* closestSphere = nullptr; + int closestSphere = -1; float hitTval = FLT_MAX; - for (const Sphere& sphere : scene.spheres) + + for ( size_t i=0; i< activeScene->spheres.size(); i++ ) { + const Sphere& sphere = activeScene->spheres[i]; glm::vec3 origin = ray.Origin - sphere.position; float a = glm::dot(ray.Direction, ray.Direction); @@ -83,24 +126,45 @@ glm::vec4 Renderer::TraceRay(const Scene& scene, const Ray& ray) continue; } - float t_0 = (-b - glm::sqrt(discriminant)) / (2.0f * a); - if (t_0 < hitTval) { - hitTval = t_0; - closestSphere = &sphere; - }//glm::vec3 sphereColor(1.0f, 0.0f, 1.0f); + float closestT = (-b - glm::sqrt(discriminant)) / (2.0f * a); + if (0.0f < closestT && closestT < hitTval) { + hitTval = closestT; + closestSphere = i; + } } - if (closestSphere == nullptr) return glm::vec4(0.0f,0.0f,0.0f,1.0f); + if (closestSphere < 0) + return Miss(ray); + return ClosestHit(ray, hitTval, closestSphere); + + +} + +Renderer::HitPayload Renderer::ClosestHit(const Ray& ray, float hitTVal, int objectIndex) +{ + + Renderer::HitPayload payload; + payload.hitTValue = hitTVal; + payload.ObjectIndex = objectIndex; - glm::vec3 origin = ray.Origin - closestSphere->position; + const Sphere& closestSphere = activeScene->spheres[objectIndex]; + glm::vec3 origin = ray.Origin - closestSphere.position; - glm::vec3 hitPos = hitTval * ray.Direction + origin; - glm::vec3 normal = glm::normalize(hitPos); + payload.worldPos = hitTVal * ray.Direction + origin; + payload.worldNormal= glm::normalize(payload.worldPos); - float lightIntensity = glm::max(glm::dot(-lightDir, glm::normalize(normal)), 0.0f); - glm::vec3 sphereColor = closestSphere->albedo; - sphereColor *= lightIntensity; - return glm::vec4(sphereColor, 1.0f); + payload.worldPos += closestSphere.position; + + return payload; } +Renderer::HitPayload Renderer::Miss(const Ray& ray) +{ + Renderer::HitPayload payload; + payload.hitTValue = -1.0f; + return payload; +} + + + diff --git a/PathTracer/src/Renderer.h b/PathTracer/src/Renderer.h index 36bb23a..d69a0bf 100644 --- a/PathTracer/src/Renderer.h +++ b/PathTracer/src/Renderer.h @@ -21,8 +21,23 @@ class Renderer { private: - glm::vec4 TraceRay(const Scene& scene, const Ray& ray); + + struct HitPayload { + float hitTValue; + glm::vec3 worldNormal; + glm::vec3 worldPos; + + uint32_t ObjectIndex; + }; + + HitPayload TraceRay(const Ray& ray); + HitPayload ClosestHit(const Ray& ray, float hitTVal, int objectIndex); + HitPayload Miss(const Ray& ray); + std::shared_ptr m_FinalImage; uint32_t* m_ImageData = nullptr; - + glm::vec4 RayGeneration(uint32_t x, uint32_t y); + + const Scene* activeScene = nullptr; + const Camera* activeCamera = nullptr; }; \ No newline at end of file diff --git a/PathTracer/src/Scene.h b/PathTracer/src/Scene.h index f7a9b10..05df564 100644 --- a/PathTracer/src/Scene.h +++ b/PathTracer/src/Scene.h @@ -8,11 +8,18 @@ struct Sphere { glm::vec3 position{ 0.0f }; glm::vec3 albedo{ 1.0f }; - float radius; + float radius = 0.1f; +}; + +struct Light { + glm::vec3 lightColor{ 1.0f }; + glm::vec3 lightDirection{ 1.0f }; + float intensity = 0.3f; }; struct Scene { std::vector spheres; + std::vector lights; }; \ No newline at end of file diff --git a/PathTracer/src/WalnutApp.cpp b/PathTracer/src/WalnutApp.cpp index 428f9d7..f04fc69 100644 --- a/PathTracer/src/WalnutApp.cpp +++ b/PathTracer/src/WalnutApp.cpp @@ -31,6 +31,21 @@ class ExampleLayer : public Walnut::Layer sphere.radius = 2.0f; scene.spheres.push_back(sphere); } + { + Light light; + light.lightColor = glm::vec3{ 1.0f }; + light.lightDirection = glm::vec3(-2.0f, -1.0f, -2.0f); + light.intensity = 0.3f; + scene.lights.push_back(light); + } + + { + Light light; + light.lightColor = glm::vec3{ 0.1f }; + light.lightDirection = glm::vec3(2.0f, -1.0f, -2.0f); + light.intensity = 0.3f; + scene.lights.push_back(light); + } } virtual void OnUIRender() override @@ -52,13 +67,20 @@ class ExampleLayer : public Walnut::Layer ImGui::Separator(); ImGui::PopID(); } + for (size_t j = 0; j < scene.lights.size(); j++) + { + ImGui::PushID((int)j +1000); + Light& light = scene.lights[j]; + ImGui::DragFloat3("Light Direction", glm::value_ptr(light.lightDirection), 0.1f); + ImGui::ColorEdit3("Light Color", glm::value_ptr(light.lightColor)); + ImGui::DragFloat("Light Intensity", &light.intensity, 0.1f); + ImGui::Separator(); + ImGui::PopID(); + } + ImGui::End(); - //static float color[3] = { (float)renderer.sphereColor.r, (float)renderer.sphereColor.g, (float)renderer.sphereColor.b }; - - /*ImGui::ColorPicker3("Sphere Color", color, 1); - ImGui::End();*/ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::Begin("ViewPort");