diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b0bd86..30e20cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,11 @@ add_subdirectory(third-party/libxm SYSTEM) if(LINUX) - set(SYSTEM_SOURCE_FILES src/system/linux/elf.c) + set(SYSTEM_SOURCE_FILES + src/system/linux/twn_elf.c + src/rendering/twn_gl_any_rendering.c + src/rendering/twn_gl_15_rendering.c + src/rendering/twn_gl_15_gpu_texture.c) else() set(SYSTEM_SOURCE_FILES) endif() @@ -65,12 +69,17 @@ set(TWN_SOURCE_FILES src/twn_context.c include/twn_context.h src/twn_audio.c include/twn_audio.h src/twn_util.c include/twn_util.h - src/twn_rendering.c include/twn_rendering.h src/twn_input.c include/twn_input.h src/twn_camera.c include/twn_camera.h - src/twn_textures.c include/twn_textures.c src/twn_game_object.c + src/twn_textures.c src/twn_textures_c.h + src/rendering/twn_rendering.c src/rendering/twn_rendering_c.h + src/rendering/twn_sprites.c + src/rendering/twn_text.c + src/rendering/twn_triangles.c + src/rendering/twn_circles.c + # for dynamic load based solution main is compiled in a separate target $<$>:src/twn_main.c> @@ -199,7 +208,7 @@ function(include_deps target) target_include_directories(${target} SYSTEM PRIVATE ${THIRD_PARTY_INCLUDES}) # allow access to headers from any point in source tree - target_include_directories(${target} PRIVATE ${TWN_ROOT_DIR}) + target_include_directories(${target} PRIVATE ${TWN_ROOT_DIR} ${TWN_ROOT_DIR}/include) endfunction() @@ -308,6 +317,7 @@ give_options(${TWN_TARGET}) include_deps(${TWN_TARGET}) link_deps(${TWN_TARGET}) target_link_libraries(${TWN_TARGET} PUBLIC twn_third_parties) +target_include_directories(${TWN_TARGET} PRIVATE ${TWN_ROOT_DIR}/src) # build the testgame if this cmake list is built directly if(${CMAKE_PROJECT_NAME} MATCHES townengine) diff --git a/apps/testgame/game.c b/apps/testgame/game.c index 6ba4617..70320e8 100644 --- a/apps/testgame/game.c +++ b/apps/testgame/game.c @@ -2,7 +2,7 @@ #include "scenes/scene.h" #include "scenes/title.h" -#include "townengine/game_api.h" +#include "twn_game_api.h" #include #include @@ -20,9 +20,6 @@ void game_tick(void) { state->scene = title_scene(state); } - input_add_action(&ctx.input, "debug_dump_atlases"); - input_bind_action_scancode(&ctx.input, "debug_dump_atlases", SDL_SCANCODE_HOME); - input_add_action(&ctx.input, "debug_toggle"); input_bind_action_scancode(&ctx.input, "debug_toggle", SDL_SCANCODE_BACKSPACE); @@ -53,10 +50,6 @@ void game_tick(void) { struct state *state = ctx.udata; - if (input_is_action_just_pressed(&ctx.input, "debug_dump_atlases")) { - textures_dump_atlases(&ctx.texture_cache); - } - if (input_is_action_just_pressed(&ctx.input, "debug_toggle")) { ctx.debug = !ctx.debug; } diff --git a/apps/testgame/player.c b/apps/testgame/player.c index d6fde3b..e5e9e8b 100644 --- a/apps/testgame/player.c +++ b/apps/testgame/player.c @@ -1,6 +1,7 @@ #include "player.h" #include "world.h" -#include "townengine/game_api.h" + +#include "twn_game_api.h" #include diff --git a/apps/testgame/player.h b/apps/testgame/player.h index c8f14dc..16c53ba 100644 --- a/apps/testgame/player.h +++ b/apps/testgame/player.h @@ -1,8 +1,7 @@ #ifndef PLAYER_H #define PLAYER_H - -#include "townengine/game_api.h" +#include "twn_game_api.h" struct world; diff --git a/apps/testgame/scenes/ingame.c b/apps/testgame/scenes/ingame.c index c8afdb8..a8ed7e9 100644 --- a/apps/testgame/scenes/ingame.c +++ b/apps/testgame/scenes/ingame.c @@ -2,7 +2,7 @@ #include "title.h" #include "scene.h" -#include "townengine/game_api.h" +#include "twn_game_api.h" #define STB_PERLIN_IMPLEMENTATION #include diff --git a/apps/testgame/scenes/ingame.h b/apps/testgame/scenes/ingame.h index 6b19d90..061dff0 100644 --- a/apps/testgame/scenes/ingame.h +++ b/apps/testgame/scenes/ingame.h @@ -1,8 +1,7 @@ #ifndef INGAME_H #define INGAME_H - -#include "townengine/game_api.h" +#include "twn_game_api.h" #include "../state.h" #include "scene.h" diff --git a/apps/testgame/scenes/title.c b/apps/testgame/scenes/title.c index 8d616b5..4fb0568 100644 --- a/apps/testgame/scenes/title.c +++ b/apps/testgame/scenes/title.c @@ -3,7 +3,7 @@ #include "../world.h" #include "../player.h" -#include "townengine/game_api.h" +#include "twn_game_api.h" #include diff --git a/apps/testgame/scenes/title.h b/apps/testgame/scenes/title.h index 450b0ea..89b99d7 100644 --- a/apps/testgame/scenes/title.h +++ b/apps/testgame/scenes/title.h @@ -1,8 +1,6 @@ #ifndef TITLE_H #define TITLE_H - -#include "townengine/game_api.h" #include "../state.h" #include "scene.h" #include "../player.h" diff --git a/apps/testgame/state.h b/apps/testgame/state.h index abb5325..9bb8647 100644 --- a/apps/testgame/state.h +++ b/apps/testgame/state.h @@ -2,8 +2,9 @@ #define STATE_H -#include "townengine/game_api.h" +#include "twn_game_api.h" +#include struct state { t_ctx *ctx; diff --git a/apps/testgame/world.c b/apps/testgame/world.c index d053971..d5dfbd1 100644 --- a/apps/testgame/world.c +++ b/apps/testgame/world.c @@ -1,4 +1,4 @@ -#include "townengine/game_api.h" +#include "twn_game_api.h" #include "world.h" diff --git a/apps/testgame/world.h b/apps/testgame/world.h index 6480ec1..d721a2a 100644 --- a/apps/testgame/world.h +++ b/apps/testgame/world.h @@ -1,8 +1,6 @@ #ifndef WORLD_H #define WORLD_H -#include "townengine/game_api.h" - #include #include diff --git a/src/twn_concatenate_c.h b/include/twn_concatenate.h similarity index 100% rename from src/twn_concatenate_c.h rename to include/twn_concatenate.h diff --git a/include/twn_context.h b/include/twn_context.h index 3dfd17e..f1df1ff 100644 --- a/include/twn_context.h +++ b/include/twn_context.h @@ -33,6 +33,8 @@ typedef struct context { bool initialization_needed; } t_ctx; +#ifndef TWN_ENGINE_CONTEXT_C_H TWN_API extern t_ctx ctx; +#endif #endif diff --git a/src/twn_option_c.h b/include/twn_option.h similarity index 98% rename from src/twn_option_c.h rename to include/twn_option.h index 22d403f..dbdd5d4 100644 --- a/src/twn_option_c.h +++ b/include/twn_option.h @@ -1,8 +1,8 @@ #ifndef TWN_OPTION_H #define TWN_OPTION_H -#include "twn_concatenate_c.h" -#include "twn_varargcount_c.h" +#include "twn_concatenate.h" +#include "twn_varargcount.h" #include diff --git a/include/twn_rendering.h b/include/twn_rendering.h index 9cf8451..4eb6631 100644 --- a/include/twn_rendering.h +++ b/include/twn_rendering.h @@ -1,9 +1,9 @@ #ifndef TWN_RENDERING_H #define TWN_RENDERING_H -#include "util.h" -#include "macros/option.h" -#include "camera.h" +#include "twn_util.h" +#include "twn_option.h" +#include "twn_camera.h" #include "twn_engine_api.h" #include diff --git a/src/twn_texture_modes_c.h b/include/twn_texture_modes.h similarity index 100% rename from src/twn_texture_modes_c.h rename to include/twn_texture_modes.h diff --git a/src/twn_varargcount_c.h b/include/twn_varargcount.h similarity index 100% rename from src/twn_varargcount_c.h rename to include/twn_varargcount.h diff --git a/src/game_object/twn_linux_game_object_c.h b/src/game_object/twn_linux_game_object_c.h index 1aa77ed..4bd0f39 100644 --- a/src/game_object/twn_linux_game_object_c.h +++ b/src/game_object/twn_linux_game_object_c.h @@ -1,5 +1,5 @@ -#include "townengine/twn_game_object.h" -#include "townengine/context.h" +#include "twn_game_object_c.h" +#include "twn_engine_context_c.h" #include #include @@ -56,7 +56,7 @@ static void load_game_object(void) { handle = new_handle; - if (ctx.tick_count != 0) + if (ctx.game.tick_count != 0) log_info("Game object was reloaded\n"); return; @@ -83,7 +83,7 @@ static void watcher_callback(XWATCHER_FILE_EVENT event, switch(event) { case XWATCHER_FILE_MODIFIED: SDL_LockMutex(lock); - last_tick_modified = ctx.tick_count; + last_tick_modified = ctx.game.tick_count; loaded_after_modification = false; SDL_UnlockMutex(lock); break; @@ -126,7 +126,7 @@ bool game_object_try_reloading(void) { /* only load the modified library after some time, as compilers make a lot of modifications */ SDL_LockMutex(lock); - if (ctx.tick_count - last_tick_modified > MODIFIED_TICKS_MERGED && + if (ctx.game.tick_count - last_tick_modified > MODIFIED_TICKS_MERGED && !loaded_after_modification) { load_game_object(); loaded_after_modification = true; diff --git a/src/rendering/twn_circles.c b/src/rendering/twn_circles.c index 2cb9bfd..9d76720 100644 --- a/src/rendering/twn_circles.c +++ b/src/rendering/twn_circles.c @@ -1,5 +1,5 @@ -#include "townengine/util.h" -#include "townengine/context.h" +#include "twn_util.h" +#include "twn_engine_context_c.h" #include "twn_rendering_c.h" #include diff --git a/src/rendering/twn_gl_15_gpu_texture.c b/src/rendering/twn_gl_15_gpu_texture.c index 6cf0b90..d8f5591 100644 --- a/src/rendering/twn_gl_15_gpu_texture.c +++ b/src/rendering/twn_gl_15_gpu_texture.c @@ -1,28 +1,68 @@ -static gpu_texture new_gl_texture(void) { +#include "twn_gpu_texture_c.h" +#include "twn_util.h" + + +gpu_texture create_gpu_texture(enum texture_filter filter, bool generate_mipmaps) { GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, (GLboolean)generate_mipmaps); + + if (filter == TEXTURE_FILTER_NEAREAST) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } else if (filter == TEXTURE_FILTER_LINEAR) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); #if !defined(EMSCRIPTEN) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #endif glBindTexture(GL_TEXTURE_2D, 0); - return create_gpu_texture(TEXTURE_FILTER_NEAREST, true); + return texture; } + +void delete_gpu_texture(gpu_texture texture) { + glDeleteTextures(1, &texture); +} + + +void upload_gpu_texture(gpu_texture texture, void *pixels, int channels, int width, int height) { + glBindTexture(GL_TEXTURE_2D, texture); + + int format_internal, format; + if (channels == 4) { + format_internal = GL_RGBA8; + format = GL_RGBA; + } else if (channels == 1) { + format_internal = GL_ALPHA; + format = GL_ALPHA; + } else { + CRY("upload_gpu_texture", "Unsupported channel count"); + return; + } + glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA8, - surface->w, - surface->h, + format_internal, + width, + height, 0, - GL_RGBA, + format, GL_UNSIGNED_BYTE, - surface->pixels); + pixels); + + glBindTexture(GL_TEXTURE_2D, 0); +} + + +void bind_gpu_texture(gpu_texture texture) { + glBindTexture(GL_TEXTURE_2D, texture); +} diff --git a/src/rendering/twn_gl_15_rendering.c b/src/rendering/twn_gl_15_rendering.c index b2701ad..246b78f 100644 --- a/src/rendering/twn_gl_15_rendering.c +++ b/src/rendering/twn_gl_15_rendering.c @@ -1,8 +1,7 @@ -#include "twn_gl_15_rendering_c.h" #include "twn_rendering_c.h" -#include "townengine/util.h" -#include "townengine/config.h" -#include "townengine/context.h" +#include "twn_util.h" +#include "twn_config.h" +#include "twn_engine_context_c.h" #include "twn_text_c.h" #include @@ -206,6 +205,7 @@ void use_texture_mode(enum texture_mode mode) { vertex_buffer_builder build_vertex_buffer(vertex_buffer buffer, size_t bytes) { glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, bytes, NULL, GL_STREAM_DRAW); void *mapping = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); if (!mapping) CRY("build_vertex_buffer", "Error mapping a vertex array buffer"); @@ -231,17 +231,19 @@ bool push_to_vertex_buffer_builder(vertex_buffer_builder *builder, return false; } + builder->mapping = (void *)((uintptr_t)builder->mapping + size); + return true; } void finally_render_sprites(const struct primitive_2d primitives[], const struct sprite_batch batch, - const vertex_buffer vertex_buffer) + const vertex_buffer buffer) { /* TODO: maybe do, dunno */ // glBindBuffer(GL_VERTEX_ARRAY, vertex_buffer); - (void)vertex_buffer; + (void)buffer; GLsizei off; GLsizei voff; @@ -360,13 +362,13 @@ bool push_sprite_payload_to_vertex_buffer_builder(struct sprite_batch batch, void finally_draw_uncolored_space_traingle_batch(const struct mesh_batch *batch, const t_texture_key texture_key, - const vertex_buffer vertex_buffer) + const vertex_buffer buffer) { const size_t primitives_len = arrlenu(batch->primitives); textures_bind(&ctx.texture_cache, texture_key); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, buffer); /* vertex specification*/ glEnableClientState(GL_VERTEX_ARRAY); @@ -399,7 +401,9 @@ bool push_text_payload_to_vertex_buffer_builder(struct font_data const *font_dat stbtt_aligned_quad quad) { (void)font_data; + (void)builder; + /* TODO: use vertex arrays */ glTexCoord2f(quad.s0, quad.t0); glVertex2f(quad.x0, quad.y0); glTexCoord2f(quad.s1, quad.t0); @@ -408,6 +412,8 @@ bool push_text_payload_to_vertex_buffer_builder(struct font_data const *font_dat glVertex2f(quad.x1, quad.y1); glTexCoord2f(quad.s0, quad.t1); glVertex2f(quad.x0, quad.y1); + + return false; } @@ -416,6 +422,9 @@ void finally_draw_text(struct font_data const *font_data, t_color color, vertex_buffer buffer) { + (void)len; + (void)buffer; + use_texture_mode(TEXTURE_MODE_GHOSTLY); glBindTexture(GL_TEXTURE_2D, font_data->texture); diff --git a/src/rendering/twn_gl_15_rendering_c.h b/src/rendering/twn_gl_15_rendering_c.h deleted file mode 100644 index 893a3ff..0000000 --- a/src/rendering/twn_gl_15_rendering_c.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef TWN_GL_15_RENDERING_H -#define TWN_GL_15_RENDERING_H - -/* - * OpenGL 1.5 and any 2.0+ compatibility version render implementation. - */ - -#include "twn_rendering_c.h" -#include "twn_gl_any_rendering_c.h" - -#ifdef EMSCRIPTEN -#include -#else -#include -#endif - -#include - - -void render_circle(const struct circle_primitive *circle); - -void render_rectangle(const struct rect_primitive *rectangle); - -void use_space_pipeline(void); - -void use_2d_pipeline(void); - -void use_texture_mode(enum texture_mode mode); - -/* uses present in 1.5 buffer mapping feature */ -vertex_buffer_builder build_vertex_buffer(vertex_buffer buffer, size_t bytes); - -/* collects bytes for sending to the gpu until all is pushed, which is when false is returned */ -bool push_to_vertex_buffer_builder(vertex_buffer_builder *builder, - void *bytes, - size_t size); - -void finally_render_sprites(struct primitive_2d const primitives[], - struct sprite_batch batch, - vertex_buffer buffer); - -size_t get_sprite_payload_size(struct sprite_batch batch); - -bool push_sprite_payload_to_vertex_buffer_builder(struct sprite_batch batch, - vertex_buffer_builder *builder, - t_fvec2 v0, t_fvec2 v1, t_fvec2 v2, t_fvec2 v3, - t_fvec2 uv0, t_fvec2 uv1, t_fvec2 uv2, t_fvec2 uv3, - t_color color); - -void finally_draw_uncolored_space_traingle_batch(struct mesh_batch const *batch, - t_texture_key texture_key, - vertex_buffer buffer); - -size_t get_text_payload_size(void); - -bool push_text_payload_to_vertex_buffer_builder(struct font_data const *font_data, - vertex_buffer_builder *builder, - stbtt_aligned_quad quad); - -void finally_draw_text(struct font_data const *font_data, - size_t len, - t_color color, - vertex_buffer buffer); - -#endif diff --git a/src/rendering/twn_gl_any_rendering.c b/src/rendering/twn_gl_any_rendering.c index c352de0..7625f20 100644 --- a/src/rendering/twn_gl_any_rendering.c +++ b/src/rendering/twn_gl_any_rendering.c @@ -1,6 +1,6 @@ -#include "twn_gl_any_rendering_c.h" -#include "townengine/context.h" -#include "townengine/util.h" +#include "twn_rendering_c.h" +#include "twn_engine_context_c.h" +#include "twn_util.h" #ifdef EMSCRIPTEN #include @@ -13,7 +13,6 @@ void setup_viewport(int x, int y, int width, int height) { glViewport(x, y, width, height); } -//////// VERTEX BUFFER //////// vertex_buffer create_vertex_buffer(void) { GLuint result; @@ -32,8 +31,6 @@ void specify_vertex_buffer(vertex_buffer buffer, void *data, size_t bytes) { glBufferData(GL_ARRAY_BUFFER, bytes, data, GL_STREAM_DRAW); } -//////// END OF VERTEX BUFFER //////// - void bind_quad_element_buffer(void) { static GLuint buffer = 0; diff --git a/src/rendering/twn_gl_any_rendering_c.h b/src/rendering/twn_gl_any_rendering_c.h deleted file mode 100644 index a1954aa..0000000 --- a/src/rendering/twn_gl_any_rendering_c.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef TWN_GL_ANY_RENDERING_H -#define TWN_GL_ANY_RENDERING_H - -/* - * Any OpenGL version base render methods. - */ - -#ifdef EMSCRIPTEN -#include -#else -#include -#endif - -#include - - -#define QUAD_ELEMENT_BUFFER_LENGTH (65536 / 6) - -typedef GLuint vertex_buffer; - -typedef struct vertex_buffer_builder { - size_t bytes_left; - void *mapping; -} vertex_buffer_builder; - - -vertex_buffer create_vertex_buffer(void); - -void delete_vertex_buffer(vertex_buffer buffer); - -void specify_vertex_buffer(vertex_buffer buffer, void *data, size_t bytes); - -void setup_viewport(int x, int y, int width, int height); - -void bind_quad_element_buffer(void); - -void clear_draw_buffer(void); - -void swap_buffers(void); - -void set_depth_range(double low, double high); - -#endif diff --git a/src/rendering/twn_gpu_texture.h b/src/rendering/twn_gpu_texture_c.h similarity index 58% rename from src/rendering/twn_gpu_texture.h rename to src/rendering/twn_gpu_texture_c.h index 6be52c2..6ed3d7e 100644 --- a/src/rendering/twn_gpu_texture.h +++ b/src/rendering/twn_gpu_texture_c.h @@ -1,15 +1,8 @@ -#ifndef TWN_GPU_TEXTURE_H -#define TWN_GPU_TEXTURE_H - -#ifdef EMSCRIPTEN -#include -#else -#include -#endif +#ifndef TWN_GPU_TEXTURE_C_H +#define TWN_GPU_TEXTURE_C_H #include - typedef GLuint gpu_texture; enum texture_filter { @@ -17,12 +10,11 @@ enum texture_filter { TEXTURE_FILTER_LINEAR, }; - gpu_texture create_gpu_texture(enum texture_filter filter, bool generate_mipmaps); void delete_gpu_texture(gpu_texture texture); -void specify_gpu_texture(gpu_texture texture, void *pixels, int channels, int width, int height); +void upload_gpu_texture(gpu_texture texture, void *pixels, int channels, int width, int height); void bind_gpu_texture(gpu_texture texture); diff --git a/src/rendering/twn_rendering.c b/src/rendering/twn_rendering.c index 01e9753..bd9b04e 100644 --- a/src/rendering/twn_rendering.c +++ b/src/rendering/twn_rendering.c @@ -1,10 +1,7 @@ #include "twn_rendering_c.h" -#include "townengine/twn_rendering.h" -#include "townengine/textures/internal_api.h" -#include "townengine/context.h" -#include "townengine/camera.h" - -#include "twn_rendering_platform.h" +#include "twn_rendering.h" +#include "twn_engine_context_c.h" +#include "twn_camera.h" #include #include @@ -114,23 +111,23 @@ void render(void) { textures_update_atlas(&ctx.texture_cache); /* fit rendering context onto the resizable screen */ - if (ctx.window_size_has_changed) { - if ((float)ctx.window_w / (float)ctx.window_h > RENDER_BASE_RATIO) { - float ratio = (float)ctx.window_h / (float)RENDER_BASE_HEIGHT; + if (ctx.game.window_size_has_changed) { + if ((float)ctx.game.window_w / (float)ctx.game.window_h > RENDER_BASE_RATIO) { + float ratio = (float)ctx.game.window_h / (float)RENDER_BASE_HEIGHT; int w = (int)((float)RENDER_BASE_WIDTH * ratio); setup_viewport( - ctx.window_w / 2 - w / 2, + ctx.game.window_w / 2 - w / 2, 0, w, - ctx.window_h + ctx.game.window_h ); } else { - float ratio = (float)ctx.window_w / (float)RENDER_BASE_WIDTH; + float ratio = (float)ctx.game.window_w / (float)RENDER_BASE_WIDTH; int h = (int)((float)RENDER_BASE_HEIGHT * ratio); setup_viewport( 0, - ctx.window_h / 2 - h / 2, - ctx.window_w, + ctx.game.window_h / 2 - h / 2, + ctx.game.window_w, h ); } diff --git a/src/rendering/twn_rendering_c.h b/src/rendering/twn_rendering_c.h index 166b606..f069bce 100644 --- a/src/rendering/twn_rendering_c.h +++ b/src/rendering/twn_rendering_c.h @@ -1,17 +1,35 @@ -#ifndef RENDERING_INTERNAL_API_H -#define RENDERING_INTERNAL_API_H +#ifndef TWN_RENDERING_C_H +#define TWN_RENDERING_C_H -#include "townengine/textures/internal_api.h" -#include "townengine/util.h" -#include "townengine/macros/option.h" +#include "twn_textures_c.h" +#include "twn_util.h" +#include "twn_option.h" #include +#include + +#ifdef EMSCRIPTEN +#include +#else +#include +#endif #include extern t_matrix4 camera_projection_matrix; extern t_matrix4 camera_look_at_matrix; +#define QUAD_ELEMENT_BUFFER_LENGTH (65536 / 6) + + +typedef GLuint vertex_buffer; + +typedef struct vertex_buffer_builder { + size_t bytes_left; + void *mapping; +} vertex_buffer_builder; + + struct sprite_primitive { t_frect rect; t_color color; @@ -100,22 +118,13 @@ struct text_cache { struct font_data **data; }; + /* renders the background, then the primitives in all render queues */ void render(void); /* clears all render queues */ void render_queue_clear(void); -void push_circle(t_fvec2 position, float radius, t_color color); - -void unfurl_triangle(const char *path, - t_fvec3 v0, - t_fvec3 v1, - t_fvec3 v2, - t_shvec2 uv0, - t_shvec2 uv1, - t_shvec2 uv2); - void create_circle_geometry(t_fvec2 position, t_color color, float radius, @@ -136,10 +145,77 @@ void render_sprites(const struct primitive_2d primitives[], void draw_uncolored_space_traingle_batch(struct mesh_batch *batch, t_texture_key texture_key); +/* text */ + void render_text(const struct text_primitive *text); void text_cache_init(struct text_cache *cache); void text_cache_deinit(struct text_cache *cache); +/* vertex buffer */ + +vertex_buffer create_vertex_buffer(void); + +void delete_vertex_buffer(vertex_buffer buffer); + +void specify_vertex_buffer(vertex_buffer buffer, void *data, size_t bytes); + +/* uses present in 1.5 buffer mapping feature */ +vertex_buffer_builder build_vertex_buffer(vertex_buffer buffer, size_t bytes); + +/* collects bytes for sending to the gpu until all is pushed, which is when false is returned */ +bool push_to_vertex_buffer_builder(vertex_buffer_builder *builder, + void *bytes, + size_t size); + +/* state */ + +void setup_viewport(int x, int y, int width, int height); + +void clear_draw_buffer(void); + +void swap_buffers(void); + +void set_depth_range(double low, double high); + +void bind_quad_element_buffer(void); + +void render_circle(const struct circle_primitive *circle); + +void render_rectangle(const struct rect_primitive *rectangle); + +void use_space_pipeline(void); + +void use_2d_pipeline(void); + +void use_texture_mode(enum texture_mode mode); + +void finally_render_sprites(struct primitive_2d const primitives[], + struct sprite_batch batch, + vertex_buffer buffer); + +size_t get_sprite_payload_size(struct sprite_batch batch); + +bool push_sprite_payload_to_vertex_buffer_builder(struct sprite_batch batch, + vertex_buffer_builder *builder, + t_fvec2 v0, t_fvec2 v1, t_fvec2 v2, t_fvec2 v3, + t_fvec2 uv0, t_fvec2 uv1, t_fvec2 uv2, t_fvec2 uv3, + t_color color); + +void finally_draw_uncolored_space_traingle_batch(struct mesh_batch const *batch, + t_texture_key texture_key, + vertex_buffer buffer); + +size_t get_text_payload_size(void); + +bool push_text_payload_to_vertex_buffer_builder(struct font_data const *font_data, + vertex_buffer_builder *builder, + stbtt_aligned_quad quad); + +void finally_draw_text(struct font_data const *font_data, + size_t len, + t_color color, + vertex_buffer buffer); + #endif diff --git a/src/rendering/twn_rendering_platform.h b/src/rendering/twn_rendering_platform.h deleted file mode 100644 index 5d8769e..0000000 --- a/src/rendering/twn_rendering_platform.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef TWN_RENDERING_PLATFORM_H -#define TWN_RENDERING_PLATFORM_H - -#ifdef EMSCRIPTEN -#include "twn_gl_es2_rendering_c.h" -#else -#include "twn_gl_15_rendering_c.h" -#endif - -#endif diff --git a/src/rendering/twn_sprites.c b/src/rendering/twn_sprites.c index 65de357..5be3149 100644 --- a/src/rendering/twn_sprites.c +++ b/src/rendering/twn_sprites.c @@ -1,9 +1,8 @@ -#include "townengine/twn_rendering.h" +#include "twn_rendering.h" #include "twn_rendering_c.h" -#include "townengine/context.h" -#include "townengine/util.h" -#include "townengine/textures/internal_api.h" -#include "twn_rendering_platform.h" +#include "twn_engine_context_c.h" +#include "twn_util.h" +#include "twn_textures_c.h" #include @@ -103,7 +102,7 @@ void render_sprites(const struct primitive_2d primitives[], if (vertex_array == 0) vertex_array = create_vertex_buffer(); - use_sprite_blendmode(batch.mode); + use_texture_mode(batch.mode); const t_frect dims = textures_get_dims(&ctx.texture_cache, primitives->sprite.texture_key); diff --git a/src/rendering/twn_text.c b/src/rendering/twn_text.c index 9326f68..af83872 100644 --- a/src/rendering/twn_text.c +++ b/src/rendering/twn_text.c @@ -1,10 +1,8 @@ #include "twn_rendering_c.h" -#include "townengine/util.h" -#include "townengine/config.h" -#include "townengine/context.h" -#include "townengine/twn_rendering.h" - -#include "twn_rendering_platform.h" +#include "twn_rendering.h" +#include "twn_util.h" +#include "twn_config.h" +#include "twn_engine_context_c.h" #include @@ -66,7 +64,7 @@ static struct font_data *text_load_font_data(const char *path, int height_px) { } font_data->texture = create_gpu_texture(TEXT_FONT_FILTERING, true); - specify_gpu_texture( + upload_gpu_texture( font_data->texture, bitmap, 1, diff --git a/src/rendering/twn_text_c.h b/src/rendering/twn_text_c.h index b828fcf..d1940df 100644 --- a/src/rendering/twn_text_c.h +++ b/src/rendering/twn_text_c.h @@ -1,5 +1,3 @@ -#include "twn_rendering_platform.h" - #include diff --git a/src/rendering/twn_triangles.c b/src/rendering/twn_triangles.c index 3efa630..4be105a 100644 --- a/src/rendering/twn_triangles.c +++ b/src/rendering/twn_triangles.c @@ -1,7 +1,6 @@ #include "twn_rendering_c.h" -#include "twn_context.h" +#include "twn_engine_context_c.h" #include "twn_textures_c.h" -#include "twn_rendering_platform.h" #include diff --git a/src/twn_audio.c b/src/twn_audio.c index 5d6e9d1..acbc02b 100644 --- a/src/twn_audio.c +++ b/src/twn_audio.c @@ -1,7 +1,7 @@ -#include "townengine/audio/internal_api.h" -#include "townengine/config.h" -#include "townengine/context.h" -#include "townengine/util.h" +#include "twn_audio_c.h" +#include "twn_config.h" +#include "twn_engine_context_c.h" +#include "twn_util.h" #include #include diff --git a/src/twn_camera.c b/src/twn_camera.c index c33812e..267a503 100644 --- a/src/twn_camera.c +++ b/src/twn_camera.c @@ -1,5 +1,5 @@ #include "twn_camera.h" -#include "twn_context.h" +#include "twn_engine_context_c.h" #include diff --git a/src/twn_context.c b/src/twn_context.c index afb3142..30a9143 100644 --- a/src/twn_context.c +++ b/src/twn_context.c @@ -1,3 +1,5 @@ #include "twn_engine_context_c.h" +/* internally there's only one context, but it gets type casted to game and engine variants based on which header is included */ +/* engine parts should never mix twn_engine_context_c.h with twn_context.h */ t_engine_ctx ctx = {0}; diff --git a/src/twn_engine_context_c.h b/src/twn_engine_context_c.h index 691cc73..8854cc9 100644 --- a/src/twn_engine_context_c.h +++ b/src/twn_engine_context_c.h @@ -1,9 +1,10 @@ -#ifndef TWN_ENGINE_CONTEXT_H -#define TWN_ENGINE_CONTEXT_H +#ifndef TWN_ENGINE_CONTEXT_C_H +#define TWN_ENGINE_CONTEXT_C_H #include "twn_context.h" -#include "textures/internal_api.h" +#include "twn_textures_c.h" #include "twn_input.h" +#include "rendering/twn_rendering_c.h" #include @@ -12,7 +13,8 @@ typedef struct engine_context { - t_ctx game_context; + /* user code facing context */ + t_ctx game; /* the program's actual argc and argv */ int argc; @@ -45,6 +47,6 @@ typedef struct engine_context { bool was_successful; } t_engine_ctx; -extern t_engine_ctx ctx = ; +extern t_engine_ctx ctx; #endif diff --git a/src/twn_game_object_c.h b/src/twn_game_object_c.h index a7b54e9..2c50ad9 100644 --- a/src/twn_game_object_c.h +++ b/src/twn_game_object_c.h @@ -1,5 +1,5 @@ -#ifndef TWN_GAME_OBJECT_H -#define TWN_GAME_OBJECT_H +#ifndef TWN_GAME_OBJECT_C_H +#define TWN_GAME_OBJECT_C_H #include diff --git a/src/twn_input.c b/src/twn_input.c index 9b45e11..a589720 100644 --- a/src/twn_input.c +++ b/src/twn_input.c @@ -1,6 +1,5 @@ -#include "townengine/input/internal_api.h" -#include "townengine/context.h" -#include "townengine/util.h" +#include "twn_input_c.h" +#include "twn_util.h" #include #include diff --git a/src/twn_input_c.h b/src/twn_input_c.h index b66e465..06a6f4a 100644 --- a/src/twn_input_c.h +++ b/src/twn_input_c.h @@ -1,7 +1,7 @@ #ifndef INPUT_INTERNAL_API_H #define INPUT_INTERNAL_API_H -#include "townengine/input.h" +#include "twn_input.h" void input_reset_state(struct input_state *input); diff --git a/src/twn_loop.c b/src/twn_loop.c index 6f73c38..8d56764 100644 --- a/src/twn_loop.c +++ b/src/twn_loop.c @@ -1,12 +1,11 @@ #include "twn_loop.h" -#include "townengine/context.h" -#include "townengine/rendering.h" -#include "townengine/input/internal_api.h" -#include "townengine/util.h" -#include "townengine/twn_game_object.h" -#include "townengine/audio/internal_api.h" -#include "townengine/textures/internal_api.h" -#include "townengine/rendering/internal_api.h" +#include "twn_engine_context_c.h" +#include "twn_input_c.h" +#include "twn_util.h" +#include "twn_game_object_c.h" +#include "twn_audio_c.h" +#include "twn_textures_c.h" +#include "twn_rendering.h" #include #include @@ -28,12 +27,12 @@ static void poll_events(void) { SDL_Event e; - ctx.window_size_has_changed = false; + ctx.game.window_size_has_changed = false; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: - ctx.is_running = false; + ctx.game.is_running = false; break; case SDL_WINDOWEVENT: @@ -42,7 +41,7 @@ static void poll_events(void) { switch (e.window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: - ctx.window_size_has_changed = true; + ctx.game.window_size_has_changed = true; break; default: @@ -93,7 +92,7 @@ static void main_loop(void) { int64_t current_frame_time = SDL_GetPerformanceCounter(); int64_t delta_time = current_frame_time - ctx.prev_frame_time; ctx.prev_frame_time = current_frame_time; - ctx.delta_time = delta_time; + ctx.game.delta_time = delta_time; /* handle unexpected timer anomalies (overflow, extra slow frames, etc) */ if (delta_time > ctx.desired_frametime * 8) { /* ignore extra-slow frames */ @@ -159,28 +158,28 @@ static void main_loop(void) { /* finally, let's get to work */ int frames = 0; - while (ctx.frame_accumulator >= ctx.desired_frametime * ctx.update_multiplicity) { + while (ctx.frame_accumulator >= ctx.desired_frametime * ctx.game.update_multiplicity) { frames += 1; - for (size_t i = 0; i < ctx.update_multiplicity; ++i) { + for (size_t i = 0; i < ctx.game.update_multiplicity; ++i) { /* TODO: disable rendering pushes on not-last ? */ render_queue_clear(); poll_events(); - if (ctx.window_size_has_changed) { + if (ctx.game.window_size_has_changed) { t_vec2 size; SDL_GetWindowSize(ctx.window, &size.x, &size.y); - ctx.window_w = size.x; - ctx.window_h = size.y; + ctx.game.window_w = size.x; + ctx.game.window_h = size.y; } - input_state_update(&ctx.input); + input_state_update(&ctx.game.input); game_object_tick(); ctx.frame_accumulator -= ctx.desired_frametime; - ctx.tick_count = (ctx.tick_count % ULLONG_MAX) + 1; - ctx.initialization_needed = false; + ctx.game.tick_count = (ctx.game.tick_count % ULLONG_MAX) + 1; + ctx.game.initialization_needed = false; } } @@ -202,9 +201,9 @@ static bool initialize(void) { /* debug mode _defaults_ to being enabled on debug builds. */ /* you should be able to enable it at runtime on any build */ #ifndef NDEBUG - ctx.debug = true; + ctx.game.debug = true; #else - ctx.debug = false; + ctx.game.debug = false; #endif #ifdef EMSCRIPTEN @@ -215,7 +214,7 @@ static bool initialize(void) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); - if (ctx.debug) + if (ctx.game.debug) SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); else SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_NO_ERROR); @@ -279,8 +278,8 @@ static bool initialize(void) { /* TODO: */ // SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h); - ctx.window_w = RENDER_BASE_WIDTH; - ctx.window_h = RENDER_BASE_HEIGHT; + ctx.game.window_w = RENDER_BASE_WIDTH; + ctx.game.window_h = RENDER_BASE_HEIGHT; /* audio initialization */ { @@ -312,11 +311,11 @@ static bool initialize(void) { } /* you could change this at runtime if you wanted */ - ctx.update_multiplicity = 1; + ctx.game.update_multiplicity = 1; #ifndef EMSCRIPTEN /* hook up opengl debugging callback */ - if (ctx.debug) { + if (ctx.game.debug) { glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(opengl_log, NULL); } @@ -325,18 +324,18 @@ static bool initialize(void) { /* random seeding */ /* SDL_GetPerformanceCounter returns some platform-dependent number. */ /* it should vary between game instances. i checked! random enough for me. */ - ctx.random_seed = SDL_GetPerformanceCounter(); - srand((unsigned int)ctx.random_seed); - stbds_rand_seed(ctx.random_seed); + ctx.game.random_seed = SDL_GetPerformanceCounter(); + srand((unsigned int)ctx.game.random_seed); + stbds_rand_seed(ctx.game.random_seed); /* main loop machinery */ - ctx.is_running = true; + ctx.game.is_running = true; ctx.resync_flag = true; ctx.clocks_per_second = SDL_GetPerformanceFrequency(); ctx.prev_frame_time = SDL_GetPerformanceCounter(); ctx.desired_frametime = ctx.clocks_per_second / TICKS_PER_SECOND; ctx.frame_accumulator = 0; - ctx.tick_count = 0; + ctx.game.tick_count = 0; /* delta time averaging */ ctx.delta_averager_residual = 0; @@ -353,7 +352,7 @@ static bool initialize(void) { text_cache_init(&ctx.text_cache); /* input */ - input_state_init(&ctx.input); + input_state_init(&ctx.game.input); /* scripting */ /* @@ -376,7 +375,7 @@ static void clean_up(void) { scripting_deinit(ctx); */ - input_state_deinit(&ctx.input); + input_state_deinit(&ctx.game.input); /* if you're gonna remove this, it's also being done in rendering.c */ for (size_t i = 0; i < arrlenu(ctx.render_queue_2d); ++i) { @@ -395,7 +394,7 @@ static void clean_up(void) { static void reset_state(void) { - input_reset_state(&ctx.input); + input_reset_state(&ctx.game.input); textures_reset_state(); } @@ -420,11 +419,11 @@ int enter_loop(int argc, char **argv) { game_object_load(); ctx.was_successful = true; - ctx.initialization_needed = true; + ctx.game.initialization_needed = true; - while (ctx.is_running) { + while (ctx.game.is_running) { if (game_object_try_reloading()) { - ctx.initialization_needed = true; + ctx.game.initialization_needed = true; reset_state(); } diff --git a/src/twn_textures.c b/src/twn_textures.c index a4d1bcb..48fbe5c 100644 --- a/src/twn_textures.c +++ b/src/twn_textures.c @@ -1,7 +1,6 @@ -#include "townengine/textures/internal_api.h" -#include "townengine/config.h" -#include "townengine/util.h" -#include "townengine/context.h" +#include "twn_textures_c.h" +#include "twn_config.h" +#include "twn_util.h" #include #include @@ -123,7 +122,7 @@ static void add_new_atlas(struct texture_cache *cache) { static void upload_texture_from_surface(gpu_texture texture, SDL_Surface *surface) { SDL_LockSurface(surface); - specify_gpu_texture(texture, surface->pixels, surface->w, surface->h); + upload_gpu_texture(texture, surface->pixels, 4, surface->w, surface->h); SDL_UnlockSurface(surface); } @@ -404,7 +403,7 @@ void textures_update_atlas(struct texture_cache *cache) { /* EXPERIMANTAL: LIKELY TO BE REMOVED! */ #if defined(__linux__) && !defined(HOT_RELOAD_SUPPORT) /* use rodata elf section for fast lookups of repeating textures */ -#include "townengine/system/linux/elf.h" +#include "system/linux/twn_elf.h" static const char *rodata_start; static const char *rodata_stop; @@ -528,10 +527,11 @@ void textures_bind_repeating(const struct texture_cache *cache, t_texture_key ke SDL_LockSurface(texture.data); - specify_gpu_texture(repeating_texture, - texture.data->pixels, - texture.data->w, - texture.data->h); + upload_gpu_texture(repeating_texture, + texture.data->pixels, + 4, + texture.data->w, + texture.data->h); SDL_UnlockSurface(texture.data); diff --git a/src/twn_textures_c.h b/src/twn_textures_c.h index 5846df0..6dfbaeb 100644 --- a/src/twn_textures_c.h +++ b/src/twn_textures_c.h @@ -1,16 +1,16 @@ -#ifndef TWN_TEXTURES_H -#define TWN_TEXTURES_H +#ifndef TWN_TEXTURES_C_H +#define TWN_TEXTURES_C_H #include "twn_util.h" #include "twn_texture_modes.h" -#include "twn_engine_api.h" -#include "twn_gpu_texture.h" +#include "rendering/twn_gpu_texture_c.h" #include #include #include + struct texture { t_frect srcrect; /* position in atlas */ SDL_Surface *data; /* original image data */ diff --git a/src/twn_util.c b/src/twn_util.c index 3db90b2..c8574f5 100644 --- a/src/twn_util.c +++ b/src/twn_util.c @@ -1,5 +1,5 @@ #include "twn_util.h" -#include "twn_context.h" +#include "twn_engine_context_c.h" #include #include @@ -218,11 +218,11 @@ void tick_timer(int *value) { } void tick_ftimer(float *value) { - *value = MAX(*value - ((float)ctx.delta_time / (float)ctx.clocks_per_second), 0.0f); + *value = MAX(*value - ((float)ctx.game.delta_time / (float)ctx.clocks_per_second), 0.0f); } bool repeat_ftimer(float *value, float at) { - *value -= (float)ctx.delta_time / (float)ctx.clocks_per_second; + *value -= (float)ctx.game.delta_time / (float)ctx.clocks_per_second; if (*value < 0.0f) { *value += at; return true;