diff options
| author | 2020-10-12 22:34:41 -0400 | |
|---|---|---|
| committer | 2020-10-12 22:34:41 -0400 | |
| commit | 73f118641b2c05148eab673b2fbcf9b4e155411d (patch) | |
| tree | dacf35cf395a7df820a380be3d88c1bbae5040bc | |
| parent | 8df6b63ee07bbbbc515ccec904ccfa1e6ce35e71 (diff) | |
| download | mauri-73f118641b2c05148eab673b2fbcf9b4e155411d.tar.gz mauri-73f118641b2c05148eab673b2fbcf9b4e155411d.tar.bz2 mauri-73f118641b2c05148eab673b2fbcf9b4e155411d.zip | |
misc render stuff, add visualizer
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | meson.build | 7 | ||||
| -rw-r--r-- | nohup.out | 0 | ||||
| -rw-r--r-- | src/engine.cc | 22 | ||||
| -rw-r--r-- | src/engine.h | 9 | ||||
| -rw-r--r-- | src/framebuffer.cc | 29 | ||||
| -rw-r--r-- | src/framebuffer.h | 26 | ||||
| -rw-r--r-- | src/gl.cc | 36 | ||||
| -rw-r--r-- | src/gl.h | 9 | ||||
| -rw-r--r-- | src/json.h | 8 | ||||
| -rw-r--r-- | src/mauri.cc | 22 | ||||
| -rw-r--r-- | src/objects/effect.cc | 64 | ||||
| -rw-r--r-- | src/objects/effect.h | 2 | ||||
| -rw-r--r-- | src/objects/material.cc | 12 | ||||
| -rw-r--r-- | src/objects/object.c | 1 | ||||
| -rw-r--r-- | src/objects/object.cc | 79 | ||||
| -rw-r--r-- | src/objects/object.h | 12 | ||||
| -rw-r--r-- | src/objects/pass.cc | 160 | ||||
| -rw-r--r-- | src/objects/pass.h | 17 | ||||
| -rw-r--r-- | src/objects/scene.cc | 7 | ||||
| -rw-r--r-- | src/objects/scene.h | 5 | ||||
| -rw-r--r-- | src/shader.cc | 13 | ||||
| -rw-r--r-- | src/texture.cc | 53 | ||||
| -rw-r--r-- | src/texture.h | 52 | ||||
| -rw-r--r-- | src/util.h | 3 | ||||
| -rw-r--r-- | src/visualizer.cc | 303 | ||||
| -rw-r--r-- | src/visualizer.h | 80 |
27 files changed, 755 insertions, 278 deletions
@@ -2,6 +2,8 @@ [x] pass parser as pointer everywhere +[ ] cleanup visualizer code + [ ] RG88 & R8 textures [ ] Re-think parse/load stage, parse stage could possibly be 1 stage where textures and framebuffers, diff --git a/meson.build b/meson.build index 482cd4a..65d37fc 100644 --- a/meson.build +++ b/meson.build @@ -34,7 +34,10 @@ Xrender = dependency('xrender', required: false) Xext = dependency('xext', required: false) GLX = dependency('glx', required: false) -deps = [dl, json, glm, lz4, stbi, glad, glfw, fmt, s3tc, X11, Xrender, Xext, GLX] +gstreamer = dependency('gstreamer-1.0', required: false) +fftw3 = dependency('fftw3', required: false) + +deps = [dl, json, glm, lz4, stbi, glad, glfw, fmt, s3tc, X11, Xrender, Xext, GLX, gstreamer, fftw3] src = [ 'src/assets.cc', @@ -44,9 +47,11 @@ src = [ 'src/shader.cc', 'src/engine.cc', 'src/texture.cc', + 'src/framebuffer.cc', 'src/context.cc', 'src/context_glfw.cc', 'src/context_x11.cc', + 'src/visualizer.cc', 'src/objects/scene.cc', 'src/objects/object.cc', 'src/objects/model.cc', diff --git a/nohup.out b/nohup.out deleted file mode 100644 index e69de29..0000000 --- a/nohup.out +++ /dev/null diff --git a/src/engine.cc b/src/engine.cc index c956ba9..ed4301a 100644 --- a/src/engine.cc +++ b/src/engine.cc @@ -4,6 +4,7 @@ #include "shader.h" #include "src/gl.h" #include "texture.h" +#include "framebuffer.h" #include "objects/object.h" #include "objects/scene.h" @@ -64,8 +65,6 @@ Engine::Engine(Scene *scene, Context *context, Parser *parser) minimal_shader = new Shader(parser, "minimal"); minimal_shader->compile(); - texture_cache.reserve(100); - create_framebuffer(COMBINE_BUFFER, view.width, view.height, 1.f); combine_buffer = get_framebuffer(COMBINE_BUFFER); @@ -81,13 +80,13 @@ Texture *Engine::get_texture(Asset *asset) { for (auto &texture : texture_cache) { - if (texture.hash == asset->hash) - return &texture; + if (texture->hash == asset->hash) + return texture; } - texture_cache.emplace_back(Texture(asset)); + texture_cache.emplace_back(new Texture(asset)); - return &texture_cache.back(); + return texture_cache.back(); } Framebuffer *Engine::get_framebuffer(const std::string &name) @@ -145,19 +144,19 @@ void Engine::draw() scene->draw(this); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + Render::bind_framebuffer(0); default_object->bind(); minimal_shader->bind(this, &default_model_flipped); combine_buffer->texture->bind(0); - glBlendFunc(GL_ONE, GL_ZERO); - glColorMask(1.f, 1.f, 1.f, 1.f); + Render::blend_func(GL_ONE, GL_ZERO); + Render::color_mask(1.f, 1.f, 1.f, 1.f); view.center_scale_viewport(); - glDrawArrays(GL_TRIANGLES, 0, 6); + default_object->draw(); } void Engine::run() @@ -186,13 +185,12 @@ Engine::~Engine() { for (auto &buffer : framebuffers) { - buffer.second->unload(); delete buffer.second; } for (auto &texture : texture_cache) { - texture.unload(); + delete texture; } delete default_object; diff --git a/src/engine.h b/src/engine.h index 30d8d3a..cb14cb8 100644 --- a/src/engine.h +++ b/src/engine.h @@ -7,6 +7,8 @@ #include "gl.h" #include "shader.h" #include "texture.h" +#include "framebuffer.h" +#include "visualizer.h" using namespace glm; @@ -48,6 +50,7 @@ class Engine Parser *parser; Context *context; + Visualizer *visualizer; View view; @@ -60,11 +63,7 @@ class Engine Shader *minimal_shader; - // Maximum textures that would be loaded by a wallpaper, - // bassed on information from the parsing stage. - u32 max_texture_count = 0; - - std::vector<Texture> texture_cache; + std::vector<Texture *> texture_cache; Texture *get_texture(Asset *asset); diff --git a/src/framebuffer.cc b/src/framebuffer.cc new file mode 100644 index 0000000..15f0129 --- /dev/null +++ b/src/framebuffer.cc @@ -0,0 +1,29 @@ +#include "framebuffer.h" + +using namespace Mauri; + +Framebuffer::Framebuffer(std::string name, f32 width, f32 height, f32 scale) + : name(name) +{ + buffer = new RenderFramebuffer(width, height, scale); + + texture = new Texture(); + + texture->wrapped = true; + + texture->texture = buffer->texture; + + texture->texture_res[0] = buffer->width; + texture->texture_res[1] = buffer->height; + texture->texture_res[2] = buffer->width; + texture->texture_res[3] = buffer->height; +} + +Framebuffer::~Framebuffer() +{ + if (texture != nullptr) + delete texture; + + if (buffer != nullptr) + delete buffer; +}
\ No newline at end of file diff --git a/src/framebuffer.h b/src/framebuffer.h new file mode 100644 index 0000000..69d224f --- /dev/null +++ b/src/framebuffer.h @@ -0,0 +1,26 @@ +#ifndef _FRAMEBUFFER_H +#define _FRAMEBUFFER_H + +#include "texture.h" +#include "gl.h" + +namespace Mauri +{ + +class Framebuffer +{ + public: + Framebuffer(std::string name, f32 width, f32 height, f32 scale); + + ~Framebuffer(); + + std::string name; + + Texture *texture; + + RenderFramebuffer *buffer; +}; + +} + +#endif // _FRAMEBUFFER_H
\ No newline at end of file @@ -42,6 +42,15 @@ void RenderObject::bind() glBindBuffer(GL_ARRAY_BUFFER, vbo); } +void RenderObject::draw() +{ +#ifdef _DEBUG_ + if (!gl_initialized) return; +#endif + + glDrawArrays(GL_TRIANGLES, 0, 6); +} + RenderObject::RenderObject(RenderObjType type, f32 width, f32 height) { #ifdef _DEBUG_ @@ -141,7 +150,6 @@ RenderShader::RenderShader(const std::string &vs_source, const std::string &fs_s if (!compile(vs_shader, vs_source.c_str(), error)) { log_error("failed to compile vertex shader (%s)", error); - std::cout << vs_source << "\n"; return; } @@ -261,6 +269,8 @@ RenderTexture::RenderTexture(bool interp, bool clamp_uv, s32 mm_count) } else { + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); } @@ -373,3 +383,27 @@ RenderFramebuffer::~RenderFramebuffer() glDeleteFramebuffers(1, &id); } +void Render::blend_func(s32 sfactor, s32 dfactor) +{ +#ifdef _DEBUG_ + if (!gl_initialized) return; +#endif + glBlendFunc(sfactor, dfactor); +} + +void Render::color_mask(f32 r, f32 g, f32 b, f32 a) +{ +#ifdef _DEBUG_ + if (!gl_initialized) return; +#endif + glColorMask(r, g, b, a); +} + +void Render::bind_framebuffer(s32 id) +{ +#ifdef _DEBUG_ + if (!gl_initialized) return; +#endif + glBindFramebuffer(GL_FRAMEBUFFER, id); +} + @@ -38,6 +38,7 @@ class RenderObject ~RenderObject(); void bind(); + void draw(); void set_data(float *vertices, s32 vertex_count); private: @@ -94,6 +95,14 @@ class RenderFramebuffer void clear(vec4 color); }; +class Render +{ + public: + static void blend_func(s32 sfactor, s32 dfactor); + static void color_mask(f32 r, f32 g, f32 b, f32 a); + static void bind_framebuffer(s32 id); +}; + } // namespace Mauri #endif // _GL_H @@ -73,6 +73,14 @@ class Parser } type = INT; } + else if (std::is_same<T, s32>::value) + { + if (jvalue.is_number()) + { + *((s32 *)res) = jvalue.get<s32>(); + } + type = INT; + } else if (std::is_same<T, f32>::value) { if (jvalue.is_number()) diff --git a/src/mauri.cc b/src/mauri.cc index f4c910d..f66e9b3 100644 --- a/src/mauri.cc +++ b/src/mauri.cc @@ -3,6 +3,7 @@ #include "gl.h" #include "json.h" #include "util.h" +#include "visualizer.h" #include "context.h" #include "context_glfw.h" @@ -21,10 +22,14 @@ 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(1920, 1080, "mauri", false); - Context *context = new ContextX11(1920, 1080, "mauri", false); + Context *context = new ContextGLFW(1280, 720, "mauri", false); + //Context *context = new ContextX11(1920, 1080, "mauri", false); //Context *context = new ContextNull(1920, 1080, "mauri", false); if (argc == 2) @@ -39,10 +44,12 @@ s32 main(s32 argc, char *argv[]) Scene *scene = new Scene(parser, scene_path); - Engine engine(scene, context, &parser); + //context->resize_window(scene->width, scene->height); - bool *visible; + Engine engine(scene, context, &parser); + engine.visualizer = v; + /* for (auto &user : parser.values) { std::cout << user.first << ":\n"; @@ -64,7 +71,7 @@ s32 main(s32 argc, char *argv[]) std::cout << (*((vec3 *)value.v))[0]; break; case VEC4: - std::cout << (*((vec4 *)value.v))[0]; + std::cout << (*((vec4 *)value.v))[0] << (*((vec4 *)value.v))[1]; break; case BOOL: std::cout << *((bool *)value.v); @@ -77,10 +84,7 @@ s32 main(s32 argc, char *argv[]) std::cout << "\n"; } } - - *visible = false; - - //context->resize_window(scene->width, scene->height); + */ engine.run(); diff --git a/src/objects/effect.cc b/src/objects/effect.cc index fb1f4e3..33b72aa 100644 --- a/src/objects/effect.cc +++ b/src/objects/effect.cc @@ -18,15 +18,6 @@ using namespace Mauri; Effect::Effect(Parser &p, json &root) { - p.get_value<u32>(root, "id", &id, 0); - - p.get_value<bool>(root, "visible", &visible, true); - - for (auto &pass0 : root["passes"]) - { - passes0.emplace_back(new Pass(p, pass0, EFFECT0_PASS)); - } - auto asset = asset_manager()->get_file(root["file"], NONE); if (asset->type == ASSET_VOID) @@ -34,8 +25,15 @@ Effect::Effect(Parser &p, json &root) auto file = json::parse(asset->as_string()); + p.get_value<u32>(root, "id", &id, 0); + p.get_value<bool>(root, "visible", &visible, true); p.get_value<std::string>(file, "name", &name, ""); + for (auto &pass0 : root["passes"]) + { + passes0.emplace_back(new Pass(p, pass0, EFFECT0_PASS)); + } + for (auto &pass1 : file["passes"]) { passes1.emplace_back(new Pass(p, pass1, EFFECT1_PASS)); @@ -47,7 +45,7 @@ Effect::Effect(Parser &p, json &root) } } -void Effect::load(Engine *engine, Object *object, bool last_effect) +void Effect::load(Engine *engine, Object *object, bool last) { buffer_id = fmt::format("_{}_{}", object->id, id); @@ -57,44 +55,26 @@ void Effect::load(Engine *engine, Object *object, bool last_effect) object->size[1], fbo.scale); } - /* - for (u32 i = 0; i < passes0.size(); i++) - { - Pass *pass = new Pass(); - - pass->combine = (i == (passes0.size() - 1)) && last_effect; - - pass->object = object; - pass->effect = this; - - passes0[i]->load(engine, EFFECT0_PASS, pass); - passes1[i]->load(engine, EFFECT1_PASS, pass); - - this->passes.push_back(new RenderPass(engine, pass)); - } - */ - u32 index = 0; for (u32 i = 0; i < passes1.size(); i++) { - Pass *pass = new Pass(); - - pass->combine = (i == (passes1.size() - 1)) && last_effect; + Pass pass; - pass->object = object; - pass->effect = this; + pass.object = object; + pass.effect = this; - if (passes1[i]->command == COPY) - passes1[i]->load(engine, EFFECT1_PASS, pass); - else + pass.combine = i == (passes1.size() - 1) && last; + + if (passes1[i]->command != COPY) { - passes0[index]->load(engine, EFFECT0_PASS, pass); - passes1[i]->load(engine, EFFECT1_PASS, pass); + passes0[index]->load(engine, EFFECT0_PASS, &pass); index++; } - this->passes.push_back(new RenderPass(engine, pass)); + passes1[i]->load(engine, EFFECT1_PASS, &pass); + + this->passes.push_back(new RenderPass(engine, &pass)); } } @@ -102,9 +82,17 @@ void Effect::draw(Engine *engine) { if (!visible) return; + +#ifdef _DEBUG_ + //std::cout << name << ":\n"; +#endif for (auto &pass : passes) { +#ifdef _DEBUG_ + //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 713c36f..40110a8 100644 --- a/src/objects/effect.h +++ b/src/objects/effect.h @@ -29,7 +29,7 @@ class Effect std::string buffer_id; - void load(Engine *engine, Object *object, bool last_effect); + void load(Engine *engine, Object *object, bool last); void draw(Engine *engine); private: diff --git a/src/objects/material.cc b/src/objects/material.cc index ae25cee..465fab1 100644 --- a/src/objects/material.cc +++ b/src/objects/material.cc @@ -39,16 +39,16 @@ void Material::load(Engine *engine, Object *object, MaterialType type, Pass *pas pass0->load(engine, MATERIAL_PASS, pass); break; case MATERIAL_MODEL: - Pass *pass = new Pass(); + Pass _pass; - pass->combine = no_effects; + _pass.object = object; + _pass.effect = nullptr; - pass->object = object; - pass->effect = nullptr; + _pass.combine = no_effects && !object->passthrough && !object->fullscreen; - pass0->load(engine, MATERIAL_ONLY_PASS, pass); + pass0->load(engine, MATERIAL_ONLY_PASS, &_pass); - object->passes.push_back(new RenderPass(engine, pass)); + object->passes.push_back(new RenderPass(engine, &_pass)); break; } diff --git a/src/objects/object.c b/src/objects/object.c new file mode 100644 index 0000000..b498fd4 --- /dev/null +++ b/src/objects/object.c @@ -0,0 +1 @@ +/ diff --git a/src/objects/object.cc b/src/objects/object.cc index efd3155..18bfdf0 100644 --- a/src/objects/object.cc +++ b/src/objects/object.cc @@ -34,8 +34,9 @@ Object::Object(Parser &p, json &root) p.get_value<vec2>(root, "size", &size, vec2(0.f)); p.get_value<vec3>(root, "scale", &scale, vec3(0.f)); p.get_value<vec3>(root, "origin", &origin, vec3(0.f)); + origin[2] = 0.f; - p.get_value<u32>(root, "colorblendmode", &color_blend_mode, 0); + p.get_value<s32>(root, "colorBlendMode", &color_blend_mode, 0); p.get_value<bool>(root, "visible", &visible, true); @@ -63,12 +64,12 @@ void Object::get_model(f32 width, f32 height, bool flip) model = glm::translate(model, origin * 2.f); - model = glm::scale(model, scale); - model = glm::rotate(model, angles[0], (vec3){1.f, 0.f, 0.f}); model = glm::rotate(model, angles[1], (vec3){0.f, 1.f, 0.f}); model = glm::rotate(model, angles[2], (vec3){0.f, 0.f, 1.f}); + model = glm::scale(model, scale); + mat4x4 _ortho = glm::ortho(-width, width, height, -height, 0.f, 1.f); if (flip) @@ -92,7 +93,6 @@ void Object::load(Engine *engine) if (dep_object != nullptr) dep_object->load(engine); } - if (image != nullptr) { @@ -117,26 +117,28 @@ void Object::load(Engine *engine) origin[1] = size[1] / 2.f; } - auto width = size[0]; - auto height = size[1]; - buffer_a = fmt::format("_rt_imageLayerComposite_{}_a", id); buffer_b = fmt::format("_rt_imageLayerComposite_{}_b", id); - engine->create_framebuffer(buffer_a, width, height, 1.f); - engine->create_framebuffer(buffer_b, width, height, 1.f); + engine->create_framebuffer(buffer_a, size[0], size[1], 1.f); + engine->create_framebuffer(buffer_b, size[0], size[1], 1.f); get_model(engine->view.width, engine->view.height, effects.size() == 0); - ortho = glm::ortho(-width, width, -height, height, 0.f, 1.f); + ortho = glm::ortho(-size[0], size[0], -size[1], size[1], 0.f, 1.f); - gl_object = new RenderObject(OBJECT, width, height); - gl_uv_object = new RenderObject(UV_SCALE, width, height); + 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); - for (u32 i = 0; i < effects.size(); i++) + for (s32 i = 0; i < effects.size(); i++) { effects[i]->load(engine, this, i == (effects.size() - 1)); } @@ -146,31 +148,55 @@ void Object::load(Engine *engine) void Object::update(Engine *engine) { - //if (engine->time > this->shake_tick) + //if (engine->time > this->shake_tick) //{ //} } void Object::draw(Engine *engine) { - //for (auto &dep : deps) - //{ - // if (dep == id) - // continue; - // auto dep_object = engine->scene->get_object_by_id(dep); - // if (dep_object != nullptr) - // dep_object->draw(engine); - //} + if (!visible) + return; + +#ifdef _DEBUG_ + //std::cout << name << " (model):\n"; +#endif for (auto &pass : passes) { +#ifdef _DEBUG_ + //std::cout << "\t" << pass->shader->name << "\n";; +#endif pass->draw(engine); } - + for (auto &effect : effects) { 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 @@ -188,11 +214,10 @@ Object::~Object() if (image != nullptr) delete image; - if (gl_object != nullptr) - delete gl_object; + delete gl_object; + delete gl_uv_object; - if (gl_uv_object != nullptr) - delete gl_uv_object; + //delete blend_shader; for (auto &pass : passes) { diff --git a/src/objects/object.h b/src/objects/object.h index 37dd2df..2ce7347 100644 --- a/src/objects/object.h +++ b/src/objects/object.h @@ -51,13 +51,17 @@ class Object RenderObject *gl_uv_object = nullptr; RenderObject *gl_object = nullptr; - u32 color_blend_mode; + s32 color_blend_mode; std::string get_target_buffer() const; std::string get_texture_buffer() const; - void swap_buffer() { - this->buffer_switch = !this->buffer_switch; + Framebuffer *previous_buffer; + Texture *previous_texture; + + void swap_buffer() + { + buffer_switch = !buffer_switch; } std::vector<RenderPass *> passes; @@ -70,6 +74,8 @@ 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 24fc868..38e68e3 100644 --- a/src/objects/pass.cc +++ b/src/objects/pass.cc @@ -31,7 +31,6 @@ Pass::Pass(Parser &p, json &root, PassStage stage) for (auto &value : _uniforms.items()) { - // Type and uname don't matter because they are stored on the shader. uniforms.emplace_back( new UniformOverride({ vec4(0.f), value.key() }) ); @@ -80,13 +79,13 @@ Pass::Pass(Parser &p, json &root, PassStage stage) break; } - auto _textures = root["textures"]; - - for (int i = 0; i < _textures.size(); i++) + for (int i = 0; i < MAX_TEXTURES; i++) { - auto _texture = _textures[i]; - if (_texture.is_string()) - textures[i] = _texture; + auto texture = root["textures"][i]; + if (texture.is_string()) + { + textures[i] = texture; + } } for (auto &combo : root["combos"].items()) @@ -97,14 +96,12 @@ Pass::Pass(Parser &p, json &root, PassStage stage) void Pass::load(Engine *engine, PassStage stage, Pass *pass) { - for (int i = 0; i < 8; i++) + for (int i = 0; i < MAX_TEXTURES; i++) { if (textures[i].empty()) continue; pass->textures[i] = textures[i]; - - //engine->max_texture_count++; } for (auto &combo : combos) @@ -128,17 +125,13 @@ void Pass::load(Engine *engine, PassStage stage, Pass *pass) if (pass->target == "previous") { - if (pass->combine) - pass->target = COMBINE_BUFFER; - else - pass->target = pass->object->get_target_buffer(); - + pass->target = pass->object->get_target_buffer(); pass->textures[0] = pass->object->get_texture_buffer(); } else pass->target.append(pass->effect->buffer_id); - for (int i = 0; i < 8; i++) + for (int i = 0; i < MAX_TEXTURES; i++) { if (binds[i].empty()) continue; @@ -157,13 +150,8 @@ void Pass::load(Engine *engine, PassStage stage, Pass *pass) break; case MATERIAL_ONLY_PASS: - if (pass->combine) - pass->target = COMBINE_BUFFER; - else - { - pass->target = pass->object->get_target_buffer(); - pass->object->swap_buffer(); - } + pass->target = pass->object->get_target_buffer(); + pass->object->swap_buffer(); [[fallthrough]]; case MATERIAL_PASS: pass->shader = shader; @@ -175,12 +163,19 @@ Pass::~Pass() { if (material != nullptr) delete material; + + //for (auto &uniform : uniforms) + //{ + // delete uniform; + //} } RenderPass::RenderPass(Engine *engine, Pass *pass) { command = pass->command; + combine = pass->combine; + if (command == COPY) { target = engine->get_framebuffer(pass->target); @@ -189,14 +184,11 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) return; } - object = pass->object; - - combine = pass->combine; - combine_blend = (BlendMode)pass->object->color_blend_mode; + target = engine->get_framebuffer(pass->target); shader = new Shader(engine->parser, pass->shader); - for (int i = 0; i < 8; i++) + for (int i = 0; i < MAX_TEXTURES; i++) { if (pass->textures[i].empty() && !shader->textures[i].empty()) pass->textures[i] = shader->textures[i]; @@ -230,28 +222,6 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) shader_uniform->value = &shader_uniform->default_value; } - /* - for (auto &shader_uniform : shader->uniforms) - { - auto add = true; - for (auto &pass_uniform : pass->uniforms) - { - if (shader_uniform->name.empty()) - continue; - if (pass_uniform->name == shader_uniform->name) - { - pass_uniform->uname = shader_uniform->uname; - pass_uniform->type = shader_uniform->type; - add = false; - delete shader_uniform; - break; - } - } - if (add) - pass->uniforms.push_back(shader_uniform); - } - */ - for (auto &uniform : shader->uniforms) { // ex: g_Texture2Resolution (vec4) @@ -261,16 +231,7 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) { auto index = uniform->uname[9] - '0'; if (textures[index] != nullptr) - uniform->value = &textures[index]->texture_resolution; - } - } - - for (auto &combo : shader->combos) - { - if (combo.name == "AUDIOPROCESSING") - { - combo.value = 0; - break; + uniform->value = &textures[index]->texture_res; } } @@ -290,9 +251,15 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) shader->combos.push_back(pass_combo); } - shader->compile(); + /* + for (auto &combo : shader->combos) + { + if (combo.name == "AUDIOPROCESSING") + combo.value = 0; + } + */ - target = engine->get_framebuffer(pass->target); + shader->compile(); if (pass->effect == nullptr) { @@ -323,13 +290,47 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) model = &engine->default_model; } } + + /* + // TODO fix this + if (pass->effect == nullptr) + { + if (pass->object->passthrough) + { + robject = pass->object->gl_object; + model = &pass->object->model; + } + else if (pass->object->fullscreen) + { + 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) { switch (command) { case DRAW: { - target->buffer->bind(); + Framebuffer *_target; + + if (combine) + _target = engine->combine_buffer; + else + _target = target; + + _target->buffer->bind(); shader->bind(engine, model); robject->bind(); @@ -340,35 +341,24 @@ void RenderPass::draw(Engine *engine) textures[i]->bind(i); } - BlendMode blend; - if (combine) - blend = combine_blend; + { + Render::blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Render::color_mask(1.f, 1.f, 1.f, 0.f); + } else - blend = NORMAL; - - switch (blend) { - case NORMAL: - glBlendFunc(GL_ONE, GL_ZERO); - glColorMask(1.f, 1.f, 1.f, 1.f); - break; - case TRANSLUCENT: - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColorMask(1.f, 1.f, 1.f, 0.f); - break; + Render::blend_func(GL_ONE, GL_ZERO); + Render::color_mask(1.f, 1.f, 1.f, 1.f); } - engine->view.default_viewport(target->buffer->width, target->buffer->height); + engine->view.default_viewport(_target->buffer->width, _target->buffer->height); - glDrawArrays(GL_TRIANGLES, 0, 6); + robject->draw(); -#if 0 - target->buffer->blit(0, engine->context->width, engine->context->height); - - engine->context->swap_buffers(); - std::this_thread::sleep_for(std::chrono::seconds(1)); -#endif + //_target->buffer->blit(0, engine->context->width, engine->context->height); + //engine->context->swap_buffers(); + //std::this_thread::sleep_for(std::chrono::seconds(2)); break; } diff --git a/src/objects/pass.h b/src/objects/pass.h index ff03a05..0211596 100644 --- a/src/objects/pass.h +++ b/src/objects/pass.h @@ -13,6 +13,8 @@ #include "objects/object.h" +#define MAX_TEXTURES 8 + namespace Mauri { @@ -56,8 +58,8 @@ class Pass std::string shader; - std::array<std::string, 8> textures; - std::array<std::string, 8> binds; + std::array<std::string, MAX_TEXTURES> textures; + std::array<std::string, MAX_TEXTURES> binds; bool combine; @@ -76,14 +78,14 @@ class RenderPass RenderPass(Engine *engine, Pass *pass); ~RenderPass(); + Shader *shader = nullptr; + void draw(Engine *engine); private: PassCommand command; - Object *object; - - Shader *shader = nullptr; + bool combine; Framebuffer *target; Framebuffer *source; @@ -91,10 +93,7 @@ class RenderPass mat4x4 *model; RenderObject *robject; - bool combine; - BlendMode combine_blend; - - std::array<Texture *, 8> textures = {0}; + std::array<Texture *, MAX_TEXTURES> textures = {0}; }; } // namespace Mauri diff --git a/src/objects/scene.cc b/src/objects/scene.cc index afb1e69..8bb2d70 100644 --- a/src/objects/scene.cc +++ b/src/objects/scene.cc @@ -41,6 +41,13 @@ Scene::Scene(Parser &p, const std::string &path) for (auto &object : root["objects"]) { + 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/objects/scene.h b/src/objects/scene.h index bd8d1b1..5c2b3a0 100644 --- a/src/objects/scene.h +++ b/src/objects/scene.h @@ -42,14 +42,9 @@ class Scene void load(Engine *engine); void draw(Engine *engine); - s32 estimated_buffer_count(); - Object *get_object_by_id(u32 id); std::vector<Object *> objects; - - private: - std::vector<RenderPass *> passes; }; } // namespace Mauri diff --git a/src/shader.cc b/src/shader.cc index bd66c16..80b928f 100644 --- a/src/shader.cc +++ b/src/shader.cc @@ -219,6 +219,19 @@ 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); + + 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_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); } Shader::~Shader() diff --git a/src/texture.cc b/src/texture.cc index 5367933..fbd894b 100644 --- a/src/texture.cc +++ b/src/texture.cc @@ -30,25 +30,29 @@ Texture::Texture(Asset *asset) asset->seek(18); - format = (TextureFormat)asset->read<u32>(); + auto format = (TextureFormat)asset->read<u32>(); - flags.integer = asset->read<u32>(); + TextureFlags flags; - texture_width = asset->read<u32>(); - texture_height = asset->read<u32>(); + flags.u.i = asset->read<u32>(); + + auto texture_width = asset->read<u32>(); + auto texture_height = asset->read<u32>(); width = asset->read<u32>(); height = asset->read<u32>(); - texture_resolution[0] = texture_width; - texture_resolution[1] = texture_height; - texture_resolution[2] = width; - texture_resolution[3] = height; + texture_res[0] = texture_width; + texture_res[1] = texture_height; + texture_res[2] = width; + texture_res[3] = height; asset->seek(4); auto container = asset->reads(9); + TextureVersion version; + auto iformat = -1; if (container.compare(0, 8, "TEXB0003") == 0) @@ -69,12 +73,13 @@ Texture::Texture(Asset *asset) } else { + version = UNKNOWN; log_error("%s", "unknown texture version"); } auto mm_count = asset->read<u32>(); - texture = new RenderTexture(flags.map.NO_INTERPOLATION, flags.map.CLAMP_UV, mm_count); + texture = new RenderTexture(flags.u.flags.NO_INTERPOLATION, flags.u.flags.CLAMP_UV, mm_count); for (int i = 0; i < mm_count; i++) { @@ -162,7 +167,7 @@ Texture::Texture(Asset *asset) asset->reset(); } -void Texture::unload() +Texture::~Texture() { if (!wrapped) delete texture; @@ -172,31 +177,3 @@ void Texture::bind(s32 index) { texture->bind(index); } - -Framebuffer::Framebuffer(std::string name, f32 width, f32 height, f32 scale) - : name(name) -{ - buffer = new RenderFramebuffer(width, height, scale); - - texture = new Texture(); - texture->wrapped = true; - - texture->texture = buffer->texture; - - texture->texture_resolution[0] = buffer->width; - texture->texture_resolution[1] = buffer->height; - texture->texture_resolution[2] = buffer->width; - texture->texture_resolution[3] = buffer->height; -} - -void Framebuffer::unload() -{ - if (texture != nullptr) - { - texture->unload(); - delete texture; - } - - if (buffer != nullptr) - delete buffer; -} diff --git a/src/texture.h b/src/texture.h index e12ad18..5093e87 100644 --- a/src/texture.h +++ b/src/texture.h @@ -25,15 +25,22 @@ enum TextureVersion { TEXB0001, TEXB0002, - TEXB0003 + TEXB0003, + UNKNOWN }; struct TextureFlags { - bool NO_INTERPOLATION : 1; - bool CLAMP_UV : 1; - bool IS_GIF : 1; - u32 UNKNWON : 29; + union { + struct + { + bool NO_INTERPOLATION : 1; + bool CLAMP_UV : 1; + bool IS_GIF : 1; + u32 UNKNWON : 29; + } flags; + u32 i; + } u; }; class Texture @@ -42,7 +49,7 @@ class Texture Texture(Asset *asset); Texture() {} - ~Texture() {}; + ~Texture(); s32 width; s32 height; @@ -51,42 +58,11 @@ class Texture bool wrapped = false; - vec4 texture_resolution; + vec4 texture_res; RenderTexture *texture; - TextureFormat format; - - void load(Asset *asset); void bind(s32 index); - - void unload(); - - private: - s32 texture_width; - s32 texture_height; - - union { - TextureFlags map; - unsigned int integer; - } flags; - - TextureVersion version; -}; - -class Framebuffer -{ - public: - Framebuffer(std::string name, f32 width, f32 height, f32 scale); - - ~Framebuffer() {}; - - std::string name; - - Texture *texture; - RenderFramebuffer *buffer; - - void unload(); }; } // namespace Mauri @@ -12,6 +12,9 @@ typedef int32_t s32; typedef uint64_t u64; typedef int64_t s64; +typedef uint16_t u16; +typedef int16_t s16; + typedef uint8_t u8; typedef int8_t s8; diff --git a/src/visualizer.cc b/src/visualizer.cc new file mode 100644 index 0000000..adfe851 --- /dev/null +++ b/src/visualizer.cc @@ -0,0 +1,303 @@ +#include <cmath> +#include <fftw3.h> +#include <numeric> +#include <stdio.h> +#include <utility> + +#include "assets.h" +#include "fmt/format.h" +#include "gst/gstcaps.h" +#include "gst/gstelement.h" +#include "gst/gstsample.h" +#include "gst/gststructure.h" +#include "log.h" +#include "objects/material.h" +#include "visualizer.h" + +using namespace Mauri; + +static const float gausian_array[] = {.242, .399, .242}; + +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) + { + 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)); + + if (i <= 0) continue; + + if (low_cutoff[i] <= low_cutoff[i - 1]) + low_cutoff[i] = low_cutoff[i - 1] + 1; + + high_cutoff[i - 1] = low_cutoff[i - 1]; + } +} + +void Visualizer::gaussian_blur(bool right) +{ + f32 *bars = (right) ? (f32 *)bars_64_right : (f32 *)bars_64_left; + + for (int i = 1; i < BAR_COUNT - 1; i++) + { + bars[i] = bars[i - 1] * gausian_array[0] + + bars[i] * gausian_array[1] + bars[i + 1] * gausian_array[2]; + } +} + +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); + + for (int i = 0; i < BAR_COUNT; ++i) + { + smoothing_factors[i] = std::pow(1.5, i); + } + + for (int i = 1; i < BAR_COUNT; ++i) + { + for (int j = 0; j < BAR_COUNT; ++j) + { + if (i == j) continue; + + const auto weighted_value = bars[i] / smoothing_factors[(int)(std::abs(i - j))]; + + if (bars[j] < weighted_value) + bars[j] = weighted_value; + } + } +} + +void Visualizer::update_bars(bool right) +{ + f32 *bars_64, *bars_32, *bars_16, *bars_falloff; + fftw_complex *out; + + if (right) + { + bars_64 = &bars_64_right[0]; + bars_32 = &bars_32_right[0]; + bars_16 = &bars_16_right[0]; + bars_falloff = &bars_64_right_falloff[0]; + out = &out_right[0]; + } + else + { + bars_64 = &bars_64_left[0]; + bars_32 = &bars_32_left[0]; + bars_16 = &bars_16_left[0]; + bars_falloff = &bars_64_left_falloff[0]; + out = &out_left[0]; + } + + for (s32 i = 0; i < BAR_COUNT; i++) + { + f64 magnitude = 0.0; + + for (s32 s = low_cutoff[i]; s <= high_cutoff[i] && s < (sample_count / 2); ++s) + { + magnitude += std::sqrt((out[s][0] * out[s][0]) + (out[s][1] * out[s][1])); + } + + f32 *bar; + + if (i < BAR_COUNT / 2) + { + bar = &bars_64[((BAR_COUNT / 2) - 1) - i]; + } + else + { + bar = &bars_64[i]; + } + + *bar = magnitude / (high_cutoff[i] - low_cutoff[i] + 1); + + *bar *= std::log2(2 + i) * (100.0 / BAR_COUNT); + *bar = std::pow(*bar, 0.5); + + auto falloff_value = std::min( + bars_falloff[i] * 0.90, + bars_falloff[i] - 1.0); + + bars_falloff[i] = std::max((f32)falloff_value, *bar); + } + + monstercat_smoothing(right); + + for (s32 i = 0; i < BAR_COUNT; i++) + { + bars_64[i] = bars_falloff[i] / 5500; + } + + for (s32 i = 0; i < BAR_COUNT / 2; i++) + { + s32 index = i * 2; + + bars_32[i] = 0; + bars_32[i] += bars_64[index]; + bars_32[i] += bars_64[index + 1]; + + bars_32[i] /= 2.0; + } + + for (s32 i = 0; i < BAR_COUNT / 4; i++) + { + s32 index = i * 4; + + bars_16[i] = 0; + bars_16[i] += bars_64[index]; + bars_16[i] += bars_64[index + 1]; + bars_16[i] += bars_64[index + 2]; + bars_16[i] += bars_64[index + 3]; + + bars_16[i] /= 4.0; + } +} + +void Visualizer::update_sample() +{ + GstSample *sample; + + g_signal_emit_by_name(appsink, "pull-sample", &sample); + + GstBuffer *buffer = gst_sample_get_buffer(sample); + + GstMemory *mem = gst_buffer_get_memory(buffer, 0); + + Sample *samples = (Sample *)(mem + mem->offset); + + g_mutex_lock(&mutex); + + for (s32 i = 0; i < sample_count; i++) + { + in_left[i] = (f64)samples[i].left; + in_right[i] = (f64)samples[i].right; + } + + fftw_execute(p_left); + fftw_execute(p_right); + + g_mutex_unlock(&mutex); +} + +void Visualizer::update() +{ + g_mutex_lock(&mutex); + + update_bars(true); + update_bars(false); + + 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(); + + return GST_FLOW_OK; +} + +static void *main_thread(void *data) +{ + Visualizer *v = (Visualizer *)data; + + GstMessage *msg = gst_bus_timed_pop_filtered(v->bus, GST_CLOCK_TIME_NONE, + (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS)); + + switch (msg->type) + { + case GST_MESSAGE_ERROR: + log_error("%s", "gstreamer pipeline died, audio wont work"); + break; + default: + break; + } + + return 0; +} + +Visualizer::Visualizer() +{ + g_mutex_init(&mutex); + + GstElement *pulsesrc; + + pipeline = gst_pipeline_new(NULL); + + pulsesrc = gst_element_factory_make("pulsesrc", NULL); + appsink = gst_element_factory_make("appsink", NULL); + + if (!pulsesrc || !appsink) + { + log_error("%s", "failed to create pipeline"); + return; + } + + 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); + gst_element_link(pulsesrc, appsink); + + gst_element_set_state(pipeline, GST_STATE_PLAYING); + + bus = gst_element_get_bus(pipeline); + + GstSample *sample; + + g_signal_emit_by_name(appsink, "pull-sample", &sample); + + 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); + + sample_count = gst_buffer_get_size(buffer) / sizeof(Sample); + + in_left = (f64 *)fftw_malloc(sizeof(f64) * sample_count); + in_right = (f64 *)fftw_malloc(sizeof(f64) * sample_count); + + 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); + + calc_cutoff(); + + p_left = fftw_plan_dft_r2c_1d(sample_count, in_left, out_left, FFTW_ESTIMATE); + p_right = fftw_plan_dft_r2c_1d(sample_count, in_right, out_right, FFTW_ESTIMATE); + + 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); +} + + diff --git a/src/visualizer.h b/src/visualizer.h new file mode 100644 index 0000000..5155391 --- /dev/null +++ b/src/visualizer.h @@ -0,0 +1,80 @@ +#ifndef _VISUALIZER_H +#define _VISUALIZER_H + +#include <gst/gst.h> +#include <fftw3.h> + +#include "util.h" + +#define BAR_COUNT 64 + +namespace Mauri +{ + +struct Sample +{ + s16 left; + s16 right; +}; + +class Visualizer +{ +public: + Visualizer(); + + ~Visualizer(); + + f32 bars_16_left[16]; + f32 bars_16_right[16]; + + f32 bars_32_left[32]; + f32 bars_32_right[32]; + + 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]; + + GstElement *pipeline; + GstBus *bus; + + GMutex mutex; + + void update(); + void update_sample(); + +private: + GstElement *appsink; + + Sample *data; + + f64 *in_left; + f64 *in_right; + + fftw_complex *out_left; + fftw_complex *out_right; + + fftw_plan p_left; + fftw_plan p_right; + + f32 low_cutoff[BAR_COUNT]; + f32 high_cutoff[BAR_COUNT]; + + f32 freqconst_per_bin[BAR_COUNT]; + + u32 high_freq_cap = 22050; + u32 low_freq_cap = 30; + + u32 sample_count; + s32 sample_rate; + + void calc_cutoff(); + void update_bars(bool right); + void gaussian_blur(bool right); + void monstercat_smoothing(bool right); +}; + +} // namespace Mauri + +#endif // _VISUALIZER_H |