diff --git a/TSE b/TSE index 769bbd4..f859288 160000 --- a/TSE +++ b/TSE @@ -1 +1 @@ -Subproject commit 769bbd426169ff79d55975524197abb9519a4774c04df0a8a92c4135f0e70eb4 +Subproject commit f8592886899fe936be29b1d0268ec86ea46e5ad6cae0dc4d1d4ba31299662c27 diff --git a/TSE-RTS/Resources/tiles.png b/TSE-RTS/Resources/tiles.png index a3a39b1..67455d4 100644 Binary files a/TSE-RTS/Resources/tiles.png and b/TSE-RTS/Resources/tiles.png differ diff --git a/TSE-RTS/Resources/trees.aseprite b/TSE-RTS/Resources/trees.aseprite new file mode 100644 index 0000000..c5abac3 Binary files /dev/null and b/TSE-RTS/Resources/trees.aseprite differ diff --git a/TSE-RTS/Resources/trees.png b/TSE-RTS/Resources/trees.png new file mode 100644 index 0000000..a45dfb6 Binary files /dev/null and b/TSE-RTS/Resources/trees.png differ diff --git a/TSE-RTS/src/game.cpp b/TSE-RTS/src/game.cpp index d590caf..8bbbfef 100644 --- a/TSE-RTS/src/game.cpp +++ b/TSE-RTS/src/game.cpp @@ -1,6 +1,7 @@ #include "game.hpp" #include "elements/Transformable.hpp" #include "BehaviourScripts/TileMap.hpp" +#include "BehaviourScripts/OrdererSpriteSet.hpp" #include "BehaviourScripts/Renderable.hpp" #include "elements/ShaderRegistry.hpp" #include "Vector2.hpp" @@ -12,25 +13,31 @@ #include "BehaviourScripts/CameraSizeChangeNotifyer.hpp" #include "BehaviourScripts/RenderTextureResizes.hpp" #include "BehaviourScripts/CanvasScaler.hpp" +#include "Random.hpp" #define circleRadius 32 #define circleFallof 25 +#define treeCircleRadius 27 +#define treeCircleFallof 20 void game::setup(TSE::Scene* s, TSE::IWindow* wnd) { using namespace TSE; s->AddLayer(&gameLayer); + s->AddLayer(&propsLayer); TileMap* maps[4]; + OrdererSpriteSet* props; Material* tileMapMaterial = new Material("tileSetMat", ShaderRegistry::GetShader("TileMapShader v2")); + tileMapMaterial->SetValue("spritePivot", Vector2(0,0)); + Texture* setTexture = new Texture("tiles.png"); + TileSet* set = new TileSet(setTexture, 10, 10); for (int i = 0; i < 4; i++) { Transformable* tileMap = new Transformable("tileMapL" + std::to_string(i)); tileMap->position += {0,0.5f * i,0}; gameLayer.AddTransformable(tileMap); - Texture* setTexture = new Texture("tiles.png"); - TileSet* set = new TileSet(setTexture, 10, 10); TileMap* map = new TileMap(); map->chunkSize = 12; map->set = set; @@ -42,19 +49,40 @@ void game::setup(TSE::Scene* s, TSE::IWindow* wnd) maps[i] = map; } + + Material* objectsMaterial = new Material("objectsTileSetMat", ShaderRegistry::GetShader("Basic Ordered Sprite Set Shader")); + Texture* treeSetTexture = new Texture("trees.png"); + TileSet* treeSet = new TileSet(treeSetTexture, 6, 2); + Transformable* tileMap = new Transformable("propMap"); + propsLayer.AddTransformable(tileMap); + OrdererSpriteSet* map = new OrdererSpriteSet(); + map->chunkSize = 12; + map->set = treeSet; + //map->SpriteScale = Vector2(1,2); + + Renderable* rend = new Renderable(objectsMaterial); + + tileMap->AddBehaviourScript(map); + tileMap->AddBehaviourScript(rend); + + props = map; + + Random rnd = Random(12345u); - - const siv::PerlinNoise::seed_type seed = 123456u; - const siv::PerlinNoise perlin{ seed }; + const siv::PerlinNoise perlin{ rnd.nextUInt() }; + const siv::PerlinNoise perlin2{ rnd.nextUInt() }; for (int x = circleRadius * -4; x < circleRadius * 4; x++) { for (int y = circleRadius * -4; y < circleRadius * 4; y++) { float noise = (float)perlin.octave2D_01(x * 0.05f,y * 0.05f, 4); + float treeNoise = (float)perlin2.octave2D_01(x * 0.05f,y * 0.05f, 2); float noiseFallof = 1; + float treeNoiseFallof = 1; Vector2 realpos = maps[0]->TileMapToRealPos(Vector2(x,y)); + Vector2 realposprop = (maps[0]->TileMapToRealPos(Vector2(x,y)) + Vector2(0, 0.25f)) * Vector2(1,0.5f); realpos *= {1,1.5f}; float dist = realpos.Length(); if(dist <= circleRadius && dist >= circleFallof) @@ -62,24 +90,54 @@ void game::setup(TSE::Scene* s, TSE::IWindow* wnd) float reldist = dist - circleFallof; noiseFallof = (reldist / (circleRadius - circleFallof) - 1) * -1; } + if(dist <= treeCircleRadius && dist >= treeCircleFallof) + { + float reldist = dist - treeCircleFallof; + treeNoiseFallof = (reldist / (treeCircleRadius - treeCircleFallof) - 1) * -1; + } + else if (dist > treeCircleRadius) + treeNoiseFallof = 0; noise *= noiseFallof; + treeNoise *= treeNoiseFallof; if(dist <= circleRadius && noise >= 0.2f) { + float treernd = rnd.nextFloat01(); + int treeid = 0; if(noise >= 0.8f) { - maps[3]->SetTile(Vector2(x, y), {0,9}, {2,9}); + if(treeNoise > 0.5f && treernd > 0.4f) + { + treeid = rnd.nextInt(0,5); + props->SetSprite(realposprop + Vector2(0, 0.75f), Vector2(treeid, 1), 4.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0)); + } + maps[3]->SetTile(Vector2(x, y), {0,9}, {1,9}); } else if(noise >= 0.6f) { - maps[2]->SetTile(Vector2(x, y), {0,9}, {2,9}); + if(treeNoise > 0.5f && treernd > 0.4f) + { + treeid = rnd.nextInt(0,5); + props->SetSprite(realposprop + Vector2(0, 0.5f), Vector2(treeid, 1), 3.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0)); + } + maps[2]->SetTile(Vector2(x, y), {0,9}, {1,9}); } else if(noise >= 0.4f) { - maps[1]->SetTile(Vector2(x, y), {0,9}, {2,9}); + if(treeNoise > 0.5f && treernd > 0.4f) + { + treeid = rnd.nextInt(0,5); + props->SetSprite(realposprop + Vector2(0, 0.25f), Vector2(treeid, 1), 2.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0)); + } + maps[1]->SetTile(Vector2(x, y), {0,9}, {1,9}); } else { - maps[0]->SetTile(Vector2(x, y), {0,9}, {2,9}); + if(treeNoise > 0.5f && treernd > 0.4f) + { + treeid = rnd.nextInt(0,5); + props->SetSprite(realposprop, Vector2(treeid, 1), 1.5f / 10.0f, Vector2(1,2), Vector2(treeid, 0)); + } + maps[0]->SetTile(Vector2(x, y), {0,9}, {1,9}); } } } @@ -88,12 +146,17 @@ void game::setup(TSE::Scene* s, TSE::IWindow* wnd) //RenderingLayer s->AddLayer(&renderingLayer); + s->AddLayer(&characterLayer); + + Transformable* player = new Transformable("Player"); Transformable* lastPassCamera = new Transformable("lastPassCamera"); Camera* lpCam = new Camera(); lpCam->SetRenderTarget(wnd); lpCam->SetRenderScale(1); lpCam->layersNotToRender.push_back(gameLayer.GetID()); + lpCam->layersNotToRender.push_back(propsLayer.GetID()); + lpCam->layersNotToRender.push_back(characterLayer.GetID()); lastPassCamera->AddBehaviourScript(lpCam); CameraSizeChangeNotifyer* camNotifyer = new CameraSizeChangeNotifyer(); camNotifyer->lastSize = {0,0}; @@ -102,21 +165,39 @@ void game::setup(TSE::Scene* s, TSE::IWindow* wnd) Vector2 canvasSize = wnd->GetSize() / 4.0f; - IRenderTexture* rt = IRenderTexture::factory->CreateTextureHeap(canvasSize, 2); + IRenderTexture* rt = IRenderTexture::factory->CreateTextureHeap(canvasSize, 3); Transformable* firstPassCamera = new Transformable("firstPassCamera"); Camera* fpCam = new Camera(); fpCam->SetRenderScale(256); fpCam->SetRenderTarget(rt); fpCam->layersNotToRender.push_back(renderingLayer.GetID()); + fpCam->layersNotToRender.push_back(propsLayer.GetID()); + fpCam->layersNotToRender.push_back(characterLayer.GetID()); firstPassCamera->AddBehaviourScript(fpCam); RenderTextureResizes* resizer = new RenderTextureResizes(); resizer->rt = rt; camNotifyer->Observe(resizer); firstPassCamera->AddBehaviourScript(resizer); + firstPassCamera->SetParent(player); + + IRenderTexture* rtProps = IRenderTexture::factory->CreateTextureHeap(canvasSize, 3); + Transformable* secondPassCamera = new Transformable("secondPassCamera"); + Camera* spCam = new Camera(); + spCam->SetRenderScale(256); + spCam->SetRenderTarget(rtProps); + spCam->layersNotToRender.push_back(renderingLayer.GetID()); + spCam->layersNotToRender.push_back(gameLayer.GetID()); + spCam->layersNotToRender.push_back(characterLayer.GetID()); + secondPassCamera->AddBehaviourScript(spCam); + RenderTextureResizes* resizerProps = new RenderTextureResizes(); + resizerProps->rt = rtProps; + camNotifyer->Observe(resizerProps); + secondPassCamera->AddBehaviourScript(resizerProps); + secondPassCamera->SetParent(player); //Render pipeline setup - gameLayer.AddTransformable(firstPassCamera); + characterLayer.AddTransformable(player); renderingLayer.AddTransformable(lastPassCamera); //final @@ -130,9 +211,13 @@ void game::setup(TSE::Scene* s, TSE::IWindow* wnd) Material* canvasMat = new Material("canvasMat", ShaderRegistry::GetShader("LastPassShader")); canvasMat->SetValue("threshold", 0.01f); - canvasMat->SetValue("darken", 0.45f); + canvasMat->SetValue("darken", 0.15f); canvasMat->SetValue("colorTextureID", rt->GetTextureId(0)); canvasMat->SetValue("heightTextureID", rt->GetTextureId(1)); + canvasMat->SetValue("depthTextureID", rt->GetTextureId(2)); + canvasMat->SetValue("colorTexture2ID", rtProps->GetTextureId(0)); + canvasMat->SetValue("heightTexture2ID", rtProps->GetTextureId(1)); + canvasMat->SetValue("depthTexture2ID", rtProps->GetTextureId(2)); Renderable* canvasRenderer = new Renderable(canvasMat); CanvasScaler* canvasScaler = new CanvasScaler(); diff --git a/TSE-RTS/src/game.hpp b/TSE-RTS/src/game.hpp index 013883f..afd8e0a 100644 --- a/TSE-RTS/src/game.hpp +++ b/TSE-RTS/src/game.hpp @@ -6,7 +6,9 @@ class game { public: inline static TSE::Layer gameLayer = TSE::Layer("gameLayer"); + inline static TSE::Layer propsLayer = TSE::Layer("propsLayer"); inline static TSE::Layer renderingLayer = TSE::Layer("renderingLayer"); + inline static TSE::Layer characterLayer = TSE::Layer("characterLayer"); static void setup(TSE::Scene* s, TSE::IWindow* wnd); }; \ No newline at end of file diff --git a/TSE-RTS/src/main.cpp b/TSE-RTS/src/main.cpp index fb4cfb3..2e3af2b 100644 --- a/TSE-RTS/src/main.cpp +++ b/TSE-RTS/src/main.cpp @@ -18,7 +18,7 @@ #include "shaders/TileMapShader.hpp" #include "shaders/LastPassShader.hpp" -//#define USE_EDITOR +#define USE_EDITOR using namespace TSE; using namespace TSE::GLFW; @@ -32,7 +32,7 @@ EditorSubsystem* editor; void SetupWindow() { - Color backColor(0.0571f, 0.0819f, 0.1043f); + Color backColor(0.0f, 0.0f, 0.0f, 0.0f); #ifdef USE_EDITOR wnd = new WindowGlfw(PROJECT_NAME, 800, 600, new OpenGLRenderingBackend(backColor, false, 8, true), WindowType::Maximized); editor = new EditorSubsystem(); @@ -50,6 +50,7 @@ void SetupWindow() #ifdef USE_EDITOR ((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->layersNotToRender.push_back(game::renderingLayer.GetID()); + ((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->SetRenderScale(128); currentScene->AddLayer(&editor->editorLayer); editor->hv.SetScene(currentScene); #endif diff --git a/TSE-RTS/src/shaders/LastPassShader.cpp b/TSE-RTS/src/shaders/LastPassShader.cpp index c7f5520..b476c0e 100644 --- a/TSE-RTS/src/shaders/LastPassShader.cpp +++ b/TSE-RTS/src/shaders/LastPassShader.cpp @@ -36,6 +36,10 @@ void LastPassShader::Init(float width, float height) instance->Enable(); instance->SetUniform("colorTexture", 0); instance->SetUniform("heightTexture", 1); + instance->SetUniform("depthTexture", 2); + instance->SetUniform("colorTexture2", 3); + instance->SetUniform("heightTexture2", 4); + instance->SetUniform("depthTexture2", 5); instance->Disable(); } @@ -64,6 +68,14 @@ void LastPassShader::OnFlush() glBindTexture(GL_TEXTURE_2D, ColorTextureID); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, HeightTextureID); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, DepthTextureID); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, ColorTexture2ID); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, HeightTexture2ID); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_2D, DepthTexture2ID); SetUniform("uThreshold", Threshold); SetUniform("uDarken", Darken); } @@ -79,10 +91,18 @@ void LastPassShader::OnSubmit(const TSE::Transformable &t, float *&target, TSE:: if (!r) return; if(!r->GetMaterial()->HasValue("colorTextureID")) return; if(!r->GetMaterial()->HasValue("heightTextureID")) return; + if(!r->GetMaterial()->HasValue("depthTextureID")) return; + if(!r->GetMaterial()->HasValue("colorTexture2ID")) return; + if(!r->GetMaterial()->HasValue("heightTexture2ID")) return; + if(!r->GetMaterial()->HasValue("depthTexture2ID")) return; if(!r->GetMaterial()->HasValue("threshold")) return; if(!r->GetMaterial()->HasValue("darken")) return; ColorTextureID = r->GetMaterial()->GetValue("colorTextureID"); + ColorTexture2ID = r->GetMaterial()->GetValue("colorTexture2ID"); HeightTextureID = r->GetMaterial()->GetValue("heightTextureID"); + HeightTexture2ID = r->GetMaterial()->GetValue("heightTexture2ID"); + DepthTextureID = r->GetMaterial()->GetValue("depthTextureID"); + DepthTexture2ID = r->GetMaterial()->GetValue("depthTexture2ID"); Threshold = r->GetMaterial()->GetValue("threshold"); Darken = r->GetMaterial()->GetValue("darken"); diff --git a/TSE-RTS/src/shaders/LastPassShader.hpp b/TSE-RTS/src/shaders/LastPassShader.hpp index 2748c5f..7c47795 100644 --- a/TSE-RTS/src/shaders/LastPassShader.hpp +++ b/TSE-RTS/src/shaders/LastPassShader.hpp @@ -10,7 +10,11 @@ class LastPassShader : public TSE::GLFW::Shader private: static LastPassShader* instance; GLuint ColorTextureID; + GLuint ColorTexture2ID; GLuint HeightTextureID; + GLuint HeightTexture2ID; + GLuint DepthTextureID; + GLuint DepthTexture2ID; float Threshold; float Darken; diff --git a/TSE-RTS/src/shaders/LastPassShaderGLSL.hpp b/TSE-RTS/src/shaders/LastPassShaderGLSL.hpp index bfb3ff8..08ae666 100644 --- a/TSE-RTS/src/shaders/LastPassShaderGLSL.hpp +++ b/TSE-RTS/src/shaders/LastPassShaderGLSL.hpp @@ -28,6 +28,10 @@ inline const char* fragLastPass = R"( uniform sampler2D colorTexture; uniform sampler2D heightTexture; + uniform sampler2D depthTexture; + uniform sampler2D colorTexture2; + uniform sampler2D heightTexture2; + uniform sampler2D depthTexture2; uniform float uThreshold; uniform float uDarken; @@ -76,8 +80,7 @@ inline const char* fragLastPass = R"( } void main() - { - + { ivec2 size = textureSize(heightTexture, 0); ivec2 p = clamp(ivec2(fs_in.uv_out * vec2(size)), ivec2(0), size - ivec2(1)); @@ -87,8 +90,21 @@ inline const char* fragLastPass = R"( float maskH = step(uThreshold, changeInHeight); float maskN = step(uThreshold, changeInNormal); float mask = max(maskH, maskN); - - vec3 col = texelFetch(colorTexture, p, 0).rgb; + + float d1 = texelFetch(depthTexture, p, 0).r; + float d2 = texelFetch(depthTexture2, p, 0).r; + float h1 = texelFetch(heightTexture, p, 0).a; + float h2 = texelFetch(heightTexture2, p, 0).a; + + vec3 col1 = texelFetch(colorTexture, p, 0).rgb; + vec3 col2 = texelFetch(colorTexture2, p, 0).rgb; + + vec3 col = col1; + + if(d2 < d1 && d2 != 0 || h1 < h2 && h2 != 0 && d2 >= d1) + { + col = col2; + } col *= mix(1.0, 1.0 - uDarken, mask); color = vec4(col, 1.0); diff --git a/TSE-RTS/src/shaders/TileMapShader.cpp b/TSE-RTS/src/shaders/TileMapShader.cpp index 40086f0..067c6e8 100644 --- a/TSE-RTS/src/shaders/TileMapShader.cpp +++ b/TSE-RTS/src/shaders/TileMapShader.cpp @@ -151,6 +151,7 @@ void TileMapShader::OnDrawCall(int indexCount) SetUniform("spriteCount", &SpriteCount); SetUniform("spriteScale", &SpriteScale); SetUniform("layerHeight", LayerHeight); + SetUniform("spritePivot", &SpritePivot); GLint prevElementBuffer = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &prevElementBuffer); @@ -183,12 +184,16 @@ void TileMapShader::OnSubmit(const Transformable &t, float *&target, Transformat auto* tm = dynamic_cast(t.GetBehaviourScript(TILE_MAP)); if (!tm) return; - LayerHeight = t.position.y / 1.5f; + LayerHeight = (1 + t.position.y / 0.5f) / 10.0f; + + if(!r->GetMaterial()->HasValue("spritePivot")) return; + SpritePivot = r->GetMaterial()->GetValue("spritePivot"); auto tileSet = tm->GetTileSet(); TextureID = tileSet->GetTextueID(); SpriteCount = tileSet->GetCount(); SpriteScale = tm->SpriteScale; + auto nextLine = tm->GetNextLineOffset(); const std::vector orderedChunks = *tm->GetChunkPositionsInOrder(); @@ -206,7 +211,7 @@ void TileMapShader::OnSubmit(const Transformable &t, float *&target, Transformat for (int i = 0; i < spriteCount; i++) { - Matrix4x4 mat = Matrix4x4::ToTranslationMatrix((chunkPos - chunk->nextLine * chunkPos.y) + spritePositions[i]) * Matrix4x4::ToRotationMatrix(Quaternion()) * Matrix4x4::ToScaleMatrix({1,1,1}); + Matrix4x4 mat = Matrix4x4::ToTranslationMatrix((chunkPos * Vector2(nextLine.x, nextLine.y * 0.5f) + Vector2(-nextLine.x * chunkPos.y, nextLine.y * 0.5f * chunkPos.x)) + spritePositions[i]) * Matrix4x4::ToRotationMatrix(Quaternion()) * Matrix4x4::ToScaleMatrix({1,1,1}); stack.Push(mat); Vector3 pos = stack.Top() * Vector3(0,0,0); diff --git a/TSE-RTS/src/shaders/TileMapShader.hpp b/TSE-RTS/src/shaders/TileMapShader.hpp index 789589e..ddb2b7e 100644 --- a/TSE-RTS/src/shaders/TileMapShader.hpp +++ b/TSE-RTS/src/shaders/TileMapShader.hpp @@ -24,6 +24,8 @@ private: TSE::Vector2 SpriteCount; TSE::Vector2 SpriteScale; float LayerHeight; + int isObjectsLayer; + TSE::Vector2 SpritePivot; public: static TileMapShader* Instance(); diff --git a/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp b/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp index 99eea45..ce6e587 100644 --- a/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp +++ b/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp @@ -13,10 +13,12 @@ inline const char* vertTile2 = R"( uniform mat4 camMatrix; uniform vec2 spriteCount; uniform vec2 spriteScale; + uniform vec2 spritePivot; out vec2 vUV; flat out int vSpriteId; flat out int vNormalId; + flat out float vTileNdcY; void main() { @@ -26,11 +28,18 @@ inline const char* vertTile2 = R"( vec3 worldPos = (iTilePos * tileSize) + (local * tileSize); - gl_Position = prMatrix * camMatrix * vec4(worldPos.x, worldPos.y, worldPos.z, 1.0); + vec4 clip = prMatrix * camMatrix * vec4(worldPos, 1.0); + gl_Position = clip; vUV = baseUV; vSpriteId = int(iSpriteId + 0.5); vNormalId = int(iNormalId + 0.5); + + vec3 localbottom = vec3(spritePivot.x, spritePivot.y, 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; } )"; @@ -40,6 +49,7 @@ inline const char* fragTile2 = R"( in vec2 vUV; flat in int vSpriteId; flat in int vNormalId; + flat in float vTileNdcY; uniform sampler2D atlas; uniform vec2 spriteCount; @@ -47,9 +57,13 @@ inline const char* fragTile2 = R"( 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);