Ajout de la 2D et du texte => couleurs pas finies + bug ordre affichage

This commit is contained in:
2026-08-30 16:59:35 +02:00
parent ab43ad1604
commit 82314d7d85
27 changed files with 412 additions and 119 deletions
+1 -1
View File
@@ -401,7 +401,7 @@ endif()
# Paramètre de compilation
if (UNIX)
set(CMAKE_CXX_FLAGS "-Wall -fPIC")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
endif ()
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

Submodule lib/All/msdf-atlas-gen updated: 2ede254314...6148900d59
+1 -1
View File
@@ -1,4 +1,4 @@
set(MSDFATLASGEN "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/artery-font-format/artery-font; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdf-atlas-gen; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/ext; {CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/core")
set(MSDFATLASGEN "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/artery-font-format/artery-font; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdf-atlas-gen; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/ext; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/core")
set(MSDFGENEXT "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/libmsdfgen-ext.a")
set(MSDFGENCORE "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/msdf-atlas-gen/msdfgen/libmsdfgen-core.a")
+137 -9
View File
@@ -1,6 +1,5 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"title": "SceneDescription",
"type": "object",
"properties": {
"name": { "type": "string", "ID": 101},
@@ -9,6 +8,11 @@
"type": "array",
"ID": 103,
"items": { "$ref": "#/definitions/Entity" }
},
"entities2D": {
"type": "array",
"ID": 104,
"items": { "$ref": "#/definitions/Entity2D" }
}
},
"required": ["name", "entities"],
@@ -31,6 +35,17 @@
"required": ["entityref", "name", "components"]
},
"Entity2D": {
"type": "object",
"properties": {
"entityref": { "type": "integer", "ID": 207 },
"name": { "type": "string", "ID": 208 },
"description": { "type": "string", "ID": 209},
"components": { "ID": 210, "$ref": "#/definitions/Components2D" }
},
"required": ["entityref", "name", "components"]
},
"Components": {
"type": "object",
"properties": {
@@ -38,10 +53,30 @@
"renderer": { "ID": 2062, "$ref": "#/definitions/Renderer" },
"camera": { "ID": 2063, "$ref": "#/definitions/Camera" },
"collider": { "ID": 2064, "$ref": "#/definitions/Collider" },
"rigidbody": { "ID": 2065, "$ref": "#/definitions/RigidBody" }
"rigidbody": { "ID": 2065, "$ref": "#/definitions/RigidBody" },
"speaker": { "ID": 2066, "$ref": "#/definitions/Speaker" },
"script": { "ID": 2067, "$ref": "#/definitions/Script" },
"light": { "ID": 2068, "$ref": "#/definitions/Light" }
}
},
"Components2D": {
"type": "object",
"properties": {
"transform": { "ID": 2069, "$ref": "#/definitions/Transform2D" },
"renderer": { "ID": 2070, "$ref": "#/definitions/Renderer2D" },
"camera": { "ID": 2071, "$ref": "#/definitions/Camera2D" },
"collider": { "ID": 2072, "$ref": "#/definitions/Collider2D" }
}
},
"Vec2": {
"type": "array",
"items": { "type": "number" },
"minItems": 2,
"maxItems": 2
},
"Vec3": {
"type": "array",
"items": { "type": "number" },
@@ -66,6 +101,20 @@
"required": ["position", "rotation", "scale"]
},
"Transform2D": {
"type": "object",
"properties": {
"position": { "ID": 4011, "$ref": "#/definitions/Vec2" },
"rotation": { "ID": 4012, "type": "number" },
"scale": { "ID": 4013, "$ref": "#/definitions/Vec2" },
"size": { "ID": 4014, "$ref": "#/definitions/Vec2" },
"pivot": { "ID": 4015, "$ref": "#/definitions/Vec3" },
"zorder": { "ID": 4016, "type": "integer", "minimum": 0 },
"visible": { "ID": 4017, "type": "boolean" }
},
"required": ["position", "size"]
},
"Renderer": {
"type": ["object", "null"],
"properties": {
@@ -76,6 +125,15 @@
"required": ["model", "shader"]
},
"Renderer2D": {
"type": ["object", "null"],
"properties": {
"model": { "type": "string", "ID": 4021 },
"shader": { "type": "string", "ID": 4022 }
},
"required": ["model", "shader"]
},
"Camera": {
"type": ["object", "null"],
"properties": {
@@ -86,13 +144,21 @@
"required": ["fov", "near", "far"]
},
"Camera2D": {
"type": ["object", "null"],
"properties": {
"zoom": { "type": "number", "minimum": 1.0, "ID": 4031 }
},
"required": ["zoom"]
},
"Collider": {
"type": ["object", "null"],
"properties": {
"type": {
"type": "string",
"type": "integer",
"ID": 3041,
"enum": ["Box", "Sphere", "Capsule", "ConvexHull", "Mesh", "Compound"]
"enum": [0,1,2,3,4,5]
},
"size": { "$ref": "#/definitions/Vec3", "ID": 3042 },
"radius": { "type": "number", "minimum": 0, "ID": 3043 },
@@ -101,33 +167,95 @@
"required": ["type"],
"allOf": [
{
"if": { "properties": { "type": { "const": "Box" } } },
"if": { "properties": { "type": { "const": 0 } } },
"then": { "required": ["size"] }
},
{
"if": { "properties": { "type": { "const": "Sphere" } } },
"if": { "properties": { "type": { "const": 1 } } },
"then": { "required": ["radius"] }
},
{
"if": { "properties": { "type": { "const": "Capsule" } } },
"if": { "properties": { "type": { "const": 2 } } },
"then": { "required": ["radius", "halfHeight"] }
}
]
},
"Collider2D": {
"type": ["object", "null"],
"properties": {
"type": {
"type": "integer",
"ID": 4041,
"enum": [0,1,2,3]
}
},
"required": ["type"]
},
"RigidBody": {
"type": ["object", "null"],
"properties": {
"type": {
"type": "string",
"type": "integer",
"ID": 3051,
"enum": ["Static", "Kinematic", "Dynamic"]
"enum": [0,1,2]
},
"mass": { "type": "number", "minimum": 0, "ID": 3052 },
"friction": { "type": "number", "minimum": 0, "maximum": 1, "ID": 3053 },
"restitution": { "type": "number", "minimum": 0, "maximum": 1, "ID": 3054 }
},
"required": ["type"]
},
"Speaker": {
"type": ["object", "null"],
"properties": {
"clips": {
"type": "array",
"ID": 3061,
"items": {
"type": "object",
"properties": {
"path": { "type": "string", "ID": 30611 },
"gain": { "type": "number", "minimum": 0, "ID": 30612 },
"pitch": { "type": "number", "minimum": 0, "ID": 30613 },
"loop": { "type": "boolean", "ID": 30614 },
"spatial": { "type": "boolean", "ID": 30615 }
},
"required": ["path"]
}}
},
"required": ["clips"]
},
"Light": {
"type": ["object", "null"],
"properties": {
"type": {
"type": "integer",
"ID": 3071,
"enum": [0,1,2]
},
"color": { "$ref": "#/definitions/Vec3", "ID": 3072 },
"intensity": { "type": "number", "minimum": 0, "ID": 3073 },
"range": { "type": "number", "minimum": 0, "ID": 3074 },
"attenuation": { "type": "number", "minimum": 0, "ID": 3075 },
"innerangle": { "type": "number", "minimum": 0, "ID": 3076 },
"outerangle": { "type": "number", "minimum": 0, "ID": 3077 },
"castshadow": { "type": "boolean", "ID": 3078 }
},
"required": ["type", "color", "intensity", "range", "attenuation", "innerangle", "outerangle", "castshadow"]
},
"Script": {
"type": ["object", "null"],
"properties": {
"scriptNames": {
"type": "array",
"items": {"type" : "string", "ID": 3079}}
},
"required": ["scriptNames"]
}
}
}
+3 -28
View File
@@ -160,40 +160,15 @@ namespace CosmicCore {
if(!isPreview)
{
m_window.initialization();
auto scene = CScene::load("scenes/scene1.json");
auto scene = CScene::load("assets/scenes/scene_menu.json");
m_activeScene = scene.get();
m_sceneMap[scene->getName()] = std::move(scene);
auto font = CResourceAPI::resources().fonts().loadFont("assets/fonts/Arial");
auto ent = m_activeScene->createEntity();
ComponentFactory::Transform2DConfig trConf = {
{100.0,100.0},
{75.0,75.0},
{1.0,1.0},
{0.0,0.0},
0.0,
0.0,
true};
ComponentFactory::addTransform2D(ent, trConf);
Model2DLoadConfig config;
config.shaderName = "ui";
auto shader = CResourceAPI::resources().shaders().get(config.shaderName);
MeshMaterial2D mm2d;
mm2d.material = new CMaterial2D();
mm2d.material->m_color = {1,1,1,1};
mm2d.material->m_font = font;
mm2d.material->shader = static_cast<CShaderImplVulkan*>(shader);
mm2d.material->build();
mm2d.mesh = new CMesh2D();
mm2d.mesh->buildFromText(mm2d.material->m_font, "TEST DE FONT");
CModel2D* model = new CModel2D({mm2d});
ent.addComponent<CTextRenderer>(model);
}
}
void loadConfigurations()
{
if(m_engineConfig.load("config/engine/engine.json"))
if(m_engineConfig.load("assets/configs/engine/engine.json"))
{
// Configuration fenêtre
// TODO: appliquer les settings de fenêtre via CGameWindow ou GraphicsAPI
@@ -207,7 +182,7 @@ namespace CosmicCore {
m_inputWorld.getMapping().setMouseSensitivity(m_engineConfig.input.mouseSensitivity);
}
if(m_gameConfig.load("config/game/game.json"))
if(m_gameConfig.load("assets/configs/game/game.json"))
{
m_window.setSize(m_gameConfig.window.width, m_gameConfig.window.height);
m_window.setTitle(m_gameConfig.window.title);
+12 -2
View File
@@ -174,7 +174,7 @@ namespace CosmicCore {
auto entities = m_ecManager.registry.view<CRenderer2D, CTransform2D>();
auto textEntities = m_ecManager.registry.view<CTextRenderer, CTransform2D>();
if(entities.begin() != entities.end())
if(entities.begin() != entities.end() || textEntities.begin() != textEntities.end())
{
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
auto cam = m_ecManager.registry.view<CCamera2D>();
@@ -409,6 +409,7 @@ namespace CosmicCore {
nlohmann::json& collider = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Collider2D)];
nlohmann::json& renderer = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Renderer2D)];
nlohmann::json& script = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_Script)];
nlohmann::json& textRenderer = components[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Component_TextRenderer2D)];
auto trConfig(!transform.is_null() ? std::optional<CosmicUtils::ComponentFactory::Transform2DConfig>({
glm::make_vec2(transform[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Transform_Position2D)].get<std::vector<float>>().data()),
@@ -437,6 +438,14 @@ namespace CosmicCore {
script.get<std::vector<std::string>>()
}): std::nullopt);
auto textRenderer2DConfig(!textRenderer.is_null() ? std::optional<CosmicUtils::ComponentFactory::TextRenderer2DConfig>({
textRenderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::TextRenderer_Text2D)].get<std::string>(),
textRenderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::TextRenderer_Shader2D)].get<std::string>(),
glm::make_vec4(textRenderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::TextRenderer_Color2D)].get<std::vector<float>>().data()),
textRenderer[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::TextRenderer_Font2D)].get<std::string>()
}) : std::nullopt);
CosmicUtils::CEntityFactory::Entity2DConfig config = {
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity2D_Name)],
entityObj[CosmicUtils::JsonKeyRegistry::key(CosmicUtils::EJsonKeys::Entity2D_Description)],
@@ -444,7 +453,8 @@ namespace CosmicCore {
camConfig,
rendererConfig,
colliderConfig,
scriptConfig
scriptConfig,
textRenderer2DConfig
};
auto entityHandle = CosmicUtils::CEntityFactory::create(scene.get(), config);
@@ -78,7 +78,7 @@ void VulkanImpl::init(SDL_Window* window){
void VulkanImpl::cleanup(){
device.waitIdle();
// 1. détruire les ressources dans le ResourceManager
// détruire les ressources dans le ResourceManager
// (buffers, pipelines, descriptor sets...)
m_deletionQueue.flushAll();
@@ -110,7 +110,6 @@ void VulkanImpl::cleanup(){
projection2DLayout = nullptr;
transform2DLayout = nullptr;
material2DLayout = nullptr;
VmaTotalStatistics stats;
vmaCalculateStatistics(allocator, &stats);
if (stats.total.statistics.allocationCount > 0) {
@@ -123,13 +122,13 @@ void VulkanImpl::cleanup(){
//Vulkan memory allocator
vmaDestroyAllocator(allocator);
// 5. surface
// surface
surface = nullptr;
// 6. device en avant-dernier
// device en avant-dernier
device = nullptr;
// 7. instance en dernier
// instance en dernier
instance = nullptr;
}
@@ -1,5 +1,6 @@
// CFont.cpp
#include "CFont.hpp"
#include "Core/Systems/Graphics/Data/Texture/CTexture.hpp"
#include "Core/Systems/Resources/API/CResourceAPI.hpp"
#include <nlohmann/json.hpp>
#include <fstream>
@@ -10,7 +11,7 @@ namespace CosmicCore {
void CFont::init(const std::string& jsonPath, const std::string& atlasPath) {
// charge l'atlas comme texture
auto& rm = CResourceAPI::resources().textures();
m_atlas = rm.loadTexture(atlasPath);
m_atlas = rm.loadTexture(atlasPath, TextureType::MSDFFont);
// parse le JSON
std::ifstream file(jsonPath);
@@ -24,7 +24,7 @@ struct SLightData {
struct SLightsUBOData {
SLightData lights[MAX_LIGHTS];
int lightCount = 0;
glm::vec3 padding;
//glm::vec3 padding;
};
class CLightsBuffer {
@@ -27,7 +27,15 @@ void CMaterial2D::build() {
vk::PipelineMultisampleStateCreateInfo multisampling{{}, vk::SampleCountFlagBits::e1, vk::False};
vk::PipelineColorBlendAttachmentState colorBlendAttachment{vk::False, {}, {}, {}, {}, {}, {}, vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA};
vk::PipelineColorBlendAttachmentState colorBlendAttachment{
vk::True,
vk::BlendFactor::eSrcAlpha,
vk::BlendFactor::eOneMinusSrcAlpha,
vk::BlendOp::eAdd,
vk::BlendFactor::eOne,
vk::BlendFactor::eZero,
vk::BlendOp::eAdd,
vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA};
vk::PipelineColorBlendStateCreateInfo colorBlending{{},vk::False, vk::LogicOp::eCopy, 1, &colorBlendAttachment};
@@ -43,7 +43,7 @@ namespace CosmicCore {
VkDeviceSize indexSize = sizeof(m_indexes[0]) * m_indexes.size();
VkDeviceSize totalSize = vertexSize + indexSize;
// 1. staging buffer - CPU visible, temporaire
//staging buffer CPU visible, temporaire
VkBufferCreateInfo stagingBufferInfo{};
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
stagingBufferInfo.size = totalSize;
@@ -58,12 +58,12 @@ namespace CosmicCore {
vmaCreateBuffer(allocator, &stagingBufferInfo, &stagingAllocInfo,
&stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo);
// 2. copie des données CPU → staging
// copie des données CPU → staging
memcpy(stagingInfo.pMappedData, m_vertexes.data(), vertexSize);
memcpy((char*)stagingInfo.pMappedData + vertexSize, m_indexes.data(), indexSize);
vmaFlushAllocation(allocator, stagingBuffer.allocation, 0, VK_WHOLE_SIZE);
// 3. vertex buffer final - DEVICE_LOCAL, rapide
//vertex buffer final - DEVICE_LOCAL
VkBufferCreateInfo vertexBufferInfo{};
vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
vertexBufferInfo.size = totalSize;
@@ -77,13 +77,13 @@ namespace CosmicCore {
vmaCreateBuffer(allocator, &vertexBufferInfo, &vertexAllocInfo,
&vertexIndexBuffer.buffer, &vertexIndexBuffer.allocation, nullptr);
// 4. copie GPU staging → vertex buffer via command buffer
// copie GPU staging vertex buffer via command buffer
api->copyBuffer(stagingBuffer.buffer, vertexIndexBuffer.buffer, totalSize);
m_vertexOffset = 0;
m_indexOffset = vertexSize;
m_indexCount = m_indexes.size();
// 5. détruire le staging buffer
//détruire le staging buffer
vmaDestroyBuffer(allocator, stagingBuffer.buffer, stagingBuffer.allocation);
}
@@ -103,45 +103,47 @@ namespace CosmicCore {
float cursorX = 0.0f;
float cursorY = 0.0f;
float maxWidth = 0.0f;
float maxHeight = 0.0f;
int lineCount = 1;
for (char c : text) {
if (c == '\n') {
maxWidth = std::max(maxWidth, cursorX);
cursorX = 0.0f;
cursorY += font->getMetrics().lineHeight * scale;
lineCount++;
continue;
}
if (c == '\n') {
maxWidth = std::max(maxWidth, cursorX);
cursorX = 0.0f;
cursorY += font->getMetrics().lineHeight * scale;
lineCount++;
continue;
}
const SGlyph* glyph = font->getGlyph((uint32_t)c);
if (!glyph) continue;
const SGlyph* glyph = font->getGlyph((uint32_t)c);
if (!glyph) continue;
// positions des coins du quad (espace local au mesh)
glm::vec2 p0 = {
cursorX + glyph->planeMin.x * scale,
cursorY - glyph->planeMax.y * scale
};
glm::vec2 p1 = {
cursorX + glyph->planeMax.x * scale,
cursorY - glyph->planeMin.y * scale
};
// positions des coins du quad (espace local au mesh)
glm::vec2 p0 = {
cursorX + glyph->planeMin.x * scale,
cursorY + glyph->planeMin.y * scale
};
glm::vec2 p1 = {
cursorX + glyph->planeMax.x * scale,
cursorY + glyph->planeMax.y * scale
};
maxHeight = std::max(maxHeight, glyph->planeMax.y);
// UVs dans l'atlas — flip V pour Vulkan
glm::vec2 uv0 = {glyph->atlasMin.x, 1.0f - glyph->atlasMax.y};
glm::vec2 uv1 = {glyph->atlasMax.x, 1.0f - glyph->atlasMin.y};
// UVs dans l'atlas — flip V pour Vulkan
glm::vec2 uv0 = {glyph->atlasMin.x, 1.0f - glyph->atlasMax.y};
glm::vec2 uv1 = {glyph->atlasMax.x, 1.0f - glyph->atlasMin.y};
uint32_t base = (uint32_t)vertices.size();
uint32_t base = (uint32_t)vertices.size();
vertices.push_back({{p0.x, p1.y}, {uv0.x, uv0.y}, {1, 1, 1, 1}});
vertices.push_back({{p0.x, p0.y}, {uv0.x, uv1.y}, {1, 1, 1, 1}});
vertices.push_back({{p1.x, p0.y}, {uv1.x, uv1.y}, {1, 1, 1, 1}});
vertices.push_back({{p1.x, p1.y}, {uv1.x, uv0.y}, {1, 1, 1, 1}});
vertices.push_back({{p0.x, p0.y}, {uv0.x, uv0.y}, {1, 1, 1, 1}});
vertices.push_back({{p1.x, p0.y}, {uv1.x, uv0.y}, {1, 1, 1, 1}});
vertices.push_back({{p1.x, p1.y}, {uv1.x, uv1.y}, {1, 1, 1, 1}});
vertices.push_back({{p0.x, p1.y}, {uv0.x, uv1.y}, {1, 1, 1, 1}});
indices.insert(indices.end(),
{base, base+1, base+2, base+2, base+3, base});
indices.insert(indices.end(),
{base, base+1, base+2, base+2, base+3, base});
cursorX += glyph->advance * scale;
cursorX += glyph->advance * scale;
}
maxWidth = std::max(maxWidth, cursorX);
@@ -3,8 +3,8 @@
#include "../../API/VulkanImplementation/VulkanImpl.hpp"
#include <iostream>
CTexture::CTexture(std::string filePath) :
m_filePath(filePath) {
CTexture::CTexture(std::string filePath, TextureType type) :
m_filePath(filePath), m_type(type) {
}
std::string CTexture::getFilePath(void) {
@@ -25,24 +25,34 @@ void CTexture::init(void) {
throw std::runtime_error("Failed to load: " + m_filePath);
}
// Choix du format en fonction du type de texture
vk::Format formatCol = (m_type == TextureType::MSDFFont)
? vk::Format::eR8G8B8A8Unorm
: vk::Format::eR8G8B8A8Srgb;
vk::Format bgraFormat = (m_type == TextureType::MSDFFont)
? vk::Format::eB8G8R8A8Unorm
: vk::Format::eB8G8R8A8Srgb;
SDL_PixelFormat sdlFormat = sdlSurface->format;
SDL_Surface* converted = nullptr;
if (sdlFormat == SDL_PIXELFORMAT_RGBA32) {
// déjà RGBA, pas de conversion
converted = sdlSurface;
m_format = vk::Format::eR8G8B8A8Srgb;
m_format = formatCol;
} else if (sdlFormat == SDL_PIXELFORMAT_BGRA32) {
// déjà BGRA, pas de conversion mais format différent
converted = sdlSurface;
m_format = vk::Format::eB8G8R8A8Srgb;
m_format = bgraFormat;
} else {
// tout autre format → on force RGBA32
converted = SDL_ConvertSurface(sdlSurface, SDL_PIXELFORMAT_RGBA32);
if (!converted)
throw std::runtime_error("Failed to convert surface: " + m_filePath);
SDL_DestroySurface(sdlSurface);
m_format = vk::Format::eR8G8B8A8Srgb;
m_format = formatCol;
}
@@ -113,17 +123,29 @@ void CTexture::init(void) {
// sampler
vk::SamplerCreateInfo samplerInfo{};
samplerInfo.magFilter = vk::Filter::eLinear;
samplerInfo.minFilter = vk::Filter::eLinear;
samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
samplerInfo.anisotropyEnable = vk::True;
samplerInfo.maxAnisotropy = api->getPhysicalDevice().getProperties().limits.maxSamplerAnisotropy;
samplerInfo.borderColor = vk::BorderColor::eIntOpaqueBlack;
samplerInfo.magFilter = vk::Filter::eLinear;
samplerInfo.minFilter = vk::Filter::eLinear;
samplerInfo.unnormalizedCoordinates = vk::False;
samplerInfo.compareEnable = vk::False;
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
samplerInfo.compareEnable = vk::False;
samplerInfo.borderColor = vk::BorderColor::eIntOpaqueBlack;
if (m_type == TextureType::MSDFFont) {
samplerInfo.addressModeU = vk::SamplerAddressMode::eClampToEdge;
samplerInfo.addressModeV = vk::SamplerAddressMode::eClampToEdge;
samplerInfo.addressModeW = vk::SamplerAddressMode::eClampToEdge;
samplerInfo.anisotropyEnable = vk::False;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eNearest;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
} else {
samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
samplerInfo.anisotropyEnable = vk::True;
samplerInfo.maxAnisotropy = api->getPhysicalDevice().getProperties().limits.maxSamplerAnisotropy;
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
}
m_sampler = vk::raii::Sampler(*device, samplerInfo);
@@ -6,6 +6,11 @@
#include <string>
#include <vulkan/vulkan_raii.hpp>
enum class TextureType {
Color, // image classique (sprite, icône, etc.)
MSDFFont // atlas de glyphes MSDF
};
class CTexture{
private:
// Path of the file.
@@ -14,7 +19,7 @@ private:
vk::raii::DeviceMemory m_textureImageMemory = nullptr;
vk::raii::ImageView m_imageView = nullptr;
vk::raii::Sampler m_sampler = nullptr;
TextureType m_type;
uint32_t m_width = 0;
uint32_t m_height = 0;
vk::Format m_format = vk::Format::eR8G8B8A8Srgb;
@@ -29,7 +34,7 @@ public:
m_textureImage = nullptr;
m_textureImageMemory = nullptr;
};
CTexture(std::string filePath);
CTexture(std::string filePath, TextureType type = TextureType::Color);
std::string getFilePath(void);
void setFilePath(std::string filePath);
void init(void);
@@ -1,7 +1,7 @@
#include "CAudioManager.hpp"
#include <algorithm>
#include <cstdint>
#include <vector>
#define DR_WAV_IMPLEMENTATION
#include "dr_wav.h"
#define DR_MP3_IMPLEMENTATION
@@ -8,11 +8,11 @@ class CTextureManager : public CAbstractResourceManager<CTexture>
{
public:
CTexture* loadTexture(const std::string& path) {
CTexture* loadTexture(const std::string& path, TextureType type = TextureType::Color) {
auto cached = get(path);
if (cached) return cached.value();
auto tex = std::make_unique<CTexture>(path);
auto tex = std::make_unique<CTexture>(path, type);
tex->init();
return add(path, std::move(tex));
}
+7 -1
View File
@@ -68,7 +68,7 @@ CEntity create(CScene* scene, Entity2DConfig& config) {
auto& collider = config.colliderConfig;
auto& renderer = config.rendererConfig;
auto& script = config.scriptConfig;
auto& textRender = config.textConfig;
if(transform.has_value())
{
ComponentFactory::addTransform2D(entity, *transform);
@@ -91,6 +91,12 @@ CEntity create(CScene* scene, Entity2DConfig& config) {
{
ComponentFactory::addScript(entity, *script);
}
if(textRender.has_value())
{
ComponentFactory::addTextRenderer2D(entity, *textRender);
}
return entity;
}
@@ -31,6 +31,7 @@ namespace CosmicUtils {
std::optional<Renderer2DConfig> rendererConfig = std::nullopt;
std::optional<Collider2DConfig> colliderConfig = std::nullopt;
std::optional<ScriptConfig> scriptConfig = std::nullopt;
std::optional<TextRenderer2DConfig> textConfig = std::nullopt;
};
CEntity create(CScene* e, EntityConfig& config);
@@ -4,7 +4,14 @@
#include "Core/Component/Camera/CCamera2D.hpp"
#include "Core/Component/Collider/CCollider2D.hpp"
#include "Core/Component/Geometry/CTransform2D.hpp"
#include "Core/Component/Graphics/CTextRenderer.hpp"
#include "Core/Component/Light/CLight.hpp"
#include "Core/Entity/CEntity.hpp"
#include "Core/Systems/Graphics/Data/Material/CMaterial2D.hpp"
#include "Core/Systems/Graphics/Data/Mesh/CMesh2D.hpp"
#include "Core/Systems/Graphics/Data/Model/CModel2D.hpp"
#include <functional>
#include <memory>
namespace CosmicUtils {
@@ -236,6 +243,10 @@ namespace CosmicUtils {
{
auto& reg = entity.getRegistry();
// CTransform obligatoire
if (!reg.registry.all_of<CTransform2D>(*entity))
throw std::runtime_error("addRenderer2D requires a CTransform2D on the entity");
Model2DLoadConfig config;
config.shaderName = rendererConfig.shader;
@@ -243,6 +254,40 @@ namespace CosmicUtils {
return reg.registry.emplace<CRenderer2D>(*entity, entity, model);
}
CTextRenderer& addTextRenderer2D(CEntity& entity, TextRenderer2DConfig& rendererConfig)
{
auto& reg = entity.getRegistry();
// CTransform obligatoire
if (!reg.registry.all_of<CTransform2D>(*entity))
throw std::runtime_error("addTextRenderer2D requires a CTransform2D on the entity");
auto font = CResourceAPI::resources().fonts().loadFont(rendererConfig.font);
auto shader = CResourceAPI::resources().shaders().get(rendererConfig.shader);
MeshMaterial2D mm2d;
auto material2D = std::make_unique<CMaterial2D>();
mm2d.material = material2D.get();
mm2d.material->m_color = rendererConfig.color;
mm2d.material->m_font = font;
mm2d.material->shader = static_cast<CShaderImplVulkan*>(shader);
mm2d.material->build();
auto mesh2D = std::make_unique<CMesh2D>();
mm2d.mesh = mesh2D.get();
mm2d.mesh->buildFromText(mm2d.material->m_font, rendererConfig.text);
std::vector mm2DVec = {mm2d};
auto model2D = std::make_unique<CModel2D>(mm2DVec);
CModel2D* model = model2D.get();
std::string prefixMat = mm2d.material->shader->getName() + mm2d.material->m_font->getAtlas()->getFilePath();
std::string keyMat = prefixMat + "_MAT2DTEXT";
std::string keyMeshes = prefixMat + std::to_string(std::hash<std::string>{}(rendererConfig.text)) + "_MESH2DTEXT";
std::string keyModel2D = keyMat + keyMeshes;
CResourceAPI::resources().materials2D().add(keyMat, std::move(material2D));
CResourceAPI::resources().meshes2D().add(keyMeshes, std::move(mesh2D));
CResourceAPI::resources().models2D().add(keyModel2D, std::move(model2D));
return reg.registry.emplace<CTextRenderer>(*entity, entity, model);
}
}
}
@@ -14,6 +14,7 @@
#include "Core/Component/Collider/CCollider2D.hpp"
#include "Core/Component/Geometry/CTransform2D.hpp"
#include "Core/Component/Graphics/CRenderer2D.hpp"
#include "Core/Component/Graphics/CTextRenderer.hpp"
#include "Core/Component/Light/CLight.hpp"
#include "Core/Component/Script/CScriptManager.hpp"
#include "glm/ext/vector_float3.hpp"
@@ -111,6 +112,13 @@ namespace CosmicUtils {
std::string shader = "ui";
};
struct TextRenderer2DConfig{
std::string text = "";
std::string shader = "ui_text";
glm::vec4 color = {1.0,1.0,1.0, 1.0};
std::string font = "assets/fonts/Arial";
};
// crée et initialise un CTransform sur une entité existante
CTransform& addTransform(CEntity& entity, TransformConfig& transformConfig);
@@ -144,6 +152,8 @@ namespace CosmicUtils {
CRenderer2D& addRenderer2D(CEntity& entity, Renderer2DConfig& rendererConfig);
CTextRenderer& addTextRenderer2D(CEntity& entity, TextRenderer2DConfig& rendererConfig);
};
}
#endif
@@ -1,5 +1,6 @@
#include "Identifier.hpp"
#include <fstream>
#include <iostream>
namespace CosmicUtils {
std::unordered_map<int, std::string> JsonKeyRegistry::m_idToKey = {};
std::unordered_map<std::string, int> JsonKeyRegistry::m_keyToId = {};
@@ -21,6 +22,7 @@ namespace CosmicUtils {
m_validator.validate(json);
return true;
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
return false;
}
}
+13 -2
View File
@@ -80,6 +80,9 @@ namespace CosmicUtils {
Light_CastShadow = 3078,
//Scripts
Script_names = 3079,
//2D
Scene_Entities2D = 104,
@@ -94,7 +97,8 @@ namespace CosmicUtils {
Component_Renderer2D = 2070,
Component_Camera2D = 2071,
Component_Collider2D = 2072,
Component_TextRenderer2D = 2073,
Component_Script2D = 2074,
// Transform
Transform_Position2D = 4011,
Transform_Rotation2D = 4012,
@@ -112,7 +116,14 @@ namespace CosmicUtils {
Camera_Zoom2D = 4031,
// Collider
Collider_Shape2D = 4041
Collider_Shape2D = 4041,
//Text2D
TextRenderer_Text2D = 4051,
TextRenderer_Shader2D = 4052,
TextRenderer_Color2D = 4053,
TextRenderer_Font2D = 4054
};
@@ -36,7 +36,7 @@ void CExampleScript::onCreate()
input.addOnMouseMove([](CEntity& e, glm::vec2 delta) {
auto& tr = e.getRegistry().registry.get<CTransform>(e.getHandle());
float sensitivity = 0.1f;
float sensitivity = 0.3f;
glm::quat yaw = glm::angleAxis(
glm::radians(-delta.x * sensitivity), glm::vec3(0,1,0));
glm::quat pitch = glm::angleAxis(
@@ -0,0 +1,49 @@
#include "QuitHandler.hpp"
#include "Core/Entity/CEntity.hpp"
#include "nlohmann/json_fwd.hpp"
#include "../CScriptRegister.hpp"
#include <csignal>
#include <iostream>
#include "Core/Component/Input/CInputManager.hpp"
#include "Core/Component/Geometry/CTransform.hpp"
void QuitHandler::start()
{
}
void QuitHandler::onCreate()
{
using namespace CosmicCore;
auto& reg = getEntity().getRegistry().registry;
// vérifie que l'entité a un CInputComponent
if (!reg.all_of<CInputManager>(getEntity().getHandle()))
reg.emplace<CInputManager>(getEntity().getHandle(), getEntity());
auto& input = reg.get<CInputManager>(getEntity().getHandle());
// bind les actions depuis le script
input.addOnGenericMouseLeftClick([](CEntity& entity){kill(getpid(), SIGTERM);
});
}
void QuitHandler::update()
{
}
void QuitHandler::destroy()
{
}
nlohmann::json QuitHandler::to_json()
{
return nlohmann::json();
}
QuitHandler::~QuitHandler(){
}
REGISTER_SCRIPT(QuitHandler);
@@ -0,0 +1,18 @@
#ifndef QUITHANDLER_HPP
#define QUITHANDLER_HPP
#include "Core/Entity/CEntity.hpp"
#include <Core/Component/Script/CAbstractScript.hpp>
class QuitHandler : public CosmicCore::CAbstractScript
{
public:
QuitHandler(CosmicCore::CEntity& entity, std::string name): CosmicCore::CAbstractScript(entity, name){};
void start() override;
void update() override;
void destroy() override;
void onCreate() override;
virtual nlohmann::json to_json() override;
virtual ~QuitHandler();
};
#endif