//**************************************************************************** // // File: LightShadow.h // License: MIT // Project: GLVU // Contents: Core lighting and shadowing backend needs. // Not the actual rendering/execution (yet at least), // but the guts needed such as atlasing and tile clustering. // //**************************************************************************** #pragma once #include "glvu.h" #include "RenderScript.h" namespace GLVU { class IQueriableScene; /// Subdividing allocator for square blocks of a 2D domain. Doesn't actually care what purpose. class AtlasCellTable { public: /// Construct for a number of levels and a given total size (ie. 5 subdivisions of a 4096x4096 texture). AtlasCellTable(int levels, int dim); /// Construct for a fitment to a 64x64 minimum tile size. AtlasCellTable(int dim); /// Helper to hide need for levels knowledge. math::float4 GetArea(int size) { return GetCell(CalculateLevel(size)); } /// Try to get a texture-region for a given subdivision level. math::float4 GetCell(int level); /// Determines the subdivision levels based on an actual pixel-size (such as 64x64) int CalculateLevel(int forSize) const; /// Reset the state. void Clear(); /// Convert into a viewport appropriate rect. As in glViewport math::uint4 ToViewport(math::float4) const; /// Sentinel value for comparisons. static const math::float4 InvalidCell; static void Divide(float4 input, float4* output); private: /// Inner handling of splitting a subdivision. void SplitCells(int level); /// Outer logical concerns for whether to split and from where in the tree to split if there is no one suitable. bool DivideCells(int level); /// Count of cells in each region. std::vector cellCount_; /// There's never more than 4 cells needed for a given level at any time due to subdivision spiral std::vector< std::array > regions_; /// LUT for mapping a pixel-size to a level of subdivision. std::vector levelDims_; /// Intended dimensions of our texture. int dim_; /// Number of subdivision levels. int levels_; }; /// Subdividing alloator for blocks of a 2D domain. Doesn't actually care what purpose. /// Unlike the AtlasCellTable this one supports retaining cells for caching purposes /// class QuadTreeAllocator { struct Cell { Cell* children_ = nullptr; math::uint4 coords_; bool taken_ = false; ~Cell() { if (children_) delete[] children_; children_ = nullptr; } void Clear() { if (children_) { children_[0].Clear(); children_[1].Clear(); children_[2].Clear(); children_[3].Clear(); } taken_ = false; } void Free() { if (children_) { children_[0].Free(); children_[1].Free(); children_[2].Free(); children_[3].Free(); } taken_ = false; } void Divide() { children_ = new Cell[4]; const unsigned bX = coords_.x; const unsigned bY = coords_.y; const unsigned w = coords_.z / 2; const unsigned h = coords_.w / 2; children_[0].coords_ = math::uint4(bX, bY, w, h); children_[1].coords_ = math::uint4(bX + w, bY, w, h); children_[2].coords_ = math::uint4(bX, bY + h, w, h); children_[3].coords_ = math::uint4(bX + w, bY + h, w, h); } inline math::uint4 ToViewport() { return math::uint4::FromPosSize(coords_.x, coords_.y, coords_.z, coords_.w); } inline uint32_t Width() const { return coords_.z; } inline uint32_t Height() const { return coords_.w; } bool AnyTaken() const; }; Cell* root_; math::uint4 GetCell(Cell*, uint32_t dim, uintptr_t datum = 0); void CollectRects(Cell*, std::vector&); std::map > datumTable_; public: QuadTreeAllocator(uint32_t width, uint32_t height); ~QuadTreeAllocator(); // as in glViewport inline math::uint4 ToViewport(math::float4 value) const { return uint4(value.x * width_, value.y * height_, value.Width() * width_, value.Height() * height_); } inline math::float4 ToFractional(math::uint4 value) const { return math::float4(value.x / (float)width_, value.y / (float)height_, value.z / (float)width_, value.w / (float)height_); } math::uint4 GetCell(uint32_t dim, uintptr_t datum = 0); void ProcessUpdate(); void ReturnCell(uintptr_t datum); void CollectRects(std::vector&); void Clear(); uint32_t width_; uint32_t height_; }; }