From 46148424c0433c6c8dba2b7d0607e4140289ec47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 18 Mar 2013 21:07:57 +0000 Subject: [PATCH] paysages : Polished weather effects. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@542 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- TODO | 1 + gui_qt/formatmosphere.cpp | 2 +- lib_paysages/atmosphere/bruneton.c | 19 ++++---- lib_paysages/atmosphere/presets.c | 6 +-- lib_paysages/atmosphere/public.h | 2 + lib_paysages/atmosphere/render.c | 72 +++++++++++++++++++++++------- 6 files changed, 74 insertions(+), 28 deletions(-) diff --git a/TODO b/TODO index df6b752..1b7ce29 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,5 @@ Technology Preview 2 : +- Better time selection widget for atmosphere. - Replace terrain canvas editor by full sculpting editor. => Add a generation dialog, with fixed resolution. => Store local terrain modifications in fully dynamic canvas. diff --git a/gui_qt/formatmosphere.cpp b/gui_qt/formatmosphere.cpp index 867861d..3d44004 100644 --- a/gui_qt/formatmosphere.cpp +++ b/gui_qt/formatmosphere.cpp @@ -84,7 +84,7 @@ FormAtmosphere::FormAtmosphere(QWidget *parent): //addInputColor(tr("Sun color"), &_definition->sun_color); addInputDouble(tr("Sun radius"), &_definition->sun_radius, 0.0, 5.0, 0.05, 0.5); //addInputDouble(tr("Influence of skydome on lighting"), &_definition->dome_lighting, 0.0, 2.0, 0.01, 0.1); - /*addInputDouble(tr("Humidity"), &_definition->humidity, 0.0, 1.0, 0.01, 0.1);*/ + addInputDouble(tr("Humidity"), &_definition->humidity, 0.0, 1.0, 0.01, 0.1); revertConfig(); } diff --git a/lib_paysages/atmosphere/bruneton.c b/lib_paysages/atmosphere/bruneton.c index 5fc93a5..64f93ab 100644 --- a/lib_paysages/atmosphere/bruneton.c +++ b/lib_paysages/atmosphere/bruneton.c @@ -919,10 +919,10 @@ static Color _getInscatterColor(Vector3* _x, double* _t, Vector3 v, Vector3 s, d } /* direct sun light for ray x+tv, when sun in direction s (=L0) */ -static Color _sunColor(Vector3 v, Vector3 s, double r, double mu) +static Color _sunColor(Vector3 v, Vector3 s, double r, double mu, double radius) { 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(radius * M_PI / 180.0), v3Dot(v, s)) * ISun; /* Lsun */ transmittance.r *= isun; transmittance.g *= isun; transmittance.b *= isun; @@ -1169,15 +1169,14 @@ AtmosphereResult brunetonGetSkyColor(Renderer* renderer, Vector3 eye, Vector3 di AtmosphereResult result; Vector3 attenuation; - Color sunColor = _sunColor(v, s, r, mu); /* L0 */ + Color sunColor = _sunColor(v, s, r, mu, renderer->atmosphere->definition->sun_radius); /* L0 */ - result.base.r = base.r + sunColor.r; + atmosphereInitResult(&result); + /*result.base.r = base.r + sunColor.r; result.base.g = base.g + sunColor.g; - result.base.b = base.b + sunColor.b; + result.base.b = base.b + sunColor.b;*/ + result.base = sunColor; result.inscattering = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */ - result.attenuation.r = 1.0; - result.attenuation.g = 1.0; - result.attenuation.b = 1.0; /* TODO Use atmosphere attenuation */ result.distance = SPHERE_SIZE; @@ -1220,12 +1219,14 @@ AtmosphereResult brunetonApplyAerialPerspective(Renderer* renderer, Vector3 loca AtmosphereResult result; Vector3 attenuation; + atmosphereInitResult(&result); + result.base = base; result.inscattering = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */ result.attenuation.r = attenuation.x; result.attenuation.g = attenuation.y; result.attenuation.b = attenuation.z; - result.distance = t; + result.distance = t / WORLD_SCALING; atmosphereUpdateResult(&result); diff --git a/lib_paysages/atmosphere/presets.c b/lib_paysages/atmosphere/presets.c index fb70c32..308d4d6 100644 --- a/lib_paysages/atmosphere/presets.c +++ b/lib_paysages/atmosphere/presets.c @@ -32,19 +32,19 @@ void atmosphereAutoPreset(AtmosphereDefinition* definition, AtmospherePreset pre definition->hour = 8; definition->minute = 30; definition->dome_lighting = 0.25; - definition->humidity = 0.3; + definition->humidity = 0.4; break; case ATMOSPHERE_PRESET_FOGGY: definition->hour = 15; definition->minute = 0; definition->dome_lighting = 0.1; - definition->humidity = 0.5; + definition->humidity = 0.7; break; case ATMOSPHERE_PRESET_STORMY: definition->hour = 15; definition->minute = 0; definition->dome_lighting = 0.05; - definition->humidity = 0.8; + definition->humidity = 0.9; break; default: ; diff --git a/lib_paysages/atmosphere/public.h b/lib_paysages/atmosphere/public.h index dd925bc..459c281 100644 --- a/lib_paysages/atmosphere/public.h +++ b/lib_paysages/atmosphere/public.h @@ -45,6 +45,7 @@ typedef struct double distance; Color inscattering; Color attenuation; + Color mask; Color final; } AtmosphereResult; @@ -72,6 +73,7 @@ void atmosphereAutoPreset(AtmosphereDefinition* definition, AtmospherePreset pre void atmosphereRenderSkydome(Renderer* renderer); +void atmosphereInitResult(AtmosphereResult* result); void atmosphereUpdateResult(AtmosphereResult* result); Renderer* atmosphereCreatePreviewRenderer(); diff --git a/lib_paysages/atmosphere/render.c b/lib_paysages/atmosphere/render.c index 957a6ba..61148a3 100644 --- a/lib_paysages/atmosphere/render.c +++ b/lib_paysages/atmosphere/render.c @@ -57,23 +57,53 @@ static void _fakeGetLightingStatus(Renderer* renderer, LightStatus* status, Vect } /******************** Real ********************/ +static inline double _getDayFactor(double daytime) +{ + daytime = 1.0 - fabs(0.5 - daytime) / 0.5; + return daytime < 0.45 ? 0.0 : sqrt((daytime - 0.45) / 0.55); +} + static inline void _applyWeatherEffects(AtmosphereDefinition* definition, AtmosphereResult* result) { double distance = result->distance; + double max_distance = 100.0 - 90.0 * definition->humidity; + double distancefactor, dayfactor; - if (distance > 100.0) + if (distance > max_distance) { - distance = 100.0; + distance = max_distance; } - distance /= 100.0; + distancefactor = (distance > max_distance ? max_distance : distance) / max_distance; + /* TODO Get day lighting from model */ + dayfactor = _getDayFactor(definition->_daytime); - result->inscattering.r += distance * 0.2 * definition->humidity; - result->inscattering.g += distance * 0.2 * definition->humidity; - result->inscattering.b += distance * 0.2 * definition->humidity; + /* Fog masking */ + if (definition->humidity > 0.3) + { + result->mask.r = result->mask.g = result->mask.b = (10.0 - 8.0 * definition->humidity) * dayfactor; + result->mask.a = distancefactor * (definition->humidity - 0.3) / 0.7; + } - result->attenuation.r *= 1.0 - distance * definition->humidity; - result->attenuation.g *= 1.0 - distance * definition->humidity; - result->attenuation.b *= 1.0 - distance * definition->humidity; + /* Scattering tweaking */ + if (definition->humidity < 0.15) + { + /* Limit scattering on ultra clear day */ + double force = (0.15 - definition->humidity) / 0.15; + colorLimitPower(&result->inscattering, 100.0 - 90.0 * pow(force, 0.1)); + } + else + { + /* Scattering boost */ + double force = 1.2 * (definition->humidity < 0.5 ? sqrt((definition->humidity - 0.15) / 0.35) : 1.0 - (definition->humidity - 0.5) / 0.5); + result->inscattering.r *= 1.0 + force * distancefactor * (definition->humidity - 0.15) / 0.85; + result->inscattering.g *= 1.0 + force * distancefactor * (definition->humidity - 0.15) / 0.85; + result->inscattering.b *= 1.0 + force * distancefactor * (definition->humidity - 0.15) / 0.85; + } + + /* Attenuation */ + result->attenuation.r *= 1.0 - 0.4 * distancefactor * definition->humidity; + result->attenuation.g *= 1.0 - 0.4 * distancefactor * definition->humidity; + result->attenuation.b *= 1.0 - 0.4 * distancefactor * definition->humidity; atmosphereUpdateResult(result); } @@ -94,7 +124,7 @@ static AtmosphereResult _realApplyAerialPerspective(Renderer* renderer, Vector3 } /* Apply weather effects */ - /*_applyWeatherEffects(definition, &result);*/ + _applyWeatherEffects(definition, &result); return result; } @@ -114,14 +144,14 @@ static AtmosphereResult _realGetSkyColor(Renderer* renderer, Vector3 direction) /* Get sun shape */ base = COLOR_BLACK; - if (v3Dot(sun_direction, direction) >= 0) + /*if (v3Dot(sun_direction, direction) >= 0) { - double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED * 5.0; /* FIXME Why should we multiply by 5 ? */ + double sun_radius = definition->sun_radius * SUN_RADIUS_SCALED * 5.0; // FIXME Why should we multiply by 5 ? Vector3 hit1, hit2; int hits = euclidRayIntersectSphere(camera_location, direction, sun_position, sun_radius, &hit1, &hit2); if (hits > 1) { - double dist = v3Norm(v3Sub(hit2, hit1)) / sun_radius; /* distance between intersection points (relative to radius) */ + double dist = v3Norm(v3Sub(hit2, hit1)) / sun_radius; // distance between intersection points (relative to radius) Color sun_color = definition->sun_color; sun_color.r *= 100.0; @@ -136,7 +166,7 @@ static AtmosphereResult _realGetSkyColor(Renderer* renderer, Vector3 direction) } base = sun_color; } - } + }*/ /* TODO Get stars */ @@ -153,7 +183,7 @@ static AtmosphereResult _realGetSkyColor(Renderer* renderer, Vector3 direction) } /* Apply weather effects */ - /*_applyWeatherEffects(definition, &result);*/ + _applyWeatherEffects(definition, &result); return result; } @@ -168,12 +198,24 @@ static Vector3 _realGetSunDirection(Renderer* renderer) return result; } +void atmosphereInitResult(AtmosphereResult* result) +{ + result->base = COLOR_BLACK; + result->inscattering = COLOR_BLACK; + result->attenuation = COLOR_WHITE; + result->mask = COLOR_TRANSPARENT; + result->distance = 0.0; + result->final = COLOR_BLACK; +} + void atmosphereUpdateResult(AtmosphereResult* result) { result->final.r = result->base.r * result->attenuation.r + result->inscattering.r; result->final.g = result->base.g * result->attenuation.g + result->inscattering.g; result->final.b = result->base.b * result->attenuation.b + result->inscattering.b; result->final.a = 1.0; + + colorMask(&result->final, &result->mask); } /******************** Renderer ********************/