diff options
| author | 2020-10-15 13:25:56 -0400 | |
|---|---|---|
| committer | 2020-10-15 13:25:56 -0400 | |
| commit | 72b4bd5c9d99d874a5900576f9a55d6f97f4f616 (patch) | |
| tree | 0a73dc1e8143803b8a6423f4cee09f8d1b98be78 /src | |
| parent | 73f118641b2c05148eab673b2fbcf9b4e155411d (diff) | |
| download | mauri-72b4bd5c9d99d874a5900576f9a55d6f97f4f616.tar.gz mauri-72b4bd5c9d99d874a5900576f9a55d6f97f4f616.tar.bz2 mauri-72b4bd5c9d99d874a5900576f9a55d6f97f4f616.zip | |
better texture handling, visualizer cleanup, proper handling of object framebuffers
Diffstat (limited to 'src')
| -rw-r--r-- | src/assets.cc | 105 | ||||
| -rw-r--r-- | src/assets.h | 8 | ||||
| -rw-r--r-- | src/engine.cc | 49 | ||||
| -rw-r--r-- | src/engine.h | 10 | ||||
| -rw-r--r-- | src/mauri.cc | 43 | ||||
| -rw-r--r-- | src/objects/effect.cc | 10 | ||||
| -rw-r--r-- | src/objects/effect.h | 10 | ||||
| -rw-r--r-- | src/objects/material.cc | 7 | ||||
| -rw-r--r-- | src/objects/material.h | 5 | ||||
| -rw-r--r-- | src/objects/model.cc | 4 | ||||
| -rw-r--r-- | src/objects/model.h | 2 | ||||
| -rw-r--r-- | src/objects/object.cc | 59 | ||||
| -rw-r--r-- | src/objects/object.h | 6 | ||||
| -rw-r--r-- | src/objects/pass.cc | 159 | ||||
| -rw-r--r-- | src/objects/pass.h | 7 | ||||
| -rw-r--r-- | src/objects/scene.cc | 5 | ||||
| -rw-r--r-- | src/shader.cc | 25 | ||||
| -rw-r--r-- | src/util.h | 2 | ||||
| -rw-r--r-- | src/visualizer.cc | 59 | ||||
| -rw-r--r-- | src/visualizer.h | 19 |
20 files changed, 319 insertions, 275 deletions
diff --git a/src/assets.cc b/src/assets.cc index cbc2e9e..789ba2e 100644 --- a/src/assets.cc +++ b/src/assets.cc @@ -1,6 +1,7 @@ #include "assets.h" #include "log.h" #include "util.h" +#include "texture.h" #include <array> #include <fstream> @@ -8,13 +9,25 @@ using namespace Mauri; +namespace Mauri +{ + +static AssetManager manager; + +AssetManager *asset_manager() +{ + return &manager; +} + +} // namespace Mauri + Asset::Asset() { type = ASSET_VOID; size = 0; pos = 0; data = nullptr; - hash = 0; + lasset = nullptr; } static Asset asset_void = Asset(); @@ -25,7 +38,7 @@ Asset::Asset(const std::string &path, byte *begin, byte *end) size = end - begin; pos = 0; data = begin; - hash = std::hash<std::string>{}(path); + lasset = nullptr; } Asset::Asset(const std::string &path) @@ -54,8 +67,6 @@ Asset::Asset(const std::string &path) pos = 0; type = ASSET_FILE; - - hash = std::hash<std::string>{}(path); } Asset::~Asset() @@ -64,6 +75,18 @@ Asset::~Asset() { delete[] data; } + + if (lasset != nullptr) + { + switch (ltype) + { + case TEXTURE: + delete (Texture *)lasset; + break; + default: + break; + } + } } bool AssetManager::load_package(const std::string &path) @@ -100,12 +123,17 @@ bool AssetManager::load_package(const std::string &path) for (auto file : pkg_files) { - files.push_back( - new Asset(std::string(file.path), - pkg->ptr() + file.offset, - pkg->ptr() + file.offset + file.length - ) + auto path = std::string(file.path); + + auto asset = new Asset(path, + pkg->ptr() + file.offset, + pkg->ptr() + file.offset + file.length ); + + asset->hash = std::hash<std::string>{}(path); + + files.push_back(asset); + log_debug("loaded file (%s)", std::string(file.path).c_str()); } @@ -118,18 +146,18 @@ Asset *AssetManager::get_file(const std::string &part, FileTypeHint hint) switch (hint) { - case FileTypeHint::TEXTURE: + case TEXTURE: path.insert(0, "materials/"); path.append(".tex"); break; - case FileTypeHint::SHADER: + case SHADER: path.insert(0, "shaders/"); break; - case FileTypeHint::FRAGMENT_SHADER: + case FRAGMENT_SHADER: path.insert(0, "shaders/"); path.append(".frag"); break; - case FileTypeHint::VERTEX_SHADER: + case VERTEX_SHADER: path.insert(0, "shaders/"); path.append(".vert"); break; @@ -138,29 +166,50 @@ Asset *AssetManager::get_file(const std::string &part, FileTypeHint hint) break; } + Asset *asset = nullptr; + u64 hash = std::hash<std::string>{}(path); for (auto &file : files) { if (file->hash == hash) { - return file; + asset = file; + break; } } - path.insert(0, "assets/"); + if (asset == nullptr) + { + path.insert(0, "assets/"); - Asset *asset = new Asset(path); + asset = new Asset(path); + asset->hash = hash; - if (asset->type == ASSET_VOID) - { - delete asset; - return &asset_void; + if (asset->type == ASSET_VOID) + { + delete asset; + return &asset_void; + } + + files.push_back(asset); } - files.push_back(std::move(asset)); + asset->ltype = hint; - return files.back(); + if (asset->lasset == nullptr) + { + switch (hint) + { + case TEXTURE: + asset->lasset = new Texture(asset); + break; + default: + break; + } + } + + return asset; } AssetManager::~AssetManager() @@ -171,15 +220,3 @@ AssetManager::~AssetManager() } delete pkg; } - -namespace Mauri -{ - -static AssetManager manager; - -AssetManager *asset_manager() -{ - return &manager; -} - -} // namespace Mauri diff --git a/src/assets.h b/src/assets.h index 14a76de..2f7677f 100644 --- a/src/assets.h +++ b/src/assets.h @@ -40,6 +40,10 @@ class Asset // free'd along with this asset. AssetType type; + // Info about loaded asset + FileTypeHint ltype; + void *lasset; + u32 size; u64 hash; @@ -99,14 +103,14 @@ class AssetManager AssetManager() {}; ~AssetManager(); + std::vector<Asset *> files; + bool load_package(const std::string &path); Asset *get_file(const std::string &part, FileTypeHint hint); private: Asset *pkg; - - std::vector<Asset *> files; }; extern AssetManager *asset_manager(); diff --git a/src/engine.cc b/src/engine.cc index ed4301a..b744f8d 100644 --- a/src/engine.cc +++ b/src/engine.cc @@ -1,4 +1,5 @@ #include "engine.h" +#include "assets.h" #include "context.h" #include "json.h" #include "shader.h" @@ -8,6 +9,7 @@ #include "objects/object.h" #include "objects/scene.h" +#include "visualizer.h" #include <glm/ext.hpp> #include <glm/ext/matrix_transform.hpp> @@ -48,8 +50,8 @@ void View::center(f32 w1, f32 h1) camera_pos[1] = (scaled_height - h1) / -2.f; } -Engine::Engine(Scene *scene, Context *context, Parser *parser) - : scene(scene), parser(parser), context(context) +Engine::Engine(Scene *scene, Context *context, Parser *parser, bool audio) + : scene(scene), parser(parser), context(context), audio_enabled(audio) { view.width = scene->width; view.height = scene->height; @@ -74,34 +76,39 @@ Engine::Engine(Scene *scene, Context *context, Parser *parser) default_model_flipped = glm::scale(default_model, (vec3){1.f, -1.f, 1.f}); scene->load(this); -} -Texture *Engine::get_texture(Asset *asset) -{ - for (auto &texture : texture_cache) + if (audio_enabled) { - if (texture->hash == asset->hash) - return texture; + visualizer = new Visualizer(); } - - texture_cache.emplace_back(new Texture(asset)); - - return texture_cache.back(); } Framebuffer *Engine::get_framebuffer(const std::string &name) { - return framebuffers[name]; + for (auto &buffer : framebuffers) + { + if (buffer->name == name) + { + return buffer; + } + } + + return nullptr; } Texture *Engine::get_framebuffer_texture(const std::string &name) { - return framebuffers[name]->texture; + auto buffer = get_framebuffer(name); + + if (buffer != nullptr) + return buffer->texture; + + return nullptr; } void Engine::create_framebuffer(std::string name, f32 width, f32 height, f32 scale) { - framebuffers[name] = new Framebuffer(name, width, height, scale); + framebuffers.emplace_back(new Framebuffer(name, width, height, scale)); } void Engine::update() @@ -133,8 +140,7 @@ void Engine::draw() { for (auto& buffer : framebuffers) { - if (buffer.second != nullptr) - buffer.second->buffer->clear((vec4){0.f, 0.f, 0.f, 0.f}); + buffer->buffer->clear((vec4){0.f, 0.f, 0.f, 0.f}); } if (scene->clear_enabled) @@ -185,14 +191,11 @@ Engine::~Engine() { for (auto &buffer : framebuffers) { - delete buffer.second; - } - - for (auto &texture : texture_cache) - { - delete texture; + delete buffer; } delete default_object; delete minimal_shader; + + delete visualizer; } diff --git a/src/engine.h b/src/engine.h index cb14cb8..8dc5093 100644 --- a/src/engine.h +++ b/src/engine.h @@ -43,14 +43,16 @@ struct View class Engine { public: - Engine(Scene *scene, Context *context, Parser *parser); + Engine(Scene *scene, Context *context, Parser *parser, bool visualizer); ~Engine(); Scene *scene; Parser *parser; Context *context; + Visualizer *visualizer; + bool audio_enabled; View view; @@ -63,13 +65,9 @@ class Engine Shader *minimal_shader; - std::vector<Texture *> texture_cache; - - Texture *get_texture(Asset *asset); - Framebuffer *combine_buffer; - std::unordered_map<std::string, Framebuffer *> framebuffers; + std::vector<Framebuffer *> framebuffers; void create_framebuffer(std::string name, f32 width, f32 height, f32 scale); diff --git a/src/mauri.cc b/src/mauri.cc index f66e9b3..f1493e4 100644 --- a/src/mauri.cc +++ b/src/mauri.cc @@ -18,14 +18,13 @@ using namespace Mauri; static std::string scene_path = "scene.json"; + s32 main(s32 argc, char *argv[]) { srand(time(NULL)); gst_init(&argc, &argv); - Visualizer *v = new Visualizer(); - //Context *context = new ContextX11(2560, 1440, "mauri", true); //Context *context = new ContextGLFW(720, 1280, "mauri", false); Context *context = new ContextGLFW(1280, 720, "mauri", false); @@ -46,45 +45,7 @@ s32 main(s32 argc, char *argv[]) //context->resize_window(scene->width, scene->height); - Engine engine(scene, context, &parser); - engine.visualizer = v; - - /* - for (auto &user : parser.values) - { - std::cout << user.first << ":\n"; - for (auto &value : user.second) - { - std::cout << "\t" << value.name << ": "; - switch (value.type) - { - case INT: - std::cout << *((u32 *)value.v); - break; - case FLOAT: - std::cout << *((f32 *)value.v); - break; - case VEC2: - std::cout << (*((vec2 *)value.v))[0]; - break; - case VEC3: - std::cout << (*((vec3 *)value.v))[0]; - break; - case VEC4: - std::cout << (*((vec4 *)value.v))[0] << (*((vec4 *)value.v))[1]; - break; - case BOOL: - std::cout << *((bool *)value.v); - break; - case STRING: - std::cout << *((std::string *)value.v); - break; - } - - std::cout << "\n"; - } - } - */ + Engine engine(scene, context, &parser, true); engine.run(); diff --git a/src/objects/effect.cc b/src/objects/effect.cc index 33b72aa..1ab5a96 100644 --- a/src/objects/effect.cc +++ b/src/objects/effect.cc @@ -83,15 +83,15 @@ void Effect::draw(Engine *engine) if (!visible) return; -#ifdef _DEBUG_ - //std::cout << name << ":\n"; +#if FRAME_STEP + std::cout << name << ":\n"; #endif for (auto &pass : passes) { -#ifdef _DEBUG_ - //if (pass->shader != nullptr) - // std::cout << "\t" << pass->shader->name << "\n"; +#if FRAME_STEP + if (pass->shader != nullptr) + std::cout << "\t" << pass->shader->name << "\n"; #endif pass->draw(engine); } diff --git a/src/objects/effect.h b/src/objects/effect.h index 40110a8..840830b 100644 --- a/src/objects/effect.h +++ b/src/objects/effect.h @@ -5,6 +5,7 @@ #include "engine.h" #include "texture.h" +#include "util.h" namespace Mauri { @@ -27,19 +28,20 @@ class Effect u32 id; std::string name; + bool visible; + std::string buffer_id; + std::vector<RenderPass *> passes; + + void load(Engine *engine, Object *object, bool last); void draw(Engine *engine); private: - bool visible; - std::vector<Pass *> passes0; std::vector<Pass *> passes1; - std::vector<RenderPass *> passes; - std::vector<EffectBuffer> fbos; }; diff --git a/src/objects/material.cc b/src/objects/material.cc index 465fab1..b91a26a 100644 --- a/src/objects/material.cc +++ b/src/objects/material.cc @@ -29,7 +29,7 @@ Material::Material(Parser &p, const std::string &path) } } -void Material::load(Engine *engine, Object *object, MaterialType type, Pass *pass, bool no_effects) +void Material::load(Engine *engine, Object *object, MaterialType type, Pass *pass) { for (auto &pass0 : passes0) { @@ -44,7 +44,10 @@ void Material::load(Engine *engine, Object *object, MaterialType type, Pass *pas _pass.object = object; _pass.effect = nullptr; - _pass.combine = no_effects && !object->passthrough && !object->fullscreen; + if (object->effects.size() == 0 && !object->passthrough) + _pass.combine = true; + else + _pass.combine = false; pass0->load(engine, MATERIAL_ONLY_PASS, &_pass); diff --git a/src/objects/material.h b/src/objects/material.h index 0e46f7f..11a2c46 100644 --- a/src/objects/material.h +++ b/src/objects/material.h @@ -23,10 +23,9 @@ class Material Material(Parser &p, const std::string &path); ~Material(); - void load(Engine *engine, Object *object, MaterialType type, Pass *pass, bool no_effects); - - private: std::vector<Pass *> passes0; + + void load(Engine *engine, Object *object, MaterialType type, Pass *pass); }; } // namespace Mauri diff --git a/src/objects/model.cc b/src/objects/model.cc index f450d34..1ec7424 100644 --- a/src/objects/model.cc +++ b/src/objects/model.cc @@ -34,9 +34,9 @@ Model::Model(Parser &p, const std::string &path) material = new Material(p, _material); } -void Model::load(Engine *engine, Object *object, bool no_effects) +void Model::load(Engine *engine, Object *object) { - material->load(engine, object, MATERIAL_MODEL, NULL, no_effects); + material->load(engine, object, MATERIAL_MODEL, NULL); } Model::~Model() diff --git a/src/objects/model.h b/src/objects/model.h index e4a55ea..243de1f 100644 --- a/src/objects/model.h +++ b/src/objects/model.h @@ -24,7 +24,7 @@ class Model f32 width; f32 height; - void load(Engine *engine, Object *object, bool no_effects); + void load(Engine *engine, Object *object); private: Material *material = nullptr; diff --git a/src/objects/object.cc b/src/objects/object.cc index 18bfdf0..1ed2053 100644 --- a/src/objects/object.cc +++ b/src/objects/object.cc @@ -130,17 +130,29 @@ void Object::load(Engine *engine) gl_object = new RenderObject(OBJECT, size[0], size[1]); gl_uv_object = new RenderObject(UV_SCALE, size[0], size[1]); - //blend_shader = new Shader(engine->parser, "passthroughblend"); - //blend_shader->combos.push_back((Combo) { "TRANSFORM", 1 }); - //blend_shader->combos.push_back((Combo) { "BLENDMODE", color_blend_mode }); - //blend_shader->compile(); - if (image != nullptr) - image->load(engine, this, effects.size() == 0); + { + image->load(engine, this); + } - for (s32 i = 0; i < effects.size(); i++) + if (effects.size() != 0) { - effects[i]->load(engine, this, i == (effects.size() - 1)); + // Get last effect that is visible + // to know when to make a combine pass. + Effect *last_effect = effects[0]; + + for (auto &effect : effects) + { + if (effect->visible) + { + last_effect = effect; + } + } + + for (auto &effect : effects) + { + effect->load(engine, this, effect == last_effect); + } } loaded = true; @@ -158,14 +170,14 @@ void Object::draw(Engine *engine) if (!visible) return; -#ifdef _DEBUG_ - //std::cout << name << " (model):\n"; +#if FRAME_STEP + std::cout << name << " (model):\n"; #endif for (auto &pass : passes) { -#ifdef _DEBUG_ - //std::cout << "\t" << pass->shader->name << "\n";; +#if FRAME_STEP + std::cout << "\t" << pass->shader->name << "\n";; #endif pass->draw(engine); } @@ -174,29 +186,6 @@ void Object::draw(Engine *engine) { effect->draw(engine); } - - //if (!visible) - // return; - - //engine->combine_buffer_a->buffer->bind(); - - //blend_shader->bind(engine, &model); - //gl_object->bind(); - - //engine->get_framebuffer_texture(get_texture_buffer())->bind(0); - - //engine->combine_buffer_b->texture->bind(1); - - //Render::blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //Render::color_mask(1.f, 1.f, 1.f, 1.f); - - //engine->view.default_viewport(engine->scene->width, engine->scene->height); - - //gl_object->draw(); - - //engine->combine_buffer_a->buffer->blit(engine->combine_buffer_b->buffer->id, - // engine->combine_buffer_a->buffer->width, - // engine->combine_buffer_a->buffer->height); } std::string Object::get_target_buffer() const diff --git a/src/objects/object.h b/src/objects/object.h index 2ce7347..24796e5 100644 --- a/src/objects/object.h +++ b/src/objects/object.h @@ -56,15 +56,13 @@ class Object std::string get_target_buffer() const; std::string get_texture_buffer() const; - Framebuffer *previous_buffer; - Texture *previous_texture; - void swap_buffer() { buffer_switch = !buffer_switch; } std::vector<RenderPass *> passes; + std::vector<Effect *> effects; void load(Engine *engine); @@ -74,8 +72,6 @@ class Object private: Model *image = nullptr; - Shader *blend_shader; - vec3 angles; vec3 color; diff --git a/src/objects/pass.cc b/src/objects/pass.cc index 38e68e3..689dda4 100644 --- a/src/objects/pass.cc +++ b/src/objects/pass.cc @@ -2,6 +2,7 @@ #include <fmt/core.h> #include <glm/fwd.hpp> #include <glm/gtc/type_ptr.hpp> +#include <jsoncpp/json/value.h> #include <stdint.h> #include <thread> #include <type_traits> @@ -72,8 +73,6 @@ Pass::Pass(Parser &p, json &root, PassStage stage) break; } case MATERIAL_ONLY_PASS: - target = "previous"; - [[fallthrough]]; case MATERIAL_PASS: shader = root["shader"]; break; @@ -123,12 +122,7 @@ void Pass::load(Engine *engine, PassStage stage, Pass *pass) pass->source = source + pass->effect->buffer_id; pass->target = target; - if (pass->target == "previous") - { - pass->target = pass->object->get_target_buffer(); - pass->textures[0] = pass->object->get_texture_buffer(); - } - else + if (!pass->target.empty()) pass->target.append(pass->effect->buffer_id); for (int i = 0; i < MAX_TEXTURES; i++) @@ -137,22 +131,18 @@ void Pass::load(Engine *engine, PassStage stage, Pass *pass) continue; if (binds[i] == "previous") - pass->textures[i] = pass->object->get_texture_buffer(); + pass->textures[i] = ""; else pass->textures[i] = binds[i] + pass->effect->buffer_id; } - if (target == "previous") - pass->object->swap_buffer(); - if (material != nullptr) - material->load(engine, pass->object, MATERIAL_EFFECT, pass, false); + { + material->load(engine, pass->object, MATERIAL_EFFECT, pass); + } break; case MATERIAL_ONLY_PASS: - pass->target = pass->object->get_target_buffer(); - pass->object->swap_buffer(); - [[fallthrough]]; case MATERIAL_PASS: pass->shader = shader; break; @@ -164,6 +154,7 @@ Pass::~Pass() if (material != nullptr) delete material; + // TODO: refcounted? //for (auto &uniform : uniforms) //{ // delete uniform; @@ -173,11 +164,17 @@ Pass::~Pass() RenderPass::RenderPass(Engine *engine, Pass *pass) { command = pass->command; - combine = pass->combine; + // This object contains information needed for + // getting previous framebuffer textures and targets. + object = pass->object; + if (command == COPY) { + // Target and source is the only needed information + // for a COPY pass. + target = engine->get_framebuffer(pass->target); source = engine->get_framebuffer(pass->source); @@ -190,18 +187,25 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) for (int i = 0; i < MAX_TEXTURES; i++) { + // If there is no texture at "i" use default shader from the texture. if (pass->textures[i].empty() && !shader->textures[i].empty()) pass->textures[i] = shader->textures[i]; if (pass->textures[i].empty()) continue; - auto asset = asset_manager()->get_file(pass->textures[i], TEXTURE); + // Check if texture is referencing a framebuffer. + textures[i] = engine->get_framebuffer_texture(pass->textures[i]); - if (asset->type != ASSET_VOID) - textures[i] = engine->get_texture(asset); - else - textures[i] = engine->get_framebuffer_texture(pass->textures[i]); + if (textures[i] == nullptr) + { + // The texture wasn't a framebuffer so try to load it from an asset. + auto asset = asset_manager()->get_file(pass->textures[i], TEXTURE); + if (asset->type != ASSET_VOID) + { + textures[i] = (Texture *)asset->lasset; + } + } } for (auto &shader_uniform : shader->uniforms) @@ -213,6 +217,9 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) continue; if (shader_uniform->name == uniform_override->name) { + // Take value as reference because "uniform_override->value" points + // to the value stored in the parser. This allows changing that value + // to have instant effect. shader_uniform->value = &uniform_override->value; default_value = false; break; @@ -232,6 +239,14 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) auto index = uniform->uname[9] - '0'; if (textures[index] != nullptr) uniform->value = &textures[index]->texture_res; + else + { + // If there is no texture at this index we assume this texture will + // be the previous framebuffer. + auto texture = engine->get_framebuffer_texture(object->get_texture_buffer()); + if (texture != nullptr) + uniform->value = &texture->texture_res; + } } } @@ -251,72 +266,74 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) shader->combos.push_back(pass_combo); } - /* - for (auto &combo : shader->combos) + // If visualizer is not enabled disable audio logic + // on the shader. + if (!engine->audio_enabled) { - if (combo.name == "AUDIOPROCESSING") - combo.value = 0; + for (auto &combo : shader->combos) + { + if (combo.name == "AUDIOPROCESSING") + combo.value = 0; + } } - */ + // Compile shader only after all necessary combos are set. shader->compile(); if (pass->effect == nullptr) { + // The fullscreen shader doesn't use ModelViewProjectionMatrix, if (pass->object->fullscreen) + { model = &engine->default_model; - else if (pass->object->passthrough || combine) - model = &pass->object->model; - else - model = &pass->object->ortho; - - if (pass->object->fullscreen) robject = engine->default_object; + } + + // The passthrough shader uses ModelViewProjectionMatrix + // but, the texture is not scaled to a power of two. else if (pass->object->passthrough) - robject = pass->object->gl_object; - else - robject = pass->object->gl_uv_object; - } - else - { - if (combine && !pass->object->fullscreen) { + model = &pass->object->model; robject = pass->object->gl_object; + } + + // If there is no effect and combine is set, + // we are forced to use a model which will + // correctly position the object. + else if (combine) + { model = &pass->object->model; + robject = pass->object->gl_uv_object; } + + // The object with UV's that scale the texture + // also has the objects size on the verteices, + // so we need to use ortho for the model. else { - robject = engine->default_object; - model = &engine->default_model; + model = &pass->object->ortho; + robject = pass->object->gl_uv_object; } } - - /* - // TODO fix this - if (pass->effect == nullptr) + else { - if (pass->object->passthrough) + // When combine is set this is the final pass + // that needs to position the object on the screen. + // Except when fullscreen is set the object doesn't + // want to be positioned. + if (combine && !pass->object->fullscreen) { robject = pass->object->gl_object; model = &pass->object->model; } - else if (pass->object->fullscreen) + + // Default everything. + else { robject = engine->default_object; model = &engine->default_model; } - else - { - robject = pass->object->gl_uv_object; - model = &pass->object->ortho; - } - } - else - { - robject = engine->default_object; - model = &engine->default_model; } - */ } void RenderPass::draw(Engine *engine) @@ -327,8 +344,10 @@ void RenderPass::draw(Engine *engine) if (combine) _target = engine->combine_buffer; - else + else if (target != nullptr) _target = target; + else + _target = engine->get_framebuffer(object->get_target_buffer()); _target->buffer->bind(); @@ -339,6 +358,18 @@ void RenderPass::draw(Engine *engine) { if (textures[i] != nullptr) textures[i]->bind(i); + else + { + // Assume this index will be the previous framebuffer. + auto texture = engine->get_framebuffer_texture(object->get_texture_buffer()); + if (texture != nullptr) + texture->bind(i); + } + } + + if (target == nullptr) + { + object->swap_buffer(); } if (combine) @@ -356,9 +387,11 @@ void RenderPass::draw(Engine *engine) robject->draw(); - //_target->buffer->blit(0, engine->context->width, engine->context->height); - //engine->context->swap_buffers(); - //std::this_thread::sleep_for(std::chrono::seconds(2)); +#if FRAME_STEP + _target->buffer->blit(0, engine->context->width, engine->context->height); + engine->context->swap_buffers(); + std::this_thread::sleep_for(std::chrono::seconds(2)); +#endif break; } diff --git a/src/objects/pass.h b/src/objects/pass.h index 0211596..3e722b8 100644 --- a/src/objects/pass.h +++ b/src/objects/pass.h @@ -50,7 +50,7 @@ class Pass PassCommand command = DRAW; - std::string target = "previous"; + std::string target; std::string source; Object *object; @@ -78,6 +78,7 @@ class RenderPass RenderPass(Engine *engine, Pass *pass); ~RenderPass(); + Shader *shader = nullptr; void draw(Engine *engine); @@ -85,7 +86,7 @@ class RenderPass private: PassCommand command; - bool combine; + Object *object; Framebuffer *target; Framebuffer *source; @@ -93,6 +94,8 @@ class RenderPass mat4x4 *model; RenderObject *robject; + bool combine; + std::array<Texture *, MAX_TEXTURES> textures = {0}; }; diff --git a/src/objects/scene.cc b/src/objects/scene.cc index 8bb2d70..d3819dc 100644 --- a/src/objects/scene.cc +++ b/src/objects/scene.cc @@ -43,11 +43,6 @@ Scene::Scene(Parser &p, const std::string &path) { if (object["image"].is_null()) continue; - if (object["name"] == "Compose") - { - //std::cout << "Skiped\n"; - //continue; - } objects.emplace_back(new Object(p, object)); } } diff --git a/src/shader.cc b/src/shader.cc index 80b928f..a524a2c 100644 --- a/src/shader.cc +++ b/src/shader.cc @@ -180,12 +180,18 @@ Shader::Shader(Parser *p, const std::string &name) if (vs_asset->type != ASSET_VOID) build_shader_source(p, vs_asset->as_string(), vs_source, true); else + { log_error("failed to load shader file (%s)", name.c_str()); + return; + } if (fs_asset->type != ASSET_VOID) build_shader_source(p, fs_asset->as_string(), fs_source, true); else + { log_error("failed to load shader file (%s)", name.c_str()); + return; + } } void Shader::bind(Engine *engine, mat4x4 *model) @@ -220,18 +226,21 @@ void Shader::bind(Engine *engine, mat4x4 *model) rshader->set_uniform("g_ModelViewProjectionMatrix", TYPE_MAT4, glm::value_ptr(_model)); rshader->set_uniform("g_ModelViewProjectionMatrixInverse", TYPE_MAT4, glm::value_ptr(_inverse)); - g_mutex_lock(&engine->visualizer->mutex); + if (engine->audio_enabled) + { + g_mutex_lock(&engine->visualizer->mutex); - glUniform1fv(rshader->uniform_loc("g_AudioSpectrum64Left"), 64, &engine->visualizer->bars_64_left[0]); - glUniform1fv(rshader->uniform_loc("g_AudioSpectrum64Right"), 64, &engine->visualizer->bars_64_right[0]); + glUniform1fv(rshader->uniform_loc("g_AudioSpectrum64Left"), 64, &engine->visualizer->bars_64_left[0]); + glUniform1fv(rshader->uniform_loc("g_AudioSpectrum64Right"), 64, &engine->visualizer->bars_64_right[0]); - glUniform1fv(rshader->uniform_loc("g_AudioSpectrum32Left"), 32, &engine->visualizer->bars_32_left[0]); - glUniform1fv(rshader->uniform_loc("g_AudioSpectrum32Right"), 32, &engine->visualizer->bars_32_right[0]); + glUniform1fv(rshader->uniform_loc("g_AudioSpectrum32Left"), 32, &engine->visualizer->bars_32_left[0]); + glUniform1fv(rshader->uniform_loc("g_AudioSpectrum32Right"), 32, &engine->visualizer->bars_32_right[0]); - glUniform1fv(rshader->uniform_loc("g_AudioSpectrum16Left"), 16, &engine->visualizer->bars_16_left[0]); - glUniform1fv(rshader->uniform_loc("g_AudioSpectrum16Right"), 16, &engine->visualizer->bars_16_right[0]); + glUniform1fv(rshader->uniform_loc("g_AudioSpectrum16Left"), 16, &engine->visualizer->bars_16_left[0]); + glUniform1fv(rshader->uniform_loc("g_AudioSpectrum16Right"), 16, &engine->visualizer->bars_16_right[0]); - g_mutex_unlock(&engine->visualizer->mutex); + g_mutex_unlock(&engine->visualizer->mutex); + } } Shader::~Shader() @@ -6,6 +6,8 @@ using namespace nlohmann; +#define FRAME_STEP 0 + typedef uint32_t u32; typedef int32_t s32; diff --git a/src/visualizer.cc b/src/visualizer.cc index adfe851..349478b 100644 --- a/src/visualizer.cc +++ b/src/visualizer.cc @@ -1,3 +1,4 @@ +#include <X11/X.h> #include <cmath> #include <fftw3.h> #include <numeric> @@ -8,8 +9,10 @@ #include "fmt/format.h" #include "gst/gstcaps.h" #include "gst/gstelement.h" +#include "gst/gstmemory.h" #include "gst/gstsample.h" #include "gst/gststructure.h" +#include "gst/gstutils.h" #include "log.h" #include "objects/material.h" #include "visualizer.h" @@ -22,14 +25,14 @@ void Visualizer::calc_cutoff() { f64 freqconst = std::log10(low_freq_cap / (f64)high_freq_cap) / ((1.0 / (BAR_COUNT + 1.0)) - 1.0); - for (s32 i = 0; i < BAR_COUNT; ++i) + for (s32 i = 0; i <= BAR_COUNT; ++i) { freqconst_per_bin[i] = high_freq_cap * std::pow(10.0, (freqconst * -1) + (((i + 1.0) / (BAR_COUNT + 1.0)) * freqconst)); f64 freq = freqconst_per_bin[i] / (sample_rate / 2.0); - low_cutoff[i] = std::floor(freq * (sample_count / 4)); + low_cutoff[i] = std::floor(freq * (sample_count / 4.0)); if (i <= 0) continue; @@ -55,8 +58,7 @@ void Visualizer::monstercat_smoothing(bool right) { f32 *bars = (right) ? (f32 *)bars_64_right_falloff : (f32 *)bars_64_left_falloff; - std::vector<f32> smoothing_factors; - smoothing_factors.reserve(BAR_COUNT); + std::array<f32, BAR_COUNT> smoothing_factors; for (int i = 0; i < BAR_COUNT; ++i) { @@ -72,7 +74,9 @@ void Visualizer::monstercat_smoothing(bool right) const auto weighted_value = bars[i] / smoothing_factors[(int)(std::abs(i - j))]; if (bars[j] < weighted_value) + { bars[j] = weighted_value; + } } } } @@ -125,13 +129,13 @@ void Visualizer::update_bars(bool right) *bar = std::pow(*bar, 0.5); auto falloff_value = std::min( - bars_falloff[i] * 0.90, + bars_falloff[i] * 0.85, bars_falloff[i] - 1.0); bars_falloff[i] = std::max((f32)falloff_value, *bar); } - monstercat_smoothing(right); + //monstercat_smoothing(right); for (s32 i = 0; i < BAR_COUNT; i++) { @@ -171,9 +175,10 @@ void Visualizer::update_sample() GstBuffer *buffer = gst_sample_get_buffer(sample); - GstMemory *mem = gst_buffer_get_memory(buffer, 0); + GstMapInfo info; + gst_buffer_map(buffer, &info, GST_MAP_READ); - Sample *samples = (Sample *)(mem + mem->offset); + Sample *samples = (Sample *)(info.data); g_mutex_lock(&mutex); @@ -199,22 +204,12 @@ void Visualizer::update() g_mutex_unlock(&mutex); } -static void *update_thread(void *data) -{ - Visualizer *v = (Visualizer *)data; - - while (true) - { - v->update(); - g_usleep(20000); - } -} - static GstFlowReturn new_sample_callback(GstElement *appsink, gpointer *udata) { Visualizer *v = (Visualizer *)udata; v->update_sample(); + v->update(); return GST_FLOW_OK; } @@ -256,6 +251,7 @@ Visualizer::Visualizer() } g_object_set(appsink, "emit-signals", TRUE, NULL); + g_object_set(pulsesrc, "device", "0", NULL); gst_bin_add_many(GST_BIN(pipeline), pulsesrc, appsink, NULL); @@ -272,8 +268,8 @@ Visualizer::Visualizer() GstBuffer *buffer = gst_sample_get_buffer(sample); GstCaps *caps = gst_sample_get_caps(sample); - GstStructure *structure = gst_caps_get_structure(caps, 0); + gst_structure_get_int(structure, "rate", &sample_rate); gst_caps_unref(caps); @@ -286,8 +282,8 @@ Visualizer::Visualizer() out_left = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * sample_count); out_right = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * sample_count); - memset(bars_64_left_falloff, 0, sizeof(f32) * BAR_COUNT); - memset(bars_64_right_falloff, 0, sizeof(f32) * BAR_COUNT); + memset(out_left, 0, sizeof(fftw_complex) * sample_count); + memset(out_right, 0, sizeof(fftw_complex) * sample_count); calc_cutoff(); @@ -296,8 +292,23 @@ Visualizer::Visualizer() g_signal_connect(appsink, "new-sample", G_CALLBACK(new_sample_callback), this); - g_thread_new(NULL, update_thread, this); - g_thread_new(NULL, main_thread, this); + thread = g_thread_new(NULL, main_thread, this); } +Visualizer::~Visualizer() +{ + fftw_free(in_left); + fftw_free(in_right); + + fftw_free(out_left); + fftw_free(out_right); + + gst_bus_post(bus, gst_message_new_eos(GST_OBJECT(pipeline))); + + g_thread_join(thread); + gst_element_set_state(pipeline, GST_STATE_NULL); + gst_object_unref(pipeline); + + g_mutex_clear(&mutex); +} diff --git a/src/visualizer.h b/src/visualizer.h index 5155391..2094d8a 100644 --- a/src/visualizer.h +++ b/src/visualizer.h @@ -33,13 +33,14 @@ public: f32 bars_64_left[BAR_COUNT]; f32 bars_64_right[BAR_COUNT]; - f32 bars_64_left_falloff[BAR_COUNT]; - f32 bars_64_right_falloff[BAR_COUNT]; + f32 bars_64_left_falloff[BAR_COUNT] = {0}; + f32 bars_64_right_falloff[BAR_COUNT] = {0}; GstElement *pipeline; GstBus *bus; GMutex mutex; + GThread *thread; void update(); void update_sample(); @@ -47,8 +48,6 @@ public: private: GstElement *appsink; - Sample *data; - f64 *in_left; f64 *in_right; @@ -58,20 +57,20 @@ private: fftw_plan p_left; fftw_plan p_right; - f32 low_cutoff[BAR_COUNT]; - f32 high_cutoff[BAR_COUNT]; + f32 low_cutoff[BAR_COUNT + 1] = {0}; + f32 high_cutoff[BAR_COUNT + 1] = {0}; - f32 freqconst_per_bin[BAR_COUNT]; + f32 freqconst_per_bin[BAR_COUNT + 1] = {0}; - u32 high_freq_cap = 22050; - u32 low_freq_cap = 30; + u32 high_freq_cap = 25000; + u32 low_freq_cap = 20; u32 sample_count; s32 sample_rate; void calc_cutoff(); - void update_bars(bool right); void gaussian_blur(bool right); + void update_bars(bool right); void monstercat_smoothing(bool right); }; |