Threaded progressive renderer
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
#include "scene.hpp"
|
||||
|
||||
#include "ray.hpp"
|
||||
|
||||
Scene::Scene(int width, int height) {
|
||||
w = width;
|
||||
h = height;
|
||||
}
|
||||
|
||||
glm::vec3 Scene::SampleSky(Ray ray) {
|
||||
return { 0.617f, 0.980f, 1.000f };
|
||||
}
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
#ifndef INFERNO_DEFINITIONS_SCENE_H_
|
||||
#define INFERNO_DEFINITIONS_SCENE_H_
|
||||
|
||||
#include "../maths.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Camera;
|
||||
class Primative;
|
||||
class Camera;
|
||||
class Mesh;
|
||||
class Ray;
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Scene(int width, int height);
|
||||
int w, h;
|
||||
Camera* camera;
|
||||
float gamma;
|
||||
std::vector<Primative*> objects;
|
||||
std::vector<Mesh*> meshs;
|
||||
|
||||
glm::vec3 SampleSky(Ray ray);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -87,6 +87,13 @@ void Display::SetPixel(int x, int y, uint32_t p) {
|
||||
m_framebufferMutex.unlock();
|
||||
}
|
||||
|
||||
void Display::SetPixel(int x, int y, glm::vec3 p) {
|
||||
Pixel pixel{ (uint8_t)p.x, (uint8_t)p.y, (uint8_t)p.z };
|
||||
m_framebufferMutex.lock();
|
||||
Framebuffer[y * this->XRes + x] = pixel.rgb();
|
||||
m_framebufferMutex.unlock();
|
||||
}
|
||||
|
||||
void Display::SetPixelSafe(int x, int y, Pixel p) {
|
||||
if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) {
|
||||
m_framebufferMutex.lock();
|
||||
@@ -103,6 +110,15 @@ void Display::SetPixelSafe(int x, int y, uint32_t p) {
|
||||
}
|
||||
}
|
||||
|
||||
void Display::SetPixelSafe(int x, int y, glm::vec3 p) {
|
||||
if (x >= 0 && x < this->XRes && y >= 0 && this->YRes) {
|
||||
Pixel pixel{ (uint8_t)p.x, (uint8_t)p.y, (uint8_t)p.z };
|
||||
m_framebufferMutex.lock();
|
||||
Framebuffer[y * this->XRes + x] = pixel.rgb();
|
||||
m_framebufferMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void Display::SetFramebuffer(uint32_t* fb) {
|
||||
m_framebufferMutex.lock();
|
||||
Framebuffer = nullptr;
|
||||
@@ -151,13 +167,13 @@ void Display::UpdateTitle() {
|
||||
}
|
||||
|
||||
void Display::Close() {
|
||||
free(Framebuffer);
|
||||
Active = false;
|
||||
SDL_DestroyTexture(m_texture);
|
||||
SDL_DestroyTexture(m_imguiTexture);
|
||||
SDL_DestroyRenderer(m_renderer);
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_Quit();
|
||||
Active = false;
|
||||
free(Framebuffer);
|
||||
}
|
||||
|
||||
Display::~Display() {
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "displayinterface.hpp"
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "../maths.hpp"
|
||||
|
||||
class Pixel;
|
||||
|
||||
class Display : public DisplayInterface {
|
||||
@@ -18,8 +20,10 @@ public:
|
||||
|
||||
void SetPixel(int x, int y, Pixel p) override;
|
||||
void SetPixel(int x, int y, uint32_t p) override;
|
||||
void SetPixel(int x, int y, glm::vec3 p) override;
|
||||
void SetPixelSafe(int x, int y, Pixel p) override;
|
||||
void SetPixelSafe(int x, int y, uint32_t p) override;
|
||||
void SetPixelSafe(int x, int y, glm::vec3 p) override;
|
||||
void SetPixelSafe(int x, int y, uint32_t p) override;
|
||||
|
||||
void SetFramebuffer(uint32_t* fb) override;
|
||||
void ClearFramebuffer() override;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define INFERNO_DISPLAY_DISPLAYINTERFACE_H_
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "../maths.hpp"
|
||||
|
||||
class Pixel;
|
||||
|
||||
@@ -21,8 +22,10 @@ public:
|
||||
|
||||
virtual void SetPixel(int x, int y, Pixel p) = 0;
|
||||
virtual void SetPixel(int x, int y, uint32_t p) = 0;
|
||||
virtual void SetPixel(int x, int y, glm::vec3 p) = 0;
|
||||
virtual void SetPixelSafe(int x, int y, Pixel p) = 0;
|
||||
virtual void SetPixelSafe(int x, int y, uint32_t p) = 0;
|
||||
virtual void SetPixelSafe(int x, int y, glm::vec3 p) = 0;
|
||||
|
||||
virtual void SetFramebuffer(uint32_t* fb) = 0;
|
||||
virtual void ClearFramebuffer() = 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "progressiverenderer.hpp"
|
||||
|
||||
#include "renderengine.hpp"
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "../pixel.hpp"
|
||||
#include "../display/displayinterface.hpp"
|
||||
@@ -16,8 +18,10 @@ ProgressiveRenderer::ProgressiveRenderer() {
|
||||
}
|
||||
|
||||
void ProgressiveRenderer::Init(DisplayInterface* interface, Scene* scene) {
|
||||
m_engine = new RenderEngine();
|
||||
m_engine->SetScene(scene);
|
||||
m_interface = interface;
|
||||
m_scene = scene;
|
||||
m_scene = scene;
|
||||
}
|
||||
|
||||
void ProgressiveRenderer::Input() {
|
||||
@@ -31,69 +35,79 @@ void ProgressiveRenderer::Input() {
|
||||
ImGui::Begin("Debug");
|
||||
ImGui::Text("Hello, world %d", 123);
|
||||
if (ImGui::Button("Save")) {}
|
||||
char* buf = ""; float f;
|
||||
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void workerThread(ProgressiveRenderer* renderer, int idd, int xStart, int xRange) {
|
||||
while (!renderer->Ready) {
|
||||
std::chrono::milliseconds dura(10);
|
||||
std::this_thread::sleep_for(dura);
|
||||
}
|
||||
|
||||
while (renderer->Ready) {
|
||||
for (int x = xStart; x < xStart + xRange; x++)
|
||||
for (int y = 0; y < renderer->m_scene->h; y++) {
|
||||
Ray ray = renderer->m_scene->camera->CastRay(x, y);
|
||||
glm::vec3 col = renderer->m_engine->GetColour(ray, 0);
|
||||
renderer->m_interface->SetPixelSafe(x, y, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressiveRenderer::Render() {
|
||||
int frames = 0;
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Allocates threads with ranges to render
|
||||
for (int i = 0; i < m_workerMax; i++) {
|
||||
if (i == m_workerMax - 1) {
|
||||
m_workers.push_back(new std::thread(workerThread, this, i,
|
||||
(m_scene->w / m_workerMax) * i,
|
||||
-((m_scene->w / m_workerMax) * i - m_scene->w)
|
||||
));
|
||||
} else {
|
||||
m_workers.push_back(new std::thread(workerThread, this, i,
|
||||
(m_scene->w / m_workerMax) * i,
|
||||
(m_scene->w / m_workerMax) * (i + 1) - (m_scene->w / m_workerMax) * i
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
int lastTime = SDL_GetTicks();
|
||||
// Starts render loop
|
||||
while (m_interface->Active) {
|
||||
|
||||
|
||||
|
||||
Ready = true;
|
||||
|
||||
// TODO: Queue frame jobs properly
|
||||
|
||||
Input();
|
||||
|
||||
m_interface->Update();
|
||||
}
|
||||
|
||||
Ready = false;
|
||||
for (auto& thread : m_workers) {
|
||||
thread->join();
|
||||
}
|
||||
|
||||
while (m_interface->Active) {
|
||||
auto frameStartTime = std::chrono::high_resolution_clock::now();
|
||||
// auto frameStartTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
#pragma omp parallel for schedule(dynamic)
|
||||
for (int x = 0; x < m_scene->w; x++)
|
||||
for (int y = 0; y < m_scene->h; y++) {
|
||||
// auto endTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
Ray ray = m_scene->camera->CastRay(x, y);
|
||||
// frames++;
|
||||
// std::cout << "Frame: " << frames << std::endl;
|
||||
// std::cout << "Frame Time: " << std::chrono::duration_cast<std::chrono::seconds>(endTime - frameStartTime).count()
|
||||
// << ":" << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - frameStartTime).count() << "s" << std::endl;
|
||||
// std::cout << "Avg Frame Time: " << std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime).count() / frames
|
||||
// << ":" << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() / frames << "s"
|
||||
// << std::endl << std::endl;
|
||||
|
||||
float t;
|
||||
Primative* hit = nullptr;
|
||||
bool didhit = TraceRayScene(ray, m_scene, t, hit);
|
||||
if (!didhit) {
|
||||
m_interface->SetPixelSafe(x, y, 0x000000);
|
||||
continue;
|
||||
}
|
||||
|
||||
glm::vec3 hitPoint = ray.origin + ray.direction * t;
|
||||
|
||||
glm::vec3 normal = hit->SurfaceNormal(hitPoint);
|
||||
Pixel col((normal.x + 1.0f) * 127.5f, (normal.y + 1.0f) * 127.5f, (normal.z + 1.0f) * 127.5f);
|
||||
m_interface->SetPixelSafe(x, y, col.rgb());
|
||||
}
|
||||
|
||||
|
||||
auto endTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
frames++;
|
||||
std::cout << "Frame: " << frames << std::endl;
|
||||
std::cout << "Frame Time: " << std::chrono::duration_cast<std::chrono::seconds>(endTime - frameStartTime).count()
|
||||
<< ":" << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - frameStartTime).count() << "s" << std::endl;
|
||||
std::cout << "Avg Frame Time: " << std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime).count() / frames
|
||||
<< ":" << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() / frames << "s"
|
||||
<< std::endl << std::endl;
|
||||
|
||||
// Swap framebuffers
|
||||
m_interface->Update();
|
||||
m_interface->ClearFramebuffer();
|
||||
}
|
||||
// Swap framebuffers
|
||||
// m_interface->Update();
|
||||
// m_interface->ClearFramebuffer();
|
||||
}
|
||||
|
||||
void ProgressiveRenderer::RenderProgressive() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
#ifndef INFERNO_ENGINE_PROGRESSIVERENDERER_H_
|
||||
#define INFERNO_ENGINE_PROGRESSIVERENDERER_H_
|
||||
|
||||
#include "../maths.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
class DisplayInterface;
|
||||
class RenderEngine;
|
||||
class Scene;
|
||||
class Ray;
|
||||
|
||||
class ProgressiveRenderer {
|
||||
public:
|
||||
@@ -19,15 +24,23 @@ public:
|
||||
void Render();
|
||||
void RenderProgressive();
|
||||
|
||||
private:
|
||||
DisplayInterface* m_interface = nullptr;
|
||||
bool Ready = false;
|
||||
|
||||
bool MXAA = true;
|
||||
public:
|
||||
Scene* m_scene = nullptr;
|
||||
DisplayInterface* m_interface = nullptr;
|
||||
RenderEngine* m_engine = nullptr;
|
||||
|
||||
int m_workerMax = 16;
|
||||
int m_workerMax = 6;
|
||||
std::vector<std::thread*> m_workers;
|
||||
std::vector<bool> m_workerStatus;
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
|
||||
bool m_mxaa = true;
|
||||
char* buf = ""; float f = 0.0f;
|
||||
};
|
||||
|
||||
void workerThread(ProgressiveRenderer* renderer, int idd, int xStart, int xRange);
|
||||
|
||||
#endif
|
||||
|
||||
30
src/engine/renderengine.cpp
Normal file
30
src/engine/renderengine.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "renderengine.hpp"
|
||||
|
||||
#include "../pixel.hpp"
|
||||
|
||||
#include "../definitions/primatives/primative.hpp"
|
||||
#include "../definitions/scene.hpp"
|
||||
#include "../definitions/ray.hpp"
|
||||
|
||||
RenderEngine::RenderEngine() {
|
||||
|
||||
}
|
||||
|
||||
void RenderEngine::SetScene(Scene* scene) {
|
||||
m_scene = scene;
|
||||
}
|
||||
|
||||
glm::vec3 RenderEngine::GetColour(Ray ray, int depth) {
|
||||
|
||||
float t; Primative* hit = nullptr;
|
||||
bool didhit = TraceRayScene(ray, m_scene, t, hit);
|
||||
if (!didhit) {
|
||||
return m_scene->SampleSky(ray);
|
||||
}
|
||||
|
||||
glm::vec3 hitPoint = ray.origin + ray.direction * t;
|
||||
|
||||
glm::vec3 normal = hit->SurfaceNormal(hitPoint);
|
||||
|
||||
return { (normal.x + 1.0f) * 127.5f, (normal.y + 1.0f) * 127.5f, (normal.z + 1.0f) * 127.5f };
|
||||
}
|
||||
20
src/engine/renderengine.hpp
Normal file
20
src/engine/renderengine.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef INFERNO_ENGINE_RENDERENGINE_H_
|
||||
#define INFERNO_ENGINE_RENDERENGINE_H_
|
||||
|
||||
#include "../maths.hpp"
|
||||
|
||||
class Scene;
|
||||
class Ray;
|
||||
|
||||
class RenderEngine {
|
||||
public:
|
||||
RenderEngine();
|
||||
|
||||
void SetScene(Scene* scene);
|
||||
|
||||
glm::vec3 GetColour(Ray ray, int depth);
|
||||
private:
|
||||
Scene* m_scene = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
0
src/engine/tonemap.cpp
Normal file
0
src/engine/tonemap.cpp
Normal file
0
src/engine/tonemap.hpp
Normal file
0
src/engine/tonemap.hpp
Normal file
Reference in New Issue
Block a user