assets-related refactor
This commit is contained in:
parent
216e38e411
commit
befc9cf09c
@ -5,6 +5,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@ -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<void(Assets*)>;
|
||||
}
|
||||
|
||||
class Assets {
|
||||
std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
|
||||
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#ifndef ASSETS_ASSETS_LOADER_H
|
||||
#define ASSETS_ASSETS_LOADER_H
|
||||
|
||||
#include "Assets.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
@ -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<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 {
|
||||
AssetType tag;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "assetload_funcs.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <filesystem>
|
||||
#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<AssetCfg>
|
||||
) {
|
||||
std::unique_ptr<Texture> texture(
|
||||
png::load_texture(paths->find(filename+".png").u8string())
|
||||
std::shared_ptr<ImageData> 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<ImageData> 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<std::string> 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<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++) {
|
||||
std::string name = filename + "_" + std::to_string(i) + ".png";
|
||||
name = paths->find(name).string();
|
||||
std::unique_ptr<Texture> 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<ImageData> 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<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,
|
||||
Assets* assets,
|
||||
const ResPaths* paths,
|
||||
@ -149,18 +147,19 @@ bool assetload::layout(
|
||||
const std::string name,
|
||||
std::shared_ptr<AssetCfg> config
|
||||
) {
|
||||
try {
|
||||
auto cfg = dynamic_cast<LayoutCfg*>(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<LayoutCfg*>(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<audio::Sound> baseSound = nullptr;
|
||||
std::unique_ptr<audio::Sound> 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<Atlas> srcAtlas (builder.build(2));
|
||||
srcAtlas->prepare();
|
||||
|
||||
Texture* srcTex = srcAtlas->getTexture();
|
||||
Texture* dstTex = dstAtlas->getTexture();
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#ifndef ASSETS_ASSET_LOADERS_H_
|
||||
#define ASSETS_ASSET_LOADERS_H_
|
||||
|
||||
#include "Assets.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
@ -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<AssetCfg> settings
|
||||
);
|
||||
bool shader(
|
||||
postfunc shader(
|
||||
AssetsLoader&,
|
||||
Assets*,
|
||||
const ResPaths* paths,
|
||||
@ -28,7 +30,7 @@ namespace assetload {
|
||||
const std::string name,
|
||||
std::shared_ptr<AssetCfg> settings
|
||||
);
|
||||
bool atlas(
|
||||
postfunc atlas(
|
||||
AssetsLoader&,
|
||||
Assets*,
|
||||
const ResPaths* paths,
|
||||
@ -36,7 +38,7 @@ namespace assetload {
|
||||
const std::string name,
|
||||
std::shared_ptr<AssetCfg> settings
|
||||
);
|
||||
bool font(
|
||||
postfunc font(
|
||||
AssetsLoader&,
|
||||
Assets*,
|
||||
const ResPaths* paths,
|
||||
@ -44,7 +46,7 @@ namespace assetload {
|
||||
const std::string name,
|
||||
std::shared_ptr<AssetCfg> settings
|
||||
);
|
||||
bool layout(
|
||||
postfunc layout(
|
||||
AssetsLoader&,
|
||||
Assets*,
|
||||
const ResPaths* paths,
|
||||
@ -53,7 +55,7 @@ namespace assetload {
|
||||
std::shared_ptr<AssetCfg> settings
|
||||
);
|
||||
|
||||
bool sound(
|
||||
postfunc sound(
|
||||
AssetsLoader&,
|
||||
Assets*,
|
||||
const ResPaths* paths,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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<ImageData> image (_png_load(filename.c_str()));
|
||||
if (image == nullptr){
|
||||
std::cerr << "Could not load texture " << filename << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<ImageData> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,12 @@ void menus::create_new_world_panel(Engine* engine) {
|
||||
auto seedInput = std::make_shared<TextBox>(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<LevelScreen>(engine, level));
|
||||
}));
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#include "ImageData.h"
|
||||
|
||||
Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> regions)
|
||||
: texture(Texture::from(image)),
|
||||
: texture(nullptr),
|
||||
image(image),
|
||||
regions(regions) {
|
||||
}
|
||||
@ -14,6 +14,10 @@ Atlas::Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> 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);
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@ public:
|
||||
Atlas(ImageData* image, std::unordered_map<std::string, UVRegion> 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<ImageData> image;
|
||||
|
||||
@ -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<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(
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1,35 +1,46 @@
|
||||
#ifndef GRAPHICS_CORE_SHADER_H_
|
||||
#define GRAPHICS_CORE_SHADER_H_
|
||||
|
||||
#include <string>
|
||||
#include <glm/glm.hpp>
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class GLSLExtension;
|
||||
|
||||
class Shader {
|
||||
uint id;
|
||||
std::unordered_map<std::string, uint> 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
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -142,5 +142,7 @@ std::unique_ptr<Atlas> BlocksPreview::build(
|
||||
fbo.unbind();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user