Restored clouds aspect preview
This commit is contained in:
parent
1d9f622a26
commit
c497cf2127
12 changed files with 180 additions and 89 deletions
|
@ -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
|
||||
{
|
||||
public:
|
||||
FakeCloudModel(BaseCloudsModel* real_model):
|
||||
BaseCloudsModel(real_model->getLayer()), real_model(real_model)
|
||||
{
|
||||
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)
|
||||
virtual ~FakeCloudModel()
|
||||
{
|
||||
double distance = 2.0 * v3Norm(location) / layer->scaling;
|
||||
delete real_model;
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
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 < 0.8)
|
||||
else if (distance < 1.0 - fallout)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (1.0 - distance) / 0.2;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ CloudsCoveragePreviewRenderer::CloudsCoveragePreviewRenderer(CloudLayerDefinitio
|
|||
{
|
||||
perspective = true;
|
||||
|
||||
render_quality = 6;
|
||||
|
||||
CloudsDefinition* clouds = getScenery()->getClouds();
|
||||
clouds->clear();
|
||||
clouds->addLayer();
|
||||
|
|
|
@ -50,32 +50,7 @@ void TerrainShapePreviewRenderer::updateEvent()
|
|||
|
||||
prepare();
|
||||
|
||||
LightComponent light;
|
||||
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);
|
||||
disableAtmosphere();
|
||||
}
|
||||
|
||||
Color TerrainShapePreviewRenderer::getColor2D(double x, double y, double scaling)
|
||||
|
|
|
@ -105,11 +105,18 @@ AtmosphereResult BaseAtmosphereRenderer::getSkyColor(Vector3)
|
|||
}
|
||||
|
||||
Vector3 BaseAtmosphereRenderer::getSunDirection()
|
||||
{
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -118,6 +118,36 @@ void SoftwareRenderer::disableClouds()
|
|||
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)
|
||||
{
|
||||
scenery->getAtmosphere()->model = AtmosphereDefinition::ATMOSPHERE_MODEL_DISABLED;
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
*
|
||||
* This function needs to be called after each prepare().
|
||||
*/
|
||||
void disableAtmosphere();
|
||||
void disableAtmosphere(const std::vector<LightComponent> &lights);
|
||||
|
||||
void setPreviewCallbacks(RenderArea::RenderCallbackStart start, RenderArea::RenderCallbackDraw draw, RenderArea::RenderCallbackUpdate update);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue