diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/config.hpp | 22 | ||||
-rw-r--r-- | app/draw.cpp | 32 | ||||
-rw-r--r-- | app/draw.hpp | 30 | ||||
-rw-r--r-- | app/main.cpp | 48 | ||||
-rw-r--r-- | app/mainwindow.cpp | 50 | ||||
-rw-r--r-- | app/mainwindow.hpp | 34 | ||||
-rw-r--r-- | app/rendercoord.cpp | 220 | ||||
-rw-r--r-- | app/rendercoord.hpp | 93 |
8 files changed, 0 insertions, 529 deletions
diff --git a/app/config.hpp b/app/config.hpp deleted file mode 100644 index 6e9962c..0000000 --- a/app/config.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#include <render.hpp> - -class Config { - public: - unsigned m_width, m_height; - unsigned m_maxhops, m_samples; - - unsigned m_framerate, m_workers; -}; - -class RendererConf : public Renderer { - public: - RendererConf(const Scene &scn, Vec3d eye, Vec3d target, Config &conf) - : Renderer(scn, eye, target, conf.m_width, conf.m_height, conf.m_maxhops) { - - } -}; - -#endif diff --git a/app/draw.cpp b/app/draw.cpp deleted file mode 100644 index 88733ef..0000000 --- a/app/draw.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "draw.hpp" -#include <qnamespace.h> -#include <qpainter.h> -#include <qglobal.h> -#include <qimage.h> -#include <qrgb.h> -#include <qtimer.h> -#include <qwindowdefs.h> -#include <iostream> - -DrawWidget::DrawWidget(const Config &conf) : - QWidget(), m_conf(conf) { - m_drawbuffer = new QRgb[conf.m_width * conf.m_height]; - - m_img = QImage((uchar*)m_drawbuffer, conf.m_width, conf.m_height, QImage::Format_ARGB32); - -} - -void DrawWidget::paintEvent(QPaintEvent*) { - QPainter painter(this); - - auto scaled = m_img.scaled(width(), height(), Qt::KeepAspectRatio); - painter.drawImage(0, 0, scaled); -} - -void DrawWidget::redraw() { - repaint(); -} - -DrawWidget::~DrawWidget() { - delete[] m_drawbuffer; -} diff --git a/app/draw.hpp b/app/draw.hpp deleted file mode 100644 index 454558c..0000000 --- a/app/draw.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef DRAW_H -#define DRAW_H - -#include "config.hpp" -#include <qimage.h> -#include <qtimer.h> -#include <qwidget.h> - -class DrawWidget : public QWidget { - Q_OBJECT - - public: - DrawWidget(const Config &conf); - void paintEvent(QPaintEvent*); - - QRgb *m_drawbuffer; - QImage m_img; - unsigned m_width, m_height; - - ~DrawWidget(); - private slots: - void redraw(); - - private: - unsigned char i; - - const Config &m_conf; -}; - -#endif diff --git a/app/main.cpp b/app/main.cpp deleted file mode 100644 index e53b8ad..0000000 --- a/app/main.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include <iostream> -#include <qapplication.h> -#include <qpushbutton.h> - -#include "mainwindow.hpp" -#include "vector.hpp" -#include <scene.hpp> -#include <render.hpp> -#include <object.hpp> - -using namespace std; - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - Scene scn; - Config conf; - conf.m_width = 500; - conf.m_height = 500; - conf.m_maxhops = 5; - conf.m_samples = 100; - conf.m_framerate = 3; - conf.m_workers = 4; - - - Material blue(Color(0.3, 0.3, 1), 1); - Material red(Color(1, 0.3, 0.3), 1); - Material white(Color(1, 1, 1), 1); - Material em(Color(1, 1, 1), 0, 2); - - scn.addShape(new Sphere(red, Vec3d(2, 6, -1), 1)); - scn.addShape(new Sphere(white, Vec3d(0, 4, -1), 1.3)); - scn.addShape(new Sphere(white, Vec3d(-2, 5, -2), 1.3)); - scn.addShape(new Sphere(blue, Vec3d(0, 7, 0), 0.5)); - - scn.addShape(new Plane(em, Vec3d(0, 0, 0), Vec3d(0, 1, 0))); - scn.addShape(new Plane(white, Vec3d(0, 10, 0), Vec3d(0, 1, 0))); - scn.addShape(new Plane(white, Vec3d(0, 0, -5), Vec3d(0, 0, 1))); - scn.addShape(new Plane(red, Vec3d(-5, 0, 0), Vec3d(1, 0, 0))); - scn.addShape(new Plane(blue, Vec3d(5, 0, 0), Vec3d(1, 0, 0))); - - RendererConf render(scn, Vec3d(0, 5, 4), Vec3d(0, 5, 0), conf); - - MainWindow main(render, conf); - main.show(); - - return a.exec(); -} diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp deleted file mode 100644 index eed98f9..0000000 --- a/app/mainwindow.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "mainwindow.hpp" -#include <qaction.h> -#include <qapplication.h> -#include <qlabel.h> -#include <qnamespace.h> -#include <QFileDialog> -#include <QMessageBox> - -MainWindow::MainWindow(Renderer r, const Config &conf) - : m_drawer(conf), - runstatus("Not running", this), - m_render(this, m_drawer, r, conf, &runstatus), - m_conf(conf) -{ - - setCentralWidget(&m_drawer); - - auto saveAct = new QAction(tr("&Save as"), this); - saveAct->setStatusTip(tr("Save the rendered image")); - connect(saveAct, &QAction::triggered, this, &MainWindow::saveimage); - - auto stopAct = new QAction(tr("&Stop"), this); - stopAct->setStatusTip(tr("Stop and sync threads")); - QObject::connect(stopAct, &QAction::triggered, &m_render, &RenderCoordinator::stop); - - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(saveAct); - - fileMenu = menuBar()->addMenu(tr("&Render")); - fileMenu->addAction(stopAct); - - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(tr("About Qt"), qApp, &QApplication::aboutQt); - - statusBar()->addWidget(&runstatus); -} - -void MainWindow::saveimage() { - - QGuiApplication::setOverrideCursor(Qt::WaitCursor); - QString fileName = QFileDialog::getSaveFileName(this, - tr("Save image"), "", tr("PNG image (*.png);;All Files (*)")); - if (fileName.isEmpty()) { - return; - } - - if (!m_drawer.m_img.save(fileName)) { - QMessageBox::information(this, tr("Unable to save file"), ""); - } -} diff --git a/app/mainwindow.hpp b/app/mainwindow.hpp deleted file mode 100644 index ffb4f08..0000000 --- a/app/mainwindow.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H - -#include <QMainWindow> -#include <QLabel> -#include <QMenuBar> -#include <QStatusBar> - -#include "config.hpp" -#include "draw.hpp" -#include "rendercoord.hpp" -#include <qmainwindow.h> -#include <render.hpp> - -class MainWindow : public QMainWindow { - Q_OBJECT - - public: - MainWindow(Renderer r, const Config &conf); - - private slots: - void saveimage(); - private: - DrawWidget m_drawer; - QLabel runstatus; - RenderCoordinator m_render; - - QMenu *fileMenu; - QMenu *helpMenu; - - const Config &m_conf; -}; - -#endif diff --git a/app/rendercoord.cpp b/app/rendercoord.cpp deleted file mode 100644 index 00a6437..0000000 --- a/app/rendercoord.cpp +++ /dev/null @@ -1,220 +0,0 @@ -#include "rendercoord.hpp" -#include <algorithm> -#include <qobject.h> -#include <iostream> -#include <qrgb.h> - -#include <qsemaphore.h> -#include <render.hpp> -#include <sstream> - -uint32_t colorToUint32(const Color &c) { - Color cnew = Color(c); - cnew.clamp(); - return (0xFF << 24) + - (cnew.r() << 16) + - (cnew.g() << 8) + - cnew.b(); -} - -// Run by main thread -RenderThread::RenderThread(Renderer r, unsigned threads, const Config &conf, QObject *parent, unsigned id) - : QThread(parent), - m_lock(1), - m_render(r), - m_conf(conf), - m_pause(1) -{ - m_id = id; - m_workers = threads; -} - -// Run on new thread -void RenderThread::run() { - while (1) { - // Wait for work - m_work.acquire(); - - // Very expensive, but necesary to get live rendering - Color *sum = new Color[m_render.m_width * m_render.m_height]; - - m_current_samples = 0; - - for (int sample = 0; sample < m_samples; sample++) { - m_current_samples = sample; - // Probably not that smart - m_pause.acquire(); - m_pause.release(); - - for (unsigned y = m_id; y < m_render.m_height; y += m_workers) { - for (unsigned x = 0; x < m_render.m_width; x++) { - auto index = x + y * m_render.m_width; - sum[index] += m_render.render(m_render.m_width - x, m_render.m_height - y, 1); - - m_writebuffer[index] = colorToUint32(sum[index] / (sample+1)); - } - } - - } - - // Signal done - m_lock.release(); - emit done(m_id); - } -} - -void RenderThread::pause() { - m_pause.acquire(); -} - -void RenderThread::resume() { - m_pause.release(); -} - -int RenderThread::render(QRgb *buffer, unsigned samples) { - // Check if already running - if (!m_lock.tryAcquire()) { - return 1; - } - m_writebuffer = buffer; - m_samples = samples; - m_work.release(); - std::cout << samples << std::endl; - - return 0; -} - -unsigned RenderThread::stop() { - stopAt(m_current_samples); - return m_current_samples; -} - -void RenderThread::stopAt(int at) { - m_samples = at; -} - -// Running on main thread -unsigned RenderThread::current_samples() { - // No sync should not be a problem here. - return m_current_samples; -} - -RenderCoordinator::RenderCoordinator(QObject *parent, DrawWidget &target, Renderer r, const Config &conf, QLabel *status) - : QObject(parent), - m_target(target), - m_renderer(r), - m_timer(this), - m_conf(conf) -{ - m_status = status; - - // Create and start workers - for (unsigned i = 0; i < conf.m_workers; i++) { - auto thread = new RenderThread(m_renderer, conf.m_workers, conf, this, i); - - thread->start(); - QObject::connect(thread, &RenderThread::done, this, &RenderCoordinator::workerDone); - - m_workers.push_back(thread); - } - - render(); - -} - -void RenderCoordinator::render() { - m_started = 0; - for (auto thd : m_workers) { - thd->render(m_target.m_drawbuffer, m_conf.m_samples); - m_started++; - } - - m_state = running; - updateUi(); - - QObject::connect(&m_timer, &QTimer::timeout, this, &RenderCoordinator::updateUi); - - m_timer.start(1000.0 / m_conf.m_framerate); -} - -void RenderCoordinator::stop() { - unsigned max = 0; - for (auto thd : m_workers) { - thd->pause(); - - auto val = thd->current_samples(); - if (val>max) { - max = val; - } - } - - std::cout << max << std::endl; - - for (auto thd : m_workers) { - thd->stopAt(max+1); - thd->resume(); - } - - m_state = stopping; - updateUi(); -} - -void RenderCoordinator::workerDone(unsigned workerid) { - std::cout << "Worker " << workerid << " done!" << std::endl; - if (--m_started) { - return; - } - std::cout << "All done :-)" << std::endl; - - // All workers are done - m_state = stopped; - m_timer.stop(); - updateUi(); -} - -unsigned RenderCoordinator::calcStats(unsigned *max, unsigned *min, double *avg) { - unsigned count = 0; - unsigned sum = 0; - for (auto thd : m_workers) { - auto val = thd->current_samples(); - if (min && (val < *min || !count)) { - *min = val; - } - if (max && (val > *max || !count)) { - *max = val; - } - - sum += val; - count++; - } - - if (avg) { - *avg = (double)sum / count; - } - - return count; -} - - -void RenderCoordinator::updateUi() { - m_target.repaint(); - - if (!m_status) { - return; - } - - // Gather statictics from workers - unsigned max; - unsigned min; - double avg; - unsigned count = calcStats(&max, &min, &avg); - - std::ostringstream status; - status << states[m_state] << - " Threads: " << count << - " Max: " << max << " samples" << - " Min: " << min << " samples" << - " Avg: " << avg << " samples"; - - m_status->setText(QString::fromStdString(status.str())); -} diff --git a/app/rendercoord.hpp b/app/rendercoord.hpp deleted file mode 100644 index eea1b40..0000000 --- a/app/rendercoord.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef RENDER_THREAD_H -#define RENDER_THREAD_H - -#include "draw.hpp" -#include "config.hpp" -#include <atomic> -#include <qlabel.h> -#include <render.hpp> - -#include <qobject.h> -#include <qrgb.h> -#include <qthread.h> -#include <qsemaphore.h> -#include <vector> -// https://doc.qt.io/archives/qt-4.8/qt-threads-mandelbrot-example.html - -class RenderThread : public QThread { - Q_OBJECT - - public: - RenderThread(Renderer r, unsigned threads, const Config &cfg, QObject *parent = nullptr, unsigned id = 0); - - // Returns 0 if successful or 1 if busy - int render(QRgb *buffer, unsigned samples); - - void pause(); - void resume(); - - unsigned stop(); - void stopAt(int at); - - unsigned current_samples(); - - signals: - void done(unsigned workerid); - - protected: - void run(); - - QSemaphore m_lock; - - QRgb *m_writebuffer; - std::atomic_int m_samples; - std::atomic_int m_current_samples; - - Renderer m_render; - - unsigned m_workers; - - Config const m_conf; - - // Value in here means work is to be done - QSemaphore m_work; - QSemaphore m_pause; - unsigned m_id; -}; - -const std::string states[] = { "Stopped", "Running", "Stopping" }; -enum State { stopped, running, stopping }; - -class RenderCoordinator : public QObject { - Q_OBJECT - - public: - RenderCoordinator(QObject *parent, DrawWidget &target, Renderer r, const Config &conf, QLabel *status=nullptr); - void setSamples(unsigned samples); - void render(); - - public slots: - void workerDone(unsigned workerid); - void stop(); - - private slots: - void updateUi(); - - private: - unsigned calcStats(unsigned *max, unsigned *min, double *avg); - - DrawWidget &m_target; - - Renderer m_renderer; - std::vector<RenderThread*> m_workers; - unsigned m_started; - - QLabel *m_status; - QTimer m_timer; - - State m_state; - - const Config &m_conf; -}; - -#endif |