Fixed aerial perspective being applied at wrong location in clouds

It was applied at the enter point of the walking algorithm, which
was the camera when it was inside a cloud layer.

Now it is applied at the first found segment, which is still not
optimal but better.

The bruneton model was also fixed to not produce black results for
aerial perspective exactly at the camera location.
This commit is contained in:
Michaël Lemaire 2015-10-09 00:43:32 +02:00
parent a5c36f90f0
commit 2be80bf8e2
3 changed files with 36 additions and 4 deletions

View file

@ -210,6 +210,23 @@ static void testNearFrustum()
startTestRender(&renderer, "near_frustum"); startTestRender(&renderer, "near_frustum");
} }
static void testCloudsNearGround()
{
Scenery scenery;
scenery.autoPreset(8);
scenery.getAtmosphere()->setDayTime(6, 20);
SoftwareCanvasRenderer renderer(&scenery);
renderer.setSize(400, 300);
renderer.setQuality(0.3);
startTestRender(&renderer, "clouds_near_ground", 1);
scenery.getCamera()->strafeUp(6.0);
scenery.getCamera()->copy(renderer.render_camera);
startTestRender(&renderer, "clouds_near_ground", 2);
}
void runTestSuite() void runTestSuite()
{ {
testGroundShadowQuality(); testGroundShadowQuality();
@ -217,4 +234,5 @@ void runTestSuite()
testCloudQuality(); testCloudQuality();
testGodRays(); testGodRays();
testNearFrustum(); testNearFrustum();
testCloudsNearGround();
} }

View file

@ -1191,6 +1191,12 @@ AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 locatio
Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(SUN_DISTANCE); Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(SUN_DISTANCE);
Vector3 direction = location.sub(eye).scale(WORLD_SCALING); Vector3 direction = location.sub(eye).scale(WORLD_SCALING);
double t = direction.getNorm();
if (t < 0.000001)
{
direction = parent->getCameraDirection(location).scale(0.001 * WORLD_SCALING);
t = direction.getNorm();
}
Vector3 x = {0.0, Rg + WORKAROUND_OFFSET + eye.y * WORLD_SCALING, 0.0}; Vector3 x = {0.0, Rg + WORKAROUND_OFFSET + eye.y * WORLD_SCALING, 0.0};
Vector3 v = direction.normalize(); Vector3 v = direction.normalize();
@ -1203,7 +1209,6 @@ AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 locatio
double r = x.getNorm(); double r = x.getNorm();
double mu = x.dotProduct(v) / r; double mu = x.dotProduct(v) / r;
double t = direction.getNorm();
AtmosphereResult result; AtmosphereResult result;
Vector3 attenuation; Vector3 attenuation;

View file

@ -11,6 +11,8 @@
#include "SurfaceMaterial.h" #include "SurfaceMaterial.h"
#include "Logs.h" #include "Logs.h"
#include <cassert>
struct CloudSegment struct CloudSegment
{ {
Vector3 start; Vector3 start;
@ -196,9 +198,16 @@ Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &e
result.a += (1.0 - result.a) * ((inside_length - transparency_depth * 0.8) / (transparency_depth * 0.2)); result.a += (1.0 - result.a) * ((inside_length - transparency_depth * 0.8) / (transparency_depth * 0.2));
} }
double a = result.a; // Apply aerial perspective
result = parent->getAtmosphereRenderer()->applyAerialPerspective(start, result).final; if (result.a > 0.00001)
result.a = a; {
assert(segment_count > 0);
double a = result.a;
// TODO Don't apply it only at first segment
result = parent->getAtmosphereRenderer()->applyAerialPerspective(segments[0].start, result).final;
result.a = a;
}
return result; return result;
} }