// Copyright [2023] Krzysztof Rudnicki #ifndef HOME_KUCHY_ENGINEER_THESIS_WUT_BREAKOUT_RESOURCEMANAGER_CPP #define HOME_KUCHY_ENGINEER_THESIS_WUT_BREAKOUT_RESOURCEMANAGER_CPP #include #include "../breakout/resourceManager.hpp" #include "./shader.hpp" #include "./stb_image.h" #include "./texture.hpp" // Instantiate static variables std::map ResourceManager::Textures; std::map ResourceManager::Shaders; Shader ResourceManager::LoadShader(const char *vShaderFile, const char *fShaderFile, const char *gShaderFile, const std::string &name) { Shaders[name] = loadShaderFromFile(vShaderFile, fShaderFile, gShaderFile); return Shaders[name]; } Shader ResourceManager::GetShader(const std::string &name) { return Shaders[name]; } Texture2D ResourceManager::LoadTexture(const char *file, bool alpha, const std::string &name) { Textures[name] = loadTextureFromFile(file, alpha); return Textures[name]; } Texture2D ResourceManager::GetTexture(const std::string &name) { return Textures[name]; } void ResourceManager::Clear() { // (properly) delete all shaders for (const auto &iter : Shaders) { glDeleteProgram(iter.second.ID); } // (properly) delete all textures for (const auto &iter : Textures) { glDeleteTextures(1, &iter.second.ID); } } static Shader ResourceManager::createShaderObject( const std::string& vertexCode, const std::string& fragmentCode, const char *gShaderFile, const std::string& geometryCode) { const char *vShaderCode = vertexCode.c_str(); const char *fShaderCode = fragmentCode.c_str(); const char *gShaderCode = geometryCode.c_str(); // 2. now create shader object from source code Shader shader; shader.Compile(vShaderCode, fShaderCode, gShaderFile != nullptr ? gShaderCode : nullptr); return shader; } static std::string ResourceManager::loadFragmentCode(const char *fShaderFile) { std::string fragmentCode; // open files std::ifstream fragmentShaderFile(fShaderFile); std::stringstream fShaderStream; // read file's buffer contents into streams fShaderStream << fragmentShaderFile.rdbuf(); // close file handlers fragmentShaderFile.close(); // convert stream into string fragmentCode = fShaderStream.str(); return fragmentCode; } static std::string ResourceManager::loadVertexCode(const char *vShaderFile) { std::string vertexCode; std::ifstream vertexShaderFile(vShaderFile); std::stringstream vShaderStream; vShaderStream << vertexShaderFile.rdbuf(); vertexShaderFile.close(); vertexCode = vShaderStream.str(); return vertexCode } static std::string ResourceManager::loadGeometryCode(const char *gShaderFile) { std::string geometryCode; std::ifstream geometryShaderFile(gShaderFile); std::stringstream gShaderStream; gShaderStream << geometryShaderFile.rdbuf(); geometryShaderFile.close(); geometryCode = gShaderStream.str(); return geometryCode; } static Shader ResourceManager::loadShaderFromFile(const char *vShaderFile, const char *fShaderFile, const char *gShaderFile) { std::string vertexCode; std::string fragmentCode; std::string geometryCode; try { vertexCode = loadVertexCode(vShaderFile); fragmentCode = loadFragmentCode(fShaderFile); // if geometry shader path is present, also load a geometry shader if (gShaderFile != nullptr) { geometryCode = loadGeometryCode(gShaderFile); } } catch (std::exception const &) { std::cout << "ERROR::SHADER: Failed to read shader files" << std::endl; } return createShaderObject( vertexCode, fragmentCode, gShaderFile, geometryCode); } static Texture2D ResourceManager::createTextureObject(bool alpha) { // create texture object Texture2D texture; if (alpha) { texture.Internal_Format = GL_RGBA; texture.Image_Format = GL_RGBA; } return texture; } Texture2D ResourceManager::loadTextureFromFile(const char *file, bool alpha) { Texture2D texture = createTextureObject(alpha); // load image int width = -1; int height = -1; int nrChannels = -1; unsigned char *data = stbi_load(file, &width, &height, &nrChannels, 0); // now generate texture texture.Generate(width, height, data); // and finally free image data stbi_image_free(data); return texture; } #endif