paysages : Restored pseudo aerial perspective for preetham atmosphere model.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@470 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
49c6c17118
commit
7e9a0e3faa
10 changed files with 475 additions and 69 deletions
1
TODO
1
TODO
|
@ -10,7 +10,6 @@ Technology Preview 2 :
|
||||||
=> Apply model to atmosphere (aerial perspective)
|
=> Apply model to atmosphere (aerial perspective)
|
||||||
=> Find a proper model for night sky (maybe Shirley)
|
=> Find a proper model for night sky (maybe Shirley)
|
||||||
- Clouds should keep distance to ground.
|
- Clouds should keep distance to ground.
|
||||||
- Restore aerial perspective.
|
|
||||||
- Implement Bruneton's scattering model.
|
- Implement Bruneton's scattering model.
|
||||||
- Add clouds to explorer with 3d textures.
|
- Add clouds to explorer with 3d textures.
|
||||||
- Start using OpenCL to optimize rendering.
|
- Start using OpenCL to optimize rendering.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "../lib_paysages/atmosphere/atmosphere.h"
|
#include "../lib_paysages/atmosphere/public.h"
|
||||||
#include "../lib_paysages/scenery.h"
|
#include "../lib_paysages/scenery.h"
|
||||||
#include "../lib_paysages/renderer.h"
|
#include "../lib_paysages/renderer.h"
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ FormAtmosphere::FormAtmosphere(QWidget *parent):
|
||||||
addInputDouble(tr("Sun halo radius"), &_definition->sun_halo_size, 0.0, 0.4, 0.004, 0.04);
|
addInputDouble(tr("Sun halo radius"), &_definition->sun_halo_size, 0.0, 0.4, 0.004, 0.04);
|
||||||
addInputCurve(tr("Sun halo profile"), _definition->sun_halo_profile, 0.0, 1.0, 0.0, 1.0, tr("Distance to center of the sun"), tr("Light influence (halo opacity)"));
|
addInputCurve(tr("Sun halo profile"), _definition->sun_halo_profile, 0.0, 1.0, 0.0, 1.0, tr("Distance to center of the sun"), tr("Light influence (halo opacity)"));
|
||||||
addInputDouble(tr("Influence of skydome on lighting"), &_definition->dome_lighting, 0.0, 2.0, 0.01, 0.1);
|
addInputDouble(tr("Influence of skydome on lighting"), &_definition->dome_lighting, 0.0, 2.0, 0.01, 0.1);
|
||||||
input = addInputDouble(tr("Humidity"), &_definition->humidity, 1.8, 6.0, 0.05, 0.5);
|
addInputDouble(tr("Humidity"), &_definition->humidity, 0.0, 1.0, 0.01, 0.1);
|
||||||
|
|
||||||
revertConfig();
|
revertConfig();
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ protected:
|
||||||
|
|
||||||
sceneryGetAtmosphere(_atmosphere);
|
sceneryGetAtmosphere(_atmosphere);
|
||||||
AtmosphereRendererClass.bind(_renderer.atmosphere, _atmosphere);
|
AtmosphereRendererClass.bind(_renderer.atmosphere, _atmosphere);
|
||||||
|
_renderer.atmosphere->applyAerialPerspective = _applyAerialPerspective;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Renderer _renderer;
|
Renderer _renderer;
|
||||||
|
@ -95,6 +96,11 @@ private:
|
||||||
{
|
{
|
||||||
lightingGetStatus((LightingDefinition*)renderer->customData[2], renderer, location, status);
|
lightingGetStatus((LightingDefinition*)renderer->customData[2], renderer, location, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Color _applyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
||||||
|
{
|
||||||
|
return base;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**************** Form ****************/
|
/**************** Form ****************/
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "atmosphere.h"
|
#include "public.h"
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -43,7 +44,7 @@ static AtmosphereDefinition* _createDefinition()
|
||||||
curveQuickAddPoint(result->sun_halo_profile, 0.1, 0.2);
|
curveQuickAddPoint(result->sun_halo_profile, 0.1, 0.2);
|
||||||
curveQuickAddPoint(result->sun_halo_profile, 1.0, 0.0);
|
curveQuickAddPoint(result->sun_halo_profile, 1.0, 0.0);
|
||||||
result->dome_lighting = 0.6;
|
result->dome_lighting = 0.6;
|
||||||
result->humidity = 2.0;
|
result->humidity = 0.1;
|
||||||
|
|
||||||
_validateDefinition(result);
|
_validateDefinition(result);
|
||||||
|
|
||||||
|
@ -107,13 +108,10 @@ StandardDefinition AtmosphereDefinitionClass = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************** Binding ********************/
|
/******************** Binding ********************/
|
||||||
extern Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
static Color _fakeApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
||||||
extern Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
|
||||||
|
|
||||||
static Color _fakeApplyAerialPerspective(Renderer* renderer, Vector3 direction, Color base)
|
|
||||||
{
|
{
|
||||||
UNUSED(renderer);
|
UNUSED(renderer);
|
||||||
UNUSED(direction);
|
UNUSED(location);
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
static Color _fakeGetSkyColor(Renderer* renderer, Vector3 direction)
|
static Color _fakeGetSkyColor(Renderer* renderer, Vector3 direction)
|
||||||
|
@ -325,6 +323,15 @@ static void _bindRenderer(AtmosphereRenderer* renderer, AtmosphereDefinition* de
|
||||||
renderer->getSkyColor = _getSkyColor;
|
renderer->getSkyColor = _getSkyColor;
|
||||||
renderer->getSkydomeLights = _getSkydomeLights;
|
renderer->getSkydomeLights = _getSkydomeLights;
|
||||||
|
|
||||||
|
switch (definition->model)
|
||||||
|
{
|
||||||
|
case ATMOSPHERE_MODEL_PREETHAM:
|
||||||
|
renderer->applyAerialPerspective = preethamApplyAerialPerspective;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
renderer->applyAerialPerspective = _fakeApplyAerialPerspective;
|
||||||
|
}
|
||||||
|
|
||||||
mutexAcquire(cache->lock);
|
mutexAcquire(cache->lock);
|
||||||
cache->nblights = -1;
|
cache->nblights = -1;
|
||||||
mutexRelease(cache->lock);
|
mutexRelease(cache->lock);
|
||||||
|
|
|
@ -1,6 +1,356 @@
|
||||||
#include "atmosphere.h"
|
#include "public.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Atmospheric scattering, based on E. Bruneton and F.Neyret work.
|
||||||
|
* http://evasion.inrialpes.fr/~Eric.Bruneton/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define TRANSMITTANCE_NON_LINEAR
|
||||||
|
#define INSCATTER_NON_LINEAR
|
||||||
|
#define FIX
|
||||||
|
|
||||||
|
static const double Rg = 6360.0;
|
||||||
|
static const double Rt = 6420.0;
|
||||||
|
static const double RL = 6421.0;
|
||||||
|
static const double exposure = 0.4;
|
||||||
|
static const float ISun = 100.0;
|
||||||
|
|
||||||
|
// Rayleigh
|
||||||
|
static const double HR = 8.0;
|
||||||
|
static const Color betaR = {5.8e-3, 1.35e-2, 3.31e-2, 1.0};
|
||||||
|
|
||||||
|
// Mie
|
||||||
|
// DEFAULT
|
||||||
|
static const double HM = 1.2;
|
||||||
|
/*static const vec3 betaMSca = vec3(4e-3);
|
||||||
|
static const vec3 betaMEx = betaMSca / 0.9;*/
|
||||||
|
static const double mieG = 0.8;
|
||||||
|
// CLEAR SKY
|
||||||
|
/*static const float HM = 1.2;
|
||||||
|
static const vec3 betaMSca = vec3(20e-3);
|
||||||
|
static const vec3 betaMEx = betaMSca / 0.9;
|
||||||
|
static const float mieG = 0.76;*/
|
||||||
|
// PARTLY CLOUDY
|
||||||
|
/*static const float HM = 3.0;
|
||||||
|
static const vec3 betaMSca = vec3(3e-3);
|
||||||
|
static const vec3 betaMEx = betaMSca / 0.9;
|
||||||
|
static const float mieG = 0.65;*/
|
||||||
|
|
||||||
|
#define step(_a_,_b_) ((_a_) < (_b_) ? 0 : 1)
|
||||||
|
#define max(_a_,_b_) ((_a_) < (_b_) ? (_a_) : (_b_))
|
||||||
|
#define sign(_a_) ((_a_) < 0.0 ? -1.0 : ((_a_) > 0.0 ? 1.0 : 0.0))
|
||||||
|
|
||||||
|
/* Rayleigh phase function */
|
||||||
|
static double _phaseFunctionR(double mu)
|
||||||
|
{
|
||||||
|
return (3.0 / (16.0 * M_PI)) * (1.0 + mu * mu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mie phase function */
|
||||||
|
static double _phaseFunctionM(double mu)
|
||||||
|
{
|
||||||
|
return 1.5 * 1.0 / (4.0 * M_PI) * (1.0 - mieG * mieG) * pow(1.0 + (mieG * mieG) - 2.0 * mieG * mu, -3.0 / 2.0) * (1.0 + mu * mu) / (2.0 + mieG * mieG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* approximated single Mie scattering (cf. approximate Cm in paragraph "Angular precision") */
|
||||||
|
static Color _getMie(Color rayMie)
|
||||||
|
{
|
||||||
|
double value = rayMie.a / max(rayMie.r, 1e-4) * (betaR.r / betaR); /* TODO divide by a vector ? */
|
||||||
|
rayMie.r *= value;
|
||||||
|
rayMie.g *= value;
|
||||||
|
rayMie.b *= value;
|
||||||
|
rayMie.a = 1.0;
|
||||||
|
return rayMie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* optical depth for ray (r,mu) of length d, using analytic formula
|
||||||
|
(mu=cos(view zenith angle)), intersections with ground ignored
|
||||||
|
H=height scale of exponential density function */
|
||||||
|
static double _opticalDepth(double H, double r, double mu, double d)
|
||||||
|
{
|
||||||
|
double a = sqrt((0.5 / H) * r);
|
||||||
|
double ax = a * (mu);
|
||||||
|
double ay = a * (mu + d / r);
|
||||||
|
double axs = sign(ax);
|
||||||
|
double ays = sign(ay);
|
||||||
|
double axq = ax * ax;
|
||||||
|
double ayq = ay * ay;
|
||||||
|
double x = ays > axs ? exp(axq) : 0.0;
|
||||||
|
double yx = axs / (2.3193 * fabs(ax) + sqrt(1.52 * axq + 4.0));
|
||||||
|
double yy = ays / (2.3193 * fabs(ay) + sqrt(1.52 * ayq + 4.0)) * exp(-d / H * (d / (2.0 * r) + mu));
|
||||||
|
return sqrt((6.2831 * H) * r) * exp((Rg - r) / H) * (x + yx - yy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color _texture4D(sampler3D table, float r, float mu, float muS, float nu)
|
||||||
|
{
|
||||||
|
float H = sqrt(Rt * Rt - Rg * Rg);
|
||||||
|
float rho = sqrt(r * r - Rg * Rg);
|
||||||
|
#ifdef INSCATTER_NON_LINEAR
|
||||||
|
float rmu = r * mu;
|
||||||
|
float delta = rmu * rmu - r * r + Rg * Rg;
|
||||||
|
vec4 cst = rmu < 0.0 && delta > 0.0 ? vec4(1.0, 0.0, 0.0, 0.5 - 0.5 / float(RES_MU)) : vec4(-1.0, H * H, H, 0.5 + 0.5 / float(RES_MU));
|
||||||
|
float uR = 0.5 / float(RES_R) + rho / H * (1.0 - 1.0 / float(RES_R));
|
||||||
|
float uMu = cst.w + (rmu * cst.x + sqrt(delta + cst.y)) / (rho + cst.z) * (0.5 - 1.0 / float(RES_MU));
|
||||||
|
// paper formula
|
||||||
|
//float uMuS = 0.5 / float(RES_MU_S) + max((1.0 - exp(-3.0 * muS - 0.6)) / (1.0 - exp(-3.6)), 0.0) * (1.0 - 1.0 / float(RES_MU_S));
|
||||||
|
// better formula
|
||||||
|
float uMuS = 0.5 / float(RES_MU_S) + (atan(max(muS, -0.1975) * tan(1.26 * 1.1)) / 1.1 + (1.0 - 0.26)) * 0.5 * (1.0 - 1.0 / float(RES_MU_S));
|
||||||
|
#else
|
||||||
|
float uR = 0.5 / float(RES_R) + rho / H * (1.0 - 1.0 / float(RES_R));
|
||||||
|
float uMu = 0.5 / float(RES_MU) + (mu + 1.0) / 2.0 * (1.0 - 1.0 / float(RES_MU));
|
||||||
|
float uMuS = 0.5 / float(RES_MU_S) + max(muS + 0.2, 0.0) / 1.2 * (1.0 - 1.0 / float(RES_MU_S));
|
||||||
|
#endif
|
||||||
|
float lerp = (nu + 1.0) / 2.0 * (float(RES_NU) - 1.0);
|
||||||
|
float uNu = floor(lerp);
|
||||||
|
lerp = lerp - uNu;
|
||||||
|
return texture3D(table, vec3((uNu + uMuS) / float(RES_NU), uMu, uR)) * (1.0 - lerp) +
|
||||||
|
texture3D(table, vec3((uNu + uMuS + 1.0) / float(RES_NU), uMu, uR)) * lerp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* transmittance(=transparency) of atmosphere for ray (r,mu) of length d
|
||||||
|
(mu=cos(view zenith angle)), intersections with ground ignored
|
||||||
|
uses analytic formula instead of transmittance texture */
|
||||||
|
static Vector3 _analyticTransmittance(double r, double mu, double d)
|
||||||
|
{
|
||||||
|
return exp(-betaR * _opticalDepth(HR, r, mu, d) - betaMEx * _opticalDepth(HM, r, mu, d));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inscattered light along ray x+tv, when sun in direction s (=S[L]-T(x,x0)S[L]|x0) */
|
||||||
|
static Color _inscatter(Vector3* x, double* t, Vector3 v, Vector3 s, double* _r, double* _mu, Color* attenuation)
|
||||||
|
{
|
||||||
|
Color result;
|
||||||
|
double r = v3Norm(x);
|
||||||
|
double mu = v3Dot(x, v) / r;
|
||||||
|
double d = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rt * Rt);
|
||||||
|
if (d > 0.0)
|
||||||
|
{ // if x in space and ray intersects atmosphere
|
||||||
|
// move x to nearest intersection of ray with top atmosphere boundary
|
||||||
|
x += d * v;
|
||||||
|
t -= d;
|
||||||
|
mu = (r * mu + d) / Rt;
|
||||||
|
r = Rt;
|
||||||
|
}
|
||||||
|
if (r <= Rt)
|
||||||
|
{ // if ray intersects atmosphere
|
||||||
|
double nu = v3Dot(v, s);
|
||||||
|
double muS = v3Dot(x, s) / r;
|
||||||
|
double phaseR = _phaseFunctionR(nu);
|
||||||
|
double phaseM = _phaseFunctionM(nu);
|
||||||
|
vec4 inscatter = max(texture4D(inscatterSampler, r, mu, muS, nu), 0.0);
|
||||||
|
if (t > 0.0)
|
||||||
|
{
|
||||||
|
Vector3 x0 = v3Add(x, v3Scale(v, t));
|
||||||
|
double r0 = v3Norm(x0);
|
||||||
|
double rMu0 = v3Dot(x0, v);
|
||||||
|
double mu0 = rMu0 / r0;
|
||||||
|
double muS0 = v3Dot(x0, s) / r0;
|
||||||
|
#ifdef FIX
|
||||||
|
// avoids imprecision problems in transmittance computations based on textures
|
||||||
|
*attenuation = _analyticTransmittance(r, mu, t);
|
||||||
|
#else
|
||||||
|
*attenuation = _transmittance(r, mu, v, x0);
|
||||||
|
#endif
|
||||||
|
if (r0 > Rg + 0.01)
|
||||||
|
{
|
||||||
|
// computes S[L]-T(x,x0)S[L]|x0
|
||||||
|
inscatter = max(inscatter - attenuation.rgbr * texture4D(inscatterSampler, r0, mu0, muS0, nu), 0.0);
|
||||||
|
#ifdef FIX
|
||||||
|
// avoids imprecision problems near horizon by interpolating between two points above and below horizon
|
||||||
|
const float EPS = 0.004;
|
||||||
|
float muHoriz = -sqrt(1.0 - (Rg / r) * (Rg / r));
|
||||||
|
if (abs(mu - muHoriz) < EPS)
|
||||||
|
{
|
||||||
|
float a = ((mu - muHoriz) + EPS) / (2.0 * EPS);
|
||||||
|
|
||||||
|
mu = muHoriz - EPS;
|
||||||
|
r0 = sqrt(r * r + t * t + 2.0 * r * t * mu);
|
||||||
|
mu0 = (r * mu + t) / r0;
|
||||||
|
vec4 inScatter0 = texture4D(inscatterSampler, r, mu, muS, nu);
|
||||||
|
vec4 inScatter1 = texture4D(inscatterSampler, r0, mu0, muS0, nu);
|
||||||
|
vec4 inScatterA = max(inScatter0 - attenuation.rgbr * inScatter1, 0.0);
|
||||||
|
|
||||||
|
mu = muHoriz + EPS;
|
||||||
|
r0 = sqrt(r * r + t * t + 2.0 * r * t * mu);
|
||||||
|
mu0 = (r * mu + t) / r0;
|
||||||
|
inScatter0 = texture4D(inscatterSampler, r, mu, muS, nu);
|
||||||
|
inScatter1 = texture4D(inscatterSampler, r0, mu0, muS0, nu);
|
||||||
|
vec4 inScatterB = max(inScatter0 - attenuation.rgbr * inScatter1, 0.0);
|
||||||
|
|
||||||
|
inscatter = mix(inScatterA, inScatterB, a);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef FIX
|
||||||
|
// avoids imprecision problems in Mie scattering when sun is below horizon
|
||||||
|
inscatter.w *= smoothstep(0.00, 0.02, muS);
|
||||||
|
#endif
|
||||||
|
result = max(inscatter.rgb * phaseR + getMie(inscatter) * phaseM, 0.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // x in space and ray looking in space
|
||||||
|
result = COLOR_BLACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_r = r;
|
||||||
|
*_mu = mu;
|
||||||
|
result.r *= ISun;
|
||||||
|
result.g *= ISun;
|
||||||
|
result.b *= ISun;
|
||||||
|
result.a = 1.0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*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)
|
||||||
|
{
|
||||||
|
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*]
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // ray looking at the sky
|
||||||
|
return COLOR_BLACK;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
static inline void _getTransmittanceUV(double r, double mu, double* u, double* v)
|
||||||
|
{
|
||||||
|
#ifdef TRANSMITTANCE_NON_LINEAR
|
||||||
|
*v = sqrt((r - Rg) / (Rt - Rg));
|
||||||
|
*u = atan((mu + 0.15) / (1.0 + 0.15) * tan(1.5)) / 1.5;
|
||||||
|
#else
|
||||||
|
*v = (r - Rg) / (Rt - Rg);
|
||||||
|
*u = (mu + 0.15) / (1.0 + 0.15);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* transmittance(=transparency) of atmosphere for infinite ray (r,mu)
|
||||||
|
(mu=cos(view zenith angle)), intersections with ground ignored */
|
||||||
|
static Color _transmittance(double r, double mu)
|
||||||
|
{
|
||||||
|
double u, v;
|
||||||
|
_getTransmittanceUV(r, mu, u, v);
|
||||||
|
return texture2D(transmittanceSampler, uv).rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* transmittance(=transparency) of atmosphere for infinite ray (r,mu)
|
||||||
|
(mu=cos(view zenith angle)), or zero if ray intersects ground */
|
||||||
|
static Color _transmittanceWithShadow(double r, double mu)
|
||||||
|
{
|
||||||
|
return mu < -sqrt(1.0 - (Rg / r) * (Rg / r)) ? COLOR_BLACK : _transmittance(r, mu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
if (t > 0.0)
|
||||||
|
{
|
||||||
|
return COLOR_BLACK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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
|
||||||
|
return transmittance * isun; // Eq (9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color _hdr(Color c1, Color c2, Color c3)
|
||||||
|
{
|
||||||
|
Color L = {c1.r + c2.r + c3.r, c1.g + c2.g + c3.g, c1.b + c2.b + c3.b, 1.0};
|
||||||
|
|
||||||
|
L = L * exposure;
|
||||||
|
L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);
|
||||||
|
L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);
|
||||||
|
L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);
|
||||||
|
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position)
|
||||||
|
{
|
||||||
|
Vector3 x = {0.0, Rg + eye.y, 0.0};
|
||||||
|
Vector3 v = v3Normalize(direction);
|
||||||
|
Vector3 s = v3Normalize(v3Sub(sun_position, eye));
|
||||||
|
|
||||||
|
double r = v3Norm(x);
|
||||||
|
double mu = v3Dot(x, v) / r;
|
||||||
|
double t = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rg * Rg);
|
||||||
|
|
||||||
|
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 = _inscatter(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 sunColor = _sunColor(x, t, v, s, r, mu); //L0
|
||||||
|
return _hdr(sunColor, groundColor, inscatterColor); // Eq (16)
|
||||||
|
}
|
||||||
|
#else
|
||||||
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position)
|
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position)
|
||||||
{
|
{
|
||||||
return COLOR_BLACK;
|
return COLOR_BLACK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "atmosphere.h"
|
#include "public.h"
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "../renderer.h"
|
#include "../renderer.h"
|
||||||
|
|
||||||
static inline double _angleBetween(double thetav, double phiv, double theta, double phi)
|
static inline double _angleBetween(double thetav, double phiv, double theta, double phi)
|
||||||
|
@ -75,7 +77,7 @@ Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3
|
||||||
cosTheta = cos(theta);
|
cosTheta = cos(theta);
|
||||||
}
|
}
|
||||||
|
|
||||||
double T = definition->humidity;
|
double T = definition->humidity * 3.0 + 1.8;
|
||||||
double T2 = T * T;
|
double T2 = T * T;
|
||||||
double suntheta = thetaSun;
|
double suntheta = thetaSun;
|
||||||
double suntheta2 = thetaSun * thetaSun;
|
double suntheta2 = thetaSun * thetaSun;
|
||||||
|
@ -128,5 +130,38 @@ Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3
|
||||||
val2 = (1.0 + AY * exp(BY)) * (1.0 + CY * exp(DY * suntheta) + EY * sqrt(cosSTheta));
|
val2 = (1.0 + AY * exp(BY)) * (1.0 + CY * exp(DY * suntheta) + EY * sqrt(cosSTheta));
|
||||||
double Y = Yz * val1 / val2;
|
double Y = Yz * val1 / val2;
|
||||||
|
|
||||||
return _xyYToRGB(x, y, Y);
|
Color result = _xyYToRGB(x, y, Y);
|
||||||
|
Color humidity_color = {0.8, 0.8, 0.8, definition->humidity * 0.8 * colorGetValue(&result)};
|
||||||
|
colorMask(&result, &humidity_color);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color preethamApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
||||||
|
{
|
||||||
|
Vector3 ray = v3Sub(location, renderer->camera_location);
|
||||||
|
Vector3 direction = v3Normalize(ray);
|
||||||
|
double distance = v3Norm(ray);
|
||||||
|
AtmosphereDefinition* definition = renderer->atmosphere->definition;
|
||||||
|
double near = 10.0 - definition->humidity * 10.0;
|
||||||
|
double far = 100.0 - definition->humidity * 90.0;
|
||||||
|
double max = 0.85 + definition->humidity * 0.12;
|
||||||
|
|
||||||
|
assert(near < far);
|
||||||
|
|
||||||
|
if (distance < near)
|
||||||
|
{
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector3 sun_position = renderer->atmosphere->getSunDirection(renderer);
|
||||||
|
Color sky = preethamGetSkyColor(definition, renderer->camera_location, direction, sun_position);
|
||||||
|
if (distance > far)
|
||||||
|
{
|
||||||
|
distance = far;
|
||||||
|
}
|
||||||
|
sky.a = max * ((distance - near) / (far - near));
|
||||||
|
colorMask(&base, &sky);
|
||||||
|
return base;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
9
lib_paysages/atmosphere/private.h
Normal file
9
lib_paysages/atmosphere/private.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef _PAYSAGES_ATMOSPHERE_PRIVATE_H_
|
||||||
|
#define _PAYSAGES_ATMOSPHERE_PRIVATE_H_
|
||||||
|
|
||||||
|
Color brunetonGetSkyColor(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);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _PAYSAGES_ATMOSPHERE_INTERFACE_H_
|
#ifndef _PAYSAGES_ATMOSPHERE_PUBLIC_H_
|
||||||
#define _PAYSAGES_ATMOSPHERE_INTERFACE_H_
|
#define _PAYSAGES_ATMOSPHERE_PUBLIC_H_
|
||||||
|
|
||||||
#include "../shared/types.h"
|
#include "../shared/types.h"
|
||||||
#include "../euclid.h"
|
#include "../euclid.h"
|
|
@ -2,7 +2,7 @@
|
||||||
#define _PAYSAGES_RENDERER_H_
|
#define _PAYSAGES_RENDERER_H_
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "atmosphere/atmosphere.h"
|
#include "atmosphere/public.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* a standard renderer.
|
* a standard renderer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "atmosphere/atmosphere.h"
|
#include "atmosphere/public.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "clouds.h"
|
#include "clouds.h"
|
||||||
#include "lighting.h"
|
#include "lighting.h"
|
||||||
|
|
Loading…
Reference in a new issue