diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | TODO | 4 | ||||
| -rw-r--r-- | src/engine.c | 187 | ||||
| -rw-r--r-- | src/engine.h | 40 | ||||
| -rw-r--r-- | src/gl.c | 11 | ||||
| -rw-r--r-- | src/gl.h | 3 | ||||
| -rw-r--r-- | src/mauri.c | 3 | ||||
| -rw-r--r-- | src/objects/effect.c | 47 | ||||
| -rw-r--r-- | src/objects/effect.h | 4 | ||||
| -rw-r--r-- | src/objects/material.c | 45 | ||||
| -rw-r--r-- | src/objects/material.h | 6 | ||||
| -rw-r--r-- | src/objects/model.c | 9 | ||||
| -rw-r--r-- | src/objects/model.h | 3 | ||||
| -rw-r--r-- | src/objects/object.c | 112 | ||||
| -rw-r--r-- | src/objects/object.h | 16 | ||||
| -rw-r--r-- | src/objects/pass.c | 115 | ||||
| -rw-r--r-- | src/objects/pass.h | 48 | ||||
| -rw-r--r-- | src/objects/scene.c | 22 | ||||
| -rw-r--r-- | src/objects/scene.h | 4 | ||||
| -rw-r--r-- | src/objects/types.h | 4 | ||||
| -rw-r--r-- | src/shader.c | 21 | ||||
| -rw-r--r-- | src/shader.h | 2 | ||||
| -rw-r--r-- | src/texture.c | 19 | ||||
| -rw-r--r-- | src/texture.h | 5 |
24 files changed, 434 insertions, 298 deletions
@@ -1,2 +1,4 @@ build*/ random.sh +compile_commands.json +.clangd/ @@ -1,2 +1,2 @@ -[ ] shader loading -[ ] store uniform location on the uniform object +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 diff --git a/src/engine.c b/src/engine.c index cf78ee1..537e5f5 100644 --- a/src/engine.c +++ b/src/engine.c @@ -2,88 +2,19 @@ #include "objects/object.h" #include "objects/scene.h" +#include "src/objects/types.h" +#include "src/shader.h" +#include "src/texture.h" +#include <unistd.h> #include <cglm/cglm.h> -typedef enum { - BACKGROUND, - BACKGROUND_ONLY, - TRANSFORM, - COMBINE, - PASS -} render_pass_stage; - -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; - - float wpad = (width - w1) / -2.f; - float hpad = (height - h1) / -2.f; - - glViewport(wpad, hpad, width, height); -} - -static void draw_pass(mri_engine *engine, render_pass_stage s, mri_render_pass *pass, - mri_render_object *object) { - switch (s) { - case BACKGROUND_ONLY: - mri_framebuffer_bind(engine->combine_buffer, false); - mri_shader_bind(engine, &pass->shader, object->ortho); - bind_gl_object(&object->gl_uv_object); - break; - case BACKGROUND: - mri_framebuffer_bind(pass->target, true); - if (object->object->passthrough) { - mri_shader_bind(engine, &pass->shader, object->model); - bind_gl_object(&object->gl_object); - } else { - mri_shader_bind(engine, &pass->shader, object->ortho); - bind_gl_object(&object->gl_uv_object); - } - break; - case PASS: - mri_framebuffer_bind(pass->target, true); - mri_shader_bind(engine, &pass->shader, NULL); - bind_gl_object(&engine->default_gl_object); - break; - case TRANSFORM: - mri_framebuffer_bind(pass->target, true); - mri_shader_bind(engine, &pass->shader, NULL); - bind_gl_object(&engine->default_gl_object); - //mri_shader_bind(engine, &pass->shader, object->model); - //bind_gl_object(&object->gl_object); - break; - case COMBINE: - mri_framebuffer_bind(engine->combine_buffer, false); - mri_shader_bind(engine, &pass->shader, object->model); - bind_gl_object(&object->gl_object); - break; - } - - for (int i = 0; i < pass->shader.texture_count; i++) { - if (pass->textures[i]) mri_texture_bind(pass->textures[i], i); - } - - if (s == COMBINE || (s == BACKGROUND && object->object->passthrough)) { - center_scale(engine->width, engine->height, engine->context->width, engine->context->height); - } else { - glViewport(0, 0, pass->target->width, pass->target->height); - } - - glDrawArrays(GL_TRIANGLES, 0, 6); -} - void mri_engine_load(mri_engine *engine, mri_scene *scene) { - mvec_init(engine->objects); + engine->scene = scene; + mvec_init(engine->framebuffers); - mvec_reserve(engine->objects, mvec_size(scene->objects)); - mvec_reserve(engine->framebuffers, mri_scene_framebuffer_count(scene)); + mvec_reserve(engine->framebuffers, mri_scene_framebuffer_count(scene) + 1); engine->width = scene->width; engine->height = scene->height; @@ -95,58 +26,15 @@ 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->width, engine->height, 1.f, - scene->clear_color); + mstr_c("_rt_FullFrameBuffer"), engine->context->width, engine->context->height, + 1.f, scene->clear_color); + mri_shader_load(&engine->mininal_shader, mstr_c("minimal")); + mri_shader_compile(&engine->mininal_shader); + create_gl_object(&engine->default_gl_object, DEFAULT, 0, 0); } -void mri_engine_next_object(mri_engine *engine, mri_object *object) { - engine->current_object = mvec_next(engine->objects); - engine->current_object->object = object; - - float width = object->size[0]; - float height = object->size[1]; - - create_gl_object(&engine->current_object->gl_uv_object, - UV_SCALE, width, height); - - create_gl_object(&engine->current_object->gl_object, - OBJECT, width, height); - - mri_object_get_model(object, engine->current_object->model, - engine->width, engine->height); - - glm_ortho(-width, width, -height, height, 0.f, 1.f, - engine->current_object->ortho); - - engine->current_object->abuffer = mri_engine_get_or_new_framebuffer(engine, - object->abuffer, engine->width, engine->height, 1.f, - (vec4){0.f, 0.f, 0.f, 0.f}); - - engine->current_object->bbuffer = mri_engine_get_or_new_framebuffer(engine, - object->bbuffer, engine->width, engine->height, 1.f, - (vec4){0.f, 0.f, 0.f, 0.f}); - - engine->current_object->buffer_switch = false; -} - -void mri_engine_next_effect(mri_engine *engine) { - engine->current_effect = mvec_next(engine->current_object->effects); - mvec_init(engine->current_effect->passes); -} - -void mri_engine_next_pass(mri_engine *engine) { - engine->current_pass = mvec_next(engine->current_effect->passes); - mvec_init(engine->current_pass->uniforms); - mvec_init(engine->current_pass->combos); -} - -void mri_engine_update(mri_engine *engine) { - engine->context->process_input(engine->context); - engine->time = engine->context->current_time(engine->context); -} - mri_framebuffer *mri_engine_get_framebuffer(mri_engine *engine, mstr *name) { mri_framebuffer *existing_buffer; mvec_loop_ptr(engine->framebuffers, existing_buffer, i) { @@ -157,8 +45,8 @@ mri_framebuffer *mri_engine_get_framebuffer(mri_engine *engine, mstr *name) { return NULL; } -mri_framebuffer *mri_engine_get_or_new_framebuffer(mri_engine *engine, - mstr *name, float width, float height, float scale, vec4 clear_color) { +mri_framebuffer *mri_engine_get_or_new_framebuffer(mri_engine *engine, mstr *name, + float width, float height, float scale, vec4 clear_color) { mri_framebuffer *buffer = mri_engine_get_framebuffer(engine, name); @@ -171,36 +59,19 @@ mri_framebuffer *mri_engine_get_or_new_framebuffer(mri_engine *engine, return buffer; } -void mri_engine_draw(mri_engine *engine) { - //mri_framebuffer_bind(engine->combine_buffer, true); +void mri_engine_update(mri_engine *engine) { + engine->context->process_input(engine->context); + engine->time = engine->context->current_time(engine->context); +} - mri_render_object *object; - mvec_loop_ptr(engine->objects, object, i) { - mri_render_pass *background_pass; - mvec_loop_ptr(object->background.passes, background_pass, s) { - draw_pass(engine, BACKGROUND, background_pass, object); - if (mvec_size(object->effects) == 0) { - draw_pass(engine, BACKGROUND_ONLY, background_pass, object); - } - } - mri_render_effect *effect; - mvec_loop_ptr(object->effects, effect, s) { - mri_render_pass *pass; - mvec_loop_ptr(effect->passes, pass, j) { - if (j == (mvec_size(effect->passes) - 1)) { - // last pass - draw_pass(engine, TRANSFORM, pass, object); - if (s == mvec_size(object->effects) - 1) { - // last effect - draw_pass(engine, COMBINE, pass, object); - } - } else { - draw_pass(engine, PASS, pass, object); - } - } - } +void mri_engine_draw(mri_engine *engine) { + mri_framebuffer *buffer; + mvec_loop_ptr(engine->framebuffers, buffer, i) { + mri_framebuffer_bind(buffer, true); } + mri_scene_draw(engine, engine->scene); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, engine->combine_buffer->buffer.id); @@ -211,9 +82,19 @@ 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 + } + + time = engine->context->current_time(engine->context); + engine->context->swap_buffers(engine->context); } } diff --git a/src/engine.h b/src/engine.h index 407988e..3a15a2f 100644 --- a/src/engine.h +++ b/src/engine.h @@ -9,40 +9,11 @@ #include "gl.h" #include "objects/types.h" - -typedef struct { - mri_shader shader; - mri_texture *textures[7]; - mri_framebuffer *target; - mvec(mri_uniform) uniforms; - mvec(mri_combo) combos; -} mri_render_pass; - -typedef struct { - mvec(mri_render_pass) passes; -} mri_render_effect; - -typedef struct { - mri_object *object; - - gl_object gl_uv_object; - gl_object gl_object; - - mat4 ortho; - mat4 model; - - mri_framebuffer *abuffer; - mri_framebuffer *bbuffer; - - bool buffer_switch; - - mri_render_effect background; - - mvec(mri_render_effect) effects; -} mri_render_object; +#include "objects/object.h" struct mri_engine { mri_context *context; + mri_scene *scene; float width; float height; @@ -55,14 +26,11 @@ struct mri_engine { gl_object default_gl_object; mri_framebuffer *combine_buffer; + mri_shader mininal_shader; mvec(mri_framebuffer) framebuffers; - mri_render_pass *current_pass; - mri_render_effect *current_effect; - mri_render_object *current_object; - - mvec(mri_render_object) objects; + mri_object *current_object; }; void mri_engine_load(mri_engine *engine, mri_scene *scene); @@ -35,17 +35,18 @@ void create_gl_texture(gl_texture *tex, bool interp, bool clamp_uv, int mm_count glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mm_count - 1); } -void upload_gl_texture(gl_texture *tex, unsigned char *data, int width, int height, int level) { +void upload_gl_texture(gl_texture *tex, unsigned char *data, int width, int height, int level, + unsigned int format) { bind_gl_texture(tex, 0); int _width = m_npof2(width); int _height = m_npof2(height); glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, _width, _height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + format, GL_UNSIGNED_BYTE, NULL); glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, - GL_RGBA, GL_UNSIGNED_BYTE, data); + format, GL_UNSIGNED_BYTE, data); } void destroy_gl_texture(gl_texture *tex) { @@ -53,7 +54,7 @@ void destroy_gl_texture(gl_texture *tex) { } void bind_gl_framebuffer(gl_framebuffer *fbo, bool clear) { - glBindFramebuffer(GL_FRAMEBUFFER, fbo->id); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->id); if (clear) { glClearColor(fbo->clear_color[1], fbo->clear_color[1], fbo->clear_color[2], fbo->clear_color[3]); @@ -85,6 +86,8 @@ void create_gl_framebuffer(gl_framebuffer *fbo, float width, float height, vec4 fbo->clear_color[3]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glGenerateMipmap(GL_TEXTURE_2D); } void destroy_gl_framebuffer(gl_framebuffer *fbo) { @@ -40,7 +40,8 @@ typedef enum { void bind_gl_texture(gl_texture *tex, unsigned int index); void create_gl_texture(gl_texture *tex, bool interp, bool clamp_uv, int mm_count); -void upload_gl_texture(gl_texture *tex, unsigned char *data, int width, int height, int level); +void upload_gl_texture(gl_texture *tex, unsigned char *data, int width, int height, int level, + unsigned int format); void destroy_gl_texture(gl_texture *tex); void bind_gl_framebuffer(gl_framebuffer *fbo, bool clear); diff --git a/src/mauri.c b/src/mauri.c index 933f089..8a8b2be 100644 --- a/src/mauri.c +++ b/src/mauri.c @@ -9,7 +9,7 @@ int main(int argc, char* argv[]) { mri_context *context = mri_glfw_context_new(); - context->create_window(context, 3000, 2000, "mauri", false); + context->create_window(context, 1920, 1080, "mauri", false); if (argc == 2) { mri_asset_manager_load_pkg(mstr_c(argv[1])); @@ -20,6 +20,7 @@ int main(int argc, char* argv[]) { //context->resize_window(context, scene.width, scene.height); mri_engine engine = {0}; + engine.context = context; mri_engine_load(&engine, &scene); diff --git a/src/objects/effect.c b/src/objects/effect.c index 7458f62..f90fad8 100644 --- a/src/objects/effect.c +++ b/src/objects/effect.c @@ -1,5 +1,13 @@ #include "effect.h" + +#include "../engine.h" #include "../json.h" +#include "../log.h" + +#include "cglm/mat4.h" +#include "src/objects/pass.h" +#include "src/objects/types.h" +#include <jansson.h> void mri_effect_parse(mri_effect *effect, json_t *root) { mvec_init(effect->passes0); @@ -20,6 +28,8 @@ void mri_effect_parse(mri_effect *effect, json_t *root) { json_t *_root = json_load_mstr(mri_asset_as_str(effect_asset)); + effect->name = mstr_from(json_string_value(json_object_get(_root, "name"))); + json_t *pass1; json_t *passes1 = json_object_get(_root, "passes"); json_array(pass1, passes1) { @@ -28,16 +38,43 @@ void mri_effect_parse(mri_effect *effect, json_t *root) { } } +mri_render_pass *mri_effect_next_pass(mri_effect *effect) { + mri_render_pass *pass = mvec_next(effect->passes); + mvec_init(pass->uniforms); + mvec_init(pass->combos); + return pass; +} + void mri_effect_load(mri_engine *engine, mri_effect *effect) { - mri_engine_next_effect(engine); - for (int i = 0; i < mvec_size(effect->passes0); i++) { - mri_engine_next_pass(engine); - mri_pass_load(engine, mvec_at(effect->passes0, i), EFFECT0_PASS); - mri_pass_load(engine, mvec_at(effect->passes1, i), EFFECT1_PASS); + 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; + + 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); + } +} + +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); + mri_render_pass_draw(engine, pass); } } void mri_effect_unload(mri_effect *effect) { + mstr_free(effect->name); + mri_pass *pass; mvec_loop_ptr(effect->passes0, pass, i) { diff --git a/src/objects/effect.h b/src/objects/effect.h index 76af254..9570fde 100644 --- a/src/objects/effect.h +++ b/src/objects/effect.h @@ -7,12 +7,16 @@ #include "pass.h" struct mri_effect { + mstr *name; + mvec(mri_pass) passes0; mvec(mri_pass) passes1; + mvec(mri_render_pass) passes; }; void mri_effect_parse(mri_effect *effect, json_t *root); void mri_effect_load(mri_engine *engine, mri_effect *effect); +void mri_effect_draw(mri_engine *engine, mri_effect *effect); void mri_effect_unload(mri_effect *effect); #endif // _EFFECT_H diff --git a/src/objects/material.c b/src/objects/material.c index d934970..2076274 100644 --- a/src/objects/material.c +++ b/src/objects/material.c @@ -1,10 +1,13 @@ #include "material.h" +#include "cglm/mat4.h" #include "pass.h" #include <moro_str.h> #include "../log.h" #include "../json.h" +#include "../engine.h" +#include "src/objects/types.h" void mri_material_parse(mri_material *material, json_t *value) { mvec_init(material->passes); @@ -20,32 +23,54 @@ void mri_material_parse(mri_material *material, json_t *value) { json_t *pass; json_t *passes = json_object_get(root, "passes"); json_array(pass, passes) { - mri_pass_parse(mvec_next(material->passes), pass, MATERIAL_PASS); + mri_pass_parse(mvec_next(material->passes0), pass, MATERIAL_PASS); } json_decref(root); } } -void mri_material_load(mri_engine *engine, mri_material *material, mri_material_type t) { - mri_pass *pass; - mvec_loop_ptr(material->passes, pass, i) { +mri_render_pass *mri_material_next_pass(mri_material *material) { + mri_render_pass *pass = mvec_next(material->passes); + mvec_init(pass->uniforms); + mvec_init(pass->combos); + return pass; +} + +void mri_material_load(mri_engine *engine, mri_material *material, mri_material_type t, + mri_render_pass *pass) { + mri_pass *pass0; + mvec_loop_ptr(material->passes0, pass0, i) { switch (t) { case MATERIAL_EFFECT: - mri_pass_load(engine, pass, MATERIAL_PASS); + mri_pass_load(engine, pass0, MATERIAL_PASS, pass); break; case MATERIAL_MODEL: - mri_engine_next_pass(engine); - mri_pass_load(engine, pass, MATERIAL_ONLY_PASS); + pass = mri_material_next_pass(material); + + pass->object = engine->current_object; + pass->gl_object = &engine->current_object->gl_uv_object; + + glm_mat4_copy(engine->current_object->ortho, pass->model); + + mri_pass_load(engine, pass0, MATERIAL_ONLY_PASS, pass); break; } } } -void mri_material_unload(mri_material *material) { - mri_pass *pass; +void mri_material_draw(mri_engine *engine, mri_material *material) { + mri_render_pass *pass; mvec_loop_ptr(material->passes, pass, i) { - mri_pass_unload(pass); + log_debug("background (%.*s): %i", pass->object->name->len, pass->object->name->ptr, i); + mri_render_pass_draw(engine, pass); + } +} + +void mri_material_unload(mri_material *material) { + mri_pass *pass0; + mvec_loop_ptr(material->passes0, pass0, i) { + mri_pass_unload(pass0); } mvec_free(material->passes); } diff --git a/src/objects/material.h b/src/objects/material.h index 805a198..5c8f7b5 100644 --- a/src/objects/material.h +++ b/src/objects/material.h @@ -12,11 +12,13 @@ typedef enum { } mri_material_type; struct mri_material { - mvec(mri_pass) passes; + mvec(mri_pass) passes0; + mvec(mri_render_pass) passes; }; void mri_material_parse(mri_material *material, json_t *value); -void mri_material_load(mri_engine *engine, mri_material *material, mri_material_type t); +void mri_material_load(mri_engine *engine, mri_material *material, mri_material_type t, mri_render_pass *pass); +void mri_material_draw(mri_engine *engine, mri_material *material); void mri_material_unload(mri_material *material); #endif // MATERIAL_H diff --git a/src/objects/model.c b/src/objects/model.c index 3fe8e1d..81cd0b0 100644 --- a/src/objects/model.c +++ b/src/objects/model.c @@ -4,8 +4,10 @@ #include "../json.h" #include "../assets.h" #include "../log.h" +#include "../engine.h" #include "model.h" +#include "src/objects/types.h" void mri_model_parse(mri_model *model, json_t *value) { if (json_is_string(value)) { @@ -29,8 +31,11 @@ void mri_model_parse(mri_model *model, json_t *value) { } void mri_model_load(mri_engine *engine, mri_model *model) { - engine->current_effect = &engine->current_object->background; - mri_material_load(engine, &model->material, MATERIAL_MODEL); + mri_material_load(engine, &model->material, MATERIAL_MODEL, NULL); +} + +void mri_model_draw(mri_engine *engine, mri_model *model) { + mri_material_draw(engine, &model->material); } void mri_model_unload(mri_model *model) { diff --git a/src/objects/model.h b/src/objects/model.h index 38f4405..4d17c72 100644 --- a/src/objects/model.h +++ b/src/objects/model.h @@ -7,8 +7,6 @@ #include "pass.h" #include "material.h" -#include "../engine.h" - struct mri_model { bool autosize; bool fullscreen; @@ -18,6 +16,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_draw(mri_engine *engine, mri_model *model); void mri_model_unload(mri_model *model); #endif // _MODEL_H diff --git a/src/objects/object.c b/src/objects/object.c index ee96a9e..b3b57c2 100644 --- a/src/objects/object.c +++ b/src/objects/object.c @@ -1,17 +1,25 @@ #include <jansson.h> #include <cglm/cglm.h> +#include "moro_str.h" +#include "src/shader.h" +#include "src/texture.h" + #include "types.h" #include "object.h" #include "model.h" +#include "scene.h" #include "../log.h" #include "../gl.h" +#include "../engine.h" #include "../json.h" void mri_object_parse(mri_object *object, json_t *root) { json_get_int(&object->id, root, "id"); + object->name = mstr_from(json_string_value(json_object_get(root, "name"))); + mvec_init(object->deps); json_t *dep; @@ -39,25 +47,7 @@ void mri_object_parse(mri_object *object, json_t *root) { json_get_bool(&object->passthrough, config, "passthrough"); } - char *abuffer, *bbuffer; - - asprintf(&abuffer, "_rt_imageLayerComposite_%i_a", object->id); - asprintf(&bbuffer, "_rt_imageLayerComposite_%i_b", object->id); - - object->abuffer = mstr_from(abuffer); - object->bbuffer = mstr_from(bbuffer); - - free(abuffer); - free(bbuffer); - - json_t *image = json_object_get(root, "image"); - - if (json_is_string(image)) { - mri_model_parse(&object->image, image); - object->has_image = true; - } else { - object->has_image = false; - } + mri_model_parse(&object->image, json_object_get(root, "image")); mvec_init(object->effects); @@ -92,7 +82,41 @@ void mri_object_get_model(mri_object *object, mat4 model, float width, float hei } void mri_object_load(mri_engine *engine, mri_object *object) { - mri_engine_next_object(engine, object); + engine->current_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); + + object->abuffer = mri_engine_get_or_new_framebuffer(engine, + mstr_c(abuffer), width, height, 1.f, + engine->scene->clear_color); + + object->bbuffer = mri_engine_get_or_new_framebuffer(engine, + mstr_c(bbuffer), width, height, 1.f, + engine->scene->clear_color); + + free(abuffer); + free(bbuffer); + + object->buffer_switch = false; + + mri_object_get_model(object, engine->current_object->model, + engine->width, engine->height); + + glm_ortho(-width, width, -height, height, 0.f, 1.f, + engine->current_object->ortho); + + create_gl_object(&engine->current_object->gl_uv_object, + UV_SCALE, width, height); + + create_gl_object(&engine->current_object->gl_object, + OBJECT, width, height); mri_model_load(engine, &object->image); @@ -114,7 +138,51 @@ void mri_object_load(mri_engine *engine, mri_object *object) { } } +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; + + float wpad = (width - w1) / -2.f; + float hpad = (height - h1) / -2.f; + + glViewport(wpad, hpad, width, height); +} + +void mri_object_draw(mri_engine *engine, mri_object *object) { + mri_model_draw(engine, &object->image); + + mri_effect *effect; + 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) { + mstr_free(object->name); + mri_effect *effect; mvec_loop_ptr(object->effects, effect, i) { mri_effect_unload(effect); @@ -123,8 +191,8 @@ void mri_object_unload(mri_object *object) { mvec_free(object->effects); mvec_free(object->deps); - mstr_free(object->abuffer); - mstr_free(object->bbuffer); + mri_framebuffer_unload(object->abuffer); + mri_framebuffer_unload(object->bbuffer); mri_model_unload(&object->image); } diff --git a/src/objects/object.h b/src/objects/object.h index 7c6969b..c7bb883 100644 --- a/src/objects/object.h +++ b/src/objects/object.h @@ -6,6 +6,7 @@ #include <stdbool.h> #include <cglm/cglm.h> +#include "src/texture.h" #include "types.h" #include "model.h" #include "pass.h" @@ -19,6 +20,7 @@ typedef enum { struct mri_object { int id; + mstr *name; mvec(int) deps; @@ -34,7 +36,6 @@ struct mri_object { bool copy_background; mri_model image; - bool has_image; vec2 size; vec3 origin; @@ -45,8 +46,16 @@ struct mri_object { bool passthrough; bool fullscreen; - mstr *abuffer; - mstr *bbuffer; + gl_object gl_uv_object; + gl_object gl_object; + + mat4 ortho; + mat4 model; + + mri_framebuffer *abuffer; + mri_framebuffer *bbuffer; + + bool buffer_switch; mvec(mri_effect) effects; }; @@ -55,6 +64,7 @@ void mri_object_get_model(mri_object *object, mat4 model, float width, float hei 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); void mri_object_unload(mri_object *object); #endif // _OBJECT_H diff --git a/src/objects/pass.c b/src/objects/pass.c index fadac16..f0cac99 100644 --- a/src/objects/pass.c +++ b/src/objects/pass.c @@ -1,3 +1,5 @@ +#include <unistd.h> + #include "pass.h" #include "material.h" #include "model.h" @@ -5,8 +7,11 @@ #include "../json.h" #include "../texture.h" +#include "../engine.h" #include "../assets.h" #include "../gl.h" +#include "src/objects/types.h" +#include "src/shader.h" void mri_pass_parse(mri_pass *pass, json_t *root, mri_pass_stage stage) { memset(pass, 0, sizeof(mri_pass)); @@ -42,21 +47,18 @@ void mri_pass_parse(mri_pass *pass, json_t *root, mri_pass_stage stage) { } case EFFECT1_PASS: { json_t *material = json_object_get(root, "material"); - if (json_is_string(material)) { pass->material = (mri_material *)calloc(1, sizeof(mri_material)); mri_material_parse(pass->material, material); } json_t *target = json_object_get(root, "target"); - if (json_is_string(target)) { pass->target = mstr_from(json_string_value(target)); } json_t *bind; json_t *binds = json_object_get(root, "bind"); - json_array(bind, binds) { int index = json_integer_value(json_object_get(bind, "index")); pass->binds[index] = mstr_from(json_string_value(json_object_get(bind, "name"))); @@ -67,24 +69,22 @@ void mri_pass_parse(mri_pass *pass, json_t *root, mri_pass_stage stage) { case MATERIAL_ONLY_PASS: case MATERIAL_PASS: { json_t *shader = json_object_get(root, "shader"); - if (json_is_string(shader)) { pass->shader = (mri_shader *)calloc(1, sizeof(mri_shader)); mri_shader_load(pass->shader, mstr_c(json_string_value(shader))); } - break; } } json_t *texture; json_t *textures = json_object_get(root, "textures"); - json_array(texture, textures) { if (json_is_string(texture)) { - mri_asset *_a = mri_asset_manager_get(mstr_c(json_string_value(texture)), TEXTURE); - if (_a->type != ASSET_VOID) { - pass->textures[i] = mri_texture_load(_a); + mri_asset *texture_asset = mri_asset_manager_get( + mstr_c(json_string_value(texture)), TEXTURE); + if (texture_asset->type != ASSET_VOID) { + pass->textures[i] = mri_texture_load(texture_asset); } } } @@ -113,9 +113,8 @@ 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_object *robject = engine->current_object; - mri_render_pass *rpass = engine->current_pass; +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++) { if (pass->textures[i]) rpass->textures[i] = pass->textures[i]; @@ -135,44 +134,74 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage) { break; } 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, 1.0f}); + (vec4){0.f, 0.f, 0.f, 0.2f}); } else { - if (!robject->buffer_switch) { - rpass->target = robject->bbuffer; - rpass->textures[0] = &robject->abuffer->texture; + // 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; } else { - rpass->target = robject->abuffer; - rpass->textures[0] = &robject->bbuffer->texture; + rpass->target = object->bbuffer; + rpass->textures[0] = &object->abuffer->texture; } - robject->buffer_switch = !robject->buffer_switch; } 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 (!robject->buffer_switch) { - rpass->textures[i] = &robject->bbuffer->texture; + if (object->buffer_switch) { + rpass->textures[i] = &object->bbuffer->texture; } else { - rpass->textures[i] = &robject->abuffer->texture; + rpass->textures[i] = &object->abuffer->texture; } } else { rpass->textures[i] = &mri_engine_get_framebuffer(engine, pass->binds[i])->texture; } } - mri_material_load(engine, pass->material, MATERIAL_EFFECT); + // 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); break; case MATERIAL_ONLY_PASS: - rpass->target = robject->abuffer; + // 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_PASS: { memcpy(&rpass->shader, pass->shader, sizeof(mri_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)); + for (int i = 0; i < 7; i++) { + // As the last step for shaders, set any unset texture slots + // with the default textures from the shader is there is any. if (!rpass->textures[i] && rpass->shader.textures[i]) { rpass->textures[i] = rpass->shader.textures[i]; } + // Set TEX0FORMAT incase extra steps are needed when sampling, + // see "common_fragment.h". + if (rpass->textures[i] && i == 0) { + mri_combo c = { + .name = mstr_from("TEX0FORMAT"), + .value = rpass->textures[i]->format + }; + mvec_push(rpass->shader.combos, c); + } } mri_uniform *pass_uniform, *shader_uniform; @@ -183,11 +212,13 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage) { mstr_cmp(shader_uniform->uname, mstr_c("Resolution"), 10, 10) == 0) { int index = shader_uniform->uname->ptr[9] - '0'; if (rpass->textures[index]) { - vec4 *texture_res = &rpass->textures[index]->texture_resolution; - memcpy(shader_uniform->value, texture_res, sizeof(vec4)); + memcpy(shader_uniform->value, + &rpass->textures[index]->texture_resolution, sizeof(vec4)); } } } + + // Handle uniform value overrides. mvec_loop_ptr(rpass->uniforms, pass_uniform, i) mvec_loop_ptr(rpass->shader.uniforms, shader_uniform, s) { if (!shader_uniform->name) continue; @@ -196,6 +227,7 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage) { } } + // Handle combo value overrides. mri_combo *pass_combo, *shader_combo; mvec_loop_ptr(rpass->combos, pass_combo, i) mvec_loop_ptr(rpass->shader.combos, shader_combo, s) { @@ -204,6 +236,7 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage) { } } + // compile the shader with the new combo values. mri_shader_compile(&rpass->shader); break; @@ -211,7 +244,37 @@ void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage) { } } +void mri_render_pass_draw(mri_engine *engine, mri_render_pass *pass) { + mri_framebuffer_bind(pass->target, pass->combine); + mri_shader_bind(engine, &pass->shader, pass->model); + + bind_gl_object(pass->gl_object); + + for (int i = 0; i < pass->shader.texture_count; i++) { + 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); + + 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); + + engine->context->swap_buffers(engine->context); + + usleep(1000000); + } +} + void mri_pass_unload(mri_pass *pass) { + // TODO render pass unloading + for (int i = 0; i < 7; i++) { if (pass->textures[i]) mri_texture_unload(pass->textures[i]); } diff --git a/src/objects/pass.h b/src/objects/pass.h index 116f91d..37c0997 100644 --- a/src/objects/pass.h +++ b/src/objects/pass.h @@ -3,14 +3,32 @@ #include <jansson.h> +#include "src/gl.h" #include "types.h" #include "../context.h" #include "../shader.h" -#include "../engine.h" #include "../texture.h" +typedef enum { + EFFECT0_PASS, + EFFECT1_PASS, + MATERIAL_PASS, + MATERIAL_ONLY_PASS +} mri_pass_stage; + +typedef enum { + BACKGROUND, + BACKGROUND_ONLY, + TRANSFORM, + COMBINE, + PASS, +} mri_render_pass_stage; + + struct mri_pass { + int id; + mri_material *material; mri_shader *shader; @@ -23,15 +41,29 @@ struct mri_pass { mvec(mri_combo) combos; }; -typedef enum { - EFFECT0_PASS, - EFFECT1_PASS, - MATERIAL_PASS, - MATERIAL_ONLY_PASS -} mri_pass_stage; +struct mri_render_pass { + mri_shader shader; + + mri_object *object; + + mat4 model; + gl_object *gl_object; + + mri_texture *textures[7]; + mri_framebuffer *target; + + bool combine; + + mri_render_pass_stage stage; + + mvec(mri_uniform) uniforms; + mvec(mri_combo) combos; +}; 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); +void mri_pass_load(mri_engine *engine, mri_pass *pass, mri_pass_stage stage, mri_render_pass *rpass); void mri_pass_unload(mri_pass *pass); +void mri_render_pass_draw(mri_engine *engine, mri_render_pass *pass); + #endif // _PASS_H diff --git a/src/objects/scene.c b/src/objects/scene.c index f887f13..db6656f 100644 --- a/src/objects/scene.c +++ b/src/objects/scene.c @@ -6,6 +6,8 @@ #include "../json.h" #include "../log.h" +#include "../engine.h" +#include "src/objects/types.h" void mri_scene_parse(mri_scene *scene) { mri_asset *scene_asset = mri_asset_manager_get(mstr_c("scene.json"), NONE); @@ -28,7 +30,7 @@ void mri_scene_parse(mri_scene *scene) { json_get_bool(&scene->clear_enabled, general, "clearenabled"); json_get_vec3((vec3 *)&scene->clear_color, general, "clearcolor"); - scene->clear_color[3] = 1.f; + scene->clear_color[3] = 0.f; json_get_vec3(&scene->ambient_color, general, "ambientcolor"); json_get_vec3(&scene->skylight_color, general, "skylightcolor"); @@ -43,7 +45,7 @@ void mri_scene_parse(mri_scene *scene) { json_array(object, objects) { bool visible; json_get_bool(&visible, object, "visible"); - if (visible) + if (visible && !(json_is_null(json_object_get(object, "image")))) mri_object_parse(mvec_next(scene->objects), object); } @@ -80,6 +82,22 @@ 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); + } + } + } + mri_object_draw(engine, object); + } +} + void mri_scene_unload(mri_scene *scene) { mri_object *object; mvec_loop_ptr(scene->objects, object, i) { diff --git a/src/objects/scene.h b/src/objects/scene.h index dee6d50..9514580 100644 --- a/src/objects/scene.h +++ b/src/objects/scene.h @@ -38,8 +38,10 @@ struct mri_scene { }; void mri_scene_parse(mri_scene *scene); -int mri_scene_framebuffer_count(mri_scene *scene); void mri_scene_load(mri_engine *engine, mri_scene *scene); +void mri_scene_draw(mri_engine *engine, mri_scene *scene); void mri_scene_unload(mri_scene *scene); +int mri_scene_framebuffer_count(mri_scene *scene); + #endif // _SCENE_H diff --git a/src/objects/types.h b/src/objects/types.h index 9701cb0..76fd8eb 100644 --- a/src/objects/types.h +++ b/src/objects/types.h @@ -8,4 +8,8 @@ typedef struct mri_material mri_material; typedef struct mri_pass mri_pass; typedef struct mri_effect mri_effect; +typedef struct mri_render_pass mri_render_pass; + +typedef struct mri_engine mri_engine; + #endif // _TYPES_H diff --git a/src/shader.c b/src/shader.c index d5b1ede..ed8090d 100644 --- a/src/shader.c +++ b/src/shader.c @@ -29,10 +29,9 @@ static const char *gl_compat = "#define texSample2D texture2D\n" "#define texSample2DLod texture2DLod\n" "#define texture2DLod texture2D\n" - "#define atan2(y,x) atan(x,y)\n" + "#define atan2(y,x) atan(y,x)\n" "#define ddx dFdx\n" "#define ddy(x) dFdy(-(x))\n" - "#define VERSION 2\n" "#define GLSL 1\n"; static const char *version = "#version 120\n"; @@ -99,6 +98,14 @@ static mstr *build_shader_source(mri_shader *shader, mstr *isource, bool start) mri_asset *_a = mri_asset_manager_get(mstr_c(json_string_value(texture)), TEXTURE); shader->textures[(int)u->value[0]] = mri_texture_load(_a); } + json_t *combo = json_object_get(root, "combo"); + if (json_is_string(combo)) { + mri_combo c = { + .name = mstr_from(json_string_value(combo)), + .value = 1 + }; + mvec_push(shader->combos, c); + } break; } case TYPE_FLOAT: @@ -170,8 +177,6 @@ void mri_shader_compile(mri_shader *shader) { char *vs_source_c = mstr_to_cstr(vs_source); char *fs_source_c = mstr_to_cstr(fs_source); - printf("%s\n", fs_source_c); - create_gl_shader(&shader->gl_shader, vs_source_c, fs_source_c); free(vs_source_c); @@ -220,7 +225,8 @@ void mri_shader_bind(mri_engine *engine, mri_shader *shader, mat4 mvp) { if (mstr_find(uniform->uname, '[') >= 0) continue; mri_uniform_set(shader, uniform); - //printf("%.*s %f\n", uniform->uname->len, uniform->uname->ptr, uniform->value[0]); + //printf("%.*s %f %f %f %f %i\n", uniform->uname->len, uniform->uname->ptr, + // uniform->value[0], uniform->value[1], uniform->value[2], uniform->value[3], uniform->type); } set_gl_uniform_named("g_Time", &shader->gl_shader, TYPE_FLOAT, &engine->time); @@ -247,8 +253,7 @@ void mri_shader_bind(mri_engine *engine, mri_shader *shader, mat4 mvp) { void mri_shader_unload(mri_shader *shader) { for (int i = 0; i < 7; i++) { - if (shader->textures[i]) - mri_texture_unload(shader->textures[i]); + if (shader->textures[i]) mri_texture_unload(shader->textures[i]); } if (shader->vs_source) @@ -273,7 +278,7 @@ void mri_shader_unload(mri_shader *shader) { mvec_free(shader->uniforms); mvec_free(shader->combos); - destroy_gl_shader(&shader->gl_shader); + //destroy_gl_shader(&shader->gl_shader); } diff --git a/src/shader.h b/src/shader.h index 6880397..8a62b98 100644 --- a/src/shader.h +++ b/src/shader.h @@ -23,8 +23,6 @@ typedef struct { } mri_combo; typedef struct { - const char *name; - mstr *vs_source; mstr *fs_source; diff --git a/src/texture.c b/src/texture.c index 50b9591..288a2ed 100644 --- a/src/texture.c +++ b/src/texture.c @@ -3,6 +3,7 @@ #include <lz4.h> #include <moro.h> +#include <glad/gl.h> #include "util.h" #include "texture.h" @@ -55,7 +56,7 @@ mri_texture *mri_texture_load(mri_asset *asset) { t->version = TEXB0001; mri_asset_seek(asset, 4); } else { - //log_error("%s", "unknown texture version"); + log_error("%s", "unknown texture version"); } int mm_count = mri_asset_value(asset, int); @@ -92,7 +93,7 @@ mri_texture *mri_texture_load(mri_asset *asset) { if (iformat == -1) { switch (t->format) { case RGBA8888: - upload_gl_texture(&t->texture, buffer, mwidth, mheight, i); + upload_gl_texture(&t->texture, buffer, mwidth, mheight, i, GL_RGBA); break; case DXT5: log_warn("%s", "DXT5 Texture"); @@ -100,12 +101,24 @@ mri_texture *mri_texture_load(mri_asset *asset) { case DXT1: log_warn("%s", "DXT1 Texture"); break; + case DXT3: + log_warn("%s", "DXT3 Texture"); + break; + case RG88: + upload_gl_texture(&t->texture, buffer, mwidth, mheight, i, GL_RG); + log_warn("%s", "RG88 Texture"); + break; + case R8: + upload_gl_texture(&t->texture, buffer, mwidth, mheight, i, GL_RED); + log_warn("%s", "RG8 Texture"); + break; default: + log_warn("%s", "Uknown Texture"); break; } } else { unsigned char *data = load_image_rgba(buffer, decompressed_byte_count); - upload_gl_texture(&t->texture, data, mwidth, mheight, i); + upload_gl_texture(&t->texture, data, mwidth, mheight, i, GL_RGBA); free(data); } diff --git a/src/texture.h b/src/texture.h index 4156072..68211b4 100644 --- a/src/texture.h +++ b/src/texture.h @@ -37,8 +37,6 @@ typedef struct { vec4 texture_resolution; - //char *combo; - union { mri_texture_flags map; unsigned int integer; @@ -52,9 +50,6 @@ typedef struct { mstr *name; float width, height; - float scale; - - bool loaded; gl_framebuffer buffer; |