From 4a6721e2ff9534a16fecbd201082b73e2ee1912b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 24 Dec 2012 11:24:27 +0000 Subject: [PATCH] paysages : Progress on bruneton atmospheric model (WIP) + fixed terrain issue. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@485 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- lib_paysages/atmosphere/bruneton.c | 392 +++++++++++++++++------------ lib_paysages/atmosphere/main.c | 3 + lib_paysages/atmosphere/private.h | 1 + lib_paysages/pack.c | 20 +- lib_paysages/pack.h | 6 +- lib_paysages/terrain/main.c | 4 + lib_paysages/tools/texture.c | 52 ++++ lib_paysages/tools/texture.h | 5 + 8 files changed, 315 insertions(+), 168 deletions(-) diff --git a/lib_paysages/atmosphere/bruneton.c b/lib_paysages/atmosphere/bruneton.c index f7a6267..96d9f6f 100644 --- a/lib_paysages/atmosphere/bruneton.c +++ b/lib_paysages/atmosphere/bruneton.c @@ -5,6 +5,7 @@ * http://evasion.inrialpes.fr/~Eric.Bruneton/ */ +#include #include #include #include @@ -13,6 +14,7 @@ #include "../tools/cache.h" #include "../tools/texture.h" #include "../tools/parallel.h" +#include "../renderer.h" /*********************** Constants ***********************/ @@ -52,12 +54,8 @@ static const double AVERAGE_GROUND_REFLECTANCE = 0.1; #endif Texture2D* _transmittanceTexture = NULL; -Texture2D* _deltaETexture = NULL; Texture2D* _irradianceTexture = NULL; Texture3D* _inscatterTexture = NULL; -Texture3D* _deltaSMTexture = NULL; -Texture3D* _deltaSRTexture = NULL; -Texture3D* _deltaJTexture = NULL; // Rayleigh static const double HR = 8.0; @@ -402,7 +400,7 @@ static void _precomputeTransmittanceTexture() } } -static void _precomputeIrrDeltaETexture() +static void _precomputeIrrDeltaETexture(Texture2D* destination) { int x, y; @@ -423,7 +421,7 @@ static void _precomputeIrrDeltaETexture() irr.b = trans.b * max(muS, 0.0); irr.a = 1.0; - texture2DSetPixel(_deltaETexture, x, y, irr); + texture2DSetPixel(destination, x, y, irr); } } } @@ -544,7 +542,7 @@ static int _inscatter1Worker(ParallelWork* work, int layer, void* data) /*********************** inscatterS.glsl ***********************/ -static Color _inscatterS(double r, double mu, double muS, double nu, int first) +static Color _inscatterS(double r, double mu, double muS, double nu, int first, Texture2D* deltaE, Texture3D* deltaSR, Texture3D* deltaSM) { Color raymie = COLOR_BLACK; @@ -599,7 +597,7 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first) gnormal.x = dground * w.x / Rg; gnormal.y = dground * w.y / Rg; gnormal.z = r + dground * w.z / Rg; - Color girradiance = _irradiance(_deltaETexture, Rg, v3Dot(gnormal, s)); + Color girradiance = _irradiance(deltaE, Rg, v3Dot(gnormal, s)); Color raymie1; /* light arriving at x from direction w */ @@ -615,15 +613,15 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first) * without the phase functions factors; they must be reintroduced here */ double pr1 = _phaseFunctionR(nu1); double pm1 = _phaseFunctionM(nu1); - Color ray1 = _texture4D(_deltaSRTexture, r, w.z, muS, nu1); - Color mie1 = _texture4D(_deltaSMTexture, r, w.z, muS, nu1); + Color ray1 = _texture4D(deltaSR, r, w.z, muS, nu1); + Color mie1 = _texture4D(deltaSM, r, w.z, muS, nu1); raymie1.r += ray1.r * pr1 + mie1.r + pm1; raymie1.g += ray1.g * pr1 + mie1.g + pm1; raymie1.b += ray1.b * pr1 + mie1.b + pm1; } else { - Color col = _texture4D(_deltaSRTexture, r, w.z, muS, nu1); + Color col = _texture4D(deltaSR, r, w.z, muS, nu1); raymie1.r += col.r; raymie1.g += col.g; raymie1.b += col.b; @@ -645,6 +643,9 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first) typedef struct { Texture3D* result; + Texture2D* deltaE; + Texture3D* deltaSR; + Texture3D* deltaSM; int first; } jParams; @@ -665,7 +666,7 @@ static int _jWorker(ParallelWork* work, int layer, void* data) Color raymie; double mu, muS, nu; _getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu); - raymie = _inscatterS(r, mu, muS, nu, params->first); + raymie = _inscatterS(r, mu, muS, nu, params->first, params->deltaE, params->deltaSR, params->deltaSM); texture3DSetPixel(params->result, x, y, layer, raymie); } } @@ -674,7 +675,7 @@ static int _jWorker(ParallelWork* work, int layer, void* data) /*********************** irradianceN.glsl ***********************/ -void _irradianceNProg(Texture2D* tex, int first) +void _irradianceNProg(Texture2D* destination, Texture3D* deltaSR, Texture3D* deltaSM, int first) { int x, y; double dphi = M_PI / (double)(IRRADIANCE_INTEGRAL_SAMPLES); @@ -706,15 +707,15 @@ void _irradianceNProg(Texture2D* tex, int first) without the phase functions factors; they must be reintroduced here */ double pr1 = _phaseFunctionR(nu); double pm1 = _phaseFunctionM(nu); - Color ray1 = _texture4D(_deltaSRTexture, r, w.z, muS, nu); - Color mie1 = _texture4D(_deltaSMTexture, r, w.z, muS, nu); + Color ray1 = _texture4D(deltaSR, r, w.z, muS, nu); + Color mie1 = _texture4D(deltaSM, r, w.z, muS, nu); result.r += (ray1.r * pr1 + mie1.r * pm1) * w.z * dw; result.g += (ray1.g * pr1 + mie1.g * pm1) * w.z * dw; result.b += (ray1.b * pr1 + mie1.b * pm1) * w.z * dw; } else { - Color col = _texture4D(_deltaSRTexture, r, w.z, muS, nu); + Color col = _texture4D(deltaSR, r, w.z, muS, nu); result.r += col.r * w.z * dw; result.g += col.g * w.z * dw; result.b += col.b * w.z * dw; @@ -722,20 +723,26 @@ void _irradianceNProg(Texture2D* tex, int first) } } - texture2DSetPixel(tex, x, y, result); + texture2DSetPixel(destination, x, y, result); } } } /*********************** inscatterN.glsl ***********************/ -static Color _integrand2(double r, double mu, double muS, double nu, double t) +typedef struct +{ + Texture3D* destination; + Texture3D* deltaJ; +} InscatterNParams; + +static Color _integrand2(Texture3D* deltaJ, double r, double mu, double muS, double nu, double t) { double ri = sqrt(r * r + t * t + 2.0 * r * mu * t); double mui = (r * mu + t) / ri; double muSi = (nu * t + muS * r) / ri; Color c1, c2; - c1 = _texture4D(_deltaJTexture, ri, mui, muSi, nu); + c1 = _texture4D(deltaJ, ri, mui, muSi, nu); c2 = _transmittance3(r, mu, t); c1.r *= c2.r; c1.g *= c2.g; @@ -743,16 +750,16 @@ static Color _integrand2(double r, double mu, double muS, double nu, double t) return c1; } -static Color _inscatterN(double r, double mu, double muS, double nu) +static Color _inscatterN(Texture3D* deltaJ, double r, double mu, double muS, double nu) { Color raymie = COLOR_BLACK; double dx = _limit(r, mu) / (double)(INSCATTER_INTEGRAL_SAMPLES); - Color raymiei = _integrand2(r, mu, muS, nu, 0.0); + Color raymiei = _integrand2(deltaJ, r, mu, muS, nu, 0.0); int i; for (i = 1; i <= INSCATTER_INTEGRAL_SAMPLES; ++i) { double xj = (double)(i) * dx; - Color raymiej = _integrand2(r, mu, muS, nu, xj); + Color raymiej = _integrand2(deltaJ, r, mu, muS, nu, xj); raymie.r += (raymiei.r + raymiej.r) / 2.0 * dx; raymie.g += (raymiei.r + raymiej.r) / 2.0 * dx; raymie.b += (raymiei.r + raymiej.r) / 2.0 * dx; @@ -765,6 +772,8 @@ static int _inscatterNWorker(ParallelWork* work, int layer, void* data) { UNUSED(work); + InscatterNParams* params = data; + double r; Color dhdH; _getLayerParams(layer, &r, &dhdH); @@ -776,7 +785,7 @@ static int _inscatterNWorker(ParallelWork* work, int layer, void* data) { double mu, muS, nu; _getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu); - texture3DSetPixel((Texture3D*)data, x, y, layer, _inscatterN(r, mu, muS, nu)); + texture3DSetPixel(params->destination, x, y, layer, _inscatterN(params->deltaJ, r, mu, muS, nu)); } } return 1; @@ -808,10 +817,9 @@ static int _copyInscatterNWorker(ParallelWork* work, int layer, void* data) _getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu); Color col1 = texture3DGetLinear(params->source, x / (double)(RES_MU_S * RES_NU), y / (double)(RES_MU), layer + 0.5 / (double)(RES_R)); Color col2 = texture3DGetPixel(params->destination, x, y, layer); - col2.r += col1.r * 0.1 / _phaseFunctionR(nu); - col2.g += col1.g * 0.1 / _phaseFunctionR(nu); - col2.b += col1.b * 0.1 / _phaseFunctionR(nu); - col2.a = 1.0; + col2.r += col1.r / _phaseFunctionR(nu); + col2.g += col1.g / _phaseFunctionR(nu); + col2.b += col1.b / _phaseFunctionR(nu); texture3DSetPixel(params->destination, x, y, layer, col2); } } @@ -923,54 +931,53 @@ static Color _getInscatterColor(Vector3* _x, double* _t, Vector3 v, Vector3 s, d /*ground radiance at end of ray x+tv, when sun in direction s *attenuated bewteen ground and viewer (=R[L0]+R[L*]) */ -/*static Color _groundColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, double mu, Color attenuation) +static Color _groundColor(Color base, Vector3 x, double t, Vector3 v, Vector3 s, double r, double mu, Vector3 attenuation) { Color result; - if (t > 0.0) - { // if ray hits ground surface - // ground reflectance at end of ray, x0 - Vector3 x0 = v3Add(x, v3Scale(v, t)); - float r0 = v3Norm(x0); - Vector3 n = v3Scale(x0, 1.0 / r0); - vec2 coords = vec2(atan(n.y, n.x), acos(n.z)) * vec2(0.5, 1.0) / M_PI + vec2(0.5, 0.0); - Color reflectance; - if (r0 > Rg + 0.01) - { - reflectance = vec4(0.4, 0.4, 0.4, 0.0); - } - else - { - reflectance = texture2D(reflectanceSampler, coords) * vec4(0.2, 0.2, 0.2, 1.0); - } - - // direct sun light (radiance) reaching x0 - float muS = v3Dot(n, s); - Color sunLight = _transmittanceWithShadow(r0, muS); - - // precomputed sky light (irradiance) (=E[L*]) at x0 - Color groundSkyLight = irradiance(irradianceSampler, r0, muS); - - // light reflected at x0 (=(R[L0]+R[L*])/T(x,x0)) - Color groundColor = reflectance.rgb * (max(muS, 0.0) * sunLight + groundSkyLight) * ISun / M_PI; - - // water specular color due to sunLight - if (reflectance.w > 0.0) - { - vec3 h = normalize(s - v); - float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0); - float waterBrdf = fresnel * pow(max(dot(h, n), 0.0), 150.0); - groundColor += reflectance.w * max(waterBrdf, 0.0) * sunLight * ISun; - } - - result = attenuation * groundColor; //=R[L0]+R[L*] +#if 0 + // ground reflectance at end of ray, x0 + Vector3 x0 = v3Add(x, v3Scale(v, t)); + float r0 = v3Norm(x0); + Vector3 n = v3Scale(x0, 1.0 / r0); + vec2 coords = vec2(atan(n.y, n.x), acos(n.z)) * vec2(0.5, 1.0) / M_PI + vec2(0.5, 0.0); + Color reflectance; + if (r0 > Rg + 0.01) + { + reflectance = vec4(0.4, 0.4, 0.4, 0.0); } else - { // ray looking at the sky - return COLOR_BLACK; + { + reflectance = texture2D(reflectanceSampler, coords) * vec4(0.2, 0.2, 0.2, 1.0); } + + // direct sun light (radiance) reaching x0 + float muS = v3Dot(n, s); + Color sunLight = _transmittanceWithShadow(r0, muS); + + // precomputed sky light (irradiance) (=E[L*]) at x0 + Color groundSkyLight = irradiance(irradianceSampler, r0, muS); + + // light reflected at x0 (=(R[L0]+R[L*])/T(x,x0)) + Color groundColor = reflectance.rgb * (max(muS, 0.0) * sunLight + groundSkyLight) * ISun / M_PI; + + // water specular color due to sunLight + if (reflectance.w > 0.0) + { + vec3 h = normalize(s - v); + float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0); + float waterBrdf = fresnel * pow(max(dot(h, n), 0.0), 150.0); + groundColor += reflectance.w * max(waterBrdf, 0.0) * sunLight * ISun; + } +#endif + + result.r = attenuation.x * base.r; //=R[L0]+R[L*] + result.g = attenuation.y * base.g; + result.b = attenuation.z * base.b; + result.a = 1.0; + return result; -}*/ +} /* direct sun light for ray x+tv, when sun in direction s (=L0) */ static Color _sunColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, double mu) @@ -991,7 +998,7 @@ static Color _sunColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, doub } } -/*********************** Cache methods ***********************/ +/*********************** Cache/debug methods ***********************/ static int _tryLoadCache2D(Texture2D* tex, const char* tag, int order) { @@ -999,10 +1006,14 @@ static int _tryLoadCache2D(Texture2D* tex, const char* tag, int order) int xsize, ysize; texture2DGetSize(tex, &xsize, &ysize); - cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order); + cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, 0, order); if (cacheFileIsReadable(cache)) { - texture2DLoadFromFile(tex, cacheFileGetPath(cache)); + PackStream* stream; + stream = packReadFile(cacheFileGetPath(cache)); + texture2DLoad(stream, tex); + packCloseStream(stream); + cacheFileDeleteAccessor(cache); return 1; } @@ -1018,6 +1029,23 @@ static void _saveCache2D(Texture2D* tex, const char* tag, int order) CacheFile* cache; int xsize, ysize; + texture2DGetSize(tex, &xsize, &ysize); + cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, 0, order); + if (cacheFileIsWritable(cache)) + { + PackStream* stream; + stream = packWriteFile(cacheFileGetPath(cache)); + texture2DSave(stream, tex); + packCloseStream(stream); + } + cacheFileDeleteAccessor(cache); +} + +static void _saveDebug2D(Texture2D* tex, const char* tag, int order) +{ + CacheFile* cache; + int xsize, ysize; + texture2DGetSize(tex, &xsize, &ysize); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order); if (cacheFileIsWritable(cache)) @@ -1033,10 +1061,14 @@ static int _tryLoadCache3D(Texture3D* tex, const char* tag, int order) int xsize, ysize, zsize; texture3DGetSize(tex, &xsize, &ysize, &zsize); - cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order); + cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, zsize, order); if (cacheFileIsReadable(cache)) { - texture3DLoadFromFile(tex, cacheFileGetPath(cache)); + PackStream* stream; + stream = packReadFile(cacheFileGetPath(cache)); + texture3DLoad(stream, tex); + packCloseStream(stream); + cacheFileDeleteAccessor(cache); return 1; } @@ -1052,6 +1084,23 @@ static void _saveCache3D(Texture3D* tex, const char* tag, int order) CacheFile* cache; int xsize, ysize, zsize; + texture3DGetSize(tex, &xsize, &ysize, &zsize); + cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, zsize, order); + if (cacheFileIsWritable(cache)) + { + PackStream* stream; + stream = packWriteFile(cacheFileGetPath(cache)); + texture3DSave(stream, tex); + packCloseStream(stream); + } + cacheFileDeleteAccessor(cache); +} + +static void _saveDebug3D(Texture3D* tex, const char* tag, int order) +{ + CacheFile* cache; + int xsize, ysize, zsize; + texture3DGetSize(tex, &xsize, &ysize, &zsize); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order); if (cacheFileIsWritable(cache)) @@ -1067,115 +1116,104 @@ void brunetonInit() int x, y, z, order; ParallelWork* work; + assert(_inscatterTexture == NULL); + /* TODO Deletes */ + _transmittanceTexture = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H); + _irradianceTexture = texture2DCreate(SKY_W, SKY_H); + _inscatterTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); + + /* try loading from cache */ + if (_tryLoadCache2D(_transmittanceTexture, "transmittance", 0) + && _tryLoadCache2D(_irradianceTexture, "irradiance", 0) + && _tryLoadCache3D(_inscatterTexture, "inscatter", 0)) + { + return; + } + + Texture2D* _deltaETexture = texture2DCreate(SKY_W, SKY_H); + Texture3D* _deltaSMTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); + Texture3D* _deltaSRTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); + Texture3D* _deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); /* computes transmittance texture T (line 1 in algorithm 4.1) */ - _transmittanceTexture = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H); - if (!_tryLoadCache2D(_transmittanceTexture, "transmittance", 0)) - { - _precomputeTransmittanceTexture(); - _saveCache2D(_transmittanceTexture, "transmittance", 0); - } + _precomputeTransmittanceTexture(); + _saveDebug2D(_transmittanceTexture, "transmittance", 0); /* computes irradiance texture deltaE (line 2 in algorithm 4.1) */ - _deltaETexture = texture2DCreate(SKY_W, SKY_H); - if (!_tryLoadCache2D(_deltaETexture, "deltaE", 0)) - { - _precomputeIrrDeltaETexture(); - _saveCache2D(_deltaETexture, "deltaE", 0); - } + _precomputeIrrDeltaETexture(_deltaETexture); + _saveDebug2D(_deltaETexture, "deltaE", 0); /* 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); - if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", 0) || !_tryLoadCache3D(_deltaSMTexture, "deltaSM", 0)) - { - Inscatter1Params params = {_deltaSRTexture, _deltaSMTexture}; - work = parallelWorkCreate(_inscatter1Worker, RES_R, ¶ms); - parallelWorkPerform(work, -1); - parallelWorkDelete(work); - - _saveCache3D(_deltaSRTexture, "deltaSR", 0); - _saveCache3D(_deltaSMTexture, "deltaSM", 0); - } + Inscatter1Params params = {_deltaSRTexture, _deltaSMTexture}; + work = parallelWorkCreate(_inscatter1Worker, RES_R, ¶ms); + parallelWorkPerform(work, -1); + parallelWorkDelete(work); + _saveDebug3D(_deltaSRTexture, "deltaSR", 0); + _saveDebug3D(_deltaSMTexture, "deltaSM", 0); /* copies deltaE into irradiance texture E (line 4 in algorithm 4.1) */ /* ??? all black texture (k=0.0) ??? */ - _irradianceTexture = texture2DCreate(SKY_W, SKY_H); texture2DFill(_irradianceTexture, COLOR_BLACK); /* copies deltaS into inscatter texture S (line 5 in algorithm 4.1) */ - _inscatterTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); - if (!_tryLoadCache3D(_inscatterTexture, "inscatter", 0)) + for (x = 0; x < RES_MU_S * RES_NU; x++) { - for (x = 0; x < RES_MU_S * RES_NU; x++) + for (y = 0; y < RES_MU; y++) { - for (y = 0; y < RES_MU; y++) + for (z = 0; z < RES_R; z++) { - 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); - } + 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", 0); } + _saveDebug3D(_inscatterTexture, "inscatter", 0); /* loop for each scattering order (line 6 in algorithm 4.1) */ for (order = 2; order <= 4; ++order) { /* computes deltaJ (line 7 in algorithm 4.1) */ - _deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); - if (!_tryLoadCache3D(_deltaJTexture, "deltaJ", order)) - { - jParams params = {_deltaJTexture, order == 2}; - work = parallelWorkCreate(_jWorker, RES_R, ¶ms); - parallelWorkPerform(work, -1); - parallelWorkDelete(work); - - _saveCache3D(_deltaJTexture, "deltaJ", order); - } + jParams jparams = {_deltaJTexture, _deltaETexture, _deltaSRTexture, _deltaSMTexture, order == 2}; + work = parallelWorkCreate(_jWorker, RES_R, &jparams); + parallelWorkPerform(work, -1); + parallelWorkDelete(work); + _saveDebug3D(_deltaJTexture, "deltaJ", order); /* computes deltaE (line 8 in algorithm 4.1) */ - _deltaETexture = texture2DCreate(SKY_W, SKY_H); - if (!_tryLoadCache2D(_deltaETexture, "deltaE", order)) - { - _irradianceNProg(_deltaETexture, order == 2); - _saveCache2D(_deltaETexture, "deltaE", order); - } + _irradianceNProg(_deltaETexture, _deltaSRTexture, _deltaSMTexture, order == 2); + _saveDebug2D(_deltaETexture, "deltaE", order); /* computes deltaS (line 9 in algorithm 4.1) */ - if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", order)) - { - work = parallelWorkCreate(_inscatterNWorker, RES_R, _deltaSRTexture); - parallelWorkPerform(work, -1); - parallelWorkDelete(work); - - _saveCache3D(_deltaSRTexture, "deltaSR", order); - } + InscatterNParams iparams = {_deltaSRTexture, _deltaJTexture}; + work = parallelWorkCreate(_inscatterNWorker, RES_R, &iparams); + parallelWorkPerform(work, -1); + parallelWorkDelete(work); + _saveDebug3D(_deltaSRTexture, "deltaSR", order); /* adds deltaE into irradiance texture E (line 10 in algorithm 4.1) */ - if (!_tryLoadCache2D(_irradianceTexture, "irradiance", order)) - { - texture2DAdd(_deltaETexture, _irradianceTexture); - _saveCache2D(_irradianceTexture, "irradiance", order); - } + texture2DAdd(_deltaETexture, _irradianceTexture); + _saveDebug2D(_irradianceTexture, "irradiance", order); /* adds deltaS into inscatter texture S (line 11 in algorithm 4.1) */ - if (!_tryLoadCache3D(_inscatterTexture, "inscatter", order)) - { - CopyInscatterNParams params = {_deltaSRTexture, _inscatterTexture}; - work = parallelWorkCreate(_copyInscatterNWorker, RES_R, ¶ms); - parallelWorkPerform(work, -1); - parallelWorkDelete(work); - - _saveCache3D(_inscatterTexture, "inscatter", order); - } + CopyInscatterNParams cparams = {_deltaSRTexture, _inscatterTexture}; + work = parallelWorkCreate(_copyInscatterNWorker, RES_R, &cparams); + parallelWorkPerform(work, -1); + parallelWorkDelete(work); + _saveDebug3D(_inscatterTexture, "inscatter", order); } + + _saveCache2D(_transmittanceTexture, "transmittance", 0); + _saveCache2D(_irradianceTexture, "irradiance", 0); + _saveCache3D(_inscatterTexture, "inscatter", 0); + + texture2DDelete(_deltaETexture); + texture3DDelete(_deltaSMTexture); + texture3DDelete(_deltaSRTexture); + texture3DDelete(_deltaJTexture); } static inline void _fixVector(Vector3* v) @@ -1188,12 +1226,12 @@ static inline void _fixVector(Vector3* v) Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position) { - Vector3 x = {0.0, Rg + eye.y, 0.0}; + Vector3 x = {0.0, Rg + (eye.y + 20.0) * 0.1, 0.0}; _fixVector(&x); Vector3 v = v3Normalize(direction); _fixVector(&v); - Vector3 s = v3Normalize(v3Sub(sun_position, eye)); - _fixVector(&s); + _fixVector(&sun_position); + Vector3 s = v3Normalize(v3Sub(sun_position, x)); double r = v3Norm(x); double mu = v3Dot(x, v) / r; @@ -1220,9 +1258,53 @@ Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 } Vector3 attenuation; - Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); //S[L]-T(x,xs)S[l]|xs - /*Color groundColor = _groundColor(x, t, v, s, r, mu, attenuation); //R[L0]+R[L*]*/ + Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */ Color groundColor = COLOR_BLACK; - Color sunColor = _sunColor(x, t, v, s, r, mu); //L0 - return _hdr(sunColor, groundColor, inscatterColor); // Eq (16) + Color sunColor = _sunColor(x, 0.0, v, s, r, mu); /* L0 */ + return _hdr(sunColor, groundColor, inscatterColor); /* Eq (16) */ +} + +Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base) +{ + Vector3 eye = renderer->camera_location; + Vector3 direction = v3Scale(v3Sub(location, eye), 0.1); + Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), 149597870.0); + + Vector3 x = {0.0, Rg + (eye.y + 20.0) * 0.1, 0.0}; + _fixVector(&x); + Vector3 v = v3Normalize(direction); + _fixVector(&v); + _fixVector(&sun_position); + Vector3 s = v3Normalize(v3Sub(sun_position, x)); + + double r = v3Norm(x); + double mu = v3Dot(x, v) / r; + /*double t = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rg * Rg);*/ + double t = v3Norm(direction); + + Vector3 g = {0.0, 0.0, Rg + 10.0}; + g = v3Sub(x, g); + double a = v.x * v.x + v.y * v.y - v.z * v.z; + double b = 2.0 * (g.x * v.x + g.y * v.y - g.z * v.z); + double c = g.x * g.x + g.y * g.y - g.z * g.z; + double d = -(b + sqrt(b * b - 4.0 * a * c)) / (2.0 * a); + int cone = d > 0.0 && fabs(x.z + d * v.z - Rg) <= 10.0; + + if (t > 0.0) + { + if (cone && d < t) + { + t = d; + } + } + else if (cone) + { + t = d; + } + + Vector3 attenuation; + Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */ + Color groundColor = _groundColor(base, x, t, v, s, r, mu, attenuation); //R[L0]+R[L*]*/ + Color sunColor = _sunColor(x, t, v, s, r, mu); /* L0 */ + return _hdr(sunColor, groundColor, inscatterColor); /* Eq (16) */ } diff --git a/lib_paysages/atmosphere/main.c b/lib_paysages/atmosphere/main.c index 5261a4f..5da95ac 100644 --- a/lib_paysages/atmosphere/main.c +++ b/lib_paysages/atmosphere/main.c @@ -338,6 +338,9 @@ static void _bindRenderer(AtmosphereRenderer* renderer, AtmosphereDefinition* de case ATMOSPHERE_MODEL_PREETHAM: renderer->applyAerialPerspective = preethamApplyAerialPerspective; break; + case ATMOSPHERE_MODEL_BRUNETON: + renderer->applyAerialPerspective = brunetonApplyAerialPerspective; + break; default: renderer->applyAerialPerspective = _fakeApplyAerialPerspective; } diff --git a/lib_paysages/atmosphere/private.h b/lib_paysages/atmosphere/private.h index 1645d2e..fa41f30 100644 --- a/lib_paysages/atmosphere/private.h +++ b/lib_paysages/atmosphere/private.h @@ -5,6 +5,7 @@ void brunetonInit(); Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position); +Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base); Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position); Color preethamApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base); diff --git a/lib_paysages/pack.c b/lib_paysages/pack.c index 858ad96..341e8ca 100644 --- a/lib_paysages/pack.c +++ b/lib_paysages/pack.c @@ -77,25 +77,25 @@ static double unpack754(uint64_t i, unsigned bits, unsigned expbits) return result; } -PackStream* packReadFile(char* filepath) +PackStream* packReadFile(const char* filepath) { PackStream* result; - + result = malloc(sizeof(PackStream)); result->fd = fopen(filepath, "rb"); result->write = 0; - + return result; } -PackStream* packWriteFile(char* filepath) +PackStream* packWriteFile(const char* filepath) { PackStream* result; - + result = malloc(sizeof(PackStream)); result->fd = fopen(filepath, "wb"); result->write = 1; - + return result; } @@ -113,7 +113,7 @@ void packWriteDouble(PackStream* stream, double* value) { int written; uint64_t servalue; - + servalue = pack754_64(*value); written = fwrite(&servalue, sizeof(uint64_t), 1, stream->fd); assert(written == 1); @@ -123,17 +123,17 @@ void packReadDouble(PackStream* stream, double* value) { int read; uint64_t servalue; - + read = fread(&servalue, sizeof(uint64_t), 1, stream->fd); assert(read == 1); - + *value = unpack754_64(servalue); } void packWriteInt(PackStream* stream, int* value) { int written; - + written = fprintf(stream->fd, "%d;", *value); assert(written > 1); } diff --git a/lib_paysages/pack.h b/lib_paysages/pack.h index 4fd1483..8a40253 100644 --- a/lib_paysages/pack.h +++ b/lib_paysages/pack.h @@ -7,8 +7,8 @@ extern "C" { typedef struct PackStream PackStream; -PackStream* packReadFile(char* filepath); -PackStream* packWriteFile(char* filepath); +PackStream* packReadFile(const char* filepath); +PackStream* packWriteFile(const char* filepath); void packCloseStream(PackStream* stream); void packWriteDouble(PackStream* stream, double* value); @@ -17,7 +17,7 @@ void packWriteInt(PackStream* stream, int* value); void packReadInt(PackStream* stream, int* value); void packWriteString(PackStream* stream, char* value, int max_length); void packReadString(PackStream* stream, char* value, int max_length); - + #ifdef __cplusplus } #endif diff --git a/lib_paysages/terrain/main.c b/lib_paysages/terrain/main.c index 9c31937..b77ac59 100644 --- a/lib_paysages/terrain/main.c +++ b/lib_paysages/terrain/main.c @@ -43,6 +43,8 @@ static void _copyDefinition(TerrainDefinition* source, TerrainDefinition* destin destination->scaling = source->scaling; destination->shadow_smoothing = source->shadow_smoothing; + noiseCopy(source->_height_noise, destination->_height_noise); + _validateDefinition(destination); } @@ -51,6 +53,7 @@ static void _saveDefinition(PackStream* stream, TerrainDefinition* definition) packWriteDouble(stream, &definition->height); packWriteDouble(stream, &definition->scaling); packWriteDouble(stream, &definition->shadow_smoothing); + noiseSaveGenerator(stream, definition->_height_noise); } static void _loadDefinition(PackStream* stream, TerrainDefinition* definition) @@ -58,6 +61,7 @@ static void _loadDefinition(PackStream* stream, TerrainDefinition* definition) packReadDouble(stream, &definition->height); packReadDouble(stream, &definition->scaling); packReadDouble(stream, &definition->shadow_smoothing); + noiseLoadGenerator(stream, definition->_height_noise); _validateDefinition(definition); } diff --git a/lib_paysages/tools/texture.c b/lib_paysages/tools/texture.c index 064b576..2370852 100644 --- a/lib_paysages/tools/texture.c +++ b/lib_paysages/tools/texture.c @@ -157,6 +157,31 @@ void texture2DAdd(Texture2D* source, Texture2D* destination) } } +void texture2DSave(PackStream* stream, Texture2D* tex) +{ + int i, n; + packWriteInt(stream, &tex->xsize); + packWriteInt(stream, &tex->ysize); + n = tex->xsize * tex->ysize; + for (i = 0; i < n; i++) + { + colorSave(stream, tex->data + i); + } +} + +void texture2DLoad(PackStream* stream, Texture2D* tex) +{ + int i, n; + packReadInt(stream, &tex->xsize); + packReadInt(stream, &tex->ysize); + n = tex->xsize * tex->ysize; + tex->data = realloc(tex->data, sizeof(Color) * n); + for (i = 0; i < n; i++) + { + colorLoad(stream, tex->data + i); + } +} + void texture2DSaveToFile(Texture2D* tex, const char* filepath) { systemSavePictureFile(filepath, (PictureCallbackSavePixel)texture2DGetPixel, tex, tex->xsize, tex->ysize); @@ -325,6 +350,33 @@ void texture3DAdd(Texture3D* source, Texture3D* destination) } } +void texture3DSave(PackStream* stream, Texture3D* tex) +{ + int i, n; + packWriteInt(stream, &tex->xsize); + packWriteInt(stream, &tex->ysize); + packWriteInt(stream, &tex->zsize); + n = tex->xsize * tex->ysize * tex->zsize; + for (i = 0; i < n; i++) + { + colorSave(stream, tex->data + i); + } +} + +void texture3DLoad(PackStream* stream, Texture3D* tex) +{ + int i, n; + packReadInt(stream, &tex->xsize); + packReadInt(stream, &tex->ysize); + packReadInt(stream, &tex->zsize); + n = tex->xsize * tex->ysize * tex->zsize; + tex->data = realloc(tex->data, sizeof(Color) * n); + for (i = 0; i < n; i++) + { + colorLoad(stream, tex->data + i); + } +} + static Color _callbackTex3dSave(Texture3D* tex, int x, int y) { int z = y / tex->ysize; diff --git a/lib_paysages/tools/texture.h b/lib_paysages/tools/texture.h index 7bf2915..f8c0698 100644 --- a/lib_paysages/tools/texture.h +++ b/lib_paysages/tools/texture.h @@ -10,6 +10,7 @@ extern "C" { #endif #include "../color.h" +#include "../pack.h" typedef struct Texture2D Texture2D; typedef struct Texture3D Texture3D; @@ -24,6 +25,8 @@ Color texture2DGetLinear(Texture2D* tex, double dx, double dy); Color texture2DGetCubic(Texture2D* tex, double dx, double dy); void texture2DFill(Texture2D* tex, Color col); void texture2DAdd(Texture2D* source, Texture2D* destination); +void texture2DSave(PackStream* stream, Texture2D* tex); +void texture2DLoad(PackStream* stream, Texture2D* tex); void texture2DSaveToFile(Texture2D* tex, const char* filepath); void texture2DLoadFromFile(Texture2D* tex, const char* filepath); @@ -37,6 +40,8 @@ Color texture3DGetLinear(Texture3D* tex, double dx, double dy, double dz); Color texture3DGetCubic(Texture3D* tex, double dx, double dy, double dz); void texture3DFill(Texture3D* tex, Color col); void texture3DAdd(Texture3D* source, Texture3D* destination); +void texture3DSave(PackStream* stream, Texture3D* tex); +void texture3DLoad(PackStream* stream, Texture3D* tex); void texture3DSaveToFile(Texture3D* tex, const char* filepath); void texture3DLoadFromFile(Texture3D* tex, const char* filepath);