paysages : Progress on bruneton atmospheric model (WIP).

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@481 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-12-15 10:14:57 +00:00 committed by ThunderK
parent 9da260a5e8
commit 70b42a33c0
5 changed files with 252 additions and 65 deletions

View file

@ -25,24 +25,28 @@ static const double Rt = 6420.0;
static const double RL = 6421.0; static const double RL = 6421.0;
static const double exposure = 0.4; static const double exposure = 0.4;
static const double ISun = 100.0; static const double ISun = 100.0;
static const double AVERAGE_GROUND_REFLECTANCE = 0.1;
#define RES_MU 128 #define RES_MU 128
#define RES_MU_S 32 #define RES_MU_S 32
#define RES_R 32 #define RES_R 32
#define RES_NU 8 #define RES_NU 8
#define TRANSMITTANCE_INTEGRAL_SAMPLES 500
#define SKY_W 64 #define SKY_W 64
#define SKY_H 16 #define SKY_H 16
#define TRANSMITTANCE_W 256 #define TRANSMITTANCE_W 256
#define TRANSMITTANCE_H 64 #define TRANSMITTANCE_H 64
#define TRANSMITTANCE_INTEGRAL_SAMPLES 500
#define INSCATTER_INTEGRAL_SAMPLES 50 #define INSCATTER_INTEGRAL_SAMPLES 50
#define IRRADIANCE_INTEGRAL_SAMPLES 32
#define INSCATTER_SPHERICAL_INTEGRAL_SAMPLES 16
Texture2D* _transmittanceTexture = NULL; Texture2D* _transmittanceTexture = NULL;
Texture2D* _irrDeltaETexture = NULL; Texture2D* _deltaETexture = NULL;
Texture2D* _irradianceTexture = NULL; Texture2D* _irradianceTexture = NULL;
Texture3D* _inscatterTexture = NULL; Texture3D* _inscatterTexture = NULL;
Texture3D* _deltaSMTexture = NULL; Texture3D* _deltaSMTexture = NULL;
Texture3D* _deltaSRTexture = NULL; Texture3D* _deltaSRTexture = NULL;
Texture3D* _deltaJTexture = NULL;
// Rayleigh // Rayleigh
static const double HR = 8.0; static const double HR = 8.0;
@ -369,29 +373,27 @@ static Color _hdr(Color c1, Color c2, Color c3)
static void _getMuMuSNu(double x, double y, double r, Color dhdH, double* mu, double* muS, double* nu) static void _getMuMuSNu(double x, double y, double r, Color dhdH, double* mu, double* muS, double* nu)
{ {
x -= 0.5;
y -= 0.5;
#ifdef INSCATTER_NON_LINEAR #ifdef INSCATTER_NON_LINEAR
double d; double d;
if (y < (double)(RES_MU) / 2.0) if (y < (double)(RES_MU) / 2.0)
{ {
d = 1.0 - y / ((double)(RES_MU) / 2.0 - 1.0); d = 1.0 - y / ((double)(RES_MU) / 2.0);
d = min(max(dhdH.b, d * dhdH.a), dhdH.a * 0.999); d = min(max(dhdH.b, d * dhdH.a), dhdH.a * 0.999);
*mu = (Rg * Rg - r * r - d * d) / (2.0 * r * d); *mu = (Rg * Rg - r * r - d * d) / (2.0 * r * d);
*mu = min(*mu, -sqrt(1.0 - (Rg / r) * (Rg / r)) - 0.001); *mu = min(*mu, -sqrt(1.0 - (Rg / r) * (Rg / r)) - 0.001);
} }
else else
{ {
double d = (y - (double)(RES_MU) / 2.0) / ((double)(RES_MU) / 2.0 - 1.0); double d = (y - (double)(RES_MU) / 2.0) / ((double)(RES_MU) / 2.0);
d = min(max(dhdH.r, d * dhdH.g), dhdH.g * 0.999); d = min(max(dhdH.r, d * dhdH.g), dhdH.g * 0.999);
*mu = (Rt * Rt - r * r - d * d) / (2.0 * r * d); *mu = (Rt * Rt - r * r - d * d) / (2.0 * r * d);
} }
*muS = fmod(x, (double)(RES_MU_S)) / ((double)(RES_MU_S) - 1.0); *muS = fmod(x, (double)(RES_MU_S)) / ((double)(RES_MU_S));
/* paper formula : /* paper formula :
* muS = -(0.6 + log(1.0 - muS * (1.0 - exp(-3.6)))) / 3.0; */ * muS = -(0.6 + log(1.0 - muS * (1.0 - exp(-3.6)))) / 3.0; */
/* better formula */ /* better formula */
*muS = tan((2.0 * (*muS) - 1.0 + 0.26) * 1.1) / tan(1.26 * 1.1); *muS = tan((2.0 * (*muS) - 1.0 + 0.26) * 1.1) / tan(1.26 * 1.1);
*nu = -1.0 + floor(x / (double)(RES_MU_S)) / ((double)(RES_NU) - 1.0) * 2.0; *nu = -1.0 + floor(x / (double)(RES_MU_S)) / ((double)(RES_NU)) * 2.0;
#else #else
mu = -1.0 + 2.0 * y / (float(RES_MU) - 1.0); mu = -1.0 + 2.0 * y / (float(RES_MU) - 1.0);
muS = mod(x, float(RES_MU_S)) / (float(RES_MU_S) - 1.0); muS = mod(x, float(RES_MU_S)) / (float(RES_MU_S) - 1.0);
@ -400,6 +402,19 @@ static void _getMuMuSNu(double x, double y, double r, Color dhdH, double* mu, do
#endif #endif
} }
static void _getIrradianceUV(double r, double muS, double* uMuS, double* uR)
{
*uR = (r - Rg) / (Rt - Rg);
*uMuS = (muS + 0.2) / (1.0 + 0.2);
}
static Color _irradiance(Texture2D* sampler, double r, double muS)
{
double u, v;
_getIrradianceUV(r, muS, &u, &v);
return texture2DGetLinear(sampler, u, v);
}
/*********************** Texture precomputing ***********************/ /*********************** Texture precomputing ***********************/
static void _precomputeTransmittanceTexture() static void _precomputeTransmittanceTexture()
@ -439,14 +454,13 @@ static void _precomputeIrrDeltaETexture()
trans = _transmittance(r, muS); trans = _transmittance(r, muS);
_getTransmittanceUV(r, muS, &u, &v); _getTransmittanceUV(r, muS, &u, &v);
//printf("%d %d -> %f %f -> %f %f %f\n", x, y, u, v, trans.r, trans.g, trans.b);
irr.r = trans.r * max(muS, 0.0); irr.r = trans.r * max(muS, 0.0);
irr.g = trans.g * max(muS, 0.0); irr.g = trans.g * max(muS, 0.0);
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(_irrDeltaETexture, x, y, irr); texture2DSetPixel(_deltaETexture, x, y, irr);
} }
} }
} }
@ -544,7 +558,7 @@ static void _inscatter1Prog(Texture3D* tex_rayleigh, Texture3D* tex_mie)
Color ray = COLOR_BLACK; Color ray = COLOR_BLACK;
Color mie = COLOR_BLACK; Color mie = COLOR_BLACK;
double mu, muS, nu; double mu, muS, nu;
_getMuMuSNu((double)x + 0.5, (double)y + 0.5, _r, _dhdH, &mu, &muS, &nu); _getMuMuSNu((double)x, (double)y, _r, _dhdH, &mu, &muS, &nu);
_inscatter1(_r, mu, muS, nu, &ray, &mie); _inscatter1(_r, mu, muS, nu, &ray, &mie);
/* store separately Rayleigh and Mie contributions, WITHOUT the phase function factor /* store separately Rayleigh and Mie contributions, WITHOUT the phase function factor
* (cf "Angular precision") */ * (cf "Angular precision") */
@ -552,7 +566,177 @@ static void _inscatter1Prog(Texture3D* tex_rayleigh, Texture3D* tex_mie)
texture3DSetPixel(tex_mie, x, y, _layer, mie); texture3DSetPixel(tex_mie, x, y, _layer, mie);
} }
} }
/* TODO Iterate texture */ }
/*********************** inscatterS.glsl ***********************/
static Color _inscatterS(double r, double mu, double muS, double nu, int first)
{
Color raymie = COLOR_BLACK;
double dphi = M_PI / (double)(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES);
double dtheta = M_PI / (double)(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES);
r = clamp(r, Rg, Rt);
mu = clamp(mu, -1.0, 1.0);
muS = clamp(muS, -1.0, 1.0);
double var = sqrt(1.0 - mu * mu) * sqrt(1.0 - muS * muS);
nu = clamp(nu, muS * mu - var, muS * mu + var);
double cthetamin = -sqrt(1.0 - (Rg / r) * (Rg / r));
Vector3 v = vec3(sqrt(1.0 - mu * mu), 0.0, mu);
double sx = v.x == 0.0 ? 0.0 : (nu - muS * mu) / v.x;
Vector3 s = vec3(sx, sqrt(max(0.0, 1.0 - sx * sx - muS * muS)), muS);
/* integral over 4.PI around x with two nested loops over w directions (theta,phi) -- Eq (7) */
int itheta;
for (itheta = 0; itheta < INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; ++itheta)
{
double theta = ((double)(itheta) + 0.5) * dtheta;
double ctheta = cos(theta);
double greflectance = 0.0;
double dground = 0.0;
Color gtransp = {0.0, 0.0, 0.0, 0.0};
if (ctheta < cthetamin)
{
/* if ground visible in direction w
* compute transparency gtransp between x and ground */
greflectance = AVERAGE_GROUND_REFLECTANCE / M_PI;
dground = -r * ctheta - sqrt(r * r * (ctheta * ctheta - 1.0) + Rg * Rg);
gtransp = _transmittance3(Rg, -(r * ctheta + dground) / Rg, dground);
}
int iphi;
for (iphi = 0; iphi < 2 * INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; ++iphi)
{
double phi = ((double)(iphi) + 0.5) * dphi;
double dw = dtheta * dphi * sin(theta);
Vector3 w = vec3(cos(phi) * sin(theta), sin(phi) * sin(theta), ctheta);
double nu1 = v3Dot(s, w);
double nu2 = v3Dot(v, w);
double pr2 = _phaseFunctionR(nu2);
double pm2 = _phaseFunctionM(nu2);
/* compute irradiance received at ground in direction w (if ground visible) =deltaE */
Vector3 gnormal;
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 raymie1; /* light arriving at x from direction w */
/* first term = light reflected from the ground and attenuated before reaching x, =T.alpha/PI.deltaE */
raymie1.r = greflectance * girradiance.r * gtransp.r;
raymie1.g = greflectance * girradiance.g * gtransp.g;
raymie1.b = greflectance * girradiance.b * gtransp.b;
/* second term = inscattered light, =deltaS */
if (first)
{
/* first iteration is special because Rayleigh and Mie were stored separately,
* 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);
raymie.r += ray1.r * pr1 + mie1.r + pm1;
raymie.g += ray1.g * pr1 + mie1.g + pm1;
raymie.b += ray1.b * pr1 + mie1.b + pm1;
}
else
{
Color col = _texture4D(_deltaSRTexture, r, w.z, muS, nu1);
raymie1.r += col.r;
raymie1.g += col.g;
raymie1.b += col.b;
}
/* light coming from direction w and scattered in direction v
= light arriving at x from direction w (raymie1) * SUM(scattering coefficient * phaseFunction)
see Eq (7) */
raymie.r += raymie1.r * (betaR.r * exp(-(r - Rg) / HR) * pr2 + betaMSca.x * exp(-(r - Rg) / HM) * pm2) * dw;
raymie.g += raymie1.g * (betaR.g * exp(-(r - Rg) / HR) * pr2 + betaMSca.y * exp(-(r - Rg) / HM) * pm2) * dw;
raymie.b += raymie1.b * (betaR.b * exp(-(r - Rg) / HR) * pr2 + betaMSca.z * exp(-(r - Rg) / HM) * pm2) * dw;
}
}
/* output raymie = J[T.alpha/PI.deltaE + deltaS] (line 7 in algorithm 4.1) */
return raymie;
}
static void _jProg(Texture3D* result, int first)
{
int x, y;
for (x = 0; x < RES_MU_S * RES_NU; x++)
{
for (y = 0; y < RES_MU; y++)
{
Color raymie;
double mu, muS, nu;
_getMuMuSNu((double)x, (double)y, _r, _dhdH, &mu, &muS, &nu);
raymie = _inscatterS(_r, mu, muS, nu, first);
texture3DSetPixel(result, x, y, _layer, raymie);
}
}
}
/*********************** irradianceN.glsl ***********************/
void _irradianceNProg(Texture2D* tex, int first)
{
int x, y;
double dphi = M_PI / (double)(IRRADIANCE_INTEGRAL_SAMPLES);
double dtheta = M_PI / (double)(IRRADIANCE_INTEGRAL_SAMPLES);
for (x = 0; x < SKY_W; x++)
{
for (y = 0; y < SKY_H; y++)
{
double r, muS;
int iphi;
_getIrradianceRMuS((double)x / SKY_W, (double)y / SKY_H, &r, &muS);
Vector3 s = vec3(max(sqrt(1.0 - muS * muS), 0.0), 0.0, muS);
Color result = COLOR_BLACK;
/* integral over 2.PI around x with two nested loops over w directions (theta,phi) -- Eq (15) */
for (iphi = 0; iphi < 2 * IRRADIANCE_INTEGRAL_SAMPLES; ++iphi)
{
double phi = ((double)(iphi) + 0.5) * dphi;
int itheta;
for (itheta = 0; itheta < IRRADIANCE_INTEGRAL_SAMPLES / 2; ++itheta)
{
double theta = ((double)(itheta) + 0.5) * dtheta;
double dw = dtheta * dphi * sin(theta);
Vector3 w = vec3(cos(phi) * sin(theta), sin(phi) * sin(theta), cos(theta));
double nu = v3Dot(s, w);
if (first)
{
/* first iteration is special because Rayleigh and Mie were stored separately,
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);
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);
result.r += col.r * w.z * dw;
result.g += col.g * w.z * dw;
result.b += col.b * w.z * dw;
}
}
}
texture2DSetPixel(tex, x, y, result);
}
}
} }
/*********************** Final getters ***********************/ /*********************** Final getters ***********************/
@ -717,25 +901,25 @@ static Color _sunColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, doub
} }
else else
{ {
Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; // T(x,xo) Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; /* T(x,xo) */
double isun = step(cos(M_PI / 180.0), v3Dot(v, s)) * ISun; // Lsun double isun = step(cos(M_PI / 180.0), v3Dot(v, s)) * ISun; /* Lsun */
transmittance.r *= isun; transmittance.r *= isun;
transmittance.g *= isun; transmittance.g *= isun;
transmittance.b *= isun; transmittance.b *= isun;
transmittance.a *= isun; transmittance.a *= isun;
return transmittance; // Eq (9) return transmittance; /* Eq (9) */
} }
} }
/*********************** Cache methods ***********************/ /*********************** Cache methods ***********************/
static int _tryLoadCache2D(Texture2D* tex, const char* tag) static int _tryLoadCache2D(Texture2D* tex, const char* tag, int order)
{ {
CacheFile* cache; CacheFile* cache;
int xsize, ysize; int xsize, ysize;
texture2DGetSize(tex, &xsize, &ysize); texture2DGetSize(tex, &xsize, &ysize);
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order);
if (cacheFileIsReadable(cache)) if (cacheFileIsReadable(cache))
{ {
texture2DLoadFromFile(tex, cacheFileGetPath(cache)); texture2DLoadFromFile(tex, cacheFileGetPath(cache));
@ -749,13 +933,13 @@ static int _tryLoadCache2D(Texture2D* tex, const char* tag)
} }
} }
static void _saveCache2D(Texture2D* tex, const char* tag) static void _saveCache2D(Texture2D* tex, const char* tag, int order)
{ {
CacheFile* cache; CacheFile* cache;
int xsize, ysize; int xsize, ysize;
texture2DGetSize(tex, &xsize, &ysize); texture2DGetSize(tex, &xsize, &ysize);
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order);
if (cacheFileIsWritable(cache)) if (cacheFileIsWritable(cache))
{ {
texture2DSaveToFile(tex, cacheFileGetPath(cache)); texture2DSaveToFile(tex, cacheFileGetPath(cache));
@ -763,13 +947,13 @@ static void _saveCache2D(Texture2D* tex, const char* tag)
cacheFileDeleteAccessor(cache); cacheFileDeleteAccessor(cache);
} }
static int _tryLoadCache3D(Texture3D* tex, const char* tag) static int _tryLoadCache3D(Texture3D* tex, const char* tag, int order)
{ {
CacheFile* cache; CacheFile* cache;
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); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order);
if (cacheFileIsReadable(cache)) if (cacheFileIsReadable(cache))
{ {
texture3DLoadFromFile(tex, cacheFileGetPath(cache)); texture3DLoadFromFile(tex, cacheFileGetPath(cache));
@ -783,13 +967,13 @@ static int _tryLoadCache3D(Texture3D* tex, const char* tag)
} }
} }
static void _saveCache3D(Texture3D* tex, const char* tag) 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); texture3DGetSize(tex, &xsize, &ysize, &zsize);
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize); cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order);
if (cacheFileIsWritable(cache)) if (cacheFileIsWritable(cache))
{ {
texture3DSaveToFile(tex, cacheFileGetPath(cache)); texture3DSaveToFile(tex, cacheFileGetPath(cache));
@ -809,34 +993,34 @@ void brunetonInit()
/* 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); _transmittanceTexture = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H);
if (!_tryLoadCache2D(_transmittanceTexture, "transmittance")) if (!_tryLoadCache2D(_transmittanceTexture, "transmittance", 0))
{ {
_precomputeTransmittanceTexture(); _precomputeTransmittanceTexture();
_saveCache2D(_transmittanceTexture, "transmittance"); _saveCache2D(_transmittanceTexture, "transmittance", 0);
} }
/* computes irradiance texture deltaE (line 2 in algorithm 4.1) */ /* computes irradiance texture deltaE (line 2 in algorithm 4.1) */
_irrDeltaETexture = texture2DCreate(SKY_W, SKY_H); _deltaETexture = texture2DCreate(SKY_W, SKY_H);
if (!_tryLoadCache2D(_irrDeltaETexture, "irradianceDeltaE")) if (!_tryLoadCache2D(_deltaETexture, "irradianceDeltaE", 0))
{ {
_precomputeIrrDeltaETexture(); _precomputeIrrDeltaETexture();
_saveCache2D(_irrDeltaETexture, "irradianceDeltaE"); _saveCache2D(_deltaETexture, "irradianceDeltaE", 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); _deltaSRTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
_deltaSMTexture = 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") || !_tryLoadCache3D(_deltaSMTexture, "deltaSM")) if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", 0) || !_tryLoadCache3D(_deltaSMTexture, "deltaSM", 0))
{ {
for (layer = 0; layer < RES_R; ++layer) for (layer = 0; layer < RES_R; ++layer)
{ {
printf("%d\n", layer); printf("deltaS %d\n", layer);
_setLayer(layer); _setLayer(layer);
_inscatter1Prog(_deltaSRTexture, _deltaSMTexture); _inscatter1Prog(_deltaSRTexture, _deltaSMTexture);
} }
_saveCache3D(_deltaSRTexture, "deltaSR"); _saveCache3D(_deltaSRTexture, "deltaSR", 0);
_saveCache3D(_deltaSMTexture, "deltaSM"); _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) */
@ -846,7 +1030,7 @@ void brunetonInit()
/* 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); _inscatterTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
if (!_tryLoadCache3D(_inscatterTexture, "inscatter")) 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++)
{ {
@ -861,35 +1045,31 @@ void brunetonInit()
} }
} }
} }
_saveCache3D(_inscatterTexture, "inscatter"); _saveCache3D(_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) */
/*glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, deltaJTexture, 0); _deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
glViewport(0, 0, RES_MU_S * RES_NU, RES_MU); if (!_tryLoadCache3D(_deltaJTexture, "deltaJ", order))
glUseProgram(jProg); {
glUniform1f(glGetUniformLocation(jProg, "first"), order == 2 ? 1.0 : 0.0); for (layer = 0; layer < RES_R; ++layer)
glUniform1i(glGetUniformLocation(jProg, "transmittanceSampler"), transmittanceUnit); {
glUniform1i(glGetUniformLocation(jProg, "deltaESampler"), deltaEUnit); _setLayer(layer);
glUniform1i(glGetUniformLocation(jProg, "deltaSRSampler"), deltaSRUnit); _jProg(_deltaJTexture, order == 2);
glUniform1i(glGetUniformLocation(jProg, "deltaSMSampler"), deltaSMUnit); }
for (int layer = 0; layer < RES_R; ++layer) { _saveCache3D(_deltaJTexture, "deltaJ", order);
setLayer(jProg, layer); }
drawQuad();
}*/
/* computes deltaE (line 8 in algorithm 4.1) */ /* computes deltaE (line 8 in algorithm 4.1) */
/*glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, deltaETexture, 0); _deltaETexture = texture2DCreate(SKY_W, SKY_H);
glViewport(0, 0, SKY_W, SKY_H); if (!_tryLoadCache2D(_deltaETexture, "deltaE", order))
glUseProgram(irradianceNProg); {
glUniform1f(glGetUniformLocation(irradianceNProg, "first"), order == 2 ? 1.0 : 0.0); _irradianceNProg(_deltaETexture, order == 2);
glUniform1i(glGetUniformLocation(irradianceNProg, "transmittanceSampler"), transmittanceUnit); _saveCache2D(_deltaETexture, "deltaE", order);
glUniform1i(glGetUniformLocation(irradianceNProg, "deltaSRSampler"), deltaSRUnit); }
glUniform1i(glGetUniformLocation(irradianceNProg, "deltaSMSampler"), deltaSMUnit);
drawQuad();*/
/* computes deltaS (line 9 in algorithm 4.1) */ /* computes deltaS (line 9 in algorithm 4.1) */
/*glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, deltaSRTexture, 0); /*glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, deltaSRTexture, 0);
@ -925,11 +1105,11 @@ void brunetonInit()
drawQuad(); drawQuad();
} }
glDisable(GL_BLEND);*/ glDisable(GL_BLEND);*/
/* DEBUG */
break;
} }
} }
/* DEBUG */
exit(1);
} }
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position) Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position)

