diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 883631e..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "cmake.debugConfig": { - "args": ["D:/PROJECTS/EtrediaEmpires/sdk/map/provinces.bmp", "D:/PROJECTS/EtrediaEmpires/sdk/map/provinces.map"] - } -} \ No newline at end of file diff --git a/assets/map/provinces.map b/assets/map/provinces.map deleted file mode 100644 index e69de29..0000000 diff --git a/sdk/map/provinces.map b/assets/map/states.map similarity index 100% rename from sdk/map/provinces.map rename to assets/map/states.map diff --git a/assets/materials/helloworld.mat b/assets/materials/helloworld.mat deleted file mode 100644 index b258151..0000000 Binary files a/assets/materials/helloworld.mat and /dev/null differ diff --git a/assets/materials/provinces.mat b/assets/materials/provinces.mat new file mode 100644 index 0000000..aefbe17 --- /dev/null +++ b/assets/materials/provinces.mat @@ -0,0 +1 @@ +Vp¸x /} \ No newline at end of file diff --git a/assets/materials/provinces.mat.bak b/assets/materials/provinces.mat.bak new file mode 100644 index 0000000..ef58fa3 --- /dev/null +++ b/assets/materials/provinces.mat.bak @@ -0,0 +1 @@ +æÛPDÞÿÀ² \ No newline at end of file diff --git a/assets/shaders/provinces.frag b/assets/shaders/provinces.frag new file mode 100644 index 0000000..793a185 --- /dev/null +++ b/assets/shaders/provinces.frag @@ -0,0 +1,7 @@ +layout(location = 0) in vec3 fragColor; + +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(fragColor, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/provinces.vert b/assets/shaders/provinces.vert new file mode 100644 index 0000000..1ef7082 --- /dev/null +++ b/assets/shaders/provinces.vert @@ -0,0 +1,28 @@ +struct Province { + uint stateId; + uint color; +}; +layout(std430, binding=0) buffer Data { + Province provinces[]; +}; + + +layout(location = 0) in vec2 position; +layout(location = 1) uniform mat4 camera; +layout(location = 2) uniform mat4 transform; +layout(location = 3) uniform uint provinceIndex; + +layout(location = 0) out vec3 fragColor; + +vec3 unpackColor(uint c) { + return vec3( + c & 0xFFu, + (c >> 8) & 0xFFu, + (c >> 16) & 0xFFu + ) / 255.0; +} + +void main() { + gl_Position = camera * vec4(position, 0.0, 1.0); + fragColor = unpackColor(provinces[provinceIndex].color); +} \ No newline at end of file diff --git a/engine-api/CMakeLists.txt b/engine-api/CMakeLists.txt index 9da7821..853ba5e 100644 --- a/engine-api/CMakeLists.txt +++ b/engine-api/CMakeLists.txt @@ -25,7 +25,12 @@ find_package(glfw3 CONFIG REQUIRED) add_library(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} PRIVATE p7) target_link_libraries(${PROJECT_NAME} PUBLIC utils) target_link_libraries(${PROJECT_NAME} PRIVATE glfw) -target_include_directories(${PROJECT_NAME} PUBLIC include/) \ No newline at end of file +target_include_directories(${PROJECT_NAME} PUBLIC include/) + +if (CMAKE_VERSION VERSION_GREATER 3.12) + set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) +endif() \ No newline at end of file diff --git a/engine/include/AssetData.hpp b/engine-api/include/ee_engine_api/AssetData.hpp similarity index 51% rename from engine/include/AssetData.hpp rename to engine-api/include/ee_engine_api/AssetData.hpp index 4f8100a..46c9198 100644 --- a/engine/include/AssetData.hpp +++ b/engine-api/include/ee_engine_api/AssetData.hpp @@ -1,4 +1,5 @@ #pragma once +#include "Map.hpp" #include #include @@ -14,25 +15,17 @@ struct AssetBinary : AssetData ~AssetBinary(); }; -struct AssetVulkanShader : AssetData +struct AssetMapMesh : AssetData { - uint32_t* content = nullptr; - size_t size = 0; + MapMesh content; - AssetVulkanShader(uint8_t* &source, const size_t &sourceSize); - ~AssetVulkanShader(); + AssetMapMesh(uint8_t* &source, const size_t &sourceSize); }; -struct AssetVulkanMaterial : AssetData +#define AssetShader AssetBinary + +struct AssetMaterial : AssetData { uint32_t vertexShaderAssetID; uint32_t fragmentShaderAssetID; - uint32_t renderType; - uint32_t renderStage; - - // Vertex shader params - // - - // Fragment shader params - // }; \ No newline at end of file diff --git a/engine-api/include/ee_engine_api/Map.hpp b/engine-api/include/ee_engine_api/Map.hpp new file mode 100644 index 0000000..786d7cb --- /dev/null +++ b/engine-api/include/ee_engine_api/Map.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include + +struct MapMesh +{ + struct Province + { + std::vector vertices; + std::vector indices; + }; + std::unordered_map> states; +}; + +struct ProvinceSSBO +{ + uint32_t stateId; + uint32_t color; +}; \ No newline at end of file diff --git a/engine-api/include/ee_engine_api/RenderInterface.hpp b/engine-api/include/ee_engine_api/RenderInterface.hpp index d6f7327..4a1819f 100644 --- a/engine-api/include/ee_engine_api/RenderInterface.hpp +++ b/engine-api/include/ee_engine_api/RenderInterface.hpp @@ -1,22 +1,61 @@ #pragma once #include +#include "Map.hpp" +#include "AssetData.hpp" + +struct ShaderRefs +{ + AssetShader *vertProvinces; + AssetShader *fragProvinces; +}; + +struct CameraTransform +{ + glm::vec2 position {0.0f, 0.0f}; + float zoom = 1.0f; +}; + +struct MeshTransform +{ + glm::vec2 position {0.0f, 0.0f}; + glm::vec2 scale {1.0f, 1.0f}; + float rotation; +}; class IRenderer { public: virtual ~IRenderer(); + void RegisterMaterials(const ShaderRefs &shaders); + void RegisterMapMesh(MapMesh *mapMesh); + + virtual void Init() = 0; + virtual void Shutdown() = 0; void Draw(); + virtual void ResizeWindow(int width, int height); + void SetCamera(const CameraTransform &camera); + void SetMapTransform(const MeshTransform &mapTransform); protected: int screenWidth, screenHeight; + float screenAspect; + CameraTransform camera; + MeshTransform mapTransform; + glm::mat4 mapModel; + glm::mat4 viewProjection; GLFWwindow *window; + MapMesh *mapMesh; + ShaderRefs shaders; explicit IRenderer(GLFWwindow *window); virtual void Clear() = 0; virtual void DrawMap() = 0; virtual void DrawUI() = 0; + + virtual void ApplyCamera() = 0; + virtual void ApplyMapTransform() = 0; }; \ No newline at end of file diff --git a/engine-api/src/AssetData.cpp b/engine-api/src/AssetData.cpp new file mode 100644 index 0000000..f0646e5 --- /dev/null +++ b/engine-api/src/AssetData.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +/* + +YOU CAN PREVENT SOURCE BUFFER FROM CLOSING. +IT CAN BE USED FOR STORING ASSET DATA WITHOUT COPY. +IN THIS CASE, YOU MUST SET SOURCE TO NULLPTR AND FREE BUFFER YOURSELF. + +*/ + +AssetBinary::AssetBinary(uint8_t* &source, const size_t &sourceSize) +{ + content = source; + size = sourceSize; + source = nullptr; +} + +AssetBinary::~AssetBinary() +{ + if (content != nullptr) + DeallocateArray(content); +} + + + +AssetMapMesh::AssetMapMesh(uint8_t* &source, const size_t &sourceSize) +{ + uint8_t* buffer = source; + uint8_t* pointer = source; + size_t leftoverSize = sourceSize; + source = nullptr; + + uint32_t statesCount = 0; + readNext(&statesCount, pointer, leftoverSize, sizeof(uint32_t)); + + for (uint32_t state = 0; state < statesCount; state++) + { + uint32_t id = 0; + glm::u8vec3 color {}; + if (!readNext(&color, pointer, leftoverSize, sizeof(glm::u8vec3))) + break; + id = static_cast(color.r) << 16 | + static_cast(color.g) << 8 | + static_cast(color.b); + + uint32_t provincesCount = 0; + readNext(&provincesCount, pointer, leftoverSize, sizeof(uint32_t)); + + for (uint32_t pi = 0; pi < provincesCount; pi++) + { + MapMesh::Province prov; + + uint32_t verticesCount = 0; + if (!readNext(&verticesCount, pointer, leftoverSize, sizeof(uint32_t))) + break; + + prov.vertices.reserve(verticesCount); + for (uint32_t vi = 0; vi < verticesCount; vi++) + { + glm::vec2 vertex; + if (!readNext(&vertex, pointer, leftoverSize, sizeof(glm::vec2))) + break; + + prov.vertices.push_back(vertex); + } + + uint32_t indicesCount = 0; + if (!readNext(&indicesCount, pointer, leftoverSize, sizeof(uint32_t))) + break; + + prov.indices.reserve(indicesCount); + for(uint32_t ii = 0; ii < indicesCount; ii++) + { + uint16_t index = 0; + if (!readNext(&index, pointer, leftoverSize, sizeof(uint16_t))) + break; + + prov.indices.push_back(index); + } + + content.states[id].push_back(prov); + } + } + + DeallocateArray(buffer); +} \ No newline at end of file diff --git a/engine-api/src/RenderInterface.cpp b/engine-api/src/RenderInterface.cpp index acfdf35..2b3dab2 100644 --- a/engine-api/src/RenderInterface.cpp +++ b/engine-api/src/RenderInterface.cpp @@ -1,10 +1,13 @@ #include #include +#include +#include "Logger.h" IRenderer::IRenderer(GLFWwindow *window) { this->window = window; glfwGetFramebufferSize(window, &screenWidth, &screenHeight); + screenAspect = static_cast(screenWidth) / static_cast(screenHeight); } IRenderer::~IRenderer() @@ -12,6 +15,16 @@ IRenderer::~IRenderer() } +void IRenderer::RegisterMaterials(const ShaderRefs &shaders) +{ + this->shaders = shaders; +} + +void IRenderer::RegisterMapMesh(MapMesh* mapMesh) +{ + this->mapMesh = mapMesh; +} + void IRenderer::Draw() { Clear(); @@ -23,4 +36,45 @@ void IRenderer::ResizeWindow(int width, int height) { screenWidth = width; screenHeight = height; + screenAspect = static_cast(screenWidth) / static_cast(screenHeight); +} + +void IRenderer::SetCamera(const CameraTransform &camera) +{ + if (camera.zoom <= 0) + { + LOG(WARNING, "Camera zoom cannot be zero or less!"); + return; + } + + this->camera = camera; + + float halfHeight = camera.zoom; + float halfWidth = camera.zoom * screenAspect; + + glm::mat4 P = glm::ortho( + -halfWidth, +halfWidth, + -halfHeight, +halfHeight + ); + + glm::mat4 V = glm::translate( + glm::mat4(1.0f), + glm::vec3(-camera.position, 0.0f) + ); + + viewProjection = P * V; + + ApplyCamera(); +} + +void IRenderer::SetMapTransform(const MeshTransform &mapTransform) +{ + this->mapTransform = mapTransform; + + glm::mat4 M(1.0f); + M = glm::translate(M, glm::vec3(mapTransform.position, 0.0f)); + M = glm::rotate(M, mapTransform.rotation, glm::vec3(0.0f, 0.0f, 1.0f)); + M = glm::scale(M, glm::vec3(mapTransform.scale, 1.0f)); + + ApplyMapTransform(); } \ No newline at end of file diff --git a/engine/include/AssetManager.hpp b/engine/include/AssetManager.hpp index 026b2c1..6390cd4 100644 --- a/engine/include/AssetManager.hpp +++ b/engine/include/AssetManager.hpp @@ -1,6 +1,6 @@ #pragma once #include "FileSystem.hpp" -#include "AssetData.hpp" +#include #include #include @@ -30,8 +30,10 @@ public: { BINARY, - VULKAN_SHADER, - VULKAN_MATERIAL, + MAP_MESH, + + SHADER, + MATERIAL, IMAGE } type = BINARY; @@ -85,11 +87,13 @@ public: void Start(); void Shutdown(); - void LoadShaders(); + void LoadDir(AssetInfo::Type type, const std::filesystem::path &path); void LoadAsync(AssetInfo::Type type, const std::filesystem::path &path); AssetHandle& Find(const std::filesystem::path &path); AssetHandle& Find(const uint32_t &id); + template T& FindOnce(const std::filesystem::path &path); + template T& FindOnce(const uint32_t &id); void Redirect(AssetHandle &handle, void *resource); template T& Get(const AssetHandle &handle); void Free(AssetHandle &handle); @@ -108,8 +112,9 @@ private: std::vector loadingEntries; std::vector binaryStorage; - std::vector shadersStorage; - std::vector materialsStorage; + std::vector mapMeshesStorage; + std::vector shadersStorage; + std::vector materialsStorage; void Threading(); void Request(const AssetStreamCommand &command); @@ -117,6 +122,8 @@ private: void Loop(); void ProcessCommand(AssetStreamCommand &command); void Release(); + + template void ClearStorage(std::vector &storage); }; template T& AssetManager::Get(const AssetHandle &handle) @@ -130,4 +137,24 @@ template T& AssetManager::Get(const AssetHandle &handle) Request(command); while (command.out->load() == nullptr); return *reinterpret_cast(command.out->load()); +} + +template T& AssetManager::FindOnce(const std::filesystem::path &path) +{ + return Get(Find(path)); +} + +template T& AssetManager::FindOnce(const uint32_t &id) +{ + return Get(Find(id)); +} + +template void AssetManager::ClearStorage(std::vector &storage) +{ + for (T* &resource : storage) + { + if (resource != nullptr) + Deallocate(resource); + } + storage.clear(); } \ No newline at end of file diff --git a/engine/include/Engine.hpp b/engine/include/Engine.hpp index b056976..48a0da3 100644 --- a/engine/include/Engine.hpp +++ b/engine/include/Engine.hpp @@ -10,6 +10,8 @@ public: static AssetManager *assetManager; static IRenderer *renderer; + static void Shutdown(); + private: Engine(); }; diff --git a/engine/src/AssetData.cpp b/engine/src/AssetData.cpp deleted file mode 100644 index cdfdbdd..0000000 --- a/engine/src/AssetData.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "AssetData.hpp" -#include - -AssetBinary::AssetBinary(uint8_t* &source, const size_t &sourceSize) -{ - content = source; - size = sourceSize; - source = nullptr; -} - -AssetBinary::~AssetBinary() -{ - if (content != nullptr) - DeallocateArray(content); -} - -AssetVulkanShader::AssetVulkanShader(uint8_t* &source, const size_t &sourceSize) -{ - content = reinterpret_cast(source); - size = sourceSize; - source = nullptr; -} - -AssetVulkanShader::~AssetVulkanShader() -{ - if (content != nullptr) - DeallocateArray(content); -} diff --git a/engine/src/AssetManager.cpp b/engine/src/AssetManager.cpp index 522f38c..788fe40 100644 --- a/engine/src/AssetManager.cpp +++ b/engine/src/AssetManager.cpp @@ -50,7 +50,8 @@ void AssetManager::Redirect(AssetHandle &handle, void* resource) { void* oldResource = asset.resourceAddress->resource.exchange(nullptr, std::memory_order_acq_rel); if (oldResource) - Deallocate(asset.resourceAddress->resource.load()); + //Deallocate(asset.resourceAddress->resource.load()); + Deallocate(oldResource); } asset.resourceAddress->resource.store(resource); @@ -174,20 +175,29 @@ void AssetManager::Loop() switch (asset.type) { - case AssetInfo::VULKAN_SHADER: + case AssetInfo::MAP_MESH: { - AssetVulkanShader* shader = Allocate(entry.file->data, entry.file->size); + AssetMapMesh* mesh = Allocate(entry.file->data, entry.file->size); + mapMeshesStorage.push_back(mesh); + Redirect(entry.handle, mapMeshesStorage.back()); + break; + } + + + case AssetInfo::SHADER: + { + AssetShader* shader = Allocate(entry.file->data, entry.file->size); shadersStorage.push_back(shader); Redirect(entry.handle, shadersStorage.back()); break; } - case AssetInfo::VULKAN_MATERIAL: + case AssetInfo::MATERIAL: { - AssetVulkanMaterial* material = Allocate(); - if (entry.file->size < sizeof(AssetVulkanMaterial)) + AssetMaterial* material = Allocate(); + if (entry.file->size < sizeof(AssetMaterial)) LOG(CRITICAL, "File size is less than needed for material"); - std::memcpy(material, entry.file->data, sizeof(AssetVulkanMaterial)); + std::memcpy(material, entry.file->data, sizeof(AssetMaterial)); materialsStorage.push_back(material); Redirect(entry.handle, materialsStorage.back()); break; @@ -246,6 +256,7 @@ void AssetManager::ProcessCommand(AssetStreamCommand &command) if (freeAssetSlots.size() > 0) { assetPos = freeAssetSlots.back(); + Deallocate(activeAssets[assetPos].resourceAddress); activeAssets[assetPos] = std::move(asset); freeAssetSlots.pop_back(); } @@ -321,9 +332,9 @@ void AssetManager::Release() { if (asset.resourceAddress->resource.load() != nullptr) { - void* oldResource = asset.resourceAddress->resource.exchange(nullptr, std::memory_order_acq_rel); - if (oldResource) - Deallocate(asset.resourceAddress->resource.load()); + void* resource = asset.resourceAddress->resource.exchange(nullptr, std::memory_order_acq_rel); + if (resource) + Deallocate(resource); } Deallocate(asset.resourceAddress); } @@ -333,30 +344,20 @@ void AssetManager::Release() Deallocate(mapping.second); assetsMapping.clear(); - //TODO: ClrearStorage(&storage); - for (AssetBinary* &resource : binaryStorage) - { - if (resource != nullptr) - Deallocate(resource); - } binaryStorage.clear(); - for (AssetVulkanShader* &resource : shadersStorage) - { - if (resource != nullptr) - Deallocate(resource); - } + mapMeshesStorage.clear(); shadersStorage.clear(); + materialsStorage.clear(); LOG(INFO, "Asset Streaming is released"); isRunning.store(false); } -void AssetManager::LoadShaders() +void AssetManager::LoadDir(AssetInfo::Type type, const std::filesystem::path &path) { - std::filesystem::path shadersRoot = "assets/shaders"; - for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(shadersRoot)) + for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(path)) { if (entry.is_directory()) continue; - LoadAsync(AssetInfo::VULKAN_SHADER, entry.path()); + LoadAsync(type, entry.path()); } } \ No newline at end of file diff --git a/engine/src/Engine.cpp b/engine/src/Engine.cpp index f9d487c..e76487d 100644 --- a/engine/src/Engine.cpp +++ b/engine/src/Engine.cpp @@ -1,4 +1,25 @@ #include "Engine.hpp" +#include AssetManager* Engine::assetManager; -IRenderer* Engine::renderer; \ No newline at end of file +IRenderer* Engine::renderer; + +void Engine::Shutdown() +{ + if (renderer != nullptr) + { + renderer->Shutdown(); + Deallocate(renderer); + } + renderer = nullptr; + + if (Engine::assetManager != nullptr) + { // Wait for asset manager to clean and shutdown + Engine::assetManager->Shutdown(); + while(Engine::assetManager->isRunning.load()); + } + + if (assetManager != nullptr) + Deallocate(assetManager); + assetManager = nullptr; +} \ No newline at end of file diff --git a/engine/src/FileSystem.cpp b/engine/src/FileSystem.cpp index 4b54ca2..06b6fb2 100644 --- a/engine/src/FileSystem.cpp +++ b/engine/src/FileSystem.cpp @@ -122,6 +122,9 @@ bool NativeFileSystem::PollReady(FileHandle &file) void NativeFileSystem::Close(FileHandle &file) { + if (file.overlapped.hEvent) + CloseHandle(file.overlapped.hEvent); + if (file.buffer != nullptr) { DeallocateArray(file.buffer); diff --git a/engine/src/main.cpp b/engine/src/main.cpp index 87b1ccb..6e43d76 100644 --- a/engine/src/main.cpp +++ b/engine/src/main.cpp @@ -34,20 +34,33 @@ int main(int argc, char **argv) glfwMakeContextCurrent(window); - // Setup assets - AssetManager assetManager; - assetManager.Start(); - //assetManager.LoadShaders(); + // Setup Asset Manager + Engine::assetManager = Allocate(); + Engine::assetManager->Start(); + Engine::assetManager->LoadDir(AssetInfo::SHADER, "assets/shaders"); + Engine::assetManager->LoadDir(AssetInfo::MATERIAL, "assets/materials"); - // Setup Renderer - // assetManager.LoadAsync(AssetInfo::MATERIAL, "assets/materials/helloworld.mat"); - // AssetHandle baseMaterialHandle = assetManager.Find("assets/materials/helloworld.mat"); - // AssetMaterial baseMaterial = assetManager.Get(baseMaterialHandle); + // Load assets + Engine::assetManager->LoadAsync(AssetInfo::MAP_MESH, "assets/map/states.map"); - //Setup Engine - Engine::assetManager = &assetManager; + // Setup renderer TODO: builder Engine::renderer = reinterpret_cast(Allocate(window)); + AssetMapMesh &states = Engine::assetManager->FindOnce("assets/map/states.map"); + Engine::renderer->RegisterMapMesh(&states.content); + + //TODO: ShaderRefs builder from set of AssetMaterial + AssetMaterial &provincesMaterial = Engine::assetManager->FindOnce("assets/materials/provinces.mat"); + AssetShader &vertProv = Engine::assetManager->FindOnce(provincesMaterial.vertexShaderAssetID); + AssetShader &fragProv = Engine::assetManager->FindOnce(provincesMaterial.fragmentShaderAssetID); + Engine::renderer->RegisterMaterials({ + .vertProvinces = &vertProv, + .fragProvinces = &fragProv + }); + + Engine::renderer->Init(); + Engine::renderer->SetCamera({.zoom = 100.0f}); + glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) { Engine::renderer->ResizeWindow(width, height); }); @@ -63,11 +76,7 @@ int main(int argc, char **argv) // Free memory LOG(INFO, "Exit..."); - if (Engine::assetManager != nullptr) - { // Wait for asset manager to clean and shutdown - Engine::assetManager->Shutdown(); - while(Engine::assetManager->isRunning.load()); - } + Engine::Shutdown(); glfwDestroyWindow(window); glfwTerminate(); //TODO: check Unregister in other threads and make threaded module base class diff --git a/renderers/magnum-renderer/include/ee_magnum/Materials.hpp b/renderers/magnum-renderer/include/ee_magnum/Materials.hpp new file mode 100644 index 0000000..95c37a3 --- /dev/null +++ b/renderers/magnum-renderer/include/ee_magnum/Materials.hpp @@ -0,0 +1,35 @@ +#pragma once + +#undef min +#undef max + +#include +#include +#include +#include +#include + +#define PROVINCES_SSBO_BINDING 0 +#define CAMERA_UNIFORM 1 +//TODO: push constant +#define TRANSFORM_UNIFORM 2 +#define PROVINCES_ID_UNIFORM 3 + +using namespace Magnum; + +class BaseMaterial : public GL::AbstractShaderProgram +{ +public: + void setModelViewProjection(const Matrix4 &m, const Matrix4 &vp); + +protected: + explicit BaseMaterial(const std::string &vertSrc, const std::string &fragSrc); +}; + +class ProvinceMaterial : public BaseMaterial +{ +public: + explicit ProvinceMaterial(const std::string &vertSrc, const std::string &fragSrc); + + void setId(const uint32_t &id); +}; \ No newline at end of file diff --git a/renderers/magnum-renderer/include/ee_magnum/Renderer.hpp b/renderers/magnum-renderer/include/ee_magnum/Renderer.hpp index d0d5491..7597b3a 100644 --- a/renderers/magnum-renderer/include/ee_magnum/Renderer.hpp +++ b/renderers/magnum-renderer/include/ee_magnum/Renderer.hpp @@ -4,8 +4,11 @@ #undef max #include +#include +#include #include +#include "Materials.hpp" #include using namespace Magnum; @@ -15,12 +18,28 @@ class MagnumRenderer : public IRenderer public: MagnumRenderer(GLFWwindow *window); ~MagnumRenderer(); + + void Init() override; + void Shutdown() override; protected: void Clear() override; void DrawMap() override; void DrawUI() override; + void ApplyCamera() override; + void ApplyMapTransform() override; + private: Platform::GLContext context; + + std::vector provinceMeshes; + GL::Buffer provinceSSBO; + ProvinceMaterial *provinceMaterial; + + void ValidateSupport(); + void LoadShaders(); + void LoadProvinces(); + + void ApplyMapMVP(); }; \ No newline at end of file diff --git a/renderers/magnum-renderer/src/Materials.cpp b/renderers/magnum-renderer/src/Materials.cpp new file mode 100644 index 0000000..d5b50b3 --- /dev/null +++ b/renderers/magnum-renderer/src/Materials.cpp @@ -0,0 +1,37 @@ +#include +#include "Logger.h" + +BaseMaterial::BaseMaterial(const std::string &vertSrc, const std::string &fragSrc) +{ + GL::Shader vert {GL::Version::GL430, GL::Shader::Type::Vertex}; + GL::Shader frag {GL::Version::GL430, GL::Shader::Type::Fragment}; + + vert.addSource(vertSrc); + frag.addSource(fragSrc); + + if (!vert.compile()) + LOG(CRITICAL, "Failed to compile vertex shader"); + if (!frag.compile()) + LOG(CRITICAL, "Failed to compile fragment shader"); + + attachShader(vert); + attachShader(frag); + + link(); +} + +void BaseMaterial::setModelViewProjection(const Matrix4 &m, const Matrix4 &vp) +{ + setUniform(TRANSFORM_UNIFORM, m); + setUniform(CAMERA_UNIFORM, vp); +} + +ProvinceMaterial::ProvinceMaterial(const std::string &vertSrc, const std::string &fragSrc): BaseMaterial(vertSrc, fragSrc) +{ + +} + +void ProvinceMaterial::setId(const uint32_t &id) +{ + setUniform(PROVINCES_ID_UNIFORM, id); +} \ No newline at end of file diff --git a/renderers/magnum-renderer/src/Renderer.cpp b/renderers/magnum-renderer/src/Renderer.cpp index 24e0f81..61c8f1d 100644 --- a/renderers/magnum-renderer/src/Renderer.cpp +++ b/renderers/magnum-renderer/src/Renderer.cpp @@ -1,4 +1,5 @@ #include "Logger.h" +#include "ee_utils/allocator.hpp" #include #include @@ -6,19 +7,28 @@ #include #include #include - #include +#include +#include + using namespace Math::Literals; MagnumRenderer::MagnumRenderer(GLFWwindow *window) : IRenderer(window) { + ValidateSupport(); + LOG(INFO, "Renderer created"); } -MagnumRenderer::~MagnumRenderer() +void MagnumRenderer::Init() { - + LOG(INFO, "GLSL version: %d", GL::Context::current().version()); + + LoadShaders(); + LoadProvinces(); + + LOG(INFO, "Renderer initialized"); } void MagnumRenderer::Clear() @@ -28,29 +38,102 @@ void MagnumRenderer::Clear() void MagnumRenderer::DrawMap() { - //TEST TRIANGLE - struct TriangleVertex { - Vector2 position; - Color3 color; - }; - const TriangleVertex vertices[]{ - {{-0.5f, -0.5f}, 0xff0000_rgbf}, /* Left vertex, red color */ - {{ 0.5f, -0.5f}, 0x00ff00_rgbf}, /* Right vertex, green color */ - {{ 0.0f, 0.5f}, 0x0000ff_rgbf} /* Top vertex, blue color */ - }; - - GL::Mesh mesh; - mesh.setCount((int)Containers::arraySize(vertices)) - .addVertexBuffer(GL::Buffer{vertices}, 0, - Shaders::VertexColor2D::Position{}, - Shaders::VertexColor2D::Color3{}); - - Shaders::VertexColor2D shader; - - shader.draw(mesh); + ApplyCamera(); + for (uint32_t i = 0; i < provinceMeshes.size(); i++) + { + provinceMaterial->setId(i); + provinceMaterial->draw(provinceMeshes[i]); + } } void MagnumRenderer::DrawUI() { +} + +void MagnumRenderer::ValidateSupport() +{ + +} + +void MagnumRenderer::ApplyCamera() +{ + ApplyMapMVP(); +} + +void MagnumRenderer::ApplyMapTransform() +{ + ApplyMapMVP(); +} + +void MagnumRenderer::ApplyMapMVP() +{ + Matrix4 viewProjection {Magnum::NoInit}; + std::memcpy(viewProjection.data(), glm::value_ptr(this->viewProjection), sizeof(float) * 16); + + Matrix4 mapModel {Magnum::NoInit}; + std::memcpy(mapModel.data(), glm::value_ptr(this->mapModel), sizeof(float) * 16); + + + provinceMaterial->setModelViewProjection(mapModel, viewProjection); +} + +void MagnumRenderer::LoadShaders() +{ + provinceMaterial = Allocate(std::string( + reinterpret_cast(shaders.vertProvinces->content), + shaders.vertProvinces->size + ) + '\0', std::string( + reinterpret_cast(shaders.fragProvinces->content), + shaders.fragProvinces->size + )) + '\0'; + + LOG(INFO, "Shaders loaded"); +} + +void MagnumRenderer::LoadProvinces() +{ + std::vector provincesData; + for (auto& [state, provs]: mapMesh->states) + { + for (MapMesh::Province &province: provs) + { + GL::Mesh stateMesh; + + stateMesh.setPrimitive(GL::MeshPrimitive::Triangles) + .setCount(static_cast(province.indices.size())) + .addVertexBuffer(GL::Buffer{province.vertices}, 0, GL::Attribute<0, Magnum::Vector2>{}) + .setIndexBuffer(GL::Buffer{province.indices}, 0, GL::MeshIndexType::UnsignedShort); + + provinceMeshes.push_back(std::move(stateMesh)); + + ProvinceSSBO data { + .stateId = state, + .color = state + }; + + provincesData.push_back(data); + } + } + + LOG(INFO, "Registered %d province meshes in renderer", provinceMeshes.size()); + + provinceSSBO.setTargetHint(GL::Buffer::TargetHint::ShaderStorage); + provinceSSBO.setData(provincesData, GL::BufferUsage::DynamicDraw); + provinceSSBO.bind(GL::Buffer::Target::ShaderStorage, PROVINCES_SSBO_BINDING); + +} + +void MagnumRenderer::Shutdown() +{ + provinceMeshes.clear(); + provinceSSBO = GL::Buffer{NoCreate}; + if (provinceMaterial != nullptr) + Deallocate(provinceMaterial); + provinceMaterial = nullptr; +} + +MagnumRenderer::~MagnumRenderer() +{ + } \ No newline at end of file diff --git a/sdk/map/CMakeLists.txt b/sdk/map/CMakeLists.txt index eac732a..255a992 100644 --- a/sdk/map/CMakeLists.txt +++ b/sdk/map/CMakeLists.txt @@ -31,8 +31,8 @@ foreach(MAP ${MAP_FILES}) add_custom_command( OUTPUT ${OUT_FILE} - COMMAND ${PROJECT_NAME} ${MAP} ${OUT_FILE} - DEPENDS ${MAP} + COMMAND $ ${MAP} ${OUT_FILE} + DEPENDS ${MAP} ${PROJECT_NAME} COMMENT "Converting map ${MAP_NAME}" VERBATIM ) diff --git a/sdk/map/__provinces.bmp b/sdk/map/__provinces.bmp deleted file mode 100644 index 9289c27..0000000 Binary files a/sdk/map/__provinces.bmp and /dev/null differ diff --git a/sdk/map/run.cmd b/sdk/map/run.cmd new file mode 100644 index 0000000..11b0a5b --- /dev/null +++ b/sdk/map/run.cmd @@ -0,0 +1,2 @@ +@echo off +"%CD%/../../out/build/DEBUG/sdk/map/convert_map.exe" states.bmp ../../assets/map/states.map \ No newline at end of file diff --git a/sdk/map/provinces.bmp b/sdk/map/states.bmp similarity index 100% rename from sdk/map/provinces.bmp rename to sdk/map/states.bmp diff --git a/sdk/materials/CMakeLists.txt b/sdk/materials/CMakeLists.txt index da8f5b2..c74e6b6 100644 --- a/sdk/materials/CMakeLists.txt +++ b/sdk/materials/CMakeLists.txt @@ -16,7 +16,7 @@ find_package(xxHash CONFIG REQUIRED) add_executable(${PROJECT_NAME} compile_materials.cpp) target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash) -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/engine/include/) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/engine-api/include/) if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) diff --git a/sdk/materials/compile_materials.cpp b/sdk/materials/compile_materials.cpp index 262decf..4cfeb9e 100644 --- a/sdk/materials/compile_materials.cpp +++ b/sdk/materials/compile_materials.cpp @@ -4,16 +4,14 @@ #include #include #include -#include "AssetData.hpp" +#include using json = nlohmann::json; NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( - AssetVulkanMaterial, + AssetMaterial, vertexShaderAssetID, - fragmentShaderAssetID, - renderType, - renderStage + fragmentShaderAssetID ) int main(int argc, char **argv) @@ -51,7 +49,7 @@ int main(int argc, char **argv) data[key] = assetId; } - AssetVulkanMaterial material = data.get(); + AssetMaterial material = data.get(); fout.write(reinterpret_cast(&material), sizeof(material)); fin.close(); diff --git a/sdk/materials/helloworld.mat.json b/sdk/materials/helloworld.mat.json deleted file mode 100644 index be905ce..0000000 --- a/sdk/materials/helloworld.mat.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "vertexShaderAssetID": "assets/shaders/helloworld.vert.spv", - "fragmentShaderAssetID": "assets/shaders/helloworld.frag.spv", - "renderType": "base", - "renderStage": 0 -} \ No newline at end of file diff --git a/sdk/materials/provinces.mat.json b/sdk/materials/provinces.mat.json new file mode 100644 index 0000000..1d969a2 --- /dev/null +++ b/sdk/materials/provinces.mat.json @@ -0,0 +1,4 @@ +{ + "vertexShaderAssetID": "assets/shaders/provinces.vert", + "fragmentShaderAssetID": "assets/shaders/provinces.frag" +} \ No newline at end of file diff --git a/utils/include/ee_utils/buffers.hpp b/utils/include/ee_utils/buffers.hpp new file mode 100644 index 0000000..aead816 --- /dev/null +++ b/utils/include/ee_utils/buffers.hpp @@ -0,0 +1,4 @@ +#pragma once +#include + +bool readNext(void* dist, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize); \ No newline at end of file diff --git a/utils/src/buffers.cpp b/utils/src/buffers.cpp new file mode 100644 index 0000000..02beceb --- /dev/null +++ b/utils/src/buffers.cpp @@ -0,0 +1,16 @@ +#include +#include + +bool readNext(void* dist, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize) +{ + if (srcLeftoverSize >= readSize) + { + srcLeftoverSize -= readSize; + std::memcpy(dist, srcPointer, readSize); + srcPointer += readSize; + + return true; + } + + return false; +} \ No newline at end of file