Some tweaks to improve clouds aspect

This commit is contained in:
Michaël Lemaire 2016-01-10 17:14:54 +01:00
parent 3b27d3be3e
commit c0a4e93c52
9 changed files with 48 additions and 35 deletions

View file

@ -167,6 +167,16 @@ void Color::limitPower(double max_power) {
}
}
void Color::scale(double factor) {
r *= factor;
g *= factor;
b *= factor;
}
Color Color::scaled(double factor) const {
return Color(r * factor, g * factor, b * factor, a);
}
Color Color::add(const Color &other) const {
return Color(r + other.r, g + other.g, b + other.b, a);
}

View file

@ -32,6 +32,15 @@ class BASICSSHARED_EXPORT Color {
double getPower() const;
void limitPower(double max_power);
/**
* Scale the RGB components by a factor.
*/
void scale(double factor);
/**
* Return a copy, with RGB components scaled by a factor.
*/
Color scaled(double factor) const;
Color add(const Color &other) const;
Color lerp(const Color &other, double f) const;

View file

@ -5,5 +5,5 @@
GodRaysDefinition::GodRaysDefinition(DefinitionNode *parent) : DefinitionNode(parent, "godrays", "godrays") {
penetration = new FloatNode(this, "penetration", 0.01);
resistance = new FloatNode(this, "resistance", 0.3);
boost = new FloatNode(this, "boost", 8.0);
boost = new FloatNode(this, "boost", 3.0);
}

View file

@ -80,7 +80,7 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
material->shininess = 4.0;
break;
case TEXTURES_LAYER_PRESET_ROCK:
terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 1.0, 1.0);
terrain_zone->addHeightRangeQuick(1.0, 0.55, 0.7, 0.9, 1.0);
displacement_noise->setConfig(1.0, 0.3, 0.5, 0.85);
detail_noise->setConfig(0.02, 0.04);
material->setColor(0.6, 0.55, 0.57, 1.0);

View file

