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
This commit is contained in:
Michaël Lemaire 2012-12-24 11:24:27 +00:00 committed by ThunderK
parent 6cd5975316
commit 4a6721e2ff
8 changed files with 315 additions and 168 deletions

View file

@ -5,6 +5,7 @@
* http://evasion.inrialpes.fr/~Eric.Bruneton/ * http://evasion.inrialpes.fr/~Eric.Bruneton/
*/ */
#include <assert.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -13,6 +14,7 @@
#include "../tools/cache.h" #include "../tools/cache.h"
#include "../tools/texture.h" #include "../tools/texture.h"
#include "../tools/parallel.h" #include "../tools/parallel.h"
#include "../renderer.h"
/*********************** Constants ***********************/ /*********************** Constants ***********************/
@ -52,12 +54,8 @@ static const double AVERAGE_GROUND_REFLECTANCE = 0.1;
#endif #endif
Texture2D* _transmittanceTexture = NULL; Texture2D* _transmittanceTexture = NULL;
Texture2D* _deltaETexture = NULL;
Texture2D* _irradianceTexture = NULL; Texture2D* _irradianceTexture = NULL;
Texture3D* _inscatterTexture = NULL; Texture3D* _inscatterTexture = NULL;
Texture3D* _deltaSMTexture = NULL;
Texture3D* _deltaSRTexture = NULL;
Texture3D* _deltaJTexture = NULL;
// Rayleigh // Rayleigh
static const double HR = 8.0; static const double HR = 8.0;
@ -402,7 +400,7 @@ static void _precomputeTransmittanceTexture()
} }
} }
static void _precomputeIrrDeltaETexture() static void _precomputeIrrDeltaETexture(Texture2D* destination)
{ {
int x, y; int x, y;
@ -423,7 +421,7 @@ static void _precomputeIrrDeltaETexture()
irr.b = trans.b * max(muS, 0.0); irr.b = trans.b * max(muS, 0.0);
irr.a = 1.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 ***********************/ /*********************** 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; 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.x = dground * w.x / Rg;
gnormal.y = dground * w.y / Rg; gnormal.y = dground * w.y / Rg;
gnormal.z = r + dground * w.z / 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 */ 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 */ * without the phase functions factors; they must be reintroduced here */
double pr1 = _phaseFunctionR(nu1); double pr1 = _phaseFunctionR(nu1);
double pm1 = _phaseFunctionM(nu1); double pm1 = _phaseFunctionM(nu1);
Color ray1 = _texture4D(_deltaSRTexture, r, w.z, muS, nu1); Color ray1 = _texture4D(deltaSR, r, w.z, muS, nu1);
Color mie1 = _texture4D(_deltaSMTexture, r, w.z, muS, nu1); Color mie1 = _texture4D(deltaSM, r, w.z, muS, nu1);
raymie1.r += ray1.r * pr1 + mie1.r + pm1; raymie1.r += ray1.r * pr1 + mie1.r + pm1;
raymie1.g += ray1.g * pr1 + mie1.g + pm1; raymie1.g += ray1.g * pr1 + mie1.g + pm1;
raymie1.b += ray1.b * pr1 + mie1.b + pm1; raymie1.b += ray1.b * pr1 + mie1.b + pm1;
} }
else else
{ {
Color col = _texture4D(_deltaSRTexture, r, w.z, muS, nu1); Color col = _texture4D(deltaSR, r, w.z, muS, nu1);
raymie1.r += col.r; raymie1.r += col.r;
raymie1.g += col.g; raymie1.g += col.g;
raymie1.b += col.b; raymie1.b += col.b;
@ -645,6 +643,9 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first)
typedef struct typedef struct
{ {
Texture3D* result; Texture3D* result;
Texture2D* deltaE;
Texture3D* deltaSR;
Texture3D* deltaSM;
int first; int first;
} jParams; } jParams;
@ -665,7 +666,7 @@ static int _jWorker(ParallelWork* work, int layer, void* data)
Color raymie; Color raymie;
double mu, muS, nu; double mu, muS, nu;
_getMuMuSNu((double)x, (double)y, r, dhdH, &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); texture3DSetPixel(params->result, x, y, layer, raymie);
} }
} }
@ -674,7 +675,7 @@ static int _jWorker(ParallelWork* work, int layer, void* data)
/*********************** irradianceN.glsl ***********************/ /*********************** irradianceN.glsl ***********************/
void _irradianceNProg(Texture2D* tex, int first) void _irradianceNProg(Texture2D* destination, Texture3D* deltaSR, Texture3D* deltaSM, int first)
{ {
int x, y; int x, y;
double dphi = M_PI / (double)(IRRADIANCE_INTEGRAL_SAMPLES); 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 */ without the phase functions factors; they must be reintroduced here */
double pr1 = _phaseFunctionR(nu); double pr1 = _phaseFunctionR(nu);
double pm1 = _phaseFunctionM(nu); double pm1 = _phaseFunctionM(nu);
Color ray1 = _texture4D(_deltaSRTexture, r, w.z, muS, nu); Color ray1 = _texture4D(deltaSR, r, w.z, muS, nu);
Color mie1 = _texture4D(_deltaSMTexture, 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.r += (ray1.r * pr1 + mie1.r * pm1) * w.z * dw;
result.g += (ray1.g * pr1 + mie1.g * 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; result.b += (ray1.b * pr1 + mie1.b * pm1) * w.z * dw;
} }
else 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.r += col.r * w.z * dw;
result.g += col.g * w.z * dw; result.g += col.g * w.z * dw;
result.b += col.b * 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 ***********************/ /*********************** 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 ri = sqrt(r * r + t * t + 2.0 * r * mu * t);
double mui = (r * mu + t) / ri; double mui = (r * mu + t) / ri;
double muSi = (nu * t + muS * r) / ri; double muSi = (nu * t + muS * r) / ri;
Color c1, c2; Color c1, c2;
c1 = _texture4D(_deltaJTexture, ri, mui, muSi, nu); c1 = _texture4D(deltaJ, ri, mui, muSi, nu);
c2 = _transmittance3(r, mu, t); c2 = _transmittance3(r, mu, t);
c1.r *= c2.r; c1.r *= c2.r;
c1.g *= c2.g; c1.g *= c2.g;
@ -743,16 +750,16 @@ static Color _integrand2(double r, double mu, double muS, double nu, double t)
return c1; 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; Color raymie = COLOR_BLACK;
double dx = _limit(r, mu) / (double)(INSCATTER_INTEGRAL_SAMPLES); 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; int i;
for (i = 1; i <= INSCATTER_INTEGRAL_SAMPLES; ++i) for (i = 1; i <= INSCATTER_INTEGRAL_SAMPLES; ++i)
{ {
double xj = (double)(i) * dx; 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.r += (raymiei.r + raymiej.r) / 2.0 * dx;
raymie.g += (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; raymie.b += (raymiei.r + raymiej.r) / 2.0 * dx;
@ -765,6 +772,8 @@ static int _inscatterNWorker(ParallelWork* work, int layer, void* data)
{ {
UNUSED(work); UNUSED(work);
InscatterNParams* params = data;
double r; double r;
Color dhdH; Color dhdH;
_getLayerParams(layer, &r, &dhdH); _getLayerParams(layer, &r, &dhdH);
@ -776,7 +785,7 @@ static int _inscatterNWorker(ParallelWork* work, int layer, void* data)
{ {
double mu, muS, nu; double mu, muS, nu;
_getMuMuSNu((double)x, (double)y, r, dhdH, &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; 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); _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 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); Color col2 = texture3DGetPixel(params->destination, x, y, layer);
col2.r += col1.r * 0.1 / _phaseFunctionR(nu); col2.r += col1.r / _phaseFunctionR(nu);
col2.g += col1.g * 0.1 / _phaseFunctionR(nu); col2.g += col1.g / _phaseFunctionR(nu);
col2.b += col1.b * 0.1 / _phaseFunctionR(nu); col2.b += col1.b / _phaseFunctionR(nu);
col2.a = 1.0;
texture3DSetPixel(params->destination, x, y, layer, col2); 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 /*ground radiance at end of ray x+tv, when sun in direction s
*attenuated bewteen ground and viewer (=R[L0]+R[L*]) */ *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; Color result;
if (t > 0.0)
{ // if ray hits ground surface
// ground reflectance at end of ray, x0 #if 0
Vector3 x0 = v3Add(x, v3Scale(v, t)); // ground reflectance at end of ray, x0
float r0 = v3Norm(x0); Vector3 x0 = v3Add(x, v3Scale(v, t));
Vector3 n = v3Scale(x0, 1.0 / r0); float r0 = v3Norm(x0);
vec2 coords = vec2(atan(n.y, n.x), acos(n.z)) * vec2(0.5, 1.0) / M_PI + vec2(0.5, 0.0); Vector3 n = v3Scale(x0, 1.0 / r0);
Color reflectance; vec2 coords = vec2(atan(n.y, n.x), acos(n.z)) * vec2(0.5, 1.0) / M_PI + vec2(0.5, 0.0);
if (r0 > Rg + 0.01) Color reflectance;
{ if (r0 > Rg + 0.01)
reflectance = vec4(0.4, 0.4, 0.4, 0.0); {
} 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*]
} }
else 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; return result;
}*/ }
/* direct sun light for ray x+tv, when sun in direction s (=L0) */ /* 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) 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) 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; int xsize, ysize;
texture2DGetSize(tex, &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)) if (cacheFileIsReadable(cache))
{ {
texture2DLoadFromFile(tex, cacheFileGetPath(cache)); PackStream* stream;
stream = packReadFile(cacheFileGetPath(cache));
texture2DLoad(stream, tex);
packCloseStream(stream);
cacheFileDeleteAccessor(cache); cacheFileDeleteAccessor(cache);
return 1; return 1;
} }
@ -1018,6 +1029,23 @@ static void _saveCache2D(Texture2D* tex, const char* tag, int order)
CacheFile* cache; CacheFile* cache;
int xsize, ysize; 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); texture2DGetSize(tex, &xsize, &ysize);
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order);
if (cacheFileIsWritable(cache)) if (cacheFileIsWritable(cache))
@ -1033,10 +1061,14 @@ static int _tryLoadCache3D(Texture3D* tex, const char* tag, int order)
int xsize, ysize, zsize; int xsize, ysize, zsize;
texture3DGetSize(tex, &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)) if (cacheFileIsReadable(cache))
{ {
texture3DLoadFromFile(tex, cacheFileGetPath(cache)); PackStream* stream;
stream = packReadFile(cacheFileGetPath(cache));
texture3DLoad(stream, tex);
packCloseStream(stream);
cacheFileDeleteAccessor(cache); cacheFileDeleteAccessor(cache);
return 1; return 1;
} }
@ -1052,6 +1084,23 @@ static void _saveCache3D(Texture3D* tex, const char* tag, int order)
CacheFile* cache; CacheFile* cache;
int xsize, ysize, zsize; 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); texture3DGetSize(tex, &xsize, &ysize, &zsize);
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order);
if (cacheFileIsWritable(cache)) if (cacheFileIsWritable(cache))
@ -1067,115 +1116,104 @@ void brunetonInit()
int x, y, z, order; int x, y, z, order;
ParallelWork* work; ParallelWork* work;
assert(_inscatterTexture == NULL);
/* TODO Deletes */ /* 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) */ /* computes transmittance texture T (line 1 in algorithm 4.1) */
_transmittanceTexture = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H); _precomputeTransmittanceTexture();
if (!_tryLoadCache2D(_transmittanceTexture, "transmittance", 0)) _saveDebug2D(_transmittanceTexture, "transmittance", 0);
{
_precomputeTransmittanceTexture();
_saveCache2D(_transmittanceTexture, "transmittance", 0);
}
/* computes irradiance texture deltaE (line 2 in algorithm 4.1) */ /* computes irradiance texture deltaE (line 2 in algorithm 4.1) */
_deltaETexture = texture2DCreate(SKY_W, SKY_H); _precomputeIrrDeltaETexture(_deltaETexture);
if (!_tryLoadCache2D(_deltaETexture, "deltaE", 0)) _saveDebug2D(_deltaETexture, "deltaE", 0);
{
_precomputeIrrDeltaETexture();
_saveCache2D(_deltaETexture, "deltaE", 0);
}
/* computes single scattering texture deltaS (line 3 in algorithm 4.1) /* computes single scattering texture deltaS (line 3 in algorithm 4.1)
* Rayleigh and Mie separated in deltaSR + deltaSM */ * Rayleigh and Mie separated in deltaSR + deltaSM */
_deltaSRTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); Inscatter1Params params = {_deltaSRTexture, _deltaSMTexture};
_deltaSMTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); work = parallelWorkCreate(_inscatter1Worker, RES_R, &params);
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", 0) || !_tryLoadCache3D(_deltaSMTexture, "deltaSM", 0)) parallelWorkPerform(work, -1);
{ parallelWorkDelete(work);
Inscatter1Params params = {_deltaSRTexture, _deltaSMTexture}; _saveDebug3D(_deltaSRTexture, "deltaSR", 0);
work = parallelWorkCreate(_inscatter1Worker, RES_R, &params); _saveDebug3D(_deltaSMTexture, "deltaSM", 0);
parallelWorkPerform(work, -1);
parallelWorkDelete(work);
_saveCache3D(_deltaSRTexture, "deltaSR", 0);
_saveCache3D(_deltaSMTexture, "deltaSM", 0);
}
/* copies deltaE into irradiance texture E (line 4 in algorithm 4.1) */ /* copies deltaE into irradiance texture E (line 4 in algorithm 4.1) */
/* ??? all black texture (k=0.0) ??? */ /* ??? all black texture (k=0.0) ??? */
_irradianceTexture = texture2DCreate(SKY_W, SKY_H);
texture2DFill(_irradianceTexture, COLOR_BLACK); texture2DFill(_irradianceTexture, COLOR_BLACK);
/* copies deltaS into inscatter texture S (line 5 in algorithm 4.1) */ /* 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", 0))
{ {
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);
Color result = texture3DGetPixel(_deltaSRTexture, x, y, z); result.a = mie.r;
Color mie = texture3DGetPixel(_deltaSMTexture, x, y, z); texture3DSetPixel(_inscatterTexture, x, y, z, result);
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) */ /* loop for each scattering order (line 6 in algorithm 4.1) */
for (order = 2; order <= 4; ++order) for (order = 2; order <= 4; ++order)
{ {
/* computes deltaJ (line 7 in algorithm 4.1) */ /* computes deltaJ (line 7 in algorithm 4.1) */
_deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R); jParams jparams = {_deltaJTexture, _deltaETexture, _deltaSRTexture, _deltaSMTexture, order == 2};
if (!_tryLoadCache3D(_deltaJTexture, "deltaJ", order)) work = parallelWorkCreate(_jWorker, RES_R, &jparams);
{ parallelWorkPerform(work, -1);
jParams params = {_deltaJTexture, order == 2}; parallelWorkDelete(work);
work = parallelWorkCreate(_jWorker, RES_R, &params); _saveDebug3D(_deltaJTexture, "deltaJ", order);
parallelWorkPerform(work, -1);
parallelWorkDelete(work);
_saveCache3D(_deltaJTexture, "deltaJ", order);
}
/* computes deltaE (line 8 in algorithm 4.1) */ /* computes deltaE (line 8 in algorithm 4.1) */
_deltaETexture = texture2DCreate(SKY_W, SKY_H); _irradianceNProg(_deltaETexture, _deltaSRTexture, _deltaSMTexture, order == 2);
if (!_tryLoadCache2D(_deltaETexture, "deltaE", order)) _saveDebug2D(_deltaETexture, "deltaE", order);
{
_irradianceNProg(_deltaETexture, order == 2);
_saveCache2D(_deltaETexture, "deltaE", order);
}
/* computes deltaS (line 9 in algorithm 4.1) */ /* computes deltaS (line 9 in algorithm 4.1) */
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", order)) InscatterNParams iparams = {_deltaSRTexture, _deltaJTexture};
{ work = parallelWorkCreate(_inscatterNWorker, RES_R, &iparams);
work = parallelWorkCreate(_inscatterNWorker, RES_R, _deltaSRTexture); parallelWorkPerform(work, -1);
parallelWorkPerform(work, -1); parallelWorkDelete(work);
parallelWorkDelete(work); _saveDebug3D(_deltaSRTexture, "deltaSR", order);
_saveCache3D(_deltaSRTexture, "deltaSR", order);
}
/* adds deltaE into irradiance texture E (line 10 in algorithm 4.1) */ /* adds deltaE into irradiance texture E (line 10 in algorithm 4.1) */
if (!_tryLoadCache2D(_irradianceTexture, "irradiance", order)) texture2DAdd(_deltaETexture, _irradianceTexture);
{ _saveDebug2D(_irradianceTexture, "irradiance", order);
texture2DAdd(_deltaETexture, _irradianceTexture);
_saveCache2D(_irradianceTexture, "irradiance", order);
}
/* adds deltaS into inscatter texture S (line 11 in algorithm 4.1) */ /* adds deltaS into inscatter texture S (line 11 in algorithm 4.1) */
if (!_tryLoadCache3D(_inscatterTexture, "inscatter", order)) CopyInscatterNParams cparams = {_deltaSRTexture, _inscatterTexture};
{ work = parallelWorkCreate(_copyInscatterNWorker, RES_R, &cparams);
CopyInscatterNParams params = {_deltaSRTexture, _inscatterTexture}; parallelWorkPerform(work, -1);
work = parallelWorkCreate(_copyInscatterNWorker, RES_R, &params); parallelWorkDelete(work);
parallelWorkPerform(work, -1); _saveDebug3D(_inscatterTexture, "inscatter", order);
parallelWorkDelete(work);
_saveCache3D(_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) 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) 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); _fixVector(&x);
Vector3 v = v3Normalize(direction); Vector3 v = v3Normalize(direction);
_fixVector(&v); _fixVector(&v);
Vector3 s = v3Normalize(v3Sub(sun_position, eye)); _fixVector(&sun_position);
_fixVector(&s); Vector3 s = v3Normalize(v3Sub(sun_position, x));
double r = v3Norm(x); double r = v3Norm(x);
double mu = v3Dot(x, v) / r; double mu = v3Dot(x, v) / r;
@ -1220,9 +1258,53 @@ Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3
} }
Vector3 attenuation; Vector3 attenuation;
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); //S[L]-T(x,xs)S[l]|xs 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 groundColor = COLOR_BLACK; Color groundColor = COLOR_BLACK;
Color sunColor = _sunColor(x, t, v, s, r, mu); //L0 Color sunColor = _sunColor(x, 0.0, v, s, r, mu); /* L0 */
return _hdr(sunColor, groundColor, inscatterColor); // Eq (16) 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) */
} }

