paysages: Refactored rendering to use a RenderArea.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@252 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-01-29 21:45:58 +00:00 committed by ThunderK
parent e5a64ebf9f
commit 878614e13c
29 changed files with 481 additions and 531 deletions

2
TODO
View file

@ -1,7 +1,7 @@
- Restore render interrupt and progress
- Clouds are lighted without filtering from ground (clouds lighted at night !) - Clouds are lighted without filtering from ground (clouds lighted at night !)
- Camera should respect ratio aspect of render area. - Camera should respect ratio aspect of render area.
- All noises should use the same entropy pool (saved separately), and avoid reallocs. - All noises should use the same entropy pool (saved separately), and avoid reallocs.
- Implement light multi-sampling (mainly for skydome). - Implement light multi-sampling (mainly for skydome).
- Remove all global variables (render_quality, render_width...), it should all be set in Renderer.
- Implement scaling and scrolling on previews. - Implement scaling and scrolling on previews.
- Water and terrain LOD moves with the camera, fix it like in the wanderer. - Water and terrain LOD moves with the camera, fix it like in the wanderer.

View file

@ -3,16 +3,17 @@
#include <string.h> #include <string.h>
#include "../lib_paysages/auto.h" #include "../lib_paysages/auto.h"
#include "../lib_paysages/main.h"
#include "../lib_paysages/render.h" #include "../lib_paysages/render.h"
#include "../lib_paysages/scenery.h" #include "../lib_paysages/scenery.h"
void startRender(Renderer* renderer, char* outputpath) void startRender(Renderer* renderer, char* outputpath, int width, int height, int quality)
{ {
printf("\rRendering %s ... \n", outputpath); printf("\rRendering %s ... \n", outputpath);
autoRenderSceneTwoPass(renderer, 0); rendererStart(renderer, width, height, quality);
printf("\rSaving %s ... \n", outputpath); printf("\rSaving %s ... \n", outputpath);
remove(outputpath); remove(outputpath);
renderSaveToFile(outputpath); renderSaveToFile(renderer->render_area, outputpath);
} }
void displayHelp() void displayHelp()
@ -97,20 +98,21 @@ int main(int argc, char** argv)
printf("Initializing ...\n"); printf("Initializing ...\n");
paysagesInit(); paysagesInit();
renderer = sceneryGetStandardRenderer(conf_render_quality); renderer = sceneryCreateStandardRenderer();
renderSetSize(conf_render_width, conf_render_height); rendererSetPreviewCallbacks(&renderer, NULL, NULL, _previewUpdate);
renderSetPreviewCallbacks(NULL, NULL, NULL, _previewUpdate);
for (outputcount = 0; outputcount < conf_nb_pictures; outputcount++) for (outputcount = 0; outputcount < conf_nb_pictures; outputcount++)
{ {
autoSetDaytimeFraction(conf_daytime_start); autoSetDaytimeFraction(conf_daytime_start);
sprintf(outputpath, "output/pic%05d.png", outputcount); sprintf(outputpath, "output/pic%05d.png", outputcount);
startRender(&renderer, outputpath); startRender(&renderer, outputpath, conf_render_width, conf_render_height, conf_render_quality);
conf_daytime_start += conf_daytime_step; conf_daytime_start += conf_daytime_step;
} }
rendererDelete(&renderer);
printf("\rDone. \n"); printf("\rDone. \n");
return 0; return 0;

View file

@ -4,46 +4,21 @@
#include <QImage> #include <QImage>
#include <QColor> #include <QColor>
#include <QPainter> #include <QPainter>
#include "tools.h"
#include "../lib_paysages/render.h"
#include "../lib_paysages/scenery.h" #include "../lib_paysages/scenery.h"
#include "../lib_paysages/auto.h" #include "../lib_paysages/auto.h"
class RenderThread:public QThread
{
public:
RenderThread(Renderer* renderer):QThread()
{
_renderer = renderer;
}
void run()
{
autoRenderSceneTwoPass(_renderer, 0);
}
private:
Renderer* _renderer;
};
static DialogRender* _current_dialog; static DialogRender* _current_dialog;
static void _renderResize(int width, int height) static void _renderStart(int width, int height, Color background)
{ {
delete _current_dialog->pixbuf; _current_dialog->pixbuf->fill(colorToQColor(background).rgb());
_current_dialog->pixbuf = new QImage(width, height, QImage::Format_ARGB32);
_current_dialog->area->setMinimumSize(width, height);
_current_dialog->area->setMaximumSize(width, height);
_current_dialog->area->resize(width, height);
_current_dialog->scroll->setMinimumSize(width > 800 ? 850 : width + 50, height > 600 ? 650 : height + 50);
}
static void _renderClear(Color col)
{
_current_dialog->pixbuf->fill(QColor(col.r * 255.0, col.g * 255.0, col.b * 255.0).rgb());
} }
static void _renderDraw(int x, int y, Color col) static void _renderDraw(int x, int y, Color col)
{ {
_current_dialog->pixbuf->setPixel(x, _current_dialog->pixbuf->height() - 1 - y, QColor(col.r * 255.0, col.g * 255.0, col.b * 255.0).rgb()); _current_dialog->pixbuf->setPixel(x, _current_dialog->pixbuf->height() - 1 - y, colorToQColor(col).rgb());
} }
static void _renderUpdate(double progress) static void _renderUpdate(double progress)
@ -52,6 +27,27 @@ static void _renderUpdate(double progress)
_current_dialog->progress_value = progress * 1000.0; _current_dialog->progress_value = progress * 1000.0;
} }
class RenderThread:public QThread
{
public:
RenderThread(Renderer* renderer, int width, int height, int quality):QThread()
{
_renderer = renderer;
_width = width;
_height = height;
_quality = quality;
}
void run()
{
rendererStart(_renderer, _width, _height, _quality);
}
private:
Renderer* _renderer;
int _width;
int _height;
int _quality;
};
class RenderArea:public QWidget class RenderArea:public QWidget
{ {
public: public:
@ -76,6 +72,7 @@ DialogRender::DialogRender(QWidget *parent):
pixbuf = new QImage(1, 1, QImage::Format_ARGB32); pixbuf = new QImage(1, 1, QImage::Format_ARGB32);
_current_dialog = this; _current_dialog = this;
render_thread = NULL; render_thread = NULL;
renderer = sceneryCreateStandardRenderer();
setModal(true); setModal(true);
setWindowTitle("Paysages 3D - Render"); setWindowTitle("Paysages 3D - Render");
@ -99,23 +96,29 @@ DialogRender::~DialogRender()
{ {
if (render_thread) if (render_thread)
{ {
renderInterrupt(); rendererInterrupt(&renderer);
render_thread->wait(); render_thread->wait();
renderSetPreviewCallbacks(NULL, NULL, NULL, NULL); rendererSetPreviewCallbacks(&renderer, NULL, NULL, NULL);
delete render_thread; delete render_thread;
} }
rendererDelete(&renderer);
delete pixbuf; delete pixbuf;
} }
void DialogRender::startRender(int quality, int width, int height) void DialogRender::startRender(int quality, int width, int height)
{ {
renderer = sceneryGetStandardRenderer(quality); delete pixbuf;
renderSetSize(width, height); pixbuf = new QImage(width, height, QImage::Format_ARGB32);
renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate); area->setMinimumSize(width, height);
area->setMaximumSize(width, height);
area->resize(width, height);
scroll->setMinimumSize(width > 800 ? 850 : width + 50, height > 600 ? 650 : height + 50);
render_thread = new RenderThread(&renderer); rendererSetPreviewCallbacks(&renderer, _renderStart, _renderDraw, _renderUpdate);
render_thread = new RenderThread(&renderer, width, height, quality);
render_thread->start(); render_thread->start();
exec(); exec();
@ -124,7 +127,7 @@ void DialogRender::startRender(int quality, int width, int height)
void DialogRender::loadLastRender() void DialogRender::loadLastRender()
{ {
progress->hide(); progress->hide();
renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate); //renderSetPreviewCallbacks(_renderStart, _renderDraw, _renderUpdate);
exec(); exec();
} }

View file

@ -74,7 +74,7 @@ void FormRender::saveRender()
filepath = QFileDialog::getSaveFileName(this, "Choose a filename to save the last render"); filepath = QFileDialog::getSaveFileName(this, "Choose a filename to save the last render");
if (!filepath.isNull()) if (!filepath.isNull())
{ {
renderSaveToFile((char*)filepath.toStdString().c_str()); //renderSaveToFile((char*)filepath.toStdString().c_str());
QMessageBox::information(this, "Message", "The picture " + filepath + " has been saved."); QMessageBox::information(this, "Message", "The picture " + filepath + " has been saved.");
} }
} }