@ -1069,7 +1069,7 @@ AtmosphereModelBruneton::~AtmosphereModelBruneton() {
}
AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3 &direction,
const Vector3 &sun_position, const Color &base) {
const Vector3 &sun_position, const Color &base) const {
Vector3 x = {0.0, Rg + eye.y * WORLD_SCALING, 0.0};
Vector3 v = direction.normalize();
Vector3 s = sun_position.sub(x).normalize();
@ -1096,7 +1096,7 @@ AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3
return result;
}
AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 location, const Color &base) {
AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 location, const Color &base) const {
Vector3 eye = parent->getCameraLocation(location);
eye.y = max(eye.y, 0.0);
location.y = max(location.y, 0.0);

View file

@ -13,8 +13,8 @@ class SOFTWARESHARED_EXPORT AtmosphereModelBruneton : public LightSource {
AtmosphereModelBruneton(SoftwareRenderer *parent);
virtual ~AtmosphereModelBruneton();
AtmosphereResult getSkyColor(Vector3 eye, const Vector3 &direction, const Vector3 &sun_position, const Color &base);
AtmosphereResult applyAerialPerspective(Vector3 location, const Color &base);
AtmosphereResult getSkyColor(Vector3 eye, const Vector3 &direction, const Vector3 &sun_position, const Color &base) const;
AtmosphereResult applyAerialPerspective(Vector3 location, const Color &base) const;
virtual bool getLightsAt(vector<LightComponent> &result, const Vector3 &location) const override;
/* Functions to get access to internal textures (for opengl shaders) */

View file

@ -2,6 +2,7 @@
#include <cassert>
#include <cmath>
#include <algorithm>
#include "CloudLayerDefinition.h"
#include "SoftwareRenderer.h"
#include "NoiseGenerator.h"
@ -63,12 +64,9 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
model->getAltitudeRange(&ymin, &ymax);
model->getDetailRange(&min_step, &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;
} else if (render_precision < max_total_length / 2000.0) {
render_precision = max_total_length / 2000.0;
}
double distance = parent->getCameraLocation(start).sub(start).getNorm();
render_precision = min_step + (max_step - min_step) * min(distance / (quality + 0.1), 100.0) * 0.01;
segment_count = 0;
current_total_length = 0.0;
@ -121,6 +119,8 @@ int CloudBasicLayerRenderer::findSegments(BaseCloudsModel *model, const Vector3
step = direction.scale((noise_distance > -render_precision) ? render_precision : -noise_distance);
}
}
render_precision *= 1.0 + 0.001 / (quality + 0.1);
} while (inside || (walker.y >= ymin - 0.001 && walker.y <= ymax + 0.001 &&
current_total_length < max_total_length && current_inside_length < max_inside_length));
@ -134,7 +134,7 @@ Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &e
double max_length, total_length, inside_length;
Vector3 start, end, direction;
Color result, col;
CloudSegment segments[20];
CloudSegment segments[30];
start = eye;
end = location;
@ -149,25 +149,18 @@ Color CloudBasicLayerRenderer::getColor(BaseCloudsModel *model, const Vector3 &e
double ymin, ymax;
model->getAltitudeRange(&ymin, &ymax);
double transparency_depth = (ymax - ymin) * 0.5;
double transparency_depth = (ymax - ymin);
segment_count = findSegments(model, start, direction, 20, transparency_depth, max_length, &inside_length,
SurfaceMaterial material(COLOR_WHITE.scaled(5.0));
material.hardness = 1.0;
material.reflection = 0.0;
material.shininess = 0.0;
material.validate();
segment_count = findSegments(model, start, direction, 30, transparency_depth, max_length, &inside_length,
&total_length, segments);
for (i = segment_count - 1; i >= 0; i--) {
SurfaceMaterial material(COLOR_WHITE);
material.hardness = 0.25;
material.reflection = 0.0;
material.shininess = 0.0;
material.validate();
col = parent->applyLightingToSurface(segments[i].start, parent->getAtmosphereRenderer()->getSunDirection(),
material);
// Boost highly lighted area
double boost = 1.0 + (col.getPower() * col.getPower());
col.r *= boost;
col.g *= boost;
col.b *= boost;
col = parent->applyLightingToSurface(segments[i].start, VECTOR_UP, material);
col.a = (segments[i].length >= transparency_depth) ? 1.0 : (segments[i].length / transparency_depth);
result.mask(col);
@ -197,7 +190,7 @@ bool CloudBasicLayerRenderer::alterLight(BaseCloudsModel *model, LightComponent
const Vector3 &location) {
Vector3 start, end, direction;
double inside_depth, total_depth, factor;
CloudSegment segments[20];
CloudSegment segments[30];
start = location;
direction = light->direction.scale(-1.0);
@ -208,8 +201,8 @@ bool CloudBasicLayerRenderer::alterLight(BaseCloudsModel *model, LightComponent
double ymin, ymax;
model->getAltitudeRange(&ymin, &ymax);
double light_traversal = (ymax - ymin) * 1.2;
findSegments(model, start, direction, 20, light_traversal, end.sub(start).getNorm(), &inside_depth, &total_depth,
double light_traversal = (ymax - ymin) * 0.8 * light->color.getPower();
findSegments(model, start, direction, 30, light_traversal, end.sub(start).getNorm(), &inside_depth, &total_depth,
segments);
if (light_traversal < 0.0001) {
@ -223,7 +216,7 @@ bool CloudBasicLayerRenderer::alterLight(BaseCloudsModel *model, LightComponent
}
}
double miminum_light = 0.3;
double miminum_light = 0.01 * light->color.getPower();
factor = 1.0 - (1.0 - miminum_light) * factor;
light->color.r *= factor;

View file

@ -97,6 +97,7 @@ void SoftwareRenderer::prepare() {
void SoftwareRenderer::setQuality(double quality) {
terrain_renderer->setQuality(quality);
textures_renderer->setQuality(quality);
clouds_renderer->setQuality(quality);
godrays->setQuality(quality);

View file

@ -33,14 +33,14 @@ void CloudModelStratoCumulus::update() {
}
void CloudModelStratoCumulus::getAltitudeRange(double *min_altitude, double *max_altitude) const {
*min_altitude = 10.0 + 10.0 * layer->altitude;
*min_altitude = 20.0 + 10.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 = 25.0 * layer->scaling;
double noise_scaling = 30.0 * layer->scaling;
getAltitudeRange(&min_altitude, &max_altitude);