View file

@ -338,6 +338,9 @@ static void _bindRenderer(AtmosphereRenderer* renderer, AtmosphereDefinition* de
case ATMOSPHERE_MODEL_PREETHAM: case ATMOSPHERE_MODEL_PREETHAM:
renderer->applyAerialPerspective = preethamApplyAerialPerspective; renderer->applyAerialPerspective = preethamApplyAerialPerspective;
break; break;
case ATMOSPHERE_MODEL_BRUNETON:
renderer->applyAerialPerspective = brunetonApplyAerialPerspective;
break;
default: default:
renderer->applyAerialPerspective = _fakeApplyAerialPerspective; renderer->applyAerialPerspective = _fakeApplyAerialPerspective;
} }

View file

@ -5,6 +5,7 @@
void brunetonInit(); void brunetonInit();
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position); 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 preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
Color preethamApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base); Color preethamApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base);

View file

@ -77,25 +77,25 @@ static double unpack754(uint64_t i, unsigned bits, unsigned expbits)
return result; return result;
} }
PackStream* packReadFile(char* filepath) PackStream* packReadFile(const char* filepath)
{ {
PackStream* result; PackStream* result;
result = malloc(sizeof(PackStream)); result = malloc(sizeof(PackStream));
result->fd = fopen(filepath, "rb"); result->fd = fopen(filepath, "rb");
result->write = 0; result->write = 0;
return result; return result;
} }
PackStream* packWriteFile(char* filepath) PackStream* packWriteFile(const char* filepath)
{ {
PackStream* result; PackStream* result;
result = malloc(sizeof(PackStream)); result = malloc(sizeof(PackStream));
result->fd = fopen(filepath, "wb"); result->fd = fopen(filepath, "wb");
result->write = 1; result->write = 1;
return result; return result;
} }
@ -113,7 +113,7 @@ void packWriteDouble(PackStream* stream, double* value)
{ {
int written; int written;
uint64_t servalue; uint64_t servalue;
servalue = pack754_64(*value); servalue = pack754_64(*value);
written = fwrite(&servalue, sizeof(uint64_t), 1, stream->fd); written = fwrite(&servalue, sizeof(uint64_t), 1, stream->fd);
assert(written == 1); assert(written == 1);
@ -123,17 +123,17 @@ void packReadDouble(PackStream* stream, double* value)
{ {
int read; int read;
uint64_t servalue; uint64_t servalue;
read = fread(&servalue, sizeof(uint64_t), 1, stream->fd); read = fread(&servalue, sizeof(uint64_t), 1, stream->fd);
assert(read == 1); assert(read == 1);
*value = unpack754_64(servalue); *value = unpack754_64(servalue);
} }
void packWriteInt(PackStream* stream, int* value) void packWriteInt(PackStream* stream, int* value)
{ {
int written; int written;
written = fprintf(stream->fd, "%d;", *value); written = fprintf(stream->fd, "%d;", *value);
assert(written > 1); assert(written > 1);
} }

View file

@ -7,8 +7,8 @@ extern "C" {
typedef struct PackStream PackStream; typedef struct PackStream PackStream;
PackStream* packReadFile(char* filepath); PackStream* packReadFile(const char* filepath);
PackStream* packWriteFile(char* filepath); PackStream* packWriteFile(const char* filepath);
void packCloseStream(PackStream* stream); void packCloseStream(PackStream* stream);
void packWriteDouble(PackStream* stream, double* value); void packWriteDouble(PackStream* stream, double* value);
@ -17,7 +17,7 @@ void packWriteInt(PackStream* stream, int* value);
void packReadInt(PackStream* stream, int* value); void packReadInt(PackStream* stream, int* value);
void packWriteString(PackStream* stream, char* value, int max_length); void packWriteString(PackStream* stream, char* value, int max_length);
void packReadString(PackStream* stream, char* value, int max_length); void packReadString(PackStream* stream, char* value, int max_length);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -43,6 +43,8 @@ static void _copyDefinition(TerrainDefinition* source, TerrainDefinition* destin
destination->scaling = source->scaling; destination->scaling = source->scaling;
destination->shadow_smoothing = source->shadow_smoothing; destination->shadow_smoothing = source->shadow_smoothing;
noiseCopy(source->_height_noise, destination->_height_noise);
_validateDefinition(destination); _validateDefinition(destination);
} }
@ -51,6 +53,7 @@ static void _saveDefinition(PackStream* stream, TerrainDefinition* definition)
packWriteDouble(stream, &definition->height); packWriteDouble(stream, &definition->height);
packWriteDouble(stream, &definition->scaling); packWriteDouble(stream, &definition->scaling);
packWriteDouble(stream, &definition->shadow_smoothing); packWriteDouble(stream, &definition->shadow_smoothing);
noiseSaveGenerator(stream, definition->_height_noise);
} }
static void _loadDefinition(PackStream* stream, TerrainDefinition* definition) 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->height);
packReadDouble(stream, &definition->scaling); packReadDouble(stream, &definition->scaling);
packReadDouble(stream, &definition->shadow_smoothing); packReadDouble(stream, &definition->shadow_smoothing);
noiseLoadGenerator(stream, definition->_height_noise);
_validateDefinition(definition); _validateDefinition(definition);
} }

