From 3cfdd7a3f2372bf9dcdce84e293db8e56aa03e7d Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Sun, 24 Apr 2022 22:12:07 +0200 Subject: [PATCH] wip --- .clang-format | 1 + src/CMakeLists.txt | 8 +- src/Controller.cpp | 5 +- src/Entity.cpp | 23 ++++-- src/Entity.h | 11 ++- src/FrameBuffer.cpp | 13 +-- src/FrameBuffer.h | 7 +- src/Helper.cpp | 14 ++-- src/JsonParser.cpp | 13 ++- src/JsonParser.h | 4 +- src/Menu.cpp | 1 - src/Mesh.cpp | 15 ++-- src/Mesh.h | 8 +- src/Model.h | 45 ---------- src/Scene.cpp | 44 ++++------ src/Scene.h | 4 +- src/Screen.cpp | 11 +-- src/Screen.h | 8 +- src/Texture.h | 94 --------------------- src/TextureFactory.cpp | 20 ----- src/TextureFactory.h | 18 ---- src/{Texture.cpp => Texture_old.cpp} | 110 +------------------------ src/Texture_old.h | 54 ++++++++++++ src/Widget.cpp | 12 +-- src/Widget.h | 10 +-- src/definitions/models.h | 10 --- src/resources/AbstractTexture.h | 15 ++++ src/resources/CubeMap.cpp | 119 +++++++++++++++++++++++++++ src/resources/CubeMap.h | 60 ++++++++++++++ src/{ => resources}/Model.cpp | 67 ++++++--------- src/resources/Model.h | 35 ++++++++ src/resources/Resource.cpp | 40 +++++++++ src/resources/Resource.h | 58 +++++++++++++ src/resources/ResourceHandler.cpp | 67 +++++++++++++++ src/resources/ResourceHandler.h | 25 ++++++ src/resources/ShaderProgram.h | 12 +++ src/resources/Texture.cpp | 98 ++++++++++++++++++++++ src/resources/Texture.h | 35 ++++++++ src/resources/TextureTypes.h | 11 +++ src/resources/VertexArray.h | 1 + src/util/Log.cpp | 7 +- tools/main.cpp | 8 +- tools/primitiveModel.h | 13 ++- 43 files changed, 777 insertions(+), 457 deletions(-) delete mode 100644 src/Model.h delete mode 100644 src/Texture.h delete mode 100644 src/TextureFactory.cpp delete mode 100644 src/TextureFactory.h rename src/{Texture.cpp => Texture_old.cpp} (62%) create mode 100644 src/Texture_old.h create mode 100644 src/resources/AbstractTexture.h create mode 100644 src/resources/CubeMap.cpp create mode 100644 src/resources/CubeMap.h rename src/{ => resources}/Model.cpp (74%) create mode 100644 src/resources/Model.h create mode 100644 src/resources/Resource.cpp create mode 100644 src/resources/Resource.h create mode 100644 src/resources/ResourceHandler.cpp create mode 100644 src/resources/ResourceHandler.h create mode 100644 src/resources/ShaderProgram.h create mode 100644 src/resources/Texture.cpp create mode 100644 src/resources/Texture.h create mode 100644 src/resources/TextureTypes.h create mode 100644 src/resources/VertexArray.h diff --git a/.clang-format b/.clang-format index 9b156a1..0fb55d6 100644 --- a/.clang-format +++ b/.clang-format @@ -4,6 +4,7 @@ AccessModifierOffset: '-4' AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: 'false' +AlwaysBreakTemplateDeclarations: 'true' BreakBeforeBraces: Mozilla ColumnLimit: '120' IndentWidth: '4' diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 48c6fb2..0e92faf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,11 +5,8 @@ add_executable(Fall-Fever EventHandler.cpp ShaderProgram.cpp VertexArray.cpp - Texture.cpp - TextureFactory.cpp Camera.cpp Mesh.cpp - Model.cpp Entity.cpp Light.cpp Scene.cpp @@ -24,6 +21,11 @@ add_executable(Fall-Fever imgui/Handler.cpp imgui/Window.cpp util/Log.cpp + resources/Resource.cpp + resources/ResourceHandler.cpp + resources/Texture.cpp + resources/Model.cpp + resources/CubeMap.cpp ) target_link_libraries( diff --git a/src/Controller.cpp b/src/Controller.cpp index f2e5351..d9660db 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -21,14 +21,15 @@ #include "JsonParser.h" #include "Light.h" #include "Menu.h" -#include "Model.h" #include "Scene.h" #include "Screen.h" #include "ShaderProgram.h" -#include "Texture.h" #include "VertexArray.h" #include "Widget.h" #include "Window.h" +#include "resources/Model.h" +#include "resources/ResourceHandler.h" +#include "resources/Texture.h" #include "util/Log.h" Controller::Controller() : m_gameWindow(std::unique_ptr(new Window)) diff --git a/src/Entity.cpp b/src/Entity.cpp index 71b903f..e202a78 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -1,8 +1,10 @@ #include "Entity.h" #include "Mesh.h" -#include "Model.h" #include "ShaderProgram.h" #include "VertexArray.h" +#include "resources/CubeMap.h" +#include "resources/Model.h" +#include "resources/ResourceHandler.h" #include #include @@ -125,7 +127,7 @@ glm::mat4 Entity::getModelMatrix() const return m_modelMatrix; } -ModelEntity::ModelEntity(Prototype prototype, Model *model, ShaderProgram *shaderProgram) +ModelEntity::ModelEntity(Prototype prototype, const Model *model, ShaderProgram *shaderProgram) : Entity(prototype.name), m_model(model), m_shaderProgram(shaderProgram) { setPosition(prototype.position); @@ -191,18 +193,20 @@ void ModelEntity::drawPointShadows(ShaderProgram *shaderProgram) } Skybox::Skybox(Prototype prototype, Model *cubeModel, ShaderProgram *shaderProgram) - : m_cubeModel(cubeModel), m_shaderProgram(shaderProgram), m_cubeMap(new CubeMap(prototype.texturePath.c_str())), - m_vertexArray(cubeModel->getMesh(0)->getVertexArray()) -{} + : m_cubeModel(cubeModel), m_shaderProgram(shaderProgram), m_vertexArray(cubeModel->getMesh(0)->getVertexArray()) +{ + m_cubeMap = + ResourceHandler::instance().registerResource(TextureCubeMapDescriptor{prototype.texturePath}); +} Skybox::~Skybox() { - delete m_cubeMap; + // delete m_cubeMap; } void Skybox::initializeOnGPU() { - m_cubeMap->initializeOnGPU(); + // m_cubeMap->initializeOnGPU(); } void Skybox::draw(glm::mat4 viewMatrix, glm::mat4 projectionMatrix) @@ -220,9 +224,10 @@ void Skybox::draw(glm::mat4 viewMatrix, glm::mat4 projectionMatrix) m_shaderProgram->setUniform("u_viewProjectionMatrix", viewProjectionMatrix); - m_cubeMap->bind(m_shaderProgram); + auto cubeMap = std::static_pointer_cast(ResourceHandler::instance().resource(m_cubeMap)); + cubeMap->bind(m_shaderProgram); m_cubeModel->getMesh(0)->drawWithoutTextures(); - m_cubeMap->unbind(); + cubeMap->unbind(); m_shaderProgram->unbind(); glDepthMask(GL_TRUE); diff --git a/src/Entity.h b/src/Entity.h index 19f5729..1c081d6 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -1,14 +1,17 @@ #pragma once -#include "Texture.h" +#include "resources/Resource.h" #include #include #include +#include +#include class VertexArray; class ShaderProgram; class Model; +class TextureCubeMap; class Entity { @@ -87,7 +90,7 @@ public: std::string shaderProgramName; }; - ModelEntity(Prototype prototype, Model *model, ShaderProgram *shaderProgram); + ModelEntity(Prototype prototype, const Model *model, ShaderProgram *shaderProgram); ~ModelEntity() = default; void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition); @@ -95,7 +98,7 @@ public: void drawPointShadows(ShaderProgram *p_shaderProgram); private: - Model *m_model; + const Model *m_model; ShaderProgram *m_shaderProgram; }; @@ -120,7 +123,7 @@ private: Model *m_cubeModel; ShaderProgram *m_shaderProgram; - CubeMap *m_cubeMap; + ResourceId m_cubeMap; VertexArray *m_vertexArray; }; diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index 4079afc..6b20261 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -1,6 +1,8 @@ #include "FrameBuffer.h" #include "ShaderProgram.h" -#include "Texture.h" +#include "resources/CubeMap.h" +#include "resources/ResourceHandler.h" +#include "resources/Texture.h" #include "util/Log.h" #include @@ -150,14 +152,15 @@ GLuint DepthMap::getDepthMap() const return m_depthMap; } -DepthMapCube::DepthMapCube(int RESOLUTION) +DepthMapCube::DepthMapCube(int resolution) { glGenFramebuffers(1, &m_FBO); bind(); - m_cubeMap = new CubeMap(RESOLUTION); + m_cubeMap = ResourceHandler::instance().registerResource(resolution); + GLuint glId = std::static_pointer_cast(ResourceHandler::instance().resource(m_cubeMap))->glId(); - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_cubeMap->getTextureId(), 0); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, glId, 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); @@ -172,5 +175,5 @@ DepthMapCube::~DepthMapCube() GLuint DepthMapCube::getCubeMapTextureId() { - return m_cubeMap->getTextureId(); + return std::static_pointer_cast(ResourceHandler::instance().resource(m_cubeMap))->glId(); } diff --git a/src/FrameBuffer.h b/src/FrameBuffer.h index 849314e..cf22307 100644 --- a/src/FrameBuffer.h +++ b/src/FrameBuffer.h @@ -1,5 +1,6 @@ #pragma once +#include "resources/CubeMap.h" #include class ShaderProgram; @@ -51,7 +52,7 @@ public: class DepthMap : public AbstractDepthMap { public: - DepthMap(int RESOLUTION); + DepthMap(int resolution); ~DepthMap(); GLuint getDepthMap() const; @@ -63,11 +64,11 @@ private: class DepthMapCube : public AbstractDepthMap { public: - DepthMapCube(int RESOLUTION); + DepthMapCube(int resolution); ~DepthMapCube(); GLuint getCubeMapTextureId(); private: - CubeMap *m_cubeMap; + ResourceId m_cubeMap; }; diff --git a/src/Helper.cpp b/src/Helper.cpp index 78bbb31..96587d7 100644 --- a/src/Helper.cpp +++ b/src/Helper.cpp @@ -122,13 +122,13 @@ void Helper::gl_debug_callback(GLenum source, GLenum type, GLuint id, GLenum sev } if (severity == GL_DEBUG_SEVERITY_HIGH || severity == GL_DEBUG_SEVERITY_MEDIUM) - Log::logger().info("[OpenGL Debug Message]\n" - "Message: {}\n" - "Source: {}\n" - "Type: {}\n" - "ID: {}\n" - "Severity: {}\n", - _message, _source, _type, id, _severity); + Log::logger().debug("\n[OpenGL Debug Message]\n" + "Message: {}\n" + "Source: {}\n" + "Type: {}\n" + "ID: {}\n" + "Severity: {}\n", + _message, _source, _type, id, _severity); } Helper::Timer::Timer(const std::string &name) : m_name(name) diff --git a/src/JsonParser.cpp b/src/JsonParser.cpp index bad0efe..13d24ec 100644 --- a/src/JsonParser.cpp +++ b/src/JsonParser.cpp @@ -25,20 +25,19 @@ JsonParser::JsonParser(const std::string &jsonFilepath) JsonParser::~JsonParser() {} -std::vector JsonParser::getModelPrototypes() const +std::vector JsonParser::getModelDescriptors() const { const Json::Value modelsJson = m_root["models"]; - std::vector modelPrototypes; + std::vector modelDescriptors; for (unsigned int index = 0; index < modelsJson.size(); index++) { std::string modelName = modelsJson[index]["unique_name"].asString(); std::string modelPath = modelsJson[index]["path"].asString(); - Model::Prototype prototype{modelName, modelPath}; - modelPrototypes.push_back(prototype); + modelDescriptors.push_back({modelPath, modelName}); } - return modelPrototypes; + return modelDescriptors; } std::vector JsonParser::getEntityPrototypes() const @@ -229,9 +228,9 @@ std::vector JsonParser::getWidgetPrototypesFromScreen(const J glm::vec2 position(currentWidgetPosition[0].asFloat(), currentWidgetPosition[1].asFloat()); glm::vec2 dimensions(currentWidgetDimensions[0].asFloat(), currentWidgetDimensions[1].asFloat()); uint16_t callBackId = currentWidgetJson["callbackId"].asUInt(); - Texture::Prototype texturePrototype{currentWidgetTextureJson.asString(), TextureType::Diffuse}; + TextureDescriptor textureDescriptor{currentWidgetTextureJson.asString(), TextureType::Diffuse}; - Widget::Prototype widgetPrototype{name, position, dimensions, texturePrototype, callBackId}; + Widget::Prototype widgetPrototype{name, position, dimensions, textureDescriptor, callBackId}; widgetPrototypes.push_back(widgetPrototype); } diff --git a/src/JsonParser.h b/src/JsonParser.h index aa14f3f..9a1ed66 100644 --- a/src/JsonParser.h +++ b/src/JsonParser.h @@ -7,10 +7,10 @@ #include "Entity.h" #include "Light.h" -#include "Model.h" #include "Screen.h" #include "ShaderProgram.h" #include "Widget.h" +#include "resources/Model.h" class Screen; class ShaderProgram; @@ -22,7 +22,7 @@ public: JsonParser(const std::string &jsonFilepath); ~JsonParser(); - std::vector getModelPrototypes() const; + std::vector getModelDescriptors() const; std::vector getEntityPrototypes() const; std::vector> getLightPrototypes() const; std::vector getScreenPrototypes() const; diff --git a/src/Menu.cpp b/src/Menu.cpp index 1f12482..afdcbce 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -71,7 +71,6 @@ void Menu::handleMouseButtonActionMap(const MouseButtonActionMap &mouseButtonAct auto widgets = m_activeScreen->getWidgets(); for (auto it = widgets.begin(); it != widgets.end(); it++) { if ((*it)->isHovered(window)) { - // std::cout << (*it)->getUniqueName() << " clicked!" << std::endl; if ((*it)->getCallbackId() == 1) resetActiveScreen(); if ((*it)->getCallbackId() == 2) diff --git a/src/Mesh.cpp b/src/Mesh.cpp index b923547..f2b8ff5 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -1,9 +1,10 @@ #include "Mesh.h" #include "ShaderProgram.h" -#include "Texture.h" #include "VertexArray.h" +#include "resources/ResourceHandler.h" +#include "resources/Texture.h" -Mesh::Mesh(std::vector vertices, std::vector indices, std::vector textures) +Mesh::Mesh(std::vector vertices, std::vector indices, std::vector textures) : m_preInitializationVertexData{vertices, indices}, m_numElements(indices.size()), m_textures(textures) {} @@ -27,9 +28,10 @@ void Mesh::draw(ShaderProgram *shaderProgram) // Bind all textures in order to its texture unit int i = 0; for (auto it : m_textures) { - TextureType currentTextureType = it->getTextureType(); + auto texture = std::static_pointer_cast(ResourceHandler::instance().resource(it)); + TextureType currentTextureType = texture->textureType(); - it->bind(i, shaderProgram, typeNumberCount[static_cast(currentTextureType)]); + texture->bind(i, shaderProgram, typeNumberCount[static_cast(currentTextureType)]); typeNumberCount[static_cast(currentTextureType)] += 1; @@ -42,8 +44,9 @@ void Mesh::draw(ShaderProgram *shaderProgram) m_vertexArray->unbind(); // Unbind all textures - for (auto it = m_textures.begin(); it != m_textures.end(); it++) { - (*it)->unbind(); + for (auto it : m_textures) { + auto texture = std::static_pointer_cast(ResourceHandler::instance().resource(it)); + texture->unbind(); } } diff --git a/src/Mesh.h b/src/Mesh.h index 97f4589..2e675f4 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -1,17 +1,17 @@ #pragma once +#include "VertexArray.h" #include "definitions/models.h" +#include "resources/Texture.h" #include class ShaderProgram; -class Texture; -class VertexArray; class Mesh { public: - Mesh(std::vector vertices, std::vector indices, std::vector textures); + Mesh(std::vector vertices, std::vector indices, std::vector textures); ~Mesh(); void initializeOnGPU(); @@ -31,7 +31,7 @@ private: bool m_isInitialized = false; uint32_t m_numElements; - std::vector m_textures; + std::vector m_textures; VertexArray *m_vertexArray; }; diff --git a/src/Model.h b/src/Model.h deleted file mode 100644 index 002d1d4..0000000 --- a/src/Model.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "definitions/models.h" - -#include -#include - -class ShaderProgram; -class Mesh; -class Texture; - -class Model -{ -public: - struct Prototype - { - std::string modelName; - std::string modelPath; - }; - - Model(const Prototype &prototype); - ~Model(); - - void initializeOnGPU(); - - void draw(ShaderProgram *shaderProgram); - void drawWithoutTextures(); - - Mesh *getMesh(unsigned int index); - const std::string &getUniqueName(); - -private: - void loadModel(const std::string &pathToModel); - - bool m_isInitialized = false; - - std::vector m_meshes; - std::vector m_textures; - - std::string m_workingPath; - - static uint32_t s_idCounter; - uint32_t m_id; - std::string m_uniqueName; -}; diff --git a/src/Scene.cpp b/src/Scene.cpp index f00fba6..2388122 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -5,9 +5,10 @@ #include "FrameBuffer.h" #include "JsonParser.h" #include "Light.h" -#include "Model.h" #include "ShaderProgram.h" -#include "Texture.h" +#include "resources/Model.h" +#include "resources/ResourceHandler.h" +#include "resources/Texture.h" #include "util/Log.h" #include @@ -30,34 +31,32 @@ Scene::Scene(std::vector shaderPrograms) JsonParser modelParser("data/scene.json"); - std::vector modelPrototypes = modelParser.getModelPrototypes(); + std::vector modelDescriptors = modelParser.getModelDescriptors(); { std::vector> futures; std::mutex mutex; - for (auto &prototype : modelPrototypes) { + for (const auto &descriptor : modelDescriptors) { auto loadModel = [=, &mutex]() { - Model *currentModel = new Model(prototype); + ResourceId model = ResourceHandler::instance().registerResource(descriptor); - Log::logger().info("Loaded model \"{}\": {}", prototype.modelName, prototype.modelPath); + Log::logger().info("Loaded model \"{}\": {}", descriptor.name, descriptor.path); std::lock_guard lock(mutex); - m_models.push_back(currentModel); + m_models.push_back(model); }; futures.push_back(std::async(std::launch::async, loadModel)); } } - for (auto &model : m_models) - model->initializeOnGPU(); - // TODO: use geometry shader instead of model and load skybox before models. Skybox::Prototype skyboxPrototype = modelParser.getSkyboxPrototype(); std::thread skyboxThread([=]() { - m_skybox = new Skybox(skyboxPrototype, getModelByName("cube"), + m_skybox = new Skybox(skyboxPrototype, + std::static_pointer_cast(ResourceHandler::instance().resource("cube")).get(), Controller::getShaderProgramByName("skyboxProgram", shaderPrograms)); Log::logger().info("Loaded skybox: {}", skyboxPrototype.texturePath); @@ -68,11 +67,13 @@ Scene::Scene(std::vector shaderPrograms) { for (auto &prototype : entityPrototypes) { // Get model - Model *currentModel = getModelByName(prototype.modelName); + const Model *currentModel = + std::static_pointer_cast(ResourceHandler::instance().resource(prototype.modelName)).get(); if (!currentModel) { // Apply fallback model (first model in vector) - currentModel = m_models[0]; + currentModel = std::static_pointer_cast(ResourceHandler::instance().resource("fallback")) + .get(); // TODO rename fallbackModel Log::logger().warn("Model could not be found by name \"{}\"", prototype.modelName); } @@ -138,9 +139,9 @@ Scene::~Scene() delete (*it); } // Iterate over models and entities and delete all items - for (auto it = m_models.begin(); it != m_models.end(); it++) { - delete (*it); - } + // for (auto it = m_models.begin(); it != m_models.end(); it++) { + // delete (*it); + // } for (auto it = m_entities.begin(); it != m_entities.end(); it++) { delete (*it); } @@ -306,17 +307,6 @@ void Scene::calculateShadows(ShaderProgram *directionalShaderProgram, ShaderProg glCullFace(GL_FRONT); } -Model *Scene::getModelByName(const std::string &name) -{ - for (auto it = m_models.begin(); it != m_models.end(); it++) { - if ((*it)->getUniqueName() == name) { - return *it; - } - } - Log::logger().warn("Model could not be found by unique name \"{}\"", name); - return nullptr; -} - ModelEntity *Scene::getEntityByName(const std::string &name) { for (auto it = m_entities.begin(); it != m_entities.end(); it++) { diff --git a/src/Scene.h b/src/Scene.h index c00513d..dd1a683 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -1,6 +1,7 @@ #pragma once #include "FrameBuffer.h" +#include "resources/Resource.h" #include #include @@ -36,7 +37,6 @@ public: Skybox *getSkybox(); ModelEntity *getEntityByName(const std::string &name); ModelEntity *getEntityById(uint32_t id); - Model *getModelByName(const std::string &name); void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition); void calculateShadows(ShaderProgram *directionalShaderProgram, ShaderProgram *pointShaderProgram); @@ -44,7 +44,7 @@ public: private: ShaderProgram *m_shaderProgram; - std::vector m_models; + std::vector m_models; std::vector m_entities; Skybox *m_skybox; diff --git a/src/Screen.cpp b/src/Screen.cpp index a6ca590..91e19c6 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -3,8 +3,9 @@ #include "Helper.h" #include "Menu.h" #include "ShaderProgram.h" -#include "Texture.h" +// #include "Texture.h" #include "Widget.h" +#include "resources/ResourceHandler.h" uint32_t Screen::s_idCounter = 0; @@ -13,10 +14,9 @@ Screen::Screen(Prototype prototype, FrameBuffer *framebuffer, ShaderProgram *sha { for (auto &prototype : prototype.widgetPrototypes) { auto texturePrototype = prototype.texturePrototype; - Texture *currentTexture = new Texture({texturePrototype.texturePath, texturePrototype.textureType}); - currentTexture->initializeOnGPU(); + ResourceId textureId = ResourceHandler::instance().registerResource(texturePrototype); - Widget *currentWidget = new Widget(prototype, currentTexture); + Widget *currentWidget = new Widget(prototype, textureId); m_widgets.push_back(currentWidget); } } @@ -27,9 +27,6 @@ Screen::~Screen() for (auto it = m_widgets.begin(); it != m_widgets.end(); it++) { delete *it; } - for (auto it = m_textures.begin(); it != m_textures.end(); it++) { - delete *it; - } } const std::string &Screen::getUniqueName() const diff --git a/src/Screen.h b/src/Screen.h index 72f8b15..64374a4 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -1,15 +1,15 @@ #pragma once +#include "Widget.h" +#include "resources/Texture.h" + #include #include #include -#include "Widget.h" - class Menu; class FrameBuffer; class ShaderProgram; -class Texture; class Screen { @@ -38,7 +38,7 @@ private: FrameBuffer *m_frameBuffer; ShaderProgram *m_shaderProgram; - std::vector m_textures; + std::vector m_textures; std::vector m_widgets; mutable std::unordered_map m_widgetNameCache; diff --git a/src/Texture.h b/src/Texture.h deleted file mode 100644 index 093077b..0000000 --- a/src/Texture.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include "definitions/models.h" - -#include -#include -#include -#include -#include - -class ShaderProgram; - -// Order is important! -enum class cubeMapFaces -{ - cm_right, - cm_left, - cm_top, - cm_bottom, - cm_back, - cm_front, - CUBEMAP_FACES_NUM_ITEMS -}; - -class Texture -{ -public: - struct Prototype - { - std::string texturePath; - TextureType textureType; - }; - - void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum); - void unbind(); - - TextureType getTextureType(); - std::string getPath(); - GLuint textureId(); - - Texture(const Prototype &texturePrototype); // TODO make private - void initializeOnGPU(); // TODO make private - ~Texture(); // TODO make private - -private: - Texture(const Texture &other) = delete; - Texture(Texture &&other) = delete; - Texture &operator=(const Texture &other) = delete; - Texture &operator=(Texture &&other) = delete; - - std::string m_texturePath; - - stbi_uc *m_textureBuffer; - - int32_t m_textureWidth; - int32_t m_textureHeight; - int32_t m_numComponents; - - GLuint m_textureId; // TODO inherit from abstract class resource - - TextureType m_textureType; - - friend class TextureFactory; -}; - -class CubeMap -{ -public: - CubeMap(const std::string &texturePseudoPath); - CubeMap(int RESOLUTION); - - void initializeOnGPU(); - - ~CubeMap(); - - void bind(ShaderProgram *shaderProgram); - void unbind(); - - GLuint getTextureId() const; - -private: - void fillTexturePathVector(const std::string &texturePseudoPath); - - bool m_isInitialized = false; - - std::vector m_texturePaths; - std::vector m_textureBuffers; - std::vector m_numComponents; - - GLuint m_textureId; - - int32_t m_textureWidth; - int32_t m_textureHeight; -}; diff --git a/src/TextureFactory.cpp b/src/TextureFactory.cpp deleted file mode 100644 index 41f90c7..0000000 --- a/src/TextureFactory.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "TextureFactory.h" - -TextureFactory &TextureFactory::instance() -{ - static TextureFactory instance; - return instance; -} - -void TextureFactory::registerTexture(const Texture::Prototype &prototype) -{ - auto texture = std::make_unique(prototype); - m_textureMap.insert({texture->textureId(), std::move(texture)}); -} - -std::unique_ptr TextureFactory::texture(uint64_t resourceId) -{ - auto texture = std::move(m_textureMap.at(resourceId)); - texture->initializeOnGPU(); - return texture; -} diff --git a/src/TextureFactory.h b/src/TextureFactory.h deleted file mode 100644 index 8178ba2..0000000 --- a/src/TextureFactory.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Texture.h" - -#include -#include - -class TextureFactory // TODO not yet used -{ -public: - static TextureFactory &instance(); - - void registerTexture(const Texture::Prototype &prototype); - std::unique_ptr texture(uint64_t resourceId); - -private: - std::map> m_textureMap; -}; \ No newline at end of file diff --git a/src/Texture.cpp b/src/Texture_old.cpp similarity index 62% rename from src/Texture.cpp rename to src/Texture_old.cpp index 32e0e77..dd98385 100644 --- a/src/Texture.cpp +++ b/src/Texture_old.cpp @@ -1,115 +1,7 @@ -#include "Texture.h" #include "ShaderProgram.h" +#include "Texture.h" #include "util/Log.h" -Texture::Texture(const Prototype &texturePrototype) - : m_texturePath(texturePrototype.texturePath), m_textureType(texturePrototype.textureType) -{ - stbi_set_flip_vertically_on_load(1); - m_textureBuffer = stbi_load(m_texturePath.c_str(), &m_textureWidth, &m_textureHeight, &m_numComponents, 0); - - if (!m_textureBuffer) - Log::logger().warn("Texture {} could not be loaded", m_texturePath); -} - -Texture::~Texture() -{ - glDeleteTextures(1, &m_textureId); -} - -void Texture::initializeOnGPU() -{ - GLenum internalFormat; - GLenum dataFormat; - - switch (m_numComponents) { - case 1: - internalFormat = GL_RED; - dataFormat = GL_RED; - break; - case 3: - internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8 : GL_RGB8; - dataFormat = GL_RGB; - break; - case 4: - internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8_ALPHA8 : GL_RGBA8; - dataFormat = GL_RGBA; - break; - } - - // Push texture to grahics card - glGenTextures(1, &m_textureId); - glBindTexture(GL_TEXTURE_2D, m_textureId); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -2.0f); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_textureWidth, m_textureHeight, 0, dataFormat, GL_UNSIGNED_BYTE, - m_textureBuffer); - glGenerateMipmap(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, 0); - - stbi_image_free(m_textureBuffer); -} - -void Texture::bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum) -{ - std::string uniformName = "texture_"; - - switch (m_textureType) { - - case TextureType::Diffuse: - uniformName += "diffuse" + std::to_string(textureTypeNum); - break; - case TextureType::Specular: - uniformName += "specular" + std::to_string(textureTypeNum); - break; - case TextureType::Normal: - uniformName += "normal" + std::to_string(textureTypeNum); - break; - case TextureType::Height: - uniformName += "height" + std::to_string(textureTypeNum); - break; - case TextureType::Gloss: - uniformName += "gloss" + std::to_string(textureTypeNum); - break; - default: - break; - } - - // Add u_material as we store textures in a struct - uniformName = "u_material." + uniformName; - - shaderProgram->setUniform(uniformName.c_str(), textureUnit); - glActiveTexture(GL_TEXTURE0 + textureUnit); - glBindTexture(GL_TEXTURE_2D, m_textureId); -} - -void Texture::unbind() -{ - glBindTexture(GL_TEXTURE_2D, 0); -} - -TextureType Texture::getTextureType() -{ - return m_textureType; -} - -std::string Texture::getPath() -{ - return m_texturePath; -} - -GLuint Texture::textureId() -{ - return m_textureId; -} - CubeMap::CubeMap(const std::string &texturePseudoPath) { // Reserve space in vector so that elements can be accessed explicitly. diff --git a/src/Texture_old.h b/src/Texture_old.h new file mode 100644 index 0000000..2e8b80f --- /dev/null +++ b/src/Texture_old.h @@ -0,0 +1,54 @@ +#pragma once + +#include "definitions/models.h" +#include "resources/Texture.h" + +#include +#include +#include +#include +#include + +class ShaderProgram; + +// Order is important! +enum class cubeMapFaces +{ + cm_right, + cm_left, + cm_top, + cm_bottom, + cm_back, + cm_front, + CUBEMAP_FACES_NUM_ITEMS +}; + +class CubeMap +{ +public: + CubeMap(const std::string &texturePseudoPath); + CubeMap(int RESOLUTION); + + void initializeOnGPU(); + + ~CubeMap(); + + void bind(ShaderProgram *shaderProgram); + void unbind(); + + GLuint getTextureId() const; + +private: + void fillTexturePathVector(const std::string &texturePseudoPath); + + bool m_isInitialized = false; + + std::vector m_texturePaths; + std::vector m_textureBuffers; + std::vector m_numComponents; + + GLuint m_textureId; + + int32_t m_textureWidth; + int32_t m_textureHeight; +}; diff --git a/src/Widget.cpp b/src/Widget.cpp index 88fafd7..54a1a7e 100644 --- a/src/Widget.cpp +++ b/src/Widget.cpp @@ -4,22 +4,17 @@ #include "ShaderProgram.h" #include "VertexArray.h" #include "Window.h" +#include "resources/ResourceHandler.h" #include -Widget::Widget(Prototype prototype, Texture *texture) +Widget::Widget(Prototype prototype, ResourceId texture) : m_position(prototype.position), m_dimensions(prototype.dimensions), m_uniqueName(prototype.name), m_callbackId(prototype.callBackId) { m_widgetTextures.push_back(texture); } -Widget::~Widget() -{ - for (auto &texture : m_widgetTextures) - delete texture; -} - std::string Widget::getUniqueName() { return m_uniqueName; @@ -41,7 +36,8 @@ void Widget::draw(ShaderProgram *shaderProgram) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_widgetTextures[0]->textureId()); + auto texture = std::static_pointer_cast(ResourceHandler::instance().resource(m_widgetTextures[0])); + glBindTexture(GL_TEXTURE_2D, texture->glId()); GLint location = glGetUniformLocation(shaderProgram->getShaderProgramId(), "u_texture"); glUniform1i(location, 0); diff --git a/src/Widget.h b/src/Widget.h index c1ad577..e71ae06 100644 --- a/src/Widget.h +++ b/src/Widget.h @@ -1,7 +1,7 @@ #pragma once -#include "Texture.h" #include "definitions/models.h" +#include "resources/Texture.h" #include #include @@ -9,7 +9,6 @@ class Menu; class ShaderProgram; -class Texture; class Window; class Mesh; @@ -21,12 +20,11 @@ public: std::string name; glm::vec2 position; glm::vec2 dimensions; - Texture::Prototype texturePrototype; + TextureDescriptor texturePrototype; uint16_t callBackId; // TODO: will be removed... }; - Widget(Prototype prototype, Texture *texture); - ~Widget(); + Widget(Prototype prototype, ResourceId texture); void draw(ShaderProgram *shaderProgram); @@ -43,5 +41,5 @@ private: uint16_t m_callbackId; - std::vector m_widgetTextures; + std::vector m_widgetTextures; }; diff --git a/src/definitions/models.h b/src/definitions/models.h index 263465c..d3d0af9 100644 --- a/src/definitions/models.h +++ b/src/definitions/models.h @@ -2,16 +2,6 @@ #include -enum class TextureType -{ - Diffuse, - Specular, - Normal, - Height, - Gloss, - TEXTURE_TYPE_NUM_ITEMS -}; - struct Vertex { // Postition diff --git a/src/resources/AbstractTexture.h b/src/resources/AbstractTexture.h new file mode 100644 index 0000000..dcced96 --- /dev/null +++ b/src/resources/AbstractTexture.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Resource.h" + +class AbstractTexture : public Resource, public GlResource +{ +public: + AbstractTexture(const std::string &path) : Resource(path) + {} + +protected: + int32_t m_textureWidth; + int32_t m_textureHeight; + int32_t m_numComponents; +}; diff --git a/src/resources/CubeMap.cpp b/src/resources/CubeMap.cpp new file mode 100644 index 0000000..415d983 --- /dev/null +++ b/src/resources/CubeMap.cpp @@ -0,0 +1,119 @@ +#include "CubeMap.h" +#include "../ShaderProgram.h" +#include "../util/Log.h" + +#include + +TextureCubeMap::TextureCubeMap(const TextureCubeMapDescriptor &descriptor) : AbstractCubeMap(descriptor.path) +{ + // Reserve space in vector so that elements can be accessed explicitly. + m_textureBuffers.resize(static_cast(CubeMapFace::CUBEMAP_FACES_NUM_ITEMS)); + + stbi_set_flip_vertically_on_load(0); + + glGenTextures(1, &m_glId); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_glId); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + int i = 0; + for (const auto &faceName : FACE_NAMES) { + std::string texturePath = descriptor.path + faceName; + + auto textureBuffer = stbi_load(texturePath.c_str(), &m_textureWidth, &m_textureHeight, &m_numComponents, 0); + + if (!textureBuffer) { + Log::logger().warn("CubeMap texture {} could not be loaded", texturePath); + return; + } + + m_textureBuffers[i] = textureBuffer; + i++; + } + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +void TextureCubeMap::initialize() +{ + m_initialized = true; + + glGenTextures(1, &m_glId); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_glId); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + int i = 0; + for (auto &textureBuffer : m_textureBuffers) { + GLenum internalFormat; + GLenum dataFormat; + + switch (m_numComponents) { + case 1: + internalFormat = GL_RED; + dataFormat = GL_RED; + break; + case 3: + internalFormat = GL_SRGB8; + dataFormat = GL_RGB; + break; + case 4: + internalFormat = GL_SRGB8_ALPHA8; + dataFormat = GL_RGBA; + break; + } + + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalFormat, m_textureWidth, m_textureHeight, 0, + dataFormat, GL_UNSIGNED_BYTE, textureBuffer); + + stbi_image_free(textureBuffer); + i++; + } + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +void AbstractCubeMap::bind(ShaderProgram *shaderProgram) const +{ + std::string uniformName = "u_skybox"; + + shaderProgram->setUniform(uniformName, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_glId); +} + +void AbstractCubeMap::unbind() const +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +InternalCubeMap::InternalCubeMap(unsigned int resolution) : AbstractCubeMap("internal") +{ + m_textureWidth = resolution; + m_textureHeight = resolution; + m_initialized = true; + + glGenTextures(1, &m_glId); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_glId); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + for (unsigned int i = 0; i < static_cast(CubeMapFace::CUBEMAP_FACES_NUM_ITEMS); i++) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT24, resolution, resolution, 0, + GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + } + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} diff --git a/src/resources/CubeMap.h b/src/resources/CubeMap.h new file mode 100644 index 0000000..f01d94d --- /dev/null +++ b/src/resources/CubeMap.h @@ -0,0 +1,60 @@ +#pragma once + +#include "AbstractTexture.h" + +#include +#include +#include + +// Order is important! +enum class CubeMapFace +{ + Right, + Left, + Top, + Bottom, + Back, + Front, + CUBEMAP_FACES_NUM_ITEMS +}; + +const std::array FACE_NAMES{"right.png", "left.png", "top.png", "bottom.png", "back.png", "front.png"}; + +class ShaderProgram; + +struct TextureCubeMapDescriptor +{ + std::string path; +}; + +class AbstractCubeMap : public AbstractTexture +{ +public: + AbstractCubeMap(const std::string path) : AbstractTexture(path) + {} + + void bind(ShaderProgram *shaderProgram) const; + void unbind() const override; +}; + +class TextureCubeMap : public AbstractCubeMap +{ +public: + TextureCubeMap(const TextureCubeMapDescriptor &descriptor); + +protected: + void initialize() override; + +private: + std::vector m_textureBuffers; +}; + +class InternalCubeMap : public AbstractCubeMap +{ +public: + InternalCubeMap(unsigned int resolution); + +protected: + void initialize() override + {} +}; diff --git a/src/Model.cpp b/src/resources/Model.cpp similarity index 74% rename from src/Model.cpp rename to src/resources/Model.cpp index 513bb5f..6237226 100644 --- a/src/Model.cpp +++ b/src/resources/Model.cpp @@ -1,59 +1,46 @@ #include "Model.h" -#include "Mesh.h" -#include "ShaderProgram.h" -#include "Texture.h" -#include "util/Log.h" +#include "../util/Log.h" +#include "ResourceHandler.h" #include #include -uint32_t Model::s_idCounter = 0; - -Model::Model(const Prototype &prototype) : m_id(s_idCounter++), m_uniqueName(prototype.modelName) +Model::Model(const ModelDescriptor &descriptor) : Resource(descriptor.path), NamedResource(descriptor.name) { - m_workingPath = prototype.modelPath.substr(0, prototype.modelPath.find_last_of('/')); + m_workingPath = descriptor.path.substr(0, descriptor.path.find_last_of('/')); - loadModel(prototype.modelPath); + loadModel(descriptor.path); } -void Model::initializeOnGPU() +void Model::initialize() { - if (m_isInitialized) - return; - - m_isInitialized = true; - - for (auto texture : m_textures) - texture->initializeOnGPU(); + m_initialized = true; for (auto mesh : m_meshes) mesh->initializeOnGPU(); } -Model::~Model() -{ - // Go through all loaded textures and delete them - for (auto it = m_textures.begin(); it != m_textures.end(); it++) { - delete (*it); - } -} - -void Model::draw(ShaderProgram *shaderProgram) +void Model::draw(ShaderProgram *shaderProgram) const { // Iterate through every mesh and call the draw function - for (auto mesh : m_meshes) { + for (const auto &mesh : m_meshes) { mesh->draw(shaderProgram); } } -void Model::drawWithoutTextures() +void Model::drawWithoutTextures() const { // Iterate through every mesh and call the draw function - for (auto mesh : m_meshes) { + for (const auto &mesh : m_meshes) { mesh->drawWithoutTextures(); } } +Mesh *Model::getMesh(unsigned int index) const +{ + return m_meshes[index]; +} + void Model::loadModel(const std::string &pathToModel) { std::ifstream input(pathToModel, std::ios::in | std::ios::binary); @@ -96,10 +83,11 @@ void Model::loadModel(const std::string &pathToModel) std::string texturePath = m_workingPath + '/' + textureSources[i].c_str(); auto loadModel = [=, &mutex]() { - Texture *currentTex = new Texture({texturePath, textureTypes[i]}); + ResourceId texture = ResourceHandler::instance().registerResource( + TextureDescriptor{texturePath, textureTypes[i]}); std::lock_guard lock(mutex); - m_textures.push_back(currentTex); + m_textures.push_back(texture); }; futures.push_back(std::async(std::launch::async, loadModel)); @@ -114,9 +102,10 @@ void Model::loadModel(const std::string &pathToModel) } if (!hasNormalMap) { - Texture *currentTex = new Texture({"data/res/models/tex/fallback_normal.png", TextureType::Normal}); + ResourceId texture = ResourceHandler::instance().registerResource( + TextureDescriptor{"data/res/models/tex/fallback_normal.png", TextureType::Normal}); - m_textures.push_back(currentTex); + m_textures.push_back(texture); } // Here starts the first mesh @@ -144,7 +133,7 @@ void Model::loadModel(const std::string &pathToModel) input.read((char *)meshIndices.data(), indexBlockSize); std::vector meshTextureIds; - std::vector meshTextures; + std::vector meshTextures; for (unsigned int i = 0; i < numMeshTextureIds; i++) { uint32_t currentTextureId; @@ -166,13 +155,3 @@ void Model::loadModel(const std::string &pathToModel) input.close(); } - -Mesh *Model::getMesh(unsigned int index) -{ - return m_meshes[index]; -} - -const std::string &Model::getUniqueName() -{ - return m_uniqueName; -} diff --git a/src/resources/Model.h b/src/resources/Model.h new file mode 100644 index 0000000..261184a --- /dev/null +++ b/src/resources/Model.h @@ -0,0 +1,35 @@ +#pragma once + +#include "../Mesh.h" +#include "Resource.h" + +#include +#include + +struct ModelDescriptor +{ + std::string path; + std::string name; +}; + +class Model : public Resource, public NamedResource +{ +public: + Model(const ModelDescriptor &descriptor); + + void draw(ShaderProgram *shaderProgram) const; + void drawWithoutTextures() const; + + Mesh *getMesh(unsigned int index) const; // TODO... + +protected: + void initialize() override; + +private: + void loadModel(const std::string &pathToModel); + + std::vector m_meshes; + std::vector m_textures; + + std::string m_workingPath; +}; diff --git a/src/resources/Resource.cpp b/src/resources/Resource.cpp new file mode 100644 index 0000000..4f28d86 --- /dev/null +++ b/src/resources/Resource.cpp @@ -0,0 +1,40 @@ +#include "Resource.h" +#include "../util/Log.h" + +ResourceId Resource::s_idCounter = 0; + +Resource::Resource(const std::string &path) : m_id(s_idCounter++), m_path(path) +{ + Log::logger().info("Resource \"{}\" with id {} created", m_path, m_id); +} + +ResourceId Resource::id() const +{ + return m_id; +} + +bool Resource::isInitialized() const +{ + return m_initialized; +} + +const std::string &Resource::resourcePath() const +{ + return m_path; +} + +GLuint GlResource::glId() const +{ + return m_glId; +} + +NamedResource::NamedResource(const std::string &name) : m_name(name) +{} + +const std::string &NamedResource::name() const +{ + return m_name; +} + +NamedResource::~NamedResource() +{} diff --git a/src/resources/Resource.h b/src/resources/Resource.h new file mode 100644 index 0000000..9c7fe04 --- /dev/null +++ b/src/resources/Resource.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +using ResourceId = uint64_t; + +class Resource +{ +public: + Resource(const std::string &path); + Resource(const Resource &other) = delete; + Resource(Resource &&other) = delete; + Resource &operator=(const Resource &other) = delete; + Resource &operator=(Resource &&other) = delete; + + ResourceId id() const; + const std::string &resourcePath() const; + +protected: + bool isInitialized() const; + virtual void initialize() = 0; + + bool m_initialized = false; + +private: + ResourceId m_id; + static ResourceId s_idCounter; + + std::string m_path; + + friend class ResourceHandler; +}; + +class GlResource +{ +public: + // virtual ~GlResource() = 0; TODO!! + virtual void unbind() const = 0; + + GLuint glId() const; + +protected: + GLuint m_glId; +}; + +class NamedResource +{ +public: + NamedResource(const std::string &name); + virtual ~NamedResource() = 0; + + const std::string &name() const; + +protected: + std::string m_name; +}; diff --git a/src/resources/ResourceHandler.cpp b/src/resources/ResourceHandler.cpp new file mode 100644 index 0000000..255b367 --- /dev/null +++ b/src/resources/ResourceHandler.cpp @@ -0,0 +1,67 @@ +#include "ResourceHandler.h" +#include "../util/Log.h" +#include "CubeMap.h" +#include "Model.h" +#include "Texture.h" + +#include + +ResourceHandler ResourceHandler::s_instance; + +ResourceHandler &ResourceHandler::instance() +{ + return s_instance; +} + +template +ResourceId ResourceHandler::registerResource(Param const &...param) +{ + auto resource = std::make_shared(param...); + m_resources.emplace(resource->id(), resource); + return resource->id(); +} + +template ResourceId ResourceHandler::registerResource(TextureDescriptor const &); +template ResourceId ResourceHandler::registerResource(TextureCubeMapDescriptor const &); +template ResourceId ResourceHandler::registerResource(int const &); +template ResourceId ResourceHandler::registerResource(ModelDescriptor const &); + +const std::shared_ptr ResourceHandler::resource(const ResourceId id) const +{ + auto it = m_resources.find(id); + + if (it != m_resources.end()) { + auto resource = it->second; + + if (!resource->isInitialized()) + resource->initialize(); + + return resource; + } + + Log::logger().warn("Could not find resource with id {}", id); + return std::shared_ptr(); +} + +const std::shared_ptr ResourceHandler::resource(const std::string &name) const +{ + auto it = std::find_if(m_resources.begin(), m_resources.end(), [&name](const auto &resource) { + if (auto namedResource = std::dynamic_pointer_cast(resource.second)) { + return namedResource->name() == name; + } + + return false; + }); + + if (it != m_resources.end()) { + auto resource = it->second; + + if (!resource->isInitialized()) + resource->initialize(); + + return resource; + } + + Log::logger().warn("Could not find resource with unique name \"{}\"", name); + return std::shared_ptr(); +} diff --git a/src/resources/ResourceHandler.h b/src/resources/ResourceHandler.h new file mode 100644 index 0000000..bc4a8ef --- /dev/null +++ b/src/resources/ResourceHandler.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Resource.h" + +#include +#include + +class ResourceHandler +{ +public: + static ResourceHandler &instance(); + + template + ResourceId registerResource(Param const &...param); + + const std::shared_ptr resource(ResourceId id) const; + const std::shared_ptr resource(const std::string &name) const; + +private: + ResourceHandler() = default; + + static ResourceHandler s_instance; + + std::map> m_resources; +}; diff --git a/src/resources/ShaderProgram.h b/src/resources/ShaderProgram.h new file mode 100644 index 0000000..765d751 --- /dev/null +++ b/src/resources/ShaderProgram.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Resource.h" + +class ShaderProgram : public GlResource, public NamedResource +{ +public: + ShaderProgram(); + + void bind() const; + void unbind() const override; +} \ No newline at end of file diff --git a/src/resources/Texture.cpp b/src/resources/Texture.cpp new file mode 100644 index 0000000..c79fa32 --- /dev/null +++ b/src/resources/Texture.cpp @@ -0,0 +1,98 @@ +#include "Texture.h" +#include "../ShaderProgram.h" +#include "../util/Log.h" + +Texture::Texture(const TextureDescriptor &descriptor) + : AbstractTexture(descriptor.path), m_textureType(descriptor.textureType) +{ + stbi_set_flip_vertically_on_load(1); + m_textureBuffer = stbi_load(resourcePath().c_str(), &m_textureWidth, &m_textureHeight, &m_numComponents, 0); + + if (!m_textureBuffer) + Log::logger().warn("Texture {} could not be loaded", resourcePath()); +} + +void Texture::initialize() +{ + m_initialized = true; + + GLenum internalFormat; + GLenum dataFormat; + + switch (m_numComponents) { + case 1: + internalFormat = GL_RED; + dataFormat = GL_RED; + break; + case 3: + internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8 : GL_RGB8; + dataFormat = GL_RGB; + break; + case 4: + internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8_ALPHA8 : GL_RGBA8; + dataFormat = GL_RGBA; + break; + } + + // Push texture to grahics card + glGenTextures(1, &m_glId); + glBindTexture(GL_TEXTURE_2D, m_glId); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -2.0f); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_textureWidth, m_textureHeight, 0, dataFormat, GL_UNSIGNED_BYTE, + m_textureBuffer); + glGenerateMipmap(GL_TEXTURE_2D); + + glBindTexture(GL_TEXTURE_2D, 0); + + stbi_image_free(m_textureBuffer); +} + +TextureType Texture::textureType() const +{ + return m_textureType; +} + +void Texture::bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum) const +{ + std::string uniformName = "texture_"; + + switch (m_textureType) { + + case TextureType::Diffuse: + uniformName += "diffuse" + std::to_string(textureTypeNum); + break; + case TextureType::Specular: + uniformName += "specular" + std::to_string(textureTypeNum); + break; + case TextureType::Normal: + uniformName += "normal" + std::to_string(textureTypeNum); + break; + case TextureType::Height: + uniformName += "height" + std::to_string(textureTypeNum); + break; + case TextureType::Gloss: + uniformName += "gloss" + std::to_string(textureTypeNum); + break; + default: + break; + } + + // Add u_material as we store textures in a struct + uniformName = "u_material." + uniformName; + + shaderProgram->setUniform(uniformName.c_str(), textureUnit); + glActiveTexture(GL_TEXTURE0 + textureUnit); + glBindTexture(GL_TEXTURE_2D, m_glId); +} + +void Texture::unbind() const +{ + glBindTexture(GL_TEXTURE_2D, 0); +} diff --git a/src/resources/Texture.h b/src/resources/Texture.h new file mode 100644 index 0000000..f878e04 --- /dev/null +++ b/src/resources/Texture.h @@ -0,0 +1,35 @@ +#pragma once + +#include "AbstractTexture.h" +#include "Resource.h" +#include "TextureTypes.h" + +#include +#include + +class ShaderProgram; + +struct TextureDescriptor +{ + std::string path; + TextureType textureType; +}; + +class Texture : public AbstractTexture +{ +public: + Texture(const TextureDescriptor &descriptor); + + TextureType textureType() const; + + void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum) const; + void unbind() const override; + +protected: + void initialize() override; + +private: + stbi_uc *m_textureBuffer; + + TextureType m_textureType; +}; \ No newline at end of file diff --git a/src/resources/TextureTypes.h b/src/resources/TextureTypes.h new file mode 100644 index 0000000..0667b32 --- /dev/null +++ b/src/resources/TextureTypes.h @@ -0,0 +1,11 @@ +#pragma once + +enum class TextureType +{ + Diffuse, + Specular, + Normal, + Height, + Gloss, + TEXTURE_TYPE_NUM_ITEMS +}; \ No newline at end of file diff --git a/src/resources/VertexArray.h b/src/resources/VertexArray.h new file mode 100644 index 0000000..7b9637e --- /dev/null +++ b/src/resources/VertexArray.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/src/util/Log.cpp b/src/util/Log.cpp index 1975c21..8271c39 100644 --- a/src/util/Log.cpp +++ b/src/util/Log.cpp @@ -7,8 +7,13 @@ Log Log::s_instance; Log::Log() { m_logger = spdlog::stdout_color_mt("Core"); - m_logger->set_level(spdlog::level::debug); // m_logger->set_pattern(""); + +#ifdef _DEBUG + m_logger->set_level(spdlog::level::debug); +#else + m_logger->set_level(spdlog::level::warn); +#endif } spdlog::logger &Log::logger() diff --git a/tools/main.cpp b/tools/main.cpp index 83dee40..845e489 100644 --- a/tools/main.cpp +++ b/tools/main.cpp @@ -18,11 +18,13 @@ #include #include "../src/definitions/models.h" +#include "../src/resources/TextureTypes.h" #include "primitiveModel.h" void processNode(aiNode *node, const aiScene *scene, Model *model); Mesh processMesh(aiMesh *mesh, const aiScene *scene, Model *model); -std::vector loadMaterialTextures(aiMaterial *mat, aiTextureType type, uint8_t textureType, Mesh *mesh, Model *model); +std::vector loadMaterialTextures(aiMaterial *mat, aiTextureType type, uint8_t textureType, Mesh *mesh, + Model *model); int main(int argc, char** argv) { @@ -221,7 +223,9 @@ Mesh processMesh(aiMesh *mesh, const aiScene *scene, Model *model) { return currentMesh; } -std::vector loadMaterialTextures(aiMaterial *mat, aiTextureType type, uint8_t textureType, Mesh *mesh, Model *model) { +std::vector loadMaterialTextures(aiMaterial *mat, aiTextureType type, uint8_t textureType, Mesh *mesh, + Model *model) +{ std::vector textures; for(uint32_t i = 0; i < mat->GetTextureCount(type); i++) { diff --git a/tools/primitiveModel.h b/tools/primitiveModel.h index 95868b2..634446b 100644 --- a/tools/primitiveModel.h +++ b/tools/primitiveModel.h @@ -3,23 +3,22 @@ #include #include -struct Texture { - +struct Texture +{ std::string pathToTexture; uint32_t textureType; uint32_t m_textureId; }; -struct Mesh { - +struct Mesh +{ std::vector vertices; std::vector indices; std::vector textureIds; - }; -struct Model { - +struct Model +{ std::vector textures; std::vector m_meshes; std::string m_workingPath;