diff --git a/src/definition/AtmosphereDefinition.cpp b/src/definition/AtmosphereDefinition.cpp index 9bf925c..8a1b4f5 100644 --- a/src/definition/AtmosphereDefinition.cpp +++ b/src/definition/AtmosphereDefinition.cpp @@ -2,14 +2,13 @@ #include #include "Maths.h" +#include "Scenery.h" #include "PackStream.h" #include "RandomGenerator.h" #include "FloatNode.h" #include "GodRaysDefinition.h" #include "CelestialBodyDefinition.h" -#define WORLD_SCALING 0.05 - AtmosphereDefinition::AtmosphereDefinition(DefinitionNode *parent) : DefinitionNode(parent, "atmosphere", "atmosphere") { model = ATMOSPHERE_MODEL_DISABLED; @@ -104,9 +103,9 @@ void AtmosphereDefinition::applyPreset(AtmospherePreset preset, RandomGenerator sun_color.b = 0.9; sun_color.a = 1.0; sun->propRadius()->setValue(1.0); - sun->propDistance()->setValue(149597870.0 / WORLD_SCALING); - moon->propDistance()->setValue(384403.0 / WORLD_SCALING); - moon->propRadius()->setValue(1737.4 / WORLD_SCALING); + sun->propDistance()->setValue(Scenery::SUN_DISTANCE_SCALED); + moon->propDistance()->setValue(384403.0 * Scenery::KM_TO_UNIT); + moon->propRadius()->setValue(1737.4 * Scenery::KM_TO_UNIT); moon->propPhi()->setValue(0.5); moon->propTheta()->setValue(0.3); diff --git a/src/definition/CameraDefinition.cpp b/src/definition/CameraDefinition.cpp index 4c55f32..dcc824b 100644 --- a/src/definition/CameraDefinition.cpp +++ b/src/definition/CameraDefinition.cpp @@ -1,6 +1,7 @@ #include "CameraDefinition.h" #include +#include "Scenery.h" #include "Maths.h" #include "PackStream.h" #include "BoundingBox.h" @@ -19,7 +20,7 @@ CameraDefinition::CameraDefinition(DefinitionNode *parent) : DefinitionNode(pare perspective.yfov = 1.0; perspective.xratio = 1.0; perspective.znear = 0.5; - perspective.zfar = 20000.0; + perspective.zfar = Scenery::FAR_LIMIT_SCALED; validate(); } diff --git a/src/definition/CelestialBodyDefinition.cpp b/src/definition/CelestialBodyDefinition.cpp index 9ae3217..f045f03 100644 --- a/src/definition/CelestialBodyDefinition.cpp +++ b/src/definition/CelestialBodyDefinition.cpp @@ -2,10 +2,7 @@ #include "Vector3.h" #include "FloatNode.h" - -static constexpr double WORLD_SCALING = 0.05; -static constexpr double EARTH_RADIUS = 6360.0; -static constexpr double EARTH_RADIUS_SCALED = EARTH_RADIUS / WORLD_SCALING; +#include "Scenery.h" CelestialBodyDefinition::CelestialBodyDefinition(DefinitionNode *parent, const string &name) : DefinitionNode(parent, name) { @@ -18,7 +15,7 @@ CelestialBodyDefinition::CelestialBodyDefinition(DefinitionNode *parent, const s Vector3 CelestialBodyDefinition::getLocation(bool over_water) const { VectorSpherical spc = {distance->getValue(), theta->getValue(), -phi->getValue()}; if (over_water) { - return Vector3(spc).sub(VECTOR_DOWN.scale(EARTH_RADIUS_SCALED)); + return Vector3(spc).sub(VECTOR_DOWN.scale(Scenery::EARTH_RADIUS_SCALED)); } else { return Vector3(spc); } diff --git a/src/definition/Scenery.h b/src/definition/Scenery.h index 4e5f524..6ef31b0 100644 --- a/src/definition/Scenery.h +++ b/src/definition/Scenery.h @@ -24,6 +24,25 @@ class DEFINITIONSHARED_EXPORT Scenery : public DefinitionNode { typedef void (*SceneryCustomDataCallback)(PackStream *stream, void *data); + /** + * Conversion factor between scenery units and kilometers. + * + * 1km == 20.0 units + */ + static constexpr double KM_TO_UNIT = 20.0; + static constexpr double UNIT_TO_KM = 1.0 / KM_TO_UNIT; + + static constexpr double EARTH_RADIUS = 6360.0; + static constexpr double EARTH_RADIUS_SCALED = EARTH_RADIUS * KM_TO_UNIT; + + static constexpr double SUN_DISTANCE = 149597870.0; + static constexpr double SUN_DISTANCE_SCALED = SUN_DISTANCE * KM_TO_UNIT; + + static constexpr double SUN_RADIUS = 6.955e5; + static constexpr double SUN_RADIUS_SCALED = EARTH_RADIUS * KM_TO_UNIT; + + static constexpr double FAR_LIMIT_SCALED = 20000.0; + public: Scenery(); diff --git a/src/interface/commandline/tests.cpp b/src/interface/commandline/tests.cpp index 8450dbc..bf09a53 100644 --- a/src/interface/commandline/tests.cpp +++ b/src/interface/commandline/tests.cpp @@ -429,11 +429,18 @@ static void testMoonRendering() { /*SkyRasterizer rasterizer(&renderer, renderer.getProgressHelper(), 0); renderer.setSoloRasterizer(&rasterizer);*/ + // During the day scenery.getAtmosphere()->setDayTime(17, 30); startTestRender(&renderer, "moon", 0); + // At night scenery.getAtmosphere()->setDayTime(23); startTestRender(&renderer, "moon", 1); + + // Eclipse + scenery.getAtmosphere()->childSun()->propPhi()->setValue(scenery.getAtmosphere()->childMoon()->propPhi()->getValue()); + scenery.getAtmosphere()->childSun()->propTheta()->setValue(scenery.getAtmosphere()->childMoon()->propTheta()->getValue()); + startTestRender(&renderer, "moon", 2); } void runTestSuite() { diff --git a/src/render/opengl/shaders/atmosphere.frag b/src/render/opengl/shaders/atmosphere.frag index 556ee8a..bb26ca8 100644 --- a/src/render/opengl/shaders/atmosphere.frag +++ b/src/render/opengl/shaders/atmosphere.frag @@ -10,10 +10,11 @@ const vec3 betaMSca = vec3(20e-3, 20e-3, 20e-3); const vec3 betaMEx = vec3(20e-3 / 0.9, 20e-3 / 0.9, 20e-3 / 0.9); const float mieG = 0.76; const float WORKAROUND_OFFSET = 0.1; -const float SPHERE_SIZE = 20000.0; -const float WORLD_SCALING = 0.03; +const float FAR_LIMIT_SCALED = 20000.0; +const float UNIT_TO_KM = 0.05; +const float KM_TO_UNIT = 20.0; const float SUN_DISTANCE = 149597870.0; -const float SUN_DISTANCE_SCALED = (SUN_DISTANCE / WORLD_SCALING); +const float SUN_DISTANCE_SCALED = (SUN_DISTANCE * KM_TO_UNIT); const float M_PI = 3.141592657; const int RES_MU = 128; @@ -259,7 +260,7 @@ vec3 applyWeatherEffects(float distance, vec3 base, vec3 _attenuation, vec3 _ins vec4 applyAerialPerspective(vec4 base) { vec3 location = vec3(unprojected.x, max(unprojected.y, 0.0), unprojected.z); - vec3 x = vec3(0.0, Rg + WORKAROUND_OFFSET + max(cameraLocation.y, 0.0) * WORLD_SCALING, 0.0); + vec3 x = vec3(0.0, Rg + WORKAROUND_OFFSET + max(cameraLocation.y, 0.0) * UNIT_TO_KM, 0.0); vec3 v = normalize(unprojected - cameraLocation); vec3 s = normalize(sunDirection * SUN_DISTANCE_SCALED - x); @@ -274,7 +275,7 @@ vec4 applyAerialPerspective(vec4 base) float r = length(x); float mu = dot(x, v) / r; - float t = length(unprojected - cameraLocation) * WORLD_SCALING; + float t = length(unprojected - cameraLocation) * UNIT_TO_KM; vec3 attenuation; vec3 inscattering = _getInscatterColor(x, t, v, s, r, mu, attenuation); @@ -284,7 +285,7 @@ vec4 applyAerialPerspective(vec4 base) vec4 getSkyColor(vec3 location, vec3 direction) { - vec3 x = vec3(0.0, Rg + location.y * WORLD_SCALING, 0.0); + vec3 x = vec3(0.0, Rg + location.y * UNIT_TO_KM, 0.0); vec3 v = normalize(direction); vec3 s = normalize(sunDirection * SUN_DISTANCE_SCALED - x); @@ -297,12 +298,12 @@ vec4 getSkyColor(vec3 location, vec3 direction) vec3 inscattering = _getInscatterColor(x, t, v, s, r, mu, attenuation); vec3 nightsky = vec3(0.01, 0.012, 0.03); - return vec4(applyWeatherEffects(SPHERE_SIZE, nightsky + sunTransmittance.rgb, vec3(1), inscattering), 1.0); + return vec4(applyWeatherEffects(FAR_LIMIT_SCALED, nightsky + sunTransmittance.rgb, vec3(1), inscattering), 1.0); } vec4 applyLighting(vec3 location, vec3 normal, vec4 color, float reflection, float shininess, float hardness) { - float r0 = Rg + WORKAROUND_OFFSET + max(location.y, 0.0) * WORLD_SCALING; + float r0 = Rg + WORKAROUND_OFFSET + max(location.y, 0.0) * UNIT_TO_KM; vec3 sun_position = sunDirection * SUN_DISTANCE; float muS = dot(vec3(0.0, 1.0, 0.0), normalize(sun_position - vec3(0.0, r0, 0.0))); diff --git a/src/render/software/AtmosphereModelBruneton.cpp b/src/render/software/AtmosphereModelBruneton.cpp index c9f5b8e..0fb2a18 100644 --- a/src/render/software/AtmosphereModelBruneton.cpp +++ b/src/render/software/AtmosphereModelBruneton.cpp @@ -27,22 +27,15 @@ #include "CacheFile.h" #include "FloatNode.h" -/* Factor to convert software units to kilometers */ -#define WORLD_SCALING 0.03 -#define SUN_DISTANCE 149597870.0 -#define SUN_DISTANCE_SCALED (SUN_DISTANCE / WORLD_SCALING) #define WORKAROUND_OFFSET 0.1 -// TODO This is copied in AtmosphereRenderer -#define SPHERE_SIZE 20000.0 - /*********************** Constants ***********************/ -static const double Rg = 6360.0; -static const double Rt = 6420.0; -static const double RL = 6421.0; -static const double ISun = 100.0; -static const double AVERAGE_GROUND_REFLECTANCE = 0.1; +static constexpr double Rg = Scenery::EARTH_RADIUS; +static constexpr double Rt = Rg + 60.0; +static constexpr double RL = Rt + 1.0; +static constexpr double ISun = 100.0; +static constexpr double AVERAGE_GROUND_REFLECTANCE = 0.1; #if 1 #define RES_MU 128 @@ -1070,7 +1063,7 @@ AtmosphereModelBruneton::~AtmosphereModelBruneton() { AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3 &direction, const Vector3 &sun_position, const Color &base) const { - Vector3 x = {0.0, Rg + eye.y * WORLD_SCALING, 0.0}; + Vector3 x = {0.0, Rg + eye.y * Scenery::UNIT_TO_KM, 0.0}; Vector3 v = direction.normalize(); Vector3 s = sun_position.sub(x).normalize(); @@ -1089,7 +1082,7 @@ AtmosphereResult AtmosphereModelBruneton::getSkyColor(Vector3 eye, const Vector3 result.base = base.add(sunColor); result.inscattering = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */ /* TODO Use atmosphere attenuation */ - result.distance = SPHERE_SIZE; + result.distance = Scenery::FAR_LIMIT_SCALED; result.updateFinal(); @@ -1100,16 +1093,16 @@ AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 locatio Vector3 eye = parent->getCameraLocation(); eye.y = max(eye.y, 0.0); location.y = max(location.y, 0.0); - Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(SUN_DISTANCE); + Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(Scenery::SUN_DISTANCE); - Vector3 direction = location.sub(eye).scale(WORLD_SCALING); + Vector3 direction = location.sub(eye).scale(Scenery::UNIT_TO_KM); double t = direction.getNorm(); if (t < 0.000001) { - direction = parent->getCameraDirection().scale(0.001 * WORLD_SCALING); + direction = parent->getCameraDirection().scale(0.001 * Scenery::UNIT_TO_KM); t = direction.getNorm(); } - Vector3 x = {0.0, Rg + WORKAROUND_OFFSET + eye.y * WORLD_SCALING, 0.0}; + Vector3 x = {0.0, Rg + WORKAROUND_OFFSET + eye.y * Scenery::UNIT_TO_KM, 0.0}; Vector3 v = direction.normalize(); Vector3 s = sun_position.sub(x).normalize(); @@ -1133,7 +1126,7 @@ AtmosphereResult AtmosphereModelBruneton::applyAerialPerspective(Vector3 locatio result.attenuation.r = attenuation.x; result.attenuation.g = attenuation.y; result.attenuation.b = attenuation.z; - result.distance = t / WORLD_SCALING; + result.distance = t * Scenery::KM_TO_UNIT; result.updateFinal(); @@ -1144,11 +1137,11 @@ bool AtmosphereModelBruneton::getLightsAt(vector &result, const LightComponent sun, irradiance; double muS; - double altitude = max(location.y * WORLD_SCALING, 0.0); + double altitude = max(location.y * Scenery::UNIT_TO_KM, 0.0); double r0 = Rg + WORKAROUND_OFFSET + altitude; Vector3 up = {0.0, 1.0, 0.0}; - Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(SUN_DISTANCE); + Vector3 sun_position = parent->getAtmosphereRenderer()->getSunDirection().scale(Scenery::SUN_DISTANCE); Vector3 x = {0.0, r0, 0.0}; Vector3 s = sun_position.sub(x).normalize(); diff --git a/src/render/software/AtmosphereRenderer.cpp b/src/render/software/AtmosphereRenderer.cpp index 135360e..1e1d9de 100644 --- a/src/render/software/AtmosphereRenderer.cpp +++ b/src/render/software/AtmosphereRenderer.cpp @@ -13,13 +13,6 @@ #include "CelestialBodyDefinition.h" #include "FloatNode.h" -/* Factor to convert software units to kilometers */ -#define WORLD_SCALING 0.05 -#define SUN_DISTANCE 149597870.0 -#define SUN_DISTANCE_SCALED (SUN_DISTANCE / WORLD_SCALING) -#define SUN_RADIUS 6.955e5 -#define SUN_RADIUS_SCALED (SUN_RADIUS / WORLD_SCALING) - static inline double _getDayFactor(double daytime) { daytime = 1.0 - fabs(0.5 - daytime) / 0.5; return daytime < 0.45 ? 0.0 : sqrt((daytime - 0.45) / 0.55); @@ -142,7 +135,7 @@ AtmosphereResult SoftwareBrunetonAtmosphereRenderer::getSkyColor(const Vector3 & sun_direction = getSunDirection(); Vector3 direction_norm = direction.normalize(); - sun_position = sun_direction.scale(SUN_DISTANCE_SCALED); + sun_position = sun_direction.scale(Scenery::SUN_DISTANCE_SCALED); base = COLOR_BLACK; @@ -177,7 +170,7 @@ AtmosphereResult SoftwareBrunetonAtmosphereRenderer::getSkyColor(const Vector3 & // Get scattering AtmosphereResult result; - Vector3 location = camera_location.add(direction_norm.scale(6421.0)); + Vector3 location = camera_location.add(direction_norm.scale(Scenery::FAR_LIMIT_SCALED)); switch (definition->model) { case AtmosphereDefinition::ATMOSPHERE_MODEL_BRUNETON: result = model->getSkyColor(camera_location, direction_norm, sun_position, base); diff --git a/src/render/software/SkyRasterizer.cpp b/src/render/software/SkyRasterizer.cpp index edfa443..0b44912 100644 --- a/src/render/software/SkyRasterizer.cpp +++ b/src/render/software/SkyRasterizer.cpp @@ -1,6 +1,7 @@ #include "SkyRasterizer.h" #include +#include "Scenery.h" #include "Maths.h" #include "Vector3.h" #include "Color.h" @@ -13,8 +14,6 @@ #include "RenderProgress.h" #include "GodRaysSampler.h" -#define SPHERE_SIZE 20000.0 - SkyRasterizer::SkyRasterizer(SoftwareRenderer *renderer, RenderProgress *progress, unsigned short client_id) : Rasterizer(renderer, progress, client_id, Color(0.7, 0.7, 1.0)) { } @@ -29,6 +28,7 @@ void SkyRasterizer::rasterizeToCanvas(CanvasPortion *canvas) { double current_i, current_j; Vector3 vertex1, vertex2, vertex3, vertex4; Vector3 camera_location, direction; + constexpr double limit = Scenery::FAR_LIMIT_SCALED; step_i = Maths::PI * 2.0 / to_double(res_i); step_j = Maths::PI / to_double(res_j); @@ -45,24 +45,24 @@ void SkyRasterizer::rasterizeToCanvas(CanvasPortion *canvas) { for (i = 0; i < res_i; i++) { current_i = to_double(i) * step_i; - direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j); - direction.y = SPHERE_SIZE * sin(current_j); - direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j); + direction.x = limit * cos(current_i) * cos(current_j); + direction.y = limit * sin(current_j); + direction.z = limit * sin(current_i) * cos(current_j); vertex1 = camera_location.add(direction); - direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j); - direction.y = SPHERE_SIZE * sin(current_j); - direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j); + direction.x = limit * cos(current_i + step_i) * cos(current_j); + direction.y = limit * sin(current_j); + direction.z = limit * sin(current_i + step_i) * cos(current_j); vertex2 = camera_location.add(direction); - direction.x = SPHERE_SIZE * cos(current_i + step_i) * cos(current_j + step_j); - direction.y = SPHERE_SIZE * sin(current_j + step_j); - direction.z = SPHERE_SIZE * sin(current_i + step_i) * cos(current_j + step_j); + direction.x = limit * cos(current_i + step_i) * cos(current_j + step_j); + direction.y = limit * sin(current_j + step_j); + direction.z = limit * sin(current_i + step_i) * cos(current_j + step_j); vertex3 = camera_location.add(direction); - direction.x = SPHERE_SIZE * cos(current_i) * cos(current_j + step_j); - direction.y = SPHERE_SIZE * sin(current_j + step_j); - direction.z = SPHERE_SIZE * sin(current_i) * cos(current_j + step_j); + direction.x = limit * cos(current_i) * cos(current_j + step_j); + direction.y = limit * sin(current_j + step_j); + direction.z = limit * sin(current_i) * cos(current_j + step_j); vertex4 = camera_location.add(direction); // TODO Triangles at poles diff --git a/src/render/software/TerrainRasterizer.cpp b/src/render/software/TerrainRasterizer.cpp index f8b27fa..7ee44c0 100644 --- a/src/render/software/TerrainRasterizer.cpp +++ b/src/render/software/TerrainRasterizer.cpp @@ -149,7 +149,7 @@ int TerrainRasterizer::performTessellation(CanvasPortion *canvas) { double cx = cam.x - fmod(cam.x, base_chunk_size); double cz = cam.z - fmod(cam.x, base_chunk_size); - while (radius_int < 20000.0) { + while (radius_int < Scenery::FAR_LIMIT_SCALED) { for (i = 0; i < chunk_count - 1; i++) { getChunk(renderer, &chunk, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size); if (chunk.detail_hint > 0) { diff --git a/src/render/software/WaterRasterizer.cpp b/src/render/software/WaterRasterizer.cpp index 3c7c0df..f8413ed 100644 --- a/src/render/software/WaterRasterizer.cpp +++ b/src/render/software/WaterRasterizer.cpp @@ -1,6 +1,7 @@ #include "WaterRasterizer.h" #include +#include "Scenery.h" #include "SoftwareRenderer.h" #include "WaterRenderer.h" #include "CanvasFragment.h" @@ -66,7 +67,7 @@ int WaterRasterizer::performTessellation(CanvasPortion *canvas) { double cx = cam.x - fmod(cam.x, base_chunk_size); double cz = cam.z - fmod(cam.x, base_chunk_size); - while (radius_int < 20000.0) { + while (radius_int < Scenery::FAR_LIMIT_SCALED) { if (interrupted) { return result; }