View file

@ -18,6 +18,8 @@ typedef struct
LightDefinition lights[MAX_SKYDOME_LIGHTS]; LightDefinition lights[MAX_SKYDOME_LIGHTS];
} AtmosphereRendererCache; } AtmosphereRendererCache;
static int _inited = 0;
/******************** Definition ********************/ /******************** Definition ********************/
static void _validateDefinition(AtmosphereDefinition* definition) static void _validateDefinition(AtmosphereDefinition* definition)
{ {
@ -28,7 +30,12 @@ static AtmosphereDefinition* _createDefinition()
{ {
AtmosphereDefinition* result; AtmosphereDefinition* result;
//brunetonInit(); /* DEBUG */ /* TODO Find a better place for this */
if (!_inited)
{
_inited = 1;
brunetonInit();
}
result = malloc(sizeof(AtmosphereDefinition)); result = malloc(sizeof(AtmosphereDefinition));
result->model = ATMOSPHERE_MODEL_PREETHAM; result->model = ATMOSPHERE_MODEL_PREETHAM;

View file

@ -11,14 +11,14 @@ struct CacheFile
char* filepath; char* filepath;
}; };
CacheFile* cacheFileCreateAccessor(const char* module, const char* ext, const char* tag1, int tag2, int tag3, int tag4) CacheFile* cacheFileCreateAccessor(const char* module, const char* ext, const char* tag1, int tag2, int tag3, int tag4, int tag5)
{ {
CacheFile* result; CacheFile* result;
result = (CacheFile*)malloc(sizeof(CacheFile)); result = (CacheFile*)malloc(sizeof(CacheFile));
result->filepath = malloc(sizeof(char) * 501); result->filepath = malloc(sizeof(char) * 501);
snprintf(result->filepath, 500, "./cache/%s-%s-%d-%d-%d.%s", module, tag1, tag2, tag3, tag4, ext); snprintf(result->filepath, 500, "./cache/%s-%s-%d-%d-%d-%d.%s", module, tag1, tag2, tag3, tag4, tag5, ext);
return result; return result;
} }

View file

@ -11,7 +11,7 @@ extern "C" {
typedef struct CacheFile CacheFile; typedef struct CacheFile CacheFile;
CacheFile* cacheFileCreateAccessor(const char* module, const char* ext, const char* tag1, int tag2, int tag3, int tag4); CacheFile* cacheFileCreateAccessor(const char* module, const char* ext, const char* tag1, int tag2, int tag3, int tag4, int tag5);
void cacheFileDeleteAccessor(CacheFile* cache); void cacheFileDeleteAccessor(CacheFile* cache);
int cacheFileIsReadable(CacheFile* cache); int cacheFileIsReadable(CacheFile* cache);
int cacheFileIsWritable(CacheFile* cache); int cacheFileIsWritable(CacheFile* cache);

View file

@ -89,7 +89,7 @@ Color texture2DGetLinear(Texture2D* tex, double dx, double dy)
Color texture2DGetCubic(Texture2D* tex, double dx, double dy) Color texture2DGetCubic(Texture2D* tex, double dx, double dy)
{ {
/* TODO */ /* TODO */
return texture2DGetNearest(tex, dx, dy); return texture2DGetLinear(tex, dx, dy);
} }
void texture2DSaveToFile(Texture2D* tex, const char* filepath) void texture2DSaveToFile(Texture2D* tex, const char* filepath)
@ -188,7 +188,7 @@ 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)
{ {
/* TODO */ /* TODO */
return texture3DGetNearest(tex, dx, dy, dz); return texture3DGetLinear(tex, dx, dy, dz);
} }
static Color _callbackTex3dSave(Texture3D* tex, int x, int y) static Color _callbackTex3dSave(Texture3D* tex, int x, int y)