View file

@ -20,7 +20,7 @@ public:
PreviewEast(QWidget* parent): PreviewEast(QWidget* parent):
Preview(parent) Preview(parent)
{ {
_renderer = rendererGetFake(); _renderer = rendererCreate();
_preview_definition = skyCreateDefinition(); _preview_definition = skyCreateDefinition();
} }
protected: protected:
@ -50,7 +50,7 @@ public:
PreviewWest(QWidget* parent): PreviewWest(QWidget* parent):
Preview(parent) Preview(parent)
{ {
_renderer = rendererGetFake(); _renderer = rendererCreate();
_preview_definition = skyCreateDefinition(); _preview_definition = skyCreateDefinition();
} }
protected: protected:

View file

@ -40,7 +40,7 @@ class PreviewTerrainColor:public Preview
public: public:
PreviewTerrainColor(QWidget* parent):Preview(parent) PreviewTerrainColor(QWidget* parent):Preview(parent)
{ {
_renderer = rendererGetFake(); _renderer = rendererCreate();
_renderer.applyTextures = _applyTextures; _renderer.applyTextures = _applyTextures;
_renderer.getTerrainHeight = _getTerrainHeight; _renderer.getTerrainHeight = _getTerrainHeight;
/*_renderer.applyLightingToSurface = _applyLightingToSurface;*/ /*_renderer.applyLightingToSurface = _applyLightingToSurface;*/

View file

@ -72,7 +72,7 @@ public:
lightingAddLight(&_lighting, light); lightingAddLight(&_lighting, light);
lightingValidateDefinition(&_lighting); lightingValidateDefinition(&_lighting);
_renderer = rendererGetFake(); _renderer = rendererCreate();
_renderer.rayWalking = _rayWalking; _renderer.rayWalking = _rayWalking;
_renderer.applyLightingToSurface = _applyLightingToSurface; _renderer.applyLightingToSurface = _applyLightingToSurface;
_renderer.customData[0] = &_water; _renderer.customData[0] = &_water;

View file

@ -6,7 +6,6 @@
#include "shared/types.h" #include "shared/types.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.h"
#include "clouds.h" #include "clouds.h"
#include "color.h" #include "color.h"
#include "lighting.h" #include "lighting.h"
@ -20,8 +19,6 @@
#include "water.h" #include "water.h"
#include "zone.h" #include "zone.h"
static int _is_rendering = 0;
void autoSetDaytime(int hour, int minute) void autoSetDaytime(int hour, int minute)
{ {
autoSetDaytimeFraction((double)hour / 24.0 + (double)minute / 1440.0); autoSetDaytimeFraction((double)hour / 24.0 + (double)minute / 1440.0);
@ -231,66 +228,3 @@ void autoGenRealisticLandscape(int seed)
scenerySetAtmosphere(&atmosphere); scenerySetAtmosphere(&atmosphere);
atmosphereDeleteDefinition(&atmosphere); atmosphereDeleteDefinition(&atmosphere);
} }
void* _renderFirstPass(void* data)
{
sceneryRenderFirstPass((Renderer*)data);
_is_rendering = 0;
return NULL;
}
void autoRenderSceneTwoPass(Renderer* renderer, int postonly)
{
Thread* thread;
int loops;
if (!postonly)
{
renderClear();
_is_rendering = 1;
thread = threadCreate(_renderFirstPass, renderer);
loops = 0;
while (_is_rendering)
{
timeSleepMs(100);
if (++loops >= 10)
{
renderUpdate();
loops = 0;
}
}
threadJoin(thread);
}
sceneryRenderSecondPass(renderer);
}
static int _postProcessRayTracingOverlay(RenderFragment* fragment)
{
Vector3 terrain_hit, look;
// TODO
/*look = v3Sub(fragment->vertex.location, camera_location);
if (!terrainProjectRay(camera_location, look, &terrain_hit, &fragment->vertex.color))
{
fragment->vertex.color = skyProjectRay(camera_location, look);
}*/
return 1;
}
void autoRenderSceneRayTracing()
{
// TODO
/*renderClear();
cameraPushOverlay(COLOR_RED, _postProcessRayTracingOverlay);
renderUpdate();
if (renderSetNextProgressStep(0.0, 1.0))
{
renderPostProcess(_cpu_count);
}*/
}

View file

@ -10,8 +10,6 @@ extern "C" {
void autoSetDaytime(int hour, int minute); void autoSetDaytime(int hour, int minute);
void autoSetDaytimeFraction(double daytime); void autoSetDaytimeFraction(double daytime);
void autoGenRealisticLandscape(int seed); void autoGenRealisticLandscape(int seed);
void autoRenderSceneTwoPass(Renderer* renderer, int postonly);
void autoRenderSceneRayTracing();
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -5,7 +5,6 @@
#include "euclid.h" #include "euclid.h"
#include "render.h" #include "render.h"
#include "shared/types.h" #include "shared/types.h"
#include "shared/globals.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "scenery.h" #include "scenery.h"
#include "tools.h" #include "tools.h"
@ -211,25 +210,25 @@ void cameraRotateRoll(CameraDefinition* camera, double value)
cameraValidateDefinition(camera, 0); cameraValidateDefinition(camera, 0);
} }
Vector3 cameraProject(CameraDefinition* camera, Vector3 point) Vector3 cameraProject(CameraDefinition* camera, Renderer* renderer, Vector3 point)
{ {
point = m4Transform(camera->project, point); point = m4Transform(camera->project, point);
point.x = (point.x + 1.0) * 0.5 * (double)render_width; point.x = (point.x + 1.0) * 0.5 * (double)renderer->render_width;
point.y = (-point.y + 1.0) * 0.5 * (double)render_height; point.y = (-point.y + 1.0) * 0.5 * (double)renderer->render_height;
return point; return point;
} }
Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point) Vector3 cameraUnproject(CameraDefinition* camera, Renderer* renderer, Vector3 point)
{ {
point.x = (point.x / (0.5 * (double)render_width) - 1.0); point.x = (point.x / (0.5 * (double)renderer->render_width) - 1.0);
point.y = -(point.y / (0.5 * (double)render_height) - 1.0); point.y = -(point.y / (0.5 * (double)renderer->render_height) - 1.0);
return m4Transform(camera->unproject, point); return m4Transform(camera->unproject, point);
} }
void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result) void cameraProjectToFragment(CameraDefinition* camera, Renderer* renderer, double x, double y, double z, RenderFragment* result)
{ {
Vector3 point = {x, y, z}; Vector3 point = {x, y, z};
point = cameraProject(camera, point); point = cameraProject(camera, renderer, point);
result->x = lround(point.x); result->x = lround(point.x);
result->y = lround(point.y); result->y = lround(point.y);
result->z = point.z; result->z = point.z;
@ -242,9 +241,9 @@ void cameraProjectToFragment(CameraDefinition* camera, double x, double y, doubl
* @param col Color of the polygon. * @param col Color of the polygon.
* @param callback Post-processing callback. * @param callback Post-processing callback.
*/ */
void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback) /*void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback)
{ {
/*Vertex v1, v2, v3, v4; Vertex v1, v2, v3, v4;
Vector3 v; Vector3 v;
v.x = 0.0; v.x = 0.0;
@ -275,5 +274,5 @@ void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCall
v4.color = col; v4.color = col;
v4.callback = callback; v4.callback = callback;
renderPushQuad(&v1, &v2, &v3, &v4);*/ renderPushQuad(&v1, &v2, &v3, &v4);
} }*/

