From cd7eb2f669d54e46e493902dfc37f12fc030dc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 13 Sep 2015 18:58:11 +0200 Subject: [PATCH] Refactored clouds rendering quality factor --- src/interface/commandline/tests.cpp | 25 ++++++++++++++++++- .../software/BaseCloudLayerRenderer.cpp | 6 +++++ src/render/software/BaseCloudLayerRenderer.h | 3 +++ .../software/CloudBasicLayerRenderer.cpp | 22 ++++++---------- src/render/software/CloudBasicLayerRenderer.h | 5 ++++ src/render/software/CloudsRenderer.cpp | 12 +++++++++ src/render/software/CloudsRenderer.h | 7 ++++++ .../software/SoftwareCanvasRenderer.cpp | 10 ++++++++ src/render/software/SoftwareCanvasRenderer.h | 8 ++++++ src/render/software/SoftwareRenderer.cpp | 1 + .../software/clouds/BaseCloudsModel.cpp | 2 +- 11 files changed, 84 insertions(+), 17 deletions(-) diff --git a/src/interface/commandline/tests.cpp b/src/interface/commandline/tests.cpp index 7d83f4a..d8786d1 100644 --- a/src/interface/commandline/tests.cpp +++ b/src/interface/commandline/tests.cpp @@ -9,6 +9,7 @@ #include "WaterDefinition.h" #include "SurfaceMaterial.h" #include "FloatNode.h" +#include "SkyRasterizer.h" #include @@ -60,7 +61,7 @@ static void testGroundShadowQuality() renderer.setQuality(0.2); for (int i = 0; i < 6; i++) { - // TODO keep same rasterization across renders, or keep rasterization quality low + // TODO keep same rasterization across renders renderer.getTerrainRenderer()->setQuality((double)i / 5.0); startTestRender(&renderer, "ground_shadow_quality", i); } @@ -81,9 +82,31 @@ static void testRasterizationQuality() } } +static void testCloudQuality() +{ + Scenery scenery; + scenery.autoPreset(3); + scenery.getCamera()->setLocation(Vector3(5.0, 5.0, 5.0)); + scenery.getCamera()->setTarget(Vector3(8.0, 7.25, 8.0)); + scenery.getTerrain()->height = 0.0; + scenery.getTerrain()->validate(); + + SoftwareCanvasRenderer renderer(&scenery); + renderer.setSize(600, 800); + SkyRasterizer *rasterizer = new SkyRasterizer(&renderer, renderer.getProgressHelper(), 0); + renderer.setSoloRasterizer(rasterizer); + for (int i = 0; i < 6; i++) + { + renderer.setQuality((double)i / 5.0); + rasterizer->setQuality(0.2); + startTestRender(&renderer, "cloud_quality", i); + } +} + void runTestSuite() { testGroundShadowQuality(); testRasterizationQuality(); + testCloudQuality(); } diff --git a/src/render/software/BaseCloudLayerRenderer.cpp b/src/render/software/BaseCloudLayerRenderer.cpp index 6443de2..c553313 100644 --- a/src/render/software/BaseCloudLayerRenderer.cpp +++ b/src/render/software/BaseCloudLayerRenderer.cpp @@ -6,6 +6,7 @@ BaseCloudLayerRenderer::BaseCloudLayerRenderer(SoftwareRenderer* parent): parent(parent) { + setQuality(0.5); } BaseCloudLayerRenderer::~BaseCloudLayerRenderer() @@ -23,6 +24,11 @@ bool BaseCloudLayerRenderer::alterLight(BaseCloudsModel *, LightComponent *, con return false; } +void BaseCloudLayerRenderer::setQuality(double quality) +{ + this->quality = quality; +} + bool BaseCloudLayerRenderer::optimizeSearchLimits(BaseCloudsModel *model, Vector3 *start, Vector3 *end) { Vector3 diff; diff --git a/src/render/software/BaseCloudLayerRenderer.h b/src/render/software/BaseCloudLayerRenderer.h index bc8e714..dc2e451 100644 --- a/src/render/software/BaseCloudLayerRenderer.h +++ b/src/render/software/BaseCloudLayerRenderer.h @@ -17,8 +17,11 @@ public: virtual Color getColor(BaseCloudsModel *model, const Vector3 &eye, const Vector3 &location); virtual bool alterLight(BaseCloudsModel *model, LightComponent* light, const Vector3 &eye, const Vector3 &location); + virtual void setQuality(double quality); + protected: SoftwareRenderer* parent; + double quality; }; } diff --git a/src/render/software/CloudBasicLayerRenderer.cpp b/src/render/software/CloudBasicLayerRenderer.cpp index 09c8a6c..bd9253c 100644 --- a/src/render/software/CloudBasicLayerRenderer.cpp +++ b/src/render/software/CloudBasicLayerRenderer.cpp @@ -9,13 +9,14 @@ #include "LightComponent.h" #include "clouds/BaseCloudsModel.h" #include "SurfaceMaterial.h" +#include "Logs.h" -typedef struct +struct CloudSegment { Vector3 start; Vector3 end; double length; -} CloudSegment; +}; CloudBasicLayerRenderer::CloudBasicLayerRenderer(SoftwareRenderer* parent): BaseCloudLayerRenderer(parent) @@ -43,7 +44,7 @@ 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, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments) +int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3 &start, const Vector3 &direction, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments) { double ymin, ymax; int inside, segment_count; @@ -62,16 +63,7 @@ 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 * (ymax - ymin) / 50.0; - if (render_precision < min_step) - { - render_precision = min_step; - } - else if (render_precision > max_step) - { - render_precision = max_step; - } + render_precision = max_step - quality * (max_step - min_step); if (render_precision > max_total_length / 10.0) { render_precision = max_total_length / 10.0; @@ -173,7 +165,7 @@ Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &e model->getAltitudeRange(&ymin, &ymax); double transparency_depth = (ymax - ymin) * 0.5; - segment_count = _findSegments(model, parent, start, direction, 20, transparency_depth, max_length, &inside_length, &total_length, segments); + segment_count = findSegments(model, start, direction, 20, transparency_depth, max_length, &inside_length, &total_length, segments); for (i = segment_count - 1; i >= 0; i--) { SurfaceMaterial material(COLOR_WHITE); @@ -224,7 +216,7 @@ bool CloudBasicLayerRenderer::alterLight(BaseCloudsModel *model, LightComponent* double ymin, ymax; model->getAltitudeRange(&ymin, &ymax); double light_traversal = (ymax - ymin) * 1.2; - _findSegments(model, parent, start, direction, 20, light_traversal, end.sub(start).getNorm(), &inside_depth, &total_depth, segments); + findSegments(model, 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/CloudBasicLayerRenderer.h b/src/render/software/CloudBasicLayerRenderer.h index 83305f2..ebeaaf0 100644 --- a/src/render/software/CloudBasicLayerRenderer.h +++ b/src/render/software/CloudBasicLayerRenderer.h @@ -5,6 +5,8 @@ #include "BaseCloudLayerRenderer.h" +typedef struct CloudSegment CloudSegment; + namespace paysages { namespace software { @@ -21,6 +23,9 @@ public: virtual Color getColor(BaseCloudsModel *model, const Vector3 &eye, const Vector3 &location) override; virtual bool alterLight(BaseCloudsModel *model, LightComponent* light, const Vector3 &eye, const Vector3 &location) override; + +private: + int findSegments(BaseCloudsModel* model, const Vector3 &start, const Vector3 &direction, int max_segments, double max_inside_length, double max_total_length, double* inside_length, double* total_length, CloudSegment* out_segments); }; } diff --git a/src/render/software/CloudsRenderer.cpp b/src/render/software/CloudsRenderer.cpp index d7aae61..db8c19e 100644 --- a/src/render/software/CloudsRenderer.cpp +++ b/src/render/software/CloudsRenderer.cpp @@ -17,6 +17,7 @@ CloudsRenderer::CloudsRenderer(SoftwareRenderer* parent): parent(parent) { + quality = 0.5; enabled = true; fake_renderer = new BaseCloudLayerRenderer(parent); @@ -40,6 +41,15 @@ CloudsRenderer::~CloudsRenderer() delete fake_model; } +void CloudsRenderer::setQuality(double factor) +{ + this->quality = factor; + for (auto &renderer: layer_renderers) + { + renderer->setQuality(factor); + } +} + void CloudsRenderer::setEnabled(bool enabled) { this->enabled = enabled; @@ -94,6 +104,8 @@ void CloudsRenderer::update() layer_models.push_back(model); model->update(); } + + setQuality(quality); } BaseCloudLayerRenderer* CloudsRenderer::getLayerRenderer(unsigned int layer) diff --git a/src/render/software/CloudsRenderer.h b/src/render/software/CloudsRenderer.h index fa2b515..be1686a 100644 --- a/src/render/software/CloudsRenderer.h +++ b/src/render/software/CloudsRenderer.h @@ -17,6 +17,11 @@ public: CloudsRenderer(SoftwareRenderer* parent); virtual ~CloudsRenderer(); + /** + * Set the quality factor (0.0-1.0) for clouds rendering. + */ + void setQuality(double factor); + /** * Enable or disable the whole cloud rendering. */ @@ -63,6 +68,8 @@ public: */ virtual bool applyLightFilter(LightComponent &light, const Vector3 &at) override; private: + double quality; + bool enabled; SoftwareRenderer* parent; diff --git a/src/render/software/SoftwareCanvasRenderer.cpp b/src/render/software/SoftwareCanvasRenderer.cpp index 01a91ab..607b11b 100644 --- a/src/render/software/SoftwareCanvasRenderer.cpp +++ b/src/render/software/SoftwareCanvasRenderer.cpp @@ -55,6 +55,16 @@ void SoftwareCanvasRenderer::setQuality(double factor) } } +void SoftwareCanvasRenderer::setSoloRasterizer(Rasterizer *rasterizer) +{ + for (auto &rast: rasterizers) + { + delete rast; + } + rasterizers.clear(); + rasterizers.push_back(rasterizer); +} + double SoftwareCanvasRenderer::getProgress() const { return progress->get(); diff --git a/src/render/software/SoftwareCanvasRenderer.h b/src/render/software/SoftwareCanvasRenderer.h index 9673af3..f793217 100644 --- a/src/render/software/SoftwareCanvasRenderer.h +++ b/src/render/software/SoftwareCanvasRenderer.h @@ -23,10 +23,18 @@ public: virtual ~SoftwareCanvasRenderer(); inline const Canvas *getCanvas() const {return canvas;} + inline RenderProgress *getProgressHelper() const {return progress;} inline bool isFinished() const {return finished;} virtual void setQuality(double factor) override; + /** + * Clear the rasterizers list, and put a single one. + * + * The renderer takes ownership of the rasterizer. + */ + void setSoloRasterizer(Rasterizer *rasterizer); + /** * Get the global rendering progress (0.0-1.0). */ diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp index 120232d..8e9d66e 100644 --- a/src/render/software/SoftwareRenderer.cpp +++ b/src/render/software/SoftwareRenderer.cpp @@ -90,6 +90,7 @@ void SoftwareRenderer::prepare() void SoftwareRenderer::setQuality(double quality) { terrain_renderer->setQuality(quality); + clouds_renderer->setQuality(quality); // TEMP compat with old code render_quality = (int)(quality * 9.0) + 1; diff --git a/src/render/software/clouds/BaseCloudsModel.cpp b/src/render/software/clouds/BaseCloudsModel.cpp index 71483ac..f1c6162 100644 --- a/src/render/software/clouds/BaseCloudsModel.cpp +++ b/src/render/software/clouds/BaseCloudsModel.cpp @@ -27,7 +27,7 @@ void BaseCloudsModel::getDetailRange(double *min_step, double *max_step) const getAltitudeRange(&min_altitude, &max_altitude); thickness = max_altitude - min_altitude; *min_step = thickness * 0.001; - *max_step = thickness * 0.05; + *max_step = thickness * 0.2; } double BaseCloudsModel::getProbability(const Vector3 &, double) const