From 9330a08e28c4c096d4bfa0097654f6da9030f51567b415870b29bb7853cdecd7 Mon Sep 17 00:00:00 2001 From: Mexpert_PRO Date: Sat, 21 Feb 2026 13:53:12 +0100 Subject: [PATCH] made improvements with MRT, and the render pipeline, and made shure, that the software works in non editor mode too --- TSE | 2 +- TSE-RTS/Resources/tiles.png | Bin 3525 -> 3873 bytes .../CameraSizeChangeNotifyer.cpp | 17 +++ .../CameraSizeChangeNotifyer.hpp | 25 ++++ TSE-RTS/src/BehaviourScripts/CanvasScaler.cpp | 13 +++ TSE-RTS/src/BehaviourScripts/CanvasScaler.hpp | 24 ++++ .../BehaviourScripts/RenderTextureResizes.cpp | 13 +++ .../BehaviourScripts/RenderTextureResizes.hpp | 23 ++++ TSE-RTS/src/game.cpp | 75 +++++++++++- TSE-RTS/src/game.hpp | 4 +- TSE-RTS/src/main.cpp | 21 ++-- TSE-RTS/src/shaders/LastPassShader.cpp | 109 ++++++++++++++++++ TSE-RTS/src/shaders/LastPassShader.hpp | 29 +++++ TSE-RTS/src/shaders/LastPassShaderGLSL.hpp | 96 +++++++++++++++ TSE-RTS/src/shaders/TileMapShader.cpp | 30 +++-- TSE-RTS/src/shaders/TileMapShader.hpp | 1 + TSE-RTS/src/shaders/TileMapShaderGLSL.hpp | 21 +++- 17 files changed, 476 insertions(+), 27 deletions(-) create mode 100644 TSE-RTS/src/BehaviourScripts/CameraSizeChangeNotifyer.cpp create mode 100644 TSE-RTS/src/BehaviourScripts/CameraSizeChangeNotifyer.hpp create mode 100644 TSE-RTS/src/BehaviourScripts/CanvasScaler.cpp create mode 100644 TSE-RTS/src/BehaviourScripts/CanvasScaler.hpp create mode 100644 TSE-RTS/src/BehaviourScripts/RenderTextureResizes.cpp create mode 100644 TSE-RTS/src/BehaviourScripts/RenderTextureResizes.hpp create mode 100644 TSE-RTS/src/shaders/LastPassShader.cpp create mode 100644 TSE-RTS/src/shaders/LastPassShader.hpp create mode 100644 TSE-RTS/src/shaders/LastPassShaderGLSL.hpp diff --git a/TSE b/TSE index 45501f1..769bbd4 160000 --- a/TSE +++ b/TSE @@ -1 +1 @@ -Subproject commit 45501f153de222598515fef62e04078a96a86a50a6e7bf670050bfd71fd3f12d +Subproject commit 769bbd426169ff79d55975524197abb9519a4774c04df0a8a92c4135f0e70eb4 diff --git a/TSE-RTS/Resources/tiles.png b/TSE-RTS/Resources/tiles.png index deeb8e26cdcee658a3300e7799b2ab078f16f3db700937f386b50a8d8b01e17f..a3a39b1da7010f7e5fefc5e4db1e1e707d4154ecb09c37a5cc4ac7cbba7c8f14 100644 GIT binary patch literal 3873 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 SXSg%*+P> literal 3525 zcmeH|`CC)R8h|GdAr}M^MFa}Lhz(HC0Lmt^g;a_`R+Sy1D2q`l4T!RY7}iQ5RxF8v zh_^+gY_e5?Nl5FkkF@#<)imw|U)I8UF2Pvhw6I_m6DqfhdzaJW?(GDUETk#O2_QtW#p0GvaWQK(ssJ5DcA!E2tRpxK{rRO{FjNeqGT zcxk#ozphLOzn2hp*=oA0y6%n|FwaU~diJ4X*3eoZCI-{2LoL7j?ioLgsY@@KQU+CH zF6-%KnIu1npiqncR0I6(u$|U3?)m^qbOyaC7>y(YEJd}wb&6ROj8Jg`rS1^`>!;Cv z7lONt)T9FE;A%zln?Z;|b zRQYf%+a!~e0~J!AzVlU!J_@y(COSgUiX`56imUztkj|@5i(`i-GP6l&s()Bsa~%1N z(H3A%FGvQ1!PkkZ?SqhKQeTN3y#B^!{h)j-N#&9}C2*0fr?{Ufmo7AxDB2ForxWpL zxWiBKsr03^z`0As1!DiFmykiP+_4Fnq@A9sb)iD8(V=Sw3hv4|-mtg?u+pqeV8)dY zpYw8=J9YyoXU_>xEVIPOx zJss5PLzqB5miCCbR(xEhS5TsF^2dmmzd>it!Sj^@+7wQXQMuDpYXAZmQH!vUAVh-N zr)6t(w(|@cpV|?%068qI6l;pc@zHNZfzmY?O%UUt6gh`Eb}(h66>?>Fupd?&gcw$r zo3c1hlwBD5_=xO&9#;eW;V<-3sL;pzsebx;r`=JdCLVFr;ghYS(uUdOUDxQ?sfLwh zMKEXsm7eMvz4*`aI0U5z)7bba?mH7S&D{^N_aEDXhja7D%zRhlz+g#L>PM)_{jW!x z-s2A|_HN&{etiC7wEySYvMNOoke@!Vvw4lz>-DTZIZevF8M@*0Y~Ue>x-9m}=WM)K zh=(Kc}^rL(K$FJ#Jw zzfInQ)5;C@Rr12EdFt8fyb^I1bS3e}%68T1s#wSwDp;C4^1^)U?J z0|lUHthN0zB5bY8Yj;pacoH!_=59e4W2rFF53#?vat@LWXtbPTk7aJc#?JcKJtL05{Ta1X4m*3 zrwnC_vUf}rN=)rI`D0BvDf^b;Xkvc2pXBy9e^tnTm}Kx++>w(fH!?m$28Ft_*A=iF zH}fqoS}_5q@+X}svXc7c3*Ewe1DuoDsg$k2yz#a@ZD&8)IxCPXBKlriQft3XfoHS$ z%tnXdqOkHAWJ;Alq77)L=WDzd;`SZo_73YB?SG@k8RZ|V6Sr00n>@XC9wris;e8}xkH?wf-T(@moE@;RX|x7i0yX@QTZ=D=ysVd_ zQ+6YIoSJNR$AUZtYV*>#T~4#wGetRenderTargetSize(); + if(currentSize != lastSize) + { + lastSize = currentSize; + TriggerObserver(&lastSize); + } + } +} \ No newline at end of file diff --git a/TSE-RTS/src/BehaviourScripts/CameraSizeChangeNotifyer.hpp b/TSE-RTS/src/BehaviourScripts/CameraSizeChangeNotifyer.hpp new file mode 100644 index 0000000..1a5c4a3 --- /dev/null +++ b/TSE-RTS/src/BehaviourScripts/CameraSizeChangeNotifyer.hpp @@ -0,0 +1,25 @@ +#pragma once + +#define CAMERASIZECHANGENOTIFYER typeid(CameraSizeChangeNotifyer).name() + +#include "elements/BehaviourScript.hpp" +#include "elements/Transformable.hpp" +#include "interfaces/IObservable.hpp" +#include "Types.hpp" +#include "BehaviourScripts/Camera.hpp" +#include "Vector2.hpp" + +class CameraSizeChangeNotifyer : public TSE::BehaviourScript, public TSE::IObservable +{ +private: + +public: + TSE::Camera* camToObserver = nullptr; + TSE::Vector2 lastSize; + + void OnUpdate() override; + inline const char* GetName() override + { + return "Camera Size Change Notifyer"; + } +}; \ No newline at end of file diff --git a/TSE-RTS/src/BehaviourScripts/CanvasScaler.cpp b/TSE-RTS/src/BehaviourScripts/CanvasScaler.cpp new file mode 100644 index 0000000..952efce --- /dev/null +++ b/TSE-RTS/src/BehaviourScripts/CanvasScaler.cpp @@ -0,0 +1,13 @@ +#include "CanvasScaler.hpp" + +void CanvasScaler::OnObserved(void *data) +{ + using namespace TSE; + + Vector2* size = (Vector2*)data; + *mesh = Mesh::GetQuadMesh(); + for(auto& vertex : mesh->vertecies) + { + vertex *= *size * 2; + } +} \ No newline at end of file diff --git a/TSE-RTS/src/BehaviourScripts/CanvasScaler.hpp b/TSE-RTS/src/BehaviourScripts/CanvasScaler.hpp new file mode 100644 index 0000000..d20b966 --- /dev/null +++ b/TSE-RTS/src/BehaviourScripts/CanvasScaler.hpp @@ -0,0 +1,24 @@ +#pragma once + +#define CANVASSCALER typeid(CanvasScaler).name() + +#include "elements/BehaviourScript.hpp" +#include "elements/Transformable.hpp" +#include "Types.hpp" +#include "interfaces/IObserver.hpp" +#include "Mesh.hpp" + +class CanvasScaler : public TSE::BehaviourScript, public TSE::IObserver +{ +private: + +public: + + TSE::Mesh* mesh = nullptr; + + void OnObserved(void* data) override; + inline const char* GetName() override + { + return "Canvas Scaler"; + } +}; \ No newline at end of file diff --git a/TSE-RTS/src/BehaviourScripts/RenderTextureResizes.cpp b/TSE-RTS/src/BehaviourScripts/RenderTextureResizes.cpp new file mode 100644 index 0000000..d839650 --- /dev/null +++ b/TSE-RTS/src/BehaviourScripts/RenderTextureResizes.cpp @@ -0,0 +1,13 @@ +#include "RenderTextureResizes.hpp" + +void RenderTextureResizes::OnObserved(void *data) +{ + using namespace TSE; + + Vector2* size = (Vector2*)data; + if(size->x < 10) + { + return; + } + rt->SetSize(*size); +} \ No newline at end of file diff --git a/TSE-RTS/src/BehaviourScripts/RenderTextureResizes.hpp b/TSE-RTS/src/BehaviourScripts/RenderTextureResizes.hpp new file mode 100644 index 0000000..97fd7c8 --- /dev/null +++ b/TSE-RTS/src/BehaviourScripts/RenderTextureResizes.hpp @@ -0,0 +1,23 @@ +#pragma once + +#define RENDERTEXTURERESIZES typeid(RenderTextureResizes).name() + +#include "elements/BehaviourScript.hpp" +#include "elements/Transformable.hpp" +#include "Types.hpp" +#include "interfaces/IRenderTexture.hpp" +#include "interfaces/IObserver.hpp" + +class RenderTextureResizes : public TSE::BehaviourScript, public TSE::IObserver +{ +private: + +public: + TSE::IRenderTexture* rt = nullptr; + + void OnObserved(void* data) override; + inline const char* GetName() override + { + return "Render Texture Resizes"; + } +}; \ No newline at end of file diff --git a/TSE-RTS/src/game.cpp b/TSE-RTS/src/game.cpp index df401f2..d590caf 100644 --- a/TSE-RTS/src/game.cpp +++ b/TSE-RTS/src/game.cpp @@ -6,11 +6,17 @@ #include "Vector2.hpp" #include #include "PerlinNoise.hpp" +#include "BehaviourScripts/Camera.hpp" +#include "interfaces/IRenderTexture.hpp" +#include "BehaviourScripts/MeshContainer.hpp" +#include "BehaviourScripts/CameraSizeChangeNotifyer.hpp" +#include "BehaviourScripts/RenderTextureResizes.hpp" +#include "BehaviourScripts/CanvasScaler.hpp" #define circleRadius 32 #define circleFallof 25 -void game::setup(TSE::Scene* s) +void game::setup(TSE::Scene* s, TSE::IWindow* wnd) { using namespace TSE; s->AddLayer(&gameLayer); @@ -61,22 +67,81 @@ void game::setup(TSE::Scene* s) { if(noise >= 0.8f) { - maps[3]->SetTile(Vector2(x, y), {0,9}); + maps[3]->SetTile(Vector2(x, y), {0,9}, {2,9}); } else if(noise >= 0.6f) { - maps[2]->SetTile(Vector2(x, y), {0,9}); + maps[2]->SetTile(Vector2(x, y), {0,9}, {2,9}); } else if(noise >= 0.4f) { - maps[1]->SetTile(Vector2(x, y), {0,9}); + maps[1]->SetTile(Vector2(x, y), {0,9}, {2,9}); } else { - maps[0]->SetTile(Vector2(x, y), {0,9}); + maps[0]->SetTile(Vector2(x, y), {0,9}, {2,9}); } } } } + //RenderingLayer + + s->AddLayer(&renderingLayer); + + Transformable* lastPassCamera = new Transformable("lastPassCamera"); + Camera* lpCam = new Camera(); + lpCam->SetRenderTarget(wnd); + lpCam->SetRenderScale(1); + lpCam->layersNotToRender.push_back(gameLayer.GetID()); + lastPassCamera->AddBehaviourScript(lpCam); + CameraSizeChangeNotifyer* camNotifyer = new CameraSizeChangeNotifyer(); + camNotifyer->lastSize = {0,0}; + camNotifyer->camToObserver = lpCam; + lastPassCamera->AddBehaviourScript(camNotifyer); + + Vector2 canvasSize = wnd->GetSize() / 4.0f; + + IRenderTexture* rt = IRenderTexture::factory->CreateTextureHeap(canvasSize, 2); + Transformable* firstPassCamera = new Transformable("firstPassCamera"); + Camera* fpCam = new Camera(); + fpCam->SetRenderScale(256); + fpCam->SetRenderTarget(rt); + fpCam->layersNotToRender.push_back(renderingLayer.GetID()); + firstPassCamera->AddBehaviourScript(fpCam); + RenderTextureResizes* resizer = new RenderTextureResizes(); + resizer->rt = rt; + camNotifyer->Observe(resizer); + firstPassCamera->AddBehaviourScript(resizer); + + //Render pipeline setup + + gameLayer.AddTransformable(firstPassCamera); + renderingLayer.AddTransformable(lastPassCamera); + + //final + + Mesh* canvasMesh = new Mesh(Mesh::GetQuadMesh()); + for(auto& vertex : canvasMesh->vertecies) + { + vertex *= wnd->GetSize(); + } + MeshContainer* canvasContainer = new MeshContainer(canvasMesh); + + Material* canvasMat = new Material("canvasMat", ShaderRegistry::GetShader("LastPassShader")); + canvasMat->SetValue("threshold", 0.01f); + canvasMat->SetValue("darken", 0.45f); + canvasMat->SetValue("colorTextureID", rt->GetTextureId(0)); + canvasMat->SetValue("heightTextureID", rt->GetTextureId(1)); + Renderable* canvasRenderer = new Renderable(canvasMat); + + CanvasScaler* canvasScaler = new CanvasScaler(); + canvasScaler->mesh = canvasMesh; + camNotifyer->Observe(canvasScaler); + + lastPassCamera->AddBehaviourScript(canvasContainer); + lastPassCamera->AddBehaviourScript(canvasRenderer); + lastPassCamera->AddBehaviourScript(canvasScaler); + + //propper resize stuff for prior passes, and canvas, and implement LastPassShader siehe dazu den chat: https://chatgpt.com/c/69985c47-6a50-838b-852d-45bb0b8454e5 } \ No newline at end of file diff --git a/TSE-RTS/src/game.hpp b/TSE-RTS/src/game.hpp index 9eda776..013883f 100644 --- a/TSE-RTS/src/game.hpp +++ b/TSE-RTS/src/game.hpp @@ -1,10 +1,12 @@ #pragma once #include "elements/Scene.hpp" +#include "interfaces/IWindow.hpp" class game { public: inline static TSE::Layer gameLayer = TSE::Layer("gameLayer"); + inline static TSE::Layer renderingLayer = TSE::Layer("renderingLayer"); - static void setup(TSE::Scene* s); + 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 8755779..fb4cfb3 100644 --- a/TSE-RTS/src/main.cpp +++ b/TSE-RTS/src/main.cpp @@ -16,8 +16,9 @@ #include "EditorSubsystem.hpp" #include "game.hpp" #include "shaders/TileMapShader.hpp" +#include "shaders/LastPassShader.hpp" -#define USE_EDITOR +//#define USE_EDITOR using namespace TSE; using namespace TSE::GLFW; @@ -36,21 +37,27 @@ void SetupWindow() wnd = new WindowGlfw(PROJECT_NAME, 800, 600, new OpenGLRenderingBackend(backColor, false, 8, true), WindowType::Maximized); editor = new EditorSubsystem(); #else - wnd = new WindowGlfw(PROJECT_NAME, 800, 600, new OpenGLRenderingBackend(backColor, false, 8, false), WindowType::Maximized); + wnd = new WindowGlfw(PROJECT_NAME, 1920, 1080, new OpenGLRenderingBackend(backColor, false, 8, false), WindowType::Fullscreen); #endif LoadBasicShaders(wnd->GetSize().x, wnd->GetSize().y); TileMapShader::Init(wnd->GetSize().x, wnd->GetSize().y); + LastPassShader::Init(wnd->GetSize().x, wnd->GetSize().y); ShaderRegistry::SetShader("TileMapShader v2", TileMapShader::Instance()); + ShaderRegistry::SetShader("LastPassShader", LastPassShader::Instance()); rend = new DefaultRendererOpenGL(*BasicShader::Instance()); currentScene = new Scene(); + + #ifdef USE_EDITOR + ((Camera*)Transformable::Find(".EditorCamera")->GetBehaviourScript(CAMERA))->layersNotToRender.push_back(game::renderingLayer.GetID()); + currentScene->AddLayer(&editor->editorLayer); + editor->hv.SetScene(currentScene); + #endif - game::setup(currentScene); + + game::setup(currentScene, wnd); -#ifdef USE_EDITOR - currentScene->AddLayer(&editor->editorLayer); - editor->hv.SetScene(currentScene); -#endif + wnd->DoneSetup(); } void CleanUp() diff --git a/TSE-RTS/src/shaders/LastPassShader.cpp b/TSE-RTS/src/shaders/LastPassShader.cpp new file mode 100644 index 0000000..c7f5520 --- /dev/null +++ b/TSE-RTS/src/shaders/LastPassShader.cpp @@ -0,0 +1,109 @@ +#include "LastPassShader.hpp" +#include "BehaviourScripts/Renderable.hpp" +#include "Color.hpp" +#include "interfaces/ITexture.hpp" +#include "LastPassShaderGLSL.hpp" + +using namespace TSE; +using namespace TSE::GLFW; + +#define SHADER_VERTEX_INDEX 0 +#define SHADER_UV_INDEX 1 + +#define SHADER_PACKAGE_SIZE (sizeof(float) * (3 + 2)) + +LastPassShader* LastPassShader::instance = nullptr; + +LastPassShader *LastPassShader::Instance() +{ + return instance; +} + +void LastPassShader::Destroy() +{ + if(instance != nullptr) + delete instance; + instance = nullptr; +} + +void LastPassShader::Init(float width, float height) +{ + std::vector> parts; + parts.push_back(ShaderPart::LoadFromString(vertLastPass, GL_VERTEX_SHADER)); + parts.push_back(ShaderPart::LoadFromString(fragLastPass, GL_FRAGMENT_SHADER)); + instance = new LastPassShader(std::move(parts)); + + instance->Enable(); + instance->SetUniform("colorTexture", 0); + instance->SetUniform("heightTexture", 1); + instance->Disable(); +} + +LastPassShader::LastPassShader(std::vector> &&parts) : Shader(parts) +{ + PackageSize = SHADER_PACKAGE_SIZE; +} + +void LastPassShader::OnEnable() const +{ + glEnableVertexAttribArray(SHADER_VERTEX_INDEX); + glVertexAttribPointer(SHADER_VERTEX_INDEX, 3, GL_FLOAT, false, SHADER_PACKAGE_SIZE, (void*)0); + glEnableVertexAttribArray(SHADER_UV_INDEX); + glVertexAttribPointer(SHADER_UV_INDEX, 2, GL_FLOAT, false, SHADER_PACKAGE_SIZE, (void*)(sizeof(float) * 3)); +} + +void LastPassShader::OnDisable() const +{ + glDisableVertexAttribArray(SHADER_VERTEX_INDEX); + glDisableVertexAttribArray(SHADER_UV_INDEX); +} + +void LastPassShader::OnFlush() +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, ColorTextureID); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, HeightTextureID); + SetUniform("uThreshold", Threshold); + SetUniform("uDarken", Darken); +} + +void LastPassShader::OnDrawCall(int indexCount) +{ + glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, NULL); +} + +void LastPassShader::OnSubmit(const TSE::Transformable &t, float *&target, TSE::TransformationStack &stack, void (*restartDrawcall)(TSE::IRenderer &), TSE::IRenderer &rnd) +{ + auto* r = dynamic_cast(t.GetBehaviourScript(RENDERABLE)); + if (!r) return; + if(!r->GetMaterial()->HasValue("colorTextureID")) return; + if(!r->GetMaterial()->HasValue("heightTextureID")) return; + if(!r->GetMaterial()->HasValue("threshold")) return; + if(!r->GetMaterial()->HasValue("darken")) return; + ColorTextureID = r->GetMaterial()->GetValue("colorTextureID"); + HeightTextureID = r->GetMaterial()->GetValue("heightTextureID"); + Threshold = r->GetMaterial()->GetValue("threshold"); + Darken = r->GetMaterial()->GetValue("darken"); + + const Vector3* verts = r->GetVertices(); + const Vector2* uvs = r->GetUVs(); + ushort vCount = r->GetVertexCount(); + + Matrix4x4 matr = t.GetLocalMatrix(); + + stack.Push(matr); + const Matrix4x4& top = stack.Top(); + + for (ushort i = 0; i < vCount; i++) { + Vector3 p = top * verts[i]; + Vector2 uv = uvs[i]; + *target++ = p.x; + *target++ = p.y; + *target++ = p.z; + *target++ = uv.x; + *target++ = uv.y; + } + + stack.Pop(); +} diff --git a/TSE-RTS/src/shaders/LastPassShader.hpp b/TSE-RTS/src/shaders/LastPassShader.hpp new file mode 100644 index 0000000..2748c5f --- /dev/null +++ b/TSE-RTS/src/shaders/LastPassShader.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "GL/gl3w.h" +#include "GL/gl.h" +#include "shader/Shader.hpp" +#include "Types.hpp" + +class LastPassShader : public TSE::GLFW::Shader +{ +private: + static LastPassShader* instance; + GLuint ColorTextureID; + GLuint HeightTextureID; + float Threshold; + float Darken; + +public: + static LastPassShader* Instance(); + static void Destroy(); + static void Init(float width, float height); + LastPassShader(std::vector>&& parts); + +protected: + void OnEnable() const override; + void OnDisable() const override; + void OnFlush() override; + void OnDrawCall(int indexCount) override; + void OnSubmit(const TSE::Transformable& t, float*& target, TSE::TransformationStack& stack, void (*restartDrawcall)(TSE::IRenderer&), TSE::IRenderer& rnd) override; +}; diff --git a/TSE-RTS/src/shaders/LastPassShaderGLSL.hpp b/TSE-RTS/src/shaders/LastPassShaderGLSL.hpp new file mode 100644 index 0000000..bfb3ff8 --- /dev/null +++ b/TSE-RTS/src/shaders/LastPassShaderGLSL.hpp @@ -0,0 +1,96 @@ +#pragma once + +inline const char* vertLastPass = R"( + #version 330 core + + layout (location = 0) in vec3 position; + layout (location = 1) in vec2 uv; + + uniform mat4 prMatrix; + uniform mat4 camMatrix; + + out DATA + { + vec2 uv_out; + } vs_out; + + + void main() + { + gl_Position = prMatrix * camMatrix * vec4(position.x, position.y, position.z, 1.0); + vs_out.uv_out = uv; + } +)"; + +inline const char* fragLastPass = R"( + #version 330 core + layout (location = 0) out vec4 color; + + uniform sampler2D colorTexture; + uniform sampler2D heightTexture; + + uniform float uThreshold; + uniform float uDarken; + + in DATA + { + vec2 uv_out; + } fs_in; + + float GetChangeInHeight4(ivec2 pos) + { + float center = texelFetch(heightTexture, pos, 0).a; + ivec2 s = textureSize(heightTexture, 0) - ivec2(1); + + float north = texelFetch(heightTexture, clamp(pos + ivec2(0, 1), ivec2(0), s), 0).a; + float south = texelFetch(heightTexture, clamp(pos + ivec2(0, -1), ivec2(0), s), 0).a; + float east = texelFetch(heightTexture, clamp(pos + ivec2(1, 0), ivec2(0), s), 0).a; + float west = texelFetch(heightTexture, clamp(pos + ivec2(-1, 0), ivec2(0), s), 0).a; + + float edge = 0.0; + edge = max(edge, abs(center - north)); + edge = max(edge, abs(center - south)); + edge = max(edge, abs(center - east)); + edge = max(edge, abs(center - west)); + + return edge; + } + + float GetChangeInNormal4(ivec2 pos) + { + float center = texelFetch(heightTexture, pos, 0).g; + ivec2 s = textureSize(heightTexture, 0) - ivec2(1); + + float north = texelFetch(heightTexture, clamp(pos + ivec2(0, 1), ivec2(0), s), 0).g; + float south = texelFetch(heightTexture, clamp(pos + ivec2(0, -1), ivec2(0), s), 0).g; + float east = texelFetch(heightTexture, clamp(pos + ivec2(1, 0), ivec2(0), s), 0).g; + float west = texelFetch(heightTexture, clamp(pos + ivec2(-1, 0), ivec2(0), s), 0).g; + + float edge = 0.0; + edge = max(edge, abs(center - north)); + edge = max(edge, abs(center - south)); + edge = max(edge, abs(center - east)); + edge = max(edge, abs(center - west)); + + return edge; + } + + void main() + { + + ivec2 size = textureSize(heightTexture, 0); + ivec2 p = clamp(ivec2(fs_in.uv_out * vec2(size)), ivec2(0), size - ivec2(1)); + + float changeInNormal = GetChangeInNormal4(p); + float changeInHeight = GetChangeInHeight4(p); + + float maskH = step(uThreshold, changeInHeight); + float maskN = step(uThreshold, changeInNormal); + float mask = max(maskH, maskN); + + vec3 col = texelFetch(colorTexture, p, 0).rgb; + 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 eda4a56..40086f0 100644 --- a/TSE-RTS/src/shaders/TileMapShader.cpp +++ b/TSE-RTS/src/shaders/TileMapShader.cpp @@ -10,8 +10,9 @@ using namespace TSE::GLFW; #define SHADER_MESH_INDEX 0 #define SHADER_POS_INDEX 1 #define SHADER_SPRITE_INDEX 2 +#define SHADER_NORMAL_INDEX 3 -#define SHADER_PACKAGE_SIZE sizeof(float) * (3 + 1) +#define SHADER_PACKAGE_SIZE sizeof(float) * (3 + 1 + 1) TileMapShader* TileMapShader::instance = nullptr; @@ -122,6 +123,11 @@ void TileMapShader::OnEnable() const glEnableVertexAttribArray(SHADER_SPRITE_INDEX); glVertexAttribPointer(SHADER_SPRITE_INDEX, 1, GL_FLOAT, GL_FALSE, PackageSize, (void*)(sizeof(float)*3)); glVertexAttribDivisor(SHADER_SPRITE_INDEX, 1); + + // layout 3: normalindex (float) + glEnableVertexAttribArray(SHADER_NORMAL_INDEX); + glVertexAttribPointer(SHADER_NORMAL_INDEX, 1, GL_FLOAT, GL_FALSE, PackageSize, (void*)(sizeof(float)*4)); + glVertexAttribDivisor(SHADER_NORMAL_INDEX, 1); } void TileMapShader::OnDisable() const @@ -129,12 +135,14 @@ void TileMapShader::OnDisable() const glDisableVertexAttribArray(SHADER_MESH_INDEX); glDisableVertexAttribArray(SHADER_POS_INDEX); glDisableVertexAttribArray(SHADER_SPRITE_INDEX); + glDisableVertexAttribArray(SHADER_NORMAL_INDEX); } void TileMapShader::OnFlush() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, TextureID); + glDisable(GL_BLEND); } void TileMapShader::OnDrawCall(int indexCount) @@ -159,6 +167,11 @@ void TileMapShader::OnDrawCall(int indexCount) } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)prevElementBuffer); +} + +void TileMapShader::OnPostDraw() +{ + glEnable(GL_BLEND); instanceCount = 0; } @@ -177,9 +190,7 @@ void TileMapShader::OnSubmit(const Transformable &t, float *&target, Transformat SpriteCount = tileSet->GetCount(); SpriteScale = tm->SpriteScale; - const int chunkcount = tm->GetChunkCount(); - Vector2 orderedChunks[chunkcount]; - tm->GetChunkPositionsInOrder(orderedChunks); + const std::vector orderedChunks = *tm->GetChunkPositionsInOrder(); Matrix4x4 matr = t.GetLocalMatrix(); @@ -189,10 +200,8 @@ void TileMapShader::OnSubmit(const Transformable &t, float *&target, Transformat { auto chunk = tm->GetChunk(chunkPos); const int spriteCount = chunk->GetSpriteCount(); - Vector2 spritePositions[spriteCount]; - int spriteIds[spriteCount]; - chunk->GetOrderedPositions(spritePositions); - chunk->GetOrderedSpriteIds(spriteIds); + const std::vector spritePositions = *chunk->GetOrderedPositions(); + const std::vector spriteIds = *chunk->GetOrderedSpriteIds(); int chunkSize = chunk->GetChunksize(); for (int i = 0; i < spriteCount; i++) @@ -204,12 +213,13 @@ void TileMapShader::OnSubmit(const Transformable &t, float *&target, Transformat *target++ = pos.x; *target++ = pos.y; *target++ = pos.z; - *target++ = spriteIds[i]; + *target++ = spriteIds[i].x; + *target++ = spriteIds[i].y; ++instanceCount; stack.Pop(); - if(instanceCount >= 20000) + if(instanceCount >= 16000) restartDrawcall(rnd); } } diff --git a/TSE-RTS/src/shaders/TileMapShader.hpp b/TSE-RTS/src/shaders/TileMapShader.hpp index 8722e7a..789589e 100644 --- a/TSE-RTS/src/shaders/TileMapShader.hpp +++ b/TSE-RTS/src/shaders/TileMapShader.hpp @@ -38,5 +38,6 @@ protected: void OnDisable() const override; void OnFlush() override; void OnDrawCall(int indexCount) override; + void OnPostDraw() override; void OnSubmit(const TSE::Transformable& t, float*& target, TSE::TransformationStack& stack, void (*restartDrawcall)(TSE::IRenderer&), TSE::IRenderer& rnd) override; }; diff --git a/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp b/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp index ebb1099..99eea45 100644 --- a/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp +++ b/TSE-RTS/src/shaders/TileMapShaderGLSL.hpp @@ -7,6 +7,7 @@ inline const char* vertTile2 = R"( layout(location = 1) in vec3 iTilePos; layout(location = 2) in float iSpriteId; + layout(location = 3) in float iNormalId; uniform mat4 prMatrix; uniform mat4 camMatrix; @@ -15,6 +16,7 @@ inline const char* vertTile2 = R"( out vec2 vUV; flat out int vSpriteId; + flat out int vNormalId; void main() { @@ -28,6 +30,7 @@ inline const char* vertTile2 = R"( vUV = baseUV; vSpriteId = int(iSpriteId + 0.5); + vNormalId = int(iNormalId + 0.5); } )"; @@ -36,6 +39,7 @@ inline const char* fragTile2 = R"( in vec2 vUV; flat in int vSpriteId; + flat in int vNormalId; uniform sampler2D atlas; uniform vec2 spriteCount; @@ -51,15 +55,26 @@ inline const char* fragTile2 = R"( 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; - FragHeight = vec4(0,0,layerHeight,1); + + 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; + } } )";