Refactored clouds rendering quality factor

This commit is contained in:
Michaël Lemaire 2015-09-13 18:58:11 +02:00
parent 6a8fc7b102
commit cd7eb2f669
11 changed files with 84 additions and 17 deletions

View file

@ -9,6 +9,7 @@
#include "WaterDefinition.h" #include "WaterDefinition.h"
#include "SurfaceMaterial.h" #include "SurfaceMaterial.h"
#include "FloatNode.h" #include "FloatNode.h"
#include "SkyRasterizer.h"
#include <sstream> #include <sstream>
@ -60,7 +61,7 @@ static void testGroundShadowQuality()
renderer.setQuality(0.2); renderer.setQuality(0.2);
for (int i = 0; i < 6; i++) 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); renderer.getTerrainRenderer()->setQuality((double)i / 5.0);
startTestRender(&renderer, "ground_shadow_quality", i); 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() void runTestSuite()
{ {
testGroundShadowQuality(); testGroundShadowQuality();
testRasterizationQuality(); testRasterizationQuality();
testCloudQuality();
} }

View file

@ -6,6 +6,7 @@
BaseCloudLayerRenderer::BaseCloudLayerRenderer(SoftwareRenderer* parent): BaseCloudLayerRenderer::BaseCloudLayerRenderer(SoftwareRenderer* parent):
parent(parent) parent(parent)
{ {
setQuality(0.5);
} }
BaseCloudLayerRenderer::~BaseCloudLayerRenderer() BaseCloudLayerRenderer::~BaseCloudLayerRenderer()
@ -23,6 +24,11 @@ bool BaseCloudLayerRenderer::alterLight(BaseCloudsModel *, LightComponent *, con
return false; return false;
} }
void BaseCloudLayerRenderer::setQuality(double quality)
{
this->quality = quality;
}
bool BaseCloudLayerRenderer::optimizeSearchLimits(BaseCloudsModel *model, Vector3 *start, Vector3 *end) bool BaseCloudLayerRenderer::optimizeSearchLimits(BaseCloudsModel *model, Vector3 *start, Vector3 *end)
{ {
Vector3 diff; Vector3 diff;

View file

@ -17,8 +17,11 @@ public:
virtual Color getColor(BaseCloudsModel *model, const Vector3 &eye, const Vector3 &location); 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 bool alterLight(BaseCloudsModel *model, LightComponent* light, const Vector3 &eye, const Vector3 &location);
virtual void setQuality(double quality);
protected: protected:
SoftwareRenderer* parent; SoftwareRenderer* parent;
double quality;
}; };
} }

View file

