From 8df6b63ee07bbbbc515ccec904ccfa1e6ce35e71 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sat, 10 Oct 2020 14:11:14 -0400 Subject: wip --- TODO | 29 ++++++- meson.build | 1 - nohup.out | 0 src/assets.cc | 17 ++-- src/assets.h | 23 ++--- src/context.h | 2 +- src/context_glfw.cc | 2 +- src/context_glfw.h | 2 +- src/context_null.h | 52 ++++++++++++ src/context_x11.cc | 2 +- src/context_x11.h | 3 +- src/engine.cc | 40 +++++---- src/engine.h | 25 +++--- src/gl.cc | 59 +++++++------ src/gl.h | 10 +-- src/json.cc | 61 -------------- src/json.h | 113 +++++++++++++++++++++++-- src/mauri.cc | 60 ++++++++++--- src/objects/effect.cc | 45 +++++++--- src/objects/effect.h | 9 +- src/objects/material.cc | 4 +- src/objects/material.h | 2 +- src/objects/model.cc | 16 ++-- src/objects/model.h | 11 ++- src/objects/object.cc | 104 ++++++++++++++--------- src/objects/object.h | 30 +++---- src/objects/pass.cc | 217 +++++++++++++++++++++++++++++++----------------- src/objects/pass.h | 29 ++++++- src/objects/scene.cc | 33 +++----- src/objects/scene.h | 27 +++--- src/shader.cc | 151 +++++++++++++++++---------------- src/shader.h | 27 ++---- src/texture.cc | 11 ++- src/texture.h | 17 ++-- 34 files changed, 779 insertions(+), 455 deletions(-) create mode 100644 nohup.out create mode 100644 src/context_null.h delete mode 100644 src/json.cc diff --git a/TODO b/TODO index c0a4100..b3fab49 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,27 @@ -[ ] better (cleaner) json handling +[x] better (cleaner) json handling + +[x] pass parser as pointer everywhere + +[ ] RG88 & R8 textures + +[ ] Re-think parse/load stage, parse stage could possibly be 1 stage where textures and framebuffers, + generate itermediate objects then "load" could simply load and map the resources either to the + itermediate objects or something else. + - We already know when a single pass is generated so we could just transfer that logic to only the parse step + - The intermediate objects should probably store the resource + +Broken: +[ ] ./mauri ../../../c/workshop_wallpapers/1703298496/scene.pkg + - xray only works in the middle + +[ ] ./mauri ../../../c/workshop_wallpapers/1778616550/scene.pkg + - first object has different blendmode, so we need to handle "combine" passes differently. + The final pass should draw to the objects framebuffer as well as to the combine buffer, + but using the "passthroughblend" shader. + +[X] ./mauri ../../../c/workshop_wallpapers/2008251577/scene.pkg + - effect doesnt draw correctly + - It was because of incorrect GL_TEXTURE_WRAP [ ] if version 2 is defined as a combo, g_Alpha and g_Color need to be set from the object visible should be a draw time check not handled when parsing @@ -8,4 +31,8 @@ // long term +[ ] separate gui and engine in mauri + - engine should be a shared library + - there should be a cli interface along with gui + [ ] particles diff --git a/meson.build b/meson.build index fe291ec..482cd4a 100644 --- a/meson.build +++ b/meson.build @@ -45,7 +45,6 @@ src = [ 'src/engine.cc', 'src/texture.cc', 'src/context.cc', - 'src/json.cc', 'src/context_glfw.cc', 'src/context_x11.cc', 'src/objects/scene.cc', diff --git a/nohup.out b/nohup.out new file mode 100644 index 0000000..e69de29 diff --git a/src/assets.cc b/src/assets.cc index 71a9f26..cbc2e9e 100644 --- a/src/assets.cc +++ b/src/assets.cc @@ -19,7 +19,7 @@ Asset::Asset() static Asset asset_void = Asset(); -Asset::Asset(std::string path, byte *begin, byte *end) +Asset::Asset(const std::string &path, byte *begin, byte *end) { type = ASSET_SLICE; size = end - begin; @@ -28,7 +28,7 @@ Asset::Asset(std::string path, byte *begin, byte *end) hash = std::hash{}(path); } -Asset::Asset(std::string path) +Asset::Asset(const std::string &path) { std::ifstream file(path, std::ios::binary | std::ios::ate); @@ -66,7 +66,7 @@ Asset::~Asset() } } -bool AssetManager::load_package(std::string path) +bool AssetManager::load_package(const std::string &path) { pkg = new Asset(path); @@ -103,16 +103,19 @@ bool AssetManager::load_package(std::string path) files.push_back( new Asset(std::string(file.path), pkg->ptr() + file.offset, - pkg->ptr() + file.offset + file.length)); - + pkg->ptr() + file.offset + file.length + ) + ); log_debug("loaded file (%s)", std::string(file.path).c_str()); } return true; } -Asset *AssetManager::get_file(std::string path, FileTypeHint hint) +Asset *AssetManager::get_file(const std::string &part, FileTypeHint hint) { + std::string path = part; + switch (hint) { case FileTypeHint::TEXTURE: @@ -171,10 +174,12 @@ AssetManager::~AssetManager() namespace Mauri { + static AssetManager manager; AssetManager *asset_manager() { return &manager; } + } // namespace Mauri diff --git a/src/assets.h b/src/assets.h index 0c88a1a..14a76de 100644 --- a/src/assets.h +++ b/src/assets.h @@ -31,8 +31,8 @@ class Asset { public: Asset(); - Asset(std::string path, byte *begin, byte *end); - Asset(std::string path); + Asset(const std::string &path, byte *begin, byte *end); + Asset(const std::string &path); ~Asset(); @@ -43,14 +43,14 @@ class Asset u32 size; u64 hash; - void seek(s32 n) + byte *ptr() const { - this->pos += n; + return &this->data[this->pos]; } - byte *ptr() const + void seek(s32 n) { - return &this->data[this->pos]; + this->pos += n; } void reset() @@ -73,14 +73,17 @@ class Asset return s; } - std::string as_string() + const std::string &as_string() { - return std::string((char *)this->ptr(), this->size); + if (_str.empty()) + _str = std::string((char *)this->ptr(), this->size); + return _str; } private: u32 pos; byte *data; + std::string _str; }; struct PkgFile @@ -96,9 +99,9 @@ class AssetManager AssetManager() {}; ~AssetManager(); - bool load_package(std::string path); + bool load_package(const std::string &path); - Asset *get_file(std::string path, FileTypeHint hint); + Asset *get_file(const std::string &part, FileTypeHint hint); private: Asset *pkg; diff --git a/src/context.h b/src/context.h index 09ba01e..8732631 100644 --- a/src/context.h +++ b/src/context.h @@ -13,7 +13,7 @@ namespace Mauri class Context { public: - Context(int width, int height, std::string name, bool wallpaper) + Context(int width, int height, const std::string &name, bool wallpaper) : width(width), height(height) {} virtual ~Context() {} diff --git a/src/context_glfw.cc b/src/context_glfw.cc index eca597e..136d124 100644 --- a/src/context_glfw.cc +++ b/src/context_glfw.cc @@ -46,7 +46,7 @@ double ContextGLFW::current_time() return glfwGetTime(); } -ContextGLFW::ContextGLFW(int width, int height, std::string name, bool wallpaper) +ContextGLFW::ContextGLFW(int width, int height, const std::string &name, bool wallpaper) : Context(width, height, name, wallpaper) { if (!glfwInit()) diff --git a/src/context_glfw.h b/src/context_glfw.h index 30a60f2..de9f1d5 100644 --- a/src/context_glfw.h +++ b/src/context_glfw.h @@ -13,7 +13,7 @@ namespace Mauri class ContextGLFW : public Context { public: - ContextGLFW(int width, int height, std::string name, bool wallpaper); + ContextGLFW(int width, int height, const std::string &name, bool wallpaper); ~ContextGLFW(); void close_window(); diff --git a/src/context_null.h b/src/context_null.h new file mode 100644 index 0000000..71c40cc --- /dev/null +++ b/src/context_null.h @@ -0,0 +1,52 @@ +#ifndef _CONTEXT_NULL +#define _CONTEXT_NULL + +#include "context.h" +#include + +namespace Mauri +{ +class ContextNull : public Context +{ +public: + ContextNull(int width, int height, const std::string &name, bool wallpaper) + : Context(width, height, name, wallpaper) {} + + ~ContextNull() {} + + int width, height; + + void resize_window(int width, int height) {} + + void close_window() + { + _should_close = true; + } + + bool should_close() const + { + return _should_close; + } + + void swap_buffers() {} + + void process_input() {} + + void cursor_pos(float *x, float *y) + { + *y = 0.f; + *x = 0.f; + } + + double current_time() + { + return 0.f; + } + + private: + bool _should_close = true; +}; + +} // namespace Mauri + +#endif // _CONTEXT_NULL diff --git a/src/context_x11.cc b/src/context_x11.cc index b24eefb..b1e36ea 100644 --- a/src/context_x11.cc +++ b/src/context_x11.cc @@ -21,7 +21,7 @@ void ContextX11::disable_input() 0, NULL, &wmHint, NULL); } -ContextX11::ContextX11(int width, int height, std::string name, bool wallpaper) +ContextX11::ContextX11(int width, int height, const std::string &name, bool wallpaper) : Context(width, height, name, wallpaper) { x11_d = XOpenDisplay(NULL); diff --git a/src/context_x11.h b/src/context_x11.h index a90bdc1..a1a45a5 100644 --- a/src/context_x11.h +++ b/src/context_x11.h @@ -34,10 +34,9 @@ namespace Mauri { class ContextX11 : public Context { public: - ContextX11(int width, int height, std::string name, bool wallpaper); + ContextX11(int width, int height, const std::string &name, bool wallpaper); ~ContextX11(); - bool create_window(int width, int height, std::string name, bool wallpaper); void close_window(); void resize_window(int width, int height); diff --git a/src/engine.cc b/src/engine.cc index 2bca247..c956ba9 100644 --- a/src/engine.cc +++ b/src/engine.cc @@ -1,5 +1,6 @@ #include "engine.h" #include "context.h" +#include "json.h" #include "shader.h" #include "src/gl.h" #include "texture.h" @@ -46,11 +47,11 @@ void View::center(f32 w1, f32 h1) camera_pos[1] = (scaled_height - h1) / -2.f; } -Engine::Engine(Scene *scene, Context *context) - : context(context), scene(scene) +Engine::Engine(Scene *scene, Context *context, Parser *parser) + : scene(scene), parser(parser), context(context) { - view.width = scene->width.value; - view.height = scene->height.value; + view.width = scene->width; + view.height = scene->height; view.texel_size[0] = 1.f / view.width; view.texel_size[1] = 1.f / view.height; @@ -60,9 +61,11 @@ Engine::Engine(Scene *scene, Context *context) view.center(context->width, context->height); - minimal_shader = new Shader("minimal"); + 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); @@ -74,32 +77,32 @@ Engine::Engine(Scene *scene, Context *context) scene->load(this); } -Texture *Engine::create_texture(Asset *asset) +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(new Texture(asset)); + texture_cache.emplace_back(Texture(asset)); - return texture_cache.back(); + return &texture_cache.back(); } -Framebuffer *Engine::get_framebuffer(std::string name) +Framebuffer *Engine::get_framebuffer(const std::string &name) { return framebuffers[name]; } -Texture *Engine::get_framebuffer_texture(std::string name) +Texture *Engine::get_framebuffer_texture(const std::string &name) { return framebuffers[name]->texture; } void Engine::create_framebuffer(std::string name, f32 width, f32 height, f32 scale) { - framebuffers[name] = new Framebuffer(width, height, scale); + framebuffers[name] = new Framebuffer(name, width, height, scale); } void Engine::update() @@ -135,9 +138,9 @@ void Engine::draw() buffer.second->buffer->clear((vec4){0.f, 0.f, 0.f, 0.f}); } - if (scene->clear_enabled.value) + if (scene->clear_enabled) { - combine_buffer->buffer->clear(scene->clear_color.value); + combine_buffer->buffer->clear(scene->clear_color); } scene->draw(this); @@ -183,8 +186,15 @@ Engine::~Engine() { for (auto &buffer : framebuffers) { + buffer.second->unload(); delete buffer.second; } + + for (auto &texture : texture_cache) + { + texture.unload(); + } + delete default_object; delete minimal_shader; } diff --git a/src/engine.h b/src/engine.h index 5ecdd22..30d8d3a 100644 --- a/src/engine.h +++ b/src/engine.h @@ -41,14 +41,18 @@ struct View class Engine { public: - Engine(Scene *scene, Context *context); + Engine(Scene *scene, Context *context, Parser *parser); ~Engine(); - f32 time; + Scene *scene; - View view; + Parser *parser; Context *context; + View view; + + f32 time; + RenderObject *default_object; mat4x4 default_model; @@ -56,9 +60,13 @@ class Engine Shader *minimal_shader; - std::vector texture_cache; + // Maximum textures that would be loaded by a wallpaper, + // bassed on information from the parsing stage. + u32 max_texture_count = 0; + + std::vector texture_cache; - Texture *create_texture(Asset *asset); + Texture *get_texture(Asset *asset); Framebuffer *combine_buffer; @@ -66,15 +74,12 @@ class Engine void create_framebuffer(std::string name, f32 width, f32 height, f32 scale); - Framebuffer *get_framebuffer(std::string name); - Texture *get_framebuffer_texture(std::string name); + Framebuffer *get_framebuffer(const std::string &name); + Texture *get_framebuffer_texture(const std::string &name); void run(); void draw(); void update(); - - private: - Scene *scene; }; } // namespace Mauri diff --git a/src/gl.cc b/src/gl.cc index c5988a7..f7291e6 100644 --- a/src/gl.cc +++ b/src/gl.cc @@ -9,9 +9,11 @@ using namespace Mauri; +static bool gl_initialized = true; + void RenderObject::set_data(f32 *vertices, s32 vertex_count) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -32,7 +34,7 @@ void RenderObject::set_data(f32 *vertices, s32 vertex_count) void RenderObject::bind() { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -42,7 +44,7 @@ void RenderObject::bind() RenderObject::RenderObject(RenderObjType type, f32 width, f32 height) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -94,7 +96,7 @@ RenderObject::RenderObject(RenderObjType type, f32 width, f32 height) RenderObject::~RenderObject() { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -104,8 +106,8 @@ RenderObject::~RenderObject() bool RenderShader::compile(u32 program, const char *source, char *error) { -#ifdef __DEBUG__ - if (!gl_initialized) return; +#ifdef _DEBUG_ + if (!gl_initialized) return true; #endif glShaderSource(program, 1, &source, 0); @@ -118,16 +120,15 @@ bool RenderShader::compile(u32 program, const char *source, char *error) if (status == GL_FALSE) { glGetShaderInfoLog(program, 256, NULL, error); - glDeleteShader(program); return false; } return true; } -RenderShader::RenderShader(std::string vs_source, std::string fs_source) +RenderShader::RenderShader(const std::string &vs_source, const std::string &fs_source) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -140,6 +141,7 @@ RenderShader::RenderShader(std::string vs_source, std::string fs_source) if (!compile(vs_shader, vs_source.c_str(), error)) { log_error("failed to compile vertex shader (%s)", error); + std::cout << vs_source << "\n"; return; } @@ -158,7 +160,7 @@ RenderShader::RenderShader(std::string vs_source, std::string fs_source) void RenderShader::bind() { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -167,17 +169,18 @@ void RenderShader::bind() RenderShader::~RenderShader() { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif - glDeleteShader(program); + if (program != 0) + glDeleteShader(program); } -s32 RenderShader::uniform_loc(std::string &name) +s32 RenderShader::uniform_loc(const std::string &name) { -#ifdef __DEBUG__ - if (!gl_initialized) return; +#ifdef _DEBUG_ + if (!gl_initialized) return 0; #endif auto loc = uniform_locations.find(name); @@ -191,9 +194,9 @@ s32 RenderShader::uniform_loc(std::string &name) return loc->second; } -void RenderShader::set_uniform(std::string name, UniformType type, f32 *value) +void RenderShader::set_uniform(const std::string &name, UniformType type, f32 *value) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -226,7 +229,7 @@ void RenderShader::set_uniform(std::string name, UniformType type, f32 *value) void RenderTexture::bind(s32 index) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -236,7 +239,7 @@ void RenderTexture::bind(s32 index) RenderTexture::RenderTexture(bool interp, bool clamp_uv, s32 mm_count) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -270,7 +273,7 @@ RenderTexture::RenderTexture(bool interp, bool clamp_uv, s32 mm_count) void RenderTexture::upload(byte *data, s32 width, s32 height, s32 level, u32 format, bool scale, bool dxt) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -304,7 +307,7 @@ void RenderTexture::upload(byte *data, s32 width, s32 height, s32 level, u32 for RenderTexture::~RenderTexture() { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -314,7 +317,7 @@ RenderTexture::~RenderTexture() RenderFramebuffer::RenderFramebuffer(f32 width0, f32 height0, f32 scale) : width(width0 / scale), height(height0 / scale) { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -332,7 +335,7 @@ RenderFramebuffer::RenderFramebuffer(f32 width0, f32 height0, f32 scale) void RenderFramebuffer::bind() { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif @@ -341,6 +344,10 @@ void RenderFramebuffer::bind() void RenderFramebuffer::blit(u32 dest, f32 w0, f32 h0) { +#ifdef _DEBUG_ + if (!gl_initialized) return; +#endif + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dest); glBindFramebuffer(GL_READ_FRAMEBUFFER, id); glBlitFramebuffer(0, h0, w0, 0, 0, 0, w0, h0, GL_COLOR_BUFFER_BIT, GL_NEAREST); @@ -348,13 +355,17 @@ void RenderFramebuffer::blit(u32 dest, f32 w0, f32 h0) void RenderFramebuffer::clear(vec4 color) { +#ifdef _DEBUG_ + if (!gl_initialized) return; +#endif + glBindFramebuffer(GL_FRAMEBUFFER, id); glClearBufferfv(GL_COLOR, 0, glm::value_ptr(color)); } RenderFramebuffer::~RenderFramebuffer() { -#ifdef __DEBUG__ +#ifdef _DEBUG_ if (!gl_initialized) return; #endif diff --git a/src/gl.h b/src/gl.h index f781b11..9bbeef9 100644 --- a/src/gl.h +++ b/src/gl.h @@ -13,10 +13,6 @@ using namespace glm; namespace Mauri { -#ifdef __DEBUG__ -static bool gl_initialized = false; -#endif - enum RenderObjType { DEFAULT, @@ -52,13 +48,13 @@ class RenderObject class RenderShader { public: - RenderShader(std::string vs_source, std::string fs_source); + RenderShader(const std::string &vs_source, const std::string &fs_source); ~RenderShader(); bool compile(u32 program, const char *source, char *error); - void set_uniform(std::string name, UniformType type, f32 *value); - s32 uniform_loc(std::string &name); + void set_uniform(const std::string &name, UniformType type, f32 *value); + s32 uniform_loc(const std::string &name); void bind(); diff --git a/src/json.cc b/src/json.cc deleted file mode 100644 index 59c9a22..0000000 --- a/src/json.cc +++ /dev/null @@ -1,61 +0,0 @@ -#include "json.h" -#include "util.h" - -namespace Mauri -{ - -template -JsonValue get_value(json jvalue, JsonValueType type) -{ - JsonValue value; - - if (jvalue.is_object()) - { - value.user = jvalue["user"]; - jvalue = value["value"]; - } - else - { - value.user = "root"; - } - - switch (type) - { - case INT: - if (jvalue.is_number()) - value.value = jvalue.get(); - break; - case FLOAT: - if (jvalue.is_number()) - value.value = jvalue.get(); - break; - case STRING: - if (jvalue.is_string()) - value.value = jvalue.get(); - break; - case VEC2: - if (jvalue.is_string()) - str_vec2(jvalue.get(), value.value); - break; - case VEC3: - if (jvalue.is_string()) - str_vec3(jvalue.get(), value.value); - break; - case VEC4: - // special case for because VEC4 is used for all - // uniform values and some can be a single float - if (jvalue.is_number()) - value.value[0] = jvalue.get(); - else if (jvalue.is_string()) - str_vec4(jvalue.get(), value.value); - break; - case BOOL: - if (jvalue.is_boolean()) - value.value = jvalue.get(); - break; - } - - return value; -} - -} diff --git a/src/json.h b/src/json.h index 9ed44c9..78556c7 100644 --- a/src/json.h +++ b/src/json.h @@ -2,8 +2,14 @@ #define _JSON_H #include +#include #include +#include +#include +#include "util.h" + +using namespace glm; using namespace nlohmann; #define str_vec4(s, v) sscanf(s, "%f %f %f %f", &(v)[0], &(v)[1], &(v)[2], &(v)[3]) @@ -23,21 +29,110 @@ enum JsonValueType STRING }; -template struct JsonValue { - JsonValue() {} - JsonValue(T value) - : user("root"), value(value) + JsonValueType type; + void *v; + std::string name; +}; + +class Parser +{ + public: + template + void get_value(json &root, const std::string &name, void *res, const T &_default) { + json jvalue; + + if (name.empty()) + jvalue = root; + else + jvalue = root[name]; + + std::string user; + + if (jvalue.is_object()) + { + auto _user = jvalue["user"]; + if (_user.is_string()) + user = _user; + jvalue = jvalue["value"]; + } + else + user = "root"; + + *((T *)res) = _default; + + JsonValueType type; + + if (std::is_same::value) + { + if (jvalue.is_number()) + { + *((u32 *)res) = jvalue.get(); + } + type = INT; + } + else if (std::is_same::value) + { + if (jvalue.is_number()) + { + *((f32 *)res) = jvalue.get(); + } + type = FLOAT; + } + else if (std::is_same::value) + { + if (jvalue.is_string()) + { + *((std::string *)res) = jvalue.get(); + } + type = STRING; + } + else if (std::is_same::value) + { + if (jvalue.is_string()) + { + str_vec2(jvalue.get().c_str(), *((vec2 *)res)); + } + type = VEC2; + } + else if (std::is_same::value) + { + if (jvalue.is_string()) + { + str_vec3(jvalue.get().c_str(), *((vec3 *)res)); + } + type = VEC3; + } + else if (std::is_same::value) + { + // Special case for because VEC4 is used for all + // uniform values and some are written as a single number, not a string. + if (jvalue.is_number()) + { + (*((vec4 *)res))[0] = jvalue.get(); + } + else if (jvalue.is_string()) + { + str_vec4(jvalue.get().c_str(), *((vec4 *)res)); + } + type = VEC4; + } + else if (std::is_same::value) + { + if (jvalue.is_boolean()) + { + *((bool *)res) = jvalue.get(); + } + type = BOOL; + } + + values[user].push_back(JsonValue { type, res, name }); } - std::string user; - T value; + std::unordered_map> values; }; - -template -extern JsonValue get_value(json jvalue, JsonValueType type); } // namespace Mauri diff --git a/src/mauri.cc b/src/mauri.cc index e8a509e..f4c910d 100644 --- a/src/mauri.cc +++ b/src/mauri.cc @@ -1,11 +1,13 @@ #include "assets.h" #include "engine.h" #include "gl.h" +#include "json.h" #include "util.h" #include "context.h" #include "context_glfw.h" #include "context_x11.h" +#include "context_null.h" #include "objects/scene.h" @@ -13,20 +15,17 @@ using namespace Mauri; -static std::string scene_path = std::string("scene.json"); +static std::string scene_path = "scene.json"; s32 main(s32 argc, char *argv[]) { srand(time(NULL)); -#ifdef __DEBUG__ - gl_initialized = true; -#endif - //Context *context = new ContextX11(2560, 1440, "mauri", true); //Context *context = new ContextGLFW(720, 1280, "mauri", false); - //Context *context = new ContextGLFW(810, 1440, "mauri", false); - Context *context = new ContextX11(2560, 1440, "mauri", true); + //Context *context = new ContextGLFW(1920, 1080, "mauri", false); + Context *context = new ContextX11(1920, 1080, "mauri", false); + //Context *context = new ContextNull(1920, 1080, "mauri", false); if (argc == 2) { @@ -36,11 +35,52 @@ s32 main(s32 argc, char *argv[]) return 1; } - Scene *scene = new Scene(scene_path); + Parser parser; - //context->resize_window(scene->width, scene->height); + Scene *scene = new Scene(parser, scene_path); + + Engine engine(scene, context, &parser); - Engine engine(scene, context); + bool *visible; + + 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]; + break; + case BOOL: + std::cout << *((bool *)value.v); + break; + case STRING: + std::cout << *((std::string *)value.v); + break; + } + + 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 bc94c17..fb1f4e3 100644 --- a/src/objects/effect.cc +++ b/src/objects/effect.cc @@ -16,15 +16,15 @@ using namespace Mauri; -Effect::Effect(json root) +Effect::Effect(Parser &p, json &root) { - id = get_value(root["id"], INT); + p.get_value(root, "id", &id, 0); - visible = get_value(root["visible"], BOOL); + p.get_value(root, "visible", &visible, true); for (auto &pass0 : root["passes"]) { - passes0.emplace_back(new Pass(pass0, EFFECT0_PASS)); + passes0.emplace_back(new Pass(p, pass0, EFFECT0_PASS)); } auto asset = asset_manager()->get_file(root["file"], NONE); @@ -34,11 +34,11 @@ Effect::Effect(json root) auto file = json::parse(asset->as_string()); - name = get_value(file["name"], STRING); + p.get_value(file, "name", &name, ""); for (auto &pass1 : file["passes"]) { - passes1.emplace_back(new Pass(pass1, EFFECT1_PASS)); + passes1.emplace_back(new Pass(p, pass1, EFFECT1_PASS)); } for (auto &fbo : file["fbos"]) @@ -49,14 +49,15 @@ Effect::Effect(json root) void Effect::load(Engine *engine, Object *object, bool last_effect) { - buffer_id = fmt::format("{}_{}", id.value, object->id.value); + buffer_id = fmt::format("_{}_{}", object->id, id); for (auto &fbo : fbos) { - engine->create_framebuffer(fbo.name + buffer_id, object->size.value[0], - object->size.value[1], fbo.scale); + engine->create_framebuffer(fbo.name + buffer_id, object->size[0], + object->size[1], fbo.scale); } + /* for (u32 i = 0; i < passes0.size(); i++) { Pass *pass = new Pass(); @@ -69,13 +70,37 @@ void Effect::load(Engine *engine, Object *object, bool last_effect) 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->object = object; + pass->effect = this; + + if (passes1[i]->command == COPY) + passes1[i]->load(engine, EFFECT1_PASS, pass); + else + { + passes0[index]->load(engine, EFFECT0_PASS, pass); + passes1[i]->load(engine, EFFECT1_PASS, pass); + index++; + } + this->passes.push_back(new RenderPass(engine, pass)); } } void Effect::draw(Engine *engine) { - if (!visible.value) + if (!visible) return; for (auto &pass : passes) diff --git a/src/objects/effect.h b/src/objects/effect.h index 29b4bb7..713c36f 100644 --- a/src/objects/effect.h +++ b/src/objects/effect.h @@ -4,6 +4,7 @@ #include #include "engine.h" +#include "texture.h" namespace Mauri { @@ -20,11 +21,11 @@ struct EffectBuffer class Effect { public: - Effect(json root); + Effect(Parser &p, json &root); ~Effect(); - JsonValue id; - JsonValue name; + u32 id; + std::string name; std::string buffer_id; @@ -32,7 +33,7 @@ class Effect void draw(Engine *engine); private: - JsonValue visible; + bool visible; std::vector passes0; std::vector passes1; diff --git a/src/objects/material.cc b/src/objects/material.cc index 699c603..ae25cee 100644 --- a/src/objects/material.cc +++ b/src/objects/material.cc @@ -11,7 +11,7 @@ using namespace Mauri; -Material::Material(std::string path) +Material::Material(Parser &p, const std::string &path) { auto asset = asset_manager()->get_file(path, NONE); @@ -25,7 +25,7 @@ Material::Material(std::string path) for (auto &pass : root["passes"]) { - passes0.push_back(new Pass(pass, MATERIAL_PASS)); + passes0.push_back(new Pass(p, pass, MATERIAL_PASS)); } } diff --git a/src/objects/material.h b/src/objects/material.h index c27c720..0e46f7f 100644 --- a/src/objects/material.h +++ b/src/objects/material.h @@ -20,7 +20,7 @@ enum MaterialType class Material { public: - Material(std::string path); + Material(Parser &p, const std::string &path); ~Material(); void load(Engine *engine, Object *object, MaterialType type, Pass *pass, bool no_effects); diff --git a/src/objects/model.cc b/src/objects/model.cc index 0574a92..f450d34 100644 --- a/src/objects/model.cc +++ b/src/objects/model.cc @@ -9,7 +9,7 @@ using namespace Mauri; -Model::Model(std::string path) +Model::Model(Parser &p, const std::string &path) { auto asset = asset_manager()->get_file(path, NONE); @@ -21,11 +21,17 @@ Model::Model(std::string path) auto root = json::parse(asset->as_string()); - autosize = get_value(root["autosize"], BOOL); - fullscreen = get_value(root["fullscreen"], BOOL); - passthrough = get_value(root["passthrough"], BOOL); + p.get_value(root, "autosize", &autosize, false); + p.get_value(root, "fullscreen", &fullscreen, false); + p.get_value(root, "passthrough", &passthrough, false); - material = new Material(root["material"]); + p.get_value(root, "width", &width, 0.f); + p.get_value(root, "height", &height, 0.f); + + auto _material = root["material"]; + + if (_material.is_string()) + material = new Material(p, _material); } void Model::load(Engine *engine, Object *object, bool no_effects) diff --git a/src/objects/model.h b/src/objects/model.h index 9e67f07..e4a55ea 100644 --- a/src/objects/model.h +++ b/src/objects/model.h @@ -14,12 +14,15 @@ namespace Mauri class Model { public: - Model(std::string path); + Model(Parser &p, const std::string &path); ~Model(); - JsonValue autosize; - JsonValue fullscreen; - JsonValue passthrough; + bool autosize = true; + bool fullscreen = false; + bool passthrough = false; + + f32 width; + f32 height; void load(Engine *engine, Object *object, bool no_effects); diff --git a/src/objects/object.cc b/src/objects/object.cc index a41cfaa..efd3155 100644 --- a/src/objects/object.cc +++ b/src/objects/object.cc @@ -12,6 +12,7 @@ #include "../json.h" #include "../log.h" +#include "fmt/format.h" #include "objects/effect.h" #include "objects/model.h" #include "objects/object.h" @@ -20,34 +21,37 @@ using namespace Mauri; -Object::Object(json root) +Object::Object(Parser &p, json &root) { - id = get_value(root["id"], INT); - name = get_value(root["id"], STRING); + p.get_value(root, "id", &id, 0); + p.get_value(root, "name", &name, ""); for (auto &id : root["dependencies"]) deps.push_back(id); - angles = get_value(root["angles"], VEC3); - color = get_value(root["colors"], VEC3); - size = get_value(root["size"], VEC2); - scale = get_value(root["size"], VEC3); - origin = get_value(root["origin"], VEC3); + p.get_value(root, "angles", &angles, vec3(0.f)); + p.get_value(root, "color", &color, vec3(0.f)); + p.get_value(root, "size", &size, vec2(0.f)); + p.get_value(root, "scale", &scale, vec3(0.f)); + p.get_value(root, "origin", &origin, vec3(0.f)); - color_blend_mode = (BlendMode)root["colorblendmode"]; + p.get_value(root, "colorblendmode", &color_blend_mode, 0); - visible = get_value(root["visible"], BOOL); + p.get_value(root, "visible", &visible, true); - image = new Model(root["image"]); + auto _image = root["image"]; + + if (_image.is_string()) + image = new Model(p, _image); auto config = root["config"]; if (!config.is_null()) - passthrough = get_value(config["passthrough"], BOOL); + p.get_value(config, "passthrough", &passthrough, false); for (auto &effect : root["effects"]) { - effects.emplace_back(new Effect(effect)); + effects.emplace_back(new Effect(p, effect)); } } @@ -57,13 +61,13 @@ void Object::get_model(f32 width, f32 height, bool flip) model = glm::translate(model, (vec3){-width, -height, 0.f}); - model = glm::translate(model, origin.value * 2.f); + model = glm::translate(model, origin * 2.f); - model = glm::scale(model, scale.value); + model = glm::scale(model, scale); - model = glm::rotate(model, angles.value[0], (vec3){1.f, 0.f, 0.f}); - model = glm::rotate(model, angles.value[1], (vec3){0.f, 1.f, 0.f}); - model = glm::rotate(model, angles.value[2], (vec3){0.f, 0.f, 1.f}); + 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}); mat4x4 _ortho = glm::ortho(-width, width, height, -height, 0.f, 1.f); @@ -80,32 +84,47 @@ void Object::load(Engine *engine) if (loaded) return; + for (auto &dep : deps) + { + if (dep == id) + continue; + auto dep_object = engine->scene->get_object_by_id(dep); + if (dep_object != nullptr) + dep_object->load(engine); + } + + if (image != nullptr) { - if (image->passthrough.value) + if (image->passthrough) passthrough = true; - if (image->fullscreen.value || passthrough.value) - { - if (size.value[0] == 0 && size.value[1] == 0) - { - size.value[0] = engine->view.width; - size.value[1] = engine->view.height; - origin.value[0] = size.value[0] / 2.f; - origin.value[1] = size.value[1] / 2.f; - } + if (image->fullscreen) fullscreen = true; + + if (image->width != 0.f && image->height != 0.f) + { + size[0] = image->width; + size[1] = image->height; } } - auto width = size.value[0]; - auto height = size.value[1]; + if (size[0] == 0 && size[1] == 0) + { + size[0] = engine->view.width; + size[1] = engine->view.height; + origin[0] = size[0] / 2.f; + origin[1] = size[1] / 2.f; + } - abuffer = fmt::format("_rt_imageLayerComposite_{}_a", this->id.value); - bbuffer = fmt::format("_rt_imageLayerComposite_{}_b", this->id.value); + auto width = size[0]; + auto height = size[1]; - engine->create_framebuffer(abuffer, width, height, 1.f); - engine->create_framebuffer(bbuffer, width, height, 1.f); + 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); get_model(engine->view.width, engine->view.height, effects.size() == 0); @@ -114,7 +133,8 @@ void Object::load(Engine *engine) gl_object = new RenderObject(OBJECT, width, height); gl_uv_object = new RenderObject(UV_SCALE, width, height); - image->load(engine, this, effects.size() == 0); + if (image != nullptr) + image->load(engine, this, effects.size() == 0); for (u32 i = 0; i < effects.size(); i++) { @@ -133,8 +153,14 @@ void Object::update(Engine *engine) void Object::draw(Engine *engine) { - if (!visible.value) - return; + //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); + //} for (auto &pass : passes) { @@ -149,12 +175,12 @@ void Object::draw(Engine *engine) std::string Object::get_target_buffer() const { - return (buffer_switch) ? abuffer : bbuffer; + return (buffer_switch) ? buffer_a : buffer_b; } std::string Object::get_texture_buffer() const { - return (buffer_switch) ? bbuffer : abuffer; + return (buffer_switch) ? buffer_b : buffer_a; } Object::~Object() diff --git a/src/objects/object.h b/src/objects/object.h index 14b6615..37dd2df 100644 --- a/src/objects/object.h +++ b/src/objects/object.h @@ -28,18 +28,20 @@ enum BlendMode class Object { public: - Object(json root); + Object(Parser &p, json &root); ~Object(); - JsonValue id; - JsonValue name; + u32 id; + std::string name; + + bool visible; std::vector deps; - JsonValue passthrough; - JsonValue fullscreen; + bool passthrough = false; + bool fullscreen = false; - JsonValue size; + vec2 size; void get_model(f32 width, f32 height, bool flip); @@ -49,7 +51,7 @@ class Object RenderObject *gl_uv_object = nullptr; RenderObject *gl_object = nullptr; - BlendMode color_blend_mode; + u32 color_blend_mode; std::string get_target_buffer() const; std::string get_texture_buffer() const; @@ -66,18 +68,16 @@ class Object void draw(Engine *engine); private: - JsonValue visible; - Model *image = nullptr; - JsonValue angles; - JsonValue color; + vec3 angles; + vec3 color; - JsonValue origin; - JsonValue scale; + vec3 origin; + vec3 scale; - std::string abuffer; - std::string bbuffer; + std::string buffer_a; + std::string buffer_b; bool buffer_switch = false; diff --git a/src/objects/pass.cc b/src/objects/pass.cc index 333694a..24fc868 100644 --- a/src/objects/pass.cc +++ b/src/objects/pass.cc @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include @@ -20,28 +22,48 @@ using namespace Mauri; -Pass::Pass(json root, PassStage stage) +Pass::Pass(Parser &p, json &root, PassStage stage) { switch (stage) { case EFFECT0_PASS: { - for (auto &value : root["constantshadervalues"].items()) + auto _uniforms = root["constantshadervalues"]; + + for (auto &value : _uniforms.items()) { - // In this case type and uname are irrelevant because this is only used to - // override the value stored on the shader which contains the type and uname. - uniforms.push_back(Uniform(value.key(), get_value(value.value(), VEC4))); + // Type and uname don't matter because they are stored on the shader. + uniforms.emplace_back( + new UniformOverride({ vec4(0.f), value.key() }) + ); + p.get_value(_uniforms, value.key(), &uniforms.back()->value, vec4(0.f)); } break; } case EFFECT1_PASS: { - material = new Material(root["material"]); + auto _material = root["material"]; + + if (_material.is_string()) + material = new Material(p, _material); + + auto _command = root["command"]; + + if (_command.is_string()) + { + if (_command == "copy") + command = COPY; + } auto _target = root["target"]; if (_target.is_string()) target = _target; + auto _source = root["source"]; + + if (_source.is_string()) + source = _source; + for (auto &bind : root["bind"]) { u32 index = bind["index"]; @@ -53,36 +75,20 @@ Pass::Pass(json root, PassStage stage) case MATERIAL_ONLY_PASS: target = "previous"; [[fallthrough]]; - case MATERIAL_PASS: { + case MATERIAL_PASS: shader = root["shader"]; - - //auto blending = root.get("blending", "normal").asString(); - - //if (blending == "normal") - // blend = NORMAL; - //else if (blending == "translucent") - // blend = TRANSLUCENT; - break; } - } - for (int i = 0; i < 8; i++) + auto _textures = root["textures"]; + + for (int i = 0; i < _textures.size(); i++) { - auto texture = root["textures"][i]; - if (texture.is_string()) - textures[i] = texture; + auto _texture = _textures[i]; + if (_texture.is_string()) + textures[i] = _texture; } - //auto _textures = root["textures"]; - - //for (int i = 0; i < _textures.size(); i++) - //{ - // auto texture = _textures[i]; - // if (texture.is_string()) - // textures[i] = texture; - //} - for (auto &combo : root["combos"].items()) { combos.emplace_back((Combo) { combo.key(), combo.value() }); @@ -97,6 +103,8 @@ void Pass::load(Engine *engine, PassStage stage, Pass *pass) continue; pass->textures[i] = textures[i]; + + //engine->max_texture_count++; } for (auto &combo : combos) @@ -113,6 +121,9 @@ void Pass::load(Engine *engine, PassStage stage, Pass *pass) } break; case EFFECT1_PASS: + pass->command = command; + + pass->source = source + pass->effect->buffer_id; pass->target = target; if (pass->target == "previous") @@ -168,10 +179,22 @@ Pass::~Pass() RenderPass::RenderPass(Engine *engine, Pass *pass) { + command = pass->command; + + if (command == COPY) + { + target = engine->get_framebuffer(pass->target); + source = engine->get_framebuffer(pass->source); + + return; + } + + object = pass->object; + combine = pass->combine; - combine_blend = pass->object->color_blend_mode; + combine_blend = (BlendMode)pass->object->color_blend_mode; - shader = new Shader(pass->shader); + shader = new Shader(engine->parser, pass->shader); for (int i = 0; i < 8; i++) { @@ -184,36 +207,62 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) auto asset = asset_manager()->get_file(pass->textures[i], TEXTURE); if (asset->type != ASSET_VOID) - textures[i] = engine->create_texture(asset); + textures[i] = engine->get_texture(asset); else textures[i] = engine->get_framebuffer_texture(pass->textures[i]); } - for (auto &uniform : shader->uniforms) + for (auto &shader_uniform : shader->uniforms) { - // ex: g_Texture2Resolution (vec4) - // ^ index - if (uniform.uname.compare(0, 9, "g_Texture") == 0 && - uniform.uname.compare(10, 10, "Resolution") == 0) + auto default_value = true; + for (auto &uniform_override : pass->uniforms) { - auto index = uniform.uname[9] - '0'; - if (textures[index] != nullptr) - uniform.value = textures[index]->texture_resolution; + if (shader_uniform->name.empty()) + continue; + if (shader_uniform->name == uniform_override->name) + { + shader_uniform->value = &uniform_override->value; + default_value = false; + break; + } } + if (default_value) + shader_uniform->value = &shader_uniform->default_value; } - for (auto &pass_uniform : pass->uniforms) + /* + for (auto &shader_uniform : shader->uniforms) { - for (auto &shader_uniform : shader->uniforms) + auto add = true; + for (auto &pass_uniform : pass->uniforms) { - if (shader_uniform.name.empty()) + if (shader_uniform->name.empty()) continue; - if (pass_uniform.name == shader_uniform.name) + if (pass_uniform->name == shader_uniform->name) { - shader_uniform.value = pass_uniform.value; + 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) + // ^ index + if (uniform->uname.compare(0, 9, "g_Texture") == 0 && + uniform->uname.compare(10, 10, "Resolution") == 0) + { + auto index = uniform->uname[9] - '0'; + if (textures[index] != nullptr) + uniform->value = &textures[index]->texture_resolution; + } } for (auto &combo : shader->combos) @@ -247,19 +296,23 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) if (pass->effect == nullptr) { - if (pass->object->passthrough.value || combine) + 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->passthrough.value) + if (pass->object->fullscreen) + robject = engine->default_object; + else if (pass->object->passthrough) robject = pass->object->gl_object; else robject = pass->object->gl_uv_object; } else { - if (combine) + if (combine && !pass->object->fullscreen) { robject = pass->object->gl_object; model = &pass->object->model; @@ -274,45 +327,55 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) void RenderPass::draw(Engine *engine) { - target->buffer->bind(); - shader->bind(engine, model); + switch (command) { + case DRAW: { + target->buffer->bind(); - robject->bind(); + shader->bind(engine, model); + robject->bind(); - for (int i = 0; i < shader->texture_count; i++) - { - if (textures[i] != nullptr) - textures[i]->bind(i); - } + for (int i = 0; i < shader->texture_count; i++) + { + if (textures[i] != nullptr) + textures[i]->bind(i); + } - BlendMode blend; + BlendMode blend; - if (combine) - blend = combine_blend; - else - blend = NORMAL; + if (combine) + blend = combine_blend; + 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; - } + 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; + } - 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); + glDrawArrays(GL_TRIANGLES, 0, 6); #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)); + target->buffer->blit(0, engine->context->width, engine->context->height); + + engine->context->swap_buffers(); + std::this_thread::sleep_for(std::chrono::seconds(1)); #endif + + break; + } + case COPY: + source->buffer->blit(target->buffer->id, source->buffer->width, source->buffer->height); + break; + } } RenderPass::~RenderPass() diff --git a/src/objects/pass.h b/src/objects/pass.h index 78de015..ff03a05 100644 --- a/src/objects/pass.h +++ b/src/objects/pass.h @@ -24,17 +24,32 @@ enum PassStage MATERIAL_ONLY_PASS }; +enum PassCommand +{ + DRAW, + COPY +}; + +struct UniformOverride +{ + vec4 value; + std::string name; +}; + class RenderPass; class Pass { public: Pass() {} - Pass(json root, PassStage stage); + Pass(Parser &p, json &root, PassStage stage); ~Pass(); - std::string target; + PassCommand command = DRAW; + + std::string target = "previous"; + std::string source; Object *object; Effect *effect; @@ -46,7 +61,7 @@ class Pass bool combine; - std::vector uniforms; + std::vector uniforms; std::vector combos; void load(Engine *engine, PassStage stage, Pass *pass); @@ -64,8 +79,14 @@ class RenderPass void draw(Engine *engine); private: - Shader *shader; + PassCommand command; + + Object *object; + + Shader *shader = nullptr; + Framebuffer *target; + Framebuffer *source; mat4x4 *model; RenderObject *robject; diff --git a/src/objects/scene.cc b/src/objects/scene.cc index 1e95f4b..afb1e69 100644 --- a/src/objects/scene.cc +++ b/src/objects/scene.cc @@ -11,7 +11,7 @@ using namespace Mauri; -Scene::Scene(std::string path) +Scene::Scene(Parser &p, const std::string &path) { auto asset = asset_manager()->get_file(path, NONE); @@ -25,25 +25,23 @@ Scene::Scene(std::string path) auto camera = root["camera"]; - cam.center = get_value(camera["center"], VEC3); - cam.eye = get_value(camera["eye"], VEC3); - cam.up = get_value(camera["up"], VEC3); + p.get_value(camera, "center", &cam.center, vec3(0.f)); + p.get_value(camera, "eye", &cam.eye, vec3(0.f)); + p.get_value(camera, "up", &cam.up, vec3(0.f)); auto general = root["general"]; - clear_enabled = get_value(general["clearenabled"], BOOL); - - clear_color = get_value(general["clearcolor"], VEC3); - clear_color.value[3] = 1.f; + p.get_value(general, "clearenabled", &clear_enabled, true); + p.get_value(general, "clearcolor", &clear_color, vec4(1.f)); auto ortho = general["orthogonalprojection"]; - width = get_value(ortho["width"], FLOAT); - height = get_value(ortho["height"], FLOAT); + p.get_value(ortho, "width", &width, 0.f); + p.get_value(ortho, "height", &height, 0.f); for (auto &object : root["objects"]) { - objects.emplace_back(new Object(object)); + objects.emplace_back(new Object(p, object)); } } @@ -51,7 +49,7 @@ Object *Scene::get_object_by_id(u32 id) { for (auto &object : objects) { - if (object->id.value == id) + if (object->id == id) { return object; } @@ -62,18 +60,11 @@ Object *Scene::get_object_by_id(u32 id) void Scene::load(Engine *engine) { - engine->view.width = width.value; - engine->view.height = height.value; + engine->view.width = width; + engine->view.height = height; for (auto &object : objects) { - for (auto &dep : object->deps) - { - auto dep_object = get_object_by_id(dep); - if (dep_object != nullptr) - dep_object->load(engine); - } - object->load(engine); } } diff --git a/src/objects/scene.h b/src/objects/scene.h index 43a4442..bd8d1b1 100644 --- a/src/objects/scene.h +++ b/src/objects/scene.h @@ -17,26 +17,27 @@ namespace Mauri { struct Camera { - JsonValue center; - JsonValue eye; - JsonValue up; - - JsonValue farz; - JsonValue nearz; - JsonValue fov; + vec3 center; + vec3 eye; + vec3 up; + float farz; + float nearz; + float fov; }; class Scene { public: - Scene(std::string path); + Scene(Parser &p, const std::string &path); ~Scene(); - JsonValue width; - JsonValue height; + Camera cam; + + f32 width; + f32 height; - JsonValue clear_enabled; - JsonValue clear_color; + bool clear_enabled; + vec4 clear_color; void load(Engine *engine); void draw(Engine *engine); @@ -48,7 +49,7 @@ class Scene std::vector objects; private: - Camera cam; + std::vector passes; }; } // namespace Mauri diff --git a/src/shader.cc b/src/shader.cc index eae4820..bd66c16 100644 --- a/src/shader.cc +++ b/src/shader.cc @@ -13,33 +13,34 @@ #include "objects/object.h" -static const char *gl_compat = "#define highp\n" - "#define mediump\n" - "#define lowp\n" - "#define mul(x, y) (y * x)\n" - "#define frac fract\n" - "#define CAST2(x) (vec2(x))\n" - "#define CAST3(x) (vec3(x))\n" - "#define CAST4(x) (vec4(x))\n" - "#define CAST3X3(x) (mat3(x))\n" - "#define saturate(x) (clamp(x, 0.0, 1.0))\n" - "#define texSample2D texture2D\n" - "#define texSample2DLod texture2DLod\n" - "#define texture2DLod texture2D\n" - "#define atan2 atan\n" - "#define ddx dFdx\n" - "#define ddy(x) dFdy(-(x))\n" - "#define GLSL 1\n"; +static const char *gl_compat = \ + "#define highp\n" + "#define mediump\n" + "#define lowp\n" + "#define mul(x, y) (y * x)\n" + "#define frac fract\n" + "#define CAST2(x) (vec2(x))\n" + "#define CAST3(x) (vec3(x))\n" + "#define CAST4(x) (vec4(x))\n" + "#define CAST3X3(x) (mat3(x))\n" + "#define saturate(x) (clamp(x, 0.0, 1.0))\n" + "#define texSample2D texture2D\n" + "#define texSample2DLod texture2DLod\n" + "#define texture2DLod texture2D\n" + "#define atan2 atan\n" + "#define ddx dFdx\n" + "#define ddy(x) dFdy(-(x))\n" + "#define GLSL 1\n"; static const char *version = "#version 120\n"; using namespace Mauri; -std::string Shader::build_shader_source(std::string isource, bool root) +void Shader::build_shader_source(Parser *p, const std::string &isource, std::string &res, bool root) { - std::stringstream stream(isource), source; - - if (root) source << gl_compat; + auto stream = std::istringstream(isource); + + if (root) res += gl_compat; for (std::string line; std::getline(stream, line);) { @@ -51,9 +52,11 @@ std::string Shader::build_shader_source(std::string isource, bool root) auto include_name = line.substr(open, line.rfind('"') - open); auto asset = asset_manager()->get_file(include_name, SHADER); - auto include_source = this->build_shader_source(asset->as_string(), false); - source << include_source; + std::string include_source; + build_shader_source(p, asset->as_string(), include_source, false); + + res += include_source; cut_line = true; } @@ -61,30 +64,27 @@ std::string Shader::build_shader_source(std::string isource, bool root) { auto type_string = line.substr(line.find(' ') + 1); - auto type = TYPE_INVALID; - - JsonValue value; + auto uniform = new Uniform(); if (type_string.compare(0, 5, "float") == 0) - type = TYPE_FLOAT; + uniform->type = TYPE_FLOAT; else if (type_string.compare(0, 4, "vec4") == 0) - type = TYPE_VEC4; + uniform->type = TYPE_VEC4; else if (type_string.compare(0, 4, "vec3") == 0) - type = TYPE_VEC3; + uniform->type = TYPE_VEC3; else if (type_string.compare(0, 4, "vec2") == 0) - type = TYPE_VEC2; + uniform->type = TYPE_VEC2; else if (type_string.compare(0, 4, "mat4") == 0) - type = TYPE_MAT4; + uniform->type = TYPE_MAT4; else if (type_string.compare(0, 9, "sampler2D") == 0) { - type = TYPE_SAMPLER2D; - value.value[0] = this->texture_count++; + uniform->type = TYPE_SAMPLER2D; + uniform->default_value[0] = texture_count++; } auto open = type_string.find(' ') + 1; - auto uname = type_string.substr(open, type_string.find(';') - open); - auto name = std::string(""); + uniform->uname = type_string.substr(open, type_string.find(';') - open); auto combo_start = line.find("// "); @@ -101,22 +101,22 @@ std::string Shader::build_shader_source(std::string isource, bool root) auto material = root["material"]; if (!material.is_null()) - name = material; + uniform->name = material; else if (!label.is_null()) - name = label; + uniform->name = label; - switch (type) + switch (uniform->type) { case TYPE_SAMPLER2D: { auto _default = root["default"]; if (!_default.is_null()) - this->textures[(int)(value.value[0])] = _default; + textures[(int)uniform->default_value[0]] = _default; auto combo = root["combo"]; if (!combo.is_null()) - this->combos.emplace_back((Combo) { .name = combo, .value = 1 }); + combos.emplace_back((Combo) { .name = combo, .value = 1 }); break; } @@ -124,16 +124,16 @@ std::string Shader::build_shader_source(std::string isource, bool root) case TYPE_VEC4: case TYPE_VEC3: case TYPE_VEC2: - value = get_value(root["default"], VEC4); + p->get_value(root, "default", &uniform->default_value, vec4(0.f)); break; case TYPE_MAT4: case TYPE_INVALID: - value.value = glm::vec4(0.f); + uniform->default_value = vec4(0.f); break; } } - - this->uniforms.emplace_back(Uniform(name, uname, type, value)); + + uniforms.emplace_back(uniform); } else if (line.compare(0, 10, "// [COMBO]") == 0) { @@ -142,71 +142,71 @@ std::string Shader::build_shader_source(std::string isource, bool root) auto root = json::parse(combo); - this->combos.emplace_back((Combo) { root["combo"], root["default"] }); + combos.emplace_back((Combo) { root["combo"], root["default"] }); } - if (!cut_line) source << line << "\n"; + if (!cut_line) res += line + "\n"; } - - return source.str(); } std::string Combo::to_string() { - return fmt::format("#define {} {}\n", this->name, this->value); + return fmt::format("#define {} {}\n", name, value); } void Shader::compile() { - auto vs_source = this->vs_source; - auto fs_source = this->fs_source; + auto _vs_source = vs_source; + auto _fs_source = fs_source; - for (auto &combo : this->combos) + for (auto &combo : combos) { - vs_source.insert(0, combo.to_string()); - fs_source.insert(0, combo.to_string()); + _vs_source.insert(0, combo.to_string()); + _fs_source.insert(0, combo.to_string()); } - vs_source.insert(0, version); - fs_source.insert(0, version); + _vs_source.insert(0, version); + _fs_source.insert(0, version); - this->rshader = new RenderShader(vs_source, fs_source); + rshader = new RenderShader(_vs_source, _fs_source); } -Shader::Shader(std::string name) +Shader::Shader(Parser *p, const std::string &name) + : name(name) { auto vs_asset = asset_manager()->get_file(name, VERTEX_SHADER); auto fs_asset = asset_manager()->get_file(name, FRAGMENT_SHADER); if (vs_asset->type != ASSET_VOID) - this->vs_source = this->build_shader_source(vs_asset->as_string(), true); + build_shader_source(p, vs_asset->as_string(), vs_source, true); else log_error("failed to load shader file (%s)", name.c_str()); if (fs_asset->type != ASSET_VOID) - this->fs_source = this->build_shader_source(fs_asset->as_string(), true); + build_shader_source(p, fs_asset->as_string(), fs_source, true); else log_error("failed to load shader file (%s)", name.c_str()); } void Shader::bind(Engine *engine, mat4x4 *model) { - this->rshader->bind(); + rshader->bind(); - for (auto &uniform : this->uniforms) + for (auto &uniform : uniforms) { - if (uniform.uname.find('[') != std::string::npos) + if (uniform->uname.find('[') != std::string::npos) continue; - //std::cout << uniform.uname << " " << uniform.value[0] << "\n"; - this->rshader->set_uniform(uniform.uname, uniform.type, glm::value_ptr(uniform.value.value)); + //std::cout << uniform->uname << " " << uniform->value[0] << "\n"; + if (uniform->value != nullptr) + rshader->set_uniform(uniform->uname, uniform->type, glm::value_ptr(*uniform->value)); } - this->rshader->set_uniform("g_Time", TYPE_FLOAT, &engine->time); + rshader->set_uniform("g_Time", TYPE_FLOAT, &engine->time); - this->rshader->set_uniform("g_TexelSize", TYPE_VEC2, glm::value_ptr(engine->view.texel_size)); - this->rshader->set_uniform("g_TexelSizeHalf", TYPE_VEC2, glm::value_ptr(engine->view.texel_half_size)); + rshader->set_uniform("g_TexelSize", TYPE_VEC2, glm::value_ptr(engine->view.texel_size)); + rshader->set_uniform("g_TexelSizeHalf", TYPE_VEC2, glm::value_ptr(engine->view.texel_half_size)); - this->rshader->set_uniform("g_PointerPosition", TYPE_VEC2, glm::value_ptr(engine->view.cursor_pos)); + rshader->set_uniform("g_PointerPosition", TYPE_VEC2, glm::value_ptr(engine->view.cursor_pos)); mat4x4 _model, _inverse; @@ -217,14 +217,19 @@ void Shader::bind(Engine *engine, mat4x4 *model) _inverse = glm::inverse(_model); - this->rshader->set_uniform("g_ModelViewProjectionMatrix", TYPE_MAT4, glm::value_ptr(_model)); - this->rshader->set_uniform("g_ModelViewProjectionMatrixInverse", TYPE_MAT4, glm::value_ptr(_inverse)); + rshader->set_uniform("g_ModelViewProjectionMatrix", TYPE_MAT4, glm::value_ptr(_model)); + rshader->set_uniform("g_ModelViewProjectionMatrixInverse", TYPE_MAT4, glm::value_ptr(_inverse)); } Shader::~Shader() { - if (this->rshader) + if (rshader != nullptr) + { + delete rshader; + } + + for (auto &uniform : uniforms) { - delete this->rshader; + delete uniform; } } diff --git a/src/shader.h b/src/shader.h index a878d4f..eed4f80 100644 --- a/src/shader.h +++ b/src/shader.h @@ -14,28 +14,17 @@ namespace Mauri struct Uniform { - Uniform(std::string name, JsonValue value) - : name(name), value(value) - { - } - - Uniform(std::string name, std::string uname, UniformType type, JsonValue value) - : name(name), uname(uname), type(type), value(value) - { - } - std::string name; std::string uname; - UniformType type; - - JsonValue value; + vec4 *value = nullptr; + vec4 default_value; }; struct Combo { std::string name; - int value; + s32 value; std::string to_string(); }; @@ -44,15 +33,17 @@ class Engine; class Shader { public: - Shader(std::string name); + Shader(Parser *p, const std::string &name); ~Shader(); - std::vector uniforms; + std::string name; + + std::vector uniforms; std::vector combos; std::array textures; - int texture_count = 0; + u32 texture_count = 0; void bind(Engine *engine, mat4x4 *model); void compile(); @@ -63,7 +54,7 @@ class Shader RenderShader *rshader = nullptr; - std::string build_shader_source(std::string isource, bool root); + void build_shader_source(Parser *p, const std::string &isource, std::string &res, bool root); }; } // namespace Mauri diff --git a/src/texture.cc b/src/texture.cc index bd8996f..5367933 100644 --- a/src/texture.cc +++ b/src/texture.cc @@ -162,7 +162,7 @@ Texture::Texture(Asset *asset) asset->reset(); } -Texture::~Texture() +void Texture::unload() { if (!wrapped) delete texture; @@ -173,7 +173,8 @@ void Texture::bind(s32 index) texture->bind(index); } -Framebuffer::Framebuffer(f32 width, f32 height, f32 scale) +Framebuffer::Framebuffer(std::string name, f32 width, f32 height, f32 scale) + : name(name) { buffer = new RenderFramebuffer(width, height, scale); @@ -188,10 +189,14 @@ Framebuffer::Framebuffer(f32 width, f32 height, f32 scale) texture->texture_resolution[3] = buffer->height; } -Framebuffer::~Framebuffer() +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 52bf197..e12ad18 100644 --- a/src/texture.h +++ b/src/texture.h @@ -40,11 +40,9 @@ class Texture { public: Texture(Asset *asset); - Texture() - { - } + Texture() {} - ~Texture(); + ~Texture() {}; s32 width; s32 height; @@ -62,6 +60,8 @@ class Texture void load(Asset *asset); void bind(s32 index); + void unload(); + private: s32 texture_width; s32 texture_height; @@ -77,11 +77,16 @@ class Texture class Framebuffer { public: - Framebuffer(f32 width, f32 height, f32 scale); - ~Framebuffer(); + Framebuffer(std::string name, f32 width, f32 height, f32 scale); + + ~Framebuffer() {}; + + std::string name; Texture *texture; RenderFramebuffer *buffer; + + void unload(); }; } // namespace Mauri -- cgit v1.2.3-101-g0448