Compare commits
1 Commits
769bbd4261
...
f859288689
| Author | SHA256 | Date | |
|---|---|---|---|
| f859288689 |
237
TSE_Core/src/BehaviourScripts/OrdererSpriteSet.cpp
Normal file
237
TSE_Core/src/BehaviourScripts/OrdererSpriteSet.cpp
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
#include "OrdererSpriteSet.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
TSE::OrdererSpriteSetChunk::OrdererSpriteSetChunk(int _chunksize, const Vector2 &_pos, SortingOrder _order)
|
||||||
|
{
|
||||||
|
chunksize = _chunksize;
|
||||||
|
pos = _pos;
|
||||||
|
order = _order;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::OrdererSpriteSetChunk::SetSprite(const Vector2 &p, const Vector2 &Spriteindex, const Vector2 &Normalindex, TileSet *set, float height, Vector2& scale)
|
||||||
|
{
|
||||||
|
int normalid = -1;
|
||||||
|
if(Normalindex != Vector2(-1,-1))
|
||||||
|
normalid = set->GetSpriteIdAt(Normalindex.x, Normalindex.y);
|
||||||
|
sprites[Vector3(p.x, p.y, height)] = {set->GetSpriteIdAt(Spriteindex.x, Spriteindex.y), normalid};
|
||||||
|
spriteScales[Vector3(p.x, p.y, height)] = scale;
|
||||||
|
dirtyPositions = true;
|
||||||
|
dirtySpriteIds = true;
|
||||||
|
dirtyScales = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::OrdererSpriteSetChunk::RemoveSprite(Vector2 p, float height)
|
||||||
|
{
|
||||||
|
sprites.erase(Vector3(p.x, p.y, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::OrdererSpriteSetChunk::SetOrdering(SortingOrder _order)
|
||||||
|
{
|
||||||
|
order = _order;
|
||||||
|
dirtyPositions = true;
|
||||||
|
dirtySpriteIds = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<TSE::Vector3> *TSE::OrdererSpriteSetChunk::GetOrderedPositions()
|
||||||
|
{
|
||||||
|
if(dirtyPositions)
|
||||||
|
{
|
||||||
|
orderedPositions.clear();
|
||||||
|
for(auto pos : sprites)
|
||||||
|
{
|
||||||
|
orderedPositions.push_back(pos.first);
|
||||||
|
}
|
||||||
|
switch (order)
|
||||||
|
{
|
||||||
|
case TopLeft:
|
||||||
|
std::sort(orderedPositions.begin(), orderedPositions.end(), [](const Vector3& a, const Vector3& b)
|
||||||
|
{
|
||||||
|
return std::tie(a.y, a.x) > std::tie(b.y, b.x);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case TopRight:
|
||||||
|
std::sort(orderedPositions.begin(), orderedPositions.end(), [](const Vector3& a, const Vector3& b)
|
||||||
|
{
|
||||||
|
if (a.y != b.y)
|
||||||
|
return a.y > b.y;
|
||||||
|
return a.x > b.x;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case BottomLeft:
|
||||||
|
std::sort(orderedPositions.begin(), orderedPositions.end(), [](const Vector3& a, const Vector3& b)
|
||||||
|
{
|
||||||
|
return std::tie(a.y, a.x) < std::tie(b.y, b.x);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case BottomRight:
|
||||||
|
std::sort(orderedPositions.begin(), orderedPositions.end(), [](const Vector3& a, const Vector3& b)
|
||||||
|
{
|
||||||
|
if (a.y != b.y)
|
||||||
|
return a.y < b.y;
|
||||||
|
return a.x > b.x;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dirtyPositions = false;
|
||||||
|
}
|
||||||
|
return &orderedPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<TSE::Vector2i> *TSE::OrdererSpriteSetChunk::GetOrderedSpriteIds()
|
||||||
|
{
|
||||||
|
if(dirtySpriteIds)
|
||||||
|
{
|
||||||
|
orderedSpriteIDs.clear();
|
||||||
|
|
||||||
|
auto tmp = GetOrderedPositions();
|
||||||
|
|
||||||
|
for(auto& pos : *tmp)
|
||||||
|
{
|
||||||
|
auto v = sprites.find(pos);
|
||||||
|
if(v != sprites.end())
|
||||||
|
orderedSpriteIDs.push_back(v->second);
|
||||||
|
else
|
||||||
|
orderedSpriteIDs.push_back({0,0});
|
||||||
|
}
|
||||||
|
|
||||||
|
dirtySpriteIds = false;
|
||||||
|
}
|
||||||
|
return &orderedSpriteIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<TSE::Vector2> *TSE::OrdererSpriteSetChunk::GetOrderedScales()
|
||||||
|
{
|
||||||
|
if(dirtyScales)
|
||||||
|
{
|
||||||
|
orderedScales.clear();
|
||||||
|
|
||||||
|
auto tmp = GetOrderedPositions();
|
||||||
|
|
||||||
|
for(auto& pos : *tmp)
|
||||||
|
{
|
||||||
|
auto v = spriteScales.find(pos);
|
||||||
|
if(v != spriteScales.end())
|
||||||
|
orderedScales.push_back(v->second);
|
||||||
|
else
|
||||||
|
orderedScales.push_back({1,1});
|
||||||
|
}
|
||||||
|
|
||||||
|
dirtyScales = false;
|
||||||
|
}
|
||||||
|
return &orderedScales;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TSE::OrdererSpriteSetChunk::GetChunksize()
|
||||||
|
{
|
||||||
|
return chunksize;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TSE::OrdererSpriteSetChunk::GetSpriteCount()
|
||||||
|
{
|
||||||
|
return sprites.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::OrdererSpriteSet::RemoveSprite(Vector2 p, float height)
|
||||||
|
{
|
||||||
|
Vector2 chunkInnerPos = LocalToChunkPos(p);
|
||||||
|
Vector2 chunkIndex = p - chunkInnerPos;
|
||||||
|
if(chunks.contains(chunkIndex))
|
||||||
|
chunks[chunkIndex].RemoveSprite(chunkInnerPos, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::OrdererSpriteSet::SetSprite(Vector2 p, Vector2 Spriteindex, float height, Vector2 scale, Vector2 Normalindex)
|
||||||
|
{
|
||||||
|
Vector2 chunkInnerPos = LocalToChunkPos(p);
|
||||||
|
Vector2 chunkIndex = p - chunkInnerPos;
|
||||||
|
if(!chunks.contains(chunkIndex))
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
chunks[chunkIndex] = OrdererSpriteSetChunk(chunkSize, chunkIndex, order);
|
||||||
|
}
|
||||||
|
chunks[chunkIndex].SetSprite(chunkInnerPos, Spriteindex, Normalindex, set, height, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::OrdererSpriteSetChunk *TSE::OrdererSpriteSet::GetChunk(const Vector2 &pos)
|
||||||
|
{
|
||||||
|
auto chunk = chunks.find(pos);
|
||||||
|
if(chunk == chunks.end())
|
||||||
|
return nullptr;
|
||||||
|
return &chunks[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<TSE::Vector2> *TSE::OrdererSpriteSet::GetChunkPositionsInOrder()
|
||||||
|
{
|
||||||
|
if(dirty)
|
||||||
|
{
|
||||||
|
orderedChunks.clear();
|
||||||
|
|
||||||
|
for(auto pos : chunks)
|
||||||
|
{
|
||||||
|
orderedChunks.push_back(pos.first);
|
||||||
|
}
|
||||||
|
switch (order)
|
||||||
|
{
|
||||||
|
case TopLeft:
|
||||||
|
std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b)
|
||||||
|
{
|
||||||
|
return std::tie(a.y, a.x) > std::tie(b.y, b.x);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case TopRight:
|
||||||
|
std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b)
|
||||||
|
{
|
||||||
|
if (a.y != b.y)
|
||||||
|
return a.y > b.y;
|
||||||
|
return a.x > b.x;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case BottomLeft:
|
||||||
|
std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b)
|
||||||
|
{
|
||||||
|
return std::tie(a.y, a.x) < std::tie(b.y, b.x);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case BottomRight:
|
||||||
|
std::sort(orderedChunks.begin(), orderedChunks.end(), [](const Vector2& a, const Vector2& b)
|
||||||
|
{
|
||||||
|
if (a.y != b.y)
|
||||||
|
return a.y < b.y;
|
||||||
|
return a.x > b.x;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
return &orderedChunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TSE::OrdererSpriteSet::GetChunkCount()
|
||||||
|
{
|
||||||
|
return chunks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::TileSet *TSE::OrdererSpriteSet::GetTileSet()
|
||||||
|
{
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::OrdererSpriteSet::DirtyAll()
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
for(auto& chunk : chunks)
|
||||||
|
{
|
||||||
|
chunk.second.dirtyPositions = true;
|
||||||
|
chunk.second.dirtySpriteIds = true;
|
||||||
|
chunk.second.dirtyScales = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::Vector2 TSE::OrdererSpriteSet::LocalToChunkPos(const Vector2 &v)
|
||||||
|
{
|
||||||
|
Vector2 p = Vector2((int)v.x % chunkSize, (int)v.y % chunkSize);
|
||||||
|
if(p.x < 0) p.x += chunkSize;
|
||||||
|
if(p.y < 0) p.y += chunkSize;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
74
TSE_Core/src/BehaviourScripts/OrdererSpriteSet.hpp
Normal file
74
TSE_Core/src/BehaviourScripts/OrdererSpriteSet.hpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define ORDERERSPRITESET typeid(OrdererSpriteSet).name()
|
||||||
|
|
||||||
|
#include "elements/BehaviourScript.hpp"
|
||||||
|
#include "elements/Transformable.hpp"
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include "enums/SortingOrder.hpp"
|
||||||
|
#include "Vector2.hpp"
|
||||||
|
#include "Vector2i.hpp"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "elements/Sprite.hpp"
|
||||||
|
#include "elements/TileSet.hpp"
|
||||||
|
|
||||||
|
namespace TSE
|
||||||
|
{
|
||||||
|
struct OrdererSpriteSetChunk
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::vector<Vector3> orderedPositions;
|
||||||
|
std::vector<Vector2i> orderedSpriteIDs;
|
||||||
|
std::vector<Vector2> orderedScales;
|
||||||
|
SortingOrder order;
|
||||||
|
int chunksize;
|
||||||
|
std::unordered_map<Vector3, Vector2i> sprites;
|
||||||
|
std::unordered_map<Vector3, Vector2> spriteScales;
|
||||||
|
public:
|
||||||
|
bool dirtyPositions = true;
|
||||||
|
bool dirtySpriteIds = true;
|
||||||
|
bool dirtyScales = true;
|
||||||
|
Vector2 pos;
|
||||||
|
|
||||||
|
OrdererSpriteSetChunk(int _chunksize = 16, const Vector2& _pos = {0,0}, SortingOrder _order = TopRight);
|
||||||
|
void SetSprite(const Vector2& p, const Vector2& Spriteindex, const Vector2& Normalindex, TileSet* set, float height, Vector2& scale);
|
||||||
|
void RemoveSprite(Vector2 p, float height);
|
||||||
|
void SetOrdering(SortingOrder _order);
|
||||||
|
const std::vector<Vector3>* GetOrderedPositions();
|
||||||
|
const std::vector<Vector2i>* GetOrderedSpriteIds();
|
||||||
|
const std::vector<Vector2>* GetOrderedScales();
|
||||||
|
int GetChunksize();
|
||||||
|
int GetSpriteCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class OrdererSpriteSet : public TSE::BehaviourScript
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool dirty = true;
|
||||||
|
std::vector<Vector2> orderedChunks;
|
||||||
|
Rect bounds = Rect(0,0,0,0);
|
||||||
|
|
||||||
|
public:
|
||||||
|
int chunkSize = 16;
|
||||||
|
SortingOrder order = TopRight;
|
||||||
|
TileSet* set;
|
||||||
|
std::unordered_map<Vector2, OrdererSpriteSetChunk> chunks;
|
||||||
|
|
||||||
|
void RemoveSprite(Vector2 p, float height);
|
||||||
|
void SetSprite(Vector2 p, Vector2 Spriteindex, float height, Vector2 scale, Vector2 Normalindex = {-1,-1});
|
||||||
|
OrdererSpriteSetChunk* GetChunk(const Vector2& pos);
|
||||||
|
const std::vector<Vector2>* GetChunkPositionsInOrder();
|
||||||
|
int GetChunkCount();
|
||||||
|
TileSet* GetTileSet();
|
||||||
|
void DirtyAll();
|
||||||
|
|
||||||
|
inline const char* GetName() override
|
||||||
|
{
|
||||||
|
return "Orderer Sprite Set";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector2 LocalToChunkPos(const Vector2& v);
|
||||||
|
};
|
||||||
|
} // namespace TSE
|
||||||
@@ -25,6 +25,8 @@ void TSE::TileMapChunk::RemoveTile(Vector2 p)
|
|||||||
void TSE::TileMapChunk::SetOrdering(SortingOrder _order)
|
void TSE::TileMapChunk::SetOrdering(SortingOrder _order)
|
||||||
{
|
{
|
||||||
order = _order;
|
order = _order;
|
||||||
|
dirtyPositions = true;
|
||||||
|
dirtySpriteIds = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<TSE::Vector2>* TSE::TileMapChunk::GetOrderedPositions()
|
const std::vector<TSE::Vector2>* TSE::TileMapChunk::GetOrderedPositions()
|
||||||
@@ -43,7 +45,7 @@ const std::vector<TSE::Vector2>* TSE::TileMapChunk::GetOrderedPositions()
|
|||||||
Vector2 p(x,y);
|
Vector2 p(x,y);
|
||||||
auto v = sprites.find(p);
|
auto v = sprites.find(p);
|
||||||
if(v != sprites.end())
|
if(v != sprites.end())
|
||||||
orderedPositions.push_back(v->first - offset);
|
orderedPositions.push_back(v->first * Vector2(nextLine.x, nextLine.y * 0.5f) + Vector2(-nextLine.x * y, nextLine.y * 0.5f * x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -56,7 +58,7 @@ const std::vector<TSE::Vector2>* TSE::TileMapChunk::GetOrderedPositions()
|
|||||||
Vector2 p(x,y);
|
Vector2 p(x,y);
|
||||||
auto v = sprites.find(p);
|
auto v = sprites.find(p);
|
||||||
if(v != sprites.end())
|
if(v != sprites.end())
|
||||||
orderedPositions.push_back(v->first - offset);
|
orderedPositions.push_back(v->first * Vector2(nextLine.x, nextLine.y * 0.5f) + Vector2(-nextLine.x * y, nextLine.y * 0.5f * x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -69,7 +71,7 @@ const std::vector<TSE::Vector2>* TSE::TileMapChunk::GetOrderedPositions()
|
|||||||
Vector2 p(x,y);
|
Vector2 p(x,y);
|
||||||
auto v = sprites.find(p);
|
auto v = sprites.find(p);
|
||||||
if(v != sprites.end())
|
if(v != sprites.end())
|
||||||
orderedPositions.push_back(v->first - offset);
|
orderedPositions.push_back(v->first * Vector2(nextLine.x, nextLine.y * 0.5f) + Vector2(-nextLine.x * y, nextLine.y * 0.5f * x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -82,7 +84,7 @@ const std::vector<TSE::Vector2>* TSE::TileMapChunk::GetOrderedPositions()
|
|||||||
Vector2 p(x,y);
|
Vector2 p(x,y);
|
||||||
auto v = sprites.find(p);
|
auto v = sprites.find(p);
|
||||||
if(v != sprites.end())
|
if(v != sprites.end())
|
||||||
orderedPositions.push_back(v->first - offset);
|
orderedPositions.push_back(v->first * Vector2(nextLine.x, nextLine.y * 0.5f) + Vector2(-nextLine.x * y, nextLine.y * 0.5f * x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -271,6 +273,7 @@ void TSE::TileMap::SetNextLineOffset(const Vector2 &offset)
|
|||||||
{
|
{
|
||||||
chunk.nextLine = offset;
|
chunk.nextLine = offset;
|
||||||
}
|
}
|
||||||
|
DirtyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
TSE::Vector2 TSE::TileMap::GetNextLineOffset()
|
TSE::Vector2 TSE::TileMap::GetNextLineOffset()
|
||||||
@@ -278,6 +281,16 @@ TSE::Vector2 TSE::TileMap::GetNextLineOffset()
|
|||||||
return nextLine;
|
return nextLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TSE::TileMap::DirtyAll()
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
for(auto& chunk : chunks)
|
||||||
|
{
|
||||||
|
chunk.second.dirtyPositions = true;
|
||||||
|
chunk.second.dirtySpriteIds = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TSE::TileMap::CheckBounds(Vector2 pos)
|
void TSE::TileMap::CheckBounds(Vector2 pos)
|
||||||
{
|
{
|
||||||
if(pos.x > bounds.p2.x)
|
if(pos.x > bounds.p2.x)
|
||||||
@@ -305,10 +318,10 @@ TSE::Vector2 TSE::TileMap::ChunkToLocalPos(const Vector2 &v, const TileMapChunk
|
|||||||
|
|
||||||
TSE::Vector2 TSE::TileMap::RealPosToTileMapPos(const Vector2 &v)
|
TSE::Vector2 TSE::TileMap::RealPosToTileMapPos(const Vector2 &v)
|
||||||
{
|
{
|
||||||
return v + nextLine * v.y;
|
return v * Vector2(nextLine.x, nextLine.y * 0.5f) + Vector2(-nextLine.x * v.y, nextLine.y * 0.5f * v.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSE::Vector2 TSE::TileMap::TileMapToRealPos(const Vector2 &v)
|
TSE::Vector2 TSE::TileMap::TileMapToRealPos(const Vector2 &v)
|
||||||
{
|
{
|
||||||
return v - nextLine * v.y;
|
return v * Vector2(nextLine.x, nextLine.y * 0.5f) + Vector2(-nextLine.x * v.y, nextLine.y * 0.5f * v.x);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,28 +8,21 @@
|
|||||||
#include "Vector2i.hpp"
|
#include "Vector2i.hpp"
|
||||||
#include "elements/Sprite.hpp"
|
#include "elements/Sprite.hpp"
|
||||||
#include "elements/TileSet.hpp"
|
#include "elements/TileSet.hpp"
|
||||||
|
#include "enums/SortingOrder.hpp"
|
||||||
|
|
||||||
namespace TSE
|
namespace TSE
|
||||||
{
|
{
|
||||||
enum SortingOrder
|
|
||||||
{
|
|
||||||
TopRight,
|
|
||||||
TopLeft,
|
|
||||||
BottomRight,
|
|
||||||
BottomLeft,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TileMapChunk
|
struct TileMapChunk
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool dirtyPositions = true;
|
|
||||||
bool dirtySpriteIds = true;
|
|
||||||
std::vector<Vector2> orderedPositions;
|
std::vector<Vector2> orderedPositions;
|
||||||
std::vector<Vector2i> orderedSpriteIDs;
|
std::vector<Vector2i> orderedSpriteIDs;
|
||||||
SortingOrder order;
|
SortingOrder order;
|
||||||
int chunksize;
|
int chunksize;
|
||||||
std::unordered_map<Vector2, Vector2i> sprites;
|
std::unordered_map<Vector2, Vector2i> sprites;
|
||||||
public:
|
public:
|
||||||
|
bool dirtyPositions = true;
|
||||||
|
bool dirtySpriteIds = true;
|
||||||
Vector2 nextLine;
|
Vector2 nextLine;
|
||||||
Vector2 pos;
|
Vector2 pos;
|
||||||
TileMapChunk(int _chunksize = 16, const Vector2& _pos = {0,0}, SortingOrder _order = TopRight);
|
TileMapChunk(int _chunksize = 16, const Vector2& _pos = {0,0}, SortingOrder _order = TopRight);
|
||||||
@@ -50,10 +43,10 @@ namespace TSE
|
|||||||
bool dirty = true;
|
bool dirty = true;
|
||||||
std::vector<Vector2> orderedChunks;
|
std::vector<Vector2> orderedChunks;
|
||||||
Rect bounds = Rect(0,0,0,0);
|
Rect bounds = Rect(0,0,0,0);
|
||||||
Vector2 nextLine = Vector2(-0.5f, 1.25f);
|
Vector2 nextLine = Vector2(0.5f, 0.5f);
|
||||||
public:
|
public:
|
||||||
int chunkSize = 16;
|
int chunkSize = 16;
|
||||||
SortingOrder order = TopRight;
|
SortingOrder order = BottomRight;
|
||||||
Vector2 SpriteScale = Vector2(1,1);
|
Vector2 SpriteScale = Vector2(1,1);
|
||||||
TileSet* set;
|
TileSet* set;
|
||||||
std::unordered_map<Vector2, TileMapChunk> chunks;
|
std::unordered_map<Vector2, TileMapChunk> chunks;
|
||||||
@@ -69,6 +62,7 @@ namespace TSE
|
|||||||
Vector2 GetNextLineOffset();
|
Vector2 GetNextLineOffset();
|
||||||
Vector2 RealPosToTileMapPos(const Vector2& v);
|
Vector2 RealPosToTileMapPos(const Vector2& v);
|
||||||
Vector2 TileMapToRealPos(const Vector2& v);
|
Vector2 TileMapToRealPos(const Vector2& v);
|
||||||
|
void DirtyAll();
|
||||||
|
|
||||||
inline const char* GetName() override
|
inline const char* GetName() override
|
||||||
{
|
{
|
||||||
|
|||||||
12
TSE_Core/src/enums/SortingOrder.hpp
Normal file
12
TSE_Core/src/enums/SortingOrder.hpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace TSE
|
||||||
|
{
|
||||||
|
enum SortingOrder
|
||||||
|
{
|
||||||
|
TopRight,
|
||||||
|
TopLeft,
|
||||||
|
BottomRight,
|
||||||
|
BottomLeft,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
TSE::EDITOR::EditorSubsystem::EditorSubsystem() : sv(nullptr), editorLayer("")
|
TSE::EDITOR::EditorSubsystem::EditorSubsystem() : sv(nullptr), editorLayer("")
|
||||||
{
|
{
|
||||||
rt = IRenderTexture::factory->CreateTextureHeap({100,100}, 2);
|
rt = IRenderTexture::factory->CreateTextureHeap({100,100}, 5);
|
||||||
sv = SceneView(rt);
|
sv = SceneView(rt);
|
||||||
|
|
||||||
controller.AddGuiElement("Scene", &sv);
|
controller.AddGuiElement("Scene", &sv);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "BehaviourScriptRegistry.hpp"
|
#include "BehaviourScriptRegistry.hpp"
|
||||||
#include "elements/ShaderRegistry.hpp"
|
#include "elements/ShaderRegistry.hpp"
|
||||||
#include "BehaviourScripts/Camera.hpp"
|
#include "BehaviourScripts/Camera.hpp"
|
||||||
|
#include "windows/HirearchieView.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace TSE::EDITOR
|
namespace TSE::EDITOR
|
||||||
@@ -612,6 +613,56 @@ namespace TSE::EDITOR
|
|||||||
if (ImGui::DragFloat("Field of View (deg)", &fov, 0.1f))
|
if (ImGui::DragFloat("Field of View (deg)", &fov, 0.1f))
|
||||||
element->SetFov(fov);
|
element->SetFov(fov);
|
||||||
if (!isPerspective) ImGui::EndDisabled();
|
if (!isPerspective) ImGui::EndDisabled();
|
||||||
|
|
||||||
|
Scene* curScene = HirearchieView::currentScene;
|
||||||
|
ImGui::SeparatorText("Layers To Render");
|
||||||
|
if (curScene == nullptr)
|
||||||
|
{
|
||||||
|
ImGui::TextDisabled("No active scene available.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginChild("LayersToRender", ImVec2(0, 170), ImGuiChildFlags_Borders))
|
||||||
|
{
|
||||||
|
const int layerCount = curScene->GetLayerCount();
|
||||||
|
if (layerCount <= 0)
|
||||||
|
{
|
||||||
|
ImGui::TextDisabled("Scene has no layers.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < layerCount; i++)
|
||||||
|
{
|
||||||
|
Layer* layer = curScene->GetLayerAt(i);
|
||||||
|
if (layer == nullptr) continue;
|
||||||
|
if (!layer->IsVisual()) continue;
|
||||||
|
|
||||||
|
const uuids::uuid& layerID = layer->GetID();
|
||||||
|
auto it = std::find(element->layersNotToRender.begin(), element->layersNotToRender.end(), layerID);
|
||||||
|
bool shouldRenderLayer = (it == element->layersNotToRender.end());
|
||||||
|
|
||||||
|
const std::string checkBoxLabel = layer->GetName() + "##layer_to_render_" + std::to_string(i);
|
||||||
|
if (ImGui::Checkbox(checkBoxLabel.c_str(), &shouldRenderLayer))
|
||||||
|
{
|
||||||
|
if (shouldRenderLayer)
|
||||||
|
{
|
||||||
|
auto removeIt = std::find(element->layersNotToRender.begin(), element->layersNotToRender.end(), layerID);
|
||||||
|
if (removeIt != element->layersNotToRender.end())
|
||||||
|
{
|
||||||
|
element->layersNotToRender.erase(removeIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (it == element->layersNotToRender.end())
|
||||||
|
{
|
||||||
|
element->layersNotToRender.push_back(layerID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
void ElementDrawer::Draw(ParticleSystem *element, const bool &debug)
|
void ElementDrawer::Draw(ParticleSystem *element, const bool &debug)
|
||||||
{
|
{
|
||||||
@@ -836,6 +887,7 @@ namespace TSE::EDITOR
|
|||||||
{
|
{
|
||||||
chunk.SetOrdering(element->order);
|
chunk.SetOrdering(element->order);
|
||||||
}
|
}
|
||||||
|
element->DirtyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::BeginDisabled();
|
ImGui::BeginDisabled();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace TSE::EDITOR
|
|||||||
RenamingTransformable = 3,
|
RenamingTransformable = 3,
|
||||||
RenamingScene = 4
|
RenamingScene = 4
|
||||||
};
|
};
|
||||||
Scene* currentScene;
|
|
||||||
uuids::uuid selected = uuids::uuid();
|
uuids::uuid selected = uuids::uuid();
|
||||||
|
|
||||||
bool openPopUpNamingLayer = false;
|
bool openPopUpNamingLayer = false;
|
||||||
@@ -29,6 +28,7 @@ namespace TSE::EDITOR
|
|||||||
Layer* tmpHolder2 = nullptr;
|
Layer* tmpHolder2 = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
inline static Scene* currentScene = nullptr;
|
||||||
HirearchieView(Scene* s);
|
HirearchieView(Scene* s);
|
||||||
void SetScene(Scene* s);
|
void SetScene(Scene* s);
|
||||||
void Define() override;
|
void Define() override;
|
||||||
|
|||||||
238
TSE_GlfwOpenGlImpl/src/shader/basicOrderedSpriteSetShader.cpp
Normal file
238
TSE_GlfwOpenGlImpl/src/shader/basicOrderedSpriteSetShader.cpp
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
#include "basicOrderedSpriteSetShader.hpp"
|
||||||
|
#include "BehaviourScripts/Renderable.hpp"
|
||||||
|
#include "BehaviourScripts/OrdererSpriteSet.hpp"
|
||||||
|
#include "Color.hpp"
|
||||||
|
#include "basicOrderedSpriteSetShaderGLSL.hpp"
|
||||||
|
|
||||||
|
using namespace TSE;
|
||||||
|
using namespace TSE::GLFW;
|
||||||
|
|
||||||
|
#define SHADER_MESH_INDEX 0
|
||||||
|
#define SHADER_POS_INDEX 1
|
||||||
|
#define SHADER_LAYER_HEIGHT_INDEX 2
|
||||||
|
#define SHADER_SPRITE_INDEX 3
|
||||||
|
#define SHADER_NORMAL_INDEX 4
|
||||||
|
#define SHADER_SCALE_INDEX 5
|
||||||
|
|
||||||
|
#define SHADER_PACKAGE_SIZE sizeof(float) * (3 + 1 + 1 + 1 + 2)
|
||||||
|
|
||||||
|
|
||||||
|
TSE::GLFW::BasicOrderedSpriteSetShader* BasicOrderedSpriteSetShader::instance = nullptr;
|
||||||
|
|
||||||
|
TSE::GLFW::BasicOrderedSpriteSetShader *TSE::GLFW::BasicOrderedSpriteSetShader::Instance()
|
||||||
|
{
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::Destroy()
|
||||||
|
{
|
||||||
|
if(instance != nullptr)
|
||||||
|
delete instance;
|
||||||
|
instance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::Init(float width, float height)
|
||||||
|
{
|
||||||
|
std::vector<std::unique_ptr<ShaderPart>> parts;
|
||||||
|
parts.push_back(ShaderPart::LoadFromString(vertOrderedSet, GL_VERTEX_SHADER));
|
||||||
|
parts.push_back(ShaderPart::LoadFromString(fragOrderedSet, GL_FRAGMENT_SHADER));
|
||||||
|
instance = new BasicOrderedSpriteSetShader(std::move(parts));
|
||||||
|
|
||||||
|
instance->Enable();
|
||||||
|
int texIDs[] = { 0 };
|
||||||
|
instance->SetUniform("atlas", 0);
|
||||||
|
instance->Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::GLFW::BasicOrderedSpriteSetShader::BasicOrderedSpriteSetShader(std::vector<std::unique_ptr<ShaderPart>> &&parts) : Shader(parts)
|
||||||
|
{
|
||||||
|
PackageSize = SHADER_PACKAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::GLFW::BasicOrderedSpriteSetShader::~BasicOrderedSpriteSetShader()
|
||||||
|
{
|
||||||
|
if (meshVBO) glDeleteBuffers(1, &meshVBO);
|
||||||
|
if (meshIBO) glDeleteBuffers(1, &meshIBO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::SetMesh(const void *verts, int vertCount, int stride, int floatCountPerVertex, int posOffsetBytes, GLenum primitive, const void *indices, int indexCount, GLenum indexType)
|
||||||
|
{
|
||||||
|
GLint prevVAO = 0, prevArrayBuffer = 0, prevElementBuffer = 0;
|
||||||
|
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &prevVAO);
|
||||||
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prevArrayBuffer);
|
||||||
|
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prevElementBuffer);
|
||||||
|
|
||||||
|
if (!meshVBO) glGenBuffers(1, &meshVBO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, meshVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertCount * stride, verts, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
if (indices && indexCount > 0)
|
||||||
|
{
|
||||||
|
if (!meshIBO) glGenBuffers(1, &meshIBO);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshIBO);
|
||||||
|
GLsizeiptr idxSize =
|
||||||
|
(indexType == GL_UNSIGNED_INT ? 4 :
|
||||||
|
indexType == GL_UNSIGNED_SHORT? 2 : 1) * indexCount;
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idxSize, indices, GL_STATIC_DRAW);
|
||||||
|
meshIndexCount = indexCount;
|
||||||
|
meshIndexType = indexType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Kein Index-Buffer
|
||||||
|
if (meshIBO) { glDeleteBuffers(1, &meshIBO); meshIBO = 0; }
|
||||||
|
meshIndexCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
meshVertexCount = vertCount;
|
||||||
|
meshStride = stride;
|
||||||
|
meshPosOffset = posOffsetBytes;
|
||||||
|
meshPosSize = floatCountPerVertex;
|
||||||
|
meshPrimitive = primitive;
|
||||||
|
meshReady = true;
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, prevArrayBuffer);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prevElementBuffer);
|
||||||
|
glBindVertexArray(prevVAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::OnEnable() const
|
||||||
|
{
|
||||||
|
if (!meshReady)
|
||||||
|
{
|
||||||
|
// Fallback: unit-Quad als TRIANGLE_FAN (4 Vertices, 2D Positionen)
|
||||||
|
const float quad[8] = { -0.5f,0, 0.5f,0, 0.5f,1, -0.5f,1 };
|
||||||
|
const_cast<BasicOrderedSpriteSetShader*>(this)->SetMesh(
|
||||||
|
quad, 4, sizeof(float)*2, 2, 0, GL_TRIANGLE_FAN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint prevArrayBuffer = 0;
|
||||||
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prevArrayBuffer);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, meshVBO);
|
||||||
|
glEnableVertexAttribArray(SHADER_MESH_INDEX); // LOC_QUAD/pos
|
||||||
|
glVertexAttribPointer(SHADER_MESH_INDEX, meshPosSize, GL_FLOAT, GL_FALSE, meshStride, (void*)meshPosOffset);
|
||||||
|
glVertexAttribDivisor(SHADER_MESH_INDEX, 0); // per-vertex (Mesh)
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, prevArrayBuffer);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(SHADER_POS_INDEX);
|
||||||
|
glVertexAttribPointer(SHADER_POS_INDEX, 3, GL_FLOAT, GL_FALSE, PackageSize, (void*)0);
|
||||||
|
glVertexAttribDivisor(SHADER_POS_INDEX, 1);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(SHADER_LAYER_HEIGHT_INDEX);
|
||||||
|
glVertexAttribPointer(SHADER_LAYER_HEIGHT_INDEX, 1, GL_FLOAT, GL_FALSE, PackageSize, (void*)(sizeof(float)*3));
|
||||||
|
glVertexAttribDivisor(SHADER_LAYER_HEIGHT_INDEX, 1);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(SHADER_SPRITE_INDEX);
|
||||||
|
glVertexAttribPointer(SHADER_SPRITE_INDEX, 1, GL_FLOAT, GL_FALSE, PackageSize, (void*)(sizeof(float)*4));
|
||||||
|
glVertexAttribDivisor(SHADER_SPRITE_INDEX, 1);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(SHADER_NORMAL_INDEX);
|
||||||
|
glVertexAttribPointer(SHADER_NORMAL_INDEX, 1, GL_FLOAT, GL_FALSE, PackageSize, (void*)(sizeof(float)*5));
|
||||||
|
glVertexAttribDivisor(SHADER_NORMAL_INDEX, 1);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(SHADER_SCALE_INDEX);
|
||||||
|
glVertexAttribPointer(SHADER_SCALE_INDEX, 2, GL_FLOAT, GL_FALSE, PackageSize, (void*)(sizeof(float)*6));
|
||||||
|
glVertexAttribDivisor(SHADER_SCALE_INDEX, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::OnDisable() const
|
||||||
|
{
|
||||||
|
glDisableVertexAttribArray(SHADER_MESH_INDEX);
|
||||||
|
glDisableVertexAttribArray(SHADER_POS_INDEX);
|
||||||
|
glDisableVertexAttribArray(SHADER_LAYER_HEIGHT_INDEX);
|
||||||
|
glDisableVertexAttribArray(SHADER_SPRITE_INDEX);
|
||||||
|
glDisableVertexAttribArray(SHADER_NORMAL_INDEX);
|
||||||
|
glDisableVertexAttribArray(SHADER_SCALE_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::OnFlush()
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, TextureID);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::OnDrawCall(int indexCount)
|
||||||
|
{
|
||||||
|
if (instanceCount <= 0) return;
|
||||||
|
SetUniform("spriteCount", &SpriteCount);
|
||||||
|
|
||||||
|
GLint prevElementBuffer = 0;
|
||||||
|
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prevElementBuffer);
|
||||||
|
|
||||||
|
if (meshIBO && meshIndexCount > 0)
|
||||||
|
{
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshIBO);
|
||||||
|
glDrawElementsInstanced(meshPrimitive, meshIndexCount, meshIndexType, (void*)0, instanceCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
glDrawArraysInstanced(meshPrimitive, 0, meshVertexCount, instanceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)prevElementBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::OnPostDraw()
|
||||||
|
{
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
instanceCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::GLFW::BasicOrderedSpriteSetShader::OnSubmit(const Transformable &t, float *&target, TransformationStack &stack, void (*restartDrawcall)(IRenderer &), IRenderer &rnd)
|
||||||
|
{
|
||||||
|
auto* r = dynamic_cast<Renderable*>(t.GetBehaviourScript(RENDERABLE));
|
||||||
|
if (!r) return;
|
||||||
|
|
||||||
|
auto* tm = dynamic_cast<OrdererSpriteSet*>(t.GetBehaviourScript(ORDERERSPRITESET));
|
||||||
|
if (!tm) return;
|
||||||
|
|
||||||
|
auto tileSet = tm->GetTileSet();
|
||||||
|
TextureID = tileSet->GetTextueID();
|
||||||
|
SpriteCount = tileSet->GetCount();
|
||||||
|
|
||||||
|
const std::vector<Vector2> orderedChunks = *tm->GetChunkPositionsInOrder();
|
||||||
|
|
||||||
|
Matrix4x4 matr = t.GetLocalMatrix();
|
||||||
|
|
||||||
|
stack.Push(matr);
|
||||||
|
|
||||||
|
for(auto chunkPos : orderedChunks)
|
||||||
|
{
|
||||||
|
auto chunk = tm->GetChunk(chunkPos);
|
||||||
|
const int spriteCount = chunk->GetSpriteCount();
|
||||||
|
const std::vector<Vector3> spritePositions = *chunk->GetOrderedPositions();
|
||||||
|
const std::vector<Vector2i> spriteIds = *chunk->GetOrderedSpriteIds();
|
||||||
|
const std::vector<Vector2> spriteScales = *chunk->GetOrderedScales();
|
||||||
|
int chunkSize = chunk->GetChunksize();
|
||||||
|
|
||||||
|
for (int i = 0; i < spriteCount; i++)
|
||||||
|
{
|
||||||
|
Matrix4x4 mat = Matrix4x4::ToTranslationMatrix(chunkPos + spritePositions[i].ToVector2()) * Matrix4x4::ToRotationMatrix(Quaternion()) * Matrix4x4::ToScaleMatrix({1,1,1});
|
||||||
|
stack.Push(mat);
|
||||||
|
Vector3 pos = stack.Top() * Vector3(0,0,0);
|
||||||
|
|
||||||
|
*target++ = pos.x;
|
||||||
|
*target++ = pos.y;
|
||||||
|
*target++ = pos.z;
|
||||||
|
*target++ = spritePositions[i].z;
|
||||||
|
*target++ = spriteIds[i].x;
|
||||||
|
*target++ = spriteIds[i].y;
|
||||||
|
*target++ = spriteScales[i].x;
|
||||||
|
*target++ = spriteScales[i].y;
|
||||||
|
|
||||||
|
++instanceCount;
|
||||||
|
stack.Pop();
|
||||||
|
|
||||||
|
if(instanceCount >= 16000)
|
||||||
|
restartDrawcall(rnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.Pop();
|
||||||
|
restartDrawcall(rnd);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GL/gl3w.h"
|
||||||
|
#include "GL/gl.h"
|
||||||
|
#include "Shader.hpp"
|
||||||
|
#include "Types.hpp"
|
||||||
|
|
||||||
|
namespace TSE::GLFW
|
||||||
|
{
|
||||||
|
class BasicOrderedSpriteSetShader : public Shader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static BasicOrderedSpriteSetShader* instance;
|
||||||
|
mutable bool meshReady = false;
|
||||||
|
GLuint meshVBO = 0;
|
||||||
|
GLuint meshIBO = 0;
|
||||||
|
GLsizei meshVertexCount = 0; // für DrawArraysInstanced
|
||||||
|
GLsizei meshIndexCount = 0; // für DrawElementsInstanced
|
||||||
|
GLenum meshPrimitive = GL_TRIANGLES;
|
||||||
|
GLenum meshIndexType = GL_UNSIGNED_SHORT;
|
||||||
|
int instanceCount = 0; // eigener Instanzzähler
|
||||||
|
GLint meshPosSize = 2; // 2D (Billboard-Formen), für 3D Meshes: 3
|
||||||
|
GLsizei meshStride = sizeof(float) * 2;
|
||||||
|
size_t meshPosOffset = 0;
|
||||||
|
GLuint TextureID;
|
||||||
|
Vector2 SpriteCount;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static BasicOrderedSpriteSetShader* Instance();
|
||||||
|
static void Destroy();
|
||||||
|
static void Init(float width, float height);
|
||||||
|
BasicOrderedSpriteSetShader(std::vector<std::unique_ptr<ShaderPart>>&& parts);
|
||||||
|
~BasicOrderedSpriteSetShader();
|
||||||
|
void SetMesh(const void* verts, int vertCount, int stride, int floatCountPerVertex, int posOffsetBytes, GLenum primitive, const void* indices = nullptr, int indexCount = 0, GLenum indexType = GL_UNSIGNED_SHORT);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void OnEnable() const override;
|
||||||
|
void OnDisable() const override;
|
||||||
|
void OnFlush() override;
|
||||||
|
void OnDrawCall(int indexCount) override;
|
||||||
|
void OnPostDraw() override;
|
||||||
|
void OnSubmit(const Transformable& t, float*& target, TransformationStack& stack, void (*restartDrawcall)(IRenderer&), IRenderer& rnd) override;
|
||||||
|
};
|
||||||
|
} // namespace TSE::GLFW
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
inline const char* vertOrderedSet = R"(
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 aPos;
|
||||||
|
|
||||||
|
layout(location = 1) in vec3 iTilePos;
|
||||||
|
layout(location = 2) in float height;
|
||||||
|
layout(location = 3) in float iSpriteId;
|
||||||
|
layout(location = 4) in float iNormalId;
|
||||||
|
layout(location = 5) in vec2 spriteScale;
|
||||||
|
|
||||||
|
uniform mat4 prMatrix;
|
||||||
|
uniform mat4 camMatrix;
|
||||||
|
|
||||||
|
out vec2 vUV;
|
||||||
|
flat out int vSpriteId;
|
||||||
|
flat out int vNormalId;
|
||||||
|
flat out float vTileNdcY;
|
||||||
|
flat out float layerHeight;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 local = vec3(aPos.x, aPos.y, 0);
|
||||||
|
vec2 baseUV = aPos + vec2(0.5, 0);
|
||||||
|
vec3 tileSize = vec3(spriteScale.x, spriteScale.y, 1);
|
||||||
|
|
||||||
|
vec3 worldPos = (iTilePos * tileSize) + (local * tileSize);
|
||||||
|
|
||||||
|
vec4 clip = prMatrix * camMatrix * vec4(worldPos, 1.0);
|
||||||
|
gl_Position = clip;
|
||||||
|
|
||||||
|
vUV = baseUV;
|
||||||
|
vSpriteId = int(iSpriteId + 0.5);
|
||||||
|
vNormalId = int(iNormalId + 0.5);
|
||||||
|
layerHeight = height;
|
||||||
|
|
||||||
|
vec3 localbottom = vec3(0.5, 0, 0);
|
||||||
|
vec3 worldPosBottom = (iTilePos * tileSize) + (localbottom * tileSize);
|
||||||
|
vec4 clipbottom = prMatrix * camMatrix * vec4(worldPosBottom, 1.0);
|
||||||
|
float ndcY = clipbottom.y / clipbottom.w;
|
||||||
|
vTileNdcY = ndcY * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
inline const char* fragOrderedSet = R"(
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 vUV;
|
||||||
|
flat in int vSpriteId;
|
||||||
|
flat in int vNormalId;
|
||||||
|
flat in float vTileNdcY;
|
||||||
|
flat in float layerHeight;
|
||||||
|
|
||||||
|
uniform sampler2D atlas;
|
||||||
|
uniform vec2 spriteCount;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
layout(location = 1) out vec4 FragHeight;
|
||||||
|
layout(location = 2) out vec4 FragDepth;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float t = (vTileNdcY + 1.0) * 0.5 *0.8;
|
||||||
|
FragDepth = vec4(t, 0, 0, 1.0);
|
||||||
|
|
||||||
|
vec2 tileUVSize = 1.0 / spriteCount;
|
||||||
|
|
||||||
|
int cols = int(spriteCount.x);
|
||||||
|
int sx = vSpriteId % cols;
|
||||||
|
int sy = vSpriteId / cols;
|
||||||
|
|
||||||
|
vec2 atlasOffset = vec2(float(sx), float(sy)) * tileUVSize;
|
||||||
|
vec2 atlasUV = atlasOffset + (vUV * tileUVSize);
|
||||||
|
vec4 c = texture(atlas, atlasUV);
|
||||||
|
if (c.a < 0.01) discard;
|
||||||
|
float colorScaler = 1 - ((layerHeight - 1) * -1) * 0.3;
|
||||||
|
c = vec4(c.x * colorScaler,c.y * colorScaler,c.z * colorScaler,c.w);
|
||||||
|
|
||||||
|
FragColor = c;
|
||||||
|
|
||||||
|
if(vNormalId != -1)
|
||||||
|
{
|
||||||
|
int sx2 = vNormalId % cols;
|
||||||
|
int sy2 = vNormalId / cols;
|
||||||
|
vec2 atlasOffsetNormal = vec2(float(sx2), float(sy2)) * tileUVSize;
|
||||||
|
vec2 atlasUVNormal = atlasOffsetNormal + (vUV * tileUVSize);
|
||||||
|
vec4 cNormal = texture(atlas, atlasUVNormal);
|
||||||
|
cNormal.w = layerHeight;
|
||||||
|
|
||||||
|
FragHeight = cNormal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "ditheringShader.hpp"
|
#include "ditheringShader.hpp"
|
||||||
#include "basicParticleShader.hpp"
|
#include "basicParticleShader.hpp"
|
||||||
#include "basicTileMapShader.hpp"
|
#include "basicTileMapShader.hpp"
|
||||||
|
#include "basicOrderedSpriteSetShader.hpp"
|
||||||
#include "elements/ShaderRegistry.hpp"
|
#include "elements/ShaderRegistry.hpp"
|
||||||
|
|
||||||
void TSE::GLFW::LoadBasicShaders(float width, float height)
|
void TSE::GLFW::LoadBasicShaders(float width, float height)
|
||||||
@@ -13,11 +14,13 @@ void TSE::GLFW::LoadBasicShaders(float width, float height)
|
|||||||
DitheringShader::Init(width, height);
|
DitheringShader::Init(width, height);
|
||||||
BasicParticleShader::Init(width, height);
|
BasicParticleShader::Init(width, height);
|
||||||
BasicTileMapShader::Init(width, height);
|
BasicTileMapShader::Init(width, height);
|
||||||
|
BasicOrderedSpriteSetShader::Init(width, height);
|
||||||
ShaderRegistry::SetShader("Basic Unlit Shader", BasicShader::Instance());
|
ShaderRegistry::SetShader("Basic Unlit Shader", BasicShader::Instance());
|
||||||
ShaderRegistry::SetShader("Basic Unlit Texture Shader", BasicTextureShader::Instance());
|
ShaderRegistry::SetShader("Basic Unlit Texture Shader", BasicTextureShader::Instance());
|
||||||
ShaderRegistry::SetShader("Basic Unlit Dithering Shader", DitheringShader::Instance());
|
ShaderRegistry::SetShader("Basic Unlit Dithering Shader", DitheringShader::Instance());
|
||||||
ShaderRegistry::SetShader("Basic Unlit Particle Shader", BasicParticleShader::Instance());
|
ShaderRegistry::SetShader("Basic Unlit Particle Shader", BasicParticleShader::Instance());
|
||||||
ShaderRegistry::SetShader("Basic Unlit TileMap Shader", BasicTileMapShader::Instance());
|
ShaderRegistry::SetShader("Basic Unlit TileMap Shader", BasicTileMapShader::Instance());
|
||||||
|
ShaderRegistry::SetShader("Basic Ordered Sprite Set Shader", BasicOrderedSpriteSetShader::Instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::GLFW::UnLoadBasicShaders()
|
void TSE::GLFW::UnLoadBasicShaders()
|
||||||
@@ -27,9 +30,11 @@ void TSE::GLFW::UnLoadBasicShaders()
|
|||||||
ShaderRegistry::RemoveShader("Basic Unlit Dithering Shader");
|
ShaderRegistry::RemoveShader("Basic Unlit Dithering Shader");
|
||||||
ShaderRegistry::RemoveShader("Basic Unlit Particle Shader");
|
ShaderRegistry::RemoveShader("Basic Unlit Particle Shader");
|
||||||
ShaderRegistry::RemoveShader("Basic Unlit TileMap Shader");
|
ShaderRegistry::RemoveShader("Basic Unlit TileMap Shader");
|
||||||
|
ShaderRegistry::RemoveShader("Basic Ordered Sprite Set Shader");
|
||||||
BasicShader::Destroy();
|
BasicShader::Destroy();
|
||||||
BasicTextureShader::Destroy();
|
BasicTextureShader::Destroy();
|
||||||
DitheringShader::Destroy();
|
DitheringShader::Destroy();
|
||||||
BasicParticleShader::Destroy();
|
BasicParticleShader::Destroy();
|
||||||
BasicTileMapShader::Destroy();
|
BasicTileMapShader::Destroy();
|
||||||
|
BasicOrderedSpriteSetShader::Destroy();
|
||||||
}
|
}
|
||||||
|
|||||||
107
TSE_Math/src/Random.cpp
Normal file
107
TSE_Math/src/Random.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "Random.hpp"
|
||||||
|
#include <bit>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
TSE::Random::Random(uint seed)
|
||||||
|
{
|
||||||
|
state = static_cast<uint>(static_cast<std::uint32_t>(seed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::uint TSE::Random::nextUInt(uint minInc, uint maxInc)
|
||||||
|
{
|
||||||
|
constexpr std::uint32_t multiplier = 1664525u;
|
||||||
|
constexpr std::uint32_t increment = 1013904223u;
|
||||||
|
|
||||||
|
std::uint32_t nextState = static_cast<std::uint32_t>(state);
|
||||||
|
nextState = nextState * multiplier + increment;
|
||||||
|
state = static_cast<uint>(nextState);
|
||||||
|
|
||||||
|
if(minInc == 0u && maxInc == 0u)
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minInc > maxInc)
|
||||||
|
{
|
||||||
|
uint temp = minInc;
|
||||||
|
minInc = maxInc;
|
||||||
|
maxInc = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint64_t span = static_cast<std::uint64_t>(maxInc) - static_cast<std::uint64_t>(minInc) + 1ull;
|
||||||
|
const std::uint64_t offset = static_cast<std::uint64_t>(nextState) % span;
|
||||||
|
return static_cast<uint>(static_cast<std::uint64_t>(minInc) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TSE::Random::nextInt(int minInc, int maxInc)
|
||||||
|
{
|
||||||
|
const std::uint32_t bits = static_cast<std::uint32_t>(nextUInt());
|
||||||
|
|
||||||
|
if(minInc == 0 && maxInc == 0)
|
||||||
|
{
|
||||||
|
return static_cast<int>(std::bit_cast<std::int32_t>(bits));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minInc > maxInc)
|
||||||
|
{
|
||||||
|
int temp = minInc;
|
||||||
|
minInc = maxInc;
|
||||||
|
maxInc = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::int64_t span = static_cast<std::int64_t>(maxInc) - static_cast<std::int64_t>(minInc) + 1ll;
|
||||||
|
const std::uint64_t offset = static_cast<std::uint64_t>(bits) % static_cast<std::uint64_t>(span);
|
||||||
|
const std::int64_t value = static_cast<std::int64_t>(minInc) + static_cast<std::int64_t>(offset);
|
||||||
|
return static_cast<int>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
short TSE::Random::nextShort(short minInc, short maxInc)
|
||||||
|
{
|
||||||
|
const std::uint32_t bits = static_cast<std::uint32_t>(nextUInt());
|
||||||
|
const std::uint16_t lowerBits = static_cast<std::uint16_t>(bits);
|
||||||
|
|
||||||
|
if(minInc == 0 && maxInc == 0)
|
||||||
|
{
|
||||||
|
return static_cast<short>(std::bit_cast<std::int16_t>(lowerBits));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minInc > maxInc)
|
||||||
|
{
|
||||||
|
short temp = minInc;
|
||||||
|
minInc = maxInc;
|
||||||
|
maxInc = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::int32_t span = static_cast<std::int32_t>(maxInc) - static_cast<std::int32_t>(minInc) + 1;
|
||||||
|
const std::uint32_t offset = static_cast<std::uint32_t>(lowerBits) % static_cast<std::uint32_t>(span);
|
||||||
|
const std::int32_t value = static_cast<std::int32_t>(minInc) + static_cast<std::int32_t>(offset);
|
||||||
|
return static_cast<short>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::byte TSE::Random::nextByte(byte minInc, byte maxInc)
|
||||||
|
{
|
||||||
|
const std::uint32_t bits = static_cast<std::uint32_t>(nextUInt());
|
||||||
|
const std::uint8_t lowerBits = static_cast<std::uint8_t>(bits);
|
||||||
|
|
||||||
|
if(minInc == 0 && maxInc == 0)
|
||||||
|
{
|
||||||
|
return static_cast<byte>(lowerBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minInc > maxInc)
|
||||||
|
{
|
||||||
|
byte temp = minInc;
|
||||||
|
minInc = maxInc;
|
||||||
|
maxInc = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint16_t span = static_cast<std::uint16_t>(maxInc) - static_cast<std::uint16_t>(minInc) + 1u;
|
||||||
|
const std::uint16_t offset = static_cast<std::uint16_t>(lowerBits) % span;
|
||||||
|
return static_cast<byte>(static_cast<std::uint16_t>(minInc) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float TSE::Random::nextFloat01()
|
||||||
|
{
|
||||||
|
constexpr float invRange = 1.0f / 4294967296.0f;
|
||||||
|
return static_cast<float>(static_cast<std::uint32_t>(nextUInt())) * invRange;
|
||||||
|
}
|
||||||
20
TSE_Math/src/Random.hpp
Normal file
20
TSE_Math/src/Random.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Types.hpp"
|
||||||
|
|
||||||
|
namespace TSE
|
||||||
|
{
|
||||||
|
class Random
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint state;
|
||||||
|
public:
|
||||||
|
Random(uint seed);
|
||||||
|
|
||||||
|
uint nextUInt(uint minInc = 0, uint maxInc = 0);
|
||||||
|
int nextInt(int minInc = 0, int maxInc = 0);
|
||||||
|
short nextShort(short minInc = 0, short maxInc = 0);
|
||||||
|
byte nextByte(byte minInc = 0, byte maxInc = 0);
|
||||||
|
float nextFloat01();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Types.hpp"
|
#include "Types.hpp"
|
||||||
|
#include <functional>
|
||||||
|
#include <cstddef>
|
||||||
|
#include "MathF.hpp"
|
||||||
|
|
||||||
namespace TSE
|
namespace TSE
|
||||||
{
|
{
|
||||||
@@ -145,3 +148,22 @@ namespace TSE
|
|||||||
|
|
||||||
};
|
};
|
||||||
} // namespace TSE
|
} // namespace TSE
|
||||||
|
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template<>
|
||||||
|
struct hash<TSE::Vector3>
|
||||||
|
{
|
||||||
|
size_t operator()(const TSE::Vector3& v) const noexcept
|
||||||
|
{
|
||||||
|
size_t h1 = std::hash<float>{}(v.x);
|
||||||
|
size_t h2 = std::hash<float>{}(v.y);
|
||||||
|
size_t h3 = std::hash<float>{}(v.z);
|
||||||
|
size_t hash = h1;
|
||||||
|
hash ^= h2 + TSE::TSE_HASH_GOLDEN_RATIO_32 + (hash << 6) + (hash >> 2);
|
||||||
|
hash ^= h3 + TSE::TSE_HASH_GOLDEN_RATIO_32 + (hash << 6) + (hash >> 2);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user