@ -9,13 +9,14 @@
#include "LightComponent.h" #include "LightComponent.h"
#include "clouds/BaseCloudsModel.h" #include "clouds/BaseCloudsModel.h"
#include "SurfaceMaterial.h" #include "SurfaceMaterial.h"
#include "Logs.h"
typedef struct struct CloudSegment
{ {
Vector3 start; Vector3 start;
Vector3 end; Vector3 end;
double length; double length;
} CloudSegment; };
CloudBasicLayerRenderer::CloudBasicLayerRenderer(SoftwareRenderer* parent): CloudBasicLayerRenderer::CloudBasicLayerRenderer(SoftwareRenderer* parent):
BaseCloudLayerRenderer(parent) BaseCloudLayerRenderer(parent)
@ -43,7 +44,7 @@ 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, 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; double ymin, ymax;
int inside, segment_count; int inside, segment_count;
@ -62,16 +63,7 @@ static int _findSegments(BaseCloudsModel* model, SoftwareRenderer* renderer, Vec
model->getAltitudeRange(&ymin, &ymax); model->getAltitudeRange(&ymin, &ymax);
model->getDetailRange(&min_step, &max_step); model->getDetailRange(&min_step, &max_step);
render_precision = 15.2 - 1.5 * (double)renderer->render_quality; render_precision = max_step - quality * (max_step - min_step);
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;
@ -173,7 +165,7 @@ Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &e
model->getAltitudeRange(&ymin, &ymax); model->getAltitudeRange(&ymin, &ymax);
double transparency_depth = (ymax - ymin) * 0.5; 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--) for (i = segment_count - 1; i >= 0; i--)
{ {
SurfaceMaterial material(COLOR_WHITE); SurfaceMaterial material(COLOR_WHITE);
@ -224,7 +216,7 @@ bool CloudBasicLayerRenderer::alterLight(BaseCloudsModel *model, LightComponent*
double ymin, ymax; double ymin, ymax;
model->getAltitudeRange(&ymin, &ymax); model->getAltitudeRange(&ymin, &ymax);
double light_traversal = (ymax - ymin) * 1.2; 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) if (light_traversal < 0.0001)
{ {

View file

@ -5,6 +5,8 @@
#include "BaseCloudLayerRenderer.h" #include "BaseCloudLayerRenderer.h"
typedef struct CloudSegment CloudSegment;
namespace paysages { namespace paysages {
namespace software { namespace software {
@ -21,6 +23,9 @@ public:
virtual Color getColor(BaseCloudsModel *model, const Vector3 &eye, const Vector3 &location) override; 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; 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);
}; };
} }

View file

@ -17,6 +17,7 @@
CloudsRenderer::CloudsRenderer(SoftwareRenderer* parent): CloudsRenderer::CloudsRenderer(SoftwareRenderer* parent):
parent(parent) parent(parent)
{ {
quality = 0.5;
enabled = true; enabled = true;
fake_renderer = new BaseCloudLayerRenderer(parent); fake_renderer = new BaseCloudLayerRenderer(parent);
@ -40,6 +41,15 @@ CloudsRenderer::~CloudsRenderer()
delete fake_model; delete fake_model;
} }
void CloudsRenderer::setQuality(double factor)
{
this->quality = factor;
for (auto &renderer: layer_renderers)
{
renderer->setQuality(factor);
}
}
void CloudsRenderer::setEnabled(bool enabled) void CloudsRenderer::setEnabled(bool enabled)
{ {
this->enabled = enabled; this->enabled = enabled;
@ -94,6 +104,8 @@ void CloudsRenderer::update()
layer_models.push_back(model); layer_models.push_back(model);
model->update(); model->update();
} }
setQuality(quality);
} }
BaseCloudLayerRenderer* CloudsRenderer::getLayerRenderer(unsigned int layer) BaseCloudLayerRenderer* CloudsRenderer::getLayerRenderer(unsigned int layer)

View file

@ -17,6 +17,11 @@ public:
CloudsRenderer(SoftwareRenderer* parent); CloudsRenderer(SoftwareRenderer* parent);
virtual ~CloudsRenderer(); virtual ~CloudsRenderer();
/**
* Set the quality factor (0.0-1.0) for clouds rendering.
*/
void setQuality(double factor);
/** /**
* Enable or disable the whole cloud rendering. * Enable or disable the whole cloud rendering.
*/ */
@ -63,6 +68,8 @@ public:
*/ */
virtual bool applyLightFilter(LightComponent &light, const Vector3 &at) override; virtual bool applyLightFilter(LightComponent &light, const Vector3 &at) override;
private: private:
double quality;
bool enabled; bool enabled;
SoftwareRenderer* parent; SoftwareRenderer* parent;

View file

@ -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 double SoftwareCanvasRenderer::getProgress() const
{ {
return progress->get(); return progress->get();

View file

@ -23,10 +23,18 @@ public:
virtual ~SoftwareCanvasRenderer(); virtual ~SoftwareCanvasRenderer();
inline const Canvas *getCanvas() const {return canvas;} inline const Canvas *getCanvas() const {return canvas;}
inline RenderProgress *getProgressHelper() const {return progress;}
inline bool isFinished() const {return finished;} inline bool isFinished() const {return finished;}
virtual void setQuality(double factor) override; 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). * Get the global rendering progress (0.0-1.0).
*/ */

View file

@ -90,6 +90,7 @@ void SoftwareRenderer::prepare()
void SoftwareRenderer::setQuality(double quality) void SoftwareRenderer::setQuality(double quality)
{ {
terrain_renderer->setQuality(quality); terrain_renderer->setQuality(quality);
clouds_renderer->setQuality(quality);
// TEMP compat with old code // TEMP compat with old code
render_quality = (int)(quality * 9.0) + 1; render_quality = (int)(quality * 9.0) + 1;

View file

@ -27,7 +27,7 @@ void BaseCloudsModel::getDetailRange(double *min_step, double *max_step) const
getAltitudeRange(&min_altitude, &max_altitude); getAltitudeRange(&min_altitude, &max_altitude);
thickness = max_altitude - min_altitude; thickness = max_altitude - min_altitude;
*min_step = thickness * 0.001; *min_step = thickness * 0.001;
*max_step = thickness * 0.05; *max_step = thickness * 0.2;
} }
double BaseCloudsModel::getProbability(const Vector3 &, double) const double BaseCloudsModel::getProbability(const Vector3 &, double) const