View file

@ -1,8 +1,9 @@
#ifndef _PAYSAGES_CAMERA_H_ #ifndef _PAYSAGES_CAMERA_H_
#define _PAYSAGES_CAMERA_H_ #define _PAYSAGES_CAMERA_H_
#include "shared/types.h"
#include <stdio.h> #include <stdio.h>
#include "shared/types.h"
#include "renderer.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -48,10 +49,10 @@ void cameraRotateYaw(CameraDefinition* camera, double value);
void cameraRotatePitch(CameraDefinition* camera, double value); void cameraRotatePitch(CameraDefinition* camera, double value);
void cameraRotateRoll(CameraDefinition* camera, double value); void cameraRotateRoll(CameraDefinition* camera, double value);
Vector3 cameraProject(CameraDefinition* camera, Vector3 point); Vector3 cameraProject(CameraDefinition* camera, Renderer* renderer, Vector3 point);
Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point); Vector3 cameraUnproject(CameraDefinition* camera, Renderer* renderer, Vector3 point);
void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result); void cameraProjectToFragment(CameraDefinition* camera, Renderer* renderer, double x, double y, double z, RenderFragment* result);
void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback); /*void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback);*/
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -8,7 +8,6 @@
#include "tools.h" #include "tools.h"
#include "shared/types.h" #include "shared/types.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.h"
typedef struct typedef struct
{ {

View file

@ -7,7 +7,6 @@
#include "shared/types.h" #include "shared/types.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.h"
#include "color.h" #include "color.h"
#include "euclid.h" #include "euclid.h"
#include "renderer.h" #include "renderer.h"

View file

@ -6,7 +6,6 @@
#include "shared/types.h" #include "shared/types.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.h"
#include "auto.h" #include "auto.h"
#include "system.h" #include "system.h"

View file

@ -11,164 +11,145 @@
#include "color.h" #include "color.h"
#include "system.h" #include "system.h"
int render_width; struct RenderArea
int render_height; {
int render_quality; int width;
static int _pixel_count; int height;
static Array* render_zone = NULL; int pixel_count;
static RenderFragment* scanline_up; Array* pixels;
static RenderFragment* scanline_down; RenderFragment* scanline_up;
static int scanline_left; RenderFragment* scanline_down;
static int scanline_right; int scanline_left;
static Color background_color; int scanline_right;
static volatile int _dirty_left; Color background_color;
static volatile int _dirty_right; volatile int dirty_left;
static volatile int _dirty_up; volatile int dirty_right;
static volatile int _dirty_down; volatile int dirty_up;
static volatile int _dirty_count; volatile int dirty_down;
static Mutex* _lock; volatile int dirty_count;
Mutex* lock;
static volatile int _interrupt = 0; RenderCallbackStart callback_start;
static volatile int _progress_pixels; RenderCallbackDraw callback_draw;
static volatile double _progress = 0.0; RenderCallbackUpdate callback_update;
static volatile double _progress_step_start = 0.0; };
static volatile double _progress_step_length = 1.0;
/*#define RENDER_INVERSE 1*/ /*#define RENDER_INVERSE 1*/
#define RENDER_WIREFRAME 1 #define RENDER_WIREFRAME 1
static void _previewResize(int width, int height) {} static void _callbackStart(int width, int height, Color background) {}
static void _previewClear(Color col) {} static void _callbackDraw(int x, int y, Color col) {}
static void _previewDraw(int x, int y, Color col) {} static void _callbackUpdate(double progress) {}
static void _previewUpdate(double progress) {}
static PreviewCallbackResize _cb_preview_resize = _previewResize;
static PreviewCallbackClear _cb_preview_clear = _previewClear;
static PreviewCallbackDraw _cb_preview_draw = _previewDraw;
static PreviewCallbackUpdate _cb_preview_update = _previewUpdate;
void renderSave(FILE* f)
{
}
void renderLoad(FILE* f)
{
}
void renderInit() void renderInit()
{ {
_lock = mutexCreate();
renderSetBackgroundColor(&COLOR_BLACK);
} }
void renderSetSize(int width, int height) RenderArea* renderCreateArea()
{
RenderArea* result;
result = malloc(sizeof(RenderArea));
result->width = 1;
result->height = 1;
result->pixel_count = 1;
result->pixels = malloc(sizeof(Array));
arrayCreate(result->pixels, sizeof(RenderFragment));
result->scanline_up = malloc(sizeof(RenderFragment));
result->scanline_down = malloc(sizeof(RenderFragment));
result->scanline_left = 0;
result->scanline_right = 0;
result->background_color = COLOR_TRANSPARENT;
result->dirty_left = 1;
result->dirty_right = -1;
result->dirty_down = 1;
result->dirty_up = -1;
result->dirty_count = 0;
result->lock = mutexCreate();
result->callback_start = _callbackStart;
result->callback_draw = _callbackDraw;
result->callback_update = _callbackUpdate;
return result;
}
void renderDeleteArea(RenderArea* area)
{
mutexDestroy(area->lock);
arrayDelete(area->pixels);
free(area->scanline_up);
free(area->scanline_down);
free(area);
}
void renderSetSize(RenderArea* area, int width, int height)
{ {
int x; int x;
int y; int y;
if (render_zone != NULL) for (x = 0; x < area->width; x++)
{ {
/* Delete previous render zone */ for (y = 0; y < area->height; y++)
for (x = 0; x < render_width; x++)
{ {
for (y = 0; y < render_height; y++) arrayDelete(area->pixels + (y * area->width + x));
{
arrayDelete(render_zone + (y * render_width + x));
}
} }
free(render_zone);
free(scanline_up);
free(scanline_down);
} }
render_width = width; area->width = width;
render_height = height; area->height = height;
render_zone = malloc(sizeof(Array) * width * height); area->pixels = realloc(area->pixels, sizeof(Array) * width * height);
area->pixel_count = width * height;
scanline_left = 0; area->scanline_left = 0;
scanline_right = render_width - 1; area->scanline_right = width - 1;
scanline_up = malloc(sizeof(RenderFragment) * width); area->scanline_up = realloc(area->scanline_up, sizeof(RenderFragment) * width);
scanline_down = malloc(sizeof(RenderFragment) * width); area->scanline_down = realloc(area->scanline_down, sizeof(RenderFragment) * width);
_dirty_left = render_width; area->dirty_left = width;
_dirty_right = -1; area->dirty_right = -1;
_dirty_down = render_height; area->dirty_down = height;
_dirty_up = -1; area->dirty_up = -1;
_dirty_count = 0; area->dirty_count = 0;
_pixel_count = render_width * render_height;
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
for (x = 0; x < width; x++) for (x = 0; x < width; x++)
{ {
arrayCreate(render_zone + (y * width + x), sizeof(RenderFragment)); arrayCreate(area->pixels + (y * width + x), sizeof(RenderFragment));
} }
} }
_cb_preview_resize(render_width, render_height);
_cb_preview_clear(background_color);
} }
int renderSetQuality(int quality) void renderSetBackgroundColor(RenderArea* area, Color* col)
{ {
if (quality < 1) area->background_color = *col;
{
render_quality = 1;
}
else if (quality > 10)
{
render_quality = 10;
}
else
{
render_quality = quality;
}
return render_quality;
} }
void renderClear() void renderClear(RenderArea* area)
{ {
int x; int x;
int y; int y;
for (x = 0; x < render_width; x++) for (x = 0; x < area->width; x++)
{ {
for (y = 0; y < render_height; y++) for (y = 0; y < area->height; y++)
{ {
arrayClear(render_zone + (y * render_width + x)); arrayClear(area->pixels + (y * area->width + x));
} }
} }
scanline_left = 0; area->scanline_left = 0;
scanline_right = render_width - 1; area->scanline_right = area->width - 1;
_progress = 0.0; area->callback_start(area->width, area->height, area->background_color);
_progress_step_start = 0.0;
_progress_step_length = 0.0;
_interrupt = 0;
_cb_preview_clear(background_color); area->dirty_left = area->width;
_cb_preview_update(_progress * _progress_step_length + _progress_step_start); area->dirty_right = -1;
area->dirty_down = area->height;
_dirty_left = render_width; area->dirty_up = -1;
_dirty_right = -1; area->dirty_count = 0;
_dirty_down = render_height;
_dirty_up = -1;
_dirty_count = 0;
} }
void renderInterrupt() /*static int _sortRenderFragment(void const* a, void const* b)
{
_interrupt = 1;
}
void renderSetBackgroundColor(Color* col)
{
background_color = *col;
}
int _sortRenderFragment(void const* a, void const* b)
{ {
double za, zb; double za, zb;
za = ((RenderFragment*)a)->z; za = ((RenderFragment*)a)->z;
@ -185,12 +166,11 @@ int _sortRenderFragment(void const* a, void const* b)
{ {
return 0; return 0;
} }
} }*/
static Color _getPixelColor(Array* pixel_data) static Color _getPixelColor(Color base, Array* pixel_data)
{ {
RenderFragment* fragment; RenderFragment* fragment;
Color result = background_color;
int i; int i;
if (pixel_data->length > 0) if (pixel_data->length > 0)
@ -198,84 +178,91 @@ static Color _getPixelColor(Array* pixel_data)
for (i = 0; i < pixel_data->length; i++) for (i = 0; i < pixel_data->length; i++)
{ {
fragment = ((RenderFragment*)pixel_data->data) + i; fragment = ((RenderFragment*)pixel_data->data) + i;
colorMask(&result, &(fragment->vertex.color)); colorMask(&base, &(fragment->vertex.color));
} }
} }
return result; return base;
} }
static inline void _setDirtyPixel(Array* pixel_data, int x, int y) static inline void _setDirtyPixel(RenderArea* area, Array* pixel_data, int x, int y)
{ {
pixel_data->dirty = 1; pixel_data->dirty = 1;
if (x < _dirty_left) if (x < area->dirty_left)
{ {
_dirty_left = x; area->dirty_left = x;
} }
if (x > _dirty_right) if (x > area->dirty_right)
{ {
_dirty_right = x; area->dirty_right = x;
} }
if (y < _dirty_down) if (y < area->dirty_down)
{ {
_dirty_down = y; area->dirty_down = y;
} }
if (y > _dirty_up) if (y > area->dirty_up)
{ {
_dirty_up = y; area->dirty_up = y;
} }
_dirty_count++; area->dirty_count++;
} }
static void _processDirtyPixels() static void _processDirtyPixels(RenderArea* area)
{ {
Color col; Color col;
Array* pixel_data; Array* pixel_data;
int x, y; int x, y;
for (y = _dirty_down; y <= _dirty_up; y++) for (y = area->dirty_down; y <= area->dirty_up; y++)
{ {
for (x = _dirty_left; x <= _dirty_right; x++) for (x = area->dirty_left; x <= area->dirty_right; x++)
{ {
pixel_data = render_zone + y * render_width + x; pixel_data = area->pixels + y * area->width + x;
if (pixel_data->dirty) if (pixel_data->dirty)
{ {
col = _getPixelColor(pixel_data); col = _getPixelColor(area->background_color, pixel_data);
_cb_preview_draw(x, y, col); area->callback_draw(x, y, col);
pixel_data->dirty = 0; pixel_data->dirty = 0;
} }
} }
} }
_cb_preview_update(_progress * _progress_step_length + _progress_step_start); area->callback_update(0.0);
_dirty_left = render_width; area->dirty_left = area->width;
_dirty_right = -1; area->dirty_right = -1;
_dirty_down = render_height; area->dirty_down = area->height;
_dirty_up = -1; area->dirty_up = -1;
_dirty_count = 0; area->dirty_count = 0;
} }
static void _setAllDirty() void renderUpdate(RenderArea* area)
{
mutexAcquire(area->lock);
_processDirtyPixels(area);
mutexRelease(area->lock);
}
static void _setAllDirty(RenderArea* area)
{ {
int x, y; int x, y;
_dirty_left = 0; area->dirty_left = 0;
_dirty_right = render_width - 1; area->dirty_right = area->width - 1;
_dirty_down = 0; area->dirty_down = 0;
_dirty_up = render_height - 1; area->dirty_up = area->height - 1;
for (y = _dirty_down; y <= _dirty_up; y++) for (y = area->dirty_down; y <= area->dirty_up; y++)
{ {
for (x = _dirty_left; x <= _dirty_right; x++) for (x = area->dirty_left; x <= area->dirty_right; x++)
{ {
(render_zone + y * render_width + x)->dirty = 1; (area->pixels + y * area->width + x)->dirty = 1;
} }
} }
} }
void renderAddFragment(RenderFragment* fragment) void renderAddFragment(RenderArea* area, RenderFragment* fragment)
{ {
Array* pixel_data; Array* pixel_data;
int x = fragment->x; int x = fragment->x;
@ -287,9 +274,9 @@ void renderAddFragment(RenderFragment* fragment)
RenderFragment* fragments; RenderFragment* fragments;
dirty = 0; dirty = 0;
if (x >= 0 && x < render_width && y >= 0 && y < render_height && z > 1.0) if (x >= 0 && x < area->width && y >= 0 && y < area->height && z > 1.0)
{ {
pixel_data = render_zone + (y * render_width + x); pixel_data = area->pixels + (y * area->width + x);
fragments = (RenderFragment*)pixel_data->data; fragments = (RenderFragment*)pixel_data->data;
fragments_count = pixel_data->length; fragments_count = pixel_data->length;
@ -336,12 +323,12 @@ void renderAddFragment(RenderFragment* fragment)
if (dirty) if (dirty)
{ {
_setDirtyPixel(pixel_data, x, y); _setDirtyPixel(area, pixel_data, x, y);
} }
} }
} }
void renderPushFragment(int x, int y, double z, Vertex* vertex) void renderPushFragment(RenderArea* area, int x, int y, double z, Vertex* vertex)
{ {
RenderFragment fragment; RenderFragment fragment;
@ -350,7 +337,7 @@ void renderPushFragment(int x, int y, double z, Vertex* vertex)
fragment.z = z; fragment.z = z;
fragment.vertex = *vertex; fragment.vertex = *vertex;
renderAddFragment(&fragment); renderAddFragment(area, &fragment);
} }
static void __vertexGetDiff(Vertex* v1, Vertex* v2, Vertex* result) static void __vertexGetDiff(Vertex* v1, Vertex* v2, Vertex* result)
@ -385,43 +372,43 @@ static void __vertexInterpolate(Vertex* v1, Vertex* diff, double value, Vertex*
result->callback_data = v1->callback_data; result->callback_data = v1->callback_data;
} }
static void __pushScanLinePoint(RenderFragment point) static void __pushScanLinePoint(RenderArea* area, RenderFragment point)
{ {
if (point.x < 0 || point.x >= render_width) if (point.x < 0 || point.x >= area->width)
{ {
return; return;
} }
if (point.x > scanline_right) if (point.x > area->scanline_right)
{ {
scanline_right = point.x; area->scanline_right = point.x;
scanline_up[scanline_right] = point; area->scanline_up[area->scanline_right] = point;
scanline_down[scanline_right] = point; area->scanline_down[area->scanline_right] = point;
if (point.x < scanline_left) if (point.x < area->scanline_left)
{ {
scanline_left = point.x; area->scanline_left = point.x;
} }
} }
else if (point.x < scanline_left) else if (point.x < area->scanline_left)
{ {
scanline_left = point.x; area->scanline_left = point.x;
scanline_up[scanline_left] = point; area->scanline_up[area->scanline_left] = point;
scanline_down[scanline_left] = point; area->scanline_down[area->scanline_left] = point;
} }
else else
{ {
if (point.y > scanline_up[point.x].y) if (point.y > area->scanline_up[point.x].y)
{ {
scanline_up[point.x] = point; area->scanline_up[point.x] = point;
} }
if (point.y < scanline_down[point.x].y) if (point.y < area->scanline_down[point.x].y)
{ {
scanline_down[point.x] = point; area->scanline_down[point.x] = point;
} }
} }
} }
static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex* vertex2) static void __pushScanLineEdge(RenderArea* area, Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex* vertex2)
{ {
double dx, dy, dz, fx; double dx, dy, dz, fx;
Vertex diff; Vertex diff;
@ -432,9 +419,9 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
if (endx < startx) if (endx < startx)
{ {
__pushScanLineEdge(v2, v1, vertex2, vertex1); __pushScanLineEdge(area, v2, v1, vertex2, vertex1);
} }
else if (endx < 0 || startx >= render_width) else if (endx < 0 || startx >= area->width)
{ {
return; return;
} }
@ -445,14 +432,14 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
fragment.z = v1.z; fragment.z = v1.z;
fragment.vertex = *vertex1; fragment.vertex = *vertex1;
__pushScanLinePoint(fragment); __pushScanLinePoint(area, fragment);
fragment.x = endx; fragment.x = endx;
fragment.y = lround(v2.y); fragment.y = lround(v2.y);
fragment.z = v2.z; fragment.z = v2.z;
fragment.vertex = *vertex2; fragment.vertex = *vertex2;
__pushScanLinePoint(fragment); __pushScanLinePoint(area, fragment);
} }
else else
{ {
@ -460,9 +447,9 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
{ {
startx = 0; startx = 0;
} }
if (endx >= render_width) if (endx >= area->width)
{ {
endx = render_width - 1; endx = area->width - 1;
} }
dx = v2.x - v1.x; dx = v2.x - v1.x;
@ -486,41 +473,41 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
fragment.z = v1.z + dz * fx / dx; fragment.z = v1.z + dz * fx / dx;
__vertexInterpolate(vertex1, &diff, fx / dx, &(fragment.vertex)); __vertexInterpolate(vertex1, &diff, fx / dx, &(fragment.vertex));
__pushScanLinePoint(fragment); __pushScanLinePoint(area, fragment);
} }
} }
} }
static void __clearScanLines() static void __clearScanLines(RenderArea* area)
{ {
int x; int x;
for (x = scanline_left; x <= scanline_right; x++) for (x = area->scanline_left; x <= area->scanline_right; x++)
{ {
scanline_up[x].y = -1; area->scanline_up[x].y = -1;
scanline_down[x].y = render_height; area->scanline_down[x].y = area->height;
} }
scanline_left = render_width; area->scanline_left = area->width;
scanline_right = -1; area->scanline_right = -1;
} }
static void __renderScanLines() static void __renderScanLines(RenderArea* area)
{ {
int x, starty, endy, cury; int x, starty, endy, cury;
Vertex diff; Vertex diff;
double dy, dz, fy; double dy, dz, fy;
RenderFragment up, down, current; RenderFragment up, down, current;
if (scanline_right > 0) if (area->scanline_right > 0)
{ {
for (x = scanline_left; x <= scanline_right; x++) for (x = area->scanline_left; x <= area->scanline_right; x++)
{ {
up = scanline_up[x]; up = area->scanline_up[x];
down = scanline_down[x]; down = area->scanline_down[x];
starty = down.y; starty = down.y;
endy = up.y; endy = up.y;
if (endy < 0 || starty >= render_height) if (endy < 0 || starty >= area->height)
{ {
continue; continue;
} }
@ -529,9 +516,9 @@ static void __renderScanLines()
{ {
starty = 0; starty = 0;
} }
if (endy >= render_height) if (endy >= area->height)
{ {
endy = render_height - 1; endy = area->height - 1;
} }
dy = (double)(up.y - down.y); dy = (double)(up.y - down.y);
@ -554,21 +541,16 @@ static void __renderScanLines()
} }
#endif #endif
renderAddFragment(&current); renderAddFragment(area, &current);
} }
} }
} }
} }
void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3) void renderPushTriangle(RenderArea* area, Vertex* v1, Vertex* v2, Vertex* v3, Vector3 p1, Vector3 p2, Vector3 p3)
{ {
Vector3 p1, p2, p3; double limit_width = (double)(area->width - 1);
double limit_width = (double)(render_width - 1); double limit_height = (double)(area->height - 1);
double limit_height = (double)(render_height - 1);
p1 = renderer->projectPoint(renderer, v1->location);
p2 = renderer->projectPoint(renderer, v2->location);
p3 = renderer->projectPoint(renderer, v3->location);
/* Filter if outside screen */ /* Filter if outside screen */
if (p1.z < 1.0 || p2.z < 1.0 || p3.z < 1.0 || (p1.x < 0.0 && p2.x < 0.0 && p3.x < 0.0) || (p1.y < 0.0 && p2.y < 0.0 && p3.y < 0.0) || (p1.x > limit_width && p2.x > limit_width && p3.x > limit_width) || (p1.y > limit_height && p2.y > limit_height && p3.y > limit_height)) if (p1.z < 1.0 || p2.z < 1.0 || p3.z < 1.0 || (p1.x < 0.0 && p2.x < 0.0 && p3.x < 0.0) || (p1.y < 0.0 && p2.y < 0.0 && p3.y < 0.0) || (p1.x > limit_width && p2.x > limit_width && p3.x > limit_width) || (p1.y > limit_height && p2.y > limit_height && p3.y > limit_height))
@ -576,19 +558,13 @@ void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3)
return; return;
} }
__clearScanLines(); __clearScanLines(area);
__pushScanLineEdge(p1, p2, v1, v2); __pushScanLineEdge(area, p1, p2, v1, v2);
__pushScanLineEdge(p2, p3, v2, v3); __pushScanLineEdge(area, p2, p3, v2, v3);
__pushScanLineEdge(p3, p1, v3, v1); __pushScanLineEdge(area, p3, p1, v3, v1);
mutexAcquire(_lock); mutexAcquire(area->lock);
__renderScanLines(); __renderScanLines(area);
mutexRelease(_lock); mutexRelease(area->lock);
}
void renderPushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4)
{
renderPushTriangle(renderer, v2, v3, v1);
renderPushTriangle(renderer, v4, v1, v3);
} }
typedef struct { typedef struct {
@ -599,6 +575,7 @@ typedef struct {
int finished; int finished;
int interrupt; int interrupt;
Thread* thread; Thread* thread;
RenderArea* area;
Renderer* renderer; Renderer* renderer;
} RenderChunk; } RenderChunk;
@ -618,7 +595,7 @@ void* _renderPostProcessChunk(void* data)
{ {
for (x = chunk->startx; x <= chunk->endx; x++) for (x = chunk->startx; x <= chunk->endx; x++)
{ {
pixel_data = render_zone + (y * render_width + x); pixel_data = chunk->area->pixels + (y * chunk->area->width + x);
fragments = (RenderFragment*)pixel_data->data; fragments = (RenderFragment*)pixel_data->data;
dirty = 0; dirty = 0;
for (i = 0; i < pixel_data->length; i++) for (i = 0; i < pixel_data->length; i++)
@ -627,7 +604,6 @@ void* _renderPostProcessChunk(void* data)
{ {
if (fragments[i].vertex.callback(fragments + i, chunk->renderer, fragments[i].vertex.callback_data)) if (fragments[i].vertex.callback(fragments + i, chunk->renderer, fragments[i].vertex.callback_data))
{ {
/* TODO Store over-exposure */
colorNormalize(&fragments[i].vertex.color); colorNormalize(&fragments[i].vertex.color);
dirty = 1; dirty = 1;
} }
@ -635,11 +611,11 @@ void* _renderPostProcessChunk(void* data)
} }
if (dirty) if (dirty)
{ {
mutexAcquire(_lock); mutexAcquire(chunk->area->lock);
_setDirtyPixel(pixel_data, x, y); _setDirtyPixel(chunk->area, pixel_data, x, y);
mutexRelease(_lock); mutexRelease(chunk->area->lock);
} }
_progress_pixels++; /* chunk->area->progress_pixels++; */
} }
if (chunk->interrupt) if (chunk->interrupt)
{ {
@ -652,12 +628,13 @@ void* _renderPostProcessChunk(void* data)
} }
#define MAX_CHUNKS 8 #define MAX_CHUNKS 8
void renderPostProcess(Renderer* renderer, int nbchunks) void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks)
{ {
volatile RenderChunk chunks[MAX_CHUNKS]; volatile RenderChunk chunks[MAX_CHUNKS];
int i; int i;
int x, y, dx, dy, nx, ny; int x, y, dx, dy, nx, ny;
int loops, running; int loops, running;
int _interrupt = 0; /* TEMP */
if (nbchunks > MAX_CHUNKS) if (nbchunks > MAX_CHUNKS)
{ {
@ -670,15 +647,16 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
nx = 10; nx = 10;
ny = 10; ny = 10;
dx = render_width / nx; dx = area->width / nx;
dy = render_height / ny; dy = area->height / ny;
x = 0; x = 0;
y = 0; y = 0;
_progress_pixels = 0; /*_progress_pixels = 0;*/
for (i = 0; i < nbchunks; i++) for (i = 0; i < nbchunks; i++)
{ {
chunks[i].thread = NULL; chunks[i].thread = NULL;
chunks[i].area = area;
chunks[i].renderer = renderer; chunks[i].renderer = renderer;
} }
@ -711,7 +689,7 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
chunks[i].startx = x * dx; chunks[i].startx = x * dx;
if (x == nx) if (x == nx)
{ {
chunks[i].endx = render_width - 1; chunks[i].endx = area->width - 1;
} }
else else
{ {
@ -720,7 +698,7 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
chunks[i].starty = y * dy; chunks[i].starty = y * dy;
if (y == ny) if (y == ny)
{ {
chunks[i].endy = render_height - 1; chunks[i].endy = area->height - 1;
} }
else else
{ {
@ -740,27 +718,20 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
if (++loops >= 10) if (++loops >= 10)
{ {
mutexAcquire(_lock); mutexAcquire(area->lock);
_progress = (double)_progress_pixels / (double)_pixel_count; /*_progress = (double)_progress_pixels / (double)_pixel_count;*/
_processDirtyPixels(); _processDirtyPixels(area);
mutexRelease(_lock); mutexRelease(area->lock);
loops = 0; loops = 0;
} }
} }
_progress = 1.0; /*_progress = 1.0;*/
_processDirtyPixels(); _processDirtyPixels(area);
} }
void renderUpdate() void renderSaveToFile(RenderArea* area, const char* path)
{
mutexAcquire(_lock);
_processDirtyPixels();
mutexRelease(_lock);
}
void renderSaveToFile(const char* path)
{ {
ILuint image_id; ILuint image_id;
ilGenImages(1, &image_id); ilGenImages(1, &image_id);
@ -768,22 +739,22 @@ void renderSaveToFile(const char* path)
Color result; Color result;
ILuint x, y; ILuint x, y;
ILuint rgba; ILuint rgba;
ILuint data[render_height * render_width]; ILuint data[area->height * area->width];
ILenum error; ILenum error;
Array* pixel_data; Array* pixel_data;
for (y = 0; y < render_height; y++) for (y = 0; y < area->height; y++)
{ {
for (x = 0; x < render_width; x++) for (x = 0; x < area->width; x++)
{ {
pixel_data = render_zone + (y * render_width + x); pixel_data = area->pixels + (y * area->width + x);
result = _getPixelColor(pixel_data); result = _getPixelColor(area->background_color, pixel_data);
rgba = colorTo32BitRGBA(&result); rgba = colorTo32BitRGBA(&result);
data[y * render_width + x] = rgba; data[y * area->width + x] = rgba;
} }
} }
ilTexImage((ILuint)render_width, (ILuint)render_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, data); ilTexImage((ILuint)area->width, (ILuint)area->height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, data);
ilSaveImage(path); ilSaveImage(path);
ilDeleteImages(1, &image_id); ilDeleteImages(1, &image_id);
@ -794,46 +765,16 @@ void renderSaveToFile(const char* path)
} }
} }
void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClear clear, PreviewCallbackDraw draw, PreviewCallbackUpdate update) void renderSetPreviewCallbacks(RenderArea* area, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update)
{ {
_cb_preview_resize = resize ? resize : _previewResize; area->callback_start = start ? start : _callbackStart;
_cb_preview_clear = clear ? clear : _previewClear; area->callback_draw = draw ? draw : _callbackDraw;
_cb_preview_draw = draw ? draw : _previewDraw; area->callback_update = update ? update : _callbackUpdate;
_cb_preview_update = update ? update : _previewUpdate;
_cb_preview_resize(render_width, render_height); area->callback_start(area->width, area->height, area->background_color);
_cb_preview_clear(background_color);
_setAllDirty(); _setAllDirty(area);
_processDirtyPixels(); _processDirtyPixels(area);
_cb_preview_update(1.0); area->callback_update(0.0);
}
int renderSetNextProgressStep(double start, double end)
{
if (_interrupt)
{
return 0;
}
else
{
_progress = 0.0;
_progress_step_start = start;
_progress_step_length = end - start;
return 1;
}
}
int renderTellProgress(double progress)
{
if (_interrupt)
{
return 0;
}
else
{
_progress = progress;
return 1;
}
} }

View file

@ -10,23 +10,21 @@ extern "C" {
#endif #endif
void renderInit(); void renderInit();
void renderSave(FILE* f); RenderArea* renderCreateArea();
void renderLoad(FILE* f); void renderDeleteArea(RenderArea* area);
void renderSetSize(int width, int height);
int renderSetQuality(int quality); void renderSetSize(RenderArea* area, int width, int height);
void renderClear(); void renderSetBackgroundColor(RenderArea* area, Color* col);
void renderUpdate(); void renderClear(RenderArea* area);
void renderInterrupt(); void renderUpdate(RenderArea* area);
void renderSetBackgroundColor(Color* col);
void renderAddFragment(RenderFragment* fragment); void renderAddFragment(RenderArea* area, RenderFragment* fragment);
void renderPushFragment(int x, int y, double z, Vertex* vertex); void renderPushFragment(RenderArea* area, int x, int y, double z, Vertex* vertex);
void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3); void renderPushTriangle(RenderArea* area, Vertex* v1, Vertex* v2, Vertex* v3, Vector3 p1, Vector3 p2, Vector3 p3);
void renderPushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4);
void renderPostProcess(Renderer* renderer, int nbchunks); void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks);
void renderSaveToFile(const char* path); void renderSaveToFile(RenderArea* area, const char* path);
void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClear clear, PreviewCallbackDraw draw, PreviewCallbackUpdate update); void renderSetPreviewCallbacks(RenderArea* area, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update);
int renderSetNextProgressStep(double start, double end);
int renderTellProgress(double progress);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -1,10 +1,59 @@
#include "renderer.h" #include "renderer.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "lighting.h" #include "lighting.h"
#include "system.h"
#include "render.h"
#include "scenery.h"
RayCastingResult _RAYCASTING_NULL = {0}; RayCastingResult _RAYCASTING_NULL = {0};
HeightInfo _WATER_HEIGHT_INFO = {-1000000.0, -1000000.0, -1000000.0}; HeightInfo _WATER_HEIGHT_INFO = {-1000000.0, -1000000.0, -1000000.0};
static void* _renderFirstPass(void* data)
{
Renderer* renderer = (Renderer*)data;
sceneryRenderFirstPass(renderer);
renderer->is_rendering = 0;
return NULL;
}
static int _addRenderProgress(Renderer* renderer, double progress)
{
return 1;
}
static double _getPrecision(Renderer* renderer, Vector3 location)
{
return 0.001;
}
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
{
return point;
}
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
{
return point;
}
static void _pushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3)
{
Vector3 p1, p2, p3;
p1 = renderer->projectPoint(renderer, v1->location);
p2 = renderer->projectPoint(renderer, v2->location);
p3 = renderer->projectPoint(renderer, v3->location);
renderPushTriangle(renderer->render_area, v1, v2, v3, p1, p2, p3);
}
static void _pushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4)
{
renderer->pushTriangle(renderer, v2, v3, v1);
renderer->pushTriangle(renderer, v4, v1, v3);
}
static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light) static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
{ {
return light_color; return light_color;
@ -50,40 +99,88 @@ static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3
return base; return base;
} }
static Vector3 _projectPoint(Renderer* renderer, Vector3 point) Renderer rendererCreate()
{
return point;
}
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
{
return point;
}
static double _getPrecision(Renderer* renderer, Vector3 location)
{
return 0.001;
}
Renderer rendererGetFake()
{ {
Renderer result; Renderer result;
result.render_quality = 5; result.render_quality = 5;
result.render_width = 1;
result.render_height = 1;
result.render_interrupt = 0;
result.render_progress = 0.0;
result.is_rendering = 0;
result.camera_location = VECTOR_ZERO; result.camera_location = VECTOR_ZERO;
result.render_area = renderCreateArea();
renderSetSize(result.render_area, 1, 1);
result.addRenderProgress = _addRenderProgress;
result.getPrecision = _getPrecision;
result.projectPoint = _projectPoint;
result.unprojectPoint = _unprojectPoint;
result.pushTriangle = _pushTriangle;
result.pushQuad = _pushQuad;
result.filterLight = _filterLight;
result.maskLight = _maskLight;
result.applyLightingToSurface = _applyLightingToSurface;
result.rayWalking = _rayWalking; result.rayWalking = _rayWalking;
result.getTerrainHeight = _getTerrainHeight; result.getTerrainHeight = _getTerrainHeight;
result.getWaterHeightInfo = _getWaterHeightInfo; result.getWaterHeightInfo = _getWaterHeightInfo;
result.applyTextures = _applyTextures; result.applyTextures = _applyTextures;
result.applyAtmosphere = _applyAtmosphere; result.applyAtmosphere = _applyAtmosphere;
result.applyClouds = _applyClouds; result.applyClouds = _applyClouds;
result.projectPoint = _projectPoint;
result.unprojectPoint = _unprojectPoint; result.filterLight = _filterLight;
result.getPrecision = _getPrecision; result.maskLight = _maskLight;
result.applyLightingToSurface = _applyLightingToSurface;
return result; return result;
} }
void rendererDelete(Renderer* renderer)
{
renderDeleteArea(renderer->render_area);
}
void rendererSetPreviewCallbacks(Renderer* renderer, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update)
{
renderSetPreviewCallbacks(renderer->render_area, start, draw, update);
}
void rendererStart(Renderer* renderer, int width, int height, int quality)
{
Thread* thread;
int loops;
int core_count = systemGetCoreCount();
renderer->render_quality = quality;
renderer->render_width = width;
renderer->render_height = height;
renderer->render_interrupt = 0;
renderer->render_progress = 0.0;
renderSetBackgroundColor(renderer->render_area, &COLOR_BLACK);
renderSetSize(renderer->render_area, width, height);
renderClear(renderer->render_area);
renderer->is_rendering = 1;
thread = threadCreate(_renderFirstPass, renderer);
loops = 0;
while (renderer->is_rendering)
{
timeSleepMs(100);
if (++loops >= 10)
{
renderUpdate(renderer->render_area);
loops = 0;
}
}
threadJoin(thread);
renderer->is_rendering = 1;
renderPostProcess(renderer->render_area, renderer, core_count);
renderer->is_rendering = 0;
}
void rendererInterrupt(Renderer* renderer)
{
}

