entity system!

This commit is contained in:
Asuro
2025-02-09 19:30:18 +01:00
parent d1270c47a9
commit 90bc5753a9
19 changed files with 306 additions and 67 deletions

View File

@@ -1 +0,0 @@
dependency/

View File

@@ -23,6 +23,9 @@ struct GameData
{ {
void* PermanentStorage = nullptr; void* PermanentStorage = nullptr;
uint64_t PermanentStorageSize = 0; uint64_t PermanentStorageSize = 0;
void* EntityStorage = nullptr;
uint64_t EntityStorageSize = 0;
}; };
struct SharedData struct SharedData

View File

@@ -1,6 +1,7 @@
#include <cstdlib> #include <cstdlib>
#include <cwchar> #include <cwchar>
#include <fileapi.h> #include <fileapi.h>
#include <processthreadsapi.h>
#include <synchapi.h> #include <synchapi.h>
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <Windows.h>
@@ -258,6 +259,10 @@ int main()
HANDLE shaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.ShaderWatcher, 0, &fileWatcherThreadId); HANDLE shaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.ShaderWatcher, 0, &fileWatcherThreadId);
HANDLE compiledShaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.CompiledShaderWatcher, 0, &fileWatcherThreadId); HANDLE compiledShaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.CompiledShaderWatcher, 0, &fileWatcherThreadId);
Shared.Game.PermanentStorageSize = 1024*1024;
Shared.Game.PermanentStorage = VirtualAllocEx(GetCurrentProcess(), NULL, Shared.Game.PermanentStorageSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
Shared.Game.EntityStorageSize = 1024*1024;
Shared.Game.EntityStorage = VirtualAllocEx(GetCurrentProcess(), NULL, Shared.Game.EntityStorageSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
StartupFunc(Shared); StartupFunc(Shared);
bool isRunning = true; bool isRunning = true;

View File

@@ -3,15 +3,52 @@
struct SharedData; struct SharedData;
struct IVec2
{
int32_t X = 0;
int32_t Y = 0;
};
struct IVec3
{
int32_t X = 0;
int32_t Y = 0;
};
struct Vec2
{
float X = 0.0f;
float Y = 0.0f;
};
struct Vec3
{
float X = 0.0f;
float Y = 0.0f;
float Z = 0.0f;
};
struct Quat
{
float X = 0.0f;
float Y = 0.0f;
float Z = 0.0f;
float W = 1.0f;
};
struct Mat4
{
float M[16] {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
};
};
namespace Game namespace Game
{ {
struct GameInstance struct GameInstance;
{
bool IsInitialized = false;
uint64_t Size = sizeof(GameInstance);
uint32_t FrameCounter = 0;
int64_t StartTime = 0;
};
SharedData& GetShared(); SharedData& GetShared();
void SetShared(SharedData& instance); void SetShared(SharedData& instance);

17
src/game/Instance.h Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
#include <cstdint>
#include "Level.h"
namespace Game
{
struct GameInstance
{
bool IsInitialized = false;
uint64_t Size = sizeof(GameInstance);
uint32_t FrameCounter = 0;
int64_t StartTime = 0;
double Now = 0.0;
Level GameLevel;
};
}

57
src/game/Level.cpp Normal file
View File

@@ -0,0 +1,57 @@
#include "Level.h"
#include "Log.h"
#include "Global.h"
#include "Instance.h"
#include <bx/math.h>
#include <bgfx/bgfx.h>
namespace Game
{
void Level::Setup(GameData& data)
{
Log("Level setup");
Cubes.Setup(data.EntityStorage);
if (Cubes.Count == 0)
{
uint64_t state = 0
| BGFX_STATE_WRITE_RGB
| BGFX_STATE_WRITE_A
| BGFX_STATE_WRITE_Z
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CW
| BGFX_STATE_MSAA;
for (uint32_t yy = 0; yy < 11; ++yy)
{
for (uint32_t xx = 0; xx < 11; ++xx)
{
Cube* c = Cubes.New();
if (c)
{
c->TestX = xx;
c->TestY = yy;
}
}
}
}
}
void Level::Update()
{
Cubes.Update();
}
void Cube::Setup()
{
}
void Cube::Update()
{
double time = GetInstance().Now;
bx::mtxRotateXY(Transform.M, time + TestX * 0.1f, time * 2 + TestY * .37f);
Transform.M[12] = -15.0f + float(TestX) * 3.0f;
Transform.M[13] = -15.0f + float(TestY) * 3.0f;
Transform.M[14] = 0.0f;
}
}

91
src/game/Level.h Normal file
View File

@@ -0,0 +1,91 @@
#pragma once
#include "Global.h"
#include "../engine/Shared.h"
#include "Log.h"
#include <bgfx/bgfx.h>
namespace Game
{
typedef uint16_t CubeHandle;
struct Cube
{
int32_t TestX = 0;
int32_t TestY = 0;
Mat4 Transform;
uint16_t MaterialIdx = 0;
uint16_t ModelIdx = 0;
void Setup();
void Update();
};
template<typename T, uint32_t C>
class EntityManager
{
public:
uint16_t Count = 0;
T* Data = nullptr;
uint32_t EntitySize = 0;
public:
uint64_t Setup(void* ptr)
{
if (EntitySize != sizeof(T))
{
Count = 0;
}
EntitySize = sizeof(T);
Data = reinterpret_cast<T*>(ptr);
return C*sizeof(T);
}
T* New()
{
if (Data == nullptr)
{
Log("Accessed EntityManager before setup!");
return nullptr;
}
if (Count >= C)
{
Log("Too many entities!");
return nullptr;
}
Data[Count] = {};
Data[Count].Setup();
T* result = &Data[Count];
++Count;
return result;
}
T* Get(uint16_t idx)
{
if (idx > Count)
{
Log("OOB Access!");
return nullptr;
}
return &Data[idx];
}
void Update()
{
for (uint32_t i = 0; i < Count; ++i)
{
Data[i].Update();
}
}
};
class Level
{
public:
EntityManager<Cube, 1024> Cubes;
public:
void Setup(GameData& data);
void Update();
};
}

View File

@@ -1,7 +1,9 @@
#include "Setup.h" #include "Setup.h"
#include "Log.h" #include "Log.h"
#include "bx/timer.h"
#include "rendering/Rendering.h" #include "rendering/Rendering.h"
#include "Global.h" #include "Global.h"
#include "Instance.h"
namespace Game namespace Game
{ {
@@ -20,7 +22,22 @@ namespace Game
{ {
Log("Game Setup Start!"); Log("Game Setup Start!");
GameInstance& instance = *reinterpret_cast<GameInstance*>(&shared.Game.PermanentStorage); if (shared.Game.PermanentStorage == nullptr)
{
Log("Game memory not initialized!!");
return;
}
if (shared.Game.EntityStorage == nullptr)
{
Log("Entity memory not initialized!");
return;
}
if (shared.Game.PermanentStorageSize < sizeof(GameInstance))
{
Log("Game memory too small! %u < %u", shared.Game.PermanentStorageSize, sizeof(GameInstance));
return;
}
GameInstance& instance = *reinterpret_cast<GameInstance*>(shared.Game.PermanentStorage);
if (sizeof(GameInstance) != instance.Size) if (sizeof(GameInstance) != instance.Size)
{ {
Log("Game instance size changed, resetting!"); Log("Game instance size changed, resetting!");
@@ -29,11 +46,14 @@ namespace Game
SetShared(shared); SetShared(shared);
SetInstance(instance); SetInstance(instance);
SetupInstance.Rendering.Setup(); SetupInstance.Rendering.Setup();
instance.GameLevel.Setup(shared.Game);
instance.IsInitialized = true;
} }
void Update() void Update()
{ {
++GetInstance().FrameCounter; ++GetInstance().FrameCounter;
GetInstance().Now = (bx::getHPCounter() - GetInstance().StartTime) / (double)(bx::getHPFrequency());
SetupInstance.Rendering.Update(); SetupInstance.Rendering.Update();
} }

View File

@@ -2,6 +2,7 @@
#include "../Log.h" #include "../Log.h"
#include "../../engine/Shared.h" #include "../../engine/Shared.h"
#include "../Global.h" #include "../Global.h"
#include "../Instance.h"
#include "bgfx/defines.h" #include "bgfx/defines.h"
#include "bx/timer.h" #include "bx/timer.h"
#include <bx/file.h> #include <bx/file.h>
@@ -18,18 +19,20 @@ namespace Game
float y; float y;
float z; float z;
uint32_t abgr; uint32_t abgr;
float uv_x;
float uv_y;
}; };
static PosColorVertex cubeVertices[] = static PosColorVertex cubeVertices[] =
{ {
{-1.0f, 1.0f, 1.0f, 0xff000000 }, {-1.0f, 1.0f, 1.0f, 0xff000000, 0.0f, 0.0f },
{ 1.0f, 1.0f, 1.0f, 0xff0000ff }, { 1.0f, 1.0f, 1.0f, 0xff0000ff, 0.0f, 0.0f },
{-1.0f, -1.0f, 1.0f, 0xff00ff00 }, {-1.0f, -1.0f, 1.0f, 0xff00ff00, 0.0f, 0.0f },
{ 1.0f, -1.0f, 1.0f, 0xff00ffff }, { 1.0f, -1.0f, 1.0f, 0xff00ffff, 0.0f, 0.0f },
{-1.0f, 1.0f, -1.0f, 0xffff0000 }, {-1.0f, 1.0f, -1.0f, 0xffff0000, 0.0f, 0.0f },
{ 1.0f, 1.0f, -1.0f, 0xffff00ff }, { 1.0f, 1.0f, -1.0f, 0xffff00ff, 0.0f, 0.0f },
{-1.0f, -1.0f, -1.0f, 0xffffff00 }, {-1.0f, -1.0f, -1.0f, 0xffffff00, 0.0f, 0.0f },
{ 1.0f, -1.0f, -1.0f, 0xffffffff }, { 1.0f, -1.0f, -1.0f, 0xffffffff, 0.0f, 0.0f },
}; };
static const uint16_t cubeTriList[] = static const uint16_t cubeTriList[] =
@@ -147,20 +150,28 @@ namespace Game
bgfx::setDebug(BGFX_DEBUG_TEXT); bgfx::setDebug(BGFX_DEBUG_TEXT);
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0); bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0);
VertLayout.begin() Models[0].VertLayout.begin()
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
.end(); .end();
VertexBuffer = bgfx::createVertexBuffer(bgfx::makeRef(cubeVertices, sizeof(cubeVertices)), VertLayout); Models[0].VertexBuffer = bgfx::createVertexBuffer(bgfx::makeRef(cubeVertices, sizeof(cubeVertices)), Models[0].VertLayout);
IndexBuffer = bgfx::createIndexBuffer(bgfx::makeRef(cubeTriList, sizeof(cubeTriList))); Models[0].IndexBuffer = bgfx::createIndexBuffer(bgfx::makeRef(cubeTriList, sizeof(cubeTriList)));
bgfx::ShaderHandle vertexShader = loadShader("vert"); bgfx::ShaderHandle vertexShader = loadShader("vert");
bgfx::ShaderHandle fragmentShader = loadShader("frag"); bgfx::ShaderHandle fragmentShader = loadShader("frag");
Shader = bgfx::createProgram(vertexShader, fragmentShader, true);
Materials[0].Shader = bgfx::createProgram(vertexShader, fragmentShader, true);
Materials[0].State = 0
| BGFX_STATE_WRITE_RGB
| BGFX_STATE_WRITE_A
| BGFX_STATE_WRITE_Z
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CW
| BGFX_STATE_MSAA;
if (!GetInstance().IsInitialized) if (!GetInstance().IsInitialized)
{ {
GetInstance().IsInitialized = true;
GetInstance().StartTime = bx::getHPCounter(); GetInstance().StartTime = bx::getHPCounter();
} }
} }
@@ -169,6 +180,7 @@ namespace Game
{ {
SharedData& shared = GetShared(); SharedData& shared = GetShared();
// Reload shaders if necessary
FileChangeNotification* shaderChange = nullptr; FileChangeNotification* shaderChange = nullptr;
if (shared.Dev.ChangedShaderCount > 0) if (shared.Dev.ChangedShaderCount > 0)
{ {
@@ -183,7 +195,7 @@ namespace Game
bgfx::ProgramHandle newProgram = bgfx::createProgram(vertexShader, fragmentShader, true); bgfx::ProgramHandle newProgram = bgfx::createProgram(vertexShader, fragmentShader, true);
if (isValid(newProgram)) if (isValid(newProgram))
{ {
Shader = newProgram; Materials[0].Shader = newProgram;
} }
else else
{ {
@@ -192,8 +204,7 @@ namespace Game
} }
} }
int64_t tickDelta = bx::getHPCounter() - GetInstance().StartTime; GetInstance().GameLevel.Update();
double time = tickDelta / double(bx::getHPFrequency());
const bx::Vec3 at = { 0.0f, 0.0f, 0.0f }; const bx::Vec3 at = { 0.0f, 0.0f, 0.0f };
const bx::Vec3 eye = { 0.0f, 0.0f, -35.0f }; const bx::Vec3 eye = { 0.0f, 0.0f, -35.0f };
@@ -215,43 +226,25 @@ namespace Game
// if no other draw calls are submitted to view 0. // if no other draw calls are submitted to view 0.
bgfx::touch(0); bgfx::touch(0);
bgfx::IndexBufferHandle ibh = IndexBuffer; for (int32_t i = 0; i < GetInstance().GameLevel.Cubes.Count; ++i)
uint64_t state = 0
| BGFX_STATE_WRITE_RGB
| BGFX_STATE_WRITE_A
| BGFX_STATE_WRITE_Z
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CW
| BGFX_STATE_MSAA
;
// Submit 11x11 cubes.
for (uint32_t yy = 0; yy < 11; ++yy)
{ {
for (uint32_t xx = 0; xx < 11; ++xx) Cube* c = GetInstance().GameLevel.Cubes.Get(i);
if (c)
{ {
float mtx[16]; bgfx::setTransform(c->Transform.M);
bx::mtxRotateXY(mtx, time + xx * 0.21f, time + yy * 0.37f);
mtx[12] = -15.0f + float(xx) * 3.0f;
mtx[13] = -15.0f + float(yy) * 3.0f;
mtx[14] = 0.0f;
// Set model matrix for rendering. Model& currentModel = Models[c->ModelIdx];
bgfx::setTransform(mtx); Material& currentMaterial = Materials[c->MaterialIdx];
bgfx::setVertexBuffer(0, currentModel.VertexBuffer);
// Set vertex and index buffer. bgfx::setIndexBuffer(currentModel.IndexBuffer);
bgfx::setVertexBuffer(0, VertexBuffer); bgfx::setState(currentMaterial.State);
bgfx::setIndexBuffer(ibh);
// Set render states.
bgfx::setState(state);
// Submit primitive for rendering to view 0. // Submit primitive for rendering to view 0.
bgfx::submit(0, Shader); bgfx::submit(0, currentMaterial.Shader);
} }
} }
bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1f", time); bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1f", GetInstance().Now);
bgfx::dbgTextPrintf(1, 2, 0x0f, "Frame: %u", GetInstance().FrameCounter); bgfx::dbgTextPrintf(1, 2, 0x0f, "Frame: %u", GetInstance().FrameCounter);
bgfx::frame(); bgfx::frame();

View File

@@ -77,19 +77,25 @@ namespace Game
} }
}; };
struct RenderState struct Model
{ {
bgfx::VertexBufferHandle VertexBuffer;
bgfx::IndexBufferHandle IndexBuffer;
bgfx::VertexLayout VertLayout;
};
struct Material
{
bgfx::ProgramHandle Shader;
uint64_t State = 0;
}; };
class GameRendering class GameRendering
{ {
private: private:
bgfx::VertexLayout VertLayout; Material Materials[8];
bgfx::VertexBufferHandle VertexBuffer; Model Models[8];
bgfx::IndexBufferHandle IndexBuffer;
bgfx::ProgramHandle Shader;
BgfxCallback Callback; BgfxCallback Callback;
RenderState State;
public: public:
void Setup(); void Setup();
void Update(); void Update();

View File

@@ -1,8 +1,16 @@
$input v_color0 $input v_color0
$input v_uv0
#include "common.sh" #include "common.sh"
float circle(vec2 uv, vec2 center, float size)
{
vec2 relPos = uv - center;
vec2 distSq = relPos.x * relPos.x + relPos.y * relPos.y;
return sqrt(distSq) <= size ? 1.0 : 0.0;
}
void main() void main()
{ {
gl_FragColor = v_color0; gl_FragColor = circle(v_uv0, vec2(0.5, 0.5), 0.5);
} }

View File

@@ -1,4 +1,6 @@
vec4 v_color0 : COLOR0 = vec4(1.0, 1.0, 0.0, 1.0); vec4 v_color0 : COLOR0 = vec4(1.0, 1.0, 0.0, 1.0);
vec2 v_uv0 : TEXCOORD0 = vec2(0.0, 0.0);
vec3 a_position : POSITION; vec3 a_position : POSITION;
vec4 a_color0 : COLOR0; vec4 a_color0 : COLOR0;
vec2 a_texcoord0 : TEXCOORD0;

View File

@@ -1,5 +1,5 @@
$input a_position, a_color0 $input a_position, a_color0, a_texcoord0
$output v_color0 $output v_color0, v_uv0
#include "common.sh" #include "common.sh"
@@ -7,4 +7,5 @@ void main()
{ {
gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0)); gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0));
v_color0 = a_color0; v_color0 = a_color0;
v_uv0 = a_texcoord0;
} }