Restored clouds aspect preview

This commit is contained in:
Michaël Lemaire 2013-12-20 17:30:27 +01:00 committed by Michael Lemaire
parent 1d9f622a26
commit c497cf2127
12 changed files with 180 additions and 89 deletions

View file

@ -2,6 +2,7 @@
#include "BasePreview.h"
#include "Scenery.h"
#include "clouds/BaseCloudsModel.h"
#include "CloudsDefinition.h"
#include "CloudLayerDefinition.h"
#include "CloudsRenderer.h"
@ -9,43 +10,78 @@
#include "LightComponent.h"
#include "AtmosphereResult.h"
/*static void _getLightingStatus(Renderer*, LightStatus* status, Vector3, int)
class FakeCloudModel:public BaseCloudsModel
{
LightComponent light;
light.color.r = 0.5;
light.color.g = 0.5;
light.color.b = 0.5;
light.direction = Vector3(-1.0, 0.5, 1.0).normalize();
light.altered = 1;
light.reflection = 0.0;
status->pushComponent(light);
light.color.r = 0.1;
light.color.g = 0.1;
light.color.b = 0.1;
light.direction = Vector3(1.0, -0.5, -1.0).normalize();
light.altered = 0;
light.reflection = 0.0;
status->pushComponent(light);
}
static double _getDensity(Renderer*, CloudLayerDefinition* layer, Vector3 location)
{
double distance = 2.0 * v3Norm(location) / layer->scaling;
if (distance > 1.0)
public:
FakeCloudModel(BaseCloudsModel* real_model):
BaseCloudsModel(real_model->getLayer()), real_model(real_model)
{
return 0.0;
}
else if (distance < 0.8)
virtual ~FakeCloudModel()
{
return 1.0;
delete real_model;
}
else
virtual void update()
{
return (1.0 - distance) / 0.2;
real_model->update();
}
}*/
virtual void getAltitudeRange(double *min_altitude, double *max_altitude) const
{
real_model->getAltitudeRange(min_altitude, max_altitude);
}
virtual void getDetailRange(double *min_step, double *max_step) const
{
real_model->getDetailRange(min_step, max_step);
*min_step *= 0.4;
*max_step *= 0.4;
}
virtual double getProbability(const Vector3 &location, double radius) const
{
return real_model->getProbability(location, radius);
}
virtual Color filterLight(const Color &light, double length, double density) const
{
return real_model->filterLight(light, length, density);
}
virtual Color applyLightExit(const Color &light, const Vector3 &light_direction, const Vector3 &direction_to_eye) const
{
return real_model->applyLightExit(light, light_direction, direction_to_eye);
}
virtual double getDensity(const Vector3 &location) const override
{
double ymin, ymax, thickness;
getAltitudeRange(&ymin, &ymax);
thickness = ymax - ymin;
Vector3 center(0.0, ymin + thickness * 0.5, 0.0);
double distance = 2.0 * location.sub(center).getNorm() / thickness;
double fallout = 0.7;
if (distance > 1.0)
{
return 0.0;
}
else if (distance < 1.0 - fallout)
{
return 1.0;
}
else
{
double factor = (1.0 - distance) / fallout;
return real_model->getDensity(location) * (1.0 - factor) + factor;
}
}
private:
BaseCloudsModel* real_model;
};
CloudsAspectPreviewRenderer::CloudsAspectPreviewRenderer(CloudLayerDefinition* layer):
layer(layer)
@ -60,35 +96,37 @@ CloudsAspectPreviewRenderer::CloudsAspectPreviewRenderer(CloudLayerDefinition* l
void CloudsAspectPreviewRenderer::bindEvent(BasePreview* preview)
{
preview->configScaling(0.5, 2.0, 0.1, 2.0);
preview->configHdrToneMapping(true);
}
void CloudsAspectPreviewRenderer::updateEvent()
{
CloudLayerDefinition* preview_layer = getScenery()->getClouds()->getCloudLayer(0);
layer->copy(preview_layer);
preview_layer->altitude = -preview_layer->scaling / 2.0;
preview_layer->validate();
preview_layer->coverage = 0.5;
prepare();
//disableAerialPerspective();
//clouds->getLayerDensity = _getDensity;
//atmosphere->getLightingStatus = _getLightingStatus;
disableAtmosphere();
BaseCloudsModel* real_model = getCloudsRenderer()->getLayerModel(0);
getCloudsRenderer()->setLayerModel(0, new FakeCloudModel(real_model), false);
}
Color CloudsAspectPreviewRenderer::getColor2D(double x, double y, double)
{
Vector3 start, end;
double thickness = layer->scaling;
BaseCloudsModel* model = getCloudsRenderer()->getLayerModel(0);
double ymin, ymax, thickness;
model->getAltitudeRange(&ymin, &ymax);
thickness = ymax - ymin;
start.x = x * thickness * 0.5;
start.z = y * thickness * 0.5;
start.y = thickness * 0.5;
start.y = ymin + (1.0 - y) * thickness * 0.5;
start.z = thickness * 0.5;
end.x = start.x;
end.z = start.z;
end.y = -start.y;
end.y = start.y;
end.z = -start.z;
return getCloudsRenderer()->getColor(start, end, COLOR_BLUE);
}

View file

@ -11,6 +11,8 @@ CloudsCoveragePreviewRenderer::CloudsCoveragePreviewRenderer(CloudLayerDefinitio
{
perspective = true;
render_quality = 6;
CloudsDefinition* clouds = getScenery()->getClouds();
clouds->clear();
clouds->addLayer();

View file

@ -50,32 +50,7 @@ void TerrainShapePreviewRenderer::updateEvent()
prepare();
LightComponent light;
std::vector<LightComponent> lights;
light.color.r = 0.6;
light.color.g = 0.6;
light.color.b = 0.6;
light.direction.x = -1.0;
light.direction.y = -0.5;
light.direction.z = 1.0;
light.direction = light.direction.normalize();
light.altered = 1;
light.reflection = 0.0;
lights.push_back(light);
light.color.r = 0.2;
light.color.g = 0.2;
light.color.b = 0.2;
light.direction.x = 1.0;
light.direction.y = -0.5;
light.direction.z = -1.0;
light.direction = light.direction.normalize();
light.altered = 0;
light.reflection = 0.0;
lights.push_back(light);
disableAtmosphere(lights);
disableAtmosphere();
}
Color TerrainShapePreviewRenderer::getColor2D(double x, double y, double scaling)

View file

@ -106,9 +106,16 @@ AtmosphereResult BaseAtmosphereRenderer::getSkyColor(Vector3)
Vector3 BaseAtmosphereRenderer::getSunDirection()
{
AtmosphereDefinition* atmosphere = getDefinition();
double sun_angle = (atmosphere->_daytime + 0.75) * M_PI * 2.0;
return Vector3(cos(sun_angle), sin(sun_angle), 0.0);
if (lights.size() > 0)
{
return lights[0].direction.scale(-1.0);
}
else
{
AtmosphereDefinition* atmosphere = getDefinition();
double sun_angle = (atmosphere->_daytime + 0.75) * M_PI * 2.0;
return Vector3(cos(sun_angle), sin(sun_angle), 0.0);
}
}
void BaseAtmosphereRenderer::setBasicLights()

View file

@ -43,14 +43,14 @@ static inline double _getDistanceToBorder(BaseCloudsModel* model, Vector3 positi
* @param out_segments Allocated space to fill found segments
* @return Number of segments found
*/
static int _findSegments(BaseCloudsModel* model, SoftwareRenderer* renderer, Vector3 start, Vector3 direction, double, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments)
static int _findSegments(BaseCloudsModel* model, SoftwareRenderer* renderer, Vector3 start, Vector3 direction, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments)
{
CloudLayerDefinition* layer = model->getLayer();
double ymin, ymax;
int inside, segment_count;
double current_total_length, current_inside_length;
double step_length, segment_length;
double noise_distance, last_noise_distance;
double min_step, max_step;
double noise_distance;
Vector3 walker, step, segment_start;
double render_precision;
@ -61,8 +61,17 @@ static int _findSegments(BaseCloudsModel* model, SoftwareRenderer* renderer, Vec
model->getAltitudeRange(&ymin, &ymax);
model->getDetailRange(&min_step, &max_step);
render_precision = 15.2 - 1.5 * (double)renderer->render_quality;
render_precision = render_precision * layer->scaling / 50.0;
render_precision = render_precision * (ymax - ymin) / 50.0;
if (render_precision < min_step)
{
render_precision = min_step;
}
else if (render_precision > max_step)
{
render_precision = max_step;
}
if (render_precision > max_total_length / 10.0)
{
render_precision = max_total_length / 10.0;
@ -85,7 +94,6 @@ static int _findSegments(BaseCloudsModel* model, SoftwareRenderer* renderer, Vec
{
walker = walker.add(step);
step_length = step.getNorm();
last_noise_distance = noise_distance;
noise_distance = _getDistanceToBorder(model, walker) * render_precision;
current_total_length += step_length;
@ -143,9 +151,8 @@ static int _findSegments(BaseCloudsModel* model, SoftwareRenderer* renderer, Vec
Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &eye, const Vector3 &location)
{
CloudLayerDefinition* layer = model->getLayer();
int i, segment_count;
double max_length, detail, total_length, inside_length;
double max_length, total_length, inside_length;
Vector3 start, end, direction;
Color result, col;
CloudSegment segments[20];
@ -162,10 +169,11 @@ Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &e
direction = direction.normalize();
result = COLOR_TRANSPARENT;
detail = parent->getPrecision(start) / layer->scaling;
double transparency_depth = layer->scaling * 1.5;
double ymin, ymax;
model->getAltitudeRange(&ymin, &ymax);
double transparency_depth = (ymax - ymin) * 0.3;
segment_count = _findSegments(model, parent, start, direction, detail, 20, transparency_depth, max_length, &inside_length, &total_length, segments);
segment_count = _findSegments(model, parent, start, direction, 20, transparency_depth, max_length, &inside_length, &total_length, segments);
for (i = segment_count - 1; i >= 0; i--)
{
SurfaceMaterial material;
@ -206,8 +214,10 @@ bool CloudBasicLayerRenderer::alterLight(BaseCloudsModel *model, LightComponent*
return false;
}
double light_traversal = model->getLayer()->scaling * 5.0;
_findSegments(model, parent, start, direction, 0.1, 20, light_traversal, end.sub(start).getNorm(), &inside_depth, &total_depth, segments);
double ymin, ymax;
model->getAltitudeRange(&ymin, &ymax);
double light_traversal = (ymax - ymin) * 0.8;
_findSegments(model, parent, start, direction, 20, light_traversal, end.sub(start).getNorm(), &inside_depth, &total_depth, segments);
if (light_traversal < 0.0001)
{

View file

@ -104,11 +104,28 @@ BaseCloudsModel* CloudsRenderer::getLayerModel(unsigned int layer)
}
else
{
qWarning("Asked for unknown layer renderer %d", layer);
qWarning("Asked for unknown layer model %d", layer);
return fake_model;
}
}
void CloudsRenderer::setLayerModel(unsigned int layer, BaseCloudsModel *model, bool delete_old)
{
if (layer < layer_models.size())
{
if (delete_old)
{
delete layer_models[layer];
}
layer_models[layer] = model;
}
else
{
qWarning("Asked to set an unknown layer model %d", layer);
delete model;
}
}
Color CloudsRenderer::getColor(const Vector3 &eye, const Vector3 &location, const Color &base)
{
CloudsDefinition* definition = parent->getScenery()->getClouds();

View file

@ -38,6 +38,14 @@ public:
*/
virtual BaseCloudsModel* getLayerModel(unsigned int layer);
/*!
* \brief Override de default density model for a given layer.
*
* This must be called after each update().
* Ownership of the model is taken.
*/
virtual void setLayerModel(unsigned int layer, BaseCloudsModel* model, bool delete_old=true);
/*!
* \brief Get the composited color, as applied on a base color and location.
*/

View file

@ -21,7 +21,7 @@ void LightStatus::pushComponent(LightComponent component)
Color LightStatus::apply(const Vector3 &normal, const SurfaceMaterial &material)
{
Color final;
Color final(0.0, 0.0, 0.0, 0.0);
for (auto component: components)
{

View file

@ -118,6 +118,36 @@ void SoftwareRenderer::disableClouds()
scenery->getClouds()->clear();
}
void SoftwareRenderer::disableAtmosphere()
{
LightComponent light;
std::vector<LightComponent> lights;
light.color.r = 1.5;
light.color.g = 1.5;
light.color.b = 1.5;
light.direction.x = -1.0;
light.direction.y = -0.5;
light.direction.z = 1.0;
light.direction = light.direction.normalize();
light.altered = 1;
light.reflection = 0.0;
lights.push_back(light);
light.color.r = 0.4;
light.color.g = 0.4;
light.color.b = 0.42;
light.direction.x = 1.0;
light.direction.y = -0.5;
light.direction.z = -1.0;
light.direction = light.direction.normalize();
light.altered = 0;
light.reflection = 0.0;
lights.push_back(light);
disableAtmosphere(lights);
}
void SoftwareRenderer::disableAtmosphere(const std::vector<LightComponent> &lights)
{
scenery->getAtmosphere()->model = AtmosphereDefinition::ATMOSPHERE_MODEL_DISABLED;

View file

@ -75,6 +75,7 @@ public:
*
* This function needs to be called after each prepare().
*/
void disableAtmosphere();
void disableAtmosphere(const std::vector<LightComponent> &lights);
void setPreviewCallbacks(RenderArea::RenderCallbackStart start, RenderArea::RenderCallbackDraw draw, RenderArea::RenderCallbackUpdate update);

View file

@ -23,8 +23,11 @@ void BaseCloudsModel::getAltitudeRange(double *min_altitude, double *max_altitud
void BaseCloudsModel::getDetailRange(double *min_step, double *max_step) const
{
*min_step = 0.1;
*max_step = 1.0;
double min_altitude, max_altitude, thickness;
getAltitudeRange(&min_altitude, &max_altitude);
thickness = max_altitude - min_altitude;
*min_step = thickness * 0.001;
*max_step = thickness * 0.05;
}
double BaseCloudsModel::getProbability(const Vector3 &, double) const

View file

@ -37,15 +37,15 @@ void CloudModelStratoCumulus::update()
void CloudModelStratoCumulus::getAltitudeRange(double *min_altitude, double *max_altitude) const
{
*min_altitude = 2.0 + 7.0 * layer->altitude;
*max_altitude = *min_altitude + 5.0 * layer->scaling;
*min_altitude = 4.0 + 14.0 * layer->altitude;
*max_altitude = *min_altitude + 11.0 * layer->scaling;
}
double CloudModelStratoCumulus::getDensity(const Vector3 &location) const
{
double val;
double min_altitude, max_altitude;
double noise_scaling = 12.0 * layer->scaling;
double noise_scaling = 25.0 * layer->scaling;
getAltitudeRange(&min_altitude, &max_altitude);