Restored (partially) render progress
This commit is contained in:
parent
18a669675f
commit
14e0320848
4 changed files with 38 additions and 34 deletions
|
@ -116,11 +116,6 @@ DialogRender::~DialogRender()
|
|||
delete pixbuf_lock;
|
||||
}
|
||||
|
||||
void DialogRender::tellProgressChange(double value)
|
||||
{
|
||||
emit progressChanged(value);
|
||||
}
|
||||
|
||||
void DialogRender::tellRenderEnded()
|
||||
{
|
||||
emit renderEnded();
|
||||
|
@ -133,6 +128,8 @@ void DialogRender::startRender()
|
|||
_render_thread = new RenderThread(this, canvas_renderer);
|
||||
_render_thread->start();
|
||||
|
||||
startTimer(100);
|
||||
|
||||
exec();
|
||||
}
|
||||
|
||||
|
@ -179,14 +176,15 @@ void DialogRender::loadLastRender()
|
|||
exec();
|
||||
}
|
||||
|
||||
void DialogRender::applyProgress(double value)
|
||||
void DialogRender::timerEvent(QTimerEvent *)
|
||||
{
|
||||
double diff = difftime(time(NULL), _started);
|
||||
int hours = (int)floor(diff / 3600.0);
|
||||
int minutes = (int)floor((diff - 3600.0 * hours) / 60.0);
|
||||
int seconds = (int)floor(diff - 3600.0 * hours - 60.0 * minutes);
|
||||
_timer->setText(tr("%1:%2.%3").arg(hours).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')));
|
||||
_progress->setValue((int)(value * 1000.0));
|
||||
|
||||
_progress->setValue((int)(canvas_renderer->getProgress() * 1000.0));
|
||||
_progress->update();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,25 +18,24 @@ class DialogRender : public QDialog
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DialogRender(QWidget *parent, SoftwareCanvasRenderer* renderer);
|
||||
explicit DialogRender(QWidget *parent, SoftwareCanvasRenderer *renderer);
|
||||
~DialogRender();
|
||||
|
||||
void tellProgressChange(double value);
|
||||
void tellRenderEnded();
|
||||
void startRender();
|
||||
void loadLastRender();
|
||||
|
||||
virtual void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
QImage* pixbuf;
|
||||
QMutex* pixbuf_lock;
|
||||
|
||||
private slots:
|
||||
void applyProgress(double value);
|
||||
void saveRender();
|
||||
void applyRenderEnded();
|
||||
void toneMappingChanged();
|
||||
|
||||
signals:
|
||||
void progressChanged(double value);
|
||||
void renderEnded();
|
||||
|
||||
private:
|
||||
|
|
|
@ -17,6 +17,7 @@ SoftwareCanvasRenderer::SoftwareCanvasRenderer()
|
|||
started = false;
|
||||
interrupted = false;
|
||||
canvas = new Canvas();
|
||||
progress = 0.0;
|
||||
|
||||
rasterizers.push_back(new SkyRasterizer(this, 0));
|
||||
rasterizers.push_back(new WaterRasterizer(this, 1));
|
||||
|
@ -55,6 +56,7 @@ void SoftwareCanvasRenderer::setSize(int width, int height, int samples)
|
|||
void SoftwareCanvasRenderer::render()
|
||||
{
|
||||
started = true;
|
||||
progress = 0.0;
|
||||
|
||||
render_camera->setRenderSize(canvas->getWidth(), canvas->getHeight());
|
||||
|
||||
|
@ -63,6 +65,8 @@ void SoftwareCanvasRenderer::render()
|
|||
// Iterate portions
|
||||
int nx = canvas->getHorizontalPortionCount();
|
||||
int ny = canvas->getVerticalPortionCount();
|
||||
int i = 0;
|
||||
int n = nx * ny;
|
||||
for (int y = 0; y < ny; y++)
|
||||
{
|
||||
for (int x = 0; x < nx; x++)
|
||||
|
@ -71,16 +75,20 @@ void SoftwareCanvasRenderer::render()
|
|||
|
||||
if (not interrupted)
|
||||
{
|
||||
progress_segment = 0.2 / (double)n;
|
||||
portion->preparePixels();
|
||||
rasterize(portion, true);
|
||||
rasterize(portion);
|
||||
}
|
||||
|
||||
if (not interrupted)
|
||||
{
|
||||
applyPixelShader(portion, true);
|
||||
progress_segment = 0.8 / (double)n;
|
||||
applyPixelShader(portion);
|
||||
}
|
||||
|
||||
portion->discardPixels();
|
||||
i++;
|
||||
progress = (double)i / (double)n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,31 +101,27 @@ void SoftwareCanvasRenderer::interrupt()
|
|||
{
|
||||
current_work->interrupt();
|
||||
}
|
||||
for (auto &rasterizer:getRasterizers())
|
||||
for (auto &rasterizer:rasterizers)
|
||||
{
|
||||
rasterizer->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<Rasterizer *> &SoftwareCanvasRenderer::getRasterizers() const
|
||||
{
|
||||
return rasterizers;
|
||||
}
|
||||
|
||||
const Rasterizer &SoftwareCanvasRenderer::getRasterizer(int client_id) const
|
||||
{
|
||||
return *(getRasterizers()[client_id]);
|
||||
return *(rasterizers[client_id]);
|
||||
}
|
||||
|
||||
void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion, bool threaded)
|
||||
void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion)
|
||||
{
|
||||
for (auto &rasterizer:getRasterizers())
|
||||
for (auto &rasterizer:rasterizers)
|
||||
{
|
||||
rasterizer->rasterizeToCanvas(portion);
|
||||
progress += progress_segment / (double)rasterizers.size();
|
||||
}
|
||||
}
|
||||
|
||||
void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion, bool threaded)
|
||||
void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion)
|
||||
{
|
||||
// Subdivide in chunks
|
||||
int chunk_size = 64;
|
||||
|
@ -125,6 +129,13 @@ void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion, bool threa
|
|||
int chunks_y = (portion->getHeight() - 1) / chunk_size + 1;
|
||||
int units = chunks_x * chunks_y;
|
||||
|
||||
// Estimate chunks
|
||||
int n = 0;
|
||||
for (int sub_chunk_size = chunk_size; sub_chunk_size >= 1; sub_chunk_size /= 2)
|
||||
{
|
||||
n += chunk_size / sub_chunk_size;
|
||||
}
|
||||
|
||||
// Render chunks in parallel
|
||||
for (int sub_chunk_size = chunk_size; sub_chunk_size >= 1; sub_chunk_size /= 2)
|
||||
{
|
||||
|
@ -139,5 +150,6 @@ void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion, bool threa
|
|||
current_work = &work;
|
||||
work.perform();
|
||||
current_work = NULL;
|
||||
progress += progress_segment * (double)(chunk_size / sub_chunk_size) / (double)n;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public:
|
|||
virtual ~SoftwareCanvasRenderer();
|
||||
|
||||
inline const Canvas *getCanvas() const {return canvas;}
|
||||
inline double getProgress() const {return progress;}
|
||||
|
||||
/**
|
||||
* Set the renderer configuration.
|
||||
|
@ -46,11 +47,6 @@ public:
|
|||
*/
|
||||
void interrupt();
|
||||
|
||||
/**
|
||||
* @brief Get the list of objects that can be rasterized to polygons on a canvas.
|
||||
*/
|
||||
virtual const std::vector<Rasterizer*> &getRasterizers() const;
|
||||
|
||||
/**
|
||||
* Get a rasterizer by its client id.
|
||||
*/
|
||||
|
@ -59,19 +55,18 @@ public:
|
|||
protected:
|
||||
/**
|
||||
* @brief Rasterize the scenery into a canvas portion.
|
||||
*
|
||||
* If 'threaded' is true, the rasterization will take advantage of multiple CPU cores.
|
||||
*/
|
||||
void rasterize(CanvasPortion *portion, bool threaded=false);
|
||||
void rasterize(CanvasPortion *portion);
|
||||
|
||||
/**
|
||||
* @brief Apply pixel shader to fragments stored in the CanvasPortion.
|
||||
*
|
||||
* If 'threaded' is true, the shader will take advantage of multiple CPU cores.
|
||||
*/
|
||||
void applyPixelShader(CanvasPortion *portion, bool threaded=true);
|
||||
void applyPixelShader(CanvasPortion *portion);
|
||||
|
||||
private:
|
||||
double progress;
|
||||
double progress_segment;
|
||||
|
||||
Canvas *canvas;
|
||||
std::vector<Rasterizer*> rasterizers;
|
||||
bool started;
|
||||
|
|
Loading…
Reference in a new issue