View file

@ -11,14 +11,23 @@ typedef struct Renderer Renderer;
struct Renderer struct Renderer
{ {
/* Quality configuration */ /* Render base configuration */
int render_quality; int render_quality;
int render_width;
int render_height;
Vector3 camera_location; Vector3 camera_location;
/* Render related */ /* Render related */
RenderArea* render_area;
double render_progress;
int render_interrupt;
int is_rendering;
double (*getPrecision)(Renderer* renderer, Vector3 location); double (*getPrecision)(Renderer* renderer, Vector3 location);
Vector3 (*projectPoint)(Renderer* renderer, Vector3 point); Vector3 (*projectPoint)(Renderer* renderer, Vector3 point);
Vector3 (*unprojectPoint)(Renderer* renderer, Vector3 point); Vector3 (*unprojectPoint)(Renderer* renderer, Vector3 point);
int (*addRenderProgress)(Renderer* renderer, double progress);
void (*pushTriangle)(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3);
void (*pushQuad)(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4);
/* Scenery related */ /* Scenery related */
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds); RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
@ -37,7 +46,11 @@ struct Renderer
void* customData[10]; void* customData[10];
}; };
Renderer rendererGetFake(); Renderer rendererCreate();
void rendererDelete(Renderer* renderer);
void rendererSetPreviewCallbacks(Renderer* renderer, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update);
void rendererStart(Renderer* renderer, int width, int height, int quality);
void rendererInterrupt(Renderer* renderer);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -177,29 +177,21 @@ void sceneryGetWater(WaterDefinition* water)
void sceneryRenderFirstPass(Renderer* renderer) void sceneryRenderFirstPass(Renderer* renderer)
{ {
if (!renderSetNextProgressStep(0.0, 0.01)) /*if (!renderSetNextProgressStep(0.0, 0.01))
{ {
return; return;
} }*/
skyRender(&_sky, renderer, renderTellProgress); skyRender(&_sky, renderer);
if (!renderSetNextProgressStep(0.01, 0.085)) /*if (!renderSetNextProgressStep(0.01, 0.085))
{ {
return; return;
} }*/
terrainRender(&_terrain, renderer, renderTellProgress); terrainRender(&_terrain, renderer);
if (!renderSetNextProgressStep(0.085, 0.1)) /*if (!renderSetNextProgressStep(0.085, 0.1))
{ {
return; return;
} }*/
waterRender(&_water, renderer, renderTellProgress); waterRender(&_water, renderer);
}
void sceneryRenderSecondPass(Renderer* renderer)
{
if (renderSetNextProgressStep(0.1, 1.0))
{
renderPostProcess(renderer, systemGetCoreCount());
}
} }
@ -277,34 +269,32 @@ static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3
static Vector3 _projectPoint(Renderer* renderer, Vector3 point) static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
{ {
return cameraProject(&_camera, point); return cameraProject(&_camera, renderer, point);
} }
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point) static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
{ {
return cameraUnproject(&_camera, point); return cameraUnproject(&_camera, renderer, point);
} }
static double _getPrecision(Renderer* renderer, Vector3 location) static double _getPrecision(Renderer* renderer, Vector3 location)
{ {
Vector3 projected; Vector3 projected;
projected = cameraProject(&_camera, location); projected = cameraProject(&_camera, renderer, location);
projected.x += 1.0; projected.x += 1.0;
//projected.y += 1.0; //projected.y += 1.0;
return v3Norm(v3Sub(cameraUnproject(&_camera, projected), location)); // / (double)render_quality; return v3Norm(v3Sub(cameraUnproject(&_camera, renderer, projected), location)); // / (double)render_quality;
} }
Renderer sceneryGetStandardRenderer(int quality) Renderer sceneryCreateStandardRenderer()
{ {
Renderer result; Renderer result;
quality = (quality > 10) ? 10 : quality; result = rendererCreate();
quality = (quality < 1) ? 1 : quality;
result.camera_location = _camera.location; result.camera_location = _camera.location;
result.render_quality = quality;
result.filterLight = _filterLight; result.filterLight = _filterLight;
result.maskLight = _maskLight; result.maskLight = _maskLight;

View file

@ -51,9 +51,8 @@ void sceneryGetTextures(TexturesDefinition* textures);
void scenerySetWater(WaterDefinition* water); void scenerySetWater(WaterDefinition* water);
void sceneryGetWater(WaterDefinition* water); void sceneryGetWater(WaterDefinition* water);
Renderer sceneryGetStandardRenderer(int quality); Renderer sceneryCreateStandardRenderer();
void sceneryRenderFirstPass(Renderer* renderer); void sceneryRenderFirstPass(Renderer* renderer);
void sceneryRenderSecondPass(Renderer* renderer);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,18 +0,0 @@
#ifndef _PAYSAGES_GLOBALS_H_
#define _PAYSAGES_GLOBALS_H_
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
extern int render_width;
extern int render_height;
extern int render_quality;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -100,11 +100,11 @@ typedef struct
typedef struct Zone Zone; typedef struct Zone Zone;
typedef void (*PreviewCallbackResize)(int width, int height); typedef void (*RenderCallbackStart)(int width, int height, Color background);
typedef void (*PreviewCallbackClear)(Color col); typedef void (*RenderCallbackDraw)(int x, int y, Color col);
typedef void (*PreviewCallbackDraw)(int x, int y, Color col); typedef void (*RenderCallbackUpdate)(double progress);
typedef void (*PreviewCallbackUpdate)(double progress);
typedef int (*RenderProgressCallback)(double progress); typedef struct RenderArea RenderArea;
typedef struct typedef struct
{ {

View file

@ -4,7 +4,6 @@
#include <math.h> #include <math.h>
#include "shared/types.h" #include "shared/types.h"
#include "shared/globals.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "color.h" #include "color.h"
#include "clouds.h" #include "clouds.h"
@ -182,7 +181,7 @@ static int _postProcessFragment(RenderFragment* fragment, Renderer* renderer, vo
return 1; return 1;
} }
void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback) void skyRender(SkyDefinition* definition, Renderer* renderer)
{ {
int res_i, res_j; int res_i, res_j;
int i, j; int i, j;
@ -203,7 +202,7 @@ void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCall
for (j = 0; j < res_j; j++) for (j = 0; j < res_j; j++)
{ {
if (!callback((double)j / (double)(res_j - 1))) if (!renderer->addRenderProgress(renderer, 0.0))
{ {
return; return;
} }
@ -251,7 +250,7 @@ void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCall
vertex4.callback_data = definition; vertex4.callback_data = definition;
/* TODO Triangles at poles */ /* TODO Triangles at poles */
renderPushQuad(renderer, &vertex1, &vertex4, &vertex3, &vertex2); renderer->pushQuad(renderer, &vertex1, &vertex4, &vertex3, &vertex2);
} }
} }
} }

