made trees possible, but they still have issues with overlapping each other wrongly, i suspect the chunkborders, because it mostly happens in lines

This commit is contained in:
2026-03-01 20:53:06 +01:00
parent 9330a08e28
commit f637f0ec08
13 changed files with 171 additions and 22 deletions

2
TSE

Submodule TSE updated: 769bbd4261...f859288689

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

BIN
TSE-RTS/Resources/trees.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -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<float>("threshold", 0.01f);
canvasMat->SetValue<float>("darken", 0.45f);
canvasMat->SetValue<float>("darken", 0.15f);
canvasMat->SetValue<uint>("colorTextureID", rt->GetTextureId(0));
canvasMat->SetValue<uint>("heightTextureID", rt->GetTextureId(1));
canvasMat->SetValue<uint>("depthTextureID", rt->GetTextureId(2));
canvasMat->SetValue<uint>("colorTexture2ID", rtProps->GetTextureId(0));
canvasMat->SetValue<uint>("heightTexture2ID", rtProps->GetTextureId(1));
canvasMat->SetValue<uint>("depthTexture2ID", rtProps->GetTextureId(2));
Renderable* canvasRenderer = new Renderable(canvasMat);
CanvasScaler* canvasScaler = new CanvasScaler();

View File

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

View File

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

View File

@@ -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<uint>("colorTextureID");
ColorTexture2ID = r->GetMaterial()->GetValue<uint>("colorTexture2ID");
HeightTextureID = r->GetMaterial()->GetValue<uint>("heightTextureID");
HeightTexture2ID = r->GetMaterial()->GetValue<uint>("heightTexture2ID");
DepthTextureID = r->GetMaterial()->GetValue<uint>("depthTextureID");
DepthTexture2ID = r->GetMaterial()->GetValue<uint>("depthTexture2ID");
Threshold = r->GetMaterial()->GetValue<float>("threshold");
Darken = r->GetMaterial()->GetValue<float>("darken");

View File

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

View File

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

View File

@@ -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<TileMap*>(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<Vector2>("spritePivot");
auto tileSet = tm->GetTileSet();
TextureID = tileSet->GetTextueID();
SpriteCount = tileSet->GetCount();
SpriteScale = tm->SpriteScale;
auto nextLine = tm->GetNextLineOffset();
const std::vector<Vector2> 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);

View File

@@ -24,6 +24,8 @@ private:
TSE::Vector2 SpriteCount;
TSE::Vector2 SpriteScale;
float LayerHeight;
int isObjectsLayer;
TSE::Vector2 SpritePivot;
public:
static TileMapShader* Instance();

View File

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