diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f868cd..6715f3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} CMakeModules/) cmake_policy(SET CMP0037 OLD) #set(CMAKE_BUILD_TYPE Debug) #set(CMAKE_CXX_FLAGS "-g") +set(CMAKE_CXX_FLAGS "-Ofast -mtune=native") set(executable output) set(SrcDIR ./src) diff --git a/src/display/display.cpp b/src/display/display.cpp index 6afb578..3735024 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -85,7 +85,7 @@ void Display::Update() { io.MouseDown[1] = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT); io.MouseWheel = static_cast(wheel); - SDL_UpdateTexture(m_texture, NULL, Framebuffer->Data, this->XRes * sizeof(uint32_t)); + SDL_UpdateTexture(m_texture, NULL, Framebuffer->RenderData, this->XRes * sizeof(uint32_t)); SDL_RenderCopy(m_renderer, m_texture, NULL, NULL); ImGui::Render(); @@ -95,7 +95,7 @@ void Display::Update() { } void Display::UpdatePartial() { - SDL_UpdateTexture(m_texture, NULL, Framebuffer->Data, this->XRes * sizeof(uint32_t)); + SDL_UpdateTexture(m_texture, NULL, Framebuffer->RenderData, this->XRes * sizeof(uint32_t)); SDL_RenderCopy(m_renderer, m_texture, NULL, NULL); SDL_RenderPresent(m_renderer); } diff --git a/src/display/framebuffer.cpp b/src/display/framebuffer.cpp index 3a2fd50..a144f0d 100644 --- a/src/display/framebuffer.cpp +++ b/src/display/framebuffer.cpp @@ -21,6 +21,10 @@ FrameBuffer::FrameBuffer(int xres, int yres) { RenderPostProcess = (glm::vec3*)malloc((xres * yres) * sizeof(glm::vec3)); memset((void*)RenderPostProcess, 0, (xres * yres) * sizeof(glm::vec3)); + + + m_swapBuffer = (glm::vec3*)malloc((XRes * YRes) * sizeof(glm::vec3)); + memset((void*)m_swapBuffer, 0, (XRes * YRes) * sizeof(glm::vec3)); } void FrameBuffer::SetPixelSafeNormal(int x, int y, glm::vec3 p) { @@ -35,7 +39,7 @@ void FrameBuffer::SetPixelSafeAlbedo(int x, int y, glm::vec3 p) { } } -void FrameBuffer::SetPixelSafe(int x, int y, glm::vec3 p, int mode = 0) { +void FrameBuffer::SetPixelSafe(int x, int y, glm::vec3 p, int mode) { if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) { if (m_lastActiveFrameBufferMode != mode) { ClearFramebuffer(); } m_lastActiveFrameBufferMode = mode; @@ -43,7 +47,7 @@ void FrameBuffer::SetPixelSafe(int x, int y, glm::vec3 p, int mode = 0) { } } -void FrameBuffer::AddPixelSafe(int x, int y, glm::vec3 p, int mode = 0) { +void FrameBuffer::AddPixelSafe(int x, int y, glm::vec3 p, int mode) { if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) { if (m_lastActiveFrameBufferMode != mode) { ClearFramebuffer(); } m_lastActiveFrameBufferMode = mode; @@ -51,35 +55,64 @@ void FrameBuffer::AddPixelSafe(int x, int y, glm::vec3 p, int mode = 0) { } } -void FrameBuffer::PostProcess(int& spp, ToneMapMode mode, RenderMode rendermode) { - if (rendermode == MODE_RENDER_NORMALS || rendermode == MODE_RENDER_PATH_LENGTH) { - spp = 0; - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) { - RenderPostProcess[y * w + x] = src[y * w + x]; - } - return; - } - - if (rendermode == MODE_RENDER_PATH_BOUNCES) { - spp++; - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) { - dst[y * w + x] = src[y * w + x] / (float)spp; - } - return; - } - - SPP++; - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) { - dst[y * w + x] = src[y * w + x] / (float)SPP; +void FrameBuffer::RenderPostProcessSafe(int x, int y, glm::vec3 p) { + if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) { + RenderPostProcess[y * this->XRes + x] = p; } } +uint32_t FrameBuffer::FinalProcess(glm::vec3 p) { + Pixel pixel { + (uint8_t)(pow(p.r, Gamma) * 255.0f), + (uint8_t)(pow(p.g, Gamma) * 255.0f), + (uint8_t)(pow(p.b, Gamma) * 255.0f) + }; + return pixel.rgb(); +} + +void FrameBuffer::RenderSetPixelSafe(int x, int y, uint32_t p) { + if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) { + RenderData[y * this->XRes + x] = p; + } +} + +void FrameBuffer::PostProcess(int& spp, ToneMapMode mode, RenderMode rendermode) { + +} + +void FrameBuffer::PostProcess(ToneMapMode mode) { + memset((void*)m_swapBuffer, 0, (XRes * YRes) * sizeof(glm::vec3)); + + if (mode == MODE_TONEMAP_BASIC) { + + float max = 0.0f; + + for (int x = 0; x < XRes; x++) + for (int y = 0; y < YRes; y++) { + if (RenderPostProcess[y * this->XRes + x].r > max) max = RenderPostProcess[y * this->XRes + x].r; + if (RenderPostProcess[y * this->XRes + x].g > max) max = RenderPostProcess[y * this->XRes + x].g; + if (RenderPostProcess[y * this->XRes + x].b > max) max = RenderPostProcess[y * this->XRes + x].b; + } + + for (int x = 0; x < XRes; x++) + for (int y = 0; y < YRes; y++) { + m_swapBuffer[y * this->XRes + x] = RenderPostProcess[y * this->XRes + x] / max; + } + + } else if (mode == MODE_TONEMAP_CLAMP) { + + for (int x = 0; x < XRes; x++) + for (int y = 0; y < YRes; y++) { + m_swapBuffer[y * this->XRes + x] = Clamp(RenderPostProcess[y * this->XRes + x], 1.0f, 0.0f); + } + + } +} + + void FrameBuffer::DumpToFile(std::string path) { // int stbi_write_png(char const* filename, int w, int h, int comp, const void* data, int stride_in_bytes); - // Red and Blue channels need to be swapped + // TODO: Red and Blue channels need to be swapped stbi_write_png(path.c_str(), this->XRes, this->YRes, sizeof(uint32_t), this->RenderData, sizeof(uint32_t) * this->XRes); } @@ -99,5 +132,6 @@ FrameBuffer::~FrameBuffer() { free(RenderTarget); free(RenderPostProcess); free(RenderData); + free(m_swapBuffer); } diff --git a/src/display/framebuffer.hpp b/src/display/framebuffer.hpp index 04d217d..679e6eb 100644 --- a/src/display/framebuffer.hpp +++ b/src/display/framebuffer.hpp @@ -29,6 +29,14 @@ public: // Add to the render target void AddPixelSafe(int x, int y, glm::vec3 p, int mode = 0); + // Set a pixel in the post processed framebuffer, ready to be corrected + // for display gamma and to be transposed over to the data buffer + void RenderPostProcessSafe(int x, int y, glm::vec3 p); + + // Finally, the pixel is ready to be rendered to the data buffer, + // this method adjusts for gamma and scales back to do the last set + uint32_t FinalProcess(glm::vec3 p); + // Sets a pixel on the RenderData framebuffer, ready for rendering // by the display or whatever mode the engine is in. the framebuffer // doesnt care. @@ -38,6 +46,11 @@ public: // the sample count for additive frames to average void PostProcess(int& spp, ToneMapMode mode = MODE_TONEMAP_CLAMP, RenderMode rendermode = MODE_RENDER_PATHTRACE); + // Just tonemap ONLY the postprocessed framebuffer + // memory usage warning, it will create the swap buffer + // if it doesnt exist already + void PostProcess(ToneMapMode mode = MODE_TONEMAP_CLAMP); + // Saves the RenderData to a file, data must first be processed // by the render engine / the engine manager based on mode void DumpToFile(std::string path); @@ -64,6 +77,8 @@ public: ~FrameBuffer(); private: + glm::vec3* m_swapBuffer; + int m_lastActiveFrameBufferMode; }; diff --git a/src/display/tonemapfb.cpp b/src/display/tonemapfb.cpp deleted file mode 100644 index 8088584..0000000 --- a/src/display/tonemapfb.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "tonemapfb.hpp" - -#include "framebuffer.hpp" - -#include "../pixel.hpp" - -ToneMapFrameBuffer::ToneMapFrameBuffer(int xres, int yres) { - XRes = xres; YRes = yres; - RenderTo = (glm::vec3*)malloc((xres * yres) * sizeof(glm::vec3)); - memset((void*)RenderTo, 0, (xres * yres) * sizeof(glm::vec3)); - ProcData = (glm::vec3*)malloc((xres * yres) * sizeof(glm::vec3)); - memset((void*)ProcData, 0, (xres * yres) * sizeof(glm::vec3)); -} - -void ToneMapFrameBuffer::SetPixel(int x, int y, glm::vec3 p) { - if (LastOp != OPERATION_SET) { ClearFramebuffer(); } - LastOp = OPERATION_SET; - RenderTo[y * this->XRes + x] = p; -} - -void ToneMapFrameBuffer::SetPixelSafe(int x, int y, glm::vec3 p) { - if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) { - if (LastOp != OPERATION_SET) { ClearFramebuffer(); } - LastOp = OPERATION_SET; - RenderTo[y * this->XRes + x] = p; - } -} - -void ToneMapFrameBuffer::AddPixelSafe(int x, int y, glm::vec3 p) { - if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) { - if (LastOp != OPERATION_ADD) { ClearFramebuffer(); } - LastOp = OPERATION_ADD; - RenderTo[y * this->XRes + x] += p; - } -} - -void ToneMapFrameBuffer::AddPixelSafeDepth(int x, int y, glm::vec3 p) { - if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) { - if (LastOp != OPERATION_ADD_DEPTH) { ClearFramebuffer(); } - LastOp = OPERATION_ADD_DEPTH; - RenderTo[y * this->XRes + x] += p; - } -} - - -void ToneMapFrameBuffer::SetFramebuffer(glm::vec3* fb) { - free(ProcData); - RenderTo = fb; -} - -void ToneMapFrameBuffer::ClearFramebuffer() { - memset((void*)RenderTo, 0, (XRes * YRes) * sizeof(glm::vec3)); -} - -void ToneMapFrameBuffer::ClampBasic(FrameBuffer* buffer) { - for (int x = 0; x < XRes; x++) - for (int y = 0; y < YRes; y++) { - buffer->SetPixelSafe(x, y, Clamp(ProcData[y * this->XRes + x], 1.0f, 0.0f)); - } -} - -void ToneMapFrameBuffer::MapBasic(FrameBuffer* buffer) { - float max = 0.0f; - - for (int x = 0; x < XRes; x++) - for (int y = 0; y < YRes; y++) { - if (ProcData[y * this->XRes + x].r > max) max = ProcData[y * this->XRes + x].r; - if (ProcData[y * this->XRes + x].g > max) max = ProcData[y * this->XRes + x].g; - if (ProcData[y * this->XRes + x].b > max) max = ProcData[y * this->XRes + x].b; - } - - for (int x = 0; x < XRes; x++) - for (int y = 0; y < YRes; y++) { - buffer->SetPixelSafe(x, y, ProcData[y * this->XRes + x] / max); - } -} - -ToneMapFrameBuffer::~ToneMapFrameBuffer() { - free(RenderTo); - free(ProcData); -} diff --git a/src/display/tonemapfb.hpp b/src/display/tonemapfb.hpp deleted file mode 100644 index da6f057..0000000 --- a/src/display/tonemapfb.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef INFERNO_ENGINE_TONEMAP_H_ -#define INFERNO_ENGINE_TONEMAP_H_ - -#include "../common.hpp" -#include "../maths.hpp" - -#include - -class FrameBuffer; -class Pixel; - -enum LastOperation { - OPERATION_SET, - OPERATION_ADD, - OPERATION_ADD_DEPTH, - OPERATION_NONE -}; - -class ToneMapFrameBuffer { -public: - ToneMapFrameBuffer(int xres, int yres); - - void SetPixel(int x, int y, glm::vec3 p); - void SetPixelSafe(int x, int y, glm::vec3 p); - void AddPixelSafe(int x, int y, glm::vec3 p); - void AddPixelSafeDepth(int x, int y, glm::vec3 p); - - void SetFramebuffer(glm::vec3* fb); - void ClearFramebuffer(); - - - void ClampBasic(FrameBuffer* buffer); - void MapBasic(FrameBuffer* buffer); - - - LastOperation LastOp = OPERATION_NONE; - glm::vec3* RenderTo; - glm::vec3* ProcData; - int XRes, YRes; - - ~ToneMapFrameBuffer(); -}; - -#endif diff --git a/src/engine/progressiverenderer.cpp b/src/engine/progressiverenderer.cpp index 4d82dec..79e9698 100644 --- a/src/engine/progressiverenderer.cpp +++ b/src/engine/progressiverenderer.cpp @@ -12,7 +12,6 @@ #include "../display/displayinterface.hpp" #include "../display/framebuffer.hpp" -#include "../display/tonemapfb.hpp" #include "../util/assetloader.hpp" #include "../util/threadpool.hpp" @@ -106,17 +105,11 @@ void ProgressiveRenderer::Render() { while (m_interface->Active) { if (m_threadPool->CheckAllJobs()) { m_engine->Mode = m_mode; - m_engine->PostProcess(m_threadPool->MappedThreadFrameBuffer->RenderTo, m_threadPool->MappedThreadFrameBuffer->ProcData, m_scene->w, m_scene->h); + m_engine->PostProcess(m_threadPool->ThreadFrameBuffer->RenderTarget, m_threadPool->ThreadFrameBuffer->RenderPostProcess, m_scene->w, m_scene->h); - if (m_engine->Mode != MODE_RENDER_NORMALS) { - if (m_toneMapModeSelected == 0) m_threadPool->MappedThreadFrameBuffer->ClampBasic(m_threadPool->ThreadFrameBuffer); - - if (m_toneMapModeSelected == 1) m_threadPool->MappedThreadFrameBuffer->MapBasic(m_threadPool->ThreadFrameBuffer); - } else { - m_threadPool->MappedThreadFrameBuffer->ClampBasic(m_threadPool->ThreadFrameBuffer); - } + m_threadPool->ThreadFrameBuffer->PostProcess((ToneMapMode)m_toneMapModeSelected); - m_threadPool->MergeBuffers(m_interface->Framebuffer->Data, m_scene->w, m_scene->h); + m_threadPool->MergeBuffers(m_interface->Framebuffer->RenderData, m_scene->w, m_scene->h); m_threadPool->RunJobsAgain(); frameEndTime = std::chrono::high_resolution_clock::now(); @@ -144,5 +137,5 @@ void ProgressiveRenderer::m_calculateTimes(std::chrono::high_resolution_clock::t AllFrameTimes.push_back(frameTime); if (FrameTimes.size() > 11) FrameTimes.erase(FrameTimes.begin()); - AverageFrameTime = std::accumulate(AllFrameTimes.begin(), AllFrameTimes.end(), 0.0) / AllFrameTimes.size(); + AverageFrameTime = std::accumulate(FrameTimes.begin(), FrameTimes.end(), 0.0) / FrameTimes.size(); } diff --git a/src/engine/renderengine.cpp b/src/engine/renderengine.cpp index 86b4fce..b644c1e 100644 --- a/src/engine/renderengine.cpp +++ b/src/engine/renderengine.cpp @@ -13,7 +13,6 @@ #include "../display/displayinterface.hpp" #include "../display/framebuffer.hpp" -#include "../display/tonemapfb.hpp" #include "../engine/renderengine.hpp" #include "../engine/progressiverenderer.hpp" @@ -26,7 +25,7 @@ static glm::vec3 Blue { 0.2f, 0.2f, 1.0f }; void workerThread(RenderThreadPool* threadpool, ProgressiveRenderer* renderer, int idd, int yStart, int yRange) { while (!renderer->Ready && !threadpool->Ready) { - std::chrono::milliseconds dura(10); + static std::chrono::milliseconds dura(10); std::this_thread::sleep_for(dura); } @@ -46,19 +45,19 @@ void workerThread(RenderThreadPool* threadpool, ProgressiveRenderer* renderer, i glm::vec3 col = renderer->m_engine->GetColour(ray, depth); if (renderer->m_engine->Mode == MODE_RENDER_NORMALS || renderer->m_engine->Mode == MODE_RENDER_PATH_LENGTH) { - threadpool->MappedThreadFrameBuffer->SetPixelSafe(x, y, col); + threadpool->ThreadFrameBuffer->SetPixelSafe(x, y, col); } else if (renderer->m_engine->Mode == MODE_RENDER_PATH_BOUNCES) { col.r = depth; col.g = depth / 3.0f; col.b = depth / 3.0f; - threadpool->MappedThreadFrameBuffer->AddPixelSafeDepth(x, y, col); + threadpool->ThreadFrameBuffer->AddPixelSafe(x, y, col, (int)renderer->m_engine->Mode); } else { - threadpool->MappedThreadFrameBuffer->AddPixelSafe(x, y, col); + threadpool->ThreadFrameBuffer->AddPixelSafe(x, y, col, (int)renderer->m_engine->Mode); } } threadpool->ThreadStatus[idd] = true; while (threadpool->ThreadStatus[idd]) { - std::chrono::nanoseconds dura(1); + static std::chrono::nanoseconds dura(1); std::this_thread::sleep_for(dura); } } diff --git a/src/util/threadpool.cpp b/src/util/threadpool.cpp index 15f4230..90fffc2 100644 --- a/src/util/threadpool.cpp +++ b/src/util/threadpool.cpp @@ -6,7 +6,6 @@ #include "../display/displayinterface.hpp" #include "../display/framebuffer.hpp" -#include "../display/tonemapfb.hpp" #include "../engine/renderengine.hpp" #include "../engine/progressiverenderer.hpp" @@ -63,7 +62,7 @@ void RenderThreadPool::RunJobsAgain() { } void RenderThreadPool::MergeBuffers(uint32_t* framebuffer, int w, int h) { - memcpy((void*)framebuffer, (void*)ThreadFrameBuffer->Data, (w * h) * sizeof(uint32_t)); + memcpy((void*)framebuffer, (void*)ThreadFrameBuffer->RenderData, (w * h) * sizeof(uint32_t)); } void RenderThreadPool::Destroy() { diff --git a/test/main.cpp b/test/main.cpp index 8922c50..2554272 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -11,6 +11,7 @@ int main(int argc, char** argv) { inferno.SetMode(MODE_OPERATION_PROGRESSIVE_GUI); bool status = inferno.InitWindow(width, height); + if (!status) { std::cout << "Error initializing window: " << inferno.LastError() << std::endl; } @@ -22,7 +23,7 @@ int main(int argc, char** argv) { scene->objects.push_back(new Sphere({ 35.0f, 26.0f, 25.0f }, 15.0f, new Material({ 1.0f, 1.0f, 1.0f }, 0.0f, 5.0f))); scene->objects.push_back(new Plane( { 0.0f, -1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, new Material({ 0.847f, 0.792f, 0.658f }, 0.2f))); - std::vector tris = LoadTrianglesBasic("E://Projects//Inferno//resources//dragon-normals.obj", "E://Projects//Inferno//resources"); + // std::vector tris = LoadTrianglesBasic("E://Projects//Inferno//resources//dragon-normals.obj", "E://Projects//Inferno//resources"); // std::vector tris = LoadTrianglesBasic("//home//ben//programming//inferno//resources//dragon-normals.obj", "//home//ben//programming//inferno//resources//resources"); //std::vector tris = LoadTrianglesBasic("E://Projects//Inferno//resources//lucy-normals-larger.obj", "E://Projects//Inferno//resources"); @@ -36,10 +37,10 @@ int main(int argc, char** argv) { //std::vector tris = LoadTrianglesBasic("E://Projects//Inferno//resources//box.obj", "E://Projects//Inferno//resources"); //std::vector tris = LoadTrianglesBasic("//home//ben//programming//inferno//resources//cornell.obj", "//home//ben//programming//inferno//resources//resources"); - Mesh* mesh1 = new Mesh(tris); - mesh1->Translate({ 0.2f, -1.04, -3.8f }); - mesh1->Optimise(); - scene->meshs.push_back(mesh1); + // Mesh* mesh1 = new Mesh(tris); + // mesh1->Translate({ 0.2f, -1.04, -3.8f }); + // mesh1->Optimise(); + // scene->meshs.push_back(mesh1); inferno.SetScene(scene);