From befc9cf09c8e76fa9b1f02e7d84e016d9b727884 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 10 Apr 2024 17:44:17 +0300 Subject: [PATCH] assets-related refactor --- src/assets/Assets.h | 7 + src/assets/AssetsLoader.cpp | 13 +- src/assets/AssetsLoader.h | 12 +- src/assets/assetload_funcs.cpp | 169 ++++++++++++------------ src/assets/assetload_funcs.h | 14 +- src/coders/GLSLExtension.cpp | 2 +- src/coders/GLSLExtension.h | 5 +- src/coders/png.cpp | 11 +- src/frontend/menu/menu_create_world.cpp | 9 +- src/graphics/core/Atlas.cpp | 11 +- src/graphics/core/Atlas.h | 3 +- src/graphics/core/Shader.cpp | 143 ++++++++++---------- src/graphics/core/Shader.h | 41 +++--- src/graphics/render/BlocksPreview.cpp | 4 +- 14 files changed, 242 insertions(+), 202 deletions(-) diff --git a/src/assets/Assets.h b/src/assets/Assets.h index 0be93771..d2d1ed00 100644 --- a/src/assets/Assets.h +++ b/src/assets/Assets.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -12,12 +13,18 @@ class Texture; class Shader; class Font; class Atlas; +class Assets; class UiDocument; namespace audio { class Sound; } +namespace assetload { + /// @brief final work to do in the main thread + using postfunc = std::function; +} + class Assets { std::unordered_map> textures; std::unordered_map> shaders; diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index b8c6f2d7..f1db04cb 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -49,9 +49,16 @@ bool AssetsLoader::loadNext() { return false; } aloader_func loader = found->second; - bool status = loader(*this, assets, paths, entry.filename, entry.alias, entry.config); - entries.pop(); - return status; + try { + auto postfunc = loader(*this, assets, paths, entry.filename, entry.alias, entry.config); + postfunc(assets); + entries.pop(); + return true; + } catch (std::runtime_error& err) { + logger.error() << err.what(); + entries.pop(); + return false; + } } void addLayouts(int env, const std::string& prefix, const fs::path& folder, AssetsLoader& loader) { diff --git a/src/assets/AssetsLoader.h b/src/assets/AssetsLoader.h index 5de43150..39dea158 100644 --- a/src/assets/AssetsLoader.h +++ b/src/assets/AssetsLoader.h @@ -1,6 +1,8 @@ #ifndef ASSETS_ASSETS_LOADER_H #define ASSETS_ASSETS_LOADER_H +#include "Assets.h" + #include #include #include @@ -23,7 +25,6 @@ enum class AssetType { }; class ResPaths; -class Assets; class AssetsLoader; class Content; @@ -43,7 +44,14 @@ struct SoundCfg : AssetCfg { SoundCfg(bool keepPCM) : keepPCM(keepPCM) {} }; -using aloader_func = std::function)>; +using aloader_func = std::function) +>; struct aloader_entry { AssetType tag; diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 668533b2..5b9327bb 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -1,6 +1,7 @@ #include "assetload_funcs.h" #include +#include #include #include "Assets.h" #include "AssetsLoader.h" @@ -9,6 +10,7 @@ #include "../files/engine_paths.h" #include "../coders/png.h" #include "../coders/json.h" +#include "../coders/GLSLExtension.h" #include "../graphics/core/Shader.h" #include "../graphics/core/Texture.h" #include "../graphics/core/ImageData.h" @@ -28,7 +30,7 @@ static bool animation( Atlas* dstAtlas ); -bool assetload::texture( +assetload::postfunc assetload::texture( AssetsLoader&, Assets* assets, const ResPaths* paths, @@ -36,18 +38,15 @@ bool assetload::texture( const std::string name, std::shared_ptr ) { - std::unique_ptr texture( - png::load_texture(paths->find(filename+".png").u8string()) + std::shared_ptr image ( + png::load_image(paths->find(filename+".png").u8string()) ); - if (texture == nullptr) { - std::cerr << "failed to load texture '" << name << "'" << std::endl; - return false; - } - assets->store(texture.release(), name); - return true; + return [name, image](auto assets) { + assets->store(Texture::from(image.get()), name); + }; } -bool assetload::shader( +assetload::postfunc assetload::shader( AssetsLoader&, Assets* assets, const ResPaths* paths, @@ -61,18 +60,16 @@ bool assetload::shader( std::string vertexSource = files::read_string(vertexFile); std::string fragmentSource = files::read_string(fragmentFile); - Shader* shader = Shader::create( - vertexFile.string(), - fragmentFile.string(), - vertexSource, fragmentSource - ); + vertexSource = Shader::preprocessor->process(vertexFile, vertexSource); + fragmentSource = Shader::preprocessor->process(fragmentFile, fragmentSource); - if (shader == nullptr) { - std::cerr << "failed to load shader '" << name << "'" << std::endl; - return false; - } - assets->store(shader, name); - return true; + return [=](auto assets) { + assets->store(Shader::create( + vertexFile.u8string(), + fragmentFile.u8string(), + vertexSource, fragmentSource + ), name); + }; } static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) { @@ -85,17 +82,13 @@ static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) { return false; } std::unique_ptr image(png::load_image(file.string())); - if (image == nullptr) { - std::cerr << "could not to load " << file.string() << std::endl; - return false; - } image->fixAlphaColor(); atlas.add(name, image.release()); return true; } -bool assetload::atlas( +assetload::postfunc assetload::atlas( AssetsLoader&, Assets* assets, const ResPaths* paths, @@ -105,17 +98,23 @@ bool assetload::atlas( ) { AtlasBuilder builder; for (const auto& file : paths->listdir(directory)) { - if (!appendAtlas(builder, file)) continue; + if (!appendAtlas(builder, file)) + continue; } + std::set names = builder.getNames(); Atlas* atlas = builder.build(2); - assets->store(atlas, name); - for (const auto& file : builder.getNames()) { - animation(assets, paths, "textures", file, atlas); - } - return true; + return [=](auto assets) { + atlas->prepare(); + assets->store(atlas, name); + + // FIXME + for (const auto& file : names) { + animation(assets, paths, "textures", file, atlas); + } + }; } -bool assetload::font( +assetload::postfunc assetload::font( AssetsLoader&, Assets* assets, const ResPaths* paths, @@ -123,25 +122,24 @@ bool assetload::font( const std::string name, std::shared_ptr ) { - std::vector> pages; + auto pages = std::make_shared>>(); for (size_t i = 0; i <= 4; i++) { std::string name = filename + "_" + std::to_string(i) + ".png"; name = paths->find(name).string(); - std::unique_ptr texture (png::load_texture(name)); - if (texture == nullptr) { - std::cerr << "failed to load bitmap font '" << name; - std::cerr << "' (missing page " << std::to_string(i) << ")"; - std::cerr << std::endl; - return false; - } - pages.push_back(std::move(texture)); + std::unique_ptr image (png::load_image(name)); + pages->push_back(std::move(image)); } - int res = pages[0]->getHeight() / 16; - assets->store(new Font(std::move(pages), res, 4), name); - return true; + return [=](auto assets) { + int res = pages->at(0)->getHeight() / 16; + std::vector> textures; + for (auto& page : *pages) { + textures.emplace_back(Texture::from(page.get())); + } + assets->store(new Font(std::move(textures), res, 4), name); + }; } -bool assetload::layout( +assetload::postfunc assetload::layout( AssetsLoader& loader, Assets* assets, const ResPaths* paths, @@ -149,18 +147,19 @@ bool assetload::layout( const std::string name, std::shared_ptr config ) { - try { - auto cfg = dynamic_cast(config.get()); - auto document = UiDocument::read(cfg->env, name, file); - assets->store(document.release(), name); - return true; - } catch (const parsing_error& err) { - std::cerr << "failed to parse layout XML '" << file << "'" << std::endl; - std::cerr << err.errorLog() << std::endl; - return false; - } + return [=](auto assets) { + try { + auto cfg = dynamic_cast(config.get()); + auto document = UiDocument::read(cfg->env, name, file); + assets->store(document.release(), name); + } catch (const parsing_error& err) { + throw std::runtime_error( + "failed to parse layout XML '"+file+"':\n"+err.errorLog() + ); + } + }; } -bool assetload::sound( +assetload::postfunc assetload::sound( AssetsLoader& loader, Assets* assets, const ResPaths* paths, @@ -172,37 +171,35 @@ bool assetload::sound( bool keepPCM = cfg ? cfg->keepPCM : false; std::string extension = ".ogg"; - try { - std::unique_ptr baseSound = nullptr; + std::unique_ptr baseSound = nullptr; - // looking for 'sound_name' as base sound - auto soundFile = paths->find(file+extension); - if (fs::exists(soundFile)) { - baseSound.reset(audio::load_sound(soundFile, keepPCM)); - } - // looking for 'sound_name_0' as base sound - auto variantFile = paths->find(file+"_0"+extension); - if (fs::exists(variantFile)) { - baseSound.reset(audio::load_sound(variantFile, keepPCM)); - } - - // loading sound variants - for (uint i = 1; ; i++) { - auto variantFile = paths->find(file+"_"+std::to_string(i)+extension); - if (!fs::exists(variantFile)) { - break; - } - baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM)); - } - assets->store(baseSound.release(), name); - } - catch (std::runtime_error& err) { - std::cerr << err.what() << std::endl; - return false; + // looking for 'sound_name' as base sound + auto soundFile = paths->find(file+extension); + if (fs::exists(soundFile)) { + baseSound.reset(audio::load_sound(soundFile, keepPCM)); } - return true; + // looking for 'sound_name_0' as base sound + auto variantFile = paths->find(file+"_0"+extension); + if (fs::exists(variantFile)) { + baseSound.reset(audio::load_sound(variantFile, keepPCM)); + } + + // loading sound variants + for (uint i = 1; ; i++) { + auto variantFile = paths->find(file+"_"+std::to_string(i)+extension); + if (!fs::exists(variantFile)) { + break; + } + baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM)); + } + + auto sound = baseSound.release(); + return [=](auto assets) { + assets->store(sound, name); + }; } +// TODO: integrate static bool animation( Assets* assets, const ResPaths* paths, @@ -256,10 +253,12 @@ static bool animation( } if (!contains) continue; } - if (!appendAtlas(builder, file)) continue; + if (!appendAtlas(builder, file)) + continue; } std::unique_ptr srcAtlas (builder.build(2)); + srcAtlas->prepare(); Texture* srcTex = srcAtlas->getTexture(); Texture* dstTex = dstAtlas->getTexture(); diff --git a/src/assets/assetload_funcs.h b/src/assets/assetload_funcs.h index aebdb0a6..abbb8196 100644 --- a/src/assets/assetload_funcs.h +++ b/src/assets/assetload_funcs.h @@ -1,6 +1,8 @@ #ifndef ASSETS_ASSET_LOADERS_H_ #define ASSETS_ASSET_LOADERS_H_ +#include "Assets.h" + #include #include @@ -12,7 +14,7 @@ struct AssetCfg; /// @brief see AssetsLoader.h: aloader_func namespace assetload { - bool texture( + postfunc texture( AssetsLoader&, Assets*, const ResPaths* paths, @@ -20,7 +22,7 @@ namespace assetload { const std::string name, std::shared_ptr settings ); - bool shader( + postfunc shader( AssetsLoader&, Assets*, const ResPaths* paths, @@ -28,7 +30,7 @@ namespace assetload { const std::string name, std::shared_ptr settings ); - bool atlas( + postfunc atlas( AssetsLoader&, Assets*, const ResPaths* paths, @@ -36,7 +38,7 @@ namespace assetload { const std::string name, std::shared_ptr settings ); - bool font( + postfunc font( AssetsLoader&, Assets*, const ResPaths* paths, @@ -44,7 +46,7 @@ namespace assetload { const std::string name, std::shared_ptr settings ); - bool layout( + postfunc layout( AssetsLoader&, Assets*, const ResPaths* paths, @@ -53,7 +55,7 @@ namespace assetload { std::shared_ptr settings ); - bool sound( + postfunc sound( AssetsLoader&, Assets*, const ResPaths* paths, diff --git a/src/coders/GLSLExtension.cpp b/src/coders/GLSLExtension.cpp index a297fd98..0aa9dacb 100644 --- a/src/coders/GLSLExtension.cpp +++ b/src/coders/GLSLExtension.cpp @@ -81,7 +81,7 @@ inline void source_line(std::stringstream& ss, uint linenum) { ss << "#line " << linenum << "\n"; } -const std::string GLSLExtension::process(const fs::path file, const std::string& source) { +const std::string GLSLExtension::process(const fs::path& file, const std::string& source) { std::stringstream ss; size_t pos = 0; uint linenum = 1; diff --git a/src/coders/GLSLExtension.h b/src/coders/GLSLExtension.h index 3b4c494f..b5344f67 100644 --- a/src/coders/GLSLExtension.h +++ b/src/coders/GLSLExtension.h @@ -29,7 +29,10 @@ public: bool hasHeader(const std::string& name) const; bool hasDefine(const std::string& name) const; - const std::string process(const std::filesystem::path file, const std::string& source); + const std::string process( + const std::filesystem::path& file, + const std::string& source + ); }; #endif // CODERS_GLSL_EXTESION_H_ diff --git a/src/coders/png.cpp b/src/coders/png.cpp index d1711c3c..349f4f26 100644 --- a/src/coders/png.cpp +++ b/src/coders/png.cpp @@ -343,18 +343,13 @@ ImageData* _png_load(const char* file){ ImageData* png::load_image(std::string filename) { ImageData* image (_png_load(filename.c_str())); if (image == nullptr) { - std::cerr << "Could not load image " << filename << std::endl; - return nullptr; + throw std::runtime_error("could not load image "+filename); } return image; } Texture* png::load_texture(std::string filename) { - std::unique_ptr image (_png_load(filename.c_str())); - if (image == nullptr){ - std::cerr << "Could not load texture " << filename << std::endl; - return nullptr; - } + std::unique_ptr image (load_image(filename)); auto texture = Texture::from(image.get()); texture->setNearestFilter(); return texture; @@ -362,4 +357,4 @@ Texture* png::load_texture(std::string filename) { void png::write_image(std::string filename, const ImageData* image) { _png_write(filename.c_str(), image->getWidth(), image->getHeight(), (const ubyte*)image->getData(), image->getFormat() == ImageFormat::rgba8888); -} \ No newline at end of file +} diff --git a/src/frontend/menu/menu_create_world.cpp b/src/frontend/menu/menu_create_world.cpp index f1fcc7c0..5b72a427 100644 --- a/src/frontend/menu/menu_create_world.cpp +++ b/src/frontend/menu/menu_create_world.cpp @@ -109,7 +109,12 @@ void menus::create_new_world_panel(Engine* engine) { auto seedInput = std::make_shared(seedstr, glm::vec4(6.0f)); panel->add(seedInput); - generatorTypeButton = guiutil::gotoButton(langs::get(L"World generator", L"world") + (L": ") + util::str2wstr_utf8(translate_generator_id(menus::generatorID)), "world_generators", engine->getGUI()->getMenu()); + generatorTypeButton = guiutil::gotoButton( + langs::get(L"World generator", L"world") + L": " + + util::str2wstr_utf8(translate_generator_id(menus::generatorID)), + "world_generators", + engine->getGUI()->getMenu() + ); panel->add(generatorTypeButton); panel->add(menus::create_button(L"Create World", glm::vec4(10), glm::vec4(1, 20, 1, 1), @@ -153,7 +158,7 @@ void menus::create_new_world_panel(Engine* engine) { engine->getContent(), engine->getContentPacks() ); - level->world->wfile->createDirectories(); + level->getWorld()->wfile->createDirectories(); menus::generatorID = WorldGenerators::getDefaultGeneratorID(); engine->setScreen(std::make_shared(engine, level)); })); diff --git a/src/graphics/core/Atlas.cpp b/src/graphics/core/Atlas.cpp index cc388345..7d855a1a 100644 --- a/src/graphics/core/Atlas.cpp +++ b/src/graphics/core/Atlas.cpp @@ -6,7 +6,7 @@ #include "ImageData.h" Atlas::Atlas(ImageData* image, std::unordered_map regions) - : texture(Texture::from(image)), + : texture(nullptr), image(image), regions(regions) { } @@ -14,6 +14,10 @@ Atlas::Atlas(ImageData* image, std::unordered_map regions Atlas::~Atlas() { } +void Atlas::prepare() { + texture.reset(Texture::from(image.get())); +} + bool Atlas::has(const std::string& name) const { return regions.find(name) != regions.end(); } @@ -80,8 +84,9 @@ Atlas* AtlasBuilder::build(uint extrusion, uint maxResolution) { } float unitX = 1.0f / width; float unitY = 1.0f / height; - regions[entry.name] = UVRegion(unitX * x, unitY * y, - unitX * (x + w), unitY * (y + h)); + regions[entry.name] = UVRegion( + unitX * x, unitY * y, unitX * (x + w), unitY * (y + h) + ); } return new Atlas(canvas.release(), regions); } diff --git a/src/graphics/core/Atlas.h b/src/graphics/core/Atlas.h index 72e407fc..24ea717a 100644 --- a/src/graphics/core/Atlas.h +++ b/src/graphics/core/Atlas.h @@ -20,6 +20,8 @@ public: Atlas(ImageData* image, std::unordered_map regions); ~Atlas(); + void prepare(); + bool has(const std::string& name) const; const UVRegion& get(const std::string& name) const; @@ -27,7 +29,6 @@ public: ImageData* getImage() const; }; - struct atlasentry { std::string name; std::shared_ptr image; diff --git a/src/graphics/core/Shader.cpp b/src/graphics/core/Shader.cpp index a44d8a7f..b7b17d44 100644 --- a/src/graphics/core/Shader.cpp +++ b/src/graphics/core/Shader.cpp @@ -17,7 +17,7 @@ namespace fs = std::filesystem; GLSLExtension* Shader::preprocessor = new GLSLExtension(); -Shader::Shader(unsigned int id) : id(id){ +Shader::Shader(uint id) : id(id){ } Shader::~Shader(){ @@ -28,106 +28,101 @@ void Shader::use(){ glUseProgram(id); } -void Shader::uniformMatrix(std::string name, glm::mat4 matrix){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(matrix)); +uint Shader::getUniformLocation(const std::string& name) { + auto found = uniformLocations.find(name); + if (found == uniformLocations.end()) { + uint location = glGetUniformLocation(id, name.c_str()); + uniformLocations.emplace(name, location); + return location; + } + return found->second; } -void Shader::uniform1i(std::string name, int x){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniform1i(transformLoc, x); +void Shader::uniformMatrix(const std::string& name, glm::mat4 matrix){ + glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix)); } -void Shader::uniform1f(std::string name, float x){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniform1f(transformLoc, x); +void Shader::uniform1i(const std::string& name, int x){ + glUniform1i(getUniformLocation(name), x); } -void Shader::uniform2f(std::string name, float x, float y){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniform2f(transformLoc, x, y); +void Shader::uniform1f(const std::string& name, float x){ + glUniform1f(getUniformLocation(name), x); } -void Shader::uniform2f(std::string name, glm::vec2 xy){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniform2f(transformLoc, xy.x, xy.y); +void Shader::uniform2f(const std::string& name, float x, float y){ + glUniform2f(getUniformLocation(name), x, y); } -void Shader::uniform2i(std::string name, glm::ivec2 xy){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniform2i(transformLoc, xy.x, xy.y); +void Shader::uniform2f(const std::string& name, glm::vec2 xy){ + glUniform2f(getUniformLocation(name), xy.x, xy.y); } -void Shader::uniform3f(std::string name, float x, float y, float z){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniform3f(transformLoc, x,y,z); +void Shader::uniform2i(const std::string& name, glm::ivec2 xy){ + glUniform2i(getUniformLocation(name), xy.x, xy.y); } -void Shader::uniform3f(std::string name, glm::vec3 xyz){ - GLuint transformLoc = glGetUniformLocation(id, name.c_str()); - glUniform3f(transformLoc, xyz.x, xyz.y, xyz.z); +void Shader::uniform3f(const std::string& name, float x, float y, float z){ + glUniform3f(getUniformLocation(name), x,y,z); } +void Shader::uniform3f(const std::string& name, glm::vec3 xyz){ + glUniform3f(getUniformLocation(name), xyz.x, xyz.y, xyz.z); +} + + +inline auto shader_deleter = [](GLuint* shader) { + glDeleteShader(*shader); +}; + +inline const uint GL_LOG_LEN = 512; + +// shader should be deleted after shader program linking +using glshader = std::unique_ptr; + +glshader compile_shader(GLenum type, const GLchar* source, const std::string& file) { + GLint success; + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &source, nullptr); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success){ + GLchar infoLog[GL_LOG_LEN]; + glGetShaderInfoLog(shader, GL_LOG_LEN, nullptr, infoLog); + glDeleteShader(shader); + throw std::runtime_error( + "vertex shader compilation failed ("+file+"):\n"+std::string(infoLog) + ); + } + return glshader(new GLuint(shader), shader_deleter); +} Shader* Shader::create( - std::string vertexFile, - std::string fragmentFile, - std::string vertexCode, - std::string fragmentCode + const std::string& vertexFile, + const std::string& fragmentFile, + const std::string& vertexCode, + const std::string& fragmentCode ) { - vertexCode = preprocessor->process(fs::path(vertexFile), vertexCode); - fragmentCode = preprocessor->process(fs::path(fragmentFile), fragmentCode); + const GLchar* vCode = vertexCode.c_str(); + const GLchar* fCode = fragmentCode.c_str(); - const GLchar* vShaderCode = vertexCode.c_str(); - const GLchar* fShaderCode = fragmentCode.c_str(); - - GLuint vertex, fragment; - GLint success; - GLchar infoLog[512]; - - // Vertex Shader - vertex = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertex, 1, &vShaderCode, nullptr); - glCompileShader(vertex); - glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); - if (!success){ - glGetShaderInfoLog(vertex, 512, nullptr, infoLog); - std::cerr << "SHADER::VERTEX: compilation failed: " << vertexFile << std::endl; - std::cerr << infoLog << std::endl; - return nullptr; - } - - // Fragment Shader - fragment = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragment, 1, &fShaderCode, nullptr); - glCompileShader(fragment); - glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); - if (!success){ - glGetShaderInfoLog(fragment, 512, nullptr, infoLog); - std::cerr << "SHADER::FRAGMENT: compilation failed: " << vertexFile << std::endl; - std::cerr << infoLog << std::endl; - return nullptr; - } + glshader vertex = compile_shader(GL_VERTEX_SHADER, vCode, vertexFile); + glshader fragment = compile_shader(GL_FRAGMENT_SHADER, fCode, fragmentFile); // Shader Program + GLint success; GLuint id = glCreateProgram(); - glAttachShader(id, vertex); - glAttachShader(id, fragment); + glAttachShader(id, *vertex); + glAttachShader(id, *fragment); glLinkProgram(id); glGetProgramiv(id, GL_LINK_STATUS, &success); if (!success){ - glGetProgramInfoLog(id, 512, nullptr, infoLog); - std::cerr << "SHADER::PROGRAM: linking failed" << std::endl; - std::cerr << infoLog << std::endl; - - glDeleteShader(vertex); - glDeleteShader(fragment); - return nullptr; + GLchar infoLog[GL_LOG_LEN]; + glGetProgramInfoLog(id, GL_LOG_LEN, nullptr, infoLog); + throw std::runtime_error( + "shader program linking failed:\n"+std::string(infoLog) + ); } - - glDeleteShader(vertex); - glDeleteShader(fragment); - return new Shader(id); } diff --git a/src/graphics/core/Shader.h b/src/graphics/core/Shader.h index 97f90ee2..5035fee4 100644 --- a/src/graphics/core/Shader.h +++ b/src/graphics/core/Shader.h @@ -1,35 +1,46 @@ #ifndef GRAPHICS_CORE_SHADER_H_ #define GRAPHICS_CORE_SHADER_H_ -#include -#include #include "../../typedefs.h" +#include +#include +#include + class GLSLExtension; class Shader { uint id; + std::unordered_map uniformLocations; + + uint getUniformLocation(const std::string& name); public: static GLSLExtension* preprocessor; - Shader(unsigned int id); + Shader(uint id); ~Shader(); void use(); - void uniformMatrix(std::string name, glm::mat4 matrix); - void uniform1i(std::string name, int x); - void uniform1f(std::string name, float x); - void uniform2f(std::string name, float x, float y); - void uniform2f(std::string name, glm::vec2 xy); - void uniform2i(std::string name, glm::ivec2 xy); - void uniform3f(std::string name, float x, float y, float z); - void uniform3f(std::string name, glm::vec3 xyz); + void uniformMatrix(const std::string&, glm::mat4 matrix); + void uniform1i(const std::string& name, int x); + void uniform1f(const std::string& name, float x); + void uniform2f(const std::string& name, float x, float y); + void uniform2f(const std::string& name, glm::vec2 xy); + void uniform2i(const std::string& name, glm::ivec2 xy); + void uniform3f(const std::string& name, float x, float y, float z); + void uniform3f(const std::string& name, glm::vec3 xyz); + /// @brief Create shader program using vertex and fragment shaders source. + /// @param vertexFile vertex shader file name + /// @param fragmentFile fragment shader file name + /// @param vertexSource vertex shader source code + /// @param fragmentSource fragment shader source code + /// @return linked shader program containing vertex and fragment shaders static Shader* create( - std::string vertexFile, - std::string fragmentFile, - std::string vertexSource, - std::string fragmentSource + const std::string& vertexFile, + const std::string& fragmentFile, + const std::string& vertexSource, + const std::string& fragmentSource ); }; diff --git a/src/graphics/render/BlocksPreview.cpp b/src/graphics/render/BlocksPreview.cpp index a38b4cef..7fcc32fe 100644 --- a/src/graphics/render/BlocksPreview.cpp +++ b/src/graphics/render/BlocksPreview.cpp @@ -142,5 +142,7 @@ std::unique_ptr BlocksPreview::build( fbo.unbind(); Window::viewport(0, 0, Window::width, Window::height); - return std::unique_ptr(builder.build(2)); + auto newAtlas = std::unique_ptr(builder.build(2)); + newAtlas->prepare(); + return newAtlas; }