From 9da260a5e839c221a2add8c04e4c764853988f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 14 Dec 2012 16:16:09 +0000 Subject: [PATCH] paysages : Cache system for bruneton precomputations. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@480 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- gui_qt/mainwindow.cpp | 14 ++- lib_paysages/atmosphere/bruneton.c | 148 ++++++++++++++++++++++------- lib_paysages/system.c | 7 +- lib_paysages/tools/cache.c | 65 +++++++++++++ lib_paysages/tools/cache.h | 24 +++++ lib_paysages/tools/texture.c | 52 +++++++++- lib_paysages/tools/texture.h | 8 ++ 7 files changed, 276 insertions(+), 42 deletions(-) create mode 100644 lib_paysages/tools/cache.c create mode 100644 lib_paysages/tools/cache.h diff --git a/gui_qt/mainwindow.cpp b/gui_qt/mainwindow.cpp index 600ec0a..02109a9 100644 --- a/gui_qt/mainwindow.cpp +++ b/gui_qt/mainwindow.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "basepreview.h" #include "formclouds.h" @@ -31,12 +32,14 @@ int main(int argc, char** argv) { MainWindow* window; + QSplashScreen* splash; int result; - paysagesInit(); - QApplication app(argc, argv); + splash = new QSplashScreen(QPixmap("images/logo_256.png")); + splash->show(); + QTranslator qtTranslator; QTranslator myTranslator; @@ -53,10 +56,17 @@ int main(int argc, char** argv) app.installTranslator(&qtTranslator); } + splash->showMessage(app.tr("Preloading environment...\n(may take some time on the first launch)"), Qt::AlignCenter, Qt::white); + app.processEvents(); + + paysagesInit(); BasePreview::initDrawers(); window = new MainWindow(); window->show(); + splash->finish(window); + + delete splash; result = app.exec(); diff --git a/lib_paysages/atmosphere/bruneton.c b/lib_paysages/atmosphere/bruneton.c index 2127600..3196917 100644 --- a/lib_paysages/atmosphere/bruneton.c +++ b/lib_paysages/atmosphere/bruneton.c @@ -8,8 +8,10 @@ #if 1 #include +#include #include #include "../system.h" +#include "../tools/cache.h" #include "../tools/texture.h" /*********************** Constants ***********************/ @@ -400,13 +402,10 @@ static void _getMuMuSNu(double x, double y, double r, Color dhdH, double* mu, do /*********************** Texture precomputing ***********************/ -static Texture2D* _precomputeTransmittanceTexture() +static void _precomputeTransmittanceTexture() { - Texture2D* result; int x, y; - result = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H); - for (x = 0; x < TRANSMITTANCE_W; x++) { for (y = 0; y < TRANSMITTANCE_H; y++) @@ -420,20 +419,15 @@ static Texture2D* _precomputeTransmittanceTexture() trans.g = exp(-(betaR.g * depth1 + betaMEx.y * depth2)); trans.b = exp(-(betaR.b * depth1 + betaMEx.z * depth2)); trans.a = 1.0; - texture2DSetPixel(result, x, y, trans); /* Eq (5) */ + texture2DSetPixel(_transmittanceTexture, x, y, trans); /* Eq (5) */ } } - - return result; } -static Texture2D* _precomputeIrrDeltaETexture() +static void _precomputeIrrDeltaETexture() { - Texture2D* result; int x, y; - result = texture2DCreate(SKY_W, SKY_H); - /* Irradiance program */ for (x = 0; x < SKY_W; x++) { @@ -452,11 +446,9 @@ static Texture2D* _precomputeIrrDeltaETexture() irr.b = trans.b * max(muS, 0.0); irr.a = 1.0; - texture2DSetPixel(result, x, y, irr); + texture2DSetPixel(_irrDeltaETexture, x, y, irr); } } - - return result; } static void _setLayer(int layer) @@ -735,31 +727,116 @@ static Color _sunColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, doub } } +/*********************** Cache methods ***********************/ + +static int _tryLoadCache2D(Texture2D* tex, const char* tag) +{ + CacheFile* cache; + int xsize, ysize; + + texture2DGetSize(tex, &xsize, &ysize); + cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0); + if (cacheFileIsReadable(cache)) + { + texture2DLoadFromFile(tex, cacheFileGetPath(cache)); + cacheFileDeleteAccessor(cache); + return 1; + } + else + { + cacheFileDeleteAccessor(cache); + return 0; + } +} + +static void _saveCache2D(Texture2D* tex, const char* tag) +{ + CacheFile* cache; + int xsize, ysize; + + texture2DGetSize(tex, &xsize, &ysize); + cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0); + if (cacheFileIsWritable(cache)) + { + texture2DSaveToFile(tex, cacheFileGetPath(cache)); + } + cacheFileDeleteAccessor(cache); +} + +static int _tryLoadCache3D(Texture3D* tex, const char* tag) +{ + CacheFile* cache; + int xsize, ysize, zsize; + + texture3DGetSize(tex, &xsize, &ysize, &zsize); + cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize); + if (cacheFileIsReadable(cache)) + { + texture3DLoadFromFile(tex, cacheFileGetPath(cache)); + cacheFileDeleteAccessor(cache); + return 1; + } + else + { + cacheFileDeleteAccessor(cache); + return 0; + } +} + +static void _saveCache3D(Texture3D* tex, const char* tag) +{ + CacheFile* cache; + int xsize, ysize, zsize; + + texture3DGetSize(tex, &xsize, &ysize, &zsize); + cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize); + if (cacheFileIsWritable(cache)) + { + texture3DSaveToFile(tex, cacheFileGetPath(cache)); + } + cacheFileDeleteAccessor(cache); +} + /*********************** Public methods ***********************/ void brunetonInit() { - int layer, x, y, z; + int layer, x, y, z, order; if (_transmittanceTexture == NULL) /* TEMP */ { - /* TODO Deletes */ + /* TODO Deletes */ - /* computes transmittance texture T (line 1 in algorithm 4.1) */ - _transmittanceTexture = _precomputeTransmittanceTexture(); + /* computes transmittance texture T (line 1 in algorithm 4.1) */ + _transmittanceTexture = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H); + if (!_tryLoadCache2D(_transmittanceTexture, "transmittance")) + { + _precomputeTransmittanceTexture(); + _saveCache2D(_transmittanceTexture, "transmittance"); + } /* computes irradiance texture deltaE (line 2 in algorithm 4.1) */ - _irrDeltaETexture = _precomputeIrrDeltaETexture(); + _irrDeltaETexture = texture2DCreate(SKY_W, SKY_H); + if (!_tryLoadCache2D(_irrDeltaETexture, "irradianceDeltaE")) + { + _precomputeIrrDeltaETexture(); + _saveCache2D(_irrDeltaETexture, "irradianceDeltaE"); + } /* computes single scattering texture deltaS (line 3 in algorithm 4.1) * Rayleigh and Mie separated in deltaSR + deltaSM */ _deltaSRTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); _deltaSMTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); - for (layer = 0; layer < RES_R; ++layer) + if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR") || !_tryLoadCache3D(_deltaSMTexture, "deltaSM")) { - printf("%d\n", layer); - _setLayer(layer); - _inscatter1Prog(_deltaSRTexture, _deltaSMTexture); + for (layer = 0; layer < RES_R; ++layer) + { + printf("%d\n", layer); + _setLayer(layer); + _inscatter1Prog(_deltaSRTexture, _deltaSMTexture); + } + _saveCache3D(_deltaSRTexture, "deltaSR"); + _saveCache3D(_deltaSMTexture, "deltaSM"); } /* copies deltaE into irradiance texture E (line 4 in algorithm 4.1) */ @@ -769,22 +846,26 @@ void brunetonInit() /* copies deltaS into inscatter texture S (line 5 in algorithm 4.1) */ _inscatterTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); - for (x = 0; x < RES_MU_S * RES_NU; x++) + if (!_tryLoadCache3D(_inscatterTexture, "inscatter")) { - for (y = 0; y < RES_MU; y++) + for (x = 0; x < RES_MU_S * RES_NU; x++) { - for (z = 0; z < RES_R; z++) + for (y = 0; y < RES_MU; y++) { - Color result = texture3DGetPixel(_deltaSRTexture, x, y, z); - Color mie = texture3DGetPixel(_deltaSMTexture, x, y, z); - result.a = mie.r; - texture3DSetPixel(_inscatterTexture, x, y, z, result); + for (z = 0; z < RES_R; z++) + { + Color result = texture3DGetPixel(_deltaSRTexture, x, y, z); + Color mie = texture3DGetPixel(_deltaSMTexture, x, y, z); + result.a = mie.r; + texture3DSetPixel(_inscatterTexture, x, y, z, result); + } } } + _saveCache3D(_inscatterTexture, "inscatter"); } /* loop for each scattering order (line 6 in algorithm 4.1) */ - for (int order = 2; order <= 4; ++order) { + for (order = 2; order <= 4; ++order) { /* computes deltaJ (line 7 in algorithm 4.1) */ /*glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, deltaJTexture, 0); @@ -848,11 +929,6 @@ void brunetonInit() } /* DEBUG */ - texture2DSaveToFile(_transmittanceTexture, "transmittance.png"); - texture2DSaveToFile(_irrDeltaETexture, "irrdeltae.png"); - texture3DSaveToFile(_deltaSRTexture, "deltasr.png"); - texture3DSaveToFile(_deltaSMTexture, "deltasm.png"); - texture3DSaveToFile(_inscatterTexture, "inscatter.png"); exit(1); } diff --git a/lib_paysages/system.c b/lib_paysages/system.c index 03b8314..79d350a 100644 --- a/lib_paysages/system.c +++ b/lib_paysages/system.c @@ -56,6 +56,8 @@ void systemInit() _core_count = _getCoreCount(); ilInit(); iluInit(); + ilOriginFunc(IL_ORIGIN_LOWER_LEFT); + ilEnable(IL_ORIGIN_SET); } int systemGetCoreCount() @@ -117,7 +119,10 @@ int systemLoadPictureFile(const char* filepath, PictureCallbackLoadStarted callb { width = ilGetInteger(IL_IMAGE_WIDTH); height = ilGetInteger(IL_IMAGE_HEIGHT); - callback_start(data, width, height); + if (callback_start) + { + callback_start(data, width, height); + } pixels = malloc(sizeof(ILuint) * width * height); ilCopyPixels(0, 0, 0, width, height, 1, IL_RGBA, IL_UNSIGNED_BYTE, pixels); diff --git a/lib_paysages/tools/cache.c b/lib_paysages/tools/cache.c new file mode 100644 index 0000000..16e24ab --- /dev/null +++ b/lib_paysages/tools/cache.c @@ -0,0 +1,65 @@ +#include + +#include "cache.h" + +#include +#include +#include "../tools.h" + +struct CacheFile +{ + char* filepath; +}; + +CacheFile* cacheFileCreateAccessor(const char* module, const char* ext, const char* tag1, int tag2, int tag3, int tag4) +{ + CacheFile* result; + + result = (CacheFile*)malloc(sizeof(CacheFile)); + result->filepath = malloc(sizeof(char) * 501); + + snprintf(result->filepath, 500, "./cache/%s-%s-%d-%d-%d.%s", module, tag1, tag2, tag3, tag4, ext); + + return result; +} + +void cacheFileDeleteAccessor(CacheFile* cache) +{ + free(cache->filepath); + free(cache); +} + +int cacheFileIsReadable(CacheFile* cache) +{ + FILE* f = fopen(cache->filepath, "rb"); + if (f) + { + fclose(f); + return 1; + } + else + { + return 0; + } +} + +int cacheFileIsWritable(CacheFile* cache) +{ + UNUSED(cache); + + FILE* f = fopen("./cache/.test", "wb"); + if (f) + { + fclose(f); + return 1; + } + else + { + return 0; + } +} + +const char* cacheFileGetPath(CacheFile* cache) +{ + return cache->filepath; +} diff --git a/lib_paysages/tools/cache.h b/lib_paysages/tools/cache.h new file mode 100644 index 0000000..7d7439c --- /dev/null +++ b/lib_paysages/tools/cache.h @@ -0,0 +1,24 @@ +#ifndef _PAYSAGES_TOOLS_CACHE_H_ +#define _PAYSAGES_TOOLS_CACHE_H_ + +/* + * Cache management. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CacheFile CacheFile; + +CacheFile* cacheFileCreateAccessor(const char* module, const char* ext, const char* tag1, int tag2, int tag3, int tag4); +void cacheFileDeleteAccessor(CacheFile* cache); +int cacheFileIsReadable(CacheFile* cache); +int cacheFileIsWritable(CacheFile* cache); +const char* cacheFileGetPath(CacheFile* cache); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib_paysages/tools/texture.c b/lib_paysages/tools/texture.c index 0c00ade..380fb9e 100644 --- a/lib_paysages/tools/texture.c +++ b/lib_paysages/tools/texture.c @@ -26,6 +26,8 @@ Texture2D* texture2DCreate(int xsize, int ysize) { Texture2D* result; + assert(xsize > 0 && ysize > 0); + result = (Texture2D*)malloc(sizeof(Texture2D)); result->xsize = xsize; result->ysize = ysize; @@ -40,6 +42,12 @@ void texture2DDelete(Texture2D* tex) free(tex); } +void texture2DGetSize(Texture2D* tex, int* xsize, int* ysize) +{ + *xsize = tex->xsize; + *ysize = tex->ysize; +} + void texture2DSetPixel(Texture2D* tex, int x, int y, Color col) { assert(x >= 0 && x < tex->xsize); @@ -89,6 +97,19 @@ void texture2DSaveToFile(Texture2D* tex, const char* filepath) systemSavePictureFile(filepath, (PictureCallbackSavePixel)texture2DGetPixel, tex, tex->xsize, tex->ysize); } +static void _callbackTex2dLoad(Texture2D* tex, int x, int y, Color col) +{ + if (x >= 0 && x < tex->xsize && y >= 0 && y < tex->ysize) + { + tex->data[y * tex->xsize + x] = col; + } +} + +void texture2DLoadFromFile(Texture2D* tex, const char* filepath) +{ + systemLoadPictureFile(filepath, NULL, (PictureCallbackLoadPixel)_callbackTex2dLoad, tex); +} + @@ -96,6 +117,8 @@ Texture3D* texture3DCreate(int xsize, int ysize, int zsize) { Texture3D* result; + assert(xsize > 0 && ysize > 0 && zsize > 0); + result = (Texture3D*)malloc(sizeof(Texture3D)); result->xsize = xsize; result->ysize = ysize; @@ -111,6 +134,13 @@ void texture3DDelete(Texture3D* tex) free(tex); } +void texture3DGetSize(Texture3D* tex, int* xsize, int* ysize, int* zsize) +{ + *xsize = tex->xsize; + *ysize = tex->ysize; + *zsize = tex->zsize; +} + void texture3DSetPixel(Texture3D* tex, int x, int y, int z, Color col) { assert(x >= 0 && x < tex->xsize); @@ -167,9 +197,9 @@ static Color _callbackTex3dSave(Texture3D* tex, int x, int y) y = y % tex->ysize; assert(x >= 0 && x < tex->xsize); - assert(y >= 0 && y < tex->xsize); - assert(z >= 0 && z < tex->xsize); - + assert(y >= 0 && y < tex->ysize); + assert(z >= 0 && z < tex->zsize); + return tex->data[z * tex->xsize * tex->ysize + y * tex->xsize + x]; } @@ -177,3 +207,19 @@ void texture3DSaveToFile(Texture3D* tex, const char* filepath) { systemSavePictureFile(filepath, (PictureCallbackSavePixel)_callbackTex3dSave, tex, tex->xsize, tex->ysize * tex->zsize); } + +static void _callbackTex3dLoad(Texture3D* tex, int x, int y, Color col) +{ + int z = y / tex->ysize; + y = y % tex->ysize; + + if (x >= 0 && x < tex->xsize && y >= 0 && y < tex->ysize && z >= 0 && z < tex->zsize) + { + tex->data[z * tex->xsize * tex->ysize + y * tex->xsize + x] = col; + } +} + +void texture3DLoadFromFile(Texture3D* tex, const char* filepath) +{ + systemLoadPictureFile(filepath, NULL, (PictureCallbackLoadPixel)_callbackTex3dLoad, tex); +} diff --git a/lib_paysages/tools/texture.h b/lib_paysages/tools/texture.h index 4e0d8f7..3860433 100644 --- a/lib_paysages/tools/texture.h +++ b/lib_paysages/tools/texture.h @@ -1,6 +1,10 @@ #ifndef _PAYSAGES_TOOLS_TEXTURE_H_ #define _PAYSAGES_TOOLS_TEXTURE_H_ +/* + * Pixel based textures. + */ + #ifdef __cplusplus extern "C" { #endif @@ -12,21 +16,25 @@ typedef struct Texture3D Texture3D; Texture2D* texture2DCreate(int xsize, int ysize); void texture2DDelete(Texture2D* tex); +void texture2DGetSize(Texture2D* tex, int* xsize, int* ysize); void texture2DSetPixel(Texture2D* tex, int x, int y, Color col); Color texture2DGetPixel(Texture2D* tex, int x, int y); Color texture2DGetNearest(Texture2D* tex, double dx, double dy); Color texture2DGetLinear(Texture2D* tex, double dx, double dy); Color texture2DGetCubic(Texture2D* tex, double dx, double dy); void texture2DSaveToFile(Texture2D* tex, const char* filepath); +void texture2DLoadFromFile(Texture2D* tex, const char* filepath); Texture3D* texture3DCreate(int xsize, int ysize, int zsize); void texture3DDelete(Texture3D* tex); +void texture3DGetSize(Texture3D* tex, int* xsize, int* ysize, int* zsize); void texture3DSetPixel(Texture3D* tex, int x, int y, int z, Color col); Color texture3DGetPixel(Texture3D* tex, int x, int y, int z); Color texture3DGetNearest(Texture3D* tex, double dx, double dy, double dz); Color texture3DGetLinear(Texture3D* tex, double dx, double dy, double dz); Color texture3DGetCubic(Texture3D* tex, double dx, double dy, double dz); void texture3DSaveToFile(Texture3D* tex, const char* filepath); +void texture3DLoadFromFile(Texture3D* tex, const char* filepath); #ifdef __cplusplus }