From 72b4bd5c9d99d874a5900576f9a55d6f97f4f616 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Thu, 15 Oct 2020 13:25:56 -0400 Subject: better texture handling, visualizer cleanup, proper handling of object framebuffers --- src/objects/effect.cc | 10 +-- src/objects/effect.h | 10 +-- src/objects/material.cc | 7 ++- src/objects/material.h | 5 +- src/objects/model.cc | 4 +- src/objects/model.h | 2 +- src/objects/object.cc | 59 ++++++++---------- src/objects/object.h | 6 +- src/objects/pass.cc | 159 +++++++++++++++++++++++++++++------------------- src/objects/pass.h | 7 ++- src/objects/scene.cc | 5 -- 11 files changed, 147 insertions(+), 127 deletions(-) (limited to 'src/objects') 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 passes; + + void load(Engine *engine, Object *object, bool last); void draw(Engine *engine); private: - bool visible; - std::vector passes0; std::vector passes1; - std::vector passes; - std::vector 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 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 passes; + std::vector 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 #include #include +#include #include #include #include @@ -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 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)); } } -- cgit v1.2.3-101-g0448