#pragma once #include "StarTtlCache.hpp" #include "StarWorldRenderData.hpp" #include "StarMaterialRenderProfile.hpp" #include "StarRenderer.hpp" #include "StarWorldCamera.hpp" #include "StarTileDrawer.hpp" namespace Star { STAR_CLASS(Assets); STAR_CLASS(MaterialDatabase); STAR_CLASS(TilePainter); class TilePainter : public TileDrawer { public: // The rendered tiles are split and cached in chunks of RenderChunkSize x // RenderChunkSize. This means that, around the border, there may be as many // as RenderChunkSize - 1 tiles rendered outside of the viewing area from // chunk alignment. In addition to this, there is also a region around each // tile that is used for neighbor based rendering rules which has a max of // MaterialRenderProfileMaxNeighborDistance. If the given tile data does not // extend RenderChunkSize + MaterialRenderProfileMaxNeighborDistance - 1 // around the viewing area, then border chunks can continuously change hash, // and will be recomputed too often. static unsigned const RenderChunkSize = 16; static unsigned const BorderTileSize = RenderChunkSize + MaterialRenderProfileMaxNeighborDistance - 1; TilePainter(RendererPtr renderer); // Adjusts lighting levels for liquids. void adjustLighting(WorldRenderData& renderData) const; // Sets up chunk data for every chunk that intersects the rendering region // and prepares it for rendering. Do not call cleanup in between calling // setup and each render method. void setup(WorldCamera const& camera, WorldRenderData& renderData); void renderBackground(WorldCamera const& camera); void renderMidground(WorldCamera const& camera); void renderLiquid(WorldCamera const& camera); void renderForeground(WorldCamera const& camera); // Clears any render data, as well as cleaning up old cached textures and // chunks. void cleanup(); private: typedef uint64_t QuadZLevel; typedef uint64_t ChunkHash; enum class TerrainLayer { Background, Midground, Foreground }; struct LiquidInfo { TexturePtr texture; Vec4B color; Vec3F bottomLightMix; float textureMovementFactor; }; typedef HashMap> TerrainChunk; typedef HashMap LiquidChunk; typedef tuple MaterialPieceTextureKey; typedef String AssetTextureKey; typedef Variant TextureKey; struct TextureKeyHash { size_t operator()(TextureKey const& key) const; }; // chunkIndex here is the index of the render chunk such that chunkIndex * // RenderChunkSize results in the coordinate of the lower left most tile in // the render chunk. static ChunkHash terrainChunkHash(WorldRenderData& renderData, Vec2I chunkIndex); static ChunkHash liquidChunkHash(WorldRenderData& renderData, Vec2I chunkIndex); void renderTerrainChunks(WorldCamera const& camera, TerrainLayer terrainLayer); shared_ptr getTerrainChunk(WorldRenderData& renderData, Vec2I chunkIndex); shared_ptr getLiquidChunk(WorldRenderData& renderData, Vec2I chunkIndex); bool produceTerrainPrimitives(HashMap>& primitives, TerrainLayer terrainLayer, Vec2I const& pos, WorldRenderData const& renderData); void produceLiquidPrimitives(HashMap>& primitives, Vec2I const& pos, WorldRenderData const& renderData); float liquidDrawLevel(float liquidLevel) const; List m_liquids; RendererPtr m_renderer; TextureGroupPtr m_textureGroup; HashTtlCache m_textureCache; HashTtlCache, shared_ptr> m_terrainChunkCache; HashTtlCache, shared_ptr> m_liquidChunkCache; List> m_pendingTerrainChunks; List> m_pendingLiquidChunks; Maybe m_lastCameraCenter; Vec2F m_cameraPan; }; }