From 7ff3e0fecc347f6a0c22a56acb2f64b60a26ed25 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Sat, 19 Aug 2023 15:09:00 +1000 Subject: [PATCH] Fix parallax and space dust jitter when lerping zoom level on very old universes --- source/core/StarRandomPoint.hpp | 35 +++++++++++---------- source/rendering/StarEnvironmentPainter.cpp | 18 +++++------ source/rendering/StarEnvironmentPainter.hpp | 2 +- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/source/core/StarRandomPoint.hpp b/source/core/StarRandomPoint.hpp index ff7d354..ac9fcd9 100644 --- a/source/core/StarRandomPoint.hpp +++ b/source/core/StarRandomPoint.hpp @@ -13,34 +13,36 @@ namespace Star { // predictable and uses the RandomSource in a predictable way. Useful for // things like starfields, fields of debris, random object placement, etc. -template +template class Random2dPointGenerator { public: - typedef List> PointSet; - + typedef Star::Polygon Poly; + typedef Star::Vector Point; + typedef Star::Rect Rect; + typedef List> PointSet; Random2dPointGenerator(uint64_t seed, float cellSize, Vec2I const& densityRange); // Each point will in the area will be generated in a predictable order, and // if the callback uses the RandomSource in a predictable way, will generate // the same field for every call. template - PointSet generate(PolyF const& area, PointCallback callback); + PointSet generate(Poly const& area, PointCallback callback); private: - HashTtlCache m_cache; + HashTtlCache m_cache; uint64_t m_seed; float m_cellSize; Vec2I m_densityRange; }; -template -inline Random2dPointGenerator::Random2dPointGenerator(uint64_t seed, float cellSize, Vec2I const& densityRange) +template +inline Random2dPointGenerator::Random2dPointGenerator(uint64_t seed, float cellSize, Vec2I const& densityRange) : m_seed(seed), m_cellSize(cellSize), m_densityRange(densityRange) {} -template +template template -auto Random2dPointGenerator::generate(PolyF const& area, PointCallback callback) -> PointSet { +auto Random2dPointGenerator::generate(Poly const& area, PointCallback callback) -> PointSet { auto bound = area.boundBox(); int64_t sectorXMin = std::floor(bound.xMin() / m_cellSize); int64_t sectorYMin = std::floor(bound.yMin() / m_cellSize); @@ -48,22 +50,21 @@ auto Random2dPointGenerator::generate(PolyF const& area, PointCallbac int64_t sectorYMax = std::ceil(bound.yMax() / m_cellSize); PointSet finalResult; + RandomSource sectorRandomness; for (int64_t x = sectorXMin; x <= sectorXMax; ++x) { for (int64_t y = sectorYMin; y <= sectorYMax; ++y) { - auto sector = RectF::withSize({x * m_cellSize, y * m_cellSize}, Vec2F::filled(m_cellSize)); - if (!area.intersects(PolyF(sector))) + auto sector = Rect::withSize({x * m_cellSize, y * m_cellSize}, Point::filled(m_cellSize)); + if (!area.intersects(Poly(sector))) continue; - finalResult.appendAll(m_cache.get(Vec2F(x, y), [&](Vec2F const&) { + finalResult.appendAll(m_cache.get(Point(x, y), [&](Point const&) { PointSet sectorResult; - - RandomSource sectorRandomness(staticRandomU64(m_seed, x, y)); - + sectorRandomness.init(staticRandomU64(m_seed, x, y)); unsigned max = sectorRandomness.randInt(m_densityRange[0], m_densityRange[1]); for (unsigned i = 0; i < max; ++i) { - Vec2F pointPos = Vec2F(x + sectorRandomness.randf(), y + sectorRandomness.randf()) * m_cellSize; - sectorResult.append(pair(pointPos, callback(sectorRandomness))); + Point pointPos = Point(x + (DataType)sectorRandomness.randd(), y + (DataType)sectorRandomness.randd()) * m_cellSize; + sectorResult.append(pair(pointPos, callback(sectorRandomness))); } return sectorResult; diff --git a/source/rendering/StarEnvironmentPainter.cpp b/source/rendering/StarEnvironmentPainter.cpp index 816281b..ff6cb35 100644 --- a/source/rendering/StarEnvironmentPainter.cpp +++ b/source/rendering/StarEnvironmentPainter.cpp @@ -100,7 +100,7 @@ void EnvironmentPainter::renderDebrisFields(float pixelRatio, Vec2F const& scree if (sky.type == SkyType::Orbital || sky.type == SkyType::Warp) { Vec2F viewSize = screenSize / pixelRatio; Vec2F viewCenter = viewSize / 2; - Vec2F viewMin = sky.starOffset - viewCenter; + Vec2D viewMin = Vec2D(sky.starOffset - viewCenter); Mat3F rotMatrix = Mat3F::rotation(sky.starRotation, viewCenter); @@ -113,7 +113,7 @@ void EnvironmentPainter::renderDebrisFields(float pixelRatio, Vec2F const& scree float debrisYVel = staticRandomFloatRange(spaceDebrisVelocityRange[0], spaceDebrisVelocityRange[1], sky.skyParameters.seed, i, "DebrisFieldYVel"); // Translate the entire field to make the debris seem as though they are moving - Vec2F velocityOffset = -Vec2F(debrisXVel, debrisYVel) * sky.epochTime; + Vec2D velocityOffset = -Vec2D(debrisXVel, debrisYVel) * sky.epochTime; JsonArray imageOptions = debrisField.query("list").toArray(); Vec2U biggest = Vec2U(); @@ -123,10 +123,8 @@ void EnvironmentPainter::renderDebrisFields(float pixelRatio, Vec2F const& scree } float screenBuffer = ceil((float)biggest.max() * (float)Constants::sqrt2); - PolyF field = PolyF(RectF::withSize(viewMin + velocityOffset, viewSize).padded(screenBuffer)); - + PolyD field = PolyD(RectD::withSize(viewMin + velocityOffset, Vec2D(viewSize)).padded(screenBuffer)); Vec2F debrisAngularVelocityRange = jsonToVec2F(debrisField.query("angularVelocityRange")); - auto debrisItems = m_debrisGenerators[i]->generate(field, [&](RandomSource& rand) { StringView debrisImage = *rand.randFrom(imageOptions).stringPtr(); @@ -135,10 +133,10 @@ void EnvironmentPainter::renderDebrisFields(float pixelRatio, Vec2F const& scree return pair(debrisImage, debrisAngularVelocity); }); - Vec2F debrisPositionOffset = viewMin + velocityOffset; + Vec2D debrisPositionOffset = viewMin + velocityOffset; for (auto& debrisItem : debrisItems) { - Vec2F debrisPosition = rotMatrix.transformVec2(debrisItem.first - debrisPositionOffset); + Vec2F debrisPosition = rotMatrix.transformVec2(Vec2F(debrisItem.first - debrisPositionOffset)); float debrisAngle = fmod(Constants::deg2rad * debrisItem.second.second * sky.epochTime, Constants::pi * 2) + sky.starRotation; drawOrbiter(pixelRatio, screenSize, sky, {SkyOrbiterType::SpaceDebris, 1.0f, debrisAngle, debrisItem.second.first, debrisPosition}); } @@ -259,8 +257,8 @@ void EnvironmentPainter::renderParallaxLayers( // texture offset in *screen pixel space* Vec2F parallaxOffset = layer.parallaxOffset * camera.pixelRatio(); if (layer.speed != 0) { - double drift = fmod((double)layer.speed * (sky.epochTime / (double)sky.dayLength) * camera.pixelRatio(), (double)parallaxPixels[0]); - parallaxOffset[0] = fmod(parallaxOffset[0] + drift, parallaxPixels[0]); + double drift = fmod((double)layer.speed * (sky.epochTime / (double)sky.dayLength), (double)parallaxSize[0]); + parallaxOffset[0] = fmod(parallaxOffset[0] + drift * camera.pixelRatio(), parallaxPixels[0]); } // parallax camera world position in *parallax space* @@ -467,7 +465,7 @@ void EnvironmentPainter::setupStars(SkyRenderData const& sky) { int debrisCellSize = debrisFields[i].getInt("cellSize"); Vec2I debrisCountRange = jsonToVec2I(debrisFields[i].get("cellCountRange")); uint64_t debrisSeed = staticRandomU64(sky.skyParameters.seed, i, "DebrisFieldSeed"); - m_debrisGenerators[i] = make_shared>>(debrisSeed, debrisCellSize, debrisCountRange); + m_debrisGenerators[i] = make_shared, double>>(debrisSeed, debrisCellSize, debrisCountRange); } } diff --git a/source/rendering/StarEnvironmentPainter.hpp b/source/rendering/StarEnvironmentPainter.hpp index 4b9fdb8..7367095 100644 --- a/source/rendering/StarEnvironmentPainter.hpp +++ b/source/rendering/StarEnvironmentPainter.hpp @@ -72,7 +72,7 @@ private: uint64_t m_starsHash; List m_starTextures; shared_ptr>> m_starGenerator; - List>>> m_debrisGenerators; + List, double>>> m_debrisGenerators; }; }