Separated MoonRenderer

This commit is contained in:
Michaël Lemaire 2016-01-16 15:05:01 +01:00
parent f4bc02c5ca
commit 5778154aae
8 changed files with 129 additions and 36 deletions

View file

@ -80,7 +80,7 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
break; break;
case TEXTURES_LAYER_PRESET_ROCK: case TEXTURES_LAYER_PRESET_ROCK:
terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 0.87, 0.95); 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); detail_noise->setConfig(0.02, 0.04);
material->setColor(0.6, 0.55, 0.57, 1.0); material->setColor(0.6, 0.55, 0.57, 1.0);
material->reflection = 0.006; material->reflection = 0.006;

View file

@ -10,6 +10,7 @@
#include "LightStatus.h" #include "LightStatus.h"
#include "Scenery.h" #include "Scenery.h"
#include "NightSky.h" #include "NightSky.h"
#include "MoonRenderer.h"
#include "CelestialBodyDefinition.h" #include "CelestialBodyDefinition.h"
#include "FloatNode.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 // Get scattering
AtmosphereResult result; AtmosphereResult result;
Vector3 location = camera_location.add(direction_norm.scale(Scenery::FAR_LIMIT_SCALED)); 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<LightComponent> &result, const Vector3 &location) const { bool SoftwareBrunetonAtmosphereRenderer::getLightsAt(vector<LightComponent> &result, const Vector3 &location) const {
bool changed = false; bool changed = false;
changed |= model->getLightsAt(result, location); changed |= model->getLightsAt(result, location);
// FIXME Should be registered on its own
changed |= parent->getNightSky()->getLightsAt(result, location); changed |= parent->getNightSky()->getLightsAt(result, location);
return changed; return changed;
} }

View file

@ -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<const CelestialBodyDefinition *>(node)) {
moon_node->copy(&impl->definition);
}
}
bool MoonRenderer::getLightsAt(vector<LightComponent> &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;
}

View file

@ -0,0 +1,40 @@
#ifndef MOONRENDERER_H
#define MOONRENDERER_H
#include "software_global.h"
#include "DefinitionWatcher.h"
#include "LightSource.h"
#include <memory>
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<LightComponent> &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<pimpl> impl;
};
}
}
#endif // MOONRENDERER_H

View file

@ -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; return result;
} }
bool NightSky::getLightsAt(vector<LightComponent> &result, const Vector3 &loc) const { bool NightSky::getLightsAt(vector<LightComponent> &result, const Vector3 &) const {
LightComponent moon, sky; LightComponent 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);
sky.color = Color(0.01, 0.012, 0.03); sky.color = Color(0.01, 0.012, 0.03);
sky.direction = VECTOR_DOWN; sky.direction = VECTOR_DOWN;

View file

@ -16,6 +16,7 @@
#include "TerrainRasterizer.h" #include "TerrainRasterizer.h"
#include "WaterRasterizer.h" #include "WaterRasterizer.h"
#include "NightSky.h" #include "NightSky.h"
#include "MoonRenderer.h"
#include "LightStatus.h" #include "LightStatus.h"
#include "LightingManager.h" #include "LightingManager.h"
#include "GodRaysSampler.h" #include "GodRaysSampler.h"
@ -37,6 +38,7 @@ SoftwareRenderer::SoftwareRenderer(Scenery *scenery) : scenery(scenery) {
water_renderer = new WaterRenderer(this); water_renderer = new WaterRenderer(this);
nightsky_renderer = new NightSky(this); nightsky_renderer = new NightSky(this);
moon_renderer = new MoonRenderer(scenery->getAtmosphere()->childMoon());
fluid_medium = new FluidMediumManager(this); fluid_medium = new FluidMediumManager(this);
lighting = new LightingManager(); lighting = new LightingManager();
@ -47,6 +49,7 @@ SoftwareRenderer::SoftwareRenderer(Scenery *scenery) : scenery(scenery) {
lighting->registerFilter(vegetation_renderer); lighting->registerFilter(vegetation_renderer);
lighting->registerFilter(clouds_renderer); lighting->registerFilter(clouds_renderer);
lighting->registerSource(atmosphere_renderer); lighting->registerSource(atmosphere_renderer);
lighting->registerSource(moon_renderer);
setQuality(0.5); setQuality(0.5);
} }
@ -59,6 +62,7 @@ SoftwareRenderer::~SoftwareRenderer() {
delete godrays; delete godrays;
delete nightsky_renderer; delete nightsky_renderer;
delete moon_renderer;
delete atmosphere_renderer; delete atmosphere_renderer;
delete clouds_renderer; delete clouds_renderer;

View file

@ -68,6 +68,9 @@ class SOFTWARESHARED_EXPORT SoftwareRenderer {
inline NightSky *getNightSky() const { inline NightSky *getNightSky() const {
return nightsky_renderer; return nightsky_renderer;
} }
inline const MoonRenderer &getMoonRenderer() const {
return *moon_renderer;
}
inline FluidMediumManager *getFluidMediumManager() const { inline FluidMediumManager *getFluidMediumManager() const {
return fluid_medium; return fluid_medium;
@ -98,6 +101,7 @@ class SOFTWARESHARED_EXPORT SoftwareRenderer {
TexturesRenderer *textures_renderer; TexturesRenderer *textures_renderer;
WaterRenderer *water_renderer; WaterRenderer *water_renderer;
NightSky *nightsky_renderer; NightSky *nightsky_renderer;
MoonRenderer *moon_renderer;
VegetationRenderer *vegetation_renderer; VegetationRenderer *vegetation_renderer;
}; };
} }

View file

@ -49,6 +49,7 @@ class RayCastingManager;
class RayCastingResult; class RayCastingResult;
class NightSky; class NightSky;
class MoonRenderer;
class TerrainRayWalker; class TerrainRayWalker;