This is my final attempt of making an efficient ResourceManager
class, which takes care of allocating OpenGL objects (like Shader, Textures, Meshes, ...). It stores each resource in a unique_ptr
and then distributes const
pointers of that type, which I call "Observant pointers." They cannot be deleted because resource allocation is only done via the ResourceManager
class.
ResourceManager.h:
#pragma once
#include <memory>
#include <vector>
#include <unordered_map>
#include "../render/Shader.h"
#include "../render/Mesh.h"
#include "../render/Texture.h"
namespace Spiky
{
class ResourceManager
{
public:
using ShaderRepo = std::unordered_map<const char*, std::unique_ptr<CShader>>;
using MeshRepo = std::unordered_map<const char*, std::unique_ptr<CMesh>>;
using TextureRepo = std::unordered_map<const char*, std::unique_ptr<CTexture>>;
//Shader
static const CShader* LoadShader(const char* ID, const char* vs, const char* fs)
{
shaderObjects.insert(std::pair<const char*, std::unique_ptr<CShader>>(ID, std::make_unique<CShader>(
(shaderRootDir + std::string(vs)).c_str(),
(shaderRootDir + std::string(fs)).c_str())));
return (shaderObjects.at(ID).get());
}
static const CShader* LoadShader(const char* ID, const char* vs, const char* fs, const char* gs)
{
shaderObjects.insert(std::pair<const char*, std::unique_ptr<CShader>>(ID, std::make_unique<CShader>(
(shaderRootDir + std::string(vs)).c_str(),
(shaderRootDir + std::string(fs)).c_str(),
(shaderRootDir + std::string(gs)).c_str())));
return (shaderObjects.at(ID).get());
}
static CShader* GetShader(const char* ID)
{
return (shaderObjects.at(ID).get());
}
//Mesh
static const CMesh* LoadMesh(const char* ID, Vertex* vertices, unsigned int numVertices, unsigned int* indeces, unsigned int numIndices)
{
meshObjects.insert(std::pair<const char*, std::unique_ptr<CMesh>>(ID, std::make_unique<CMesh>(
vertices,
numVertices,
indeces,
numIndices)));
return (meshObjects.at(ID).get());
}
static const CMesh* LoadMesh(const char* ID, const char* fileName)
{
meshObjects.insert(std::pair<const char*, std::unique_ptr<CMesh>>(ID, std::make_unique<CMesh>(
(meshRootDir + std::string(fileName)).c_str())));
return (meshObjects.at(ID).get());
}
//Texture
static const CTexture* LoadTexture(const char* ID, const char* texturePath, GLenum texTarget = GL_TEXTURE_2D, GLfloat filter = GL_LINEAR,
GLfloat pattern = GL_REPEAT, GLenum attachment = GL_NONE)
{
textureObjects.insert(std::pair<const char*, std::unique_ptr<CTexture>>(ID, std::unique_ptr<CTexture>(new CTexture(
(textureRootDir + std::string(texturePath)).c_str(), texTarget, filter, pattern, attachment))));
return (textureObjects.at(ID).get());
}
static const CTexture* LoadTexture(const char* ID, int width, int height, unsigned char* data = nullptr, GLenum texTarget = GL_TEXTURE_2D,
GLfloat filter = GL_LINEAR, GLfloat pattern = GL_REPEAT, GLenum attachment = GL_NONE)
{
textureObjects.insert(std::pair<const char*, std::unique_ptr<CTexture>>(ID, std::unique_ptr<CTexture>(new CTexture(
width, height, data, texTarget, filter, pattern, attachment))));
return (textureObjects.at(ID).get());
}
static const CTexture* LoadTextureCustomPath(const char* ID, const char* texturePath, GLenum texTarget = GL_TEXTURE_2D, GLfloat filter = GL_LINEAR, GLfloat pattern = GL_REPEAT, GLenum attachment = GL_NONE)
{
textureObjects.insert(std::pair<const char*, std::unique_ptr<CTexture>>(ID, std::unique_ptr<CTexture>(new CTexture(
texturePath, texTarget, filter, pattern, attachment))));
return (textureObjects.at(ID).get());
}
static const* CTexture GetTexture(const char* ID)
{
return (textureObjects.at(ID).get());
}
private:
static ShaderRepo shaderObjects;
static MeshRepo meshObjects;
static TextureRepo textureObjects;
static std::string shaderRootDir;
static std::string meshRootDir;
static std::string textureRootDir;
};
}
ResourceManager.cpp:
#include "../core/ResourceManager.h"
namespace Spiky
{
ResourceManager::ShaderRepo ResourceManager::shaderObjects = ShaderRepo();
ResourceManager::MeshRepo ResourceManager::meshObjects = MeshRepo();
ResourceManager::TextureRepo ResourceManager::textureObjects = TextureRepo();
std::string ResourceManager::shaderRootDir = std::string("assets/shaders/");
std::string ResourceManager::meshRootDir = std::string("assets/models/");
std::string ResourceManager::textureRootDir = std::string("assets/images/");
}