From c497cf2127b82834181b9ca6ffe53a797b110b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 20 Dec 2013 17:30:27 +0100 Subject: [PATCH] Restored clouds aspect preview --- .../preview/CloudsAspectPreviewRenderer.cpp | 120 ++++++++++++------ .../preview/CloudsCoveragePreviewRenderer.cpp | 2 + .../preview/TerrainShapePreviewRenderer.cpp | 27 +--- src/render/software/AtmosphereRenderer.cpp | 13 +- .../software/CloudBasicLayerRenderer.cpp | 34 +++-- src/render/software/CloudsRenderer.cpp | 19 ++- src/render/software/CloudsRenderer.h | 8 ++ src/render/software/LightStatus.cpp | 2 +- src/render/software/SoftwareRenderer.cpp | 30 +++++ src/render/software/SoftwareRenderer.h | 1 + .../software/clouds/BaseCloudsModel.cpp | 7 +- .../clouds/CloudModelStratoCumulus.cpp | 6 +- 12 files changed, 180 insertions(+), 89 deletions(-) diff --git a/src/render/preview/CloudsAspectPreviewRenderer.cpp b/src/render/preview/CloudsAspectPreviewRenderer.cpp index a47d2e7..d7cb112 100644 --- a/src/render/preview/CloudsAspectPreviewRenderer.cpp +++ b/src/render/preview/CloudsAspectPreviewRenderer.cpp @@ -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); } diff --git a/src/render/preview/CloudsCoveragePreviewRenderer.cpp b/src/render/preview/CloudsCoveragePreviewRenderer.cpp index 6c6b43f..289ae49 100644 --- a/src/render/preview/CloudsCoveragePreviewRenderer.cpp +++ b/src/render/preview/CloudsCoveragePreviewRenderer.cpp @@ -11,6 +11,8 @@ CloudsCoveragePreviewRenderer::CloudsCoveragePreviewRenderer(CloudLayerDefinitio { perspective = true; + render_quality = 6; + CloudsDefinition* clouds = getScenery()->getClouds(); clouds->clear(); clouds->addLayer(); diff --git a/src/render/preview/TerrainShapePreviewRenderer.cpp b/src/render/preview/TerrainShapePreviewRenderer.cpp index 64afaf2..c7605fc 100644 --- a/src/render/preview/TerrainShapePreviewRenderer.cpp +++ b/src/render/preview/TerrainShapePreviewRenderer.cpp @@ -50,32 +50,7 @@ void TerrainShapePreviewRenderer::updateEvent() prepare(); - LightComponent light; - std::vector 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) diff --git a/src/render/software/AtmosphereRenderer.cpp b/src/render/software/AtmosphereRenderer.cpp index 0e78f6f..5b79eba 100644 --- a/src/render/software/AtmosphereRenderer.cpp +++ b/src/render/software/AtmosphereRenderer.cpp @@ -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() diff --git a/src/render/software/CloudBasicLayerRenderer.cpp b/src/render/software/CloudBasicLayerRenderer.cpp index b59f3d1..dbffe41 100644 --- a/src/render/software/CloudBasicLayerRenderer.cpp +++ b/src/render/software/CloudBasicLayerRenderer.cpp @@ -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) { diff --git a/src/render/software/CloudsRenderer.cpp b/src/render/software/CloudsRenderer.cpp index 16236ea..69286a6 100644 --- a/src/render/software/CloudsRenderer.cpp +++ b/src/render/software/CloudsRenderer.cpp @@ -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(); diff --git a/src/render/software/CloudsRenderer.h b/src/render/software/CloudsRenderer.h index 8631887..59c4695 100644 --- a/src/render/software/CloudsRenderer.h +++ b/src/render/software/CloudsRenderer.h @@ -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. */ diff --git a/src/render/software/LightStatus.cpp b/src/render/software/LightStatus.cpp index cceac2e..a424267 100644 --- a/src/render/software/LightStatus.cpp +++ b/src/render/software/LightStatus.cpp @@ -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) { diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp index 5817772..c0d8882 100644 --- a/src/render/software/SoftwareRenderer.cpp +++ b/src/render/software/SoftwareRenderer.cpp @@ -118,6 +118,36 @@ void SoftwareRenderer::disableClouds() scenery->getClouds()->clear(); } +void SoftwareRenderer::disableAtmosphere() +{ + LightComponent light; + std::vector 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 &lights) { scenery->getAtmosphere()->model = AtmosphereDefinition::ATMOSPHERE_MODEL_DISABLED; diff --git a/src/render/software/SoftwareRenderer.h b/src/render/software/SoftwareRenderer.h index c4f03fa..4894949 100644 --- a/src/render/software/SoftwareRenderer.h +++ b/src/render/software/SoftwareRenderer.h @@ -75,6 +75,7 @@ public: * * This function needs to be called after each prepare(). */ + void disableAtmosphere(); void disableAtmosphere(const std::vector &lights); void setPreviewCallbacks(RenderArea::RenderCallbackStart start, RenderArea::RenderCallbackDraw draw, RenderArea::RenderCallbackUpdate update); diff --git a/src/render/software/clouds/BaseCloudsModel.cpp b/src/render/software/clouds/BaseCloudsModel.cpp index 7e943e5..71483ac 100644 --- a/src/render/software/clouds/BaseCloudsModel.cpp +++ b/src/render/software/clouds/BaseCloudsModel.cpp @@ -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 diff --git a/src/render/software/clouds/CloudModelStratoCumulus.cpp b/src/render/software/clouds/CloudModelStratoCumulus.cpp index b10f92f..f186903 100644 --- a/src/render/software/clouds/CloudModelStratoCumulus.cpp +++ b/src/render/software/clouds/CloudModelStratoCumulus.cpp @@ -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);