assets-related refactor

This commit is contained in:
MihailRis
2024-04-10 17:44:17 +03:00
parent 216e38e411
commit befc9cf09c
14 changed files with 242 additions and 202 deletions
+7
View File
@@ -5,6 +5,7 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <functional>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@@ -12,12 +13,18 @@ class Texture;
class Shader; class Shader;
class Font; class Font;
class Atlas; class Atlas;
class Assets;
class UiDocument; class UiDocument;
namespace audio { namespace audio {
class Sound; class Sound;
} }
namespace assetload {
/// @brief final work to do in the main thread
using postfunc = std::function<void(Assets*)>;
}
class Assets { class Assets {
std::unordered_map<std::string, std::shared_ptr<Texture>> textures; std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders; std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
+10 -3
View File
@@ -49,9 +49,16 @@ bool AssetsLoader::loadNext() {
return false; return false;
} }
aloader_func loader = found->second; aloader_func loader = found->second;
bool status = loader(*this, assets, paths, entry.filename, entry.alias, entry.config); try {
entries.pop(); auto postfunc = loader(*this, assets, paths, entry.filename, entry.alias, entry.config);
return status; 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) { void addLayouts(int env, const std::string& prefix, const fs::path& folder, AssetsLoader& loader) {
+10 -2
View File
@@ -1,6 +1,8 @@
#ifndef ASSETS_ASSETS_LOADER_H #ifndef ASSETS_ASSETS_LOADER_H
#define ASSETS_ASSETS_LOADER_H #define ASSETS_ASSETS_LOADER_H
#include "Assets.h"
#include <string> #include <string>
#include <memory> #include <memory>
#include <filesystem> #include <filesystem>
@@ -23,7 +25,6 @@ enum class AssetType {
}; };
class ResPaths; class ResPaths;
class Assets;
class AssetsLoader; class AssetsLoader;
class Content; class Content;
@@ -43,7 +44,14 @@ struct SoundCfg : AssetCfg {
SoundCfg(bool keepPCM) : keepPCM(keepPCM) {} SoundCfg(bool keepPCM) : keepPCM(keepPCM) {}
}; };
using aloader_func = std::function<bool(AssetsLoader&, Assets*, const ResPaths*, const std::string&, const std::string&, std::shared_ptr<AssetCfg>)>; using aloader_func = std::function<assetload::postfunc(
AssetsLoader&,
Assets*,
const ResPaths*,
const std::string&,
const std::string&,
std::shared_ptr<AssetCfg>)
>;
struct aloader_entry { struct aloader_entry {
AssetType tag; AssetType tag;
+82 -83
View File
@@ -1,6 +1,7 @@
#include "assetload_funcs.h" #include "assetload_funcs.h"
#include <iostream> #include <iostream>
#include <stdexcept>
#include <filesystem> #include <filesystem>
#include "Assets.h" #include "Assets.h"
#include "AssetsLoader.h" #include "AssetsLoader.h"
@@ -9,6 +10,7 @@
#include "../files/engine_paths.h" #include "../files/engine_paths.h"
#include "../coders/png.h" #include "../coders/png.h"
#include "../coders/json.h" #include "../coders/json.h"
#include "../coders/GLSLExtension.h"
#include "../graphics/core/Shader.h" #include "../graphics/core/Shader.h"
#include "../graphics/core/Texture.h" #include "../graphics/core/Texture.h"
#include "../graphics/core/ImageData.h" #include "../graphics/core/ImageData.h"
@@ -28,7 +30,7 @@ static bool animation(
Atlas* dstAtlas Atlas* dstAtlas
); );
bool assetload::texture( assetload::postfunc assetload::texture(
AssetsLoader&, AssetsLoader&,
Assets* assets, Assets* assets,
const ResPaths* paths, const ResPaths* paths,
@@ -36,18 +38,15 @@ bool assetload::texture(
const std::string name, const std::string name,
std::shared_ptr<AssetCfg> std::shared_ptr<AssetCfg>
) { ) {
std::unique_ptr<Texture> texture( std::shared_ptr<ImageData> image (
png::load_texture(paths->find(filename+".png").u8string()) png::load_image(paths->find(filename+".png").u8string())
); );
if (texture == nullptr) { return [name, image](auto assets) {
std::cerr << "failed to load texture '" << name << "'" << std::endl; assets->store(Texture::from(image.get()), name);
return false; };
}
assets->store(texture.release(), name);
return true;
} }
bool assetload::shader( assetload::postfunc assetload::shader(
AssetsLoader&, AssetsLoader&,
Assets* assets, Assets* assets,
const ResPaths* paths, const ResPaths* paths,
@@ -61,18 +60,16 @@ bool assetload::shader(
std::string vertexSource = files::read_string(vertexFile); std::string vertexSource = files::read_string(vertexFile);
std::string fragmentSource = files::read_string(fragmentFile); std::string fragmentSource = files::read_string(fragmentFile);
Shader* shader = Shader::create( vertexSource = Shader::preprocessor->process(vertexFile, vertexSource);
vertexFile.string(), fragmentSource = Shader::preprocessor->process(fragmentFile, fragmentSource);
fragmentFile.string(),
vertexSource, fragmentSource
);
if (shader == nullptr) { return [=](auto assets) {
std::cerr << "failed to load shader '" << name << "'" << std::endl; assets->store(Shader::create(
return false; vertexFile.u8string(),
} fragmentFile.u8string(),
assets->store(shader, name); vertexSource, fragmentSource
return true; ), name);
};
} }
static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) { static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) {
@@ -85,17 +82,13 @@ static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) {
return false; return false;
} }
std::unique_ptr<ImageData> image(png::load_image(file.string())); std::unique_ptr<ImageData> image(png::load_image(file.string()));
if (image == nullptr) {
std::cerr << "could not to load " << file.string() << std::endl;
return false;
}
image->fixAlphaColor(); image->fixAlphaColor();
atlas.add(name, image.release()); atlas.add(name, image.release());
return true; return true;
} }
bool assetload::atlas( assetload::postfunc assetload::atlas(
AssetsLoader&, AssetsLoader&,
Assets* assets, Assets* assets,
const ResPaths* paths, const ResPaths* paths,
@@ -105,17 +98,23 @@ bool assetload::atlas(
) { ) {
AtlasBuilder builder; AtlasBuilder builder;
for (const auto& file : paths->listdir(directory)) { for (const auto& file : paths->listdir(directory)) {
if (!appendAtlas(builder, file)) continue; if (!appendAtlas(builder, file))
continue;
} }
std::set<std::string> names = builder.getNames();
Atlas* atlas = builder.build(2); Atlas* atlas = builder.build(2);
assets->store(atlas, name); return [=](auto assets) {
for (const auto& file : builder.getNames()) { atlas->prepare();
animation(assets, paths, "textures", file, atlas); assets->store(atlas, name);
}
return true; // FIXME
for (const auto& file : names) {
animation(assets, paths, "textures", file, atlas);
}
};
} }
bool assetload::font( assetload::postfunc assetload::font(
AssetsLoader&, AssetsLoader&,
Assets* assets, Assets* assets,
const ResPaths* paths, const ResPaths* paths,
@@ -123,25 +122,24 @@ bool assetload::font(
const std::string name, const std::string name,
std::shared_ptr<AssetCfg> std::shared_ptr<AssetCfg>
) { ) {
std::vector<std::unique_ptr<Texture>> pages; auto pages = std::make_shared<std::vector<std::unique_ptr<ImageData>>>();
for (size_t i = 0; i <= 4; i++) { for (size_t i = 0; i <= 4; i++) {
std::string name = filename + "_" + std::to_string(i) + ".png"; std::string name = filename + "_" + std::to_string(i) + ".png";
name = paths->find(name).string(); name = paths->find(name).string();
std::unique_ptr<Texture> texture (png::load_texture(name)); std::unique_ptr<ImageData> image (png::load_image(name));
if (texture == nullptr) { pages->push_back(std::move(image));
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));
} }
int res = pages[0]->getHeight() / 16; return [=](auto assets) {
assets->store(new Font(std::move(pages), res, 4), name); int res = pages->at(0)->getHeight() / 16;
return true; std::vector<std::unique_ptr<Texture>> 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, AssetsLoader& loader,
Assets* assets, Assets* assets,
const ResPaths* paths, const ResPaths* paths,
@@ -149,18 +147,19 @@ bool assetload::layout(
const std::string name, const std::string name,
std::shared_ptr<AssetCfg> config std::shared_ptr<AssetCfg> config
) { ) {
try { return [=](auto assets) {
auto cfg = dynamic_cast<LayoutCfg*>(config.get()); try {
auto document = UiDocument::read(cfg->env, name, file); auto cfg = dynamic_cast<LayoutCfg*>(config.get());
assets->store(document.release(), name); auto document = UiDocument::read(cfg->env, name, file);
return true; assets->store(document.release(), name);
} catch (const parsing_error& err) { } catch (const parsing_error& err) {
std::cerr << "failed to parse layout XML '" << file << "'" << std::endl; throw std::runtime_error(
std::cerr << err.errorLog() << std::endl; "failed to parse layout XML '"+file+"':\n"+err.errorLog()
return false; );
} }
};
} }
bool assetload::sound( assetload::postfunc assetload::sound(
AssetsLoader& loader, AssetsLoader& loader,
Assets* assets, Assets* assets,
const ResPaths* paths, const ResPaths* paths,
@@ -172,37 +171,35 @@ bool assetload::sound(
bool keepPCM = cfg ? cfg->keepPCM : false; bool keepPCM = cfg ? cfg->keepPCM : false;
std::string extension = ".ogg"; std::string extension = ".ogg";
try { std::unique_ptr<audio::Sound> baseSound = nullptr;
std::unique_ptr<audio::Sound> baseSound = nullptr;
// looking for 'sound_name' as base sound // looking for 'sound_name' as base sound
auto soundFile = paths->find(file+extension); auto soundFile = paths->find(file+extension);
if (fs::exists(soundFile)) { if (fs::exists(soundFile)) {
baseSound.reset(audio::load_sound(soundFile, keepPCM)); baseSound.reset(audio::load_sound(soundFile, keepPCM));
} }
// looking for 'sound_name_0' as base sound // looking for 'sound_name_0' as base sound
auto variantFile = paths->find(file+"_0"+extension); auto variantFile = paths->find(file+"_0"+extension);
if (fs::exists(variantFile)) { if (fs::exists(variantFile)) {
baseSound.reset(audio::load_sound(variantFile, keepPCM)); baseSound.reset(audio::load_sound(variantFile, keepPCM));
} }
// loading sound variants // loading sound variants
for (uint i = 1; ; i++) { for (uint i = 1; ; i++) {
auto variantFile = paths->find(file+"_"+std::to_string(i)+extension); auto variantFile = paths->find(file+"_"+std::to_string(i)+extension);
if (!fs::exists(variantFile)) { if (!fs::exists(variantFile)) {
break; break;
}
baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
} }
assets->store(baseSound.release(), name); baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
} }
catch (std::runtime_error& err) {
std::cerr << err.what() << std::endl; auto sound = baseSound.release();
return false; return [=](auto assets) {
} assets->store(sound, name);
return true; };
} }
// TODO: integrate
static bool animation( static bool animation(
Assets* assets, Assets* assets,
const ResPaths* paths, const ResPaths* paths,
@@ -256,10 +253,12 @@ static bool animation(
} }
if (!contains) continue; if (!contains) continue;
} }
if (!appendAtlas(builder, file)) continue; if (!appendAtlas(builder, file))
continue;
} }
std::unique_ptr<Atlas> srcAtlas (builder.build(2)); std::unique_ptr<Atlas> srcAtlas (builder.build(2));
srcAtlas->prepare();
Texture* srcTex = srcAtlas->getTexture(); Texture* srcTex = srcAtlas->getTexture();
Texture* dstTex = dstAtlas->getTexture(); Texture* dstTex = dstAtlas->getTexture();
+8 -6
View File
@@ -1,6 +1,8 @@
#ifndef ASSETS_ASSET_LOADERS_H_ #ifndef ASSETS_ASSET_LOADERS_H_
#define ASSETS_ASSET_LOADERS_H_ #define ASSETS_ASSET_LOADERS_H_
#include "Assets.h"
#include <string> #include <string>
#include <memory> #include <memory>
@@ -12,7 +14,7 @@ struct AssetCfg;
/// @brief see AssetsLoader.h: aloader_func /// @brief see AssetsLoader.h: aloader_func
namespace assetload { namespace assetload {
bool texture( postfunc texture(
AssetsLoader&, AssetsLoader&,
Assets*, Assets*,
const ResPaths* paths, const ResPaths* paths,
@@ -20,7 +22,7 @@ namespace assetload {
const std::string name, const std::string name,
std::shared_ptr<AssetCfg> settings std::shared_ptr<AssetCfg> settings
); );
bool shader( postfunc shader(
AssetsLoader&, AssetsLoader&,
Assets*, Assets*,
const ResPaths* paths, const ResPaths* paths,
@@ -28,7 +30,7 @@ namespace assetload {
const std::string name, const std::string name,
std::shared_ptr<AssetCfg> settings std::shared_ptr<AssetCfg> settings
); );
bool atlas( postfunc atlas(
AssetsLoader&, AssetsLoader&,
Assets*, Assets*,
const ResPaths* paths, const ResPaths* paths,
@@ -36,7 +38,7 @@ namespace assetload {
const std::string name, const std::string name,
std::shared_ptr<AssetCfg> settings std::shared_ptr<AssetCfg> settings
); );
bool font( postfunc font(
AssetsLoader&, AssetsLoader&,
Assets*, Assets*,
const ResPaths* paths, const ResPaths* paths,
@@ -44,7 +46,7 @@ namespace assetload {
const std::string name, const std::string name,
std::shared_ptr<AssetCfg> settings std::shared_ptr<AssetCfg> settings
); );
bool layout( postfunc layout(
AssetsLoader&, AssetsLoader&,
Assets*, Assets*,
const ResPaths* paths, const ResPaths* paths,
@@ -53,7 +55,7 @@ namespace assetload {
std::shared_ptr<AssetCfg> settings std::shared_ptr<AssetCfg> settings
); );
bool sound( postfunc sound(
AssetsLoader&, AssetsLoader&,
Assets*, Assets*,
const ResPaths* paths, const ResPaths* paths,
+1 -1
View File
@@ -81,7 +81,7 @@ inline void source_line(std::stringstream& ss, uint linenum) {
ss << "#line " << linenum << "\n"; 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; std::stringstream ss;
size_t pos = 0; size_t pos = 0;
uint linenum = 1; uint linenum = 1;
+4 -1
View File
@@ -29,7 +29,10 @@ public:
bool hasHeader(const std::string& name) const; bool hasHeader(const std::string& name) const;
bool hasDefine(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_ #endif // CODERS_GLSL_EXTESION_H_
+2 -7
View File
@@ -343,18 +343,13 @@ ImageData* _png_load(const char* file){
ImageData* png::load_image(std::string filename) { ImageData* png::load_image(std::string filename) {
ImageData* image (_png_load(filename.c_str())); ImageData* image (_png_load(filename.c_str()));
if (image == nullptr) { if (image == nullptr) {
std::cerr << "Could not load image " << filename << std::endl; throw std::runtime_error("could not load image "+filename);
return nullptr;
} }
return image; return image;
} }
Texture* png::load_texture(std::string filename) { Texture* png::load_texture(std::string filename) {
std::unique_ptr<ImageData> image (_png_load(filename.c_str())); std::unique_ptr<ImageData> image (load_image(filename));
if (image == nullptr){
std::cerr << "Could not load texture " << filename << std::endl;
return nullptr;
}
auto texture = Texture::from(image.get()); auto texture = Texture::from(image.get());
texture->setNearestFilter(); texture->setNearestFilter();
return texture; return texture;
+7 -2
View File
@@ -109,7 +109,12 @@ void menus::create_new_world_panel(Engine* engine) {
auto seedInput = std::make_shared<TextBox>(seedstr, glm::vec4(6.0f)); auto seedInput = std::make_shared<TextBox>(seedstr, glm::vec4(6.0f));
panel->add(seedInput); 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(generatorTypeButton);
panel->add(menus::create_button(L"Create World", glm::vec4(10), glm::vec4(1, 20, 1, 1), 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->getContent(),
engine->getContentPacks() engine->getContentPacks()
); );
level->world->wfile->createDirectories(); level->getWorld()->wfile->createDirectories();
menus::generatorID = WorldGenerators::getDefaultGeneratorID(); menus::generatorID = WorldGenerators::getDefaultGeneratorID();
engine->setScreen(std::make_shared<LevelScreen>(engine, level)); engine->setScreen(std::make_shared<LevelScreen>(engine, level));
})); }));
+8 -3
View File
@@ -6,7 +6,7 @@
#include "ImageData.h" #include "ImageData.h"
Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions) Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions)
: texture(Texture::from(image)), : texture(nullptr),
image(image), image(image),
regions(regions) { regions(regions) {
} }
@@ -14,6 +14,10 @@ Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions
Atlas::~Atlas() { Atlas::~Atlas() {
} }
void Atlas::prepare() {
texture.reset(Texture::from(image.get()));
}
bool Atlas::has(const std::string& name) const { bool Atlas::has(const std::string& name) const {
return regions.find(name) != regions.end(); return regions.find(name) != regions.end();
} }
@@ -80,8 +84,9 @@ Atlas* AtlasBuilder::build(uint extrusion, uint maxResolution) {
} }
float unitX = 1.0f / width; float unitX = 1.0f / width;
float unitY = 1.0f / height; float unitY = 1.0f / height;
regions[entry.name] = UVRegion(unitX * x, unitY * y, regions[entry.name] = UVRegion(
unitX * (x + w), unitY * (y + h)); unitX * x, unitY * y, unitX * (x + w), unitY * (y + h)
);
} }
return new Atlas(canvas.release(), regions); return new Atlas(canvas.release(), regions);
} }
+2 -1
View File
@@ -20,6 +20,8 @@ public:
Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions); Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions);
~Atlas(); ~Atlas();
void prepare();
bool has(const std::string& name) const; bool has(const std::string& name) const;
const UVRegion& get(const std::string& name) const; const UVRegion& get(const std::string& name) const;
@@ -27,7 +29,6 @@ public:
ImageData* getImage() const; ImageData* getImage() const;
}; };
struct atlasentry { struct atlasentry {
std::string name; std::string name;
std::shared_ptr<ImageData> image; std::shared_ptr<ImageData> image;
+69 -74
View File
@@ -17,7 +17,7 @@ namespace fs = std::filesystem;
GLSLExtension* Shader::preprocessor = new GLSLExtension(); GLSLExtension* Shader::preprocessor = new GLSLExtension();
Shader::Shader(unsigned int id) : id(id){ Shader::Shader(uint id) : id(id){
} }
Shader::~Shader(){ Shader::~Shader(){
@@ -28,106 +28,101 @@ void Shader::use(){
glUseProgram(id); glUseProgram(id);
} }
void Shader::uniformMatrix(std::string name, glm::mat4 matrix){ uint Shader::getUniformLocation(const std::string& name) {
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); auto found = uniformLocations.find(name);
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(matrix)); 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){ void Shader::uniformMatrix(const std::string& name, glm::mat4 matrix){
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix));
glUniform1i(transformLoc, x);
} }
void Shader::uniform1f(std::string name, float x){ void Shader::uniform1i(const std::string& name, int x){
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniform1i(getUniformLocation(name), x);
glUniform1f(transformLoc, x);
} }
void Shader::uniform2f(std::string name, float x, float y){ void Shader::uniform1f(const std::string& name, float x){
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniform1f(getUniformLocation(name), x);
glUniform2f(transformLoc, x, y);
} }
void Shader::uniform2f(std::string name, glm::vec2 xy){ void Shader::uniform2f(const std::string& name, float x, float y){
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniform2f(getUniformLocation(name), x, y);
glUniform2f(transformLoc, xy.x, xy.y);
} }
void Shader::uniform2i(std::string name, glm::ivec2 xy){ void Shader::uniform2f(const std::string& name, glm::vec2 xy){
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniform2f(getUniformLocation(name), xy.x, xy.y);
glUniform2i(transformLoc, xy.x, xy.y);
} }
void Shader::uniform3f(std::string name, float x, float y, float z){ void Shader::uniform2i(const std::string& name, glm::ivec2 xy){
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniform2i(getUniformLocation(name), xy.x, xy.y);
glUniform3f(transformLoc, x,y,z);
} }
void Shader::uniform3f(std::string name, glm::vec3 xyz){ void Shader::uniform3f(const std::string& name, float x, float y, float z){
GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniform3f(getUniformLocation(name), x,y,z);
glUniform3f(transformLoc, xyz.x, xyz.y, xyz.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<GLuint, decltype(shader_deleter)>;
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( Shader* Shader::create(
std::string vertexFile, const std::string& vertexFile,
std::string fragmentFile, const std::string& fragmentFile,
std::string vertexCode, const std::string& vertexCode,
std::string fragmentCode const std::string& fragmentCode
) { ) {
vertexCode = preprocessor->process(fs::path(vertexFile), vertexCode); const GLchar* vCode = vertexCode.c_str();
fragmentCode = preprocessor->process(fs::path(fragmentFile), fragmentCode); const GLchar* fCode = fragmentCode.c_str();
const GLchar* vShaderCode = vertexCode.c_str(); glshader vertex = compile_shader(GL_VERTEX_SHADER, vCode, vertexFile);
const GLchar* fShaderCode = fragmentCode.c_str(); glshader fragment = compile_shader(GL_FRAGMENT_SHADER, fCode, fragmentFile);
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;
}
// Shader Program // Shader Program
GLint success;
GLuint id = glCreateProgram(); GLuint id = glCreateProgram();
glAttachShader(id, vertex); glAttachShader(id, *vertex);
glAttachShader(id, fragment); glAttachShader(id, *fragment);
glLinkProgram(id); glLinkProgram(id);
glGetProgramiv(id, GL_LINK_STATUS, &success); glGetProgramiv(id, GL_LINK_STATUS, &success);
if (!success){ if (!success){
glGetProgramInfoLog(id, 512, nullptr, infoLog); GLchar infoLog[GL_LOG_LEN];
std::cerr << "SHADER::PROGRAM: linking failed" << std::endl; glGetProgramInfoLog(id, GL_LOG_LEN, nullptr, infoLog);
std::cerr << infoLog << std::endl; throw std::runtime_error(
"shader program linking failed:\n"+std::string(infoLog)
glDeleteShader(vertex); );
glDeleteShader(fragment);
return nullptr;
} }
glDeleteShader(vertex);
glDeleteShader(fragment);
return new Shader(id); return new Shader(id);
} }
+26 -15
View File
@@ -1,35 +1,46 @@
#ifndef GRAPHICS_CORE_SHADER_H_ #ifndef GRAPHICS_CORE_SHADER_H_
#define GRAPHICS_CORE_SHADER_H_ #define GRAPHICS_CORE_SHADER_H_
#include <string>
#include <glm/glm.hpp>
#include "../../typedefs.h" #include "../../typedefs.h"
#include <string>
#include <unordered_map>
#include <glm/glm.hpp>
class GLSLExtension; class GLSLExtension;
class Shader { class Shader {
uint id; uint id;
std::unordered_map<std::string, uint> uniformLocations;
uint getUniformLocation(const std::string& name);
public: public:
static GLSLExtension* preprocessor; static GLSLExtension* preprocessor;
Shader(unsigned int id); Shader(uint id);
~Shader(); ~Shader();
void use(); void use();
void uniformMatrix(std::string name, glm::mat4 matrix); void uniformMatrix(const std::string&, glm::mat4 matrix);
void uniform1i(std::string name, int x); void uniform1i(const std::string& name, int x);
void uniform1f(std::string name, float x); void uniform1f(const std::string& name, float x);
void uniform2f(std::string name, float x, float y); void uniform2f(const std::string& name, float x, float y);
void uniform2f(std::string name, glm::vec2 xy); void uniform2f(const std::string& name, glm::vec2 xy);
void uniform2i(std::string name, glm::ivec2 xy); void uniform2i(const std::string& name, glm::ivec2 xy);
void uniform3f(std::string name, float x, float y, float z); void uniform3f(const std::string& name, float x, float y, float z);
void uniform3f(std::string name, glm::vec3 xyz); 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( static Shader* create(
std::string vertexFile, const std::string& vertexFile,
std::string fragmentFile, const std::string& fragmentFile,
std::string vertexSource, const std::string& vertexSource,
std::string fragmentSource const std::string& fragmentSource
); );
}; };
+3 -1
View File
@@ -142,5 +142,7 @@ std::unique_ptr<Atlas> BlocksPreview::build(
fbo.unbind(); fbo.unbind();
Window::viewport(0, 0, Window::width, Window::height); Window::viewport(0, 0, Window::width, Window::height);
return std::unique_ptr<Atlas>(builder.build(2)); auto newAtlas = std::unique_ptr<Atlas>(builder.build(2));
newAtlas->prepare();
return newAtlas;
} }