View file

@ -32,7 +32,7 @@ void skyValidateDefinition(SkyDefinition* definition);
int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights); int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights);
Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look); Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look);
void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback); void skyRender(SkyDefinition* definition, Renderer* renderer);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -6,7 +6,6 @@
#include <assert.h> #include <assert.h>
#include "shared/types.h" #include "shared/types.h"
#include "shared/globals.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "euclid.h" #include "euclid.h"
#include "render.h" #include "render.h"
@ -322,7 +321,7 @@ static void _renderQuad(TerrainDefinition* definition, Renderer* renderer, doubl
if (v1.location.y > water_height || v2.location.y > water_height || v3.location.y > water_height || v4.location.y > water_height) if (v1.location.y > water_height || v2.location.y > water_height || v3.location.y > water_height || v4.location.y > water_height)
{ {
renderPushQuad(renderer, &v1, &v2, &v3, &v4); renderer->pushQuad(renderer, &v1, &v2, &v3, &v4);
} }
} }
@ -349,7 +348,7 @@ Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double
return _getColor(definition, renderer, point, detail); return _getColor(definition, renderer, point, detail);
} }
void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback) void terrainRender(TerrainDefinition* definition, Renderer* renderer)
{ {
int chunk_factor, chunk_count, i; int chunk_factor, chunk_count, i;
double cx = renderer->camera_location.x; double cx = renderer->camera_location.x;
@ -371,7 +370,7 @@ void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProg
while (radius_ext < 1000.0) while (radius_ext < 1000.0)
{ {
if (!callback(radius_ext / 1000.0)) if (!renderer->addRenderProgress(renderer, 0.0))
{ {
return; return;
} }

View file

@ -41,7 +41,7 @@ int terrainProjectRay(TerrainDefinition* definition, Renderer* renderer, Vector3
double terrainGetHeight(TerrainDefinition* definition, double x, double z); double terrainGetHeight(TerrainDefinition* definition, double x, double z);
double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z); double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z);
Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail); Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail);
void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback); void terrainRender(TerrainDefinition* definition, Renderer* renderer);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -7,7 +7,6 @@
#include "shared/types.h" #include "shared/types.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.h"
#include "color.h" #include "color.h"
#include "euclid.h" #include "euclid.h"
#include "lighting.h" #include "lighting.h"

