diff options
| -rw-r--r-- | meson.build | 6 | ||||
| -rw-r--r-- | src/assets.c | 16 | ||||
| -rw-r--r-- | src/context_glfw.c | 7 | ||||
| -rw-r--r-- | src/engine.c | 19 | ||||
| -rw-r--r-- | src/engine.h | 3 | ||||
| -rw-r--r-- | src/gl.c | 11 | ||||
| -rw-r--r-- | src/gl.h | 5 | ||||
| -rw-r--r-- | src/mauri.c | 4 | ||||
| -rw-r--r-- | src/objects/c | 1 | ||||
| -rw-r--r-- | src/objects/effect.c | 58 | ||||
| -rw-r--r-- | src/objects/effect.h | 10 | ||||
| -rw-r--r-- | src/objects/material.c | 13 | ||||
| -rw-r--r-- | src/objects/material.h | 3 | ||||
| -rw-r--r-- | src/objects/model.c | 4 | ||||
| -rw-r--r-- | src/objects/model.h | 2 | ||||
| -rw-r--r-- | src/objects/object.c | 59 | ||||
| -rw-r--r-- | src/objects/object.h | 4 | ||||
| -rw-r--r-- | src/objects/pass.c | 162 | ||||
| -rw-r--r-- | src/objects/pass.h | 9 | ||||
| -rw-r--r-- | src/objects/scene.c | 18 | ||||
| -rw-r--r-- | src/shader.c | 69 | ||||
| -rw-r--r-- | src/texture.c | 38 | ||||
| -rw-r--r-- | src/texture.h | 4 | ||||
| -rw-r--r-- | subprojects/stb_image/meson.build | 3 |
24 files changed, 317 insertions, 211 deletions
diff --git a/meson.build b/meson.build index 0a3f83b..e21a94b 100644 --- a/meson.build +++ b/meson.build @@ -8,13 +8,17 @@ if get_option('buildtype').startswith('debug') add_project_arguments('-D_DEBUG_', language : 'c') endif +add_project_arguments('-Wno-sign-compare', language : 'c') +add_project_arguments('-Wno-unused-but-set-variable', language : 'c') +add_project_arguments('-Wno-unused-parameter', language : 'c') + moro = subproject('moro').get_variable('moro') stbi = subproject('stb_image').get_variable('stbi') glad = subproject('glad').get_variable('glad') +jansson = dependency('jansson') lz4 = dependency('liblz4') cglm = dependency('cglm') -jansson = dependency('jansson') glfw = dependency('glfw3') deps = [jansson, cglm, lz4, moro, stbi, glad, glfw] diff --git a/src/assets.c b/src/assets.c index cd68bb8..1e18eb9 100644 --- a/src/assets.c +++ b/src/assets.c @@ -3,6 +3,7 @@ #include "log.h" #include "assets.h" +#include "moro_str.h" #include "moro_vec.h" #include "util.h" @@ -54,14 +55,14 @@ static void asset_from_path(mstr *path, mri_asset *asset) { fclose(asset_file); if (res != asset->size) { - //log_error("failed to read file (%s)", path); + log_error("failed to read file (%.*s)", MSTR_PRINTF(path)); free(asset->data); return; } } static void mri_asset_manager_init() { - asset_manager.pkg.type = ASSET_VOID; + memset(&asset_manager.pkg, 0, sizeof(mri_asset)); mvec_init(asset_manager.files); } @@ -71,7 +72,7 @@ bool mri_asset_manager_load_pkg(mstr *path) { asset_from_path(path, &asset_manager.pkg); if (asset_manager.pkg.type == ASSET_VOID) { - //log_error("failed to load pkg file: (%s)", path); + log_error("failed to load pkg file: (%.*s)", MSTR_PRINTF(path)); return false; } @@ -79,7 +80,7 @@ bool mri_asset_manager_load_pkg(mstr *path) { mri_asset_value(&asset_manager.pkg, int)); if (!mstr_eqn(&signature, mstr_c("PKGV"), 4)) { - //log_error("invalid pkg file: (%.*s)", path.len, path.ptr); + log_error("invalid pkg file: (%.*s)", MSTR_PRINTF(path)); return false; } @@ -102,12 +103,12 @@ bool mri_asset_manager_load_pkg(mstr *path) { mri_asset_ptr(&asset_manager.pkg) + file->offset, mri_asset_ptr(&asset_manager.pkg) + file->offset + file->length); - //log_debug("loaded file (%.*s)", mstr_expand(&file->path)); + log_debug("loaded file (%.*s)", MSTR_PRINTF(&file->path)); mvec_push(asset_manager.files, asset); } - //log_info("successfully loaded pkg file (%s)", path); + log_info("successfully loaded pkg file (%.*s)", MSTR_PRINTF(path)); free(pkg_files); @@ -155,8 +156,7 @@ mri_asset *mri_asset_manager_get(mstr *part, mri_file_type_hint hint) { asset = mvec_next(asset_manager.files); asset_from_path(path, asset); if (asset->type == ASSET_VOID) { - mvec_pop(asset_manager.files); - asset = &asset_void; + asset = &mvec_pop(asset_manager.files); } } diff --git a/src/context_glfw.c b/src/context_glfw.c index 6470205..d40b595 100644 --- a/src/context_glfw.c +++ b/src/context_glfw.c @@ -34,13 +34,10 @@ static bool create_window(mri_context *c, float width, float height, const char return false; } - glEnable(GL_MULTISAMPLE); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); + glEnable(GL_MULTISAMPLE); - //glDisable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/src/engine.c b/src/engine.c index 0cf7fe4..155dd85 100644 --- a/src/engine.c +++ b/src/engine.c @@ -1,6 +1,5 @@ #include "engine.h" -#include "cglm/vec4.h" #include "objects/object.h" #include "objects/scene.h" #include "src/context.h" @@ -28,11 +27,7 @@ void mri_engine_load(mri_engine *engine, mri_scene *scene) { engine->texel_half_size[1] = .5f / engine->height; engine->combine_buffer = mri_engine_get_or_new_framebuffer(engine, - mstr_c("_rt_FullFrameBuffer"), engine->context->width, engine->context->height, - 1.f, NULL); - - mri_shader_load(&engine->mininal_shader, mstr_c("minimal")); - mri_shader_compile(&engine->mininal_shader); + mstr_c("_rt_FullFrameBuffer"), engine->context->width, engine->context->height, 1.f); create_gl_object(&engine->default_gl_object, DEFAULT, 0, 0); } @@ -48,14 +43,14 @@ mri_framebuffer *mri_engine_get_framebuffer(mri_engine *engine, mstr *name) { } mri_framebuffer *mri_engine_get_or_new_framebuffer(mri_engine *engine, mstr *name, - float width, float height, float scale, vec4 clear_color) { + float width, float height, float scale) { mri_framebuffer *buffer = mri_engine_get_framebuffer(engine, name); if (!buffer) { buffer = mvec_next(engine->framebuffers); mri_framebuffer_create(buffer, name, width, height, scale); - mri_framebuffer_load(buffer, engine->scene->clear_color); + mri_framebuffer_load(buffer); } return buffer; @@ -67,10 +62,8 @@ void mri_engine_update(mri_engine *engine) { } void mri_engine_draw(mri_engine *engine) { - mri_framebuffer *buffer; - mvec_loop_ptr(engine->framebuffers, buffer, i) { - mri_framebuffer_bind(buffer, true); - } + mri_framebuffer_bind(engine->combine_buffer); + glClearBufferfv(GL_COLOR, 0, engine->scene->clear_color); mri_scene_draw(engine, engine->scene); @@ -85,13 +78,13 @@ void mri_engine_draw(mri_engine *engine) { void mri_engine_run(mri_engine *engine) { const float TARGET_FPS = 60.f; + float time = engine->context->current_time(engine->context); while (!engine->context->should_close(engine->context)) { mri_engine_update(engine); mri_engine_draw(engine); - while (engine->context->current_time(engine->context) < time + 1.f / TARGET_FPS) { usleep(2000); // 2ms } diff --git a/src/engine.h b/src/engine.h index 3a15a2f..95fccae 100644 --- a/src/engine.h +++ b/src/engine.h @@ -26,7 +26,6 @@ struct mri_engine { gl_object default_gl_object; mri_framebuffer *combine_buffer; - mri_shader mininal_shader; mvec(mri_framebuffer) framebuffers; @@ -37,7 +36,7 @@ void mri_engine_load(mri_engine *engine, mri_scene *scene); mri_framebuffer *mri_engine_get_framebuffer(mri_engine *engine, mstr *name); mri_framebuffer *mri_engine_get_or_new_framebuffer(mri_engine *engine, - mstr *name, float width, float height, float scale, vec4 clear_color); + mstr *name, float width, float height, float scale); void mri_engine_next_pass(mri_engine *engine); void mri_engine_next_effect(mri_engine *engine); @@ -55,14 +55,11 @@ void destroy_gl_texture(gl_texture *tex) { glDeleteTextures(1, &tex->id); } -void bind_gl_framebuffer(gl_framebuffer *buffer, bool clear) { +void bind_gl_framebuffer(gl_framebuffer *buffer) { glBindFramebuffer(GL_FRAMEBUFFER, buffer->id); - if (clear) { - glClearBufferfv(GL_COLOR, 0, buffer->clear_color); - } } -void create_gl_framebuffer(gl_framebuffer *buffer, float width, float height, vec4 clear_color) { +void create_gl_framebuffer(gl_framebuffer *buffer, float width, float height) { glGenFramebuffers(1, &buffer->id); glGenTextures(1, &buffer->texture.id); @@ -80,11 +77,9 @@ void create_gl_framebuffer(gl_framebuffer *buffer, float width, float height, ve glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer->texture.id, 0); - glm_vec4_copy(clear_color, buffer->clear_color); - glDrawBuffers(1, (GLenum[]){GL_COLOR_ATTACHMENT0}); - glClearBufferfv(GL_COLOR, 0, (vec4){1.f, 1.f, 1.f, 1.f}); + glClearBufferfv(GL_COLOR, 0, (vec4){0.f, 0.f, 0.f, 0.f}); } void destroy_gl_framebuffer(gl_framebuffer *buffer) { @@ -26,7 +26,6 @@ typedef struct { typedef struct { unsigned int id; gl_texture texture; - vec4 clear_color; } gl_framebuffer; typedef enum { @@ -44,8 +43,8 @@ void upload_gl_texture(gl_texture *tex, unsigned char *data, int width, int heig unsigned int format); void destroy_gl_texture(gl_texture *tex); -void bind_gl_framebuffer(gl_framebuffer *buffer, bool clear); -void create_gl_framebuffer(gl_framebuffer *buffer, float width, float height, vec4 clear_color); +void bind_gl_framebuffer(gl_framebuffer *buffer); +void create_gl_framebuffer(gl_framebuffer *buffer, float width, float height); void destroy_gl_framebuffer(gl_framebuffer *buffer); void create_gl_object(gl_object *obj, gl_obj_type type, float width, float height); diff --git a/src/mauri.c b/src/mauri.c index 8a8b2be..75d9d47 100644 --- a/src/mauri.c +++ b/src/mauri.c @@ -12,7 +12,9 @@ int main(int argc, char* argv[]) { context->create_window(context, 1920, 1080, "mauri", false); if (argc == 2) { - mri_asset_manager_load_pkg(mstr_c(argv[1])); + if (!mri_asset_manager_load_pkg(mstr_c(argv[1]))) { + return 1; + } mri_scene scene = {0}; mri_scene_parse(&scene); diff --git a/src/objects/c b/src/objects/c deleted file mode 100644 index 8b13789..0000000 --- a/src/objects/c +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/objects/effect.c b/src/objects/effect.c index 1bc0726..cb37281 100644 --- a/src/objects/effect.c +++ b/src/objects/effect.c @@ -5,6 +5,8 @@ #include "../log.h" #include "cglm/mat4.h" +#include "moro_str.h" +#include "moro_vec.h" #include "src/objects/pass.h" #include "src/objects/types.h" #include <jansson.h> @@ -14,6 +16,8 @@ void mri_effect_parse(mri_effect *effect, json_t *root) { mvec_init(effect->passes0); mvec_init(effect->passes1); + json_get_int(&effect->id, root, "id"); + json_t *pass0; json_t *passes0 = json_object_get(root, "passes"); json_array(pass0, passes0) { @@ -36,6 +40,18 @@ void mri_effect_parse(mri_effect *effect, json_t *root) { json_array(pass1, passes1) { mri_pass_parse(mvec_next(effect->passes1), pass1, EFFECT1_PASS); } + + mvec_init(effect->fbos); + + json_t *fbo; + json_t *fbos = json_object_get(_root, "fbos"); + json_array(fbo, fbos) { + mri_effect_buffer buffer = { + .name = mstr_from(json_string_value(json_object_get(fbo, "name"))), + .scale = json_number_value(json_object_get(fbo, "scale")) + }; + mvec_push(effect->fbos, buffer); + } } } @@ -46,19 +62,35 @@ mri_render_pass *mri_effect_next_pass(mri_effect *effect) { return pass; } -void mri_effect_load(mri_engine *engine, mri_effect *effect) { +void mri_effect_load(mri_engine *engine, mri_effect *effect, bool last_effect) { + mri_effect_buffer *buffer; + mvec_loop_ptr(effect->fbos, buffer, i) { + mri_object *object = engine->current_object; + + mstr *effect_buffer_id = mstr_sprintf("%i_%i", effect->id, object->id); + mstr_cat(buffer->name, effect_buffer_id); + mstr_free(effect_buffer_id); + + mri_engine_get_or_new_framebuffer(engine, buffer->name, + object->size[0], object->size[1], buffer->scale); + } + for (unsigned int i = 0; i < mvec_size(effect->passes0); i++) { mri_render_pass *pass = mri_effect_next_pass(effect); - if (i == mvec_size(effect->passes0) - 1) { - pass->combine = true; - } - pass->object = engine->current_object; - pass->gl_object = &engine->default_gl_object; + pass->effect = effect; - glm_mat4_identity(pass->model); + pass->combine = (i == mvec_size(effect->passes0) - 1) && last_effect; + if (pass->combine) { + pass->gl_object = &engine->current_object->gl_object; + glm_mat4_copy(engine->current_object->model, pass->model); + } else { + pass->gl_object = &engine->default_gl_object; + glm_mat4_identity(pass->model); + } + mri_pass_load(engine, mvec_at(effect->passes0, i), EFFECT0_PASS, pass); mri_pass_load(engine, mvec_at(effect->passes1, i), EFFECT1_PASS, pass); } @@ -67,8 +99,8 @@ void mri_effect_load(mri_engine *engine, mri_effect *effect) { void mri_effect_draw(mri_engine *engine, mri_effect *effect) { mri_render_pass *pass; mvec_loop_ptr(effect->passes, pass, i) { - log_debug("effect (%.*s): %.*s %i", pass->object->name->len, pass->object->name->ptr, - effect->name->len, effect->name->ptr, i + 1); + //log_debug("effect (%.*s): %.*s %i", pass->object->name->len, pass->object->name->ptr, + // effect->name->len, effect->name->ptr, i + 1); mri_render_pass_draw(engine, pass); } } @@ -88,4 +120,12 @@ void mri_effect_unload(mri_effect *effect) { mvec_free(effect->passes0); mvec_free(effect->passes1); + + mri_effect_buffer *buffer; + mvec_loop_ptr(effect->fbos, buffer, i) { + if (buffer->name) + mstr_free(buffer->name); + } + + mvec_free(effect->fbos); } diff --git a/src/objects/effect.h b/src/objects/effect.h index 9570fde..374a39f 100644 --- a/src/objects/effect.h +++ b/src/objects/effect.h @@ -6,16 +6,24 @@ #include "types.h" #include "pass.h" +typedef struct { + mstr *name; + float scale; +} mri_effect_buffer; + struct mri_effect { mstr *name; + int id; mvec(mri_pass) passes0; mvec(mri_pass) passes1; mvec(mri_render_pass) passes; + + mvec(mri_effect_buffer) fbos; }; void mri_effect_parse(mri_effect *effect, json_t *root); -void mri_effect_load(mri_engine *engine, mri_effect *effect); +void mri_effect_load(mri_engine *engine, mri_effect *effect, bool last_effect); void mri_effect_draw(mri_engine *engine, mri_effect *effect); void mri_effect_unload(mri_effect *effect); diff --git a/src/objects/material.c b/src/objects/material.c index c340463..75422d1 100644 --- a/src/objects/material.c +++ b/src/objects/material.c @@ -39,7 +39,7 @@ mri_render_pass *mri_material_next_pass(mri_material *material) { } void mri_material_load(mri_engine *engine, mri_material *material, mri_material_type t, - mri_render_pass *pass) { + mri_render_pass *pass, bool no_effects) { mri_pass *pass0; mvec_loop_ptr(material->passes0, pass0, i) { switch (t) { @@ -50,15 +50,20 @@ void mri_material_load(mri_engine *engine, mri_material *material, mri_material_ pass = mri_material_next_pass(material); pass->object = engine->current_object; + pass->combine = no_effects; - if (engine->current_object->passthrough) { - pass->gl_object = &engine->current_object->gl_object; + if (engine->current_object->passthrough || no_effects) { glm_mat4_copy(engine->current_object->model, pass->model); } else { - pass->gl_object = &engine->current_object->gl_uv_object; glm_mat4_copy(engine->current_object->ortho, pass->model); } + if (engine->current_object->passthrough) { + pass->gl_object = &engine->current_object->gl_object; + } else { + pass->gl_object = &engine->current_object->gl_uv_object; + } + mri_pass_load(engine, pass0, MATERIAL_ONLY_PASS, pass); break; } diff --git a/src/objects/material.h b/src/objects/material.h index 5c8f7b5..e8bc13d 100644 --- a/src/objects/material.h +++ b/src/objects/material.h @@ -17,7 +17,8 @@ struct mri_material { }; void mri_material_parse(mri_material *material, json_t *value); -void mri_material_load(mri_engine *engine, mri_material *material, mri_material_type t, mri_render_pass *pass); +void mri_material_load(mri_engine *engine, mri_material *material, mri_material_type t, mri_render_pass *pass, + bool no_effects); void mri_material_draw(mri_engine *engine, mri_material *material); void mri_material_unload(mri_material *material); diff --git a/src/objects/model.c b/src/objects/model.c index 81cd0b0..45317f2 100644 --- a/src/objects/model.c +++ b/src/objects/model.c @@ -30,8 +30,8 @@ void mri_model_parse(mri_model *model, json_t *value) { } } -void mri_model_load(mri_engine *engine, mri_model *model) { - mri_material_load(engine, &model->material, MATERIAL_MODEL, NULL); +void mri_model_load(mri_engine *engine, mri_model *model, bool no_effects) { + mri_material_load(engine, &model->material, MATERIAL_MODEL, NULL, no_effects); } void mri_model_draw(mri_engine *engine, mri_model *model) { diff --git a/src/objects/model.h b/src/objects/model.h index 4d17c72..9daed21 100644 --- a/src/objects/model.h +++ b/src/objects/model.h @@ -15,7 +15,7 @@ struct mri_model { }; void mri_model_parse(mri_model *model, json_t *value); -void mri_model_load(mri_engine *engine, mri_model *model); +void mri_model_load(mri_engine *engine, mri_model *model, bool no_effects); void mri_model_draw(mri_engine *engine, mri_model *model); void mri_model_unload(mri_model *model); diff --git a/src/objects/object.c b/src/objects/object.c index d525d3a..6a67bea 100644 --- a/src/objects/object.c +++ b/src/objects/object.c @@ -84,22 +84,17 @@ void mri_object_load(mri_engine *engine, mri_object *object) { float width = object->size[0]; float height = object->size[1]; - // mstr_sprintf - char *abuffer, *bbuffer; - - asprintf(&abuffer, "_rt_imageLayerComposite_%i_a", object->id); - asprintf(&bbuffer, "_rt_imageLayerComposite_%i_b", object->id); + mstr *abuffer = mstr_sprintf("_rt_imageLayerComposite_%i_a", object->id); + mstr *bbuffer = mstr_sprintf("_rt_imageLayerComposite_%i_b", object->id); object->abuffer = mri_engine_get_or_new_framebuffer(engine, - mstr_c(abuffer), width, height, 1.f, - engine->scene->clear_color); + abuffer, width, height, 1.f); object->bbuffer = mri_engine_get_or_new_framebuffer(engine, - mstr_c(bbuffer), width, height, 1.f, - engine->scene->clear_color); + bbuffer, width, height, 1.f); - free(abuffer); - free(bbuffer); + mstr_free(abuffer); + mstr_free(bbuffer); object->buffer_switch = false; @@ -115,7 +110,7 @@ void mri_object_load(mri_engine *engine, mri_object *object) { create_gl_object(&engine->current_object->gl_object, OBJECT, width, height); - mri_model_load(engine, &object->image); + mri_model_load(engine, &object->image, mvec_size(object->effects) == 0); if (object->image.fullscreen) { object->fullscreen = true; @@ -131,23 +126,20 @@ void mri_object_load(mri_engine *engine, mri_object *object) { mri_effect *effect; mvec_loop_ptr(object->effects, effect, i) { - mri_effect_load(engine, effect); + mri_effect_load(engine, effect, i == (mvec_size(object->effects) - 1)); } } -static void center_scale(float w0, float h0, float w1, float h1) { - float w_scale = w1 / w0; - float h_scale = h1 / h0; - - float scale = (w_scale > h_scale) ? w_scale : h_scale; - - float width = w0 * scale; - float height = h0 * scale; +void mri_object_switch_buffer(mri_object *object) { + object->buffer_switch = !object->buffer_switch; +} - float wpad = (width - w1) / -2.f; - float hpad = (height - h1) / -2.f; +mri_framebuffer *mri_object_get_target_buffer(mri_object *object) { + return (object->buffer_switch) ? object->abuffer : object->bbuffer; +} - glViewport(wpad, hpad, width, height); +mri_texture *mri_object_get_texture_buffer(mri_object *object) { + return &((object->buffer_switch) ? object->bbuffer : object->abuffer)->texture; } void mri_object_draw(mri_engine *engine, mri_object *object) { @@ -157,25 +149,6 @@ void mri_object_draw(mri_engine *engine, mri_object *object) { mvec_loop_ptr(object->effects, effect, i) { mri_effect_draw(engine, effect); } - - mri_framebuffer_bind(engine->combine_buffer, false); - - if (object->buffer_switch) { - mri_texture_bind(&object->bbuffer->texture, 0); - } else { - mri_texture_bind(&object->abuffer->texture, 0); - } - - mri_shader_bind(engine, &engine->mininal_shader, object->model); - - bind_gl_object(&object->gl_object); - - center_scale(engine->width, engine->height, engine->context->width, engine->context->height); - - glDrawArrays(GL_TRIANGLES, 0, 6); - - - //log_debug("combine (%.*s)", object->name->len, object->name->ptr); } void mri_object_unload(mri_object *object) { diff --git a/src/objects/object.h b/src/objects/object.h index c7bb883..6431237 100644 --- a/src/objects/object.h +++ b/src/objects/object.h @@ -62,6 +62,10 @@ struct mri_object { void mri_object_get_model(mri_object *object, mat4 model, float width, float height); +void mri_object_switch_buffer(mri_object *object); +mri_framebuffer *mri_object_get_target_buffer(mri_object *object); +mri_texture *mri_object_get_texture_buffer(mri_object *object); + void mri_object_parse(mri_object *object, json_t *root); void mri_object_load(mri_engine *engine, mri_object *object); void mri_object_draw(mri_engine *engine, mri_object *object); diff --git a/src/objects/pass.c b/src/objects/pass.c index e5604e6..4820065 100644 --- a/src/objects/pass.c +++ b/src/objects/pass.c @@ -2,6 +2,7 @@ #include <unistd.h> #include "moro_str.h" +#include "moro_vec.h" #include "pass.h" #include "material.h" #include "model.h" @@ -13,8 +14,8 @@ #include "../engine.h" #include "../assets.h" #include "../gl.h" -#include "src/objects/types.h" -#include "src/shader.h" +#include "../objects/types.h" +#include "../shader.h" void mri_pass_parse(mri_pass *pass, json_t *root, mri_pass_stage stage) { memset(pass, 0, sizeof(mri_pass)); @@ -76,6 +77,16 @@ void mri_pass_parse(mri_pass *pass, json_t *root, mri_pass_stage stage) { pass->shader = (mri_shader *)calloc(1, sizeof(mri_shader)); mri_shader_load(pass->shader, mstr_c(json_string_value(shader))); } + + json_t *blend = json_object_get(root, "blending"); + if (json_is_string(blend)) { + if (mstr_eq(mstr_c(json_string_value(blend)), mstr_c("normal"))) { + pass->blend = NORMAL; + } else if (mstr_eq(mstr_c(json_string_value(blend)), mstr_c("translucent"))) { + pass->blend = TRANSLUCENT; + } + } + break; } } @@ -119,7 +130,7 @@ void mri_pass_parse(mri_pass *pass, json_t *root, mri_pass_stage stage) { void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage, mri_render_pass *rpass) { mri_object *object = engine->current_object; - for (int i = 1; i < 7; i++) { + for (int i = 0; i < 7; i++) { if (pass->textures[i]) rpass->textures[i] = pass->textures[i]; } @@ -138,57 +149,59 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage, mri } case EFFECT1_PASS: // If there is an explicit target framebuffer, set it. - if (pass->target) { - rpass->target = mri_engine_get_or_new_framebuffer(engine, - pass->target, engine->width, engine->height, 2.f, - (vec4){0.f, 0.f, 0.f, 0.4f}); - } else { - // If no target was specified pick the next buffer in the - // alternating AB buffers. - if (object->buffer_switch) { - rpass->target = object->abuffer; - rpass->textures[0] = &object->bbuffer->texture; + if (!pass->target) { + if (rpass->combine) { + rpass->target = engine->combine_buffer; } else { - rpass->target = object->bbuffer; - rpass->textures[0] = &object->abuffer->texture; + // If no target was specified pick the next buffer in the + // alternating AB buffers. + rpass->target = mri_object_get_target_buffer(object); } + rpass->textures[0] = mri_object_get_texture_buffer(object); + } else { + mstr *effect_buffer_id = mstr_sprintf("%i_%i", rpass->effect->id, rpass->object->id); + mstr_cat(pass->target, effect_buffer_id); + mstr_free(effect_buffer_id); + + rpass->target = mri_engine_get_framebuffer(engine, pass->target); } + for (int i = 0; i < 7; i++) { if (!pass->binds[i]) continue; // If there are explicit binds given for this pass, set them. if (mstr_eq(pass->binds[i], mstr_c("previous"))) { - if (object->buffer_switch) { - rpass->textures[i] = &object->bbuffer->texture; - } else { - rpass->textures[i] = &object->abuffer->texture; - } + rpass->textures[i] = mri_object_get_texture_buffer(object); } else { + mstr *effect_buffer_id = mstr_sprintf("%i_%i", rpass->effect->id, rpass->object->id); + mstr_cat(pass->binds[i], effect_buffer_id); + mstr_free(effect_buffer_id); + rpass->textures[i] = &mri_engine_get_framebuffer(engine, pass->binds[i])->texture; } } - // If we selected one of the AB buffers, switch the flag after + + // If we selected one of the AB buffers, switch the flag _after_ // setting binds to keep the ordering correct. - if (!pass->target) - object->buffer_switch = !object->buffer_switch; - mri_material_load(engine, pass->material, MATERIAL_EFFECT, rpass); + if (!pass->target) mri_object_switch_buffer(object); + + // EFFECT1 passes has the material with the final draw passes. + mri_material_load(engine, pass->material, MATERIAL_EFFECT, rpass, false); break; - case MATERIAL_ONLY_PASS: - // This object has no effects so Texture0 is an image and draw on the A buffer. - rpass->target = object->abuffer; - rpass->textures[0] = pass->textures[0]; + case MATERIAL_ONLY_PASS: + // There is no EFFECT1 pass before this to set the target, so set it here. + if (rpass->combine) { + rpass->target = engine->combine_buffer; + } else { + rpass->target = mri_object_get_target_buffer(object); + mri_object_switch_buffer(object); + } + rpass->combine_blend = pass->blend; + __attribute__ ((fallthrough)); case MATERIAL_PASS: { - memcpy(&rpass->shader, pass->shader, sizeof(mri_shader)); + rpass->shader = *pass->shader; - // mvec_clone - mvec_ptr(rpass->shader.uniforms) = (mri_uniform *)malloc( - sizeof(mri_uniform) * mvec_alloc(pass->shader->uniforms)); - memcpy(mvec_ptr(rpass->shader.uniforms), mvec_ptr(pass->shader->uniforms), - sizeof(mri_uniform) * mvec_alloc(pass->shader->uniforms)); - - mvec_ptr(rpass->shader.combos) = (mri_combo *)malloc( - sizeof(mri_combo) * mvec_alloc(pass->shader->combos)); - memcpy(mvec_ptr(rpass->shader.combos), mvec_ptr(pass->shader->combos), - sizeof(mri_combo) * mvec_alloc(pass->shader->combos)); + mvec_clone(rpass->shader.uniforms, pass->shader->uniforms); + mvec_clone(rpass->shader.combos, pass->shader->combos); for (int i = 0; i < 7; i++) { // As the last step for shaders, set any unset texture slots @@ -196,7 +209,8 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage, mri if (!rpass->textures[i] && rpass->shader.textures[i]) { rpass->textures[i] = rpass->shader.textures[i]; } - // Set TEX0FORMAT incase extra steps are needed when sampling, + + // Set TEX0FORMAT in-case extra steps are needed when sampling, // see "common_fragment.h". if (rpass->textures[i] && i == 0) { mri_combo c = { @@ -262,8 +276,27 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage, mri } } +static void viewport_center_scale(float w0, float h0, float w1, float h1) { + float w_scale = w1 / w0; + float h_scale = h1 / h0; + + float scale = (w_scale > h_scale) ? w_scale : h_scale; + + float width = w0 * scale; + float height = h0 * scale; + + float wpad = (width - w1) / -2.f; + float hpad = (height - h1) / -2.f; + + glViewport(wpad, hpad, width, height); +} + +static void viewport_default(float w0, float h0) { + glViewport(0, 0, w0, h0); +} + void mri_render_pass_draw(mri_engine *engine, mri_render_pass *pass) { - mri_framebuffer_bind(pass->target, false); + mri_framebuffer_bind(pass->target); mri_shader_bind(engine, &pass->shader, pass->model); bind_gl_object(pass->gl_object); @@ -272,27 +305,50 @@ void mri_render_pass_draw(mri_engine *engine, mri_render_pass *pass) { if (pass->textures[i]) mri_texture_bind(pass->textures[i], i); } - glViewport(0, 0, pass->target->width, pass->target->height); - glDrawArrays(GL_TRIANGLES, 0, 6); + mri_pass_blend_mode blend; + if (pass->combine) { + blend = pass->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; + } + + if (pass->combine) { + viewport_center_scale(engine->width, engine->height, engine->context->width, engine->context->height); + } else { + viewport_default(pass->target->width, pass->target->height); + } + + glDrawArrays(GL_TRIANGLES, 0, 6); + for (int i = 0; i < pass->shader.texture_count; i++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, 0); } - if (0) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBindFramebuffer(GL_READ_FRAMEBUFFER, pass->target->buffer.id); +#if 0 + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, pass->target->buffer.id); - // Drawing past the dimensions of the read buffer is an error. - glBlitFramebuffer(0, engine->context->height, engine->context->width, 0, 0, 0, - engine->context->width, engine->context->height, - GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, engine->context->height, engine->context->width, 0, 0, 0, + engine->context->width, engine->context->height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); - engine->context->swap_buffers(engine->context); + engine->context->swap_buffers(engine->context); - usleep(5000000); - } + usleep(1400000); +#endif } void mri_pass_unload(mri_pass *pass) { diff --git a/src/objects/pass.h b/src/objects/pass.h index 37c0997..64947c9 100644 --- a/src/objects/pass.h +++ b/src/objects/pass.h @@ -25,6 +25,10 @@ typedef enum { PASS, } mri_render_pass_stage; +typedef enum { + TRANSLUCENT, + NORMAL +} mri_pass_blend_mode; struct mri_pass { int id; @@ -37,6 +41,8 @@ struct mri_pass { mstr *target; mstr *binds[7]; + mri_pass_blend_mode blend; + mvec(mri_uniform) uniforms; mvec(mri_combo) combos; }; @@ -45,6 +51,7 @@ struct mri_render_pass { mri_shader shader; mri_object *object; + mri_effect *effect; mat4 model; gl_object *gl_object; @@ -54,6 +61,8 @@ struct mri_render_pass { bool combine; + mri_pass_blend_mode combine_blend; + mri_render_pass_stage stage; mvec(mri_uniform) uniforms; diff --git a/src/objects/scene.c b/src/objects/scene.c index e320acf..62c70b2 100644 --- a/src/objects/scene.c +++ b/src/objects/scene.c @@ -82,15 +82,15 @@ void mri_scene_load(mri_engine *engine, mri_scene *scene) { void mri_scene_draw(mri_engine *engine, mri_scene *scene) { mri_object *object; mvec_loop_ptr(scene->objects, object, i) { - int dep; - mvec_loop(object->deps, dep, s) { - mri_object *dep_object; - mvec_loop_ptr(scene->objects, dep_object, j) { - if (dep_object->id == dep) { - mri_object_draw(engine, dep_object); - } - } - } + //int dep; + //mvec_loop(object->deps, dep, s) { + // mri_object *dep_object; + // mvec_loop_ptr(scene->objects, dep_object, j) { + // if (dep_object->id == dep) { + // mri_object_draw(engine, dep_object); + // } + // } + //} mri_object_draw(engine, object); } } diff --git a/src/shader.c b/src/shader.c index 3df4a21..b054cbb 100644 --- a/src/shader.c +++ b/src/shader.c @@ -6,6 +6,7 @@ #include <moro.h> +#include "moro_str.h" #include "shader.h" #include "assets.h" #include "json.h" @@ -36,11 +37,11 @@ static const char *gl_compat = static const char *version = "#version 120\n"; -static mstr *build_shader_source(mri_shader *shader, mstr *isource, bool start) { +static mstr *build_shader_source(mri_shader *shader, mstr *isource, bool root) { mstr *source = mstr_from("\0"); - if (start) - mstr_cat(source, mstr_c(gl_compat)); + // Append compatablity macros once per shader + if (root) mstr_cat(source, mstr_c(gl_compat)); mstr line = {0}; @@ -81,23 +82,36 @@ static mstr *build_shader_source(mri_shader *shader, mstr *isource, bool start) json_t *root = json_load_mstr(&combo_str); - if (!root) continue; + if (!root) { + log_error("err: failed to load the combo for (%.*s)", MSTR_PRINTF(u->uname)); + continue; + } + // If material is present, it's always used to reference this + // uniform for setting its values. If material is not present, + // label is used. json_t *label = json_object_get(root, "label"); json_t *material = json_object_get(root, "material"); - if (json_is_string(material)) + if (json_is_string(material)) { u->name = mstr_clone(mstr_c(json_string_value(material))); - else if (json_is_string(label)) + } else if (json_is_string(label)) { u->name = mstr_clone(mstr_c(json_string_value(label))); + } switch (u->type) { case TYPE_SAMPLER2D: { + int index = (int)u->value[0]; + json_t *texture = json_object_get(root, "default"); if (json_is_string(texture)) { - mri_asset *_a = mri_asset_manager_get(mstr_c(json_string_value(texture)), TEXTURE); - shader->textures[(int)u->value[0]] = mri_texture_load(_a); + mstr *path = mstr_c(json_string_value(texture)); + shader->textures[index] = mri_texture_load( + mri_asset_manager_get(path, TEXTURE)); } + + // NOTE: I assume the only case where this is wrong would + // be if "combo" is present and not "default". json_t *combo = json_object_get(root, "combo"); if (json_is_string(combo)) { mri_combo c = { @@ -106,6 +120,7 @@ static mstr *build_shader_source(mri_shader *shader, mstr *isource, bool start) }; mvec_push(shader->combos, c); } + break; } case TYPE_FLOAT: @@ -133,12 +148,22 @@ static mstr *build_shader_source(mri_shader *shader, mstr *isource, bool start) json_t *root = json_load_mstr(&combo); - mri_combo c = { - .name = mstr_from(json_string_value(json_object_get(root, "combo"))), - .value = json_integer_value(json_object_get(root, "default")) - }; + if (!root) { + log_error("%s", "err: failed to load [COMBO]"); + continue; + } + + json_t *_combo = json_object_get(root, "combo"); + json_t *_value = json_object_get(root, "default"); - mvec_push(shader->combos, c); + if (json_is_string(_combo) && json_is_integer(_value)) { + mri_combo c = { + .name = mstr_from(json_string_value(_combo)), + .value = json_integer_value(_value) + }; + + mvec_push(shader->combos, c); + } json_decref(root); } @@ -152,11 +177,9 @@ static mstr *build_shader_source(mri_shader *shader, mstr *isource, bool start) return source; } -static char *mri_combo_to_str(mri_combo *combo) { - char *combo_str; - asprintf(&combo_str, "#define %.*s %i\n", (int)combo->name->len, +static mstr *mri_combo_to_str(mri_combo *combo) { + return mstr_sprintf("#define %.*s %i\n", (int)combo->name->len, combo->name->ptr, combo->value); - return combo_str; } void mri_shader_compile(mri_shader *shader) { @@ -165,10 +188,10 @@ void mri_shader_compile(mri_shader *shader) { mri_combo *combo; mvec_loop_ptr(shader->combos, combo, i) { - char *combo_str = mri_combo_to_str(combo); - mstr_prepend(vs_source, mstr_c(combo_str)); - mstr_prepend(fs_source, mstr_c(combo_str)); - free(combo_str); + mstr *combo_str = mri_combo_to_str(combo); + mstr_prepend(vs_source, combo_str); + mstr_prepend(fs_source, combo_str); + mstr_free(combo_str); } mstr_prepend(vs_source, mstr_c(version)); @@ -195,7 +218,7 @@ void mri_shader_load(mri_shader *shader, mstr *name) { if (vs_asset->type != ASSET_VOID) { shader->vs_source = build_shader_source(shader, mri_asset_as_str(vs_asset), true); } else { - log_error("failed to load shader file (%.*s.vert)", name->len, name->ptr); + log_error("failed to load shader file (%.*s.vert)", MSTR_PRINTF(name)); } mri_asset *fs_asset = mri_asset_manager_get(name, FRAGMENT_SHADER); @@ -203,7 +226,7 @@ void mri_shader_load(mri_shader *shader, mstr *name) { if (fs_asset->type != ASSET_VOID) { shader->fs_source = build_shader_source(shader, mri_asset_as_str(fs_asset), true); } else { - log_error("failed to load shader file (%.*s.frag)", name->len, name->ptr); + log_error("failed to load shader file (%.*s.frag)", MSTR_PRINTF(name)); } } diff --git a/src/texture.c b/src/texture.c index edc81a0..29f6cab 100644 --- a/src/texture.c +++ b/src/texture.c @@ -18,26 +18,27 @@ static unsigned char *load_image_rgba(unsigned char *data, int len) { return stbi_load_from_memory(data, len, &w, &h, &channels, 4); } -static uint32_t rgba_to_brga(uint32_t x) { - return ((x) & 0xff00ff00) | - ((x >> 16) & 0xFF) | - ((x << 16) & 0xFF0000); -} - -static uint32_t argb_to_brga(uint32_t x) { - return ((x & 0xFF000000) >> 24) | //______AA - ((x & 0x00FF0000) >> 8) | //____RR__ - ((x & 0x0000FF00) << 8) | //__GG____ - ((x & 0x000000FF) << 24); -} +//static uint32_t rgba_to_brga(uint32_t x) { +// return ((x) & 0xff00ff00) | +// ((x >> 16) & 0xFF) | +// ((x << 16) & 0xFF0000); +//} +// +//static uint32_t argb_to_brga(uint32_t x) { +// return ((x & 0xFF000000) >> 24) | //______AA +// ((x & 0x00FF0000) >> 8) | //____RR__ +// ((x & 0x0000FF00) << 8) | //__GG____ +// ((x & 0x000000FF) << 24); +//} mri_texture *mri_texture_load(mri_asset *asset) { // check if texture was previously loaded mri_texture *t = (mri_texture *)malloc(sizeof(mri_texture)); - mstr type = mri_asset_str(asset, 9); - mstr itype = mri_asset_str(asset, 9); + //mstr type = mri_asset_str(asset, 9); + //mstr itype = mri_asset_str(asset, 9); + mri_asset_seek(asset, 18); t->format = (mri_texture_format)mri_asset_value(asset, unsigned int); @@ -159,7 +160,6 @@ void mri_texture_bind(mri_texture *t, int index) { bind_gl_texture(&t->texture, index); } - void mri_framebuffer_create(mri_framebuffer *buffer, mstr *name, float width, float height, float scale) { buffer->name = mstr_clone(name); @@ -172,8 +172,8 @@ void mri_framebuffer_create(mri_framebuffer *buffer, mstr *name, float width, fl buffer->texture.texture_resolution[3] = buffer->height; } -void mri_framebuffer_load(mri_framebuffer *buffer, vec4 clear_color) { - create_gl_framebuffer(&buffer->buffer, buffer->width, buffer->height, clear_color); +void mri_framebuffer_load(mri_framebuffer *buffer) { + create_gl_framebuffer(&buffer->buffer, buffer->width, buffer->height); buffer->texture.texture.id = buffer->buffer.texture.id; } @@ -183,8 +183,8 @@ void mri_framebuffer_unload(mri_framebuffer *buffer) { //free(buffer); } -void mri_framebuffer_bind(mri_framebuffer *buffer, bool clear) { - bind_gl_framebuffer(&buffer->buffer, clear); +void mri_framebuffer_bind(mri_framebuffer *buffer) { + bind_gl_framebuffer(&buffer->buffer); } diff --git a/src/texture.h b/src/texture.h index 68211b4..0ed692f 100644 --- a/src/texture.h +++ b/src/texture.h @@ -61,8 +61,8 @@ void mri_texture_unload(mri_texture *texture); void mri_texture_bind(mri_texture *t, int index); void mri_framebuffer_create(mri_framebuffer *buffer, mstr *name, float width, float height, float scale); -void mri_framebuffer_load(mri_framebuffer *buffer, vec4 clear_color); +void mri_framebuffer_load(mri_framebuffer *buffer); void mri_framebuffer_unload(mri_framebuffer *buffer); -void mri_framebuffer_bind(mri_framebuffer *buffer, bool clear); +void mri_framebuffer_bind(mri_framebuffer *buffer); #endif // _TEXTURE_H diff --git a/subprojects/stb_image/meson.build b/subprojects/stb_image/meson.build index 0f7515f..6a1e2ad 100644 --- a/subprojects/stb_image/meson.build +++ b/subprojects/stb_image/meson.build @@ -1,5 +1,4 @@ project('stb_image', 'c') -stbi_inc = include_directories('.') -stbi = declare_dependency(include_directories: stbi_inc) +stbi = declare_dependency(include_directories: include_directories('.')) |