made improvements with MRT, and the render pipeline, and made shure, that the software works in non editor mode too

This commit is contained in:
2026-02-21 13:53:12 +01:00
parent 08ab5c4f02
commit 9330a08e28
17 changed files with 476 additions and 27 deletions

2
TSE

Submodule TSE updated: 45501f153d...769bbd4261

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,17 @@
#include "CameraSizeChangeNotifyer.hpp"
#include "interfaces/IRenderTarget.hpp"
void CameraSizeChangeNotifyer::OnUpdate()
{
using namespace TSE;
if(camToObserver != nullptr)
{
Vector2 currentSize = camToObserver->GetRenderTargetSize();
if(currentSize != lastSize)
{
lastSize = currentSize;
TriggerObserver(&lastSize);
}
}
}

View File

@@ -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";
}
};

View File

@@ -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;
}
}

View File

@@ -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";
}
};

View File

@@ -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);
}

View File

@@ -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";
}
};

View File

@@ -6,11 +6,17 @@
#include "Vector2.hpp"
#include <cmath>
#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<float>("threshold", 0.01f);
canvasMat->SetValue<float>("darken", 0.45f);
canvasMat->SetValue<uint>("colorTextureID", rt->GetTextureId(0));
canvasMat->SetValue<uint>("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
}

View File

@@ -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);
};

View File

@@ -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()

View File

@@ -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<std::unique_ptr<ShaderPart>> 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<std::unique_ptr<TSE::GLFW::ShaderPart>> &&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<Renderable*>(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<uint>("colorTextureID");
HeightTextureID = r->GetMaterial()->GetValue<uint>("heightTextureID");
Threshold = r->GetMaterial()->GetValue<float>("threshold");
Darken = r->GetMaterial()->GetValue<float>("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();
}

View File

@@ -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<std::unique_ptr<TSE::GLFW::ShaderPart>>&& 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;
};

View File

@@ -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);
}
)";

View File

@@ -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<Vector2> 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<Vector2> spritePositions = *chunk->GetOrderedPositions();
const std::vector<Vector2i> 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);
}
}

View File

@@ -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;
};

View File

@@ -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;
}
}
)";