View file

@ -2,7 +2,6 @@
#include "shared/types.h" #include "shared/types.h"
#include "shared/constants.h" #include "shared/constants.h"
#include "shared/globals.h"
#include "color.h" #include "color.h"
#include "euclid.h" #include "euclid.h"
#include "render.h" #include "render.h"
@ -266,10 +265,10 @@ static void _renderQuad(WaterDefinition* definition, Renderer* renderer, double
v2 = _getFirstPassVertex(definition, x, z + size, size); v2 = _getFirstPassVertex(definition, x, z + size, size);
v3 = _getFirstPassVertex(definition, x + size, z + size, size); v3 = _getFirstPassVertex(definition, x + size, z + size, size);
v4 = _getFirstPassVertex(definition, x + size, z, size); v4 = _getFirstPassVertex(definition, x + size, z, size);
renderPushQuad(renderer, &v1, &v2, &v3, &v4); renderer->pushQuad(renderer, &v1, &v2, &v3, &v4);
} }
void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback) void waterRender(WaterDefinition* definition, Renderer* renderer)
{ {
int chunk_factor, chunk_count, i; int chunk_factor, chunk_count, i;
double cx = renderer->camera_location.x; double cx = renderer->camera_location.x;
@ -286,7 +285,7 @@ void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgress
while (radius_ext < 1000.0) while (radius_ext < 1000.0)
{ {
if (!callback(radius_ext / 1000.0)) if (!renderer->addRenderProgress(renderer, 0.0))
{ {
return; return;
} }

View file

@ -47,7 +47,7 @@ HeightInfo waterGetHeightInfo(WaterDefinition* definition);
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light); Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look); WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look); Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback); void waterRender(WaterDefinition* definition, Renderer* renderer);
#ifdef __cplusplus #ifdef __cplusplus
} }