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:
parent
9da260a5e8
commit
70b42a33c0
5 changed files with 252 additions and 65 deletions
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue