Rework API graphique Vulkan - EnTT pour ECS + Chargement modèle 3D assimp + SDL3 pour events input et fenetre + mesh texture camera transform ok + attention tous les assets nouveaus ne sont pas commités et il y a du code test en dur dans scene addentity + restructuration globale
This commit is contained in:
@@ -27,7 +27,7 @@ namespace CosmicCore {
|
||||
CAbstractComponent(CEntity& entity): m_owningEntity(entity){};
|
||||
virtual ~CAbstractComponent() = default;
|
||||
|
||||
CEntity& getEntity() {
|
||||
CEntity getEntity() const {
|
||||
return m_owningEntity;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef CABSTRACTCAMERA_HPP
|
||||
#define CABSTRACTCAMERA_HPP
|
||||
#include "../CAbstractComponent.hpp"
|
||||
namespace CosmicCore {
|
||||
class CAbstractCamera: CAbstractComponent
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
153
src/Engine/Core/Component/Camera/CCamera.hpp
Normal file
153
src/Engine/Core/Component/Camera/CCamera.hpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#ifndef CCAMERA_HPP
|
||||
#define CCAMERA_HPP
|
||||
|
||||
#include "../CAbstractComponent.hpp"
|
||||
//pour vulkan depth 0-1 (opengl [-1,1])
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "../../Graphics/API/VulkanImpl.hpp"
|
||||
#include "../Geometry/CTransform.hpp"
|
||||
namespace CosmicCore {
|
||||
|
||||
class CCamera : public CAbstractComponent {
|
||||
private:
|
||||
// paramètres de la caméra
|
||||
float m_fov = 45.0f;
|
||||
float m_near = 0.1f;
|
||||
float m_far = 1000.0f;
|
||||
float m_aspect = 16.0f / 9.0f;
|
||||
|
||||
// matrices calculées
|
||||
glm::mat4 m_view = glm::mat4(1.0f);
|
||||
glm::mat4 m_projection = glm::mat4(1.0f);
|
||||
|
||||
// GPU
|
||||
struct CameraUBOData {
|
||||
glm::mat4 view;
|
||||
glm::mat4 projection;
|
||||
};
|
||||
|
||||
std::array<VMABuffer, MAX_FRAMES_IN_FLIGHT> m_uniformBuffers;
|
||||
std::array<void*, MAX_FRAMES_IN_FLIGHT> m_mappedData{};
|
||||
std::array<ManagedDescriptorSet, MAX_FRAMES_IN_FLIGHT> m_descriptorSets;
|
||||
|
||||
void recalcProjection() {
|
||||
m_projection = glm::perspective(glm::radians(m_fov), m_aspect, m_near, m_far);
|
||||
// Vulkan a l'axe Y inversé par rapport à OpenGL
|
||||
m_projection[1][1] *= -1;
|
||||
}
|
||||
|
||||
public:
|
||||
CCamera(CEntity& entity) : CAbstractComponent(entity) {
|
||||
recalcProjection();
|
||||
}
|
||||
|
||||
~CCamera(){
|
||||
destroy();
|
||||
}
|
||||
|
||||
void setFov(float fov) {
|
||||
m_fov = fov;
|
||||
recalcProjection();
|
||||
}
|
||||
|
||||
void setAspect(float aspect) {
|
||||
m_aspect = aspect;
|
||||
recalcProjection();
|
||||
}
|
||||
|
||||
void setNearFar(float near, float far) {
|
||||
m_near = near;
|
||||
m_far = far;
|
||||
recalcProjection();
|
||||
}
|
||||
|
||||
// getters
|
||||
glm::mat4 getView(const CTransform& transform) const {
|
||||
glm::quat q = transform.getOrientation();
|
||||
glm::vec3 position = transform.getCenter();
|
||||
|
||||
// rotation inverse (conjugué du quaternion) + translation inverse
|
||||
glm::mat4 rotInverse = glm::toMat4(glm::conjugate(q));
|
||||
glm::mat4 transInverse = glm::translate(glm::mat4(1.0f), -position);
|
||||
|
||||
return rotInverse * transInverse;
|
||||
}
|
||||
glm::mat4 getProjection() const { return m_projection; }
|
||||
|
||||
// GPU
|
||||
void initUniformBuffer(VmaAllocator allocator) {
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
|
||||
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = sizeof(CameraUBOData);
|
||||
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
|
||||
VmaAllocationCreateInfo allocInfo{};
|
||||
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
|
||||
allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
|
||||
VmaAllocationInfo info{};
|
||||
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo,
|
||||
&m_uniformBuffers[i].buffer,
|
||||
&m_uniformBuffers[i].allocation,
|
||||
&info);
|
||||
m_mappedData[i] = info.pMappedData;
|
||||
|
||||
m_descriptorSets[i] = api->getDescriptorPoolManager().allocate(
|
||||
*api->getCameraLayout()
|
||||
);
|
||||
|
||||
vk::DescriptorBufferInfo descriptorBufferInfo{
|
||||
vk::Buffer(m_uniformBuffers[i].buffer),
|
||||
0,
|
||||
sizeof(CameraUBOData)
|
||||
};
|
||||
vk::WriteDescriptorSet descriptorWrite{
|
||||
*m_descriptorSets[i].set,
|
||||
0, 0, 1,
|
||||
vk::DescriptorType::eUniformBuffer,
|
||||
{}, &descriptorBufferInfo
|
||||
};
|
||||
static_cast<vk::raii::Device*>(api->getDevice())->updateDescriptorSets(descriptorWrite, {});
|
||||
}
|
||||
}
|
||||
|
||||
void destroyUniformBuffer(VmaAllocator allocator) {
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
api->getDescriptorPoolManager().free(m_descriptorSets[i]);
|
||||
vmaDestroyBuffer(allocator, m_uniformBuffers[i].buffer,
|
||||
m_uniformBuffers[i].allocation);
|
||||
}
|
||||
}
|
||||
|
||||
void updateUniformBuffer(uint32_t frameIndex, const CTransform& transform) {
|
||||
CameraUBOData data{ getView(transform), m_projection };
|
||||
memcpy(m_mappedData[frameIndex], &data, sizeof(data));
|
||||
}
|
||||
|
||||
vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) {
|
||||
return m_descriptorSets[frameIndex].set;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
|
||||
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
|
||||
api->destroyBuffer(m_uniformBuffers[i], api->getCurrentFrameIndex());
|
||||
api->destroyDescriptorSet(m_descriptorSets[i], api->getCurrentFrameIndex());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nlohmann::json to_json(){};
|
||||
};
|
||||
|
||||
} // namespace CosmicCore
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "CTransform.hpp"
|
||||
|
||||
#include "../../Graphics/API/VulkanImpl.hpp"
|
||||
#include "../Relationships/CRelationship.hpp"
|
||||
namespace CosmicCore
|
||||
{
|
||||
|
||||
@@ -22,7 +23,7 @@ namespace CosmicCore
|
||||
CTransform::CTransform(CEntity& entity) : CAbstractComponent(entity),
|
||||
m_center(0.0f, 0.0f, 0.0f),
|
||||
m_scale(1.0f, 1.0f, 1.0f),
|
||||
m_orientation(),
|
||||
m_orientation(glm::identity<glm::quat>()),
|
||||
m_observers() {
|
||||
calcTranslation();
|
||||
calcRotation();
|
||||
@@ -41,6 +42,11 @@ namespace CosmicCore
|
||||
calcTranformation();
|
||||
}
|
||||
|
||||
CTransform::~CTransform()
|
||||
{
|
||||
destroyUniformBuffer();
|
||||
}
|
||||
|
||||
glm::mat4 CTransform::getTranslation(void) const {
|
||||
return m_translation;
|
||||
}
|
||||
@@ -58,17 +64,18 @@ namespace CosmicCore
|
||||
}
|
||||
|
||||
glm::mat4 CTransform::getInheritedTransformation(void) const {
|
||||
/*const auto& entity = getEntity();
|
||||
if(entity)
|
||||
{
|
||||
if (entity->getParent().expired()) {
|
||||
return m_transformation;
|
||||
}
|
||||
else {
|
||||
auto p = entity->getParent().lock();
|
||||
return p->getTransform().getInheritedTransformation() * m_transformation;
|
||||
}
|
||||
}*/
|
||||
auto& registry = getEntity().getRegistry();
|
||||
|
||||
if (!registry().all_of<CRelationship>(*getEntity()))
|
||||
return m_transformation;
|
||||
|
||||
auto& rel = registry().get<CRelationship>(*getEntity());
|
||||
|
||||
if (rel.getParent() == entt::null)
|
||||
return m_transformation;
|
||||
|
||||
auto& parentTransform = registry().get<CTransform>(rel.getParent());
|
||||
return parentTransform.getInheritedTransformation() * m_transformation;
|
||||
}
|
||||
|
||||
glm::vec3 CTransform::getCenter(void) const {
|
||||
@@ -158,7 +165,7 @@ namespace CosmicCore
|
||||
}
|
||||
}
|
||||
|
||||
void CTransform::forward(glm::vec3 value) {
|
||||
void CTransform::forward(glm::vec3 value) {
|
||||
glm::vec3 relValue = m_orientation * value;
|
||||
m_center += relValue;
|
||||
calcTranslation();
|
||||
@@ -177,4 +184,47 @@ namespace CosmicCore
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
void CTransform::updateUniformBuffer(uint32_t frameIndex) {
|
||||
auto data{ getInheritedTransformation() }; // utilise la transformation héritée
|
||||
memcpy(m_mappedData[frameIndex], &data, sizeof(data));
|
||||
}
|
||||
|
||||
void CTransform::initUniformBuffer(VmaAllocator allocator) {
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
|
||||
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = sizeof(glm::mat4);
|
||||
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
|
||||
VmaAllocationCreateInfo allocInfo{};
|
||||
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
|
||||
allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
|
||||
VmaAllocationInfo info{};
|
||||
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo,
|
||||
&m_uniformBuffers[i].buffer,
|
||||
&m_uniformBuffers[i].allocation,
|
||||
&info);
|
||||
m_mappedData[i] = info.pMappedData;
|
||||
|
||||
m_descriptorSets[i] = api->getDescriptorPoolManager().allocate(api->getTransformLayout());
|
||||
|
||||
vk::DescriptorBufferInfo descriptorBufferInfo{vk::Buffer(m_uniformBuffers[i].buffer), 0, sizeof(glm::mat4)};
|
||||
vk::WriteDescriptorSet descriptorWrite{m_descriptorSets[i].set, 0, 0,1, vk::DescriptorType::eUniformBuffer, {}, &descriptorBufferInfo};
|
||||
static_cast<vk::raii::Device*>(api->getDevice())->updateDescriptorSets(descriptorWrite, {});
|
||||
}
|
||||
}
|
||||
|
||||
void CTransform::destroyUniformBuffer() {
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
|
||||
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
|
||||
api->destroyBuffer(m_uniformBuffers[i], api->getCurrentFrameIndex());
|
||||
api->destroyDescriptorSet(m_descriptorSets[i], api->getCurrentFrameIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include "../../Graphics/API/VMABuffer.hpp"
|
||||
#include "../../Graphics/API/ManagedDescriptorSet.hpp"
|
||||
|
||||
namespace CosmicCore
|
||||
{
|
||||
/**
|
||||
@@ -79,6 +82,10 @@ namespace CosmicCore
|
||||
* @brief Compute the full transformation of the object.
|
||||
*/
|
||||
void calcTranformation(void);
|
||||
|
||||
std::array<VMABuffer, MAX_FRAMES_IN_FLIGHT> m_uniformBuffers;
|
||||
std::array<void*, MAX_FRAMES_IN_FLIGHT> m_mappedData{};
|
||||
std::array<ManagedDescriptorSet, MAX_FRAMES_IN_FLIGHT> m_descriptorSets;
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -87,6 +94,13 @@ namespace CosmicCore
|
||||
*/
|
||||
CTransform(CEntity& m_entity);
|
||||
|
||||
~CTransform();
|
||||
|
||||
CTransform(CTransform&&) = default;
|
||||
CTransform& operator=(CTransform&&) = default;
|
||||
|
||||
CTransform(const CTransform&) = delete;
|
||||
CTransform& operator=(const CTransform&) = delete;
|
||||
/**
|
||||
* @brief CTransform's constructor.
|
||||
* @param[in, out] m_entity The entity to which the transform belongs.
|
||||
@@ -240,6 +254,17 @@ namespace CosmicCore
|
||||
t.setScale(glm::vec3(j["Scale"]["x"], j["Scale"]["y"], j["Scale"]["z"]));
|
||||
return t;
|
||||
};
|
||||
|
||||
void initUniformBuffer(VmaAllocator allocator);
|
||||
void destroyUniformBuffer();
|
||||
void updateUniformBuffer(uint32_t frameIndex);
|
||||
|
||||
VMABuffer& getUniformBuffer(uint32_t frameIndex) {
|
||||
return m_uniformBuffers[frameIndex];
|
||||
};
|
||||
vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) {
|
||||
return m_descriptorSets[frameIndex].set;
|
||||
};
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -6,7 +6,6 @@ namespace CosmicCore {
|
||||
{
|
||||
public:
|
||||
CAbstractRenderer(CEntity& e): CAbstractComponent(e){};
|
||||
virtual void render() = 0;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -1,78 +0,0 @@
|
||||
#ifndef CMODEL_HPP
|
||||
#define CMODEL_HPP
|
||||
|
||||
#include "Material/SMaterial.hpp"
|
||||
#include "Mesh/CMesh.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/**
|
||||
* @brief Class representing a 3D model.
|
||||
*/
|
||||
class CModel {
|
||||
private:
|
||||
/**
|
||||
* @brief The meshes, a vector which contains all the meshes of the object.
|
||||
*/
|
||||
std::vector<CMesh*> m_meshes;
|
||||
|
||||
/**
|
||||
* @brief A boolean representing the loading state of the model.
|
||||
*/
|
||||
bool m_loaded;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief CModel's default constructor, disabled.
|
||||
*/
|
||||
CModel(void) = delete;
|
||||
|
||||
/**
|
||||
* @brief CModel constructor.
|
||||
* @param meshes : The list of the meshes of the object.
|
||||
*/
|
||||
CModel(std::vector<CMesh*> meshes);
|
||||
|
||||
/**
|
||||
* @brief CModel's destructor.
|
||||
*/
|
||||
~CModel(void);
|
||||
|
||||
/**
|
||||
* @brief Load the model in the GPU.
|
||||
*/
|
||||
void load(void);
|
||||
|
||||
/**
|
||||
* @brief Render the model on the screen.
|
||||
* @param[in] model The transform of the object.
|
||||
* @param[in] view The view of the object.
|
||||
* @param[in] projection The projection of the object.
|
||||
* @param[in] lightPos The light's position.
|
||||
* @param[in] intensity The light's intensity.
|
||||
*/
|
||||
void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity);
|
||||
|
||||
/**
|
||||
* @brief Getter to the meshes of the model.
|
||||
* @return A vector which represent the list of meshes of the model, it's a direct reference to the member m_meshes.
|
||||
*/
|
||||
std::vector<CMesh*>& getMeshes(void);
|
||||
|
||||
/**
|
||||
* @brief Setter to the meshes.
|
||||
* @param[in] meshes The list of meshes to set to the model.
|
||||
*/
|
||||
void setMeshes(std::vector<CMesh*> meshes);
|
||||
|
||||
/**
|
||||
* @brief Getter to m_loaded member, say if the model is loaded or not.
|
||||
* @return A boolean representing the state of the model, loaded or not.
|
||||
*/
|
||||
bool isLoaded(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
3
src/Engine/Core/Component/Graphics/CRenderer.cpp
Normal file
3
src/Engine/Core/Component/Graphics/CRenderer.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "CRenderer.hpp"
|
||||
namespace CosmicCore {
|
||||
}
|
||||
18
src/Engine/Core/Component/Graphics/CRenderer.hpp
Normal file
18
src/Engine/Core/Component/Graphics/CRenderer.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef CTESTRENDERER_HPP
|
||||
#define CTESTRENDERER_HPP
|
||||
#include "CAbstractRenderer.hpp"
|
||||
#include "../../Graphics/Data/CModel.hpp"
|
||||
namespace CosmicCore {
|
||||
class CRenderer: public CAbstractRenderer
|
||||
{
|
||||
CModel* m_model = nullptr;
|
||||
public:
|
||||
CRenderer() = delete;
|
||||
CRenderer(CEntity& e): CAbstractRenderer(e){};
|
||||
CRenderer(CEntity& e, CModel* mod): CAbstractRenderer(e), m_model(mod){};
|
||||
nlohmann::json to_json() override{return nlohmann::json();};
|
||||
CModel* getModel(){return m_model;};
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#include "CTestRenderer.hpp"
|
||||
#include <iostream>
|
||||
namespace CosmicCore {
|
||||
void CTestRenderer::render()
|
||||
{
|
||||
int a = 2*25;
|
||||
int b = a +2;
|
||||
std::cout << b << std::endl;
|
||||
};
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifndef CTESTRENDERER_HPP
|
||||
#define CTESTRENDERER_HPP
|
||||
#include "CAbstractRenderer.hpp"
|
||||
|
||||
namespace CosmicCore {
|
||||
class CTestRenderer: public CAbstractRenderer
|
||||
{
|
||||
public:
|
||||
CTestRenderer() = delete;
|
||||
CTestRenderer(CEntity& e): CAbstractRenderer(e){};
|
||||
void render() override;
|
||||
nlohmann::json to_json(){return nlohmann::json();};
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef SMATERIAL_HPP
|
||||
#define SMATERIAL_HPP
|
||||
|
||||
#include "../Shader/CShader.hpp"
|
||||
#include "../Texture/CAbstractTexture.hpp"
|
||||
#include "SColor.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @file SMaterial.hpp
|
||||
* @brief File for the material struct.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The struct material.
|
||||
*/
|
||||
typedef struct SMaterial {
|
||||
/**
|
||||
* @brief List of textures for the material.
|
||||
*/
|
||||
std::vector<CAbstractTexture*> m_textures;
|
||||
|
||||
/**
|
||||
* @brief List of colors for the material.
|
||||
*/
|
||||
std::vector<SColor> m_colors;
|
||||
|
||||
/**
|
||||
* @brief The shader used to render.
|
||||
*/
|
||||
CShader* m_shader = nullptr;
|
||||
|
||||
~SMaterial() { for (unsigned int i = 0; i < m_textures.size(); ++i) {
|
||||
delete m_textures[i];
|
||||
} };
|
||||
} SMaterial;
|
||||
|
||||
#endif
|
||||
@@ -1,216 +0,0 @@
|
||||
#include "CMesh.hpp"
|
||||
|
||||
void CMesh::bindMaterial(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) {
|
||||
// Test the material.
|
||||
if (m_material == nullptr) {
|
||||
throw CLogicException("This mesh is not linked to a material.");
|
||||
}
|
||||
|
||||
// Active the shader.
|
||||
m_material->m_shader->use();
|
||||
|
||||
// Give the matrix to the shader.
|
||||
m_material->m_shader->setMat4("model", model);
|
||||
m_material->m_shader->setMat4("view", view);
|
||||
m_material->m_shader->setMat4("projection", projection);
|
||||
m_material->m_shader->setVec3("lightPos", lightPos);
|
||||
m_material->m_shader->setFloat("intensity", intensity);
|
||||
|
||||
// Counter for each Texture Type :
|
||||
unsigned int countTex[TEXTURE_TYPE_NUMBER];
|
||||
for (unsigned int i = 0; i < TEXTURE_TYPE_NUMBER; i++) {
|
||||
countTex[i] = 0;
|
||||
}
|
||||
|
||||
// For each texture in the material :
|
||||
for (unsigned int i = 0; i < m_material->m_textures.size(); i++) {
|
||||
|
||||
// Active the shader unit.
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
|
||||
// Retrieve texture name.
|
||||
std::string name;
|
||||
|
||||
switch (m_material->m_textures[i]->getType()) {
|
||||
case TEXTURE_DIFFUSE:
|
||||
name = "textureDiffuse" + std::to_string(countTex[0]);
|
||||
countTex[0]++;
|
||||
break;
|
||||
case TEXTURE_SPECULAR:
|
||||
name = "textureSpecular" + std::to_string(countTex[1]);
|
||||
countTex[1]++;
|
||||
break;
|
||||
case TEXTURE_NORMAL:
|
||||
name = "textureNormal" + std::to_string(countTex[2]);
|
||||
countTex[2]++;
|
||||
break;
|
||||
case TEXTURE_HEIGHT:
|
||||
name = "textureHeight" + std::to_string(countTex[3]);
|
||||
countTex[3]++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the uniform storage space of the shader.
|
||||
glUniform1i(glGetUniformLocation(m_material->m_shader->getId(), name.c_str()), i);
|
||||
|
||||
// And finally bind the texture.
|
||||
glBindTexture(GL_TEXTURE_2D, m_material->m_textures[i]->getId());
|
||||
}
|
||||
|
||||
// Always good practice to set everything back to defaults once configured.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
|
||||
|
||||
// Counter for each color Type :
|
||||
unsigned int countCol[COLOR_TYPE_NUMBER];
|
||||
for (unsigned int i = 0; i < COLOR_TYPE_NUMBER; i++) {
|
||||
countCol[i] = 0;
|
||||
}
|
||||
|
||||
// For each color in the material :
|
||||
for (unsigned int i = 0; i < m_material->m_colors.size(); i++) {
|
||||
|
||||
// Retrieve texture name.
|
||||
std::string name;
|
||||
|
||||
switch (m_material->m_colors[i].m_type) {
|
||||
case COLOR_DIFFUSE:
|
||||
name = "colorDiffuse" + std::to_string(countCol[0]);
|
||||
countCol[0]++;
|
||||
break;
|
||||
case COLOR_SPECULAR:
|
||||
name = "colorSpecular" + std::to_string(countCol[1]);
|
||||
countCol[1]++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Give the color as a vector 4.
|
||||
m_material->m_shader->setVec4(name, m_material->m_colors[i].m_vector);
|
||||
}
|
||||
|
||||
// Active the shader.
|
||||
//m_material->m_shader->use();
|
||||
}
|
||||
|
||||
CMesh::CMesh(void) :
|
||||
m_vertexes(),
|
||||
m_indexes(),
|
||||
m_material(nullptr),
|
||||
m_vertexBufferObject(0),
|
||||
m_elementBufferObject(0),
|
||||
m_vertexArrayObject(0) {
|
||||
}
|
||||
|
||||
CMesh::~CMesh(void) {
|
||||
// Delete the VAO.
|
||||
if (m_vertexArrayObject != 0) {
|
||||
glDeleteVertexArrays(1, &m_vertexArrayObject);
|
||||
}
|
||||
|
||||
if (m_material != nullptr)
|
||||
{
|
||||
delete m_material;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SVertex>& CMesh::getVertexes(void) {
|
||||
return m_vertexes;
|
||||
}
|
||||
|
||||
std::vector<unsigned int>& CMesh::getIndexes(void) {
|
||||
return m_indexes;
|
||||
}
|
||||
|
||||
SMaterial* CMesh::getMaterial(void) {
|
||||
return m_material;
|
||||
}
|
||||
|
||||
void CMesh::setMaterial(SMaterial* material) {
|
||||
m_material = material;
|
||||
}
|
||||
|
||||
void CMesh::setVertices(std::vector<SVertex> vertices)
|
||||
{
|
||||
m_vertexes = vertices;
|
||||
}
|
||||
|
||||
void CMesh::setIndexes(std::vector<unsigned int> indexes)
|
||||
{
|
||||
m_indexes = indexes;
|
||||
}
|
||||
|
||||
void CMesh::load(void) {
|
||||
if (m_vertexes.empty() || m_indexes.empty()) {
|
||||
throw CLogicException("This mesh do no contain vertex data.");
|
||||
}
|
||||
|
||||
// Create the VAO.
|
||||
glGenVertexArrays(1, &m_vertexArrayObject);
|
||||
|
||||
// Create the VBO.
|
||||
glGenBuffers(1, &m_vertexBufferObject);
|
||||
|
||||
// Create the EBO.
|
||||
glGenBuffers(1, &m_elementBufferObject);
|
||||
|
||||
|
||||
// Open the VAO.
|
||||
glBindVertexArray(m_vertexArrayObject);
|
||||
|
||||
// Open the VBO, and link it to the VAO.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferObject);
|
||||
|
||||
// Give the block of memory of vertexes vector (so, it works like a c list), and the struct is transparent du to their conception).
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertexes.size() * sizeof(SVertex), &m_vertexes[0], GL_STATIC_DRAW);
|
||||
|
||||
// Open the EBO, and link it to the VAO.
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBufferObject);
|
||||
|
||||
// Give the block of memory of indexes vector (so, it works like a c list), and the struct is transparent du to their conception).
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexes.size() * sizeof(unsigned int), &m_indexes[0], GL_STATIC_DRAW);
|
||||
|
||||
|
||||
// Set the vertex attribute pointers.
|
||||
// Vertex Positions.
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)0);
|
||||
// Vertex normals.
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_normal));
|
||||
// Vertex texture coords.
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_texCoords));
|
||||
// Vertex tangent.
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_tangent));
|
||||
// Vertex bitangent.
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_bitangent));
|
||||
|
||||
|
||||
// Unbind the VAO.
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void CMesh::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) {
|
||||
if (m_vertexArrayObject == 0) {
|
||||
throw CLogicException("This mesh is not loaded in GPU, you can not draw it.");
|
||||
}
|
||||
|
||||
// Bind the material.
|
||||
bindMaterial(model, view, projection, lightPos, intensity);
|
||||
|
||||
// Enable the vertex array object, so the shader use the vertex attribute in this vao.
|
||||
glBindVertexArray(m_vertexArrayObject);
|
||||
|
||||
// Render the triangles in the vertex array object.
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)m_indexes.size(), GL_UNSIGNED_INT, 0);
|
||||
|
||||
// Disable the vertex array object.
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
#ifndef CMESH_HPP
|
||||
#define CMESH_HPP
|
||||
|
||||
#include "../Material/SMaterial.hpp"
|
||||
#include "../Texture/CAbstractTexture.hpp"
|
||||
#include "SVertex.hpp"
|
||||
#include "../../../Controller/Exception/CLogicException.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <gl/glew.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/**
|
||||
* @file CMesh.hpp
|
||||
* @brief File for the mesh struct.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Class CMesh, used to represent a mesh, a set of vertex (which can be indexed), ready to be drawn.
|
||||
*/
|
||||
class CMesh {
|
||||
private:
|
||||
/**
|
||||
* @brief List of the vertices of the mesh.
|
||||
*/
|
||||
std::vector<SVertex> m_vertexes;
|
||||
|
||||
/**
|
||||
* @brief List of the indices of the mesh.
|
||||
*/
|
||||
std::vector<unsigned int> m_indexes;
|
||||
|
||||
/**
|
||||
* @brief A pointer to the material containing textures, colors and the shader used for the mesh.
|
||||
*/
|
||||
SMaterial* m_material;
|
||||
|
||||
/**
|
||||
* @brief The vertex buffer.
|
||||
*/
|
||||
unsigned int m_vertexBufferObject;
|
||||
|
||||
/**
|
||||
* @brief The index buffer.
|
||||
*/
|
||||
unsigned int m_elementBufferObject;
|
||||
|
||||
/**
|
||||
* @brief Vertex array object, all the data.
|
||||
*/
|
||||
unsigned int m_vertexArrayObject;
|
||||
|
||||
/**
|
||||
* @brief Apply material to use for drawing.
|
||||
* @param[in] model the model matrix.
|
||||
* @param[in] view the view matrix.
|
||||
* @param[in] projection the projection matrix.
|
||||
* @param[in] lightPos the position of the light source.
|
||||
* @param[in] intensity the intensity of the light source.
|
||||
*/
|
||||
void bindMaterial(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief the constructor.
|
||||
*/
|
||||
CMesh(void);
|
||||
|
||||
/**
|
||||
* @brief the destructor.
|
||||
*/
|
||||
~CMesh(void);
|
||||
|
||||
/**
|
||||
* @brief The vertex array getter.
|
||||
* @return std::vector<SVertex>&, A reference to the list of vertex.
|
||||
*/
|
||||
std::vector<SVertex>& getVertexes(void);
|
||||
|
||||
/**
|
||||
* @brief The index array getter.
|
||||
* @return std::vector<unsigned int>&, A reference to the list of index.
|
||||
*/
|
||||
std::vector<unsigned int>& getIndexes(void);
|
||||
|
||||
/**
|
||||
* @brief The material getter.
|
||||
* @return SMaterial*, the material.
|
||||
*/
|
||||
SMaterial* getMaterial(void);
|
||||
|
||||
/**
|
||||
* @brief The material setter.
|
||||
* @param[in] material the wanted material.
|
||||
*/
|
||||
void setMaterial(SMaterial* material);
|
||||
|
||||
/**
|
||||
* @brief The vertex setter.
|
||||
* @param[in] vertices list of the vertices to give to the GPU.
|
||||
*/
|
||||
void setVertices(std::vector<SVertex> vertices);
|
||||
|
||||
/**
|
||||
* @brief The indexes setter.
|
||||
* @param[in] indexes list of the indexes for the index buffer
|
||||
*/
|
||||
void setIndexes(std::vector<unsigned int> indexes);
|
||||
|
||||
/**
|
||||
* @brief Load the mesh in GPU.
|
||||
*/
|
||||
void load(void);
|
||||
|
||||
/**
|
||||
* @brief draw the mesh.
|
||||
* @param[in] model the model matrix.
|
||||
* @param[in] view the view matrix.
|
||||
* @param[in] projection the projection matrix.
|
||||
* @param[in] lightPos the position of the light source.
|
||||
* @param[in] intensity the intensity of the light source.
|
||||
*/
|
||||
void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef SVERTEX_HPP
|
||||
#define SVERTEX_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/**
|
||||
* @file SVertex.hpp
|
||||
* @brief File for the vertex struct.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief the struct Vertex, use to represent vertex and vertex attribute.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Position attribute.
|
||||
* 3D vector.
|
||||
*/
|
||||
glm::vec3 m_position;
|
||||
|
||||
/**
|
||||
* @brief Normal attribute.
|
||||
* 3D vector.
|
||||
*/
|
||||
glm::vec3 m_normal;
|
||||
|
||||
/**
|
||||
* @brief Texture coordinates attribute.
|
||||
* 2D vector.
|
||||
*/
|
||||
glm::vec2 m_texCoords;
|
||||
|
||||
/**
|
||||
* @brief Tangent attribute.
|
||||
* 3D vector.
|
||||
*/
|
||||
glm::vec3 m_tangent;
|
||||
|
||||
/**
|
||||
* @brief Bitangent attribute.
|
||||
* 3D vector (perpendicular to m_tangent vector).
|
||||
*/
|
||||
glm::vec3 m_bitangent;
|
||||
|
||||
// m_normal, m_tangent, m_bitangent are supposed to create a vector base to compute normal map.
|
||||
} SVertex;
|
||||
|
||||
#endif
|
||||
@@ -1,18 +0,0 @@
|
||||
#include "CAbstractTexture.hpp"
|
||||
|
||||
void CAbstractTexture::setId(unsigned int newId) {
|
||||
m_glId = newId;
|
||||
}
|
||||
|
||||
CAbstractTexture::CAbstractTexture(ETextureType type) :
|
||||
m_glId(0),
|
||||
m_type(type) {
|
||||
}
|
||||
|
||||
unsigned int CAbstractTexture::getId(void) {
|
||||
return m_glId;
|
||||
}
|
||||
|
||||
ETextureType CAbstractTexture::getType(void) {
|
||||
return m_type;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#ifndef CABSTRACTTEXTURE_HPP
|
||||
#define CABSTRACTTEXTURE_HPP
|
||||
|
||||
#define TEXTURE_TYPE_NUMBER 4
|
||||
|
||||
/**
|
||||
* @brief enum representing every type of texture available.
|
||||
*/
|
||||
enum ETextureType {
|
||||
TEXTURE_DIFFUSE,
|
||||
TEXTURE_SPECULAR,
|
||||
TEXTURE_NORMAL,
|
||||
TEXTURE_HEIGHT,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class representing a texture.
|
||||
*/
|
||||
class CAbstractTexture {
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief OpenGL ID.
|
||||
*/
|
||||
unsigned int m_glId;
|
||||
|
||||
/**
|
||||
* @brief The texture's type.
|
||||
*/
|
||||
ETextureType m_type;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Setter to the m_glId member.
|
||||
* @param newId : OpenGL id to set.
|
||||
*/
|
||||
void setId(unsigned int newId);
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief CAbstractTexture's default constructor, disabled.
|
||||
*/
|
||||
CAbstractTexture(void) = delete;
|
||||
|
||||
/**
|
||||
* @brief CAbstractTexture's constructor.
|
||||
* @param[in] type The texture's type.
|
||||
*/
|
||||
CAbstractTexture(ETextureType type);
|
||||
|
||||
virtual ~CAbstractTexture() {};
|
||||
|
||||
/**
|
||||
* @brief Getter to the m_glId member.
|
||||
* @return The m_glId member.
|
||||
*/
|
||||
unsigned int getId(void);
|
||||
|
||||
/**
|
||||
* @brief Getter to the texture's type.
|
||||
* @return The texture's type.
|
||||
*/
|
||||
ETextureType getType(void);
|
||||
|
||||
/**
|
||||
* @brief Load the texture in the GPU (uses only redefined function in the child classes).
|
||||
*/
|
||||
virtual void init(void) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "CImageTexture.hpp"
|
||||
|
||||
CImageTexture::CImageTexture(ETextureType type, std::string filePath) :
|
||||
CAbstractTexture(type),
|
||||
m_filePath(filePath) {
|
||||
}
|
||||
|
||||
std::string CImageTexture::getFilePath(void) {
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void CImageTexture::setFilePath(std::string filePath) {
|
||||
m_filePath = filePath;
|
||||
}
|
||||
|
||||
void CImageTexture::init(void) {
|
||||
// Read the image file.
|
||||
SDL_Surface* sdlSurface = IMG_Load(m_filePath.c_str());
|
||||
|
||||
if (sdlSurface == NULL) {
|
||||
throw CLibException(std::string("Image file \"") + m_filePath + std::string("\" can not be opened : ") + std::string(SDL_GetError()));
|
||||
}
|
||||
|
||||
// Create the id.
|
||||
unsigned int id;
|
||||
glGenTextures(1, &id);
|
||||
setId(id);
|
||||
|
||||
// Image format.
|
||||
GLenum internalFormat(0);
|
||||
GLenum externalFormat(0);
|
||||
|
||||
if (sdlSurface->format->BytesPerPixel == 3) {
|
||||
// We use RGB as internal format.
|
||||
internalFormat = GL_RGB;
|
||||
|
||||
// Choose the external format.
|
||||
if (sdlSurface->format->Rmask == 0xff)
|
||||
externalFormat = GL_RGB;
|
||||
else
|
||||
externalFormat = GL_BGR;
|
||||
}
|
||||
else if (sdlSurface->format->BytesPerPixel == 4) {
|
||||
// We use RGBA as internal format.
|
||||
internalFormat = GL_RGBA;
|
||||
|
||||
// Choose the external format.
|
||||
if (sdlSurface->format->Rmask == 0xff)
|
||||
externalFormat = GL_RGBA;
|
||||
else
|
||||
externalFormat = GL_BGRA;
|
||||
}
|
||||
else {
|
||||
SDL_FreeSurface(sdlSurface);
|
||||
throw CRuntimeException("Unknow image internal format.");
|
||||
}
|
||||
|
||||
// Lock the texture to use it.
|
||||
glBindTexture(GL_TEXTURE_2D, getId());
|
||||
|
||||
// Fill the GL texture.
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, sdlSurface->w, sdlSurface->h, 0, externalFormat, GL_UNSIGNED_BYTE, sdlSurface->pixels);
|
||||
|
||||
// Set filters : the near texture have a linear filter.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
// The far texture have a nearest filter, meaning no filter.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Unlock the texture.
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// Free the surface.
|
||||
SDL_FreeSurface(sdlSurface);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef CIMAGETEXTURE_HPP
|
||||
#define CIMAGETEXTURE_HPP
|
||||
|
||||
#include "../../../Controller/Exception/CLibException.hpp"
|
||||
#include "../../../Controller/Exception/CRuntimeException.hpp"
|
||||
#include "../../../Controller/Exception/CLogicException.hpp"
|
||||
#include "CAbstractTexture.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#ifdef WIN32
|
||||
#include <gl/glew.h>
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
class CImageTexture : public CAbstractTexture {
|
||||
private:
|
||||
// Path of the file.
|
||||
std::string m_filePath;
|
||||
public:
|
||||
CImageTexture(void) = delete;
|
||||
~CImageTexture(void) {};
|
||||
CImageTexture(ETextureType type, std::string filePath);
|
||||
std::string getFilePath(void);
|
||||
void setFilePath(std::string filePath);
|
||||
virtual void init(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
29
src/Engine/Core/Component/Relationships/CRelationship.hpp
Normal file
29
src/Engine/Core/Component/Relationships/CRelationship.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef CRELATIONSHIP_HPP
|
||||
#define CRELATIONSHIP_HPP
|
||||
|
||||
#include "../CAbstractComponent.hpp"
|
||||
#include "nlohmann/json_fwd.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace CosmicCore {
|
||||
class CRelationship : public CAbstractComponent{
|
||||
private:
|
||||
EntityId parent = entt::null;
|
||||
std::vector<EntityId> children;
|
||||
public:
|
||||
CRelationship(CEntity& entity): CAbstractComponent(entity){}
|
||||
CRelationship(CEntity& entity, EntityId p): CAbstractComponent(entity), parent(p){}
|
||||
CRelationship(CEntity& entity, std::vector<EntityId> childs): CAbstractComponent(entity), children(childs){}
|
||||
CRelationship(CEntity& entity, EntityId p, std::vector<EntityId> childs): CAbstractComponent(entity), parent(p), children(childs){}
|
||||
|
||||
nlohmann::json to_json(){return nlohmann::json();}
|
||||
void setParent(EntityId par){parent = par;}
|
||||
void addChild(EntityId child){children.emplace_back(child);}
|
||||
EntityId getParent(){return parent;}
|
||||
std::vector<EntityId>& getChildren(){return children;}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,86 +0,0 @@
|
||||
#include "CContext.hpp"
|
||||
|
||||
bool CContext::m_screenSaver = false;
|
||||
|
||||
void CContext::init(unsigned int sdlFlags, unsigned int imageFlags) {
|
||||
// Log initialisation.
|
||||
initLog();
|
||||
DEBUG_LOG(trace, "Kernel", "Context", "Log initialized!")
|
||||
|
||||
// SDL Initialization.
|
||||
DEBUG_LOG(trace, "Kernel", "Context", "SDL initialization...")
|
||||
if (SDL_Init(sdlFlags) < 0) {
|
||||
SDL_Quit();
|
||||
HandleException(CLibException(std::string("Unable to initialize SDL: ") + SDL_GetError()), true);
|
||||
}
|
||||
DEBUG_LOG(trace, "Kernel", "Context", "SDL initialized!")
|
||||
|
||||
|
||||
// SDL_Image Initialization.
|
||||
int initted = IMG_Init(imageFlags);
|
||||
DEBUG_LOG(trace, "Kernel", "Context", "SDL_Image initialization...")
|
||||
if ((initted & imageFlags) != imageFlags) {
|
||||
HandleException(CLibException(std::string("Unable to initialize SDL Image: ") + IMG_GetError()), true);
|
||||
}
|
||||
DEBUG_LOG(trace, "Kernel", "Context", "SDL_Image initialized!")
|
||||
|
||||
// SDL_TTF Initialization.
|
||||
DEBUG_LOG(trace, "Kernel", "Context", "SDL_TTF initialization...")
|
||||
if (TTF_Init() == -1) {
|
||||
HandleException(CLibException(std::string("Unable to initialize SDL TTF: ") + TTF_GetError()), true);
|
||||
}
|
||||
DEBUG_LOG(trace, "Kernel", "Context", "SDL_TTF initialized!")
|
||||
}
|
||||
|
||||
bool CContext::isScreenSaverEnable(void) {
|
||||
return m_screenSaver;
|
||||
}
|
||||
|
||||
void CContext::setScreenSaverEnable(bool newScreenSaver) {
|
||||
m_screenSaver = newScreenSaver;
|
||||
if (m_screenSaver) {
|
||||
SDL_EnableScreenSaver();
|
||||
}
|
||||
else {
|
||||
SDL_DisableScreenSaver();
|
||||
}
|
||||
}
|
||||
|
||||
void CContext::quit(void) {
|
||||
TTF_Quit();
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void CContext::initLog(void) {
|
||||
static const std::string COMMON_FMT("[%TimeStamp%][%Severity%]%Message%");
|
||||
|
||||
boost::log::register_simple_formatter_factory< boost::log::trivial::severity_level, char >("Severity");
|
||||
|
||||
// Output message to console.
|
||||
boost::log::add_console_log(
|
||||
std::cout,
|
||||
boost::log::keywords::format = COMMON_FMT,
|
||||
boost::log::keywords::auto_flush = true
|
||||
);
|
||||
|
||||
// Output message to file, rotates when file reached 1mb or at midnight every day. Each log file
|
||||
// is capped at 1mb and total is 50mb.
|
||||
boost::log::add_file_log(
|
||||
boost::log::keywords::file_name = LOG_FILE,
|
||||
boost::log::keywords::rotation_size = LOG_ROTATION_SIZE,
|
||||
boost::log::keywords::max_size = LOG_MAX_SIZE,
|
||||
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
|
||||
boost::log::keywords::format = COMMON_FMT,
|
||||
boost::log::keywords::auto_flush = true
|
||||
);
|
||||
|
||||
boost::log::add_common_attributes();
|
||||
|
||||
// Only output message with INFO or higher severity in Release.
|
||||
#ifndef _DEBUG
|
||||
boost::log::core::get()->set_filter(
|
||||
boost::log::trivial::severity >= boost::log::trivial::info
|
||||
);
|
||||
#endif
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#ifndef CCONTEXT_HPP
|
||||
#define CCONTEXT_HPP
|
||||
|
||||
#include "../Controller/Exception/CLibException.hpp"
|
||||
#include "../Controller/Exception/CExceptionManager.hpp"
|
||||
|
||||
#define BOOST_LOG_DYN_LINK 1
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/log/utility/setup.hpp>
|
||||
|
||||
#include <SDL.h>
|
||||
#ifdef WIN32
|
||||
#include <SDL_Image.h>
|
||||
#else
|
||||
#include <SDL_image.h>
|
||||
#endif
|
||||
#include <SDL_ttf.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_LOG(level, object, component, message) \
|
||||
BOOST_LOG_TRIVIAL(level) << "[" << object << "]" << "[" << component << "] : " << message;
|
||||
#else
|
||||
#define DEBUG_LOG(level, object, component, message)
|
||||
|
||||
#endif
|
||||
#define ERROR_LOG(level, object, component, message) \
|
||||
BOOST_LOG_TRIVIAL(level) << "[" << object << "]" << "[" << component << "] : " << message;
|
||||
|
||||
#define LOG_FILE "CosmicEngine_%3N.log"
|
||||
#define LOG_ROTATION_SIZE 1 * 1024 * 1024
|
||||
#define LOG_MAX_SIZE 50 * 1024 * 1024
|
||||
|
||||
/**
|
||||
* @file CContext.hpp
|
||||
* @brief File of CContext, a class reprensenting a SDL context, using SDL2 lib.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Class reprensenting a SDL context, using SDL2 lib.
|
||||
*/
|
||||
class CContext {
|
||||
private:
|
||||
// Say if the screenSaver is enabled.
|
||||
static bool m_screenSaver;
|
||||
|
||||
public:
|
||||
CContext(void) = delete;
|
||||
|
||||
static void init(unsigned int sdlFlags, unsigned int imageFlags);
|
||||
|
||||
static void quit(void);
|
||||
/**
|
||||
* @brief Say if the screen saver is enabled.
|
||||
* @return bool, a boolean which say the screen saver status.
|
||||
*/
|
||||
static bool isScreenSaverEnable(void);
|
||||
|
||||
/**
|
||||
* @brief Set the screen saver status.
|
||||
* @param[in] newScreenSaver New value of screen saver status.
|
||||
*/
|
||||
static void setScreenSaverEnable(bool newScreenSaver);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Init the logging system.
|
||||
*/
|
||||
static void initLog(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,119 +0,0 @@
|
||||
#ifndef CGAMEWINDOW_HPP
|
||||
#define CGAMEWINDOW_HPP
|
||||
|
||||
#include "CWindow.hpp"
|
||||
#include "../../Controller/Exception/CLibException.hpp"
|
||||
#include "../../Controller/Exception/CLogicException.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <SDL.h>
|
||||
#ifdef WIN32
|
||||
#include <SDL_Image.h>
|
||||
#else
|
||||
#include <SDL_image.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file CGameWindow.hpp
|
||||
* @brief File of CGameWindow, a class reprensenting a OpenGL Window, using SDL2 lib.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Class reprensenting a OpenGL Window, using SDL2 lib.
|
||||
*/
|
||||
class CGameWindow : public CWindow {
|
||||
private:
|
||||
// Say if the mouse is grabbed.
|
||||
bool m_grabCursor;
|
||||
|
||||
// Say if the mouse is in relative mode.
|
||||
bool m_relativeCursor;
|
||||
|
||||
// The anti-aliasing.
|
||||
unsigned char m_msaa;
|
||||
|
||||
public:
|
||||
CGameWindow(void) = delete;
|
||||
CGameWindow(const CGameWindow& param) = delete;
|
||||
CGameWindow& operator=(const CGameWindow& param) = delete;
|
||||
|
||||
/**
|
||||
* @brief The default constructor, build a non visible window with size of widthxheight.
|
||||
* @param[in] title The title of the window.
|
||||
* @param[in] iconPath The iconPath of the window.
|
||||
* @param[in] width The width of the window.
|
||||
* @param[in] height The height of the window.
|
||||
* @param[in] resizable The define the resizable property of the window.
|
||||
* @param[in] fullscreen The define the fullscreen property of the window.
|
||||
* @param[in] sdlFlags Allow to add SDL flags.
|
||||
* @param[in] imageFlags Allow to add SDL_Image flags.
|
||||
*/
|
||||
CGameWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen);
|
||||
|
||||
CGameWindow(std::string title, SDL_Window* window);
|
||||
|
||||
/**
|
||||
* @brief The destructor.
|
||||
*/
|
||||
~CGameWindow(void);
|
||||
|
||||
/**
|
||||
* @brief Say if the mouse is grabbed.
|
||||
* @return bool, a boolean which say the mouse grab status.
|
||||
*/
|
||||
bool isCursorGrabbed(void) const;
|
||||
|
||||
/**
|
||||
* @brief Set the mouse grab status.
|
||||
* @param[in] newMouseGrab New value of mouse grab status.
|
||||
*/
|
||||
void setCursorGrabbed(bool newMouseGrab);
|
||||
|
||||
/**
|
||||
* @brief Say if the mouse is relative.
|
||||
* @return bool, a boolean which say the mouse relative status.
|
||||
*/
|
||||
bool isCursorRelative(void) const;
|
||||
|
||||
/**
|
||||
* @brief Set the mouse relative status, if true, the cursor grabb is also forced to true if not.
|
||||
* @param[in] newMouseRelative New value of mouse relative status.
|
||||
*/
|
||||
void setCursorRelative(bool newMouseRelative);
|
||||
|
||||
/**
|
||||
* @brief Get the MSAA value.
|
||||
* @return unsigned char, the MSAA value.
|
||||
*/
|
||||
unsigned char getAntiAliasing(void) const;
|
||||
|
||||
/**
|
||||
* @brief Set the MSAA of the window.
|
||||
* @param[in] newMsaa New value of MSAA, must be 2, 4, 8, 16.
|
||||
* @post if newMsaa not equal 2, 4, 8, 16, the value is set to 0.
|
||||
*/
|
||||
void setAntiAliasing(unsigned char newMsaa);
|
||||
|
||||
/**
|
||||
* @brief Launched before the creation of the window, usefull for setting OpenGL attribute.
|
||||
*/
|
||||
virtual void preinitialization();
|
||||
|
||||
/**
|
||||
* @brief Launched after the creation of the window, usefull for setting others attribute.
|
||||
*/
|
||||
virtual void postinitialization();
|
||||
|
||||
/**
|
||||
* @brief Get the OpenGLContext of the window.
|
||||
* @return SDL_GLContext the OpenGL context of the window, in SDL2 format, we need to destroy it after using, with SDL_GL_DeleteContext(SDL_GLContext);.
|
||||
* @post Give a error if the window is not initialized.
|
||||
*/
|
||||
SDL_GLContext getOpenGLContext(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,204 +0,0 @@
|
||||
#ifndef CWINDOW_HPP
|
||||
#define CWINDOW_HPP
|
||||
|
||||
#include "../../Controller/Exception/CLibException.hpp"
|
||||
#include "../../Controller/Exception/CLogicException.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <SDL.h>
|
||||
#ifdef WIN32
|
||||
#include <SDL_Image.h>
|
||||
#else
|
||||
#include <SDL_image.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file CWindow.hpp
|
||||
* @brief File of CWindow, a class reprensenting a Window, using SDL2 lib.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Class reprensenting a Window, using SDL2 lib.
|
||||
*/
|
||||
class CWindow {
|
||||
private:
|
||||
// The title of the window.
|
||||
std::string m_title;
|
||||
|
||||
// The path to the icon.
|
||||
std::string m_iconPath;
|
||||
|
||||
// First is the width, second is the height.
|
||||
std::pair<unsigned int, unsigned int> m_size;
|
||||
|
||||
// Say if the window is fullscreen.
|
||||
bool m_fullscreen;
|
||||
|
||||
// Say if the window is visible.
|
||||
bool m_visible;
|
||||
|
||||
// Say if the window is resizable.
|
||||
bool m_resizable;
|
||||
|
||||
// SDL flags for creating the window.
|
||||
unsigned int m_sdlFlags;
|
||||
|
||||
// The pointer to the window.
|
||||
SDL_Window* m_pwindow;
|
||||
|
||||
public:
|
||||
CWindow(void) = delete;
|
||||
CWindow(const CWindow& param) = delete;
|
||||
CWindow& operator=(const CWindow& param) = delete;
|
||||
|
||||
/**
|
||||
* @brief The default constructor, build a non visible window with size of widthxheight.
|
||||
* @param[in] title The title of the window.
|
||||
* @param[in] iconPath The iconPath of the window.
|
||||
* @param[in] width The width of the window.
|
||||
* @param[in] height The height of the window.
|
||||
* @param[in] sdlFlags Allow to add SDL flags.
|
||||
*/
|
||||
CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, unsigned int sdlFlags);
|
||||
|
||||
/**
|
||||
* @brief The default constructor, build a non visible window with size of widthxheight.
|
||||
* @param[in] title The title of the window.
|
||||
* @param[in] The window to embed the game in.
|
||||
* @param[in] sdlFlags Allow to add SDL flags.
|
||||
* @param[in] imageFlags Allow to add SDL_Image flags.
|
||||
*/
|
||||
CWindow(std::string title, SDL_Window* window, unsigned int sdlFlags, unsigned int imageFlags);
|
||||
|
||||
|
||||
/**
|
||||
* @brief The destructor.
|
||||
*/
|
||||
~CWindow(void);
|
||||
|
||||
/**
|
||||
* @brief Get the SDL_Window* of the window.
|
||||
* @return SDL_Window The window, in SDL2 format.
|
||||
*/
|
||||
SDL_Window* getWindow(void);
|
||||
|
||||
void setWindow(SDL_Window* window){m_pwindow = window; };
|
||||
/**
|
||||
* @brief Say if the window is fullscreen.
|
||||
* @return bool, a boolean which say the fullscreen status.
|
||||
*/
|
||||
bool isFullscreen(void) const;
|
||||
|
||||
/**
|
||||
* @brief Set the fullscreen status.
|
||||
* @param[in] newFullscreen New value of fullscreen status.
|
||||
*/
|
||||
void setFullscreen(bool newFullscreen);
|
||||
|
||||
/**
|
||||
* @brief Say if the window is visible.
|
||||
* @return bool, a boolean which say the visible status.
|
||||
*/
|
||||
bool isVisible(void) const;
|
||||
|
||||
/**
|
||||
* @brief Set the visibility status.
|
||||
* @param[in] newVisible New value of visibility status.
|
||||
*/
|
||||
void setVisible(bool newVisible);
|
||||
|
||||
/**
|
||||
* @brief Get the window icon path.
|
||||
* @return std::string, the path.
|
||||
*/
|
||||
std::string getIconPath(void) const;
|
||||
|
||||
/**
|
||||
* @brief Get the window title.
|
||||
* @return std::string, the title.
|
||||
*/
|
||||
std::string getTitle(void) const;
|
||||
|
||||
/**
|
||||
* @brief Change the window title.
|
||||
* @param[in] newTitle New title of the window.
|
||||
*/
|
||||
void setTitle(std::string newTitle);
|
||||
|
||||
/**
|
||||
* @brief Change the window icon.
|
||||
* @param[in] newIconPath New icon path of the window.
|
||||
*/
|
||||
void setIconPath(std::string newIconPath);
|
||||
|
||||
/**
|
||||
* @brief Get the window width.
|
||||
* @return unsigned int, the window width (in pixel).
|
||||
*/
|
||||
unsigned int getWidth(void) const;
|
||||
|
||||
/**
|
||||
* @brief Get the window height.
|
||||
* @return unsigned int, the window height (in pixel).
|
||||
*/
|
||||
unsigned int getHeight(void) const;
|
||||
|
||||
/**
|
||||
* @brief Get the window size.
|
||||
* @return std::pair<unsigned int, unsigned int>, the window size (in pixel).
|
||||
*/
|
||||
std::pair<unsigned int, unsigned int> getSize(void) const;
|
||||
|
||||
/**
|
||||
* @brief Set the window size.
|
||||
* @param[in] newSize New value of window size.
|
||||
*/
|
||||
void setSize(std::pair<unsigned int, unsigned int> newSize);
|
||||
|
||||
/**
|
||||
* @brief Set the window size.
|
||||
* @param[in] newWidth New value of window width.
|
||||
* @param[in] newHeight New value of window height.
|
||||
*/
|
||||
void setSize(unsigned int newWidth, unsigned int newHeight);
|
||||
|
||||
/**
|
||||
* @brief Say if the window is resizable.
|
||||
* @return bool, a boolean which say the resizable status.
|
||||
*/
|
||||
bool isResizable(void) const;
|
||||
|
||||
/**
|
||||
* @brief Set the rezisable status.
|
||||
* @param[in] newResizable New value of rezisable status.
|
||||
*/
|
||||
void setResizable(bool newResizable);
|
||||
|
||||
/**
|
||||
* @brief Say if the window is initialized.
|
||||
* @return bool, a boolean which say the initialization status.
|
||||
*/
|
||||
bool isInitialized(void) const;
|
||||
|
||||
/**
|
||||
* @brief Initialize the window.
|
||||
* @post Give a error if the windows is already init.
|
||||
*/
|
||||
void initialization();
|
||||
|
||||
/**
|
||||
* @brief Launched before the creation of the window, usefull for setting OpenGL attribute.
|
||||
*/
|
||||
virtual void preinitialization() = 0;
|
||||
|
||||
/**
|
||||
* @brief Launched after the creation of the window, usefull for setting others attribute.
|
||||
*/
|
||||
virtual void postinitialization() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,20 +6,20 @@
|
||||
namespace CosmicCore
|
||||
{
|
||||
|
||||
CEntity::CEntity(ECManager& registry, EntityId handle) : CSerializable(), m_registryReference(registry), m_handle(handle)
|
||||
CEntity::CEntity(EntityComponentManager& registry, EntityId handle, CScene* scene) : CSerializable(), m_scene(scene), m_registryReference(registry), m_handle(handle)
|
||||
{
|
||||
}
|
||||
|
||||
CEntity::CEntity(const CEntity& cop): m_registryReference(cop.m_registryReference), m_handle(cop.m_handle){
|
||||
CEntity::CEntity(const CEntity& cop): m_scene(cop.m_scene), m_registryReference(cop.m_registryReference), m_handle(cop.m_handle){
|
||||
|
||||
}
|
||||
|
||||
std::weak_ptr<CScene> CEntity::getScene()
|
||||
CScene* CEntity::getScene()
|
||||
{
|
||||
return m_scene;
|
||||
}
|
||||
|
||||
void CEntity::setScene(std::weak_ptr<CScene> s)
|
||||
void CEntity::setScene(CScene* s)
|
||||
{
|
||||
m_scene = s;
|
||||
}
|
||||
|
||||
@@ -4,24 +4,22 @@
|
||||
#include <forward_list>
|
||||
#include <memory>
|
||||
#include "../Utils/CSerializable.hpp"
|
||||
#include <entt/entt.hpp>
|
||||
#include "../Systems/EntityComponentManager.hpp"
|
||||
|
||||
namespace CosmicCore
|
||||
{
|
||||
class CScene;
|
||||
|
||||
class CEntity : public CSerializable {
|
||||
using ECManager = entt::registry;
|
||||
using EntityId = entt::entity;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief A pointer to the scene containing the entity.
|
||||
*/
|
||||
std::weak_ptr<CScene> m_scene;
|
||||
CScene* m_scene;
|
||||
|
||||
ECManager& m_registryReference;
|
||||
EntityComponentManager& m_registryReference;
|
||||
|
||||
EntityId m_handle;
|
||||
|
||||
@@ -32,7 +30,7 @@ namespace CosmicCore
|
||||
*/
|
||||
CEntity() = delete;
|
||||
|
||||
CEntity(ECManager& registry, EntityId handle);
|
||||
CEntity(EntityComponentManager& registry, EntityId handle, CScene* scene);
|
||||
|
||||
CEntity(const CEntity& cop);
|
||||
/**
|
||||
@@ -49,26 +47,34 @@ namespace CosmicCore
|
||||
template<typename compType, typename... Args>
|
||||
void addComponent(std::forward_list<Args...> args)
|
||||
{
|
||||
m_registryReference.emplace<compType>(m_handle, *this, args);
|
||||
m_registryReference().emplace<compType>(m_handle, *this, args);
|
||||
}
|
||||
|
||||
template<typename compType>
|
||||
void addComponent()
|
||||
{
|
||||
m_registryReference.emplace<compType>(m_handle, *this);
|
||||
m_registryReference().emplace<compType>(m_handle, *this);
|
||||
}
|
||||
|
||||
EntityComponentManager& getRegistry(){return m_registryReference;};
|
||||
|
||||
/**
|
||||
* @brief Getter to the entity's scene.
|
||||
* @return The pointer m_scene.
|
||||
*/
|
||||
std::weak_ptr<CScene> getScene();
|
||||
CScene* getScene();
|
||||
|
||||
/**
|
||||
* @brief Setter of the scene.
|
||||
* @param[in, out] e The scene in which the entity will be set.
|
||||
*/
|
||||
void setScene(std::weak_ptr<CScene> s);
|
||||
void setScene(CScene* s);
|
||||
|
||||
EntityId operator*(){
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
//TODO GET COMPONENT VECTOR OF SPECIFIC TYPE ? si utile
|
||||
|
||||
nlohmann::json to_json();
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "CException.hpp"
|
||||
|
||||
void CException::makeFullMessage(void) {
|
||||
std::stringstream sstring;
|
||||
/*std::stringstream sstring;
|
||||
sstring << "Error : " << m_code << std::endl << m_message << std::endl;
|
||||
boost::stacktrace::stacktrace stacktrace = boost::stacktrace::stacktrace();
|
||||
std::size_t frames = stacktrace.size();
|
||||
@@ -17,7 +17,7 @@ void CException::makeFullMessage(void) {
|
||||
sstring << " (" << stacktrace[i].address() << ')' << std::endl;
|
||||
}
|
||||
|
||||
m_fullMessage = sstring.str();
|
||||
m_fullMessage = sstring.str();*/
|
||||
}
|
||||
|
||||
CException::CException(void) noexcept :
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <boost/stacktrace.hpp>
|
||||
|
||||
/**
|
||||
* @file CException.hpp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "CExceptionManager.hpp"
|
||||
|
||||
void HandleException(const CException& e, bool fatal) {
|
||||
/*void HandleException(const CException& e, bool fatal) {
|
||||
|
||||
std::string windowMessage(e.getMessage());
|
||||
windowMessage += "\nException reported in \"";
|
||||
@@ -31,4 +31,4 @@ void HandleException(const CException& e, bool fatal) {
|
||||
// It's fatal, so we quit.
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -2,10 +2,6 @@
|
||||
#define CEXCEPTIONMANAGER_HPP
|
||||
|
||||
#include "CException.hpp"
|
||||
#include "../File/CFileManager.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <SDL.h>
|
||||
|
||||
/**
|
||||
* @file CExceptionManager.hpp
|
||||
|
||||
1
src/Engine/Core/Graphics/API/Constants.hpp
Normal file
1
src/Engine/Core/Graphics/API/Constants.hpp
Normal file
@@ -0,0 +1 @@
|
||||
#define MAX_FRAMES_IN_FLIGHT 2
|
||||
54
src/Engine/Core/Graphics/API/DeletionQueue.hpp
Normal file
54
src/Engine/Core/Graphics/API/DeletionQueue.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef DELETIONQUEUE_HPP
|
||||
#define DELETIONQUEUE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <deque>
|
||||
#include <array>
|
||||
#include "Constants.hpp"
|
||||
|
||||
class DeletionQueue {
|
||||
private:
|
||||
// une queue par frame + une queue immédiate
|
||||
std::array<std::deque<std::function<void()>>, MAX_FRAMES_IN_FLIGHT> m_frameQueues;
|
||||
std::deque<std::function<void()>> m_immediateQueue;
|
||||
|
||||
public:
|
||||
// destruction différée - attendre MAX_FRAMES_IN_FLIGHT frames
|
||||
void push(uint32_t currentFrame, std::function<void()>&& func) {
|
||||
// on enfile dans la frame "opposée" pour attendre un cycle complet
|
||||
uint32_t targetFrame = (currentFrame + MAX_FRAMES_IN_FLIGHT - 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
m_frameQueues[targetFrame].push_back(std::move(func));
|
||||
}
|
||||
|
||||
// destruction immédiate - device.waitIdle() doit avoir été appelé avant
|
||||
void pushImmediate(std::function<void()>&& func) {
|
||||
m_immediateQueue.push_back(std::move(func));
|
||||
}
|
||||
|
||||
// appelé au début de chaque frame - détruit les ressources de cette frame
|
||||
void flush(uint32_t frameIndex) {
|
||||
auto& queue = m_frameQueues[frameIndex];
|
||||
while (!queue.empty()) {
|
||||
queue.front()();
|
||||
queue.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
// appelé à la fermeture - détruit tout
|
||||
void flushAll() {
|
||||
// vider toutes les frame queues
|
||||
for (auto& queue : m_frameQueues) {
|
||||
while (!queue.empty()) {
|
||||
queue.front()();
|
||||
queue.pop_front();
|
||||
}
|
||||
}
|
||||
// vider la queue immédiate
|
||||
while (!m_immediateQueue.empty()) {
|
||||
m_immediateQueue.front()();
|
||||
m_immediateQueue.pop_front();
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
10
src/Engine/Core/Graphics/API/GraphicsAPI.cpp
Normal file
10
src/Engine/Core/Graphics/API/GraphicsAPI.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "GraphicsAPI.hpp"
|
||||
#include "VulkanImpl.hpp"
|
||||
#include <memory>
|
||||
|
||||
std::unique_ptr<GraphicsAPI> GraphicsAPI::impl = nullptr;
|
||||
|
||||
void GraphicsAPI::initAPI(){
|
||||
//todo check config for chosen api
|
||||
impl = std::make_unique<VulkanImpl>();
|
||||
}
|
||||
33
src/Engine/Core/Graphics/API/GraphicsAPI.hpp
Normal file
33
src/Engine/Core/Graphics/API/GraphicsAPI.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef GRAPHICAPI_HPP
|
||||
#define GRAPHICAPI_HPP
|
||||
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <memory>
|
||||
#include "../Shader/CShadersManager.hpp"
|
||||
#include "../Data/CResourceManager.hpp"
|
||||
|
||||
enum class GraphicsBackend{
|
||||
Vulkan,
|
||||
OpenGL,
|
||||
Metal
|
||||
};
|
||||
|
||||
class GraphicsAPI{
|
||||
static std::unique_ptr<GraphicsAPI> impl;
|
||||
protected:
|
||||
CShadersManager shadermanager;
|
||||
CResourceManager resourceManager;
|
||||
public:
|
||||
static void initAPI();
|
||||
static std::unique_ptr<GraphicsAPI>& getAPI(){return impl;};
|
||||
virtual void init(SDL_Window* window) = 0;
|
||||
virtual void cleanup() = 0;
|
||||
virtual ~GraphicsAPI(){};
|
||||
virtual void* getDevice() = 0;
|
||||
virtual void drawFrame() = 0;
|
||||
CShadersManager& getShaderManager(){return shadermanager;};
|
||||
CResourceManager& getResourceManager(){return resourceManager;};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
21
src/Engine/Core/Graphics/API/ManagedDescriptorSet.hpp
Normal file
21
src/Engine/Core/Graphics/API/ManagedDescriptorSet.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef MANAGEDDESCRIPTORSET_HPP
|
||||
#define MANAGEDDESCRIPTORSET_HPP
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
#define MAX_FRAMES_IN_FLIGHT 2
|
||||
|
||||
struct ManagedDescriptorSet {
|
||||
vk::raii::DescriptorSet set = nullptr;
|
||||
VkDescriptorPool ownerPool = VK_NULL_HANDLE;
|
||||
|
||||
ManagedDescriptorSet() = default;
|
||||
ManagedDescriptorSet(ManagedDescriptorSet&&) = default;
|
||||
ManagedDescriptorSet& operator=(ManagedDescriptorSet&&) = default;
|
||||
|
||||
ManagedDescriptorSet(const ManagedDescriptorSet&) = delete;
|
||||
ManagedDescriptorSet& operator=(const ManagedDescriptorSet&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
15
src/Engine/Core/Graphics/API/VMABuffer.hpp
Normal file
15
src/Engine/Core/Graphics/API/VMABuffer.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef VMABUFFER_HPP
|
||||
#define VMABUFFER_HPP
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
|
||||
typedef struct vmaBufferStruct {
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
VmaAllocation allocation = VK_NULL_HANDLE;
|
||||
|
||||
void destroy(VmaAllocator allocator) {
|
||||
vmaDestroyBuffer(allocator, buffer, allocation);
|
||||
}
|
||||
}VMABuffer;
|
||||
|
||||
#endif
|
||||
2
src/Engine/Core/Graphics/API/VMAUsage.cpp
Normal file
2
src/Engine/Core/Graphics/API/VMAUsage.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#define VMA_IMPLEMENTATION
|
||||
#include "vk_mem_alloc.h"
|
||||
789
src/Engine/Core/Graphics/API/VulkanImpl.cpp
Normal file
789
src/Engine/Core/Graphics/API/VulkanImpl.cpp
Normal file
@@ -0,0 +1,789 @@
|
||||
#include "VulkanImpl.hpp"
|
||||
#include <SDL3/SDL_events.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
#include "../../Kernel/CKernel.hpp"
|
||||
#include "DeletionQueue.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
static uint32_t chooseSwapMinImageCount(vk::SurfaceCapabilitiesKHR const &surfaceCapabilities)
|
||||
{
|
||||
auto minImageCount = std::max(3u, surfaceCapabilities.minImageCount);
|
||||
if ((0 < surfaceCapabilities.maxImageCount) && (surfaceCapabilities.maxImageCount < minImageCount))
|
||||
{
|
||||
minImageCount = surfaceCapabilities.maxImageCount;
|
||||
}
|
||||
return minImageCount;
|
||||
}
|
||||
|
||||
static vk::SurfaceFormatKHR chooseSwapSurfaceFormat(std::vector<vk::SurfaceFormatKHR> const &availableFormats)
|
||||
{
|
||||
assert(!availableFormats.empty());
|
||||
const auto formatIt = std::ranges::find_if(
|
||||
availableFormats,
|
||||
[](const auto &format) { return format.format == vk::Format::eB8G8R8A8Srgb && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear; });
|
||||
return formatIt != availableFormats.end() ? *formatIt : availableFormats[0];
|
||||
}
|
||||
|
||||
static vk::PresentModeKHR chooseSwapPresentMode(const std::vector<vk::PresentModeKHR> &availablePresentModes)
|
||||
{
|
||||
assert(std::ranges::any_of(availablePresentModes, [](auto presentMode) { return presentMode == vk::PresentModeKHR::eFifo; }));
|
||||
return std::ranges::any_of(availablePresentModes,
|
||||
[](const vk::PresentModeKHR value) { return vk::PresentModeKHR::eMailbox == value; }) ?
|
||||
vk::PresentModeKHR::eMailbox :
|
||||
vk::PresentModeKHR::eFifo;
|
||||
}
|
||||
|
||||
vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR &capabilities, SDL_Window* window)
|
||||
{
|
||||
if (capabilities.currentExtent.width != 0xFFFFFFFF)
|
||||
{
|
||||
return capabilities.currentExtent;
|
||||
}
|
||||
int width, height;
|
||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
|
||||
return {
|
||||
std::clamp<uint32_t>(width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width),
|
||||
std::clamp<uint32_t>(height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height)};
|
||||
}
|
||||
|
||||
void VulkanImpl::init(SDL_Window* window){
|
||||
m_window = window;
|
||||
createInstance();
|
||||
createSurface();
|
||||
pickPhysicalDevice();
|
||||
createLogicalDevice();
|
||||
//getShaders after creating device
|
||||
shadermanager.create();
|
||||
shadermanager.compile();
|
||||
createSwapChain();
|
||||
createImageViews();
|
||||
createDescriptorSetLayouts();
|
||||
//createGraphicsPipeline();
|
||||
createDepthResources();
|
||||
createCommandPool();
|
||||
createDescriptorPool();
|
||||
createDefaultTexture();
|
||||
createCommandBuffer();
|
||||
createSyncObjects();
|
||||
}
|
||||
|
||||
void VulkanImpl::cleanup(){
|
||||
device.waitIdle();
|
||||
// 1. détruire les ressources dans le ResourceManager
|
||||
// (buffers, pipelines, descriptor sets...)
|
||||
m_deletionQueue.flushAll();
|
||||
|
||||
CosmicCore::CKernel::m_kernel->cleanup();
|
||||
|
||||
resourceManager.cleanup();
|
||||
shadermanager.cleanup();
|
||||
|
||||
|
||||
m_deletionQueue.flushAll();
|
||||
|
||||
// 2. sync objects
|
||||
inFlightFences.clear();
|
||||
renderFinishedSemaphores.clear();
|
||||
presentCompleteSemaphores.clear();
|
||||
|
||||
// 3. command buffers puis command pool
|
||||
commandBuffers.clear();
|
||||
commandPool = nullptr;
|
||||
|
||||
// 4. swapchain
|
||||
cleanupSwapChain();
|
||||
|
||||
// descriptor set layouts + pipeline layout avant le device
|
||||
defaultPipelineLayoutInfo = nullptr;
|
||||
cameraLayout = nullptr;
|
||||
transformLayout = nullptr;
|
||||
materialLayout = nullptr;
|
||||
|
||||
VmaTotalStatistics stats;
|
||||
vmaCalculateStatistics(allocator, &stats);
|
||||
if (stats.total.statistics.allocationCount > 0) {
|
||||
std::cout << "VMA: " << stats.total.statistics.allocationCount
|
||||
<< " allocations non libérées !" << std::endl;
|
||||
std::cout << "VMA: " << stats.total.statistics.allocationBytes
|
||||
<< " bytes non libérés" << std::endl;
|
||||
}
|
||||
|
||||
//Vulkan memory allocator
|
||||
vmaDestroyAllocator(allocator);
|
||||
|
||||
// 5. surface
|
||||
surface = nullptr;
|
||||
|
||||
// 6. device en avant-dernier
|
||||
device = nullptr;
|
||||
|
||||
// 7. instance en dernier
|
||||
instance = nullptr;
|
||||
}
|
||||
|
||||
void VulkanImpl::createInstance(){
|
||||
constexpr vk::ApplicationInfo appInfo{ "CosmicEngine",
|
||||
VK_MAKE_VERSION( 1, 0, 0 ),
|
||||
"No Engine",
|
||||
VK_MAKE_VERSION( 1, 0, 0 ),
|
||||
vk::ApiVersion13};
|
||||
|
||||
uint32_t sdl_extensions_count = 0;
|
||||
const char* const* sdl_extensions = SDL_Vulkan_GetInstanceExtensions(&sdl_extensions_count);
|
||||
|
||||
auto extensionProp = context.enumerateInstanceExtensionProperties();
|
||||
for (uint32_t i = 0; i < sdl_extensions_count; ++i)
|
||||
{
|
||||
if (std::ranges::none_of(extensionProp,
|
||||
[sdlExtension = sdl_extensions[i]](auto const& extensionProperty)
|
||||
{ return strcmp(extensionProperty.extensionName, sdlExtension) == 0; }))
|
||||
{
|
||||
throw std::runtime_error("Required SDL extension not supported: " + std::string(sdl_extensions[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the required layers
|
||||
std::vector<char const*> requiredLayers;
|
||||
if (enableValidationLayers)
|
||||
{
|
||||
requiredLayers.assign(validationLayers.begin(), validationLayers.end());
|
||||
}
|
||||
|
||||
// Check if the required layers are supported by the Vulkan implementation.
|
||||
auto layerProperties = context.enumerateInstanceLayerProperties();
|
||||
auto unsupportedLayerIt = std::ranges::find_if(requiredLayers,
|
||||
[&layerProperties](auto const &requiredLayer) {
|
||||
return std::ranges::none_of(layerProperties,
|
||||
[requiredLayer](auto const &layerProperty) { return strcmp(layerProperty.layerName, requiredLayer) == 0; });
|
||||
});
|
||||
if (unsupportedLayerIt != requiredLayers.end())
|
||||
{
|
||||
throw std::runtime_error("Required layer not supported: " + std::string(*unsupportedLayerIt));
|
||||
}
|
||||
|
||||
vk::InstanceCreateInfo createInfo{{},&appInfo, static_cast<uint32_t>(requiredLayers.size()), requiredLayers.data(), sdl_extensions_count, sdl_extensions};
|
||||
|
||||
|
||||
instance = vk::raii::Instance(context, createInfo);
|
||||
}
|
||||
|
||||
void VulkanImpl::pickPhysicalDevice()
|
||||
{
|
||||
std::vector<vk::raii::PhysicalDevice> devices = instance.enumeratePhysicalDevices();
|
||||
const auto devIter = std::ranges::find_if(
|
||||
devices,
|
||||
[&](auto const &device) {
|
||||
// Check if the device supports the Vulkan 1.3 API version
|
||||
bool supportsVulkan1_3 = device.getProperties().apiVersion >= VK_API_VERSION_1_3;
|
||||
|
||||
// Check if any of the queue families support graphics operations
|
||||
auto queueFamilies = device.getQueueFamilyProperties();
|
||||
bool supportsGraphics =
|
||||
std::ranges::any_of(queueFamilies, [](auto const &qfp) { return !!(qfp.queueFlags & vk::QueueFlagBits::eGraphics); });
|
||||
|
||||
// Check if all required device extensions are available
|
||||
auto availableDeviceExtensions = device.enumerateDeviceExtensionProperties();
|
||||
bool supportsAllRequiredExtensions =
|
||||
std::ranges::all_of(requiredDeviceExtension,
|
||||
[&availableDeviceExtensions](auto const &requiredDeviceExtension) {
|
||||
return std::ranges::any_of(availableDeviceExtensions,
|
||||
[requiredDeviceExtension](auto const &availableDeviceExtension) { return strcmp(availableDeviceExtension.extensionName, requiredDeviceExtension) == 0; });
|
||||
});
|
||||
|
||||
auto features = device.template getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
|
||||
bool supportsRequiredFeatures = features.template get<vk::PhysicalDeviceVulkan13Features>().dynamicRendering &&
|
||||
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
|
||||
|
||||
return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures;
|
||||
});
|
||||
if (devIter != devices.end())
|
||||
{
|
||||
physicalDevice = *devIter;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("failed to find a suitable GPU!");
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanImpl::createLogicalDevice()
|
||||
{
|
||||
// find the index of the first queue family that supports graphics
|
||||
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
|
||||
|
||||
// get the first index into queueFamilyProperties which supports graphics
|
||||
auto graphicsQueueFamilyProperty = std::ranges::find_if(queueFamilyProperties, [](auto const &qfp) { return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlags>(0); });
|
||||
assert(graphicsQueueFamilyProperty != queueFamilyProperties.end() && "No graphics queue family found!");
|
||||
|
||||
auto graphicsIndex = static_cast<uint32_t>(std::distance(queueFamilyProperties.begin(), graphicsQueueFamilyProperty));
|
||||
|
||||
// determine a queueFamilyIndex that supports present
|
||||
// first check if the graphicsIndex is good enough
|
||||
auto presentIndex = physicalDevice.getSurfaceSupportKHR( graphicsIndex, *surface )
|
||||
? graphicsIndex
|
||||
: static_cast<uint32_t>( queueFamilyProperties.size() );
|
||||
if ( presentIndex == queueFamilyProperties.size() )
|
||||
{
|
||||
// the graphicsIndex doesn't support present -> look for another family index that supports both
|
||||
// graphics and present
|
||||
for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
|
||||
{
|
||||
if ( ( queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics ) &&
|
||||
physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), *surface ) )
|
||||
{
|
||||
graphicsIndex = static_cast<uint32_t>( i );
|
||||
presentIndex = graphicsIndex;
|
||||
queueIndex = graphicsIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( presentIndex == queueFamilyProperties.size() )
|
||||
{
|
||||
// there's nothing like a single family index that supports both graphics and present -> look for another
|
||||
// family index that supports present
|
||||
for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
|
||||
{
|
||||
if ( physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), *surface ) )
|
||||
{
|
||||
presentIndex = static_cast<uint32_t>( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ( graphicsIndex == queueFamilyProperties.size() ) || ( presentIndex == queueFamilyProperties.size() ) )
|
||||
{
|
||||
throw std::runtime_error( "Could not find a queue for graphics or present -> terminating" );
|
||||
}
|
||||
|
||||
queueIndex = graphicsIndex;
|
||||
|
||||
// query for Vulkan 1.3 features
|
||||
|
||||
auto features = physicalDevice.getFeatures2();
|
||||
vk::PhysicalDeviceVulkan11Features vulkan11Features;
|
||||
vulkan11Features.shaderDrawParameters = vk::True;
|
||||
|
||||
vk::PhysicalDeviceVulkan13Features vulkan13Features;
|
||||
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures;
|
||||
vulkan13Features.dynamicRendering = vk::True;
|
||||
vulkan13Features.synchronization2 = vk::True;
|
||||
extendedDynamicStateFeatures.extendedDynamicState = vk::True;
|
||||
vulkan11Features.pNext = &vulkan13Features;
|
||||
vulkan13Features.pNext = &extendedDynamicStateFeatures;
|
||||
features.pNext = &vulkan11Features;
|
||||
|
||||
// create a Device
|
||||
float queuePriority = 0.5f;
|
||||
vk::DeviceQueueCreateInfo deviceQueueCreateInfo{{},
|
||||
graphicsIndex,
|
||||
1,
|
||||
&queuePriority};
|
||||
|
||||
vk::DeviceCreateInfo deviceCreateInfo{{},
|
||||
1,
|
||||
&deviceQueueCreateInfo,
|
||||
{},
|
||||
{},
|
||||
static_cast<uint32_t>(requiredDeviceExtension.size()),
|
||||
requiredDeviceExtension.data(),
|
||||
{},
|
||||
&features
|
||||
};
|
||||
|
||||
|
||||
device = vk::raii::Device(physicalDevice, deviceCreateInfo);
|
||||
graphicsQueue = vk::raii::Queue(device, graphicsIndex, 0);
|
||||
presentQueue = vk::raii::Queue( device, presentIndex, 0 );
|
||||
|
||||
VmaAllocatorCreateInfo allocatorInfo{};
|
||||
allocatorInfo.physicalDevice = *physicalDevice;
|
||||
allocatorInfo.device = *device;
|
||||
allocatorInfo.instance = *instance;
|
||||
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_3;
|
||||
vmaCreateAllocator(&allocatorInfo, &allocator);
|
||||
}
|
||||
|
||||
void VulkanImpl::createSurface()
|
||||
{
|
||||
VkSurfaceKHR _surface;
|
||||
if (!SDL_Vulkan_CreateSurface(m_window, *instance, nullptr, &_surface)) {
|
||||
throw std::runtime_error("failed to create window surface!");
|
||||
}
|
||||
surface = vk::raii::SurfaceKHR(instance, _surface);
|
||||
}
|
||||
|
||||
void VulkanImpl::createSwapChain()
|
||||
{
|
||||
auto surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(*surface);
|
||||
swapChainExtent = chooseSwapExtent(surfaceCapabilities, m_window);
|
||||
swapChainSurfaceFormat = chooseSwapSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(*surface));
|
||||
vk::SwapchainCreateInfoKHR swapChainCreateInfo{ {},
|
||||
*surface,
|
||||
chooseSwapMinImageCount(surfaceCapabilities),
|
||||
swapChainSurfaceFormat.format,
|
||||
swapChainSurfaceFormat.colorSpace,
|
||||
swapChainExtent,
|
||||
1,
|
||||
vk::ImageUsageFlagBits::eColorAttachment,
|
||||
vk::SharingMode::eExclusive,
|
||||
{},
|
||||
surfaceCapabilities.currentTransform,
|
||||
vk::CompositeAlphaFlagBitsKHR::eOpaque,
|
||||
chooseSwapPresentMode(physicalDevice.getSurfacePresentModesKHR(*surface)),
|
||||
true};
|
||||
|
||||
swapChain = vk::raii::SwapchainKHR(device, swapChainCreateInfo);
|
||||
|
||||
swapChainImages = swapChain.getImages();
|
||||
}
|
||||
|
||||
void VulkanImpl::createImageViews()
|
||||
{
|
||||
vk::ImageViewCreateInfo imageViewCreateInfo{
|
||||
{},
|
||||
{},
|
||||
vk::ImageViewType::e2D,
|
||||
swapChainSurfaceFormat.format,
|
||||
{},
|
||||
{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}
|
||||
};
|
||||
for (auto& image : swapChainImages)
|
||||
{
|
||||
imageViewCreateInfo.image = image;
|
||||
swapChainImageViews.emplace_back(device, imageViewCreateInfo);
|
||||
}
|
||||
}
|
||||
|
||||
vk::raii::ImageView VulkanImpl::createImageView(vk::raii::Image& image, vk::Format format, vk::ImageAspectFlags aspectFlags)
|
||||
{
|
||||
vk::ImageViewCreateInfo imageViewCreateInfo{
|
||||
{},
|
||||
image,
|
||||
vk::ImageViewType::e2D,
|
||||
format,
|
||||
{},
|
||||
{aspectFlags, 0, 1, 0, 1}
|
||||
};
|
||||
return vk::raii::ImageView(device, imageViewCreateInfo);
|
||||
}
|
||||
|
||||
void VulkanImpl::createCommandPool()
|
||||
{
|
||||
vk::CommandPoolCreateInfo poolInfo{vk::CommandPoolCreateFlagBits::eResetCommandBuffer, queueIndex};
|
||||
commandPool = vk::raii::CommandPool(device, poolInfo);
|
||||
}
|
||||
|
||||
void VulkanImpl::createCommandBuffer()
|
||||
{
|
||||
vk::CommandBufferAllocateInfo allocInfo{commandPool, vk::CommandBufferLevel::ePrimary, MAX_FRAMES_IN_FLIGHT};
|
||||
commandBuffers = vk::raii::CommandBuffers(device, allocInfo);
|
||||
}
|
||||
|
||||
|
||||
void VulkanImpl::recordCommandBuffer(uint32_t imageIndex)
|
||||
{
|
||||
auto &commandBuffer = commandBuffers[frameIndex];
|
||||
commandBuffer.begin({});
|
||||
// Before starting rendering, transition the swapchain image to COLOR_ATTACHMENT_OPTIMAL
|
||||
transitionImageLayout(
|
||||
swapChainImages[imageIndex],
|
||||
vk::ImageLayout::eUndefined,
|
||||
vk::ImageLayout::eColorAttachmentOptimal,
|
||||
{}, // srcAccessMask (no need to wait for previous operations)
|
||||
vk::AccessFlagBits2::eColorAttachmentWrite, // dstAccessMask
|
||||
vk::PipelineStageFlagBits2::eColorAttachmentOutput, // srcStage
|
||||
vk::PipelineStageFlagBits2::eColorAttachmentOutput, // dstStage
|
||||
vk::ImageAspectFlagBits::eColor
|
||||
);
|
||||
|
||||
// Transition depth image to depth attachment optimal layout
|
||||
transitionImageLayout(
|
||||
depthImage,
|
||||
vk::ImageLayout::eUndefined,
|
||||
vk::ImageLayout::eDepthAttachmentOptimal,
|
||||
vk::AccessFlagBits2::eDepthStencilAttachmentWrite,
|
||||
vk::AccessFlagBits2::eDepthStencilAttachmentWrite,
|
||||
vk::PipelineStageFlagBits2::eEarlyFragmentTests | vk::PipelineStageFlagBits2::eLateFragmentTests,
|
||||
vk::PipelineStageFlagBits2::eEarlyFragmentTests | vk::PipelineStageFlagBits2::eLateFragmentTests,
|
||||
vk::ImageAspectFlagBits::eDepth);
|
||||
|
||||
vk::ClearValue clearColor = vk::ClearColorValue(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
vk::ClearValue clearDepth = vk::ClearDepthStencilValue(1.0f, 0);
|
||||
//color
|
||||
vk::RenderingAttachmentInfo attachmentInfo = {
|
||||
swapChainImageViews[imageIndex],
|
||||
vk::ImageLayout::eColorAttachmentOptimal,
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
vk::AttachmentLoadOp::eClear,
|
||||
vk::AttachmentStoreOp::eStore,
|
||||
clearColor
|
||||
};
|
||||
//depth
|
||||
vk::RenderingAttachmentInfo depthAttachmentInfo = {
|
||||
depthImageView,
|
||||
vk::ImageLayout::eDepthAttachmentOptimal,
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
vk::AttachmentLoadOp::eClear,
|
||||
vk::AttachmentStoreOp::eDontCare,
|
||||
clearDepth};
|
||||
|
||||
vk::RenderingInfo renderingInfo = {{},{{0, 0}, swapChainExtent},
|
||||
1,
|
||||
{},
|
||||
1,
|
||||
&attachmentInfo,
|
||||
&depthAttachmentInfo};
|
||||
|
||||
commandBuffer.beginRendering(renderingInfo);
|
||||
|
||||
commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(swapChainExtent.width), static_cast<float>(swapChainExtent.height), 0.0f, 1.0f));
|
||||
commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent));
|
||||
|
||||
CosmicCore::CKernel::m_kernel->getActiveScene()->render(commandBuffer, frameIndex);
|
||||
|
||||
commandBuffer.endRendering();
|
||||
// After rendering, transition the swapchain image to PRESENT_SRC
|
||||
transitionImageLayout(
|
||||
swapChainImages[imageIndex],
|
||||
vk::ImageLayout::eColorAttachmentOptimal,
|
||||
vk::ImageLayout::ePresentSrcKHR,
|
||||
vk::AccessFlagBits2::eColorAttachmentWrite, // srcAccessMask
|
||||
{}, // dstAccessMask
|
||||
vk::PipelineStageFlagBits2::eColorAttachmentOutput, // srcStage
|
||||
vk::PipelineStageFlagBits2::eBottomOfPipe, // dstStage
|
||||
vk::ImageAspectFlagBits::eColor
|
||||
);
|
||||
commandBuffer.end();
|
||||
}
|
||||
|
||||
void VulkanImpl::transitionImageLayout(
|
||||
vk::Image image,
|
||||
vk::ImageLayout old_layout,
|
||||
vk::ImageLayout new_layout,
|
||||
vk::AccessFlags2 src_access_mask,
|
||||
vk::AccessFlags2 dst_access_mask,
|
||||
vk::PipelineStageFlags2 src_stage_mask,
|
||||
vk::PipelineStageFlags2 dst_stage_mask, vk::ImageAspectFlags image_aspect_flags)
|
||||
{
|
||||
|
||||
vk::ImageMemoryBarrier2 barrier = {src_stage_mask, src_access_mask, dst_stage_mask, dst_access_mask, old_layout, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, image, {image_aspect_flags,0,1,0,1}};
|
||||
vk::DependencyInfo dependency_info = {{},{},{},{}, {}, 1,&barrier};
|
||||
commandBuffers[frameIndex].pipelineBarrier2(dependency_info);
|
||||
}
|
||||
|
||||
void VulkanImpl::createSyncObjects()
|
||||
{
|
||||
for (size_t i = 0; i < swapChainImages.size(); i++)
|
||||
{
|
||||
renderFinishedSemaphores.emplace_back(device, vk::SemaphoreCreateInfo());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
presentCompleteSemaphores.emplace_back(device, vk::SemaphoreCreateInfo());
|
||||
inFlightFences.emplace_back(device, vk::FenceCreateInfo{vk::FenceCreateFlagBits::eSignaled});
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanImpl::drawFrame()
|
||||
{
|
||||
auto fenceResult = device.waitForFences(*inFlightFences[frameIndex], vk::True, UINT64_MAX);
|
||||
m_deletionQueue.flush(frameIndex); // détruit les ressources de cette frame
|
||||
if (fenceResult != vk::Result::eSuccess)
|
||||
{
|
||||
throw std::runtime_error("failed to wait for fence!");
|
||||
}
|
||||
device.resetFences(*inFlightFences[frameIndex]);
|
||||
|
||||
auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr);
|
||||
commandBuffers[frameIndex].reset();
|
||||
recordCommandBuffer(imageIndex);
|
||||
|
||||
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput);
|
||||
const vk::SubmitInfo submitInfo{1, &*presentCompleteSemaphores[frameIndex], &waitDestinationStageMask, 1, &*commandBuffers[frameIndex], 1, &*renderFinishedSemaphores[imageIndex]};
|
||||
presentQueue.submit(submitInfo, *inFlightFences[frameIndex]);
|
||||
|
||||
const vk::PresentInfoKHR presentInfoKHR{1, &*renderFinishedSemaphores[imageIndex], 1, &*swapChain, &imageIndex};
|
||||
result = presentQueue.presentKHR(presentInfoKHR);
|
||||
// Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result
|
||||
// here and does not need to be caught by an exception.
|
||||
if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized)
|
||||
{
|
||||
framebufferResized = false;
|
||||
recreateSwapChain();
|
||||
}
|
||||
else
|
||||
{
|
||||
// There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception.
|
||||
assert(result == vk::Result::eSuccess);
|
||||
}
|
||||
frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
void VulkanImpl::cleanupSwapChain()
|
||||
{
|
||||
depthImageView = nullptr;
|
||||
depthImage = nullptr;
|
||||
depthImageMemory = nullptr;
|
||||
|
||||
swapChainImageViews.clear();
|
||||
swapChain = nullptr;
|
||||
swapChainImages.clear();
|
||||
}
|
||||
|
||||
void VulkanImpl::recreateSwapChain()
|
||||
{
|
||||
int width = 0, height = 0;
|
||||
SDL_GetWindowSizeInPixels(m_window, &width, &height);
|
||||
while (width == 0 || height == 0) {
|
||||
SDL_GetWindowSizeInPixels(m_window, &width, &height);
|
||||
SDL_WaitEvent(nullptr);
|
||||
}
|
||||
|
||||
device.waitIdle();
|
||||
|
||||
cleanupSwapChain();
|
||||
createSwapChain();
|
||||
createImageViews();
|
||||
createDepthResources();
|
||||
}
|
||||
|
||||
uint32_t VulkanImpl::findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties)
|
||||
{
|
||||
vk::PhysicalDeviceMemoryProperties memProperties = physicalDevice.getMemoryProperties();
|
||||
|
||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
|
||||
{
|
||||
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("failed to find suitable memory type!");
|
||||
}
|
||||
|
||||
void VulkanImpl::copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) {
|
||||
vk::raii::CommandBuffer commandCopyBuffer = beginSingleTimeCommands();
|
||||
commandCopyBuffer.copyBuffer(vk::Buffer(src), vk::Buffer(dst), vk::BufferCopy(0, 0, size));
|
||||
endSingleTimeCommands(commandCopyBuffer);
|
||||
}
|
||||
|
||||
void VulkanImpl::createDescriptorSetLayouts()
|
||||
{
|
||||
// set 0 - Camera : un UBO en vertex shader
|
||||
vk::DescriptorSetLayoutBinding cameraBinding{
|
||||
0, // binding
|
||||
vk::DescriptorType::eUniformBuffer, // type
|
||||
1, // count
|
||||
vk::ShaderStageFlagBits::eVertex, // stage
|
||||
nullptr
|
||||
};
|
||||
cameraLayout = vk::raii::DescriptorSetLayout(
|
||||
device,
|
||||
vk::DescriptorSetLayoutCreateInfo{{}, 1, &cameraBinding}
|
||||
);
|
||||
|
||||
// set 1 - Transform : un UBO en vertex shader
|
||||
vk::DescriptorSetLayoutBinding transformBinding{
|
||||
0,
|
||||
vk::DescriptorType::eUniformBuffer,
|
||||
1,
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
nullptr
|
||||
};
|
||||
transformLayout = vk::raii::DescriptorSetLayout(
|
||||
device,
|
||||
vk::DescriptorSetLayoutCreateInfo{{}, 1, &transformBinding}
|
||||
);
|
||||
|
||||
// set 2 - Material : un UBO + deux samplers en fragment shader
|
||||
std::array<vk::DescriptorSetLayoutBinding, 3> materialBindings{{
|
||||
{0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eFragment, nullptr},
|
||||
{1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, nullptr},
|
||||
{2, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, nullptr},
|
||||
}};
|
||||
materialLayout = vk::raii::DescriptorSetLayout(
|
||||
device,
|
||||
vk::DescriptorSetLayoutCreateInfo{{},
|
||||
static_cast<uint32_t>(materialBindings.size()),
|
||||
materialBindings.data()}
|
||||
);
|
||||
|
||||
std::array<vk::DescriptorSetLayout, 3> layouts{
|
||||
*cameraLayout,
|
||||
*transformLayout,
|
||||
*materialLayout
|
||||
};
|
||||
vk::PipelineLayoutCreateInfo layoutInfo{{},
|
||||
static_cast<uint32_t>(layouts.size()),
|
||||
layouts.data()
|
||||
};
|
||||
defaultPipelineLayoutInfo = vk::raii::PipelineLayout(device, layoutInfo);
|
||||
}
|
||||
|
||||
//Fonction d'ajout de descriptor set qui regarde la taille de la pool, si la pool est dépassée, on ajoute une pool 2x plus grande
|
||||
void VulkanImpl::createDescriptorPool()
|
||||
{
|
||||
descriptorPoolManager.init(device);
|
||||
}
|
||||
|
||||
void VulkanImpl::createDepthResources()
|
||||
{
|
||||
vk::Format depthFormat = findDepthFormat();
|
||||
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eDepthStencilAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, depthImage, depthImageMemory);
|
||||
depthImageView = createImageView(depthImage, depthFormat, vk::ImageAspectFlagBits::eDepth);
|
||||
}
|
||||
|
||||
vk::Format VulkanImpl::findSupportedFormat(const std::vector<vk::Format>& candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features)
|
||||
{
|
||||
for (const auto format : candidates) {
|
||||
vk::FormatProperties props = physicalDevice.getFormatProperties(format);
|
||||
|
||||
if (tiling == vk::ImageTiling::eLinear && (props.linearTilingFeatures & features) == features) {
|
||||
return format;
|
||||
}
|
||||
if (tiling == vk::ImageTiling::eOptimal && (props.optimalTilingFeatures & features) == features) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("failed to find supported format!");
|
||||
}
|
||||
|
||||
vk::Format VulkanImpl::findDepthFormat() {
|
||||
return findSupportedFormat(
|
||||
{vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint},
|
||||
vk::ImageTiling::eOptimal,
|
||||
vk::FormatFeatureFlagBits::eDepthStencilAttachment
|
||||
);
|
||||
}
|
||||
|
||||
bool VulkanImpl::hasStencilComponent(vk::Format format) {
|
||||
return format == vk::Format::eD32SfloatS8Uint || format == vk::Format::eD24UnormS8Uint;
|
||||
}
|
||||
|
||||
void VulkanImpl::createImage(uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags properties, vk::raii::Image &image, vk::raii::DeviceMemory &imageMemory)
|
||||
{
|
||||
vk::ImageCreateInfo imageInfo{{},vk::ImageType::e2D, format, {width, height, 1}, 1, 1, vk::SampleCountFlagBits::e1, tiling, usage, vk::SharingMode::eExclusive};
|
||||
|
||||
image = vk::raii::Image(device, imageInfo);
|
||||
|
||||
vk::MemoryRequirements memRequirements = image.getMemoryRequirements();
|
||||
vk::MemoryAllocateInfo allocInfo{memRequirements.size,
|
||||
findMemoryType(memRequirements.memoryTypeBits, properties)};
|
||||
imageMemory = vk::raii::DeviceMemory(device, allocInfo);
|
||||
image.bindMemory(imageMemory, 0);
|
||||
}
|
||||
|
||||
vk::raii::CommandBuffer VulkanImpl::beginSingleTimeCommands() {
|
||||
vk::CommandBufferAllocateInfo allocInfo{ commandPool, vk::CommandBufferLevel::ePrimary, 1 };
|
||||
vk::raii::CommandBuffer commandBuffer = std::move(device.allocateCommandBuffers(allocInfo).front());
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo{ vk::CommandBufferUsageFlagBits::eOneTimeSubmit };
|
||||
commandBuffer.begin(beginInfo);
|
||||
|
||||
return commandBuffer;
|
||||
}
|
||||
|
||||
void VulkanImpl::endSingleTimeCommands(vk::raii::CommandBuffer& commandBuffer) {
|
||||
commandBuffer.end();
|
||||
|
||||
vk::SubmitInfo submitInfo{{},{},{},1, &*commandBuffer };
|
||||
graphicsQueue.submit(submitInfo, nullptr);
|
||||
graphicsQueue.waitIdle();
|
||||
}
|
||||
|
||||
|
||||
void VulkanImpl::transitionImageLayout(vk::Image image, vk::ImageLayout oldLayout, vk::ImageLayout newLayout)
|
||||
{
|
||||
auto commandBuffer = beginSingleTimeCommands();
|
||||
|
||||
vk::ImageMemoryBarrier barrier{{},{},oldLayout, newLayout,{}, {}, image, {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}};
|
||||
|
||||
vk::PipelineStageFlags sourceStage;
|
||||
vk::PipelineStageFlags destinationStage;
|
||||
|
||||
if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
|
||||
{
|
||||
barrier.srcAccessMask = {};
|
||||
barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
|
||||
|
||||
sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
destinationStage = vk::PipelineStageFlagBits::eTransfer;
|
||||
}
|
||||
else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
|
||||
{
|
||||
barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
|
||||
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
|
||||
|
||||
sourceStage = vk::PipelineStageFlagBits::eTransfer;
|
||||
destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::invalid_argument("unsupported layout transition!");
|
||||
}
|
||||
commandBuffer.pipelineBarrier(sourceStage, destinationStage, {}, {}, nullptr, barrier);
|
||||
endSingleTimeCommands(commandBuffer);
|
||||
}
|
||||
|
||||
void VulkanImpl::copyBufferToImage(const vk::raii::Buffer &buffer, vk::raii::Image &image, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto commandBuffer = beginSingleTimeCommands();
|
||||
vk::BufferImageCopy region{0, 0, 0, {vk::ImageAspectFlagBits::eColor, 0, 0, 1}, {0, 0, 0}, {width, height, 1}};
|
||||
commandBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, {region});
|
||||
endSingleTimeCommands(commandBuffer);
|
||||
}
|
||||
|
||||
void VulkanImpl::destroyBuffer(VMABuffer& buffer, uint32_t frame) {
|
||||
VmaAllocator& alloc = allocator;
|
||||
VkBuffer& buf = buffer.buffer;
|
||||
VmaAllocation& mem = buffer.allocation;
|
||||
|
||||
m_deletionQueue.push(frame, [alloc, buf, mem]() {
|
||||
vmaDestroyBuffer(alloc, buf, mem);
|
||||
});
|
||||
|
||||
buffer.buffer = VK_NULL_HANDLE;
|
||||
buffer.allocation = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
// destruction d'un descriptor set
|
||||
void VulkanImpl::destroyDescriptorSet(ManagedDescriptorSet& set, uint32_t frame) {
|
||||
auto s = std::make_shared<ManagedDescriptorSet>(std::move(set));
|
||||
m_deletionQueue.push(frame, [&dpm = descriptorPoolManager, s]() mutable {
|
||||
dpm.free(*s);
|
||||
});
|
||||
}
|
||||
|
||||
void VulkanImpl::destroyPipeline(vk::raii::Pipeline& pipeline, vk::raii::PipelineLayout& layout)
|
||||
{
|
||||
auto p = std::make_shared<vk::raii::Pipeline>(std::move(pipeline));
|
||||
auto pl = std::make_shared<vk::raii::PipelineLayout>(std::move(layout));
|
||||
|
||||
m_deletionQueue.push(frameIndex, [p, pl]() mutable {
|
||||
p = nullptr;
|
||||
pl = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void VulkanImpl::createDefaultTexture()
|
||||
{
|
||||
auto def = std::make_unique<CTexture>("");
|
||||
def.get()->initDefaultTexture();
|
||||
m_defaultTexture = def.get();
|
||||
getResourceManager().getTextureManager().addTexture("default", std::move(def));
|
||||
}
|
||||
226
src/Engine/Core/Graphics/API/VulkanImpl.hpp
Normal file
226
src/Engine/Core/Graphics/API/VulkanImpl.hpp
Normal file
@@ -0,0 +1,226 @@
|
||||
#ifndef VULKANIMPL_HPP
|
||||
#define VULKANIMPL_HPP
|
||||
|
||||
#include "GraphicsAPI.hpp"
|
||||
#include "DeletionQueue.hpp"
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "ManagedDescriptorSet.hpp"
|
||||
const std::vector<char const*> validationLayers = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
};
|
||||
|
||||
#ifdef NDEBUG
|
||||
constexpr bool enableValidationLayers = false;
|
||||
#else
|
||||
constexpr bool enableValidationLayers = true;
|
||||
#endif
|
||||
|
||||
class DescriptorAllocator {
|
||||
struct Pool {
|
||||
vk::raii::DescriptorPool pool = nullptr;
|
||||
uint32_t capacity = 0;
|
||||
uint32_t allocated = 0;
|
||||
|
||||
bool isFull() const { return allocated >= capacity; }
|
||||
bool isEmpty() const { return allocated == 0; }
|
||||
};
|
||||
|
||||
vk::raii::Device* m_device = nullptr;
|
||||
uint32_t m_baseSize = 64;
|
||||
std::vector<Pool> m_pools;
|
||||
|
||||
Pool createPool(uint32_t size) {
|
||||
std::vector<vk::DescriptorPoolSize> sizes = {
|
||||
{vk::DescriptorType::eUniformBuffer, size * 2},
|
||||
{vk::DescriptorType::eCombinedImageSampler, size * 2},
|
||||
};
|
||||
Pool p;
|
||||
p.capacity = size;
|
||||
p.pool = vk::raii::DescriptorPool(*m_device,
|
||||
vk::DescriptorPoolCreateInfo{
|
||||
vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
|
||||
size,
|
||||
static_cast<uint32_t>(sizes.size()),
|
||||
sizes.data()
|
||||
}
|
||||
);
|
||||
return p;
|
||||
}
|
||||
|
||||
Pool& getAvailablePool() {
|
||||
// cherche une pool non pleine
|
||||
for (auto& p : m_pools)
|
||||
if (!p.isFull()) return p;
|
||||
|
||||
//nouvelle pool x2
|
||||
uint32_t newSize = m_pools.empty()
|
||||
? m_baseSize
|
||||
: m_pools.back().capacity * 2;
|
||||
|
||||
return m_pools.emplace_back(createPool(newSize));
|
||||
}
|
||||
|
||||
public:
|
||||
void init(vk::raii::Device& device) { m_device = &device; }
|
||||
|
||||
ManagedDescriptorSet allocate(vk::DescriptorSetLayout layout) {
|
||||
auto& p = getAvailablePool();
|
||||
|
||||
vk::DescriptorSetAllocateInfo allocInfo{*p.pool, 1, &layout};
|
||||
auto sets = m_device->allocateDescriptorSets(allocInfo);
|
||||
p.allocated++;
|
||||
ManagedDescriptorSet mds;
|
||||
mds.set = std::move(sets[0]);
|
||||
mds.ownerPool = *p.pool;
|
||||
return mds;
|
||||
}
|
||||
|
||||
void free(ManagedDescriptorSet& man) {
|
||||
// retrouve la pool du set pour décrémenter
|
||||
VkDescriptorPool rawPool = man.ownerPool; // handle de la pool parente
|
||||
man.set = nullptr; // libère vk::raii free
|
||||
|
||||
for (auto it = m_pools.begin(); it != m_pools.end(); ++it) {
|
||||
if (*it->pool == rawPool) {
|
||||
it->allocated--;
|
||||
if (it->isEmpty())
|
||||
m_pools.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class VulkanImpl: public GraphicsAPI{
|
||||
private:
|
||||
vk::raii::Context context;
|
||||
vk::raii::Instance instance = nullptr;
|
||||
vk::raii::PhysicalDevice physicalDevice = nullptr;
|
||||
std::vector<const char *> requiredDeviceExtension = {
|
||||
vk::KHRSwapchainExtensionName};
|
||||
|
||||
vk::raii::Device device = nullptr;
|
||||
vk::raii::Queue graphicsQueue = nullptr;
|
||||
vk::raii::Queue presentQueue = nullptr;
|
||||
uint32_t queueIndex = ~0;
|
||||
vk::raii::SurfaceKHR surface = nullptr;
|
||||
|
||||
vk::raii::SwapchainKHR swapChain = nullptr;
|
||||
std::vector<vk::Image> swapChainImages;
|
||||
vk::SurfaceFormatKHR swapChainSurfaceFormat;
|
||||
vk::Extent2D swapChainExtent;
|
||||
std::vector<vk::raii::ImageView> swapChainImageViews;
|
||||
|
||||
vk::raii::CommandPool commandPool = nullptr;
|
||||
std::vector<vk::raii::CommandBuffer> commandBuffers;
|
||||
|
||||
std::vector<vk::raii::Semaphore> presentCompleteSemaphores;
|
||||
std::vector<vk::raii::Semaphore> renderFinishedSemaphores;
|
||||
std::vector<vk::raii::Fence> inFlightFences;
|
||||
uint32_t frameIndex = 0;
|
||||
SDL_Window* m_window;
|
||||
|
||||
bool framebufferResized = false;
|
||||
|
||||
VmaAllocator allocator = nullptr;
|
||||
|
||||
vk::raii::DescriptorSetLayout cameraLayout = nullptr; // set 0
|
||||
vk::raii::DescriptorSetLayout transformLayout = nullptr; // set 1
|
||||
vk::raii::DescriptorSetLayout materialLayout = nullptr; // set 2
|
||||
|
||||
DescriptorAllocator descriptorPoolManager;
|
||||
vk::raii::PipelineLayout defaultPipelineLayoutInfo = nullptr;
|
||||
|
||||
vk::raii::Image depthImage = nullptr;
|
||||
vk::raii::DeviceMemory depthImageMemory = nullptr;
|
||||
vk::raii::ImageView depthImageView = nullptr;
|
||||
|
||||
DeletionQueue m_deletionQueue;
|
||||
|
||||
CTexture* m_defaultTexture = nullptr;
|
||||
public:
|
||||
virtual ~VulkanImpl(){};
|
||||
void init(SDL_Window* window) override;
|
||||
void cleanup()override;
|
||||
void createInstance();
|
||||
void pickPhysicalDevice();
|
||||
void createLogicalDevice();
|
||||
void createSurface();
|
||||
void createSwapChain();
|
||||
void createImageViews();
|
||||
//void createGraphicsPipeline();
|
||||
void createCommandPool();
|
||||
void createCommandBuffer();
|
||||
void createSyncObjects();
|
||||
void drawFrame() override;
|
||||
void recreateSwapChain();
|
||||
void createDescriptorSetLayouts();
|
||||
void cleanupSwapChain();
|
||||
void createDepthResources();
|
||||
|
||||
void transitionImageLayout(vk::Image image, vk::ImageLayout old_layout, vk::ImageLayout new_layout, vk::AccessFlags2 src_access_mask, vk::AccessFlags2 dst_access_mask, vk::PipelineStageFlags2 src_stage_mask, vk::PipelineStageFlags2 dst_stage_mask, vk::ImageAspectFlags image_aspect_flags);
|
||||
void transitionImageLayout(vk::Image image, vk::ImageLayout oldLayout, vk::ImageLayout newLayout);
|
||||
void recordCommandBuffer(uint32_t imageIndex);
|
||||
void* getDevice()override {return &device;};
|
||||
uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties);
|
||||
vk::SurfaceFormatKHR& getSwapChainFormat(){return swapChainSurfaceFormat;};
|
||||
uint32_t getGraphicsQueueIndex() const { return queueIndex; }
|
||||
vk::Extent2D getSwapChainExtent() const { return swapChainExtent; }
|
||||
|
||||
// accès au command buffer courant pour que le Renderer puisse enregistrer
|
||||
vk::raii::CommandBuffer& getCurrentCommandBuffer();
|
||||
|
||||
// accès à l'image view courante pour le color attachment
|
||||
vk::raii::ImageView& getCurrentSwapChainImageView();
|
||||
|
||||
// pour que le Renderer sache quelle frame est en cours
|
||||
uint32_t getCurrentFrameIndex() const { return frameIndex; }
|
||||
|
||||
VmaAllocator getAllocator() { return allocator; }
|
||||
vk::raii::PhysicalDevice& getPhysicalDevice() { return physicalDevice; }
|
||||
vk::raii::DescriptorSetLayout& getCameraLayout() { return cameraLayout; }
|
||||
vk::raii::DescriptorSetLayout& getTransformLayout() { return transformLayout; }
|
||||
vk::raii::DescriptorSetLayout& getMaterialLayout() { return materialLayout; }
|
||||
|
||||
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
||||
|
||||
vk::Format findSupportedFormat(const std::vector<vk::Format>& candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features);
|
||||
vk::Format findDepthFormat();
|
||||
|
||||
bool hasStencilComponent(vk::Format format);
|
||||
void createImage(uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags properties, vk::raii::Image &image, vk::raii::DeviceMemory &imageMemory);
|
||||
|
||||
DescriptorAllocator& getDescriptorPoolManager(){return descriptorPoolManager;};
|
||||
|
||||
void createDescriptorPool();
|
||||
|
||||
vk::raii::CommandBuffer beginSingleTimeCommands();
|
||||
|
||||
void endSingleTimeCommands(vk::raii::CommandBuffer& commandBuffer);
|
||||
|
||||
vk::raii::ImageView createImageView(vk::raii::Image& image, vk::Format format, vk::ImageAspectFlags aspectFlags);
|
||||
|
||||
|
||||
void copyBufferToImage(const vk::raii::Buffer &buffer, vk::raii::Image &image, uint32_t width, uint32_t height);
|
||||
|
||||
void destroyBuffer(VMABuffer& buffer, uint32_t frameIndex);
|
||||
|
||||
void destroyDescriptorSet(ManagedDescriptorSet& set, uint32_t frameIndex);
|
||||
|
||||
void destroyPipeline(vk::raii::Pipeline& pipeline, vk::raii::PipelineLayout& layout);
|
||||
|
||||
vk::raii::PipelineLayout& getDefaultPipelineLayout(){return defaultPipelineLayoutInfo;};
|
||||
|
||||
DeletionQueue& getDeletionQueue(){return m_deletionQueue;};
|
||||
|
||||
CTexture* getDefaultTexture() { return m_defaultTexture; }
|
||||
|
||||
void createDefaultTexture();
|
||||
};
|
||||
#endif
|
||||
42
src/Engine/Core/Graphics/CContext.cpp
Normal file
42
src/Engine/Core/Graphics/CContext.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "CContext.hpp"
|
||||
#include "API/GraphicsAPI.hpp"
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
|
||||
bool CContext::m_screenSaver = false;
|
||||
|
||||
void CContext::init(SDL_InitFlags sdlFlags) {
|
||||
// Log initialisation.
|
||||
initLog();
|
||||
|
||||
|
||||
// SDL Initialization.
|
||||
if (SDL_Init(sdlFlags)) {
|
||||
SDL_Quit();
|
||||
//HandleException(CLibException(std::string("Unable to initialize SDL: ") + SDL_GetError()), true);
|
||||
}
|
||||
|
||||
GraphicsAPI::initAPI();
|
||||
}
|
||||
|
||||
bool CContext::isScreenSaverEnable(void) {
|
||||
return m_screenSaver;
|
||||
}
|
||||
|
||||
void CContext::setScreenSaverEnable(bool newScreenSaver) {
|
||||
m_screenSaver = newScreenSaver;
|
||||
if (m_screenSaver) {
|
||||
SDL_EnableScreenSaver();
|
||||
}
|
||||
else {
|
||||
SDL_DisableScreenSaver();
|
||||
}
|
||||
}
|
||||
|
||||
void CContext::quit(void) {
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void CContext::initLog(void) {
|
||||
//todo
|
||||
}
|
||||
34
src/Engine/Core/Graphics/CContext.hpp
Normal file
34
src/Engine/Core/Graphics/CContext.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CCONTEXT_HPP
|
||||
#define CCONTEXT_HPP
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
|
||||
#define LOG_FILE "CosmicEngine_%3N.log"
|
||||
#define LOG_ROTATION_SIZE 1 * 1024 * 1024
|
||||
#define LOG_MAX_SIZE 50 * 1024 * 1024
|
||||
|
||||
class CContext {
|
||||
private:
|
||||
// Say if the screenSaver is enabled.
|
||||
static bool m_screenSaver;
|
||||
|
||||
public:
|
||||
CContext(void) = delete;
|
||||
|
||||
static void init(SDL_InitFlags sdlFlags);
|
||||
|
||||
static void quit(void);
|
||||
|
||||
static bool isScreenSaverEnable(void);
|
||||
|
||||
|
||||
static void setScreenSaverEnable(bool newScreenSaver);
|
||||
|
||||
private:
|
||||
|
||||
static void initLog(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,10 +6,6 @@ CModel::CModel(std::vector<CMesh*> meshes) :
|
||||
}
|
||||
|
||||
CModel::~CModel(void) {
|
||||
for (unsigned int i = 0; i < m_meshes.size(); i++)
|
||||
{
|
||||
delete m_meshes[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CModel::load(void) {
|
||||
@@ -21,12 +17,12 @@ void CModel::load(void) {
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
void CModel::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) {
|
||||
/*void CModel::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) {
|
||||
// For each meshes of the model.
|
||||
for (unsigned int i = 0; i < m_meshes.size(); i++) {
|
||||
m_meshes[i]->draw(model, view, projection, lightPos, intensity);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
std::vector<CMesh*>& CModel::getMeshes()
|
||||
{
|
||||
34
src/Engine/Core/Graphics/Data/CModel.hpp
Normal file
34
src/Engine/Core/Graphics/Data/CModel.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CMODEL_HPP
|
||||
#define CMODEL_HPP
|
||||
|
||||
#include "Mesh/CMesh.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class CModel {
|
||||
private:
|
||||
|
||||
std::vector<CMesh*> m_meshes;
|
||||
|
||||
bool m_loaded;
|
||||
|
||||
public:
|
||||
|
||||
CModel(void) = delete;
|
||||
|
||||
CModel(std::vector<CMesh*> meshes);
|
||||
|
||||
~CModel(void);
|
||||
|
||||
void load(void);
|
||||
|
||||
//void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity);
|
||||
|
||||
std::vector<CMesh*>& getMeshes(void);
|
||||
|
||||
void setMeshes(std::vector<CMesh*> meshes);
|
||||
|
||||
bool isLoaded(void);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
151
src/Engine/Core/Graphics/Data/CModelLoader.cpp
Normal file
151
src/Engine/Core/Graphics/Data/CModelLoader.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "CModelLoader.hpp"
|
||||
#include "../API/GraphicsAPI.hpp"
|
||||
#include <memory>
|
||||
|
||||
CModel* CModelLoader::loadModel(std::string fileName, CResourceManager& rm)
|
||||
{
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(fileName,
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_FlipUVs |
|
||||
aiProcess_CalcTangentSpace |
|
||||
aiProcess_GenNormals
|
||||
);
|
||||
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||
throw std::runtime_error("Assimp: " + std::string(importer.GetErrorString()));
|
||||
|
||||
// dossier de base pour les textures relatives
|
||||
std::vector<CMesh*> meshes;
|
||||
processNode(scene->mRootNode, scene, fileName, rm, meshes);
|
||||
|
||||
// crée et enregistre le model
|
||||
auto model = std::make_unique<CModel>(meshes);
|
||||
auto* ptr = model.get();
|
||||
rm.getModelManager().addModel(fileName,std::move(model));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void CModelLoader::processNode(aiNode* node, const aiScene* scene, const std::string& directory, CResourceManager& rm, std::vector<CMesh*>& meshes)
|
||||
{
|
||||
// process all the node's meshes (if any)
|
||||
for (uint32_t i = 0; i < node->mNumMeshes; i++) {
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
meshes.push_back(processMesh(mesh, scene, directory, rm));
|
||||
}
|
||||
// then do the same for each of its children
|
||||
for (uint32_t i = 0; i < node->mNumChildren; i++) {
|
||||
processNode(node->mChildren[i], scene, directory, rm, meshes);
|
||||
}
|
||||
}
|
||||
|
||||
CMesh* CModelLoader::processMesh(aiMesh* mesh, const aiScene* scene, const std::string& directory, CResourceManager& rm)
|
||||
{
|
||||
std::vector<SVertex> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
// vertices
|
||||
for (uint32_t i = 0; i < mesh->mNumVertices; i++) {
|
||||
SVertex vertex{};
|
||||
vertex.m_position = {
|
||||
mesh->mVertices[i].x,
|
||||
mesh->mVertices[i].y,
|
||||
mesh->mVertices[i].z
|
||||
};
|
||||
vertex.m_normal = mesh->HasNormals() ?
|
||||
glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z) :
|
||||
glm::vec3(0.0f);
|
||||
|
||||
vertex.m_texCoords = mesh->mTextureCoords[0] ?
|
||||
glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y) :
|
||||
glm::vec2(0.0f);
|
||||
|
||||
vertex.m_tangent = mesh->HasTangentsAndBitangents() ?
|
||||
glm::vec3(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z) :
|
||||
glm::vec3(0.0f);
|
||||
|
||||
vertex.m_bitangent = mesh->HasTangentsAndBitangents() ?
|
||||
glm::vec3(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z) :
|
||||
glm::vec3(0.0f);
|
||||
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
// indices
|
||||
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
|
||||
aiFace face = mesh->mFaces[i];
|
||||
for (uint32_t j = 0; j < face.mNumIndices; j++)
|
||||
indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
|
||||
// material
|
||||
CMaterial* material = nullptr;
|
||||
if (mesh->mMaterialIndex >= 0) {
|
||||
material = processMaterial(
|
||||
scene->mMaterials[mesh->mMaterialIndex],
|
||||
directory,
|
||||
rm
|
||||
);
|
||||
}
|
||||
|
||||
// crée et enregistre le mesh
|
||||
auto newMesh = std::make_unique<CMesh>();
|
||||
newMesh->setVertices(vertices);
|
||||
newMesh->setIndexes(indices);
|
||||
if (material) newMesh->setMaterial(material);
|
||||
newMesh->load();
|
||||
|
||||
auto* ptr = newMesh.get();
|
||||
rm.getMeshManager().addMesh(directory, std::move(newMesh));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
CMaterial* CModelLoader::processMaterial(aiMaterial* mat, const std::string& directory, CResourceManager& rm)
|
||||
{
|
||||
auto newMat = std::make_unique<CMaterial>();
|
||||
|
||||
// albedo
|
||||
if (mat->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
|
||||
aiString path;
|
||||
mat->GetTexture(aiTextureType_DIFFUSE, 0, &path);
|
||||
newMat->textureAlbedo = loadTexture(
|
||||
directory + "/" + path.C_Str(), rm
|
||||
);
|
||||
}
|
||||
|
||||
// normal
|
||||
if (mat->GetTextureCount(aiTextureType_NORMALS) > 0) {
|
||||
aiString path;
|
||||
mat->GetTexture(aiTextureType_NORMALS, 0, &path);
|
||||
newMat->textureNormal = loadTexture(
|
||||
directory + "/" + path.C_Str(), rm
|
||||
);
|
||||
}
|
||||
|
||||
auto shader = GraphicsAPI::getAPI()->getShaderManager().get("triangle");
|
||||
newMat->shader = static_cast<CShaderImplVulkan*>(shader);
|
||||
newMat->build();
|
||||
|
||||
auto* ptr = newMat.get();
|
||||
rm.getMaterialManager().addMaterial(directory, std::move(newMat));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
CTexture* CModelLoader::loadTexture(const std::string& directory, CResourceManager& rm)
|
||||
{
|
||||
auto text = rm.getTextureManager().get(directory);
|
||||
if(rm.getTextureManager().get(directory))
|
||||
{
|
||||
return text.value();
|
||||
}
|
||||
else {
|
||||
auto tex = std::make_unique<CTexture>(directory);
|
||||
tex->init();
|
||||
|
||||
auto* ptr = tex.get();
|
||||
rm.getTextureManager().addTexture(directory, std::move(tex));
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,15 @@
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include "../../Model/Graphic/Texture/CImageTexture.hpp"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include "../../Model/Graphic/Mesh/CMesh.hpp"
|
||||
#include "../../Model/Graphic/CModel.hpp"
|
||||
#include "../../Model/Node/CScene.hpp"
|
||||
#include "../../Controller/CKernel.hpp"
|
||||
#include "../../Context/CContext.hpp"
|
||||
|
||||
#include "CResourceManager.hpp"
|
||||
#include "Mesh/CMesh.hpp"
|
||||
#include "Texture/CTexture.hpp"
|
||||
|
||||
/**
|
||||
* @brief Class allowing to load models from obj files.
|
||||
*/
|
||||
#include <filesystem>
|
||||
class CModelLoader {
|
||||
private:
|
||||
/**
|
||||
@@ -26,7 +23,7 @@ private:
|
||||
* @param[in] meshes The mesh list.
|
||||
* @param[in] material A pointer to a material. It's optionnal and override the obj's material.
|
||||
*/
|
||||
static void processNode(aiNode* node, const aiScene* scene, std::vector<CMesh*>* meshes, SMaterial* material);
|
||||
static void processNode(aiNode* node, const aiScene* scene, const std::string& directory, CResourceManager& rm, std::vector<CMesh*>& meshes);
|
||||
|
||||
/**
|
||||
* @brief Compute every meshes.
|
||||
@@ -35,7 +32,7 @@ private:
|
||||
* @param[in] meshes The list of meshes.
|
||||
* @param[in] material A pointer to a material. It's optionnal and override the obj's material.
|
||||
*/
|
||||
static void processMesh(aiMesh* mesh, const aiScene* scene, std::vector<CMesh*>* meshes, SMaterial* material);
|
||||
static CMesh* processMesh(aiMesh* mesh, const aiScene* scene, const std::string& directory, CResourceManager& rm);
|
||||
|
||||
/**
|
||||
* @brief Load Textures from the obj file.
|
||||
@@ -43,7 +40,9 @@ private:
|
||||
* @param[in] type The assimp's texture type.
|
||||
* @param[in] typeName The texture's type.
|
||||
*/
|
||||
static std::vector<CImageTexture*> loadMaterialTextures(aiMaterial* mat, aiTextureType type, ETextureType typeName);
|
||||
static CTexture* loadTexture(const std::string& directory, CResourceManager& rm);
|
||||
|
||||
static CMaterial* processMaterial(aiMaterial* mat, const std::string& directory, CResourceManager& rm);
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -52,7 +51,7 @@ public:
|
||||
* @param[in] material Pointer to a material. It's optionnal and override the obj's material.
|
||||
* @return A dynamically allocated CModel.
|
||||
*/
|
||||
static CModel* loadModel(std::string fileName, SMaterial* material);
|
||||
static CModel* loadModel(std::string filename, CResourceManager& rm);
|
||||
|
||||
};
|
||||
|
||||
32
src/Engine/Core/Graphics/Data/CModelManager.hpp
Normal file
32
src/Engine/Core/Graphics/Data/CModelManager.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef CMODELMANAGER_HPP
|
||||
#define CMODELMANAGER_HPP
|
||||
|
||||
#include "CModel.hpp"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
class CModelManager
|
||||
{
|
||||
public:
|
||||
std::list<std::unique_ptr<CModel>> loadedModel;
|
||||
std::unordered_map<std::string, CModel*> modelsMap;
|
||||
|
||||
void addModel(std::string name, std::unique_ptr<CModel>&& model)
|
||||
{
|
||||
loadedModel.push_back(std::move(model));
|
||||
modelsMap[name] = loadedModel.back().get();
|
||||
}
|
||||
std::optional<CModel*> get(std::string name)
|
||||
{
|
||||
auto find = modelsMap.find(name);
|
||||
if(find != modelsMap.end())
|
||||
{
|
||||
return find->second;
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
28
src/Engine/Core/Graphics/Data/CResourceManager.hpp
Normal file
28
src/Engine/Core/Graphics/Data/CResourceManager.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef CRESOURCEMANAGER_HPP
|
||||
#define CRESOURCEMANAGER_HPP
|
||||
|
||||
#include "CModelManager.hpp"
|
||||
#include "Mesh/CMeshManager.hpp"
|
||||
#include "Material/CMaterialManager.hpp"
|
||||
#include "Texture/CTextureManager.hpp"
|
||||
|
||||
class CResourceManager{
|
||||
private:
|
||||
CModelManager modelManager;
|
||||
CMeshManager meshManager;
|
||||
CMaterialManager materialManager;
|
||||
CTextureManager textureManager;
|
||||
public:
|
||||
CModelManager& getModelManager() { return modelManager; }
|
||||
CMeshManager& getMeshManager() { return meshManager; }
|
||||
CMaterialManager& getMaterialManager() { return materialManager; }
|
||||
CTextureManager& getTextureManager() {return textureManager;}
|
||||
void cleanup(){
|
||||
materialManager.loadedMaterials.clear();
|
||||
meshManager.loadedMeshes.clear();
|
||||
modelManager.loadedModel.clear();
|
||||
textureManager.loadedTextures.clear();
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "CTextTexture.hpp"
|
||||
/*#include "CTextTexture.hpp"
|
||||
|
||||
CTextTexture::CTextTexture(ETextureType type, std::string filePath, std::string text, unsigned int fontSize, glm::vec3 fontColor, glm::bvec4 fontStyle) :
|
||||
CAbstractTexture(type),
|
||||
@@ -108,4 +108,4 @@ void CTextTexture::init(void) {
|
||||
|
||||
// Free the surface.
|
||||
SDL_FreeSurface(sdlSurface);
|
||||
}
|
||||
}*/
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef CTEXTTEXTURE_HPP
|
||||
/*#ifndef CTEXTTEXTURE_HPP
|
||||
#define CTEXTTEXTURE_HPP
|
||||
|
||||
#include "../../../Controller/Exception/CLibException.hpp"
|
||||
@@ -44,4 +44,4 @@ public:
|
||||
virtual void init(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif*/
|
||||
137
src/Engine/Core/Graphics/Data/Material/CMaterial.cpp
Normal file
137
src/Engine/Core/Graphics/Data/Material/CMaterial.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "CMaterial.hpp"
|
||||
#include "../Mesh/SVertex.hpp"
|
||||
#include "../../API/VulkanImpl.hpp"
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
void CMaterial::build()
|
||||
{
|
||||
if(isInit)
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
auto* device= static_cast<vk::raii::Device*>(api->getDevice());
|
||||
auto shaderStages = shader->getShaderStages(0, vk::ShaderStageFlagBits::eVertex, vk::ShaderStageFlagBits::eFragment);
|
||||
|
||||
auto bindingDescription = Vertex::getBindingDescription();
|
||||
auto attributeDescriptions = Vertex::getAttributeDescriptions();
|
||||
vk::PipelineVertexInputStateCreateInfo vertexInputInfo{{}, 1, &bindingDescription, static_cast<uint32_t>(attributeDescriptions.size()), attributeDescriptions.data()};
|
||||
|
||||
vk::PipelineInputAssemblyStateCreateInfo inputAssembly{{},vk::PrimitiveTopology::eTriangleList};
|
||||
vk::PipelineViewportStateCreateInfo viewportState{{},1, {},1};
|
||||
|
||||
vk::PipelineRasterizationStateCreateInfo rasterizer{{},vk::False, vk::False, vk::PolygonMode::eFill,vk::CullModeFlagBits::eBack, vk::FrontFace::eCounterClockwise, vk::False, {}, {}, 1.0f, 1.0f};
|
||||
|
||||
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::PipelineColorBlendStateCreateInfo colorBlending{{},vk::False, vk::LogicOp::eCopy, 1, &colorBlendAttachment};
|
||||
|
||||
vk::PipelineDepthStencilStateCreateInfo depthStencil{{},
|
||||
vk::True,
|
||||
vk::True,
|
||||
vk::CompareOp::eLess,
|
||||
vk::False,
|
||||
vk::False};
|
||||
|
||||
std::vector dynamicStates = {
|
||||
vk::DynamicState::eViewport,
|
||||
vk::DynamicState::eScissor};
|
||||
vk::PipelineDynamicStateCreateInfo dynamicState{{}, static_cast<uint32_t>(dynamicStates.size()), dynamicStates.data()};
|
||||
|
||||
std::array<vk::DescriptorSetLayout, 3> layouts{
|
||||
*api->getCameraLayout(), // set 0
|
||||
*api->getTransformLayout(), // set 1
|
||||
*api->getMaterialLayout() // set 2
|
||||
};
|
||||
|
||||
vk::PipelineLayoutCreateInfo pipelineLayoutInfo{{},3,layouts.data(), 0};
|
||||
|
||||
pipelineLayout = vk::raii::PipelineLayout(*static_cast<vk::raii::Device*>(api->getDevice()), pipelineLayoutInfo);
|
||||
|
||||
vk::StructureChain<vk::GraphicsPipelineCreateInfo, vk::PipelineRenderingCreateInfo> pipelineCreateInfoChain = {
|
||||
{{},
|
||||
2,
|
||||
shaderStages.data(),
|
||||
&vertexInputInfo,
|
||||
&inputAssembly,
|
||||
{},
|
||||
&viewportState,
|
||||
&rasterizer,
|
||||
&multisampling,
|
||||
&depthStencil,
|
||||
&colorBlending,
|
||||
&dynamicState,
|
||||
pipelineLayout,
|
||||
nullptr
|
||||
},
|
||||
{{},
|
||||
1,
|
||||
&api->getSwapChainFormat().format,
|
||||
api->findDepthFormat()
|
||||
}
|
||||
};
|
||||
|
||||
pipeline = vk::raii::Pipeline(*static_cast<vk::raii::Device*>(api->getDevice()), nullptr, pipelineCreateInfoChain.get<vk::GraphicsPipelineCreateInfo>());
|
||||
|
||||
// descriptor sets du material (set 2)
|
||||
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
m_descriptorSets[i] = api->getDescriptorPoolManager().allocate(
|
||||
*api->getMaterialLayout()
|
||||
);
|
||||
|
||||
std::vector<vk::WriteDescriptorSet> writes;
|
||||
|
||||
// binding 1 : albedo (si présent)
|
||||
vk::DescriptorImageInfo albedoInfo;
|
||||
if (textureAlbedo) {
|
||||
albedoInfo = {
|
||||
*textureAlbedo->getSampler(),
|
||||
*textureAlbedo->getImageView(),
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal
|
||||
};
|
||||
writes.push_back({
|
||||
*m_descriptorSets[i].set,
|
||||
1, 0, 1,
|
||||
vk::DescriptorType::eCombinedImageSampler,
|
||||
&albedoInfo
|
||||
});
|
||||
}
|
||||
else {
|
||||
albedoInfo = {
|
||||
api->getDefaultTexture()->getSampler(),
|
||||
api->getDefaultTexture()->getImageView(),
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal
|
||||
};
|
||||
writes.push_back({
|
||||
*m_descriptorSets[i].set,
|
||||
1, 0, 1,
|
||||
vk::DescriptorType::eCombinedImageSampler,
|
||||
&albedoInfo
|
||||
});
|
||||
}
|
||||
|
||||
if (!writes.empty())
|
||||
device->updateDescriptorSets(writes, {});
|
||||
}
|
||||
isInit = true;
|
||||
}
|
||||
|
||||
CMaterial::~CMaterial()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void CMaterial::destroy()
|
||||
{
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
uint32_t currentFrame = api->getCurrentFrameIndex();
|
||||
|
||||
api->destroyPipeline(pipeline, pipelineLayout);
|
||||
|
||||
// descriptor sets
|
||||
for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
api->destroyDescriptorSet(m_descriptorSets[i], i);
|
||||
}
|
||||
}
|
||||
30
src/Engine/Core/Graphics/Data/Material/CMaterial.hpp
Normal file
30
src/Engine/Core/Graphics/Data/Material/CMaterial.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef SMATERIAL_HPP
|
||||
#define SMATERIAL_HPP
|
||||
|
||||
#include "../../Shader/Implementations/CShaderImplVulkan.hpp"
|
||||
#include "../../API/ManagedDescriptorSet.hpp"
|
||||
#include "SColor.hpp"
|
||||
#include "../Texture/CTexture.hpp"
|
||||
|
||||
class CMaterial {
|
||||
public:
|
||||
|
||||
~CMaterial();
|
||||
void destroy();
|
||||
bool isInit = false;
|
||||
SColor m_color;
|
||||
CTexture* textureAlbedo = nullptr;
|
||||
CTexture* textureNormal = nullptr;
|
||||
CShaderImplVulkan* shader;
|
||||
vk::raii::PipelineLayout pipelineLayout = nullptr;
|
||||
vk::raii::Pipeline pipeline = nullptr;
|
||||
std::array<ManagedDescriptorSet, MAX_FRAMES_IN_FLIGHT> m_descriptorSets;
|
||||
void build();
|
||||
vk::raii::Pipeline& getPipeline(){return pipeline;};
|
||||
vk::raii::PipelineLayout& getPipelineLayout(){return pipelineLayout;};
|
||||
vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) {
|
||||
return m_descriptorSets[frameIndex].set;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
31
src/Engine/Core/Graphics/Data/Material/CMaterialManager.hpp
Normal file
31
src/Engine/Core/Graphics/Data/Material/CMaterialManager.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef CMATERIALMANAGER_HPP
|
||||
#define CMATERIALMANAGER_HPP
|
||||
|
||||
#include "CMaterial.hpp"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
class CMaterialManager
|
||||
{
|
||||
public:
|
||||
std::list<std::unique_ptr<CMaterial>> loadedMaterials;
|
||||
std::unordered_map<std::string, CMaterial*> materialsMap;
|
||||
void addMaterial(std::string name, std::unique_ptr<CMaterial>&& mat)
|
||||
{
|
||||
loadedMaterials.push_back(std::move(mat));
|
||||
materialsMap[name] = loadedMaterials.back().get();
|
||||
}
|
||||
std::optional<CMaterial*> get(std::string name)
|
||||
{
|
||||
auto find = materialsMap.find(name);
|
||||
if(find != materialsMap.end())
|
||||
{
|
||||
return find->second;
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
107
src/Engine/Core/Graphics/Data/Mesh/CMesh.cpp
Normal file
107
src/Engine/Core/Graphics/Data/Mesh/CMesh.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "CMesh.hpp"
|
||||
#include "../../API/VulkanImpl.hpp"
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
CMesh::CMesh(void) :
|
||||
m_vertexes() {
|
||||
}
|
||||
|
||||
CMesh::~CMesh(void) {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void CMesh::destroy()
|
||||
{
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
api->destroyBuffer(vertexIndexBuffer, api->getCurrentFrameIndex());
|
||||
/*if (api && vertexIndexBuffer.buffer != VK_NULL_HANDLE)
|
||||
vmaDestroyBuffer(api->getAllocator(), vertexIndexBuffer.buffer, vertexIndexBuffer.allocation);*/
|
||||
}
|
||||
std::vector<SVertex>& CMesh::getVertices(void) {
|
||||
return m_vertexes;
|
||||
}
|
||||
|
||||
|
||||
void CMesh::setVertices(std::vector<SVertex> vertices)
|
||||
{
|
||||
m_vertexes = vertices;
|
||||
}
|
||||
void CMesh::setIndexes(std::vector<uint32_t> indexes){
|
||||
m_indexes = indexes;
|
||||
}
|
||||
|
||||
std::vector<uint32_t>& CMesh::getIndexes(void){
|
||||
return m_indexes;
|
||||
}
|
||||
|
||||
/*void CMesh::load(void) {
|
||||
vk::BufferCreateInfo bufferInfo{{},sizeof(m_vertexes[0]) * m_vertexes.size(), vk::BufferUsageFlagBits::eVertexBuffer, vk::SharingMode::eExclusive};
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
vertexBuffer = vk::raii::Buffer(*static_cast<vk::raii::Device*>(api->getDevice()), bufferInfo);
|
||||
|
||||
vk::MemoryRequirements memRequirements = vertexBuffer.getMemoryRequirements();
|
||||
vk::MemoryAllocateInfo memoryAllocateInfo{memRequirements.size, api->findMemoryType(memRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent)};
|
||||
vertexBufferMemory = vk::raii::DeviceMemory(*static_cast<vk::raii::Device*>(api->getDevice()), memoryAllocateInfo);
|
||||
|
||||
vertexBuffer.bindMemory(*vertexBufferMemory, 0);
|
||||
|
||||
void *data = vertexBufferMemory.mapMemory(0, bufferInfo.size);
|
||||
memcpy(data, m_vertexes.data(), bufferInfo.size);
|
||||
vertexBufferMemory.unmapMemory();
|
||||
}*/
|
||||
|
||||
void CMesh::load(void) {
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
VmaAllocator allocator = api->getAllocator();
|
||||
|
||||
VkDeviceSize vertexSize = sizeof(m_vertexes[0]) * m_vertexes.size();
|
||||
VkDeviceSize indexSize = sizeof(m_indexes[0]) * m_indexes.size();
|
||||
VkDeviceSize totalSize = vertexSize + indexSize;
|
||||
|
||||
// 1. staging buffer - CPU visible, temporaire
|
||||
VkBufferCreateInfo stagingBufferInfo{};
|
||||
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
stagingBufferInfo.size = totalSize;
|
||||
stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
VmaAllocationCreateInfo stagingAllocInfo{};
|
||||
stagingAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
|
||||
stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
|
||||
VMABuffer stagingBuffer;
|
||||
VmaAllocationInfo stagingInfo{};
|
||||
vmaCreateBuffer(allocator, &stagingBufferInfo, &stagingAllocInfo,
|
||||
&stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo);
|
||||
|
||||
// 2. 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
|
||||
VkBufferCreateInfo vertexBufferInfo{};
|
||||
vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
vertexBufferInfo.size = totalSize;
|
||||
vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
VmaAllocationCreateInfo vertexAllocInfo{};
|
||||
vertexAllocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
|
||||
vmaCreateBuffer(allocator, &vertexBufferInfo, &vertexAllocInfo,
|
||||
&vertexIndexBuffer.buffer, &vertexIndexBuffer.allocation, nullptr);
|
||||
|
||||
// 4. 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
|
||||
vmaDestroyBuffer(allocator, stagingBuffer.buffer, stagingBuffer.allocation);
|
||||
}
|
||||
|
||||
/*void CMesh::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) {
|
||||
|
||||
}*/
|
||||
53
src/Engine/Core/Graphics/Data/Mesh/CMesh.hpp
Normal file
53
src/Engine/Core/Graphics/Data/Mesh/CMesh.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef CMESH_HPP
|
||||
#define CMESH_HPP
|
||||
|
||||
#include "SVertex.hpp"
|
||||
#include "../Material/CMaterial.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/glm.hpp>
|
||||
#include "../../API/VMABuffer.hpp"
|
||||
|
||||
class CMesh {
|
||||
private:
|
||||
|
||||
std::vector<Vertex> m_vertexes;
|
||||
std::vector<uint32_t> m_indexes;
|
||||
|
||||
VMABuffer vertexIndexBuffer;
|
||||
VkDeviceSize m_vertexOffset = 0;
|
||||
VkDeviceSize m_indexOffset = 0;
|
||||
uint32_t m_indexCount = 0;
|
||||
|
||||
CMaterial* m_material;
|
||||
|
||||
public:
|
||||
|
||||
CMesh(void);
|
||||
|
||||
~CMesh(void);
|
||||
|
||||
std::vector<SVertex>& getVertices(void);
|
||||
std::vector<uint32_t>& getIndexes(void);
|
||||
|
||||
void setVertices(std::vector<SVertex> vertices);
|
||||
void setIndexes(std::vector<uint32_t> indexes);
|
||||
|
||||
void setMaterial(CMaterial* mat){m_material = mat;};
|
||||
|
||||
void load(void);
|
||||
|
||||
//void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity);
|
||||
|
||||
CMaterial* getMaterial(){return m_material;};
|
||||
VMABuffer& getVertexIndexBuffer(){return vertexIndexBuffer;};
|
||||
VkDeviceSize getVertexOffset(){return m_vertexOffset;}
|
||||
VkDeviceSize getIndexOffset(){return m_indexOffset;};
|
||||
uint32_t getIndexCount(){return m_indexCount;};
|
||||
void destroy();
|
||||
};
|
||||
|
||||
#endif
|
||||
31
src/Engine/Core/Graphics/Data/Mesh/CMeshManager.hpp
Normal file
31
src/Engine/Core/Graphics/Data/Mesh/CMeshManager.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef CMESHMANAGER_HPP
|
||||
#define CMESHMANAGER_HPP
|
||||
|
||||
#include "CMesh.hpp"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
class CMeshManager
|
||||
{
|
||||
public:
|
||||
std::list<std::unique_ptr<CMesh>> loadedMeshes;
|
||||
std::unordered_map<std::string, CMesh*> meshesMap;
|
||||
void addMesh(std::string name, std::unique_ptr<CMesh>&& mesh)
|
||||
{
|
||||
loadedMeshes.push_back(std::move(mesh));
|
||||
meshesMap[name] = loadedMeshes.back().get();
|
||||
}
|
||||
|
||||
std::optional<CMesh*> get(std::string name)
|
||||
{
|
||||
auto find = meshesMap.find(name);
|
||||
if(find != meshesMap.end())
|
||||
{
|
||||
return find->second;
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
70
src/Engine/Core/Graphics/Data/Mesh/SVertex.hpp
Normal file
70
src/Engine/Core/Graphics/Data/Mesh/SVertex.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef SVERTEX_HPP
|
||||
#define SVERTEX_HPP
|
||||
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/**
|
||||
* @file SVertex.hpp
|
||||
* @brief File for the vertex struct.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief the struct Vertex, use to represent vertex and vertex attribute.
|
||||
*/
|
||||
typedef struct SVertex{
|
||||
/**
|
||||
* @brief Position attribute.
|
||||
* 3D vector.
|
||||
*/
|
||||
glm::vec3 m_position;
|
||||
|
||||
/**
|
||||
* @brief Position attribute.
|
||||
* 3D vector.
|
||||
*/
|
||||
glm::vec4 m_color;
|
||||
/**
|
||||
* @brief Normal attribute.
|
||||
* 3D vector.
|
||||
*/
|
||||
glm::vec3 m_normal;
|
||||
|
||||
/**
|
||||
* @brief Texture coordinates attribute.
|
||||
* 2D vector.
|
||||
*/
|
||||
glm::vec2 m_texCoords;
|
||||
|
||||
/**
|
||||
* @brief Tangent attribute.
|
||||
* 3D vector.
|
||||
*/
|
||||
glm::vec3 m_tangent;
|
||||
|
||||
/**
|
||||
* @brief Bitangent attribute.
|
||||
* 3D vector (perpendicular to m_tangent vector).
|
||||
*/
|
||||
glm::vec3 m_bitangent;
|
||||
|
||||
// m_normal, m_tangent, m_bitangent are supposed to create a vector base to compute normal map.
|
||||
|
||||
static vk::VertexInputBindingDescription getBindingDescription() {
|
||||
return { 0, sizeof(SVertex), vk::VertexInputRate::eVertex };
|
||||
}
|
||||
|
||||
static std::array<vk::VertexInputAttributeDescription, 6> getAttributeDescriptions() {
|
||||
return {
|
||||
vk::VertexInputAttributeDescription( 0, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_position) ),
|
||||
vk::VertexInputAttributeDescription( 1, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(SVertex, m_color) ),
|
||||
vk::VertexInputAttributeDescription( 2, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_normal) ),
|
||||
vk::VertexInputAttributeDescription( 3, 0, vk::Format::eR32G32Sfloat, offsetof(SVertex, m_texCoords) ),
|
||||
vk::VertexInputAttributeDescription( 4, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_tangent) ),
|
||||
vk::VertexInputAttributeDescription( 5, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_bitangent) )
|
||||
};
|
||||
}
|
||||
|
||||
} Vertex;
|
||||
|
||||
#endif
|
||||
219
src/Engine/Core/Graphics/Data/Texture/CTexture.cpp
Normal file
219
src/Engine/Core/Graphics/Data/Texture/CTexture.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "CTexture.hpp"
|
||||
|
||||
#include "../../API/VulkanImpl.hpp"
|
||||
|
||||
CTexture::CTexture(std::string filePath) :
|
||||
m_filePath(filePath) {
|
||||
}
|
||||
|
||||
std::string CTexture::getFilePath(void) {
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void CTexture::setFilePath(std::string filePath) {
|
||||
m_filePath = filePath;
|
||||
}
|
||||
|
||||
void CTexture::init(void) {
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
auto* device= static_cast<vk::raii::Device*>(api->getDevice());
|
||||
// Read the image file.
|
||||
SDL_Surface* sdlSurface = IMG_Load(m_filePath.c_str());
|
||||
|
||||
if(sdlSurface == nullptr)
|
||||
{
|
||||
//error here
|
||||
}
|
||||
|
||||
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;
|
||||
} else if (sdlFormat == SDL_PIXELFORMAT_BGRA32) {
|
||||
// déjà BGRA, pas de conversion mais format différent
|
||||
converted = sdlSurface;
|
||||
m_format = vk::Format::eB8G8R8A8Srgb;
|
||||
} 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_width = converted->w;
|
||||
m_height = converted->h;
|
||||
VkDeviceSize imageSize = m_width * m_height * 4;
|
||||
|
||||
// 2. staging buffer
|
||||
VkBufferCreateInfo stagingBufferInfo{};
|
||||
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
stagingBufferInfo.size = imageSize;
|
||||
stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
VmaAllocationCreateInfo stagingAllocInfo{};
|
||||
stagingAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
|
||||
stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
|
||||
VMABuffer stagingBuffer;
|
||||
VmaAllocationInfo stagingInfo{};
|
||||
vmaCreateBuffer(api->getAllocator(), &stagingBufferInfo, &stagingAllocInfo,
|
||||
&stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo);
|
||||
|
||||
memcpy(stagingInfo.pMappedData, converted->pixels, imageSize);
|
||||
// Free the surface.
|
||||
SDL_DestroySurface(converted);
|
||||
|
||||
// 3. crée l'image GPU
|
||||
api->createImage(
|
||||
m_width, m_height,
|
||||
m_format,
|
||||
vk::ImageTiling::eOptimal,
|
||||
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
|
||||
vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||
m_textureImage,
|
||||
m_textureImageMemory
|
||||
);
|
||||
|
||||
// 4. transitions et copie
|
||||
api->transitionImageLayout(m_textureImage,
|
||||
vk::ImageLayout::eUndefined,
|
||||
vk::ImageLayout::eTransferDstOptimal);
|
||||
|
||||
{
|
||||
auto cmd = api->beginSingleTimeCommands();
|
||||
vk::BufferImageCopy region{
|
||||
0, 0, 0,
|
||||
{vk::ImageAspectFlagBits::eColor, 0, 0, 1},
|
||||
{0, 0, 0},
|
||||
{static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height), 1}
|
||||
};
|
||||
cmd.copyBufferToImage(
|
||||
vk::Buffer(stagingBuffer.buffer),
|
||||
m_textureImage,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
region
|
||||
);
|
||||
api->endSingleTimeCommands(cmd);
|
||||
}
|
||||
|
||||
api->transitionImageLayout(m_textureImage,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
vmaDestroyBuffer(api->getAllocator(), stagingBuffer.buffer, stagingBuffer.allocation);
|
||||
|
||||
// 5. image view
|
||||
m_imageView = api->createImageView(m_textureImage, m_format, vk::ImageAspectFlagBits::eColor);
|
||||
|
||||
// 6. 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.unnormalizedCoordinates = vk::False;
|
||||
samplerInfo.compareEnable = vk::False;
|
||||
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
|
||||
|
||||
m_sampler = vk::raii::Sampler(*device, samplerInfo);
|
||||
|
||||
}
|
||||
|
||||
void CTexture::initDefaultTexture()
|
||||
{
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
auto* device= static_cast<vk::raii::Device*>(api->getDevice());
|
||||
|
||||
// pixel blanc 1x1 RGBA
|
||||
uint32_t whitePixel = 0x00000ff0;
|
||||
uint32_t width = 1;
|
||||
uint32_t height = 1;
|
||||
VkDeviceSize imageSize = sizeof(uint32_t);
|
||||
|
||||
// staging buffer
|
||||
VkBufferCreateInfo stagingBufferInfo{};
|
||||
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
stagingBufferInfo.size = imageSize;
|
||||
stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
VmaAllocationCreateInfo stagingAllocInfo{};
|
||||
stagingAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
|
||||
stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
|
||||
VMABuffer stagingBuffer;
|
||||
VmaAllocationInfo stagingInfo{};
|
||||
vmaCreateBuffer(api->getAllocator(), &stagingBufferInfo, &stagingAllocInfo,
|
||||
&stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo);
|
||||
|
||||
memcpy(stagingInfo.pMappedData, &whitePixel, imageSize);
|
||||
|
||||
// image GPU
|
||||
api->createImage(width, height,
|
||||
vk::Format::eR8G8B8A8Srgb,
|
||||
vk::ImageTiling::eOptimal,
|
||||
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
|
||||
vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||
m_textureImage,
|
||||
m_textureImageMemory
|
||||
);
|
||||
|
||||
api->transitionImageLayout(m_textureImage,
|
||||
vk::ImageLayout::eUndefined,
|
||||
vk::ImageLayout::eTransferDstOptimal);
|
||||
|
||||
{
|
||||
auto cmd = api->beginSingleTimeCommands();
|
||||
vk::BufferImageCopy region{
|
||||
0, 0, 0,
|
||||
{vk::ImageAspectFlagBits::eColor, 0, 0, 1},
|
||||
{0, 0, 0},
|
||||
{width, height, 1}
|
||||
};
|
||||
cmd.copyBufferToImage(
|
||||
vk::Buffer(stagingBuffer.buffer),
|
||||
m_textureImage,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
region
|
||||
);
|
||||
api->endSingleTimeCommands(cmd);
|
||||
}
|
||||
|
||||
api->transitionImageLayout(m_textureImage,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
vmaDestroyBuffer(api->getAllocator(), stagingBuffer.buffer, stagingBuffer.allocation);
|
||||
|
||||
// image view
|
||||
m_imageView = api->createImageView(
|
||||
m_textureImage,
|
||||
vk::Format::eR8G8B8A8Srgb,
|
||||
vk::ImageAspectFlagBits::eColor
|
||||
);
|
||||
|
||||
// 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::False;
|
||||
samplerInfo.maxAnisotropy = 1.0f;
|
||||
samplerInfo.borderColor = vk::BorderColor::eIntOpaqueBlack;
|
||||
samplerInfo.unnormalizedCoordinates = vk::False;
|
||||
samplerInfo.compareEnable = vk::False;
|
||||
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
|
||||
|
||||
m_sampler = vk::raii::Sampler(*device, samplerInfo);
|
||||
}
|
||||
45
src/Engine/Core/Graphics/Data/Texture/CTexture.hpp
Normal file
45
src/Engine/Core/Graphics/Data/Texture/CTexture.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef CTEXTURE_HPP
|
||||
#define CTEXTURE_HPP
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
#include <string>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
|
||||
class CTexture{
|
||||
private:
|
||||
// Path of the file.
|
||||
std::string m_filePath;
|
||||
vk::raii::Image m_textureImage = nullptr;
|
||||
vk::raii::DeviceMemory m_textureImageMemory = nullptr;
|
||||
vk::raii::ImageView m_imageView = nullptr;
|
||||
vk::raii::Sampler m_sampler = nullptr;
|
||||
|
||||
uint32_t m_width = 0;
|
||||
uint32_t m_height = 0;
|
||||
vk::Format m_format = vk::Format::eR8G8B8A8Srgb;
|
||||
|
||||
public:
|
||||
CTexture(void) = delete;
|
||||
CTexture(const CTexture&) = delete;
|
||||
CTexture& operator=(const CTexture&) = delete;
|
||||
~CTexture(void) {
|
||||
m_sampler = nullptr;
|
||||
m_imageView = nullptr;
|
||||
m_textureImage = nullptr;
|
||||
m_textureImageMemory = nullptr;
|
||||
};
|
||||
CTexture(std::string filePath);
|
||||
std::string getFilePath(void);
|
||||
void setFilePath(std::string filePath);
|
||||
void init(void);
|
||||
void initDefaultTexture();
|
||||
|
||||
vk::raii::ImageView& getImageView() { return m_imageView; }
|
||||
vk::raii::Sampler& getSampler() { return m_sampler; }
|
||||
uint32_t getWidth() const { return m_width; }
|
||||
uint32_t getHeight() const { return m_height; }
|
||||
};
|
||||
|
||||
#endif
|
||||
32
src/Engine/Core/Graphics/Data/Texture/CTextureManager.hpp
Normal file
32
src/Engine/Core/Graphics/Data/Texture/CTextureManager.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef CTEXTUREMANAGER_HPP
|
||||
#define CTEXTUREMANAGER_HPP
|
||||
|
||||
#include "CTexture.hpp"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
class CTextureManager
|
||||
{
|
||||
public:
|
||||
std::list<std::unique_ptr<CTexture>> loadedTextures;
|
||||
std::unordered_map<std::string, CTexture*> texturesMap;
|
||||
void addTexture(std::string name, std::unique_ptr<CTexture>&& text)
|
||||
{
|
||||
loadedTextures.push_back(std::move(text));
|
||||
texturesMap[name] = loadedTextures.back().get();
|
||||
}
|
||||
std::optional<CTexture*> get(std::string name)
|
||||
{
|
||||
auto find = texturesMap.find(name);
|
||||
if(find != texturesMap.end())
|
||||
{
|
||||
return find->second;
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,24 +1,17 @@
|
||||
#include "CShadersManager.hpp"
|
||||
|
||||
#include "CShaderFactory.hpp"
|
||||
#include "../CKernel.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
CShadersManager::CShadersManager(void) :m_shadersMap(), m_shaderList(nullptr) {
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include "../../../Utils/Factory/CShaderFactory.hpp"
|
||||
CShadersManager::CShadersManager(void) :m_shadersMap() {
|
||||
|
||||
}
|
||||
|
||||
CShadersManager::~CShadersManager(void) {
|
||||
for (std::pair<const std::string, CShader*>& it : m_shadersMap)
|
||||
{
|
||||
delete it.second;
|
||||
}
|
||||
free(m_shaderList);
|
||||
}
|
||||
|
||||
CShader* CShadersManager::get(std::string name) const {
|
||||
std::map<std::string, CShader*>::const_iterator it = m_shadersMap.find(name);
|
||||
std::unordered_map<std::string, CShader*>::const_iterator it = m_shadersMap.find(name);
|
||||
if (it == m_shadersMap.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -28,60 +21,33 @@ CShader* CShadersManager::get(std::string name) const {
|
||||
}
|
||||
|
||||
void CShadersManager::create(void) {
|
||||
if (std::filesystem::is_directory(CEngineConfiguration::configuration->getGlobalShadersPath())) {
|
||||
for (std::filesystem::directory_iterator itr(CEngineConfiguration::configuration->getGlobalShadersPath()); itr != std::filesystem::directory_iterator(); ++itr) {
|
||||
std::filesystem::path shaderDir = std::filesystem::absolute(SHADERS_FOLDER);
|
||||
if (std::filesystem::is_directory(shaderDir)) {
|
||||
for (std::filesystem::directory_iterator itr(shaderDir); itr != std::filesystem::directory_iterator(); ++itr) {
|
||||
if (std::filesystem::is_regular_file(itr->status())) {
|
||||
DEBUG_LOG(trace, "Kernel", "ShadersManager", "Shader : " + itr->path().string() + " found.")
|
||||
|
||||
CFileManager jsonfm(itr->path().string());
|
||||
std::string json = jsonfm.read();
|
||||
std::ifstream jsonfm(itr->path().string());
|
||||
try {
|
||||
nlohmann::json shaderJson = nlohmann::json::parse(json);
|
||||
std::string name = shaderJson["name"];
|
||||
std::string vert = shaderJson["vert"];
|
||||
std::string frag = shaderJson["frag"];
|
||||
|
||||
CShader* newShader = CShaderFactory::createShader(CKernel::m_kernel ,name, CEngineConfiguration::configuration->getGlobalShadersPath().string() + std::string("/") + vert, CEngineConfiguration::configuration->getGlobalShadersPath().string() + std::string("/") + frag);
|
||||
|
||||
m_shadersMap.insert(std::pair<std::string, CShader*>(name, newShader));
|
||||
auto shader = CosmicUtils::CShaderFactory::create(itr->path().stem(), itr->path());
|
||||
shaders.push_back(std::move(shader));
|
||||
m_shadersMap.insert(std::make_pair(itr->path().stem(), shaders.back().get()));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
throw CJsonException(std::string("Failed to parse and retrieve data from the json file ") + itr->path().string() + ": " + e.what());
|
||||
//throw CJsonException(std::string("Failed to parse and retrieve data from the json file ") + itr->path().string() + ": " + e.what());
|
||||
}
|
||||
|
||||
DEBUG_LOG(trace, "Kernel", "ShadersManager", "Shader : " + itr->path().string() + " successfully retrieved.")
|
||||
}
|
||||
}
|
||||
|
||||
m_shaderList = (CShader**)malloc(sizeof(CShader*) * m_shadersMap.size());
|
||||
|
||||
if (m_shaderList == NULL) {
|
||||
throw CRuntimeException("unable to alloc shaders list");
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
|
||||
for (std::pair<std::string, CShader*> it : m_shadersMap)
|
||||
{
|
||||
m_shaderList[i] = it.second;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
throw CFileException(std::string("Failed to find the shaders folder : ") + CKernel::m_kernel->getEngineConfig()->getGlobalShadersPath().string());
|
||||
//throw CFileException(std::string("Failed to find the shaders folder : ") + CKernel::m_kernel->getEngineConfig()->getGlobalShadersPath().string());
|
||||
}
|
||||
}
|
||||
|
||||
void CShadersManager::compile(void) {
|
||||
DEBUG_LOG(trace, "Kernel", "ShadersManager", "Starting compiling shaders files.");
|
||||
|
||||
unsigned int nbShader = m_shadersMap.size();
|
||||
|
||||
for (unsigned int i = 0; i < nbShader; i++)
|
||||
for (auto& el: shaders)
|
||||
{
|
||||
m_shaderList[i]->init();
|
||||
el->init();
|
||||
}
|
||||
|
||||
DEBUG_LOG(trace, "Kernel", "ShadersManager", "All shaders are ready to use.")
|
||||
}
|
||||
@@ -1,68 +1,45 @@
|
||||
#ifndef CSHADERSMANAGER_HPP
|
||||
#define CSHADERSMANAGER_HPP
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../../Model/Graphic/Shader/CShader.hpp"
|
||||
#include "../../Context/CContext.hpp"
|
||||
#include "CShader.hpp"
|
||||
|
||||
#include "../Exception/CJsonException.hpp"
|
||||
#include "../Exception/CFileException.hpp"
|
||||
#include "../Exception/CRuntimeException.hpp"
|
||||
#define SHADERS_FOLDER "assets/shaders/slang/spv"
|
||||
|
||||
/*#ifdef WIN32
|
||||
#define SHADERS_FOLDER "../assets/shaders"
|
||||
#else
|
||||
#define SHADERS_FOLDER "../../assets/shaders"
|
||||
#endif*/
|
||||
|
||||
/**
|
||||
* @brief Class to manage shaders.
|
||||
*/
|
||||
class CShadersManager {
|
||||
private:
|
||||
/**
|
||||
* @brief map to store in a proper way the shaders.
|
||||
*/
|
||||
std::map<std::string, CShader*> m_shadersMap;
|
||||
std::list<std::unique_ptr<CShader>> shaders;
|
||||
std::unordered_map<std::string, CShader*> m_shadersMap;
|
||||
|
||||
CShader** m_shaderList;
|
||||
public:
|
||||
/**
|
||||
* @brief constructor.
|
||||
*/
|
||||
|
||||
CShadersManager(void);
|
||||
|
||||
CShadersManager(const CShadersManager& param) = delete;
|
||||
|
||||
/**
|
||||
* @brief destructor, destroy the shaders of the list.
|
||||
*/
|
||||
~CShadersManager(void);
|
||||
|
||||
CShadersManager& operator=(const CShadersManager& param) = delete;
|
||||
|
||||
/**
|
||||
* @brief get a shader by its name.
|
||||
* @param[in] name shader name.
|
||||
* @return the shader.
|
||||
*/
|
||||
CShader* get(std::string name) const;
|
||||
|
||||
/**
|
||||
* @brief compile and link all the shaders to make them ready to use.
|
||||
*/
|
||||
std::list<std::unique_ptr<CShader>>::const_iterator beginShaders(){return shaders.cbegin();};
|
||||
std::list<std::unique_ptr<CShader>>::const_iterator endShaders(){return shaders.cend();};
|
||||
|
||||
void compile(void);
|
||||
|
||||
/**
|
||||
* @brief search the folder assets/shaders and create the shaders specifieds by a json file.
|
||||
* @post throw an FileException if the shaders folder is not found.
|
||||
*/
|
||||
void create(void);
|
||||
|
||||
void cleanup(){
|
||||
shaders.clear();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
#include "CShaderImplVulkan.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "../../API/GraphicsAPI.hpp"
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
#include <spirv_reflect.h>
|
||||
|
||||
|
||||
CShaderImplVulkan::CShaderImplVulkan(std::string name, std::filesystem::path spvPath): m_name(name), spirvPath(spvPath)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string CShaderImplVulkan::getName(void) const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setName(std::string name) {
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::init()
|
||||
{
|
||||
std::ifstream fileShader(spirvPath, std::ios::binary | std::ios::ate);
|
||||
size_t fileSize = fileShader.tellg();
|
||||
fileShader.seekg(0);
|
||||
|
||||
std::vector<uint32_t> spirv(fileSize / sizeof(uint32_t));
|
||||
fileShader.read(reinterpret_cast<char*>(spirv.data()), fileSize);
|
||||
//spirv.push_back('\0');
|
||||
//fileSize++;
|
||||
fileShader.close();
|
||||
|
||||
vk::ShaderModuleCreateInfo createInfo{ {},fileSize,spirv.data() };
|
||||
shaderModule = vk::raii::ShaderModule(*static_cast<vk::raii::Device*>(GraphicsAPI::getAPI()->getDevice()), createInfo);
|
||||
|
||||
SpvReflectShaderModule module;
|
||||
SpvReflectResult result = spvReflectCreateShaderModule(
|
||||
spirv.size() * sizeof(uint32_t),
|
||||
spirv.data(),
|
||||
&module
|
||||
);
|
||||
assert(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||
|
||||
uint32_t entryPointCount = module.entry_point_count;
|
||||
for (uint32_t i = 0; i < entryPointCount; i++) {
|
||||
const SpvReflectEntryPoint& entry = module.entry_points[i];
|
||||
|
||||
switch (entry.shader_stage) {
|
||||
case SPV_REFLECT_SHADER_STAGE_VERTEX_BIT:
|
||||
stageEntryPoints[vk::ShaderStageFlagBits::eVertex].push_back(entry.name);
|
||||
break;
|
||||
case SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT:
|
||||
stageEntryPoints[vk::ShaderStageFlagBits::eFragment].push_back(entry.name);
|
||||
break;
|
||||
case SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT:
|
||||
stageEntryPoints[vk::ShaderStageFlagBits::eGeometry].push_back(entry.name);
|
||||
break;
|
||||
case SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
|
||||
stageEntryPoints[vk::ShaderStageFlagBits::eTessellationControl].push_back(entry.name);
|
||||
break;
|
||||
case SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
|
||||
stageEntryPoints[vk::ShaderStageFlagBits::eTessellationEvaluation].push_back(entry.name);
|
||||
break;
|
||||
case SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT:
|
||||
stageEntryPoints[vk::ShaderStageFlagBits::eCompute].push_back(entry.name);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
spvReflectDestroyShaderModule(&module);
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setBool(const std::string& name, bool value) const
|
||||
{
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setInt(const std::string& name, int value) const
|
||||
{
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setFloat(const std::string& name, float value) const
|
||||
{
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setMat2(const std::string& name, glm::mat2 value) const {
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setMat3(const std::string& name, glm::mat3 value) const {
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setMat4(const std::string& name, glm::mat4 value) const {
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setVec2(const std::string& name, glm::vec2 value) const {
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setVec3(const std::string& name, glm::vec3 value) const {
|
||||
}
|
||||
|
||||
void CShaderImplVulkan::setVec4(const std::string& name, glm::vec4 value) const {
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#ifndef CSHADEROPENGLIMPLHPP
|
||||
#define CSHADEROPENGLIMPLHPP
|
||||
|
||||
#include "../CShader.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
/**
|
||||
* @file CShaderImplVulkan.hpp
|
||||
* @brief File of CShaderImplVulkan, a Vulkan impl. of CShader to manage shader program.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief a Vulkan impl. of CShader to manage shader program.
|
||||
*/
|
||||
class CShaderImplVulkan : public CShader {
|
||||
private:
|
||||
|
||||
std::string m_name;
|
||||
std::filesystem::path spirvPath;
|
||||
vk::raii::ShaderModule shaderModule = nullptr;
|
||||
vk::raii::Device* device = nullptr;
|
||||
std::unordered_map<vk::ShaderStageFlagBits,std::vector<std::string>> stageEntryPoints;
|
||||
|
||||
public:
|
||||
|
||||
CShaderImplVulkan() = delete;
|
||||
|
||||
CShaderImplVulkan(std::string name, std::string vertexPath, std::string fragmentPath) = delete;
|
||||
|
||||
CShaderImplVulkan(std::string name, std::string vertexPath, std::string fragmentPath, std::string geomPath) = delete;
|
||||
|
||||
CShaderImplVulkan(std::string name, std::filesystem::path spvPath);
|
||||
|
||||
virtual unsigned int getId(void) const {return 0;};
|
||||
|
||||
virtual std::string getName(void) const;
|
||||
|
||||
virtual std::string getVertexPath(void) const {return "";};
|
||||
|
||||
virtual std::string getGeomPath(void) const{return "";};
|
||||
|
||||
virtual std::string getFragmentPath(void) const {return "";};
|
||||
|
||||
virtual void setName(std::string name);
|
||||
|
||||
virtual void setVertexPath(std::string vp) {};
|
||||
|
||||
virtual void setGeomPath(std::string gp) {};
|
||||
|
||||
virtual void setFragmentPath(std::string fp) {};
|
||||
|
||||
virtual bool isReady(void) const {return true;};
|
||||
|
||||
virtual bool hasGeom(void) const {return true;};
|
||||
|
||||
virtual void use(void) {};
|
||||
|
||||
virtual void init(void);
|
||||
|
||||
template <typename... Flags>
|
||||
std::vector<vk::PipelineShaderStageCreateInfo> getShaderStages(unsigned int offset = 0, Flags... flagBits)
|
||||
{
|
||||
std::vector<vk::PipelineShaderStageCreateInfo> pipe;
|
||||
for(auto el : std::initializer_list<vk::ShaderStageFlagBits>{ flagBits... })
|
||||
{
|
||||
//todo assert exists
|
||||
std::string& entry = stageEntryPoints[el][offset];
|
||||
vk::PipelineShaderStageCreateInfo info{{}, el, shaderModule, entry.c_str() };//todo check specialized info ?
|
||||
pipe.push_back(info);
|
||||
}
|
||||
return pipe;
|
||||
}
|
||||
|
||||
virtual void setBool(const std::string& name, bool value) const;
|
||||
|
||||
virtual void setInt(const std::string& name, int value) const;
|
||||
|
||||
virtual void setFloat(const std::string& name, float value) const;
|
||||
|
||||
virtual void setMat2(const std::string& name, glm::mat2 value) const;
|
||||
|
||||
virtual void setMat3(const std::string& name, glm::mat3 value) const;
|
||||
|
||||
virtual void setMat4(const std::string& name, glm::mat4 value) const;
|
||||
|
||||
virtual void setVec2(const std::string& name, glm::vec2 value) const;
|
||||
|
||||
virtual void setVec3(const std::string& name, glm::vec3 value) const;
|
||||
|
||||
virtual void setVec4(const std::string& name, glm::vec4 value) const;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,14 +1,16 @@
|
||||
#include "CGameWindow.hpp"
|
||||
#include <SDL3/SDL_mouse.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
|
||||
CGameWindow::CGameWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen) :
|
||||
CWindow(title, iconPath, width, height, false, false, SDL_WINDOW_OPENGL),
|
||||
CWindow(title, iconPath, width, height, false, false, SDL_WINDOW_VULKAN),
|
||||
m_grabCursor(false),
|
||||
m_relativeCursor(false),
|
||||
m_msaa(0) {
|
||||
}
|
||||
|
||||
CGameWindow::CGameWindow(std::string title, SDL_Window* window) :
|
||||
CWindow(title, window, SDL_WINDOW_OPENGL, 0),
|
||||
CWindow(title, window, SDL_WINDOW_VULKAN),
|
||||
m_grabCursor(false),
|
||||
m_relativeCursor(false),
|
||||
m_msaa(0) {
|
||||
@@ -17,18 +19,18 @@ CGameWindow::CGameWindow(std::string title, SDL_Window* window) :
|
||||
CGameWindow::~CGameWindow(void) {
|
||||
}
|
||||
|
||||
SDL_GLContext CGameWindow::getOpenGLContext(void) {
|
||||
/*SDL_GLContext CGameWindow::getOpenGLContext(void) {
|
||||
if (getWindow() == nullptr) {
|
||||
throw CLogicException("The window must be initialized before using this method !");
|
||||
//throw CLogicException("The window must be initialized before using this method !");
|
||||
}
|
||||
else {
|
||||
SDL_GLContext out = SDL_GL_CreateContext(getWindow());
|
||||
if (out == nullptr) {
|
||||
throw CLibException(std::string("Unable to create OpenGL context: ") + SDL_GetError());
|
||||
//throw CLibException(std::string("Unable to create OpenGL context: ") + SDL_GetError());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
bool CGameWindow::isCursorGrabbed(void) const {
|
||||
return m_grabCursor;
|
||||
@@ -43,10 +45,10 @@ void CGameWindow::setCursorGrabbed(bool newMouseGrab) {
|
||||
|
||||
if (getWindow() != nullptr) {
|
||||
if (m_grabCursor) {
|
||||
SDL_SetWindowGrab(getWindow(), SDL_TRUE);
|
||||
SDL_SetWindowMouseGrab(getWindow(), true);
|
||||
}
|
||||
else {
|
||||
SDL_SetWindowGrab(getWindow(), SDL_FALSE);
|
||||
SDL_SetWindowMouseGrab(getWindow(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,10 +66,10 @@ void CGameWindow::setCursorRelative(bool newMouseRelative) {
|
||||
|
||||
if (getWindow() != nullptr) {
|
||||
if (m_relativeCursor) {
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
SDL_SetWindowRelativeMouseMode(getWindow(), true);
|
||||
}
|
||||
else {
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
SDL_SetWindowRelativeMouseMode(getWindow(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,7 +80,7 @@ unsigned char CGameWindow::getAntiAliasing(void) const {
|
||||
|
||||
void CGameWindow::setAntiAliasing(unsigned char newMsaa) {
|
||||
if (getWindow() != nullptr) {
|
||||
throw CLogicException("The window must be uninitialized before using this method !");
|
||||
//throw CLogicException("The window must be uninitialized before using this method !");
|
||||
}
|
||||
else {
|
||||
if (newMsaa == 2 || newMsaa == 4 || newMsaa == 8 || newMsaa == 16) {
|
||||
@@ -92,7 +94,7 @@ void CGameWindow::setAntiAliasing(unsigned char newMsaa) {
|
||||
|
||||
void CGameWindow::preinitialization(void) {
|
||||
// We want OpenGL version 3.3.
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
/*SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
|
||||
// Anti-aliasing Configuration.
|
||||
@@ -108,7 +110,8 @@ void CGameWindow::preinitialization(void) {
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
// Depht Buffer.
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);*/
|
||||
//TODO init graphic generic (opengl vulkan etc.... commence par vulkan ?)
|
||||
|
||||
}
|
||||
|
||||
@@ -116,17 +119,17 @@ void CGameWindow::postinitialization(void) {
|
||||
|
||||
// Set the cursorGrab property.
|
||||
if (m_grabCursor) {
|
||||
SDL_SetWindowGrab(getWindow(), SDL_TRUE);
|
||||
SDL_SetWindowMouseGrab(getWindow(), true);
|
||||
}
|
||||
else {
|
||||
SDL_SetWindowGrab(getWindow(), SDL_FALSE);
|
||||
SDL_SetWindowMouseGrab(getWindow(), false);
|
||||
}
|
||||
|
||||
// Set the cursorRelative property.
|
||||
if (m_relativeCursor) {
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
SDL_SetWindowRelativeMouseMode(getWindow(), true);
|
||||
}
|
||||
else {
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
SDL_SetWindowRelativeMouseMode(getWindow(), false);
|
||||
}
|
||||
}
|
||||
49
src/Engine/Core/Graphics/Window/CGameWindow.hpp
Normal file
49
src/Engine/Core/Graphics/Window/CGameWindow.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef CGAMEWINDOW_HPP
|
||||
#define CGAMEWINDOW_HPP
|
||||
|
||||
#include "CWindow.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
class CGameWindow : public CWindow {
|
||||
private:
|
||||
// Say if the mouse is grabbed.
|
||||
bool m_grabCursor;
|
||||
|
||||
// Say if the mouse is in relative mode.
|
||||
bool m_relativeCursor;
|
||||
|
||||
// The anti-aliasing.
|
||||
unsigned char m_msaa;
|
||||
|
||||
public:
|
||||
CGameWindow(void) = delete;
|
||||
CGameWindow(const CGameWindow& param) = delete;
|
||||
CGameWindow& operator=(const CGameWindow& param) = delete;
|
||||
|
||||
CGameWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen);
|
||||
|
||||
CGameWindow(std::string title, SDL_Window* window);
|
||||
|
||||
~CGameWindow(void);
|
||||
|
||||
bool isCursorGrabbed(void) const;
|
||||
|
||||
void setCursorGrabbed(bool newMouseGrab);
|
||||
|
||||
bool isCursorRelative(void) const;
|
||||
|
||||
void setCursorRelative(bool newMouseRelative);
|
||||
|
||||
unsigned char getAntiAliasing(void) const;
|
||||
|
||||
void setAntiAliasing(unsigned char newMsaa);
|
||||
|
||||
virtual void preinitialization();
|
||||
|
||||
virtual void postinitialization();
|
||||
|
||||
//SDL_GLContext getOpenGLContext(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "CLoadingWindow.hpp"
|
||||
/*#include "CLoadingWindow.hpp"
|
||||
|
||||
CLoadingWindow::CLoadingWindow(std::string title, std::string iconPath, std::string splashPath, unsigned int width, unsigned int height) :
|
||||
CWindow(title, iconPath, width, height, false, false, SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP),
|
||||
@@ -37,4 +37,4 @@ void CLoadingWindow::postinitialization(void) {
|
||||
SDL_RenderCopy(renderer, tex, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef CLOADINGWINDOW_HPP
|
||||
/*#ifndef CLOADINGWINDOW_HPP
|
||||
#define CLOADINGWINDOW_HPP
|
||||
|
||||
#include "CWindow.hpp"
|
||||
@@ -17,14 +17,6 @@
|
||||
#include <SDL_image.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file CLoadingWindow.hpp
|
||||
* @brief File of CWindow, a class reprensenting a loading Window, using SDL2 lib.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Class reprensenting a loading Window, using SDL2 lib.
|
||||
*/
|
||||
class CLoadingWindow : public CWindow {
|
||||
private:
|
||||
// The path to the splash image.
|
||||
@@ -38,30 +30,13 @@ public:
|
||||
CLoadingWindow(const CLoadingWindow& param) = delete;
|
||||
CLoadingWindow& operator=(const CLoadingWindow& param) = delete;
|
||||
|
||||
/**
|
||||
* @brief The default constructor, build a non visible window with size of widthxheight.
|
||||
* @param[in] title The title of the window.
|
||||
* @param[in] iconPath The iconPath of the window.
|
||||
* @param[in] splashPath The splashPath of the window.
|
||||
* @param[in] width The width of the window.
|
||||
* @param[in] height The height of the window.
|
||||
*/
|
||||
CLoadingWindow(std::string title, std::string iconPath, std::string splashPath, unsigned int width, unsigned int height);
|
||||
|
||||
/**
|
||||
* @brief The destructor.
|
||||
*/
|
||||
~CLoadingWindow(void);
|
||||
|
||||
/**
|
||||
* @brief Launched before the creation of the window, usefull for setting OpenGL attribute.
|
||||
*/
|
||||
virtual void preinitialization();
|
||||
|
||||
/**
|
||||
* @brief Launched after the creation of the window, usefull for setting others attribute.
|
||||
*/
|
||||
virtual void postinitialization();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif*/
|
||||
@@ -1,20 +1,21 @@
|
||||
#include "CWindow.hpp"
|
||||
|
||||
CWindow::CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, unsigned int sdlFlags) :
|
||||
#include <SDL3/SDL_surface.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include "../API/GraphicsAPI.hpp"
|
||||
CWindow::CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, SDL_WindowFlags sdlFlags) :
|
||||
m_title(title),
|
||||
m_iconPath(iconPath),
|
||||
m_size(width, height),
|
||||
m_visible(false),
|
||||
m_fullscreen(fullscreen),
|
||||
m_visible(false),
|
||||
m_resizable(resizable),
|
||||
m_sdlFlags(sdlFlags) {
|
||||
m_pwindow = nullptr;
|
||||
}
|
||||
|
||||
CWindow::CWindow(std::string title, SDL_Window* window, unsigned int sdlFlags, unsigned int imageFlags): m_sdlFlags(sdlFlags), m_size(600,400)
|
||||
CWindow::CWindow(std::string title, SDL_Window* window, SDL_WindowFlags sdlFlags): m_title(title), m_size(600,400), m_sdlFlags(sdlFlags), m_pwindow(window)
|
||||
{
|
||||
m_title = title;
|
||||
m_pwindow = window;
|
||||
|
||||
}
|
||||
|
||||
CWindow::~CWindow(void) {
|
||||
@@ -65,7 +66,7 @@ void CWindow::setIconPath(std::string newIconPath) {
|
||||
image = IMG_Load(m_iconPath.c_str());
|
||||
if (image != nullptr) {
|
||||
SDL_SetWindowIcon(m_pwindow, image);
|
||||
SDL_FreeSurface(image);
|
||||
SDL_DestroySurface(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,10 +106,10 @@ void CWindow::setResizable(bool newResizable) {
|
||||
m_resizable = newResizable;
|
||||
if (m_pwindow != nullptr) {
|
||||
if (m_resizable) {
|
||||
SDL_SetWindowResizable(m_pwindow, SDL_TRUE);
|
||||
SDL_SetWindowResizable(m_pwindow, true);
|
||||
}
|
||||
else {
|
||||
SDL_SetWindowResizable(m_pwindow, SDL_FALSE);
|
||||
SDL_SetWindowResizable(m_pwindow, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,11 +140,11 @@ void CWindow::initialization(void) {
|
||||
preinitialization();
|
||||
|
||||
// Création de la fenetre.
|
||||
m_pwindow = SDL_CreateWindow(m_title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_size.first, m_size.second, SDL_WINDOW_HIDDEN | m_sdlFlags);
|
||||
m_pwindow = SDL_CreateWindow(m_title.c_str(), m_size.first, m_size.second, SDL_WINDOW_HIDDEN | m_sdlFlags);
|
||||
|
||||
// Handle error.
|
||||
if (m_pwindow == nullptr) {
|
||||
throw CLibException(std::string("Unable to create window: ") + SDL_GetError());
|
||||
//throw CLibException(std::string("Unable to create window: ") + SDL_GetError());//todo exceptions
|
||||
}
|
||||
|
||||
// Set the icon.
|
||||
@@ -151,15 +152,18 @@ void CWindow::initialization(void) {
|
||||
image = IMG_Load(m_iconPath.c_str());
|
||||
if (image != nullptr) {
|
||||
SDL_SetWindowIcon(m_pwindow, image);
|
||||
SDL_FreeSurface(image);
|
||||
SDL_DestroySurface(image);
|
||||
}
|
||||
|
||||
GraphicsAPI::getAPI()->init(m_pwindow);
|
||||
|
||||
|
||||
// Set the rezisable property.
|
||||
if (m_resizable) {
|
||||
SDL_SetWindowResizable(m_pwindow, SDL_TRUE);
|
||||
SDL_SetWindowResizable(m_pwindow, true);
|
||||
}
|
||||
else {
|
||||
SDL_SetWindowResizable(m_pwindow, SDL_FALSE);
|
||||
SDL_SetWindowResizable(m_pwindow, false);
|
||||
}
|
||||
|
||||
// Set the fullscreen property.
|
||||
95
src/Engine/Core/Graphics/Window/CWindow.hpp
Normal file
95
src/Engine/Core/Graphics/Window/CWindow.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifndef CWINDOW_HPP
|
||||
#define CWINDOW_HPP
|
||||
|
||||
#include <SDL3/SDL_render.h>
|
||||
#define SDL_MAIN_USE_CALLBACKS // This is necessary for the new callbacks API. To use the legacy API, don't define this.
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
|
||||
class CWindow {
|
||||
private:
|
||||
// The title of the window.
|
||||
std::string m_title;
|
||||
|
||||
// The path to the icon.
|
||||
std::string m_iconPath;
|
||||
|
||||
// First is the width, second is the height.
|
||||
std::pair<unsigned int, unsigned int> m_size;
|
||||
|
||||
// Say if the window is fullscreen.
|
||||
bool m_fullscreen;
|
||||
|
||||
// Say if the window is visible.
|
||||
bool m_visible;
|
||||
|
||||
// Say if the window is resizable.
|
||||
bool m_resizable;
|
||||
|
||||
// SDL flags for creating the window.
|
||||
SDL_WindowFlags m_sdlFlags;
|
||||
|
||||
// The pointer to the window.
|
||||
SDL_Window* m_pwindow;
|
||||
|
||||
public:
|
||||
CWindow(void) = delete;
|
||||
CWindow(const CWindow& param) = delete;
|
||||
CWindow& operator=(const CWindow& param) = delete;
|
||||
|
||||
CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, SDL_WindowFlags sdlFlags);
|
||||
|
||||
CWindow(std::string title, SDL_Window* window, SDL_WindowFlags sdlFlags);
|
||||
|
||||
|
||||
~CWindow(void);
|
||||
|
||||
|
||||
SDL_Window* getWindow(void);
|
||||
|
||||
void setWindow(SDL_Window* window){m_pwindow = window; };
|
||||
|
||||
bool isFullscreen(void) const;
|
||||
|
||||
void setFullscreen(bool newFullscreen);
|
||||
|
||||
bool isVisible(void) const;
|
||||
|
||||
void setVisible(bool newVisible);
|
||||
|
||||
std::string getIconPath(void) const;
|
||||
|
||||
std::string getTitle(void) const;
|
||||
|
||||
void setTitle(std::string newTitle);
|
||||
|
||||
void setIconPath(std::string newIconPath);
|
||||
|
||||
unsigned int getWidth(void) const;
|
||||
|
||||
unsigned int getHeight(void) const;
|
||||
|
||||
std::pair<unsigned int, unsigned int> getSize(void) const;
|
||||
|
||||
void setSize(std::pair<unsigned int, unsigned int> newSize);
|
||||
|
||||
void setSize(unsigned int newWidth, unsigned int newHeight);
|
||||
|
||||
bool isResizable(void) const;
|
||||
|
||||
void setResizable(bool newResizable);
|
||||
|
||||
bool isInitialized(void) const;
|
||||
|
||||
void initialization();
|
||||
|
||||
virtual void preinitialization() = 0;
|
||||
|
||||
virtual void postinitialization() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "CInput.hpp"
|
||||
|
||||
/*
|
||||
#include "../CKernel.hpp"
|
||||
|
||||
#include <iostream>
|
||||
@@ -162,4 +162,4 @@ void CInput::onKKeyDown(unsigned int which) {
|
||||
|
||||
void CInput::onKKeyUp(unsigned int which) {
|
||||
(void)which;
|
||||
}
|
||||
}*/
|
||||
@@ -1,17 +1,17 @@
|
||||
#ifndef CINPUT_HPP
|
||||
#define CINPUT_HPP
|
||||
|
||||
#include "../../Model/Input/CMouse.hpp"
|
||||
/*#include "../../Model/Input/CMouse.hpp"
|
||||
#include "../../Model/Input/CKeyboard.hpp"
|
||||
#include "../../Model/Input/CController.hpp"
|
||||
#include "../Exception/CException.hpp"
|
||||
#include "../../Model/Observer/CKeyObserver.hpp"
|
||||
#include "../Exception/CExceptionManager.hpp"
|
||||
#include "../CKernel.fwd.hpp"
|
||||
#include "../CKernel.fwd.hpp"*/
|
||||
|
||||
#include <SDL.h>
|
||||
/*#include <SDL.h>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <map>*/
|
||||
|
||||
/**
|
||||
* @file CInput.hpp
|
||||
@@ -21,38 +21,38 @@
|
||||
/**
|
||||
* @brief Class to handle all input event.
|
||||
*/
|
||||
class CInput : public CKeyObserver {
|
||||
private:
|
||||
/*class CInput : public CKeyObserver {
|
||||
private:*/
|
||||
// A pointer to the game.
|
||||
CKernel* m_kernel;
|
||||
//CKernel* m_kernel;
|
||||
|
||||
// The event handler.
|
||||
SDL_Event m_event;
|
||||
//SDL_Event m_event;
|
||||
|
||||
// The mouse model.
|
||||
CMouse m_mouse;
|
||||
//CMouse m_mouse;
|
||||
|
||||
// The keyboard model.
|
||||
CKeyboard m_keyboard;
|
||||
//CKeyboard m_keyboard;
|
||||
|
||||
// The controllers model, sorted by id.
|
||||
std::map<unsigned int, CController*> m_controllers;
|
||||
//std::map<unsigned int, CController*> m_controllers;
|
||||
|
||||
public:
|
||||
/*public:
|
||||
CInput(void) = delete;
|
||||
CInput(const CInput& param) = delete;
|
||||
CInput& operator=(const CInput& param) = delete;
|
||||
CInput& operator=(const CInput& param) = delete;*/
|
||||
|
||||
/**
|
||||
* @brief The usage constructor.
|
||||
* @param[in] game A pointer to the game object, to handle specific event, like quit.
|
||||
*/
|
||||
CInput(CKernel* game);
|
||||
//CInput(CKernel* game);
|
||||
|
||||
/**
|
||||
* @brief The destructor.
|
||||
*/
|
||||
~CInput(void);
|
||||
//~CInput(void);
|
||||
|
||||
/**
|
||||
* @brief Function to handle all event of the game, SDL and CGame must be initialized. This function is call once per game frame.
|
||||
@@ -63,38 +63,38 @@ public:
|
||||
* @brief The keyboard getter.
|
||||
* @return CKeyboard*, The keyboard.
|
||||
*/
|
||||
CKeyboard* getKeyboard(void);
|
||||
//CKeyboard* getKeyboard(void);
|
||||
|
||||
/**
|
||||
* @brief The mouse getter.
|
||||
* @return CMouse*, The mouse.
|
||||
*/
|
||||
CMouse* getMouse(void);
|
||||
//CMouse* getMouse(void);
|
||||
|
||||
/**
|
||||
* @brief The controller getter.
|
||||
* @param[in] id The id of the wanted controller.
|
||||
* @return CController*, The controller.
|
||||
*/
|
||||
CController* getController(unsigned int id);
|
||||
//CController* getController(unsigned int id);
|
||||
|
||||
/**
|
||||
* @brief The controllers getter.
|
||||
* @return std::map<unsigned int, CController*>, All the controllers, ordered by id.
|
||||
*/
|
||||
std::map<unsigned int, CController*> getControllers(void);
|
||||
//std::map<unsigned int, CController*> getControllers(void);
|
||||
|
||||
/**
|
||||
* @brief Handle key down event.
|
||||
* @param[in] which The code of the key.
|
||||
*/
|
||||
virtual void onKKeyDown(unsigned int which);
|
||||
/*virtual void onKKeyDown(unsigned int which);*/
|
||||
|
||||
/**
|
||||
* @brief Handle key down event.
|
||||
* @param[in] which The code of the key.
|
||||
*/
|
||||
virtual void onKKeyUp(unsigned int which);
|
||||
};
|
||||
//virtual void onKKeyUp(unsigned int which);
|
||||
//};
|
||||
|
||||
#endif
|
||||
@@ -1,16 +1,23 @@
|
||||
#include "CKernel.hpp"
|
||||
#include <chrono>
|
||||
#include <SDL3/SDL_events.h>
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
#include <SDL3/SDL_render.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "../../Configurations/Configuration/CConfiguration.hpp"
|
||||
#include "../../Modules/Module/CModuleLoader.hpp"
|
||||
#include "../Component/Graphics/CTestRenderer.hpp"
|
||||
|
||||
//CKernel* CKernel::m_kernel;
|
||||
#include "../Graphics/CContext.hpp"
|
||||
#include "../Graphics/API/GraphicsAPI.hpp"
|
||||
#include "../Scene/CScene.hpp"
|
||||
#include "../Entity/CEntity.hpp"
|
||||
#include "../Component/Camera/CCamera.hpp"
|
||||
//CShader* CKernel::m_mainShader;
|
||||
|
||||
// #define NAME "Cosmic Engine"
|
||||
// #define LOGO "../assets/spaceEngineIcon.png"
|
||||
#define LOGO "assets/spaceEngineIcon.png"
|
||||
// #define SPLASH "../assets/shrekt.png"
|
||||
// #define SPLASH_HEIGHT 512
|
||||
// #define SPLASH_WIDTH 512
|
||||
@@ -18,21 +25,19 @@
|
||||
// #define GAME_WIDTH 640
|
||||
|
||||
namespace CosmicCore {
|
||||
|
||||
CKernel* CKernel::m_kernel;
|
||||
|
||||
CKernel::CKernel(std::string name, std::string gameName) :
|
||||
m_gameName(gameName)
|
||||
m_gameName(gameName), m_window(gameName, LOGO, 1270, 720, true, false)
|
||||
{
|
||||
//m_kernel = this;
|
||||
//CContext::init(SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC,IMG_INIT_PNG | IMG_INIT_JPG);
|
||||
m_activeScene = std::make_unique<CScene>("Scene1");
|
||||
m_kernel = this;
|
||||
|
||||
CContext::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC);
|
||||
}
|
||||
|
||||
CKernel::~CKernel()
|
||||
{
|
||||
/*for(std::pair<const std::string, CScene*>& scenePair : m_sceneList)
|
||||
{
|
||||
delete scenePair.second;
|
||||
}*/
|
||||
}
|
||||
|
||||
/*void CKernel::setContext(SDL_GLContext context)
|
||||
@@ -40,10 +45,10 @@ namespace CosmicCore {
|
||||
m_GLcontext = context;
|
||||
}*/
|
||||
|
||||
/*CScene* CKernel::getActiveScene()
|
||||
CScene* CKernel::getActiveScene()
|
||||
{
|
||||
return m_activeScene;
|
||||
}*/
|
||||
}
|
||||
|
||||
/*void CKernel::initGL()
|
||||
{
|
||||
@@ -59,11 +64,16 @@ namespace CosmicCore {
|
||||
void CKernel::start(bool isPreview) {
|
||||
|
||||
//DEBUG_LOG(trace, "Kernel", "Context", "Starting " + m_gameName + "...")
|
||||
CConfiguration::init();
|
||||
//CosmicConfig::CConfiguration::init();
|
||||
//CComponentFactory::registerStandardProvidedAbstractComponents();
|
||||
std::cout << CModuleLoader::loadAll() << std::endl;
|
||||
//std::cout << CModuleLoader::loadAll() << std::endl;
|
||||
if(!isPreview)
|
||||
{
|
||||
m_window.initialization();
|
||||
|
||||
m_sceneMap["TestScene"] = std::make_unique<CScene>("Scene1");
|
||||
m_activeScene = m_sceneMap["TestScene"].get();
|
||||
m_activeScene->addEntity("TestEntity", "Description");
|
||||
// Open the splash window.
|
||||
//DEBUG_LOG(trace, "Kernel", "Context", "Loading splash window...")
|
||||
//m_loadingWindow.setVisible(true);
|
||||
@@ -131,88 +141,92 @@ namespace CosmicCore {
|
||||
}
|
||||
|
||||
void CKernel::loop() {
|
||||
while(1)
|
||||
{
|
||||
int addOrNot = 0;
|
||||
std::cout << "Create test renderer to add to the scene via an entity ?" << std::endl;
|
||||
std::cin >> addOrNot;
|
||||
if(addOrNot == 1)
|
||||
{
|
||||
auto entity = m_activeScene->addEntity("test1", "testDesc");
|
||||
entity.addComponent<CTestRenderer>();
|
||||
std::cout << "nb Entities : " << m_activeScene->getNumEntity() << std::endl;
|
||||
}
|
||||
else if(addOrNot == 2)
|
||||
{
|
||||
//m_activeScene.get()->getEntityComponentManager().getEntities().clear();
|
||||
//m_activeScene.get()->getEntityComponentManager().addComponent<CTestRenderer>(m_activeScene.get()->getEntityComponentManager().getEntities().size()-1, EComponentType::COMPONENT_RENDERER);
|
||||
}
|
||||
m_activeScene->render();
|
||||
}
|
||||
/*unsigned int frameRate(1000 / m_config.getTargetedFramerate());
|
||||
|
||||
unsigned int frameRate(1000 / 144);
|
||||
unsigned int beginIterationTime(0);
|
||||
unsigned int endIterationTime(0);
|
||||
unsigned int spendedIterationTime(0);
|
||||
unsigned int lastFrame = 0;
|
||||
|
||||
// Activation du Depth Buffer
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
//lancement des scripts
|
||||
unsigned int numEntities = m_activeScene->getNumEntity();
|
||||
for (unsigned int i = 0; i < numEntities; i++)
|
||||
{
|
||||
unsigned int numComponents = m_activeScene->getEntity(i)->getComponents(EComponentType::COMPONENT_SCRIPT).size();
|
||||
for (unsigned int j = 0; j < numComponents; j++)
|
||||
{
|
||||
((CAbstractScript*)(m_activeScene->getEntity(i)->getComponents(EComponentType::COMPONENT_SCRIPT)[j]))->start();
|
||||
}
|
||||
|
||||
}
|
||||
m_window.setVisible(true);
|
||||
m_window.setResizable(true);
|
||||
while (!m_finished) {
|
||||
// Define the starting time.
|
||||
beginIterationTime = SDL_GetTicks();
|
||||
|
||||
|
||||
// Compute the delta time.
|
||||
unsigned int currentFrame = beginIterationTime;
|
||||
m_deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
|
||||
// Update event system.
|
||||
m_inputHandler.updateEvent();
|
||||
//m_inputHandler.updateEvent();
|
||||
// ####### start render #######
|
||||
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
if (event.type == SDL_EVENT_QUIT)
|
||||
m_finished = true;
|
||||
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(m_window.getWindow()))
|
||||
m_finished = true;
|
||||
if (event.type == SDL_EVENT_KEY_DOWN) {
|
||||
// Handle key press
|
||||
SDL_Keycode keyPressed = event.key.key;
|
||||
auto entities = m_activeScene->getECManager().registry.view<CCamera, CTransform>();
|
||||
auto& ent = m_activeScene->getECManager().registry.get<CTransform>(entities.front());
|
||||
switch (keyPressed) {
|
||||
case SDLK_Z:
|
||||
ent.forward({0.0f, 0.0f, -0.05f});
|
||||
break;
|
||||
case SDLK_Q:
|
||||
ent.forward({-0.05f, 0.0f, 0.0f});
|
||||
break;
|
||||
case SDLK_S:
|
||||
ent.forward({0.0f, 0.0f, 0.05f});
|
||||
break;
|
||||
case SDLK_D:
|
||||
ent.forward({0.05f, 0.0f, 0.0f});
|
||||
break;
|
||||
case SDLK_LCTRL:
|
||||
ent.forward({0.0f, -0.05f, 0.0f});
|
||||
break;
|
||||
case SDLK_LSHIFT:
|
||||
ent.forward({0.0f, 0.05f, 0.0f});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Nettoyage de l'<27>cran.
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Update des scripts.
|
||||
m_activeScene->updateScript();
|
||||
|
||||
// Actualisation du monde physique.
|
||||
//todo fonction wrap => pour rendre valide même si c'est pas ODE
|
||||
dSpaceCollide(m_activeScene->getTangibleWorld()->getSpace(), m_activeScene->getTangibleWorld(), &(m_activeScene->getTangibleWorld())->callback);
|
||||
m_activeScene->getTangibleWorld()->updateWorld(0.12f);
|
||||
|
||||
|
||||
// Rendu.
|
||||
m_activeScene->render();
|
||||
|
||||
// Actualisation de la fen<65>tre.
|
||||
SDL_GL_SwapWindow(m_window.getWindow());
|
||||
// Process the key pressed
|
||||
}
|
||||
if(event.type == SDL_EVENT_MOUSE_MOTION)
|
||||
{
|
||||
auto entities = m_activeScene->getECManager().registry.view<CCamera, CTransform>();
|
||||
auto& ent = m_activeScene->getECManager().registry.get<CTransform>(entities.front());
|
||||
static const float sensitivity = 0.1f;
|
||||
// yaw : rotation autour de Y global (axe monde)
|
||||
ent.rotate(glm::vec3(0.0f, 1.0f, 0.0f), glm::radians(-event.motion.xrel * sensitivity));
|
||||
|
||||
// pitch : rotation autour de X local (axe de la caméra)
|
||||
ent.rotate(glm::vec3(1.0f, 0.0f, 0.0f), glm::radians(-event.motion.yrel * sensitivity));
|
||||
}
|
||||
}
|
||||
|
||||
if(m_activeScene)
|
||||
GraphicsAPI::getAPI()->drawFrame();
|
||||
// ####### end render #######
|
||||
|
||||
// Compute the end and spended time .
|
||||
endIterationTime = SDL_GetTicks();
|
||||
spendedIterationTime = endIterationTime - beginIterationTime;
|
||||
|
||||
spendedIterationTime = endIterationTime - beginIterationTime;
|
||||
// If need, we pause the programm to have the right fps amount.
|
||||
if (spendedIterationTime < frameRate) {
|
||||
SDL_Delay(frameRate - spendedIterationTime);
|
||||
}
|
||||
}
|
||||
if(m_isOriginOfContext)
|
||||
CContext::quit();*/
|
||||
GraphicsAPI::getAPI()->cleanup();
|
||||
CContext::quit();
|
||||
}
|
||||
|
||||
void CKernel::quit() {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
//#include "../Context/CContext.hpp"
|
||||
//#include "../Context/Window/CGameWindow.hpp"
|
||||
#include "../Graphics/Window/CGameWindow.hpp"
|
||||
//#include "../Context/Window/CLoadingWindow.hpp"
|
||||
|
||||
//#include "../Controller/Configuration/CGameConfiguration.hpp"
|
||||
@@ -46,15 +46,15 @@ namespace CosmicCore {
|
||||
|
||||
// The windows.
|
||||
//CLoadingWindow m_loadingWindow;
|
||||
//CGameWindow m_window;
|
||||
|
||||
CGameWindow m_window;
|
||||
|
||||
// Global game var.
|
||||
bool m_finished;
|
||||
unsigned int m_deltaTime;
|
||||
|
||||
// The Scenes.
|
||||
std::unique_ptr<CScene> m_activeScene;
|
||||
//std::map<std::string, CScene*> m_sceneList;
|
||||
CScene* m_activeScene;
|
||||
std::map<std::string, std::unique_ptr<CScene>> m_sceneMap;
|
||||
|
||||
//CInput m_inputHandler;
|
||||
//SDL_GLContext m_GLcontext;
|
||||
@@ -66,7 +66,7 @@ namespace CosmicCore {
|
||||
/**
|
||||
* @brief A pointer to the simulation which is accessible from anywhere.
|
||||
*/
|
||||
//static CKernel* m_kernel;
|
||||
static CKernel* m_kernel;
|
||||
|
||||
/**
|
||||
* @brief A pointer to the shader used, accessible from anywhere.
|
||||
@@ -86,7 +86,8 @@ namespace CosmicCore {
|
||||
//void addScene(std::shared_ptr<CScene>& scene);
|
||||
//void setActiveScene(std::string scene);
|
||||
//void setContext(SDL_GLContext context);
|
||||
//CScene* getActiveScene();
|
||||
CScene* getActiveScene();
|
||||
void cleanup(){m_sceneMap.clear();};
|
||||
//unsigned int getNbScene() { return m_sceneList.size(); };
|
||||
//std::map<std::string, CScene*>& getScenes() { return m_sceneList; };
|
||||
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
#include "CScene.hpp"
|
||||
#include "nlohmann/json_fwd.hpp"
|
||||
#include "../Component/Graphics/CTestRenderer.hpp"
|
||||
//#include "../../Controller/Exception/CRuntimeException.hpp"
|
||||
//#include "Components/CAbstractScript.hpp"
|
||||
#include "../Entity/CEntity.hpp"
|
||||
#include "../Component/Graphics/CRenderer.hpp"
|
||||
#include "../Component/Meta/CMetaData.hpp"
|
||||
#include "../Component/Geometry/CTransform.hpp"
|
||||
#include "../Component/Camera/CCamera.hpp"
|
||||
#include "../Component/Relationships/CRelationship.hpp"
|
||||
#include "../Graphics/API/GraphicsAPI.hpp"
|
||||
#include "../Graphics/Data/CModelLoader.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
namespace CosmicCore {
|
||||
|
||||
CScene::CScene(std::string name) : CSerializable(),
|
||||
@@ -15,8 +21,52 @@ namespace CosmicCore {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
CEntity CScene::addEntity(std::string name, std::string description){
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
|
||||
auto handle = m_ecManager.registry.create();
|
||||
CEntity handler(m_ecManager, handle, this);
|
||||
m_ecManager().emplace<CTransform>(handle, handler);
|
||||
m_ecManager().emplace<CMetaData>(handle, handler, std::move(name), std::move(description));
|
||||
|
||||
auto& rM = GraphicsAPI::getAPI()->getResourceManager();
|
||||
|
||||
auto model = CModelLoader::loadModel("assets/models/cube.glb", rM);
|
||||
|
||||
rM.getTextureManager().loadedTextures.push_back(std::make_unique<CTexture>("assets/shrekt.png"));
|
||||
auto texture = rM.getTextureManager().loadedTextures.back().get();
|
||||
texture->init();
|
||||
for(auto& mesh : model->getMeshes())
|
||||
{
|
||||
mesh->getMaterial()->textureAlbedo = texture;
|
||||
mesh->getMaterial()->build();
|
||||
}
|
||||
|
||||
m_ecManager().emplace<CRenderer>(handle, handler, model);
|
||||
auto& tr = m_ecManager.registry.get<CTransform>(handle);
|
||||
tr.initUniformBuffer(dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get())->getAllocator());
|
||||
tr.updateUniformBuffer(0);
|
||||
tr.updateUniformBuffer(1);
|
||||
|
||||
auto camHandle = m_ecManager.registry.create();
|
||||
CEntity handlerCam(m_ecManager, camHandle, this);
|
||||
|
||||
auto& transform = m_ecManager().emplace<CTransform>(camHandle, handlerCam);
|
||||
auto& cam = m_ecManager.registry.emplace<CCamera>(camHandle, handlerCam);
|
||||
|
||||
m_ecManager.registry.emplace<CRelationship>(camHandle, handlerCam, std::vector<EntityId>{handle});
|
||||
m_ecManager.registry.emplace<CRelationship>(handle, handler, camHandle);
|
||||
|
||||
transform.setCenter({0.0f, 0.9f, 3.0f});
|
||||
cam.setAspect((float)api->getSwapChainExtent().width / api->getSwapChainExtent().height);
|
||||
cam.initUniformBuffer(api->getAllocator());
|
||||
cam.updateUniformBuffer(0, transform);
|
||||
cam.updateUniformBuffer(1, transform);
|
||||
return handler;
|
||||
}
|
||||
|
||||
unsigned int CScene::getNumEntity(void) const {
|
||||
return this->m_ecManager.view<CMetaData>()->size();
|
||||
return m_ecManager().view<CMetaData>()->size();
|
||||
}
|
||||
|
||||
void CScene::removeEntity(unsigned int index, bool destroy)
|
||||
@@ -24,24 +74,57 @@ namespace CosmicCore {
|
||||
|
||||
}
|
||||
|
||||
void CScene::render(){
|
||||
auto renderers = m_ecManager.view<CTestRenderer>();
|
||||
for(auto beg = renderers->begin(); beg != renderers->end(); ++beg)
|
||||
{
|
||||
beg->render();
|
||||
}
|
||||
//std::chrono::steady_clock::time_point begin1 = std::chrono::steady_clock::now();
|
||||
//auto eh = m_ecManager.create();
|
||||
//m_ecManager.emplace<CTestRenderer>(eh, nullptr);
|
||||
//std::chrono::steady_clock::time_point end1 = std::chrono::steady_clock::now();
|
||||
//std::cout << "added entity and comptest : " <<std::chrono::duration_cast<std::chrono::seconds>(end1 - begin1).count() << std::endl;
|
||||
//static unsigned int entitynb = 0;
|
||||
//entitynb++;
|
||||
//std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
|
||||
//m_ecManager.view<CTestRenderer>().each([](auto e, CTestRenderer& comp){comp.render();});
|
||||
//std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
|
||||
//std::cout << "render func : " << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count() << std::endl;
|
||||
//std::cout << "nb : " << entitynb << std::endl;
|
||||
void CScene::render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex){
|
||||
auto entities = m_ecManager.registry.view<CRenderer, CTransform>();
|
||||
VulkanImpl* api = dynamic_cast<VulkanImpl*>(GraphicsAPI::getAPI().get());
|
||||
auto cam = m_ecManager.registry.view<CCamera, CTransform>();
|
||||
auto& camera = m_ecManager.registry.get<CCamera>(cam.front());
|
||||
auto& transform = m_ecManager.registry.get<CTransform>(cam.front());
|
||||
|
||||
camera.updateUniformBuffer(frameIndex, transform);
|
||||
|
||||
cmd.bindDescriptorSets(
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
api->getDefaultPipelineLayout(), // layout du pipeline
|
||||
0,
|
||||
*camera.getDescriptorSet(frameIndex),
|
||||
{}
|
||||
);
|
||||
|
||||
for (auto& entity : entities) {
|
||||
auto model = m_ecManager.registry.get<CRenderer>(entity).getModel();
|
||||
auto& transform = m_ecManager.registry.get<CTransform>(entity);
|
||||
|
||||
transform.updateUniformBuffer(frameIndex);
|
||||
//trier meshes par matérial ?
|
||||
|
||||
// bind transform UBO (set = 1)
|
||||
cmd.bindDescriptorSets(
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
api->getDefaultPipelineLayout(), // layout du pipeline
|
||||
1, // set = 1
|
||||
*transform.getDescriptorSet(frameIndex),
|
||||
{}
|
||||
);
|
||||
|
||||
for (auto& mesh : model->getMeshes()) {
|
||||
// ne rebind le pipeline que si le material change
|
||||
//if (mesh.getMaterial() != boundMaterial) {
|
||||
//boundMaterial = mesh.getMaterial();
|
||||
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics,
|
||||
*mesh->getMaterial()->getPipeline());
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
*mesh->getMaterial()->getPipelineLayout(),
|
||||
2,
|
||||
*mesh->getMaterial()->getDescriptorSet(frameIndex),
|
||||
{});
|
||||
//}
|
||||
|
||||
cmd.bindVertexBuffers(0, vk::Buffer(mesh->getVertexIndexBuffer().buffer), mesh->getVertexOffset());
|
||||
cmd.bindIndexBuffer(vk::Buffer(mesh->getVertexIndexBuffer().buffer), mesh->getIndexOffset(), vk::IndexType::eUint32);
|
||||
cmd.drawIndexed(mesh->getIndexCount(), 1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void CScene::setMask(unsigned int mask)
|
||||
|
||||
@@ -1,37 +1,32 @@
|
||||
#ifndef CSCENE_HPP
|
||||
#define CSCENE_HPP
|
||||
|
||||
#include "../Component/Geometry/CTransform.hpp"
|
||||
#include "../Component/Meta/CMetaData.hpp"
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
#include "../Systems/EntityComponentManager.hpp"
|
||||
#include "../Utils/CSerializable.hpp"
|
||||
#include <string>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
namespace CosmicCore {;
|
||||
namespace CosmicCore {
|
||||
class CEntity;
|
||||
class CScene : public CSerializable {
|
||||
using ECManager = entt::registry;
|
||||
private:
|
||||
// The name of the scene.
|
||||
std::string m_name;
|
||||
ECManager m_ecManager;
|
||||
|
||||
EntityComponentManager m_ecManager;
|
||||
|
||||
public:
|
||||
CScene() = delete;
|
||||
CScene(std::string name);
|
||||
~CScene() = default;
|
||||
virtual ~CScene() = default;
|
||||
|
||||
unsigned int getNumEntity() const;
|
||||
|
||||
CEntity addEntity(std::string name, std::string description){
|
||||
auto handle = m_ecManager.create();
|
||||
CEntity handler(m_ecManager, handle);
|
||||
m_ecManager.emplace<CTransform>(handle, handler);
|
||||
m_ecManager.emplace<CMetaData>(handle, handler, std::move(name), std::move(description));
|
||||
return handler;
|
||||
}
|
||||
CEntity addEntity(std::string name, std::string description);
|
||||
|
||||
std::string getName() const;
|
||||
|
||||
EntityComponentManager& getECManager(){return m_ecManager;};
|
||||
|
||||
void removeEntity(unsigned int index, bool destroy = true);
|
||||
|
||||
//CEntity* getActiveCamera();
|
||||
@@ -73,7 +68,7 @@ namespace CosmicCore {;
|
||||
*/
|
||||
//unsigned int getMask();
|
||||
|
||||
void render();
|
||||
void render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex);
|
||||
//void updateScript();
|
||||
|
||||
nlohmann::json to_json();
|
||||
|
||||
26
src/Engine/Core/Systems/EntityComponentManager.hpp
Normal file
26
src/Engine/Core/Systems/EntityComponentManager.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef ENTITYCOMPONENTMANAGER_HPP
|
||||
#define ENTITYCOMPONENTMANAGER_HPP
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
namespace CosmicCore {
|
||||
|
||||
using ECManager = entt::registry;
|
||||
using EntityId = entt::entity;
|
||||
|
||||
class EntityComponentManager{
|
||||
public:
|
||||
ECManager registry;
|
||||
ECManager& operator()(){
|
||||
return registry;
|
||||
}
|
||||
|
||||
const ECManager& operator()() const {
|
||||
return registry;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "CFileManager.hpp"
|
||||
|
||||
void CFileManager::open(const char mode) {
|
||||
/*void CFileManager::open(const char mode) {
|
||||
DEBUG_LOG(trace, "Kernel", "FileManager", "file " + m_filePath + " opened.")
|
||||
|
||||
switch (mode) {
|
||||
@@ -59,4 +59,4 @@ std::string CFileManager::read(void) {
|
||||
close();
|
||||
|
||||
return out;
|
||||
}
|
||||
}*/
|
||||
@@ -1,14 +1,8 @@
|
||||
#ifndef CFILEMANAGER_HPP
|
||||
#define CFILEMANAGER_HPP
|
||||
|
||||
#include "../Exception/CFileException.hpp"
|
||||
#include "../../Context/CContext.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @file CFileManager.hpp
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
#include "CModelLoader.hpp"
|
||||
#include <iostream>
|
||||
|
||||
CModel* CModelLoader::loadModel(std::string fileName, SMaterial* material)
|
||||
{
|
||||
Assimp::Importer import;
|
||||
const aiScene* scene = import.ReadFile(fileName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_JoinIdenticalVertices);
|
||||
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||
{
|
||||
std::cout << std::string(import.GetErrorString()) << std::endl;
|
||||
DEBUG_LOG(trace, "Kernel", "ModelLoader", std::string("Assimp error : ") + std::string(import.GetErrorString()))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<CMesh*> meshes;
|
||||
processNode(scene->mRootNode, scene, &meshes, material);
|
||||
|
||||
CModel* model = new CModel(meshes);
|
||||
model->load();
|
||||
return model;
|
||||
}
|
||||
|
||||
void CModelLoader::processNode(aiNode* node, const aiScene* scene, std::vector<CMesh*>* meshes, SMaterial* material)
|
||||
{
|
||||
// process all the node's meshes (if any)
|
||||
for (unsigned int i = 0; i < node->mNumMeshes; i++)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
processMesh(mesh, scene, meshes, material);
|
||||
}
|
||||
// then do the same for each of its children
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++)
|
||||
{
|
||||
processNode(node->mChildren[i], scene, meshes, material);
|
||||
}
|
||||
}
|
||||
|
||||
void CModelLoader::processMesh(aiMesh* mesh, const aiScene* scene, std::vector<CMesh*>* meshes, SMaterial* material)
|
||||
{
|
||||
std::vector<SVertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
SVertex vertex;
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||
{
|
||||
vertex.m_position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
||||
vertex.m_normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
|
||||
|
||||
if (mesh->mTextureCoords[0]) // if the mesh contains texture coordinates
|
||||
{
|
||||
vertex.m_texCoords.x = mesh->mTextureCoords[0][i].x;
|
||||
vertex.m_texCoords.y = mesh->mTextureCoords[0][i].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.m_texCoords = glm::vec2(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (mesh->mBitangents)// if the mesh contains bitangent coordinates
|
||||
{
|
||||
vertex.m_bitangent.x = mesh->mBitangents->x;
|
||||
vertex.m_bitangent.y = mesh->mBitangents->y;
|
||||
vertex.m_bitangent.z = mesh->mBitangents->z;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.m_bitangent = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (mesh->mTangents)// if the mesh contains tangent coordinates
|
||||
{
|
||||
vertex.m_tangent.x = mesh->mTangents->x;
|
||||
vertex.m_tangent.y = mesh->mTangents->y;
|
||||
vertex.m_tangent.z = mesh->mTangents->z;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.m_tangent = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
// process indices
|
||||
|
||||
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
|
||||
{
|
||||
aiFace face = mesh->mFaces[i];
|
||||
for (unsigned int j = 0; j < face.mNumIndices; j++)
|
||||
indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
// process material
|
||||
std::vector<CImageTexture*> diffuseMaps;
|
||||
std::vector<CImageTexture*> specularMaps;
|
||||
std::vector<CAbstractTexture*> textures;
|
||||
SMaterial* mat = new SMaterial;
|
||||
if (mesh->mMaterialIndex >= 0 && material == nullptr)
|
||||
{
|
||||
aiMaterial* amaterial = scene->mMaterials[mesh->mMaterialIndex];
|
||||
diffuseMaps = loadMaterialTextures(amaterial,
|
||||
aiTextureType_DIFFUSE, ETextureType::TEXTURE_DIFFUSE);
|
||||
specularMaps = loadMaterialTextures(amaterial,
|
||||
aiTextureType_SPECULAR, ETextureType::TEXTURE_SPECULAR);
|
||||
|
||||
for (size_t i = 0; i < diffuseMaps.size(); i++)
|
||||
{
|
||||
textures.push_back((CAbstractTexture*)diffuseMaps[i]);
|
||||
}
|
||||
for (size_t j = 0; j < specularMaps.size(); j++)
|
||||
{
|
||||
textures.push_back((CAbstractTexture*)specularMaps[j]);
|
||||
}
|
||||
std::vector<SColor> colorsC; //= { {glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), EColorType::COLOR_DIFFUSE} };
|
||||
aiColor4D color(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
amaterial->Get(AI_MATKEY_COLOR_DIFFUSE, color);
|
||||
SColor diffuseColor = { glm::vec4(color.r, color.g, color.b, color.a), EColorType::COLOR_DIFFUSE };
|
||||
colorsC.push_back(diffuseColor);
|
||||
|
||||
*mat = { textures, colorsC, CKernel::m_mainShader };
|
||||
}
|
||||
else// if the material is given, override the material of the wavefront obj file
|
||||
{
|
||||
delete mat;
|
||||
mat = material;
|
||||
}
|
||||
|
||||
|
||||
CMesh* m = new CMesh();
|
||||
|
||||
m->setMaterial(mat);
|
||||
|
||||
m->setIndexes(indices);
|
||||
m->setVertices(vertices);
|
||||
|
||||
meshes->push_back(m);
|
||||
|
||||
}
|
||||
|
||||
std::vector<CImageTexture*> CModelLoader::loadMaterialTextures(aiMaterial* mat, aiTextureType type, ETextureType typeName)
|
||||
{
|
||||
std::vector<CImageTexture*> textures;
|
||||
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++)
|
||||
{
|
||||
aiString str;
|
||||
mat->GetTexture(type, i, &str);
|
||||
CImageTexture* text = new CImageTexture(typeName, str.C_Str());
|
||||
text->init();//Load the texture in GPU before adding it the texture list
|
||||
textures.push_back(text);
|
||||
}
|
||||
return textures;
|
||||
}
|
||||
Reference in New Issue
Block a user