View file

@ -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) void texture2DSaveToFile(Texture2D* tex, const char* filepath)
{ {
systemSavePictureFile(filepath, (PictureCallbackSavePixel)texture2DGetPixel, tex, tex->xsize, tex->ysize); 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) static Color _callbackTex3dSave(Texture3D* tex, int x, int y)
{ {
int z = y / tex->ysize; int z = y / tex->ysize;

View file

@ -10,6 +10,7 @@ extern "C" {
#endif #endif
#include "../color.h" #include "../color.h"
#include "../pack.h"
typedef struct Texture2D Texture2D; typedef struct Texture2D Texture2D;
typedef struct Texture3D Texture3D; typedef struct Texture3D Texture3D;
@ -24,6 +25,8 @@ Color texture2DGetLinear(Texture2D* tex, double dx, double dy);
Color texture2DGetCubic(Texture2D* tex, double dx, double dy); Color texture2DGetCubic(Texture2D* tex, double dx, double dy);
void texture2DFill(Texture2D* tex, Color col); void texture2DFill(Texture2D* tex, Color col);
void texture2DAdd(Texture2D* source, Texture2D* destination); 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 texture2DSaveToFile(Texture2D* tex, const char* filepath);
void texture2DLoadFromFile(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); Color texture3DGetCubic(Texture3D* tex, double dx, double dy, double dz);
void texture3DFill(Texture3D* tex, Color col); void texture3DFill(Texture3D* tex, Color col);
void texture3DAdd(Texture3D* source, Texture3D* destination); 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 texture3DSaveToFile(Texture3D* tex, const char* filepath);
void texture3DLoadFromFile(Texture3D* tex, const char* filepath); void texture3DLoadFromFile(Texture3D* tex, const char* filepath);