Rendering states in Magnum
This commit is contained in:
parent
91bee9f300
commit
6bcea3087a
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -1,5 +0,0 @@
|
||||
{
|
||||
"cmake.debugConfig": {
|
||||
"args": ["D:/PROJECTS/EtrediaEmpires/sdk/map/provinces.bmp", "D:/PROJECTS/EtrediaEmpires/sdk/map/provinces.map"]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
1
assets/materials/provinces.mat
Normal file
1
assets/materials/provinces.mat
Normal file
@ -0,0 +1 @@
|
||||
Vpクx /}
|
||||
1
assets/materials/provinces.mat.bak
Normal file
1
assets/materials/provinces.mat.bak
Normal file
@ -0,0 +1 @@
|
||||
贔PD゙<EFBFBD>タイ
|
||||
7
assets/shaders/provinces.frag
Normal file
7
assets/shaders/provinces.frag
Normal file
@ -0,0 +1,7 @@
|
||||
layout(location = 0) in vec3 fragColor;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(fragColor, 1.0);
|
||||
}
|
||||
28
assets/shaders/provinces.vert
Normal file
28
assets/shaders/provinces.vert
Normal file
@ -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);
|
||||
}
|
||||
@ -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/)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC include/)
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
|
||||
endif()
|
||||
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "Map.hpp"
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
|
||||
@ -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
|
||||
// <param id:value>
|
||||
|
||||
// Fragment shader params
|
||||
// <param id:value>
|
||||
};
|
||||
21
engine-api/include/ee_engine_api/Map.hpp
Normal file
21
engine-api/include/ee_engine_api/Map.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
struct MapMesh
|
||||
{
|
||||
struct Province
|
||||
{
|
||||
std::vector<glm::vec2> vertices;
|
||||
std::vector<uint16_t> indices;
|
||||
};
|
||||
std::unordered_map<uint32_t, std::vector<Province>> states;
|
||||
};
|
||||
|
||||
struct ProvinceSSBO
|
||||
{
|
||||
uint32_t stateId;
|
||||
uint32_t color;
|
||||
};
|
||||
@ -1,22 +1,61 @@
|
||||
#pragma once
|
||||
#include <GLFW/glfw3.h>
|
||||
#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;
|
||||
};
|
||||
89
engine-api/src/AssetData.cpp
Normal file
89
engine-api/src/AssetData.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include <ee_engine_api/AssetData.hpp>
|
||||
#include <ee_utils/allocator.hpp>
|
||||
#include <ee_utils/buffers.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/*
|
||||
|
||||
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<uint32_t>(color.r) << 16 |
|
||||
static_cast<uint32_t>(color.g) << 8 |
|
||||
static_cast<uint32_t>(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);
|
||||
}
|
||||
@ -1,10 +1,13 @@
|
||||
#include <ee_engine_api/RenderInterface.hpp>
|
||||
#include <ee_utils/allocator.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "Logger.h"
|
||||
|
||||
IRenderer::IRenderer(GLFWwindow *window)
|
||||
{
|
||||
this->window = window;
|
||||
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
|
||||
screenAspect = static_cast<float>(screenWidth) / static_cast<float>(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<float>(screenWidth) / static_cast<float>(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();
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "FileSystem.hpp"
|
||||
#include "AssetData.hpp"
|
||||
#include <ee_engine_api/AssetData.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
@ -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 <Asset T> T& FindOnce(const std::filesystem::path &path);
|
||||
template <Asset T> T& FindOnce(const uint32_t &id);
|
||||
void Redirect(AssetHandle &handle, void *resource);
|
||||
template <Asset T> T& Get(const AssetHandle &handle);
|
||||
void Free(AssetHandle &handle);
|
||||
@ -108,8 +112,9 @@ private:
|
||||
std::vector<AssetLoadingEntry> loadingEntries;
|
||||
|
||||
std::vector<AssetBinary*> binaryStorage;
|
||||
std::vector<AssetVulkanShader*> shadersStorage;
|
||||
std::vector<AssetVulkanMaterial*> materialsStorage;
|
||||
std::vector<AssetMapMesh*> mapMeshesStorage;
|
||||
std::vector<AssetShader*> shadersStorage;
|
||||
std::vector<AssetMaterial*> materialsStorage;
|
||||
|
||||
void Threading();
|
||||
void Request(const AssetStreamCommand &command);
|
||||
@ -117,6 +122,8 @@ private:
|
||||
void Loop();
|
||||
void ProcessCommand(AssetStreamCommand &command);
|
||||
void Release();
|
||||
|
||||
template<Asset T> void ClearStorage(std::vector<T*> &storage);
|
||||
};
|
||||
|
||||
template <Asset T> T& AssetManager::Get(const AssetHandle &handle)
|
||||
@ -130,4 +137,24 @@ template <Asset T> T& AssetManager::Get(const AssetHandle &handle)
|
||||
Request(command);
|
||||
while (command.out->load() == nullptr);
|
||||
return *reinterpret_cast<T*>(command.out->load());
|
||||
}
|
||||
|
||||
template <Asset T> T& AssetManager::FindOnce(const std::filesystem::path &path)
|
||||
{
|
||||
return Get<T>(Find(path));
|
||||
}
|
||||
|
||||
template <Asset T> T& AssetManager::FindOnce(const uint32_t &id)
|
||||
{
|
||||
return Get<T>(Find(id));
|
||||
}
|
||||
|
||||
template<Asset T> void AssetManager::ClearStorage(std::vector<T*> &storage)
|
||||
{
|
||||
for (T* &resource : storage)
|
||||
{
|
||||
if (resource != nullptr)
|
||||
Deallocate(resource);
|
||||
}
|
||||
storage.clear();
|
||||
}
|
||||
@ -10,6 +10,8 @@ public:
|
||||
static AssetManager *assetManager;
|
||||
static IRenderer *renderer;
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
Engine();
|
||||
};
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
#include "AssetData.hpp"
|
||||
#include <ee_utils/allocator.hpp>
|
||||
|
||||
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<uint32_t*>(source);
|
||||
size = sourceSize;
|
||||
source = nullptr;
|
||||
}
|
||||
|
||||
AssetVulkanShader::~AssetVulkanShader()
|
||||
{
|
||||
if (content != nullptr)
|
||||
DeallocateArray(content);
|
||||
}
|
||||
@ -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<AssetVulkanShader>(entry.file->data, entry.file->size);
|
||||
AssetMapMesh* mesh = Allocate<AssetMapMesh>(entry.file->data, entry.file->size);
|
||||
mapMeshesStorage.push_back(mesh);
|
||||
Redirect(entry.handle, mapMeshesStorage.back());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case AssetInfo::SHADER:
|
||||
{
|
||||
AssetShader* shader = Allocate<AssetShader>(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<AssetVulkanMaterial>();
|
||||
if (entry.file->size < sizeof(AssetVulkanMaterial))
|
||||
AssetMaterial* material = Allocate<AssetMaterial>();
|
||||
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());
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,25 @@
|
||||
#include "Engine.hpp"
|
||||
#include <ee_utils/allocator.hpp>
|
||||
|
||||
AssetManager* Engine::assetManager;
|
||||
IRenderer* Engine::renderer;
|
||||
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;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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<AssetManager>();
|
||||
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<AssetMaterial>(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<IRenderer*>(Allocate<MagnumRenderer>(window));
|
||||
|
||||
AssetMapMesh &states = Engine::assetManager->FindOnce<AssetMapMesh>("assets/map/states.map");
|
||||
Engine::renderer->RegisterMapMesh(&states.content);
|
||||
|
||||
//TODO: ShaderRefs builder from set of AssetMaterial
|
||||
AssetMaterial &provincesMaterial = Engine::assetManager->FindOnce<AssetMaterial>("assets/materials/provinces.mat");
|
||||
AssetShader &vertProv = Engine::assetManager->FindOnce<AssetShader>(provincesMaterial.vertexShaderAssetID);
|
||||
AssetShader &fragProv = Engine::assetManager->FindOnce<AssetShader>(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
|
||||
|
||||
35
renderers/magnum-renderer/include/ee_magnum/Materials.hpp
Normal file
35
renderers/magnum-renderer/include/ee_magnum/Materials.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#include <Magnum/GL/AbstractShaderProgram.h>
|
||||
#include <Magnum/GL/Shader.h>
|
||||
#include <Magnum/GL/Version.h>
|
||||
#include <Magnum/Math/Matrix4.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#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);
|
||||
};
|
||||
@ -4,8 +4,11 @@
|
||||
#undef max
|
||||
|
||||
#include <Magnum/Platform/GLContext.h>
|
||||
#include <Magnum/GL/Mesh.h>
|
||||
#include <Magnum/GL/Buffer.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "Materials.hpp"
|
||||
#include <ee_engine_api/RenderInterface.hpp>
|
||||
|
||||
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<GL::Mesh> provinceMeshes;
|
||||
GL::Buffer provinceSSBO;
|
||||
ProvinceMaterial *provinceMaterial;
|
||||
|
||||
void ValidateSupport();
|
||||
void LoadShaders();
|
||||
void LoadProvinces();
|
||||
|
||||
void ApplyMapMVP();
|
||||
};
|
||||
37
renderers/magnum-renderer/src/Materials.cpp
Normal file
37
renderers/magnum-renderer/src/Materials.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <ee_magnum/Materials.hpp>
|
||||
#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);
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
#include "Logger.h"
|
||||
#include "ee_utils/allocator.hpp"
|
||||
#include <ee_magnum/Renderer.hpp>
|
||||
|
||||
#include <Magnum/GL/Buffer.h>
|
||||
@ -6,19 +7,28 @@
|
||||
#include <Magnum/GL/Mesh.h>
|
||||
#include <Magnum/Math/Color.h>
|
||||
#include <Magnum/Shaders/VertexColor.h>
|
||||
|
||||
#include <Corrade/Utility/Debug.h>
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <string>
|
||||
|
||||
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<ProvinceMaterial>(std::string(
|
||||
reinterpret_cast<const char*>(shaders.vertProvinces->content),
|
||||
shaders.vertProvinces->size
|
||||
) + '\0', std::string(
|
||||
reinterpret_cast<const char*>(shaders.fragProvinces->content),
|
||||
shaders.fragProvinces->size
|
||||
)) + '\0';
|
||||
|
||||
LOG(INFO, "Shaders loaded");
|
||||
}
|
||||
|
||||
void MagnumRenderer::LoadProvinces()
|
||||
{
|
||||
std::vector<ProvinceSSBO> provincesData;
|
||||
for (auto& [state, provs]: mapMesh->states)
|
||||
{
|
||||
for (MapMesh::Province &province: provs)
|
||||
{
|
||||
GL::Mesh stateMesh;
|
||||
|
||||
stateMesh.setPrimitive(GL::MeshPrimitive::Triangles)
|
||||
.setCount(static_cast<Magnum::Int>(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()
|
||||
{
|
||||
|
||||
}
|
||||
@ -31,8 +31,8 @@ foreach(MAP ${MAP_FILES})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${OUT_FILE}
|
||||
COMMAND ${PROJECT_NAME} ${MAP} ${OUT_FILE}
|
||||
DEPENDS ${MAP}
|
||||
COMMAND $<TARGET_FILE:${PROJECT_NAME}> ${MAP} ${OUT_FILE}
|
||||
DEPENDS ${MAP} ${PROJECT_NAME}
|
||||
COMMENT "Converting map ${MAP_NAME}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 33 MiB |
2
sdk/map/run.cmd
Normal file
2
sdk/map/run.cmd
Normal file
@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
"%CD%/../../out/build/DEBUG/sdk/map/convert_map.exe" states.bmp ../../assets/map/states.map
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@ -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)
|
||||
|
||||
@ -4,16 +4,14 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <xxhash.h>
|
||||
#include <string>
|
||||
#include "AssetData.hpp"
|
||||
#include <ee_engine_api/AssetData.hpp>
|
||||
|
||||
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<AssetVulkanMaterial>();
|
||||
AssetMaterial material = data.get<AssetMaterial>();
|
||||
fout.write(reinterpret_cast<const char*>(&material), sizeof(material));
|
||||
|
||||
fin.close();
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"vertexShaderAssetID": "assets/shaders/helloworld.vert.spv",
|
||||
"fragmentShaderAssetID": "assets/shaders/helloworld.frag.spv",
|
||||
"renderType": "base",
|
||||
"renderStage": 0
|
||||
}
|
||||
4
sdk/materials/provinces.mat.json
Normal file
4
sdk/materials/provinces.mat.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"vertexShaderAssetID": "assets/shaders/provinces.vert",
|
||||
"fragmentShaderAssetID": "assets/shaders/provinces.frag"
|
||||
}
|
||||
4
utils/include/ee_utils/buffers.hpp
Normal file
4
utils/include/ee_utils/buffers.hpp
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
bool readNext(void* dist, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize);
|
||||
16
utils/src/buffers.cpp
Normal file
16
utils/src/buffers.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <ee_utils/buffers.hpp>
|
||||
#include <cstring>
|
||||
|
||||
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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user