diff --git a/README.md b/README.md index 45aa30d..778c7fb 100644 --- a/README.md +++ b/README.md @@ -155,10 +155,13 @@ - ## TODO + - Fix bugs with sprite batch renderer not working with projection matrix + - Implement necessary changes to run Soloud on linux + - Get rid of pkg-confg and system-installed SDL2 dependancy on linux and instead put custom compiled SDL libs in third_party similar to how we're handling it in windows + - Add fallback shader + - Implement Game States - Store Materials in new format supported by parser - Add model description file which has the same syntax supported by parser and modify old blender exporter to conform to new standards - - Implement sound/listener loading from scene file - - Finish loading scene from file - Update makefiles to be able to compile the code in it's current state - Find a solution for the asset import/export situation by either updating the blender exporter or adding assimp as dependancy - Fix bugs with sound sources not updating @@ -330,4 +333,10 @@ * Implmented writing to file through the new Parser and Parser_Objects * Changed Config to read/write using new Parser and Parser_Objects * Implemented Reading/Writing keybindings using new parser object - * Replaced OpenAL with Soloud with SDL2 backend \ No newline at end of file + * Replaced OpenAL with Soloud with SDL2 backend + * Implemented sound/listener loading from scene file + * Finished loading scene from file + * Initial implementation of immediate-mode batched sprite render + * Fixed bugs with shader include file pre-processor + * Fixed bugs with editor's camera property viewer + * Fixed bugs related to changing camera projection diff --git a/assets/shaders/sprite.frag b/assets/shaders/sprite.frag new file mode 100644 index 0000000..ebd1fa9 --- /dev/null +++ b/assets/shaders/sprite.frag @@ -0,0 +1,14 @@ +//include version.glsl + +in vec2 uv; +in vec4 color; + +uniform sampler2D sampler; + +out vec4 frag_color; + +void main() +{ + frag_color = color * texture(sampler, uv); + //frag_color = vec4(0, 1, 0, 1); +} diff --git a/assets/shaders/sprite.vert b/assets/shaders/sprite.vert new file mode 100644 index 0000000..1d00706 --- /dev/null +++ b/assets/shaders/sprite.vert @@ -0,0 +1,17 @@ +//include version.glsl + +uniform mat4 mvp; + +in vec3 vPosition; +in vec2 vUV; +in vec4 vColor; + +out vec2 uv; +out vec4 color; + +void main() +{ + gl_Position = mvp * vec4(vPosition, 1.0); + uv = vUV; + color = vColor; +} diff --git a/src/common/log.c b/src/common/log.c index 66e7143..38ded42 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -74,6 +74,18 @@ void log_to_stdout(const char* message, ...) printf("\n%s", COL_RESET); } +void log_raw(const char* str, ...) +{ + va_list console_list, file_list; + va_start(console_list, str); + va_copy(file_list, console_list); + vfprintf(log_file, str, file_list); + vprintf(str, console_list); + va_end(console_list); + va_end(file_list); + fflush(log_file); +} + void log_message(const char* message, ...) { printf("%sMSG : ", COL_DEFAULT); diff --git a/src/common/log.h b/src/common/log.h index 256d028..99980b5 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -9,6 +9,7 @@ void log_message(const char* message, ...); void log_warning(const char* message, ...); void log_error(const char* context, const char* error, ...); void log_to_stdout(const char* message, ...); /* Only use when logging is not initialized */ +void log_raw(const char* str, ...); FILE* log_file_handle_get(void); void log_file_handle_set(FILE* file); diff --git a/src/libsymmetry/camera.c b/src/libsymmetry/camera.c index 0be17aa..0255a49 100644 --- a/src/libsymmetry/camera.c +++ b/src/libsymmetry/camera.c @@ -5,6 +5,7 @@ #include "../common/array.h" #include "framebuffer.h" #include "texture.h" +#include "game.h" #include "bounding_volumes.h" #include "../common/utils.h" @@ -44,8 +45,8 @@ void camera_create(struct Entity* entity, int width, int height) camera->farz = 1000.f; camera->nearz = 0.1f; camera->fov = 60.f; - camera->ortho = 0; - camera->resizeable = 1; + camera->ortho = false; + camera->resizeable = true; float aspect_ratio = (float)width / (float)height; camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; mat4_identity(&camera->view_mat); @@ -62,7 +63,10 @@ void camera_update_view_proj(struct Entity* entity) { struct Camera* camera = &entity->camera; mat4_identity(&camera->view_proj_mat); - mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat); + if(camera->ortho) + mat4_mul(&camera->view_proj_mat, &camera->view_proj_mat, &camera->proj_mat); + else + mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat); update_frustum(camera); } @@ -92,7 +96,11 @@ void camera_update_proj(struct Entity* entity) } else { - mat4_ortho(&camera->proj_mat, -1, 1, -1, 1, camera->nearz, camera->farz); + int width, height; + struct Game_State* game_state = game_state_get(); + platform->window.get_size(game_state->window, &width, &height); + + mat4_ortho(&camera->proj_mat, 0, width, height, 0, camera->nearz, camera->farz); } camera_update_view_proj(entity); } diff --git a/src/libsymmetry/editor.c b/src/libsymmetry/editor.c index aad42ef..9c10dff 100644 --- a/src/libsymmetry/editor.c +++ b/src/libsymmetry/editor.c @@ -373,20 +373,49 @@ void editor_update(float dt) { if(nk_tree_push(context, NK_TREE_TAB, "Camera", NK_MAXIMIZED)) { + bool update = false; struct Camera* camera = &entity->camera; - - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio); + if(!camera->ortho) + { + nk_layout_row_dynamic(context, row_height, 1); + float new_fov = nk_propertyf(context, "Fov", 30.f, camera->fov, 90.f, 0.1f, 1.f); + if(new_fov != camera->fov) + { + camera->fov = new_fov; + update = true; + } + + nk_layout_row_dynamic(context, row_height, 2); + nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio); + } + + nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Clear Color", NK_TEXT_ALIGN_CENTERED); nk_layout_row_dynamic(context, row_height, 1); - nk_property_float(context, "Fov", 45.f, &camera->fov, 90.f, 1.f, 5.f); + editor_widget_color_combov4(context, &camera->clear_color, 200, 300); nk_layout_row_dynamic(context, row_height, 1); - nk_property_float(context, "NearZ", 0.01f, &camera->nearz, camera->farz, 0.1f, 1.f); + float new_near_z = nk_propertyf(context, "NearZ", -FLT_MAX, camera->nearz, camera->farz, 0.1f, 1.f); + if(new_near_z != camera->nearz) + { + camera->nearz = new_near_z; + update = true; + } nk_layout_row_dynamic(context, row_height, 1); - nk_property_float(context, "FarZ", camera->nearz, &camera->farz, FLT_MAX, 1.f, 5.f); - + float new_far_z = nk_propertyf(context, "FarZ", camera->nearz, camera->farz, FLT_MAX, 0.1f, 2.f); + if(new_far_z != camera->farz) + { + camera->farz = new_far_z; + update = true; + } + + if(update) + { + if(!camera->ortho) camera_update_view(entity); + camera_update_proj(entity); + } + nk_tree_pop(context); } } diff --git a/src/libsymmetry/game.c b/src/libsymmetry/game.c index fb00c4c..9f492ba 100644 --- a/src/libsymmetry/game.c +++ b/src/libsymmetry/game.c @@ -24,6 +24,7 @@ #include "gl_load.h" #include "gui.h" #include "editor.h" +#include "sprite.h" #include "../common/parser.h" #include "../common/hashmap.h" #include "../common/variant.h" @@ -216,6 +217,12 @@ void scene_setup(void) struct Entity* player = entity_find("player"); game_state->player_node = player->id; + /*struct Camera* camera = &player->camera; + camera->ortho = true; + camera->farz = 1.f; + camera->nearz = -1.f; + camera_update_proj(player);*/ + /*struct Entity* suz = entity_find("Suzanne"); struct Entity* sound_ent = scene_add_as_child("Sound_Ent", ET_SOUND_SOURCE, suz->id); struct Sound_Source* sound_source = &sound_ent->sound_source; @@ -363,6 +370,36 @@ void debug(float dt) transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD); vec3 amount = {0, 0, -5 * dt}; transform_translate(model, &amount, TS_LOCAL); + + struct Sprite_Batch* batch = get_batch(); + + sprite_batch_begin(batch); + static struct Sprite sprite; + + sprite.vertices[0].pos.x = 0.f; sprite.vertices[0].pos.y = 0.f; sprite.vertices[0].pos.z = 0.f; + sprite.vertices[1].pos.x = 1.f; sprite.vertices[1].pos.y = 0.f; sprite.vertices[1].pos.z = 0.f; + sprite.vertices[2].pos.x = 0.f; sprite.vertices[2].pos.y = 1.f; sprite.vertices[2].pos.z = 0.f; + sprite.vertices[3].pos.x = 0.f; sprite.vertices[3].pos.y = 1.f; sprite.vertices[3].pos.z = 0.f; + sprite.vertices[4].pos.x = 1.f; sprite.vertices[4].pos.y = 1.f; sprite.vertices[4].pos.z = 0.f; + sprite.vertices[5].pos.x = 1.f; sprite.vertices[5].pos.y = 0.f; sprite.vertices[5].pos.z = 0.f; + + sprite.vertices[0].uv.x = 0.f; sprite.vertices[0].uv.y = 0.f; + sprite.vertices[1].uv.x = 1.f; sprite.vertices[1].uv.y = 0.f; + sprite.vertices[2].uv.x = 0.f; sprite.vertices[2].uv.y = 1.f; + sprite.vertices[3].uv.x = 0.f; sprite.vertices[3].uv.y = 1.f; + sprite.vertices[4].uv.x = 1.f; sprite.vertices[4].uv.y = 1.f; + sprite.vertices[5].uv.x = 1.f; sprite.vertices[5].uv.y = 0.f; + + sprite.vertices[0].color.x = 0.f; sprite.vertices[0].color.y = 0.f; sprite.vertices[0].color.z = 0.f; sprite.vertices[0].color.w = 1.f; + sprite.vertices[1].color.x = 1.f; sprite.vertices[1].color.y = 0.f; sprite.vertices[1].color.z = 0.f; sprite.vertices[1].color.w = 1.f; + sprite.vertices[2].color.x = 0.f; sprite.vertices[2].color.y = 1.f; sprite.vertices[2].color.z = 0.f; sprite.vertices[2].color.w = 1.f; + sprite.vertices[3].color.x = 1.f; sprite.vertices[3].color.y = 1.f; sprite.vertices[3].color.z = 0.f; sprite.vertices[3].color.w = 1.f; + sprite.vertices[4].color.x = 1.f; sprite.vertices[4].color.y = 1.f; sprite.vertices[4].color.z = 0.f; sprite.vertices[4].color.w = 1.f; + sprite.vertices[5].color.x = 1.f; sprite.vertices[5].color.y = 1.f; sprite.vertices[5].color.z = 0.f; sprite.vertices[5].color.w = 1.f; + + sprite_batch_add_sprite(batch, &sprite); + + sprite_batch_end(batch); } bool run(void) diff --git a/src/libsymmetry/gl_load.h b/src/libsymmetry/gl_load.h index 7d62a21..aa2902c 100644 --- a/src/libsymmetry/gl_load.h +++ b/src/libsymmetry/gl_load.h @@ -8,7 +8,6 @@ #else -#include #define SYMMETRY_GL_LIST \ /* ret, name, params */ \ diff --git a/src/libsymmetry/renderer.c b/src/libsymmetry/renderer.c index a3a720f..966b0fc 100644 --- a/src/libsymmetry/renderer.c +++ b/src/libsymmetry/renderer.c @@ -18,6 +18,7 @@ #include "geometry.h" #include "material.h" #include "editor.h" +#include "sprite.h" #include "../common/variant.h" #include "../common/common.h" @@ -38,6 +39,8 @@ static int num_culled = 0, num_rendered = 0, num_indices = 0; static int num_culled_slot = -1, num_rendered_slot = -1, num_indices_slot = -1; +static struct Sprite_Batch* sprite_batch = NULL; + void on_framebuffer_size_change(int width, int height); void renderer_init(void) @@ -117,6 +120,16 @@ void renderer_init(void) num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT); num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT); num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT); + + sprite_batch = malloc(sizeof(*sprite_batch)); + if(!sprite_batch) + { + log_error("renderer:init", "Failed to allocated sprite batch"); + } + else + { + sprite_batch_create(sprite_batch, "sprite_map.tga", "sprite.vert", "sprite.frag", GL_TRIANGLES); + } } void renderer_draw(struct Entity* active_viewer) @@ -390,12 +403,30 @@ void renderer_draw(struct Entity* active_viewer) shader_unbind(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } - + + /* Render 2D stuff */ + shader_bind(sprite_batch->shader); + { + static mat4 ortho_mat; + mat4_identity(&ortho_mat); + /*int width, height; + struct Game_State* game_state = game_state_get(); + platform->window.get_size(game_state->window, &width, &height); + + mat4_ortho(&ortho_mat, 0, width, height, 0, -1.f, 1.f);*/ + shader_set_uniform_mat4(sprite_batch->shader, "mvp", &ortho_mat); + + sprite_batch_render(sprite_batch); + } + shader_unbind(); + + /* Render UI */ gui_render(NK_ANTI_ALIASING_ON); } void renderer_cleanup(void) { + free(sprite_batch); gui_cleanup(); geom_remove(quad_geo); framebuffer_remove(def_fbo); @@ -445,6 +476,11 @@ int renderer_check_glerror(const char* context) error = 0; return error; +} + +struct Sprite_Batch * get_batch(void) +{ + return sprite_batch; } void renderer_debug_draw_enabled(bool enabled) diff --git a/src/libsymmetry/renderer.h b/src/libsymmetry/renderer.h index 791165e..b73c304 100644 --- a/src/libsymmetry/renderer.h +++ b/src/libsymmetry/renderer.h @@ -32,6 +32,7 @@ struct Render_Settings }; struct Entity; +struct Sprite_Batch; void renderer_settings_get(struct Render_Settings* settings); void renderer_settings_set(const struct Render_Settings* settings); @@ -42,4 +43,6 @@ void renderer_clearcolor_set(float r, float g, float b, float a); void renderer_debug_draw_enabled(bool enabled); int renderer_check_glerror(const char* context); +struct Sprite_Batch* get_batch(void); + #endif diff --git a/src/libsymmetry/shader.c b/src/libsymmetry/shader.c index 4568424..4c07183 100644 --- a/src/libsymmetry/shader.c +++ b/src/libsymmetry/shader.c @@ -13,28 +13,24 @@ #include #include -// Constants for locations of attributes inside all shaders -const int POSITION_LOC = 0; -const int NORMAL_LOC = 1; -const int UV_LOC = 2; -const int COLOR_LOC = 3; - static uint* shader_list; static int* empty_indices; +#define MAX_INCLUDE_LINE_LEN 256 + void debug_print_shader(const char* shaderText) { size_t len = strlen(shaderText); int line_count = 1; - printf("%d. ", line_count); + log_raw("%d. ", line_count); for(uint i = 0; i < len; i++) { if(shaderText[i] != '\n') - printf("%c", shaderText[i]); + log_raw("%c", shaderText[i]); else - printf("\n%d. ", ++line_count); + log_raw("\n%d. ", ++line_count); } - printf("\n END_DEBUG_PRINT\n\n"); + log_raw("\n END_DEBUG_PRINT\n\n"); } char* run_preprocessor(char* shader_text) @@ -42,40 +38,32 @@ char* run_preprocessor(char* shader_text) char* include_loc = strstr(shader_text, "//include"); if(include_loc) { - char* line_end = strchr(include_loc, '\n'); - int line_size = line_end - include_loc; - char* inc_line = malloc((sizeof(char) * line_size) + 1); - strncpy(inc_line, include_loc, line_size); - inc_line[line_size] = '\0'; + char inc_line[MAX_INCLUDE_LINE_LEN]; + memset(inc_line, '\0', MAX_INCLUDE_LINE_LEN); + + char fmt_str[64]; + snprintf(fmt_str, 64, "//include %%%d[^\r\n]", MAX_INCLUDE_LINE_LEN); + sscanf(shader_text, fmt_str, inc_line); char* filename = strtok(inc_line, " "); while(filename) { - filename = strtok(NULL, " "); if(filename) { char* path = str_new("shaders/"); path = str_concat(path, filename); - char* file = platform->file.read(DIRT_INSTALL, path, "r", NULL); - char* shader_copy = str_new(shader_text); - char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2)); - if(temp) + char* file_contents = platform->file.read(DIRT_INSTALL, path, "rb", NULL); + if(file_contents) { - shader_text = temp; - strcpy(shader_text, file); - strcat(shader_text, shader_copy); + char* shader_text_new = str_new("%s\n%s", file_contents, shader_text); + free(shader_text); + free(file_contents); + free(path); + shader_text = shader_text_new; } - else - { - log_warning("Realloc failed in Shader::run_preprocessor"); - } - - free(path); - free(shader_copy); - free(file); } + filename = strtok(NULL, " "); } - free(inc_line); } return shader_text; } @@ -96,8 +84,8 @@ int shader_create(const char* vert_shader_name, const char* frag_shader_name) GLuint vert_shader = glCreateShader(GL_VERTEX_SHADER); GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER); - char* vert_source = platform->file.read(DIRT_INSTALL, vs_path, "r", NULL); - char* frag_source = platform->file.read(DIRT_INSTALL, fs_path, "r", NULL); + char* vert_source = platform->file.read(DIRT_INSTALL, vs_path, "rb", NULL); + char* frag_source = platform->file.read(DIRT_INSTALL, fs_path, "rb", NULL); assert(vert_source != NULL); assert(frag_source != NULL); @@ -164,10 +152,10 @@ int shader_create(const char* vert_shader_name, const char* frag_shader_name) glAttachShader(program, frag_shader); // Bind attribute locations - glBindAttribLocation(program, POSITION_LOC, "vPosition"); - glBindAttribLocation(program, NORMAL_LOC, "vNormal"); - glBindAttribLocation(program, UV_LOC, "vUV"); - glBindAttribLocation(program, COLOR_LOC, "vColor"); + glBindAttribLocation(program, AL_POSITION, "vPosition"); + glBindAttribLocation(program, AL_NORMAL, "vNormal"); + glBindAttribLocation(program, AL_UV, "vUV"); + glBindAttribLocation(program, AL_COLOR, "vColor"); renderer_check_glerror("shader:create"); glLinkProgram(program); diff --git a/src/libsymmetry/shader.h b/src/libsymmetry/shader.h index e3bcb7f..7921fc7 100644 --- a/src/libsymmetry/shader.h +++ b/src/libsymmetry/shader.h @@ -3,6 +3,15 @@ #include "../common/linmath.h" +// Constants for locations of attributes inside all shaders +enum Attribute_Location +{ + AL_POSITION = 0, + AL_NORMAL = 1, + AL_UV = 2, + AL_COLOR = 3 +}; + enum Uniform_Type { UT_FLOAT = 0, diff --git a/src/libsymmetry/sprite.c b/src/libsymmetry/sprite.c new file mode 100644 index 0000000..406b0b1 --- /dev/null +++ b/src/libsymmetry/sprite.c @@ -0,0 +1,137 @@ +#include "sprite.h" +#include "texture.h" +#include "shader.h" +#include "renderer.h" +#include "../common/log.h" +#include "../common/array.h" +#include "gl_load.h" + +#include + + +static int sprite_count = 0; + +void sprite_init(void) +{ + +} + +void sprite_cleanup(void) +{ + +} + +void sprite_batch_create(struct Sprite_Batch* batch, const char* texture_name, const char* vert_shader, const char* frag_shader, int draw_mode) +{ + assert(batch); + memset(&batch->sprites[0], '\0', sizeof(struct Sprite) * SPRITE_BATCH_SIZE); + glGenVertexArrays(1, &batch->vao); + + glBindVertexArray(batch->vao); + + glGenBuffers(1, &batch->vbo); + glBindBuffer(GL_ARRAY_BUFFER, batch->vbo); + glBufferData(GL_ARRAY_BUFFER, + sizeof(struct Vertex) * MAX_SPRITE_VERTICES * SPRITE_BATCH_SIZE, + NULL, + GL_STREAM_DRAW); + renderer_check_glerror("sprite_batch_create:glBufferData"); + + // Position + glVertexAttribPointer(AL_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), 0); + renderer_check_glerror("sprite_batch_create:glVertexAttribPointer"); + glEnableVertexAttribArray(AL_POSITION); + renderer_check_glerror("sprite_batch_create:glEnableVertexAttribPointer"); + + // Uvs + glVertexAttribPointer(AL_UV, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), sizeof(vec3)); + renderer_check_glerror("sprite_batch_create:glVertexAttribPointer"); + glEnableVertexAttribArray(AL_UV); + renderer_check_glerror("sprite_batch_create:glEnableVertexAttribPointer"); + + // Color + glVertexAttribPointer(AL_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), sizeof(vec3) + sizeof(vec2)); + renderer_check_glerror("sprite_batch_create:glVertexAttribPointer"); + glEnableVertexAttribArray(AL_COLOR); + renderer_check_glerror("sprite_batch_create:glEnableVertexAttribPointer"); + + //glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + int texture = texture_create_from_file(texture_name, TU_DIFFUSE); + if(texture < 0) + { + log_error("sprite_batch:create", "Failed to find texture '%s' when creating sprite batch", texture_name); + texture = texture_create_from_file("default.tga", TU_DIFFUSE); + } + batch->texture = texture; + + int shader = shader_create(vert_shader, frag_shader); + if(shader < -1) + { + log_error("sprite_batch:create", "Failed to create shader from '%s'/'%s' sprite batch", vert_shader, frag_shader); + shader = shader_create("default.vert", "default.frag"); + } + batch->shader = shader; + batch->draw_mode = draw_mode; +} + +void sprite_batch_begin(struct Sprite_Batch* batch) +{ + assert(batch); + batch->current_sprite_count = 0; +} + +void sprite_batch_add_sprite(struct Sprite_Batch* batch, struct Sprite* sprite) +{ + assert(batch); + if(batch->current_sprite_count < SPRITE_BATCH_SIZE) + { + batch->current_sprite_count++; + memcpy(&batch->sprites[batch->current_sprite_count - 1], sprite, sizeof(struct Sprite)); + } + else + { + log_error("sprite_batch:add_sprite", "Batch full"); + } +} + +void sprite_batch_add_sprite_new(struct Sprite_Batch* batch, int texture, struct Vertex vertices[MAX_SPRITE_VERTICES]) +{ + assert(batch); + if(batch->current_sprite_count < SPRITE_BATCH_SIZE) + { + batch->current_sprite_count++; + memcpy(&batch->sprites[batch->current_sprite_count - 1], &vertices[0], sizeof(struct Sprite)); + } + else + { + log_error("sprite_batch:add_sprite", "Batch full"); + } +} + +void sprite_batch_end(struct Sprite_Batch* batch) +{ + assert(batch); + glBindBuffer(GL_ARRAY_BUFFER, batch->vbo); + glBufferSubData(GL_ARRAY_BUFFER, + 0, + sizeof(struct Vertex) * MAX_SPRITE_VERTICES * batch->current_sprite_count, + &batch->sprites[0]); + renderer_check_glerror("sprite_batch_end:glBufferSubData"); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void sprite_batch_render(struct Sprite_Batch* batch) +{ + assert(batch); + + texture_bind(batch->texture); + glBindVertexArray(batch->vao); + + glDrawArrays(batch->draw_mode, 0, MAX_SPRITE_VERTICES * batch->current_sprite_count); + renderer_check_glerror("sprite_batch_render:glDrawArrays"); + + glBindVertexArray(0); + texture_unbind(batch->texture); +} diff --git a/src/libsymmetry/sprite.h b/src/libsymmetry/sprite.h new file mode 100644 index 0000000..5d9b045 --- /dev/null +++ b/src/libsymmetry/sprite.h @@ -0,0 +1,43 @@ +#ifndef SPRITE_H +#define SPRITE_H + +#include "../common/linmath.h" +#include "../common/num_types.h" + +#define SPRITE_BATCH_SIZE 1024 +#define MAX_SPRITE_VERTICES 6 + +struct Vertex +{ + vec3 pos; + vec2 uv; + vec4 color; +}; + +struct Sprite +{ + struct Vertex vertices[MAX_SPRITE_VERTICES]; +}; + +struct Sprite_Batch +{ + int texture; + int shader; + struct Sprite sprites[SPRITE_BATCH_SIZE]; + int draw_mode; + uint vao; + uint vbo; + int current_sprite_count; +}; + +void sprite_init(void); +void sprite_cleanup(void); + +void sprite_batch_create(struct Sprite_Batch* batch, const char* texture_name, const char* vert_shader, const char* frag_shader, int draw_mode); +void sprite_batch_begin(struct Sprite_Batch* batch); +void sprite_batch_add_sprite(struct Sprite_Batch* batch, struct Sprite* sprite); +void sprite_batch_add_sprite_new(struct Sprite_Batch* batch, int texture, struct Vertex vertices[MAX_SPRITE_VERTICES]); +void sprite_batch_end(struct Sprite_Batch* batch); +void sprite_batch_render(struct Sprite_Batch* batch); + +#endif