diff --git a/src/definition/TextureLayerDefinition.cpp b/src/definition/TextureLayerDefinition.cpp index d85442c..f43c9bc 100644 --- a/src/definition/TextureLayerDefinition.cpp +++ b/src/definition/TextureLayerDefinition.cpp @@ -80,7 +80,7 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera break; case TEXTURES_LAYER_PRESET_ROCK: terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 0.87, 0.95); - displacement_noise->setConfig(4.0, 0.3, 0.5, 0.85); + displacement_noise->setConfig(4.0, 0.15, 0.5, 0.8); detail_noise->setConfig(0.02, 0.04); material->setColor(0.6, 0.55, 0.57, 1.0); material->reflection = 0.006; diff --git a/src/render/software/AtmosphereRenderer.cpp b/src/render/software/AtmosphereRenderer.cpp index 988dd21..a739ba9 100644 --- a/src/render/software/AtmosphereRenderer.cpp +++ b/src/render/software/AtmosphereRenderer.cpp @@ -10,6 +10,7 @@ #include "LightStatus.h" #include "Scenery.h" #include "NightSky.h" +#include "MoonRenderer.h" #include "CelestialBodyDefinition.h" #include "FloatNode.h" @@ -171,6 +172,9 @@ AtmosphereResult SoftwareBrunetonAtmosphereRenderer::getSkyColor(const Vector3 & } }*/ + // Get the moon + base.mask(parent->getMoonRenderer().getColor(camera_location, direction_norm, parent->getLightingManager())); + // Get scattering AtmosphereResult result; Vector3 location = camera_location.add(direction_norm.scale(Scenery::FAR_LIMIT_SCALED)); @@ -194,6 +198,7 @@ AtmosphereResult SoftwareBrunetonAtmosphereRenderer::getSkyColor(const Vector3 & bool SoftwareBrunetonAtmosphereRenderer::getLightsAt(vector &result, const Vector3 &location) const { bool changed = false; changed |= model->getLightsAt(result, location); + // FIXME Should be registered on its own changed |= parent->getNightSky()->getLightsAt(result, location); return changed; } diff --git a/src/render/software/MoonRenderer.cpp b/src/render/software/MoonRenderer.cpp new file mode 100644 index 0000000..21e8c1e --- /dev/null +++ b/src/render/software/MoonRenderer.cpp @@ -0,0 +1,72 @@ +#include "MoonRenderer.h" + +#include "CelestialBodyDefinition.h" +#include "Color.h" +#include "LightingManager.h" +#include "Geometry.h" +#include "SurfaceMaterial.h" +#include "FloatNode.h" + +class MoonRenderer::pimpl { + public: + pimpl() : definition(NULL, "moon"), material(Color(3.0, 3.0, 3.0)) { + // TODO Put material in scenery + } + CelestialBodyDefinition definition; + SurfaceMaterial material; +}; + +MoonRenderer::MoonRenderer(CelestialBodyDefinition *moon_node) : impl(new pimpl()) { + startWatching(moon_node->getRoot(), moon_node->getPath()); + + // FIXME should not be needed because the above watcher should watch the whole node + // and call nodeChanged + moon_node->copy(&impl->definition); +} + +MoonRenderer::~MoonRenderer() { +} + +void MoonRenderer::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) { + if (auto moon_node = static_cast(node)) { + moon_node->copy(&impl->definition); + } +} + +bool MoonRenderer::getLightsAt(vector &result, const Vector3 &location) const { + LightComponent light; + + // TODO Don't add if its contribution is negligible + // TODO Take moon phase into account + + light.color = Color(0.03, 0.03, 0.03); + light.direction = location.sub(impl->definition.getLocation()).normalize(); + light.reflection = 0.2; + light.altered = true; + + result.push_back(light); + return true; +} + +Color MoonRenderer::getColor(const Vector3 &eye, const Vector3 &direction, LightingManager *lighting) const { + auto moon_location = impl->definition.getLocation(); + auto moon_direction = moon_location.sub(eye).normalize(); + if (moon_direction.dotProduct(direction) >= 0) { + // TODO Alter radius near horizon (lens effect) + double moon_radius = impl->definition.propRadius()->getValue(); + Vector3 hit1, hit2; + int hits = Geometry::rayIntersectSphere(eye, direction, moon_location, moon_radius, &hit1, &hit2); + if (hits > 1) { + // distance between intersection points (relative to radius) + double dist = hit2.sub(hit1).getNorm() / moon_radius; + auto nearest = (hit1.sub(eye).getNorm() > hit2.sub(eye).getNorm()) ? hit2 : hit1; + + auto moon_color = lighting->apply(eye, nearest, nearest.sub(moon_location).normalize(), impl->material); + if (dist <= 0.05) { + moon_color.a *= 1.0 - dist / 0.05; + } + return moon_color; + } + } + return COLOR_TRANSPARENT; +} diff --git a/src/render/software/MoonRenderer.h b/src/render/software/MoonRenderer.h new file mode 100644 index 0000000..3bcbf99 --- /dev/null +++ b/src/render/software/MoonRenderer.h @@ -0,0 +1,40 @@ +#ifndef MOONRENDERER_H +#define MOONRENDERER_H + +#include "software_global.h" + +#include "DefinitionWatcher.h" +#include "LightSource.h" + +#include + +namespace paysages { +namespace software { + +/** + * Moon renderer. + */ +class SOFTWARESHARED_EXPORT MoonRenderer : public DefinitionWatcher, public LightSource { + public: + MoonRenderer(CelestialBodyDefinition *moon_node); + virtual ~MoonRenderer(); + + virtual void nodeChanged(const DefinitionNode *node, const DefinitionDiff *diff) override; + virtual bool getLightsAt(vector &result, const Vector3 &location) const override; + + /** + * Get the final moon color, given a looking ray. + * + * The result will be lighted with *lighting*. + */ + Color getColor(const Vector3 &eye, const Vector3 &direction, LightingManager *lighting) const; + + private: + class pimpl; + unique_ptr impl; + +}; +} +} + +#endif // MOONRENDERER_H diff --git a/src/render/software/NightSky.cpp b/src/render/software/NightSky.cpp index 70c570e..adb9916 100644 --- a/src/render/software/NightSky.cpp +++ b/src/render/software/NightSky.cpp @@ -51,44 +51,11 @@ const Color NightSky::getColor(double altitude, const Vector3 &direction) { } } - // Get moon - Vector3 moon_position = atmosphere->childMoon()->getLocation(); - Vector3 moon_direction = moon_position.sub(renderer->getCameraLocation()).normalize(); - if (moon_direction.dotProduct(direction) >= 0) { - double moon_radius = atmosphere->childMoon()->propRadius()->getValue(); - Vector3 hit1, hit2; - int hits = Geometry::rayIntersectSphere(location, direction, moon_position, moon_radius, &hit1, &hit2); - if (hits > 1) { - double dist = - hit2.sub(hit1).getNorm() / moon_radius; // distance between intersection points (relative to radius) - - Vector3 nearest = (hit1.sub(location).getNorm() > hit2.sub(location).getNorm()) ? hit2 : hit1; - SurfaceMaterial moon_material(Color(3.0, 3.0, 3.0)); - moon_material.validate(); - - Color moon_color = - renderer->applyLightingToSurface(nearest, nearest.sub(moon_position).normalize(), moon_material); - if (dist <= 0.05) { - moon_color.a *= 1.0 - dist / 0.05; - } - result.mask(moon_color); - } - } - return result; } -bool NightSky::getLightsAt(vector &result, const Vector3 &loc) const { - LightComponent moon, sky; - - AtmosphereDefinition *atmosphere = renderer->getScenery()->getAtmosphere(); - - moon.color = Color(0.03, 0.03, 0.03); // TODO take moon phase into account - moon.direction = loc.sub(atmosphere->childMoon()->getLocation()).normalize(); - moon.reflection = 0.2; - moon.altered = 1; - - result.push_back(moon); +bool NightSky::getLightsAt(vector &result, const Vector3 &) const { + LightComponent sky; sky.color = Color(0.01, 0.012, 0.03); sky.direction = VECTOR_DOWN; diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp index 48be00d..ee59d17 100644 --- a/src/render/software/SoftwareRenderer.cpp +++ b/src/render/software/SoftwareRenderer.cpp @@ -16,6 +16,7 @@ #include "TerrainRasterizer.h" #include "WaterRasterizer.h" #include "NightSky.h" +#include "MoonRenderer.h" #include "LightStatus.h" #include "LightingManager.h" #include "GodRaysSampler.h" @@ -37,6 +38,7 @@ SoftwareRenderer::SoftwareRenderer(Scenery *scenery) : scenery(scenery) { water_renderer = new WaterRenderer(this); nightsky_renderer = new NightSky(this); + moon_renderer = new MoonRenderer(scenery->getAtmosphere()->childMoon()); fluid_medium = new FluidMediumManager(this); lighting = new LightingManager(); @@ -47,6 +49,7 @@ SoftwareRenderer::SoftwareRenderer(Scenery *scenery) : scenery(scenery) { lighting->registerFilter(vegetation_renderer); lighting->registerFilter(clouds_renderer); lighting->registerSource(atmosphere_renderer); + lighting->registerSource(moon_renderer); setQuality(0.5); } @@ -59,6 +62,7 @@ SoftwareRenderer::~SoftwareRenderer() { delete godrays; delete nightsky_renderer; + delete moon_renderer; delete atmosphere_renderer; delete clouds_renderer; diff --git a/src/render/software/SoftwareRenderer.h b/src/render/software/SoftwareRenderer.h index 0175576..803395b 100644 --- a/src/render/software/SoftwareRenderer.h +++ b/src/render/software/SoftwareRenderer.h @@ -68,6 +68,9 @@ class SOFTWARESHARED_EXPORT SoftwareRenderer { inline NightSky *getNightSky() const { return nightsky_renderer; } + inline const MoonRenderer &getMoonRenderer() const { + return *moon_renderer; + } inline FluidMediumManager *getFluidMediumManager() const { return fluid_medium; @@ -98,6 +101,7 @@ class SOFTWARESHARED_EXPORT SoftwareRenderer { TexturesRenderer *textures_renderer; WaterRenderer *water_renderer; NightSky *nightsky_renderer; + MoonRenderer *moon_renderer; VegetationRenderer *vegetation_renderer; }; } diff --git a/src/render/software/software_global.h b/src/render/software/software_global.h index a5682a0..e5a3f72 100644 --- a/src/render/software/software_global.h +++ b/src/render/software/software_global.h @@ -49,6 +49,7 @@ class RayCastingManager; class RayCastingResult; class NightSky; +class MoonRenderer; class TerrainRayWalker;