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 "BasePreview.h"
#include "Scenery.h" #include "Scenery.h"
#include "clouds/BaseCloudsModel.h"
#include "CloudsDefinition.h" #include "CloudsDefinition.h"
#include "CloudLayerDefinition.h" #include "CloudLayerDefinition.h"
#include "CloudsRenderer.h" #include "CloudsRenderer.h"
@ -9,43 +10,78 @@
#include "LightComponent.h" #include "LightComponent.h"
#include "AtmosphereResult.h" #include "AtmosphereResult.h"
/*static void _getLightingStatus(Renderer*, LightStatus* status, Vector3, int) class FakeCloudModel:public BaseCloudsModel
{ {
LightComponent light; public:
FakeCloudModel(BaseCloudsModel* real_model):
light.color.r = 0.5; BaseCloudsModel(real_model->getLayer()), real_model(real_model)
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)
{ {
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): CloudsAspectPreviewRenderer::CloudsAspectPreviewRenderer(CloudLayerDefinition* layer):
layer(layer) layer(layer)
@ -60,35 +96,37 @@ CloudsAspectPreviewRenderer::CloudsAspectPreviewRenderer(CloudLayerDefinition* l
void CloudsAspectPreviewRenderer::bindEvent(BasePreview* preview) void CloudsAspectPreviewRenderer::bindEvent(BasePreview* preview)
{ {
preview->configScaling(0.5, 2.0, 0.1, 2.0); preview->configScaling(0.5, 2.0, 0.1, 2.0);
preview->configHdrToneMapping(true);
} }
void CloudsAspectPreviewRenderer::updateEvent() void CloudsAspectPreviewRenderer::updateEvent()
{ {
CloudLayerDefinition* preview_layer = getScenery()->getClouds()->getCloudLayer(0); CloudLayerDefinition* preview_layer = getScenery()->getClouds()->getCloudLayer(0);
layer->copy(preview_layer); layer->copy(preview_layer);
preview_layer->coverage = 0.5;
preview_layer->altitude = -preview_layer->scaling / 2.0;
preview_layer->validate();
prepare(); prepare();
//disableAerialPerspective(); disableAtmosphere();
//clouds->getLayerDensity = _getDensity; BaseCloudsModel* real_model = getCloudsRenderer()->getLayerModel(0);
//atmosphere->getLightingStatus = _getLightingStatus; getCloudsRenderer()->setLayerModel(0, new FakeCloudModel(real_model), false);
} }
Color CloudsAspectPreviewRenderer::getColor2D(double x, double y, double) Color CloudsAspectPreviewRenderer::getColor2D(double x, double y, double)
{ {
Vector3 start, end; 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.x = x * thickness * 0.5;
start.z = y * thickness * 0.5; start.y = ymin + (1.0 - y) * thickness * 0.5;
start.y = thickness * 0.5; start.z = thickness * 0.5;
end.x = start.x; 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); return getCloudsRenderer()->getColor(start, end, COLOR_BLUE);
} }

View file

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

View file

@ -50,32 +50,7 @@ void TerrainShapePreviewRenderer::updateEvent()
prepare(); prepare();
LightComponent light; disableAtmosphere();
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);
} }
Color TerrainShapePreviewRenderer::getColor2D(double x, double y, double scaling) Color TerrainShapePreviewRenderer::getColor2D(double x, double y, double scaling)

View file

@ -106,9 +106,16 @@ AtmosphereResult BaseAtmosphereRenderer::getSkyColor(Vector3)
Vector3 BaseAtmosphereRenderer::getSunDirection() Vector3 BaseAtmosphereRenderer::getSunDirection()
{ {
AtmosphereDefinition* atmosphere = getDefinition(); if (lights.size() > 0)
double sun_angle = (atmosphere->_daytime + 0.75) * M_PI * 2.0; {
return Vector3(cos(sun_angle), sin(sun_angle), 0.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() 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 * @param out_segments Allocated space to fill found segments
* @return Number of segments found * @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; double ymin, ymax;
int inside, segment_count; int inside, segment_count;
double current_total_length, current_inside_length; double current_total_length, current_inside_length;
double step_length, segment_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; Vector3 walker, step, segment_start;
double render_precision; double render_precision;
@ -61,8 +61,17 @@ static int _findSegments(BaseCloudsModel* model, SoftwareRenderer* renderer, Vec
model->getAltitudeRange(&ymin, &ymax); model->getAltitudeRange(&ymin, &ymax);
model->getDetailRange(&min_step, &max_step);
render_precision = 15.2 - 1.5 * (double)renderer->render_quality; 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) if (render_precision > max_total_length / 10.0)
{ {
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); walker = walker.add(step);
step_length = step.getNorm(); step_length = step.getNorm();
last_noise_distance = noise_distance;
noise_distance = _getDistanceToBorder(model, walker) * render_precision; noise_distance = _getDistanceToBorder(model, walker) * render_precision;
current_total_length += step_length; 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) Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &eye, const Vector3 &location)
{ {
CloudLayerDefinition* layer = model->getLayer();
int i, segment_count; int i, segment_count;
double max_length, detail, total_length, inside_length; double max_length, total_length, inside_length;
Vector3 start, end, direction; Vector3 start, end, direction;
Color result, col; Color result, col;
CloudSegment segments[20]; CloudSegment segments[20];
@ -162,10 +169,11 @@ Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &e
direction = direction.normalize(); direction = direction.normalize();
result = COLOR_TRANSPARENT; result = COLOR_TRANSPARENT;
detail = parent->getPrecision(start) / layer->scaling; double ymin, ymax;
double transparency_depth = layer->scaling * 1.5; 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--) for (i = segment_count - 1; i >= 0; i--)
{ {
SurfaceMaterial material; SurfaceMaterial material;
@ -206,8 +214,10 @@ bool CloudBasicLayerRenderer::alterLight(BaseCloudsModel *model, LightComponent*
return false; return false;
} }
double light_traversal = model->getLayer()->scaling * 5.0; double ymin, ymax;
_findSegments(model, parent, start, direction, 0.1, 20, light_traversal, end.sub(start).getNorm(), &inside_depth, &total_depth, segments); 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) if (light_traversal < 0.0001)
{ {

View file

@ -104,11 +104,28 @@ BaseCloudsModel* CloudsRenderer::getLayerModel(unsigned int layer)
} }
else else
{ {
qWarning("Asked for unknown layer renderer %d", layer); qWarning("Asked for unknown layer model %d", layer);
return fake_model; 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) Color CloudsRenderer::getColor(const Vector3 &eye, const Vector3 &location, const Color &base)
{ {
CloudsDefinition* definition = parent->getScenery()->getClouds(); CloudsDefinition* definition = parent->getScenery()->getClouds();

View file

@ -38,6 +38,14 @@ public:
*/ */
virtual BaseCloudsModel* getLayerModel(unsigned int layer); 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. * \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 LightStatus::apply(const Vector3 &normal, const SurfaceMaterial &material)
{ {
Color final; Color final(0.0, 0.0, 0.0, 0.0);
for (auto component: components) for (auto component: components)
{ {

View file

@ -118,6 +118,36 @@ void SoftwareRenderer::disableClouds()
scenery->getClouds()->clear(); 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) void SoftwareRenderer::disableAtmosphere(const std::vector<LightComponent> &lights)
{ {
scenery->getAtmosphere()->model = AtmosphereDefinition::ATMOSPHERE_MODEL_DISABLED; scenery->getAtmosphere()->model = AtmosphereDefinition::ATMOSPHERE_MODEL_DISABLED;

View file

@ -75,6 +75,7 @@ public:
* *
* This function needs to be called after each prepare(). * This function needs to be called after each prepare().
*/ */
void disableAtmosphere();
void disableAtmosphere(const std::vector<LightComponent> &lights); void disableAtmosphere(const std::vector<LightComponent> &lights);
void setPreviewCallbacks(RenderArea::RenderCallbackStart start, RenderArea::RenderCallbackDraw draw, RenderArea::RenderCallbackUpdate update); 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 void BaseCloudsModel::getDetailRange(double *min_step, double *max_step) const
{ {
*min_step = 0.1; double min_altitude, max_altitude, thickness;
*max_step = 1.0; 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 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 void CloudModelStratoCumulus::getAltitudeRange(double *min_altitude, double *max_altitude) const
{ {
*min_altitude = 2.0 + 7.0 * layer->altitude; *min_altitude = 4.0 + 14.0 * layer->altitude;
*max_altitude = *min_altitude + 5.0 * layer->scaling; *max_altitude = *min_altitude + 11.0 * layer->scaling;
} }
double CloudModelStratoCumulus::getDensity(const Vector3 &location) const double CloudModelStratoCumulus::getDensity(const Vector3 &location) const
{ {
double val; double val;
double min_altitude, max_altitude; double min_altitude, max_altitude;
double noise_scaling = 12.0 * layer->scaling; double noise_scaling = 25.0 * layer->scaling;
getAltitudeRange(&min_altitude, &max_altitude); getAltitudeRange(&min_altitude, &max_altitude);