diff --git a/PathTracer/src/Renderer.cpp b/PathTracer/src/Renderer.cpp index 2a52917..885ef13 100644 --- a/PathTracer/src/Renderer.cpp +++ b/PathTracer/src/Renderer.cpp @@ -20,20 +20,23 @@ namespace Utilities { void Renderer::OnResize(uint32_t width, uint32_t height) { - if (m_FinalImage) { + if (finalImage) { // There was no need for any resizes - if (m_FinalImage -> GetHeight() == height && m_FinalImage -> GetWidth() == width) + if (finalImage -> GetHeight() == height && finalImage -> GetWidth() == width) return; - m_FinalImage->Resize(width, height); + finalImage->Resize(width, height); } else { - m_FinalImage = std::make_shared(width, height, Walnut::ImageFormat::RGBA); + finalImage = std::make_shared(width, height, Walnut::ImageFormat::RGBA); } delete[] m_ImageData; m_ImageData = new uint32_t[width * height]; + + delete[] accumulationData; + accumulationData = new glm::vec4[width * height]; } void Renderer::Render(const Scene& scene, const Camera& camera) { @@ -41,21 +44,31 @@ void Renderer::Render(const Scene& scene, const Camera& camera) { activeCamera = &camera; activeScene = &scene; const glm::vec3& rayOrigin = camera.GetPosition(); - - for (uint32_t y = 0; y < m_FinalImage->GetHeight(); y++) + if (frameIndex == 1) + memset(accumulationData, 0, finalImage->GetHeight() * finalImage->GetWidth() * sizeof(glm::vec4)); + + for (uint32_t y = 0; y < finalImage->GetHeight(); y++) { - for (uint32_t x = 0; x < m_FinalImage->GetWidth(); x++) { + for (uint32_t x = 0; x < finalImage->GetWidth(); x++) { + glm::vec4 color = RayGeneration(x, y); - color = glm::clamp(color, glm::vec4(0.0f), glm::vec4(1.0f)); + accumulationData[x + y * finalImage->GetWidth()] += color; + + glm::vec4 accumulatedColor = accumulationData[x + y * finalImage->GetWidth()]; + accumulatedColor /= (float)frameIndex; + accumulatedColor = glm::clamp(accumulatedColor, glm::vec4(0.0f), glm::vec4(1.0f)); - m_ImageData[x + m_FinalImage->GetWidth() * y] = Utilities::ConvertToRGBA(color); + m_ImageData[x + finalImage->GetWidth() * y] = Utilities::ConvertToRGBA(accumulatedColor); } } - m_FinalImage->SetData(m_ImageData); + finalImage->SetData(m_ImageData); + + if (settings.Accumulate) frameIndex++; + else frameIndex = 1; } @@ -63,7 +76,7 @@ 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()]; + ray.Direction = activeCamera->GetRayDirections()[x + y * finalImage->GetWidth()]; glm::vec3 finalColor(0.0f); diff --git a/PathTracer/src/Renderer.h b/PathTracer/src/Renderer.h index d69a0bf..2487dd6 100644 --- a/PathTracer/src/Renderer.h +++ b/PathTracer/src/Renderer.h @@ -11,14 +11,22 @@ class Renderer { public: + + struct Settings { + bool Accumulate = false; + }; Renderer() = default; void OnResize(uint32_t width, uint32_t height); void Render(const Scene& scene, const Camera& camera); - std::shared_ptr GetFinalImage() const { return m_FinalImage; } + std::shared_ptr GetFinalImage() const { return finalImage; } + + + void ResetFrameIndex() { frameIndex = 1; } + Settings& GetSettings() { return settings; } private: @@ -34,10 +42,16 @@ class Renderer { HitPayload ClosestHit(const Ray& ray, float hitTVal, int objectIndex); HitPayload Miss(const Ray& ray); - std::shared_ptr m_FinalImage; - uint32_t* m_ImageData = nullptr; + std::shared_ptr finalImage; glm::vec4 RayGeneration(uint32_t x, uint32_t y); const Scene* activeScene = nullptr; const Camera* activeCamera = nullptr; + + Settings settings; + + uint32_t* m_ImageData = nullptr; + glm::vec4* accumulationData = nullptr; + + uint32_t frameIndex = 1; }; \ No newline at end of file diff --git a/PathTracer/src/WalnutApp.cpp b/PathTracer/src/WalnutApp.cpp index fd8e6ca..dd1ff8e 100644 --- a/PathTracer/src/WalnutApp.cpp +++ b/PathTracer/src/WalnutApp.cpp @@ -63,6 +63,12 @@ class ExampleLayer : public Walnut::Layer if (ImGui::Button("Render")) { Render(); } + + ImGui::Checkbox("Accumulate", &renderer.GetSettings().Accumulate); + + if (ImGui::Button("Reset")) { + renderer.ResetFrameIndex(); + } ImGui::End(); ImGui::Begin("Scene"); for (int i = 0; i < scene.spheres.size(); i++) @@ -123,7 +129,9 @@ class ExampleLayer : public Walnut::Layer } virtual void OnUpdate(float timeStep) override{ - camera.OnUpdate(timeStep); + if (camera.OnUpdate(timeStep)) + renderer.ResetFrameIndex(); + } void Render() {