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 "SurfaceMaterial.h"
#include "FloatNode.h"
#include "SkyRasterizer.h"
#include <sstream>
@ -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();
}

View file

@ -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;

View file

@ -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;
};
}

View file

@ -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)
{

View file

@ -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);
};
}

View file

@ -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)

View file

@ -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;

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
{
return progress->get();

View file

@ -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).
*/

View file

@ -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;

View file

@ -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