From 878614e13c40480cf7567927ed11b6e0f6ca9a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 29 Jan 2012 21:45:58 +0000 Subject: [PATCH] paysages: Refactored rendering to use a RenderArea. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@252 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- TODO | 2 +- cli/main.c | 16 +- gui_qt/dialogrender.cpp | 75 ++--- gui_qt/formrender.cpp | 2 +- gui_qt/formsky.cpp | 4 +- gui_qt/formterrain.cpp | 2 +- gui_qt/formwater.cpp | 2 +- lib_paysages/auto.c | 66 ----- lib_paysages/auto.h | 2 - lib_paysages/camera.c | 25 +- lib_paysages/camera.h | 11 +- lib_paysages/clouds.c | 1 - lib_paysages/lighting.c | 1 - lib_paysages/main.c | 1 - lib_paysages/render.c | 511 +++++++++++++++------------------- lib_paysages/render.h | 32 +-- lib_paysages/renderer.c | 141 ++++++++-- lib_paysages/renderer.h | 17 +- lib_paysages/scenery.c | 42 ++- lib_paysages/scenery.h | 3 +- lib_paysages/shared/globals.h | 18 -- lib_paysages/shared/types.h | 10 +- lib_paysages/sky.c | 7 +- lib_paysages/sky.h | 2 +- lib_paysages/terrain.c | 7 +- lib_paysages/terrain.h | 2 +- lib_paysages/textures.c | 1 - lib_paysages/water.c | 7 +- lib_paysages/water.h | 2 +- 29 files changed, 481 insertions(+), 531 deletions(-) delete mode 100644 lib_paysages/shared/globals.h diff --git a/TODO b/TODO index 46e4bc7..d66ff25 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,7 @@ +- Restore render interrupt and progress - Clouds are lighted without filtering from ground (clouds lighted at night !) - Camera should respect ratio aspect of render area. - All noises should use the same entropy pool (saved separately), and avoid reallocs. - 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. - Water and terrain LOD moves with the camera, fix it like in the wanderer. diff --git a/cli/main.c b/cli/main.c index 2e977ea..4ecfbd2 100644 --- a/cli/main.c +++ b/cli/main.c @@ -3,16 +3,17 @@ #include #include "../lib_paysages/auto.h" +#include "../lib_paysages/main.h" #include "../lib_paysages/render.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); - autoRenderSceneTwoPass(renderer, 0); + rendererStart(renderer, width, height, quality); printf("\rSaving %s ... \n", outputpath); remove(outputpath); - renderSaveToFile(outputpath); + renderSaveToFile(renderer->render_area, outputpath); } void displayHelp() @@ -97,19 +98,20 @@ int main(int argc, char** argv) printf("Initializing ...\n"); paysagesInit(); - renderer = sceneryGetStandardRenderer(conf_render_quality); - renderSetSize(conf_render_width, conf_render_height); - renderSetPreviewCallbacks(NULL, NULL, NULL, _previewUpdate); + renderer = sceneryCreateStandardRenderer(); + rendererSetPreviewCallbacks(&renderer, NULL, NULL, _previewUpdate); for (outputcount = 0; outputcount < conf_nb_pictures; outputcount++) { autoSetDaytimeFraction(conf_daytime_start); 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; } + + rendererDelete(&renderer); printf("\rDone. \n"); diff --git a/gui_qt/dialogrender.cpp b/gui_qt/dialogrender.cpp index 750dde7..26acdf6 100644 --- a/gui_qt/dialogrender.cpp +++ b/gui_qt/dialogrender.cpp @@ -4,46 +4,21 @@ #include #include #include +#include "tools.h" -#include "../lib_paysages/render.h" #include "../lib_paysages/scenery.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 void _renderResize(int width, int height) +static void _renderStart(int width, int height, Color background) { - delete _current_dialog->pixbuf; - _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()); + _current_dialog->pixbuf->fill(colorToQColor(background).rgb()); } 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) @@ -52,6 +27,27 @@ static void _renderUpdate(double progress) _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 { public: @@ -76,6 +72,7 @@ DialogRender::DialogRender(QWidget *parent): pixbuf = new QImage(1, 1, QImage::Format_ARGB32); _current_dialog = this; render_thread = NULL; + renderer = sceneryCreateStandardRenderer(); setModal(true); setWindowTitle("Paysages 3D - Render"); @@ -99,23 +96,29 @@ DialogRender::~DialogRender() { if (render_thread) { - renderInterrupt(); + rendererInterrupt(&renderer); render_thread->wait(); - renderSetPreviewCallbacks(NULL, NULL, NULL, NULL); + rendererSetPreviewCallbacks(&renderer, NULL, NULL, NULL); delete render_thread; } + rendererDelete(&renderer); delete pixbuf; } void DialogRender::startRender(int quality, int width, int height) { - renderer = sceneryGetStandardRenderer(quality); - renderSetSize(width, height); - renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate); + delete pixbuf; + pixbuf = new QImage(width, height, QImage::Format_ARGB32); + area->setMinimumSize(width, height); + area->setMaximumSize(width, height); + area->resize(width, height); + scroll->setMinimumSize(width > 800 ? 850 : width + 50, height > 600 ? 650 : height + 50); + + rendererSetPreviewCallbacks(&renderer, _renderStart, _renderDraw, _renderUpdate); - render_thread = new RenderThread(&renderer); + render_thread = new RenderThread(&renderer, width, height, quality); render_thread->start(); exec(); @@ -124,7 +127,7 @@ void DialogRender::startRender(int quality, int width, int height) void DialogRender::loadLastRender() { progress->hide(); - renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate); + //renderSetPreviewCallbacks(_renderStart, _renderDraw, _renderUpdate); exec(); } diff --git a/gui_qt/formrender.cpp b/gui_qt/formrender.cpp index b0aedf7..e31f609 100644 --- a/gui_qt/formrender.cpp +++ b/gui_qt/formrender.cpp @@ -74,7 +74,7 @@ void FormRender::saveRender() filepath = QFileDialog::getSaveFileName(this, "Choose a filename to save the last render"); 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."); } } diff --git a/gui_qt/formsky.cpp b/gui_qt/formsky.cpp index 8108a93..e481bfa 100644 --- a/gui_qt/formsky.cpp +++ b/gui_qt/formsky.cpp @@ -20,7 +20,7 @@ public: PreviewEast(QWidget* parent): Preview(parent) { - _renderer = rendererGetFake(); + _renderer = rendererCreate(); _preview_definition = skyCreateDefinition(); } protected: @@ -50,7 +50,7 @@ public: PreviewWest(QWidget* parent): Preview(parent) { - _renderer = rendererGetFake(); + _renderer = rendererCreate(); _preview_definition = skyCreateDefinition(); } protected: diff --git a/gui_qt/formterrain.cpp b/gui_qt/formterrain.cpp index 51b7a5e..e7c2275 100644 --- a/gui_qt/formterrain.cpp +++ b/gui_qt/formterrain.cpp @@ -40,7 +40,7 @@ class PreviewTerrainColor:public Preview public: PreviewTerrainColor(QWidget* parent):Preview(parent) { - _renderer = rendererGetFake(); + _renderer = rendererCreate(); _renderer.applyTextures = _applyTextures; _renderer.getTerrainHeight = _getTerrainHeight; /*_renderer.applyLightingToSurface = _applyLightingToSurface;*/ diff --git a/gui_qt/formwater.cpp b/gui_qt/formwater.cpp index b366f40..39d6823 100644 --- a/gui_qt/formwater.cpp +++ b/gui_qt/formwater.cpp @@ -72,7 +72,7 @@ public: lightingAddLight(&_lighting, light); lightingValidateDefinition(&_lighting); - _renderer = rendererGetFake(); + _renderer = rendererCreate(); _renderer.rayWalking = _rayWalking; _renderer.applyLightingToSurface = _applyLightingToSurface; _renderer.customData[0] = &_water; diff --git a/lib_paysages/auto.c b/lib_paysages/auto.c index ebde561..273826b 100644 --- a/lib_paysages/auto.c +++ b/lib_paysages/auto.c @@ -6,7 +6,6 @@ #include "shared/types.h" #include "shared/constants.h" -#include "shared/globals.h" #include "clouds.h" #include "color.h" #include "lighting.h" @@ -20,8 +19,6 @@ #include "water.h" #include "zone.h" -static int _is_rendering = 0; - void autoSetDaytime(int hour, int minute) { autoSetDaytimeFraction((double)hour / 24.0 + (double)minute / 1440.0); @@ -231,66 +228,3 @@ void autoGenRealisticLandscape(int seed) scenerySetAtmosphere(&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); - }*/ -} diff --git a/lib_paysages/auto.h b/lib_paysages/auto.h index 6ee47ea..b7a9ca1 100644 --- a/lib_paysages/auto.h +++ b/lib_paysages/auto.h @@ -10,8 +10,6 @@ extern "C" { void autoSetDaytime(int hour, int minute); void autoSetDaytimeFraction(double daytime); void autoGenRealisticLandscape(int seed); -void autoRenderSceneTwoPass(Renderer* renderer, int postonly); -void autoRenderSceneRayTracing(); #ifdef __cplusplus } diff --git a/lib_paysages/camera.c b/lib_paysages/camera.c index 5521fd0..2954367 100644 --- a/lib_paysages/camera.c +++ b/lib_paysages/camera.c @@ -5,7 +5,6 @@ #include "euclid.h" #include "render.h" #include "shared/types.h" -#include "shared/globals.h" #include "shared/constants.h" #include "scenery.h" #include "tools.h" @@ -211,25 +210,25 @@ void cameraRotateRoll(CameraDefinition* camera, double value) cameraValidateDefinition(camera, 0); } -Vector3 cameraProject(CameraDefinition* camera, Vector3 point) +Vector3 cameraProject(CameraDefinition* camera, Renderer* renderer, Vector3 point) { point = m4Transform(camera->project, point); - point.x = (point.x + 1.0) * 0.5 * (double)render_width; - point.y = (-point.y + 1.0) * 0.5 * (double)render_height; + point.x = (point.x + 1.0) * 0.5 * (double)renderer->render_width; + point.y = (-point.y + 1.0) * 0.5 * (double)renderer->render_height; 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.y = -(point.y / (0.5 * (double)render_height) - 1.0); + point.x = (point.x / (0.5 * (double)renderer->render_width) - 1.0); + point.y = -(point.y / (0.5 * (double)renderer->render_height) - 1.0); 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}; - point = cameraProject(camera, point); + point = cameraProject(camera, renderer, point); result->x = lround(point.x); result->y = lround(point.y); result->z = point.z; @@ -242,9 +241,9 @@ void cameraProjectToFragment(CameraDefinition* camera, double x, double y, doubl * @param col Color of the polygon. * @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; v.x = 0.0; @@ -275,5 +274,5 @@ void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCall v4.color = col; v4.callback = callback; - renderPushQuad(&v1, &v2, &v3, &v4);*/ -} + renderPushQuad(&v1, &v2, &v3, &v4); +}*/ diff --git a/lib_paysages/camera.h b/lib_paysages/camera.h index b236fa7..9d1c7f9 100644 --- a/lib_paysages/camera.h +++ b/lib_paysages/camera.h @@ -1,8 +1,9 @@ #ifndef _PAYSAGES_CAMERA_H_ #define _PAYSAGES_CAMERA_H_ -#include "shared/types.h" #include +#include "shared/types.h" +#include "renderer.h" #ifdef __cplusplus extern "C" { @@ -48,10 +49,10 @@ void cameraRotateYaw(CameraDefinition* camera, double value); void cameraRotatePitch(CameraDefinition* camera, double value); void cameraRotateRoll(CameraDefinition* camera, double value); -Vector3 cameraProject(CameraDefinition* camera, Vector3 point); -Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point); -void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result); -void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback); +Vector3 cameraProject(CameraDefinition* camera, Renderer* renderer, Vector3 point); +Vector3 cameraUnproject(CameraDefinition* camera, Renderer* renderer, Vector3 point); +void cameraProjectToFragment(CameraDefinition* camera, Renderer* renderer, double x, double y, double z, RenderFragment* result); +/*void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback);*/ #ifdef __cplusplus } diff --git a/lib_paysages/clouds.c b/lib_paysages/clouds.c index 3b7b211..d5a4f02 100644 --- a/lib_paysages/clouds.c +++ b/lib_paysages/clouds.c @@ -8,7 +8,6 @@ #include "tools.h" #include "shared/types.h" #include "shared/constants.h" -#include "shared/globals.h" typedef struct { diff --git a/lib_paysages/lighting.c b/lib_paysages/lighting.c index 9a23850..764cce3 100644 --- a/lib_paysages/lighting.c +++ b/lib_paysages/lighting.c @@ -7,7 +7,6 @@ #include "shared/types.h" #include "shared/constants.h" -#include "shared/globals.h" #include "color.h" #include "euclid.h" #include "renderer.h" diff --git a/lib_paysages/main.c b/lib_paysages/main.c index a268141..53620a9 100644 --- a/lib_paysages/main.c +++ b/lib_paysages/main.c @@ -6,7 +6,6 @@ #include "shared/types.h" #include "shared/constants.h" -#include "shared/globals.h" #include "auto.h" #include "system.h" diff --git a/lib_paysages/render.c b/lib_paysages/render.c index c9b0bac..f052b7c 100644 --- a/lib_paysages/render.c +++ b/lib_paysages/render.c @@ -11,164 +11,145 @@ #include "color.h" #include "system.h" -int render_width; -int render_height; -int render_quality; -static int _pixel_count; -static Array* render_zone = NULL; -static RenderFragment* scanline_up; -static RenderFragment* scanline_down; -static int scanline_left; -static int scanline_right; -static Color background_color; -static volatile int _dirty_left; -static volatile int _dirty_right; -static volatile int _dirty_up; -static volatile int _dirty_down; -static volatile int _dirty_count; -static Mutex* _lock; - -static volatile int _interrupt = 0; -static volatile int _progress_pixels; -static volatile double _progress = 0.0; -static volatile double _progress_step_start = 0.0; -static volatile double _progress_step_length = 1.0; +struct RenderArea +{ + int width; + int height; + int pixel_count; + Array* pixels; + RenderFragment* scanline_up; + RenderFragment* scanline_down; + int scanline_left; + int scanline_right; + Color background_color; + volatile int dirty_left; + volatile int dirty_right; + volatile int dirty_up; + volatile int dirty_down; + volatile int dirty_count; + Mutex* lock; + RenderCallbackStart callback_start; + RenderCallbackDraw callback_draw; + RenderCallbackUpdate callback_update; +}; /*#define RENDER_INVERSE 1*/ #define RENDER_WIREFRAME 1 -static void _previewResize(int width, int height) {} -static void _previewClear(Color col) {} -static void _previewDraw(int x, int y, Color col) {} -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) -{ -} +static void _callbackStart(int width, int height, Color background) {} +static void _callbackDraw(int x, int y, Color col) {} +static void _callbackUpdate(double progress) {} 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 y; - if (render_zone != NULL) + for (x = 0; x < area->width; x++) { - /* Delete previous render zone */ - for (x = 0; x < render_width; x++) + for (y = 0; y < area->height; y++) { - for (y = 0; y < render_height; y++) - { - arrayDelete(render_zone + (y * render_width + x)); - } + arrayDelete(area->pixels + (y * area->width + x)); } - free(render_zone); - free(scanline_up); - free(scanline_down); } - render_width = width; - render_height = height; - render_zone = malloc(sizeof(Array) * width * height); + area->width = width; + area->height = height; + area->pixels = realloc(area->pixels, sizeof(Array) * width * height); + area->pixel_count = width * height; - scanline_left = 0; - scanline_right = render_width - 1; - scanline_up = malloc(sizeof(RenderFragment) * width); - scanline_down = malloc(sizeof(RenderFragment) * width); + area->scanline_left = 0; + area->scanline_right = width - 1; + area->scanline_up = realloc(area->scanline_up, sizeof(RenderFragment) * width); + area->scanline_down = realloc(area->scanline_down, sizeof(RenderFragment) * width); - _dirty_left = render_width; - _dirty_right = -1; - _dirty_down = render_height; - _dirty_up = -1; - _dirty_count = 0; - - _pixel_count = render_width * render_height; + area->dirty_left = width; + area->dirty_right = -1; + area->dirty_down = height; + area->dirty_up = -1; + area->dirty_count = 0; for (y = 0; y < height; y++) { 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) - { - render_quality = 1; - } - else if (quality > 10) - { - render_quality = 10; - } - else - { - render_quality = quality; - } - return render_quality; + area->background_color = *col; } -void renderClear() +void renderClear(RenderArea* area) { int x; 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; - scanline_right = render_width - 1; + area->scanline_left = 0; + area->scanline_right = area->width - 1; - _progress = 0.0; - _progress_step_start = 0.0; - _progress_step_length = 0.0; - _interrupt = 0; + area->callback_start(area->width, area->height, area->background_color); - _cb_preview_clear(background_color); - _cb_preview_update(_progress * _progress_step_length + _progress_step_start); - - _dirty_left = render_width; - _dirty_right = -1; - _dirty_down = render_height; - _dirty_up = -1; - _dirty_count = 0; + area->dirty_left = area->width; + area->dirty_right = -1; + area->dirty_down = area->height; + area->dirty_up = -1; + area->dirty_count = 0; } -void renderInterrupt() -{ - _interrupt = 1; -} - -void renderSetBackgroundColor(Color* col) -{ - background_color = *col; -} - -int _sortRenderFragment(void const* a, void const* b) +/*static int _sortRenderFragment(void const* a, void const* b) { double za, zb; za = ((RenderFragment*)a)->z; @@ -185,12 +166,11 @@ int _sortRenderFragment(void const* a, void const* b) { return 0; } -} +}*/ -static Color _getPixelColor(Array* pixel_data) +static Color _getPixelColor(Color base, Array* pixel_data) { RenderFragment* fragment; - Color result = background_color; int i; if (pixel_data->length > 0) @@ -198,84 +178,91 @@ static Color _getPixelColor(Array* pixel_data) for (i = 0; i < pixel_data->length; 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; - 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; Array* pixel_data; 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) { - col = _getPixelColor(pixel_data); - _cb_preview_draw(x, y, col); + col = _getPixelColor(area->background_color, pixel_data); + area->callback_draw(x, y, col); pixel_data->dirty = 0; } } } - _cb_preview_update(_progress * _progress_step_length + _progress_step_start); + area->callback_update(0.0); - _dirty_left = render_width; - _dirty_right = -1; - _dirty_down = render_height; - _dirty_up = -1; - _dirty_count = 0; + area->dirty_left = area->width; + area->dirty_right = -1; + area->dirty_down = area->height; + area->dirty_up = -1; + 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; - _dirty_left = 0; - _dirty_right = render_width - 1; - _dirty_down = 0; - _dirty_up = render_height - 1; + area->dirty_left = 0; + area->dirty_right = area->width - 1; + area->dirty_down = 0; + 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; int x = fragment->x; @@ -287,9 +274,9 @@ void renderAddFragment(RenderFragment* fragment) RenderFragment* fragments; 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_count = pixel_data->length; @@ -336,12 +323,12 @@ void renderAddFragment(RenderFragment* fragment) 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; @@ -350,7 +337,7 @@ void renderPushFragment(int x, int y, double z, Vertex* vertex) fragment.z = z; fragment.vertex = *vertex; - renderAddFragment(&fragment); + renderAddFragment(area, &fragment); } 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; } -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; } - if (point.x > scanline_right) + if (point.x > area->scanline_right) { - scanline_right = point.x; - scanline_up[scanline_right] = point; - scanline_down[scanline_right] = point; - if (point.x < scanline_left) + area->scanline_right = point.x; + area->scanline_up[area->scanline_right] = point; + area->scanline_down[area->scanline_right] = point; + 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; - scanline_up[scanline_left] = point; - scanline_down[scanline_left] = point; + area->scanline_left = point.x; + area->scanline_up[area->scanline_left] = point; + area->scanline_down[area->scanline_left] = point; } 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; Vertex diff; @@ -432,9 +419,9 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex* 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; } @@ -445,14 +432,14 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex* fragment.z = v1.z; fragment.vertex = *vertex1; - __pushScanLinePoint(fragment); + __pushScanLinePoint(area, fragment); fragment.x = endx; fragment.y = lround(v2.y); fragment.z = v2.z; fragment.vertex = *vertex2; - __pushScanLinePoint(fragment); + __pushScanLinePoint(area, fragment); } else { @@ -460,9 +447,9 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex* { startx = 0; } - if (endx >= render_width) + if (endx >= area->width) { - endx = render_width - 1; + endx = area->width - 1; } 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; __vertexInterpolate(vertex1, &diff, fx / dx, &(fragment.vertex)); - __pushScanLinePoint(fragment); + __pushScanLinePoint(area, fragment); } } } -static void __clearScanLines() +static void __clearScanLines(RenderArea* area) { 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; - scanline_down[x].y = render_height; + area->scanline_up[x].y = -1; + area->scanline_down[x].y = area->height; } - scanline_left = render_width; - scanline_right = -1; + area->scanline_left = area->width; + area->scanline_right = -1; } -static void __renderScanLines() +static void __renderScanLines(RenderArea* area) { int x, starty, endy, cury; Vertex diff; double dy, dz, fy; 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]; - down = scanline_down[x]; + up = area->scanline_up[x]; + down = area->scanline_down[x]; starty = down.y; endy = up.y; - if (endy < 0 || starty >= render_height) + if (endy < 0 || starty >= area->height) { continue; } @@ -529,9 +516,9 @@ static void __renderScanLines() { starty = 0; } - if (endy >= render_height) + if (endy >= area->height) { - endy = render_height - 1; + endy = area->height - 1; } dy = (double)(up.y - down.y); @@ -554,21 +541,16 @@ static void __renderScanLines() } #endif - renderAddFragment(¤t); + renderAddFragment(area, ¤t); } } } } -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)(render_width - 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); + double limit_width = (double)(area->width - 1); + double limit_height = (double)(area->height - 1); /* 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)) @@ -576,19 +558,13 @@ void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3) return; } - __clearScanLines(); - __pushScanLineEdge(p1, p2, v1, v2); - __pushScanLineEdge(p2, p3, v2, v3); - __pushScanLineEdge(p3, p1, v3, v1); - mutexAcquire(_lock); - __renderScanLines(); - mutexRelease(_lock); -} - -void renderPushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4) -{ - renderPushTriangle(renderer, v2, v3, v1); - renderPushTriangle(renderer, v4, v1, v3); + __clearScanLines(area); + __pushScanLineEdge(area, p1, p2, v1, v2); + __pushScanLineEdge(area, p2, p3, v2, v3); + __pushScanLineEdge(area, p3, p1, v3, v1); + mutexAcquire(area->lock); + __renderScanLines(area); + mutexRelease(area->lock); } typedef struct { @@ -599,6 +575,7 @@ typedef struct { int finished; int interrupt; Thread* thread; + RenderArea* area; Renderer* renderer; } RenderChunk; @@ -618,7 +595,7 @@ void* _renderPostProcessChunk(void* data) { 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; dirty = 0; 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)) { - /* TODO Store over-exposure */ colorNormalize(&fragments[i].vertex.color); dirty = 1; } @@ -635,11 +611,11 @@ void* _renderPostProcessChunk(void* data) } if (dirty) { - mutexAcquire(_lock); - _setDirtyPixel(pixel_data, x, y); - mutexRelease(_lock); + mutexAcquire(chunk->area->lock); + _setDirtyPixel(chunk->area, pixel_data, x, y); + mutexRelease(chunk->area->lock); } - _progress_pixels++; + /* chunk->area->progress_pixels++; */ } if (chunk->interrupt) { @@ -652,12 +628,13 @@ void* _renderPostProcessChunk(void* data) } #define MAX_CHUNKS 8 -void renderPostProcess(Renderer* renderer, int nbchunks) +void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks) { volatile RenderChunk chunks[MAX_CHUNKS]; int i; int x, y, dx, dy, nx, ny; int loops, running; + int _interrupt = 0; /* TEMP */ if (nbchunks > MAX_CHUNKS) { @@ -670,15 +647,16 @@ void renderPostProcess(Renderer* renderer, int nbchunks) nx = 10; ny = 10; - dx = render_width / nx; - dy = render_height / ny; + dx = area->width / nx; + dy = area->height / ny; x = 0; y = 0; - _progress_pixels = 0; + /*_progress_pixels = 0;*/ for (i = 0; i < nbchunks; i++) { chunks[i].thread = NULL; + chunks[i].area = area; chunks[i].renderer = renderer; } @@ -711,7 +689,7 @@ void renderPostProcess(Renderer* renderer, int nbchunks) chunks[i].startx = x * dx; if (x == nx) { - chunks[i].endx = render_width - 1; + chunks[i].endx = area->width - 1; } else { @@ -720,7 +698,7 @@ void renderPostProcess(Renderer* renderer, int nbchunks) chunks[i].starty = y * dy; if (y == ny) { - chunks[i].endy = render_height - 1; + chunks[i].endy = area->height - 1; } else { @@ -740,27 +718,20 @@ void renderPostProcess(Renderer* renderer, int nbchunks) if (++loops >= 10) { - mutexAcquire(_lock); - _progress = (double)_progress_pixels / (double)_pixel_count; - _processDirtyPixels(); - mutexRelease(_lock); + mutexAcquire(area->lock); + /*_progress = (double)_progress_pixels / (double)_pixel_count;*/ + _processDirtyPixels(area); + mutexRelease(area->lock); loops = 0; } } - _progress = 1.0; - _processDirtyPixels(); + /*_progress = 1.0;*/ + _processDirtyPixels(area); } -void renderUpdate() -{ - mutexAcquire(_lock); - _processDirtyPixels(); - mutexRelease(_lock); -} - -void renderSaveToFile(const char* path) +void renderSaveToFile(RenderArea* area, const char* path) { ILuint image_id; ilGenImages(1, &image_id); @@ -768,22 +739,22 @@ void renderSaveToFile(const char* path) Color result; ILuint x, y; ILuint rgba; - ILuint data[render_height * render_width]; + ILuint data[area->height * area->width]; ILenum error; 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); - result = _getPixelColor(pixel_data); + pixel_data = area->pixels + (y * area->width + x); + result = _getPixelColor(area->background_color, pixel_data); 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); 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; - _cb_preview_clear = clear ? clear : _previewClear; - _cb_preview_draw = draw ? draw : _previewDraw; - _cb_preview_update = update ? update : _previewUpdate; + area->callback_start = start ? start : _callbackStart; + area->callback_draw = draw ? draw : _callbackDraw; + area->callback_update = update ? update : _callbackUpdate; - _cb_preview_resize(render_width, render_height); - _cb_preview_clear(background_color); + area->callback_start(area->width, area->height, area->background_color); - _setAllDirty(); - _processDirtyPixels(); + _setAllDirty(area); + _processDirtyPixels(area); - _cb_preview_update(1.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; - } + area->callback_update(0.0); } diff --git a/lib_paysages/render.h b/lib_paysages/render.h index dcab63b..f55c811 100644 --- a/lib_paysages/render.h +++ b/lib_paysages/render.h @@ -10,23 +10,21 @@ extern "C" { #endif void renderInit(); -void renderSave(FILE* f); -void renderLoad(FILE* f); -void renderSetSize(int width, int height); -int renderSetQuality(int quality); -void renderClear(); -void renderUpdate(); -void renderInterrupt(); -void renderSetBackgroundColor(Color* col); -void renderAddFragment(RenderFragment* fragment); -void renderPushFragment(int x, int y, double z, Vertex* vertex); -void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3); -void renderPushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4); -void renderPostProcess(Renderer* renderer, int nbchunks); -void renderSaveToFile(const char* path); -void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClear clear, PreviewCallbackDraw draw, PreviewCallbackUpdate update); -int renderSetNextProgressStep(double start, double end); -int renderTellProgress(double progress); +RenderArea* renderCreateArea(); +void renderDeleteArea(RenderArea* area); + +void renderSetSize(RenderArea* area, int width, int height); +void renderSetBackgroundColor(RenderArea* area, Color* col); +void renderClear(RenderArea* area); +void renderUpdate(RenderArea* area); + +void renderAddFragment(RenderArea* area, RenderFragment* fragment); +void renderPushFragment(RenderArea* area, int x, int y, double z, Vertex* vertex); +void renderPushTriangle(RenderArea* area, Vertex* v1, Vertex* v2, Vertex* v3, Vector3 p1, Vector3 p2, Vector3 p3); + +void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks); +void renderSaveToFile(RenderArea* area, const char* path); +void renderSetPreviewCallbacks(RenderArea* area, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update); #ifdef __cplusplus diff --git a/lib_paysages/renderer.c b/lib_paysages/renderer.c index 69bcca0..69f1fb5 100644 --- a/lib_paysages/renderer.c +++ b/lib_paysages/renderer.c @@ -1,10 +1,59 @@ #include "renderer.h" #include "shared/constants.h" #include "lighting.h" +#include "system.h" +#include "render.h" +#include "scenery.h" RayCastingResult _RAYCASTING_NULL = {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) { return light_color; @@ -50,40 +99,88 @@ static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3 return base; } -static Vector3 _projectPoint(Renderer* renderer, Vector3 point) -{ - return point; -} - -static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point) -{ - return point; -} - -static double _getPrecision(Renderer* renderer, Vector3 location) -{ - return 0.001; -} - -Renderer rendererGetFake() +Renderer rendererCreate() { Renderer result; 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.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.getTerrainHeight = _getTerrainHeight; result.getWaterHeightInfo = _getWaterHeightInfo; result.applyTextures = _applyTextures; result.applyAtmosphere = _applyAtmosphere; result.applyClouds = _applyClouds; - result.projectPoint = _projectPoint; - result.unprojectPoint = _unprojectPoint; - result.getPrecision = _getPrecision; + + result.filterLight = _filterLight; + result.maskLight = _maskLight; + result.applyLightingToSurface = _applyLightingToSurface; 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) +{ +} diff --git a/lib_paysages/renderer.h b/lib_paysages/renderer.h index 917ce9d..6c1032f 100644 --- a/lib_paysages/renderer.h +++ b/lib_paysages/renderer.h @@ -11,14 +11,23 @@ typedef struct Renderer Renderer; struct Renderer { - /* Quality configuration */ + /* Render base configuration */ int render_quality; + int render_width; + int render_height; Vector3 camera_location; /* Render related */ + RenderArea* render_area; + double render_progress; + int render_interrupt; + int is_rendering; double (*getPrecision)(Renderer* renderer, Vector3 location); Vector3 (*projectPoint)(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 */ 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]; }; -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 } diff --git a/lib_paysages/scenery.c b/lib_paysages/scenery.c index ecd08df..48a94da 100644 --- a/lib_paysages/scenery.c +++ b/lib_paysages/scenery.c @@ -177,29 +177,21 @@ void sceneryGetWater(WaterDefinition* water) void sceneryRenderFirstPass(Renderer* renderer) { - if (!renderSetNextProgressStep(0.0, 0.01)) + /*if (!renderSetNextProgressStep(0.0, 0.01)) { return; - } - skyRender(&_sky, renderer, renderTellProgress); - if (!renderSetNextProgressStep(0.01, 0.085)) + }*/ + skyRender(&_sky, renderer); + /*if (!renderSetNextProgressStep(0.01, 0.085)) { return; - } - terrainRender(&_terrain, renderer, renderTellProgress); - if (!renderSetNextProgressStep(0.085, 0.1)) + }*/ + terrainRender(&_terrain, renderer); + /*if (!renderSetNextProgressStep(0.085, 0.1)) { return; - } - waterRender(&_water, renderer, renderTellProgress); -} - -void sceneryRenderSecondPass(Renderer* renderer) -{ - if (renderSetNextProgressStep(0.1, 1.0)) - { - renderPostProcess(renderer, systemGetCoreCount()); - } + }*/ + waterRender(&_water, renderer); } @@ -277,34 +269,32 @@ static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3 static Vector3 _projectPoint(Renderer* renderer, Vector3 point) { - return cameraProject(&_camera, point); + return cameraProject(&_camera, renderer, point); } static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point) { - return cameraUnproject(&_camera, point); + return cameraUnproject(&_camera, renderer, point); } static double _getPrecision(Renderer* renderer, Vector3 location) { Vector3 projected; - projected = cameraProject(&_camera, location); + projected = cameraProject(&_camera, renderer, location); projected.x += 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; - - quality = (quality > 10) ? 10 : quality; - quality = (quality < 1) ? 1 : quality; + + result = rendererCreate(); result.camera_location = _camera.location; - result.render_quality = quality; result.filterLight = _filterLight; result.maskLight = _maskLight; diff --git a/lib_paysages/scenery.h b/lib_paysages/scenery.h index fa44287..6b8791e 100644 --- a/lib_paysages/scenery.h +++ b/lib_paysages/scenery.h @@ -51,9 +51,8 @@ void sceneryGetTextures(TexturesDefinition* textures); void scenerySetWater(WaterDefinition* water); void sceneryGetWater(WaterDefinition* water); -Renderer sceneryGetStandardRenderer(int quality); +Renderer sceneryCreateStandardRenderer(); void sceneryRenderFirstPass(Renderer* renderer); -void sceneryRenderSecondPass(Renderer* renderer); #ifdef __cplusplus } diff --git a/lib_paysages/shared/globals.h b/lib_paysages/shared/globals.h deleted file mode 100644 index 836d4c0..0000000 --- a/lib_paysages/shared/globals.h +++ /dev/null @@ -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 diff --git a/lib_paysages/shared/types.h b/lib_paysages/shared/types.h index 49f312c..7c10f7c 100644 --- a/lib_paysages/shared/types.h +++ b/lib_paysages/shared/types.h @@ -100,11 +100,11 @@ typedef struct typedef struct Zone Zone; -typedef void (*PreviewCallbackResize)(int width, int height); -typedef void (*PreviewCallbackClear)(Color col); -typedef void (*PreviewCallbackDraw)(int x, int y, Color col); -typedef void (*PreviewCallbackUpdate)(double progress); -typedef int (*RenderProgressCallback)(double progress); +typedef void (*RenderCallbackStart)(int width, int height, Color background); +typedef void (*RenderCallbackDraw)(int x, int y, Color col); +typedef void (*RenderCallbackUpdate)(double progress); + +typedef struct RenderArea RenderArea; typedef struct { diff --git a/lib_paysages/sky.c b/lib_paysages/sky.c index 8d323c3..f8ae1a3 100644 --- a/lib_paysages/sky.c +++ b/lib_paysages/sky.c @@ -4,7 +4,6 @@ #include #include "shared/types.h" -#include "shared/globals.h" #include "shared/constants.h" #include "color.h" #include "clouds.h" @@ -182,7 +181,7 @@ static int _postProcessFragment(RenderFragment* fragment, Renderer* renderer, vo return 1; } -void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback) +void skyRender(SkyDefinition* definition, Renderer* renderer) { int res_i, res_j; int i, j; @@ -203,7 +202,7 @@ void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCall for (j = 0; j < res_j; j++) { - if (!callback((double)j / (double)(res_j - 1))) + if (!renderer->addRenderProgress(renderer, 0.0)) { return; } @@ -251,7 +250,7 @@ void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCall vertex4.callback_data = definition; /* TODO Triangles at poles */ - renderPushQuad(renderer, &vertex1, &vertex4, &vertex3, &vertex2); + renderer->pushQuad(renderer, &vertex1, &vertex4, &vertex3, &vertex2); } } } diff --git a/lib_paysages/sky.h b/lib_paysages/sky.h index 43bd11d..461b89e 100644 --- a/lib_paysages/sky.h +++ b/lib_paysages/sky.h @@ -32,7 +32,7 @@ void skyValidateDefinition(SkyDefinition* definition); int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights); 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 } diff --git a/lib_paysages/terrain.c b/lib_paysages/terrain.c index 96f91fc..c54aac8 100644 --- a/lib_paysages/terrain.c +++ b/lib_paysages/terrain.c @@ -6,7 +6,6 @@ #include #include "shared/types.h" -#include "shared/globals.h" #include "shared/constants.h" #include "euclid.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) { - 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); } -void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback) +void terrainRender(TerrainDefinition* definition, Renderer* renderer) { int chunk_factor, chunk_count, i; double cx = renderer->camera_location.x; @@ -371,7 +370,7 @@ void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProg while (radius_ext < 1000.0) { - if (!callback(radius_ext / 1000.0)) + if (!renderer->addRenderProgress(renderer, 0.0)) { return; } diff --git a/lib_paysages/terrain.h b/lib_paysages/terrain.h index b089cf1..c903164 100644 --- a/lib_paysages/terrain.h +++ b/lib_paysages/terrain.h @@ -41,7 +41,7 @@ int terrainProjectRay(TerrainDefinition* definition, Renderer* renderer, Vector3 double terrainGetHeight(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); -void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback); +void terrainRender(TerrainDefinition* definition, Renderer* renderer); #ifdef __cplusplus } diff --git a/lib_paysages/textures.c b/lib_paysages/textures.c index f88e373..ec45083 100644 --- a/lib_paysages/textures.c +++ b/lib_paysages/textures.c @@ -7,7 +7,6 @@ #include "shared/types.h" #include "shared/constants.h" -#include "shared/globals.h" #include "color.h" #include "euclid.h" #include "lighting.h" diff --git a/lib_paysages/water.c b/lib_paysages/water.c index 3f5fcdf..6fb5005 100644 --- a/lib_paysages/water.c +++ b/lib_paysages/water.c @@ -2,7 +2,6 @@ #include "shared/types.h" #include "shared/constants.h" -#include "shared/globals.h" #include "color.h" #include "euclid.h" #include "render.h" @@ -266,10 +265,10 @@ static void _renderQuad(WaterDefinition* definition, Renderer* renderer, double v2 = _getFirstPassVertex(definition, x, z + size, size); v3 = _getFirstPassVertex(definition, x + size, z + size, 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; double cx = renderer->camera_location.x; @@ -286,7 +285,7 @@ void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgress while (radius_ext < 1000.0) { - if (!callback(radius_ext / 1000.0)) + if (!renderer->addRenderProgress(renderer, 0.0)) { return; } diff --git a/lib_paysages/water.h b/lib_paysages/water.h index 857d08e..afcfb79 100644 --- a/lib_paysages/water.h +++ b/lib_paysages/water.h @@ -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); WaterResult waterGetColorDetail(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 }