From ad383f4389bb9f943ad345f763e0b54cae40b2d2 Mon Sep 17 00:00:00 2001 From: Dylan Falconer Date: Mon, 5 Sep 2022 14:25:39 +1000 Subject: [PATCH 1/3] Batch rendering, sprite sheets, refactoring Moving the render state out of global state as it's not required to be there. Added batch rendering using the glBufferSubData method. Added sprite sheet calculation - currently each sheet must be of one sprite size, rather than packing everything into one image. Currently only supports one sheet, but will add the ability to load several textures at once in the next episode. --- assets/player.png | Bin 0 -> 5490 bytes shaders/batch_quad_frag.glsl | 13 ++ shaders/batch_quad_vert.glsl | 15 +++ src/engine/entity/entity.c | 3 +- src/engine/global.h | 1 - src/engine/physics/physics.c | 4 +- src/engine/render.h | 31 ++++- src/engine/render/render.c | 184 ++++++++++++++++++++++++---- src/engine/render/render_init.c | 62 ++++++++-- src/engine/render/render_internal.h | 14 +-- src/main.c | 50 ++++---- 11 files changed, 302 insertions(+), 75 deletions(-) create mode 100644 assets/player.png create mode 100644 shaders/batch_quad_frag.glsl create mode 100644 shaders/batch_quad_vert.glsl diff --git a/assets/player.png b/assets/player.png new file mode 100644 index 0000000000000000000000000000000000000000..88b57b23eabcada5d995b4be3e3aab48e6e66809 GIT binary patch literal 5490 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 #include "types.h" +#include "array_list.h" -typedef struct render_state { - SDL_Window *window; +typedef struct sprite_sheet { f32 width; f32 height; -} Render_State; + f32 cell_width; + f32 cell_height; + u32 texture_id; +} Sprite_Sheet; -void render_init(void); +#define Batch_Vertex_Def +typedef struct batch_vertex { + vec2 position; + vec2 uvs; + vec4 color; +} Batch_Vertex; + +enum { + MAX_BATCH_QUADS = 10000, + MAX_BATCH_VERTICES = MAX_BATCH_QUADS * 4, + MAX_BATCH_ELEMENTS = MAX_BATCH_QUADS * 6, +}; + +SDL_Window *render_init(void); void render_begin(void); -void render_end(void); +void render_end(SDL_Window *window); void render_quad(vec2 pos, vec2 size, vec4 color); void render_quad_line(vec2 pos, vec2 size, vec4 color); void render_line_segment(vec2 start, vec2 end, vec4 color); void render_aabb(f32 *aabb, vec4 color); - +void render_sprite_sheet_init(Sprite_Sheet *sprite_sheet, const char *path, f32 cell_width, f32 cell_height); +void render_sprite_sheet_frame(Sprite_Sheet *sprite_sheet, f32 row, f32 column, vec2 position); +void render_set_batch_texture(u32 texture_id); +f32 render_get_scale(); diff --git a/src/engine/render/render.c b/src/engine/render/render.c index bedfa34..879cfde 100644 --- a/src/engine/render/render.c +++ b/src/engine/render/render.c @@ -3,34 +3,86 @@ #include "../global.h" #include "../render.h" #include "render_internal.h" +#include "../util.h" + +#define STB_IMAGE_IMPLEMENTATION +#include + +f32 window_width = 1920; +f32 window_height = 1080; +f32 render_width = 640; +f32 render_height = 360; +f32 scale = 3; + +static u32 vao_quad; +static u32 vbo_quad; +static u32 ebo_quad; +static u32 vao_line; +static u32 vbo_line; +static u32 shader_default; +static u32 texture_color; +static u32 vao_batch; +static u32 vbo_batch; +static u32 ebo_batch; +static u32 shader_batch; +static u32 texture_batch; +static Array_List *list_batch; + +Batch_Vertex bv = {0}; + +SDL_Window *render_init(void) { + /// RENDER WIDTH AND VIEWPORT WIDTH SHOULD BE DIFFERENT - PIXEL ART + SDL_Window *window = render_init_window(window_width, window_height); + + render_init_quad(&vao_quad, &vbo_quad, &ebo_quad); + render_init_line(&vao_line, &vbo_line); + render_init_shaders(&shader_default, &shader_batch, render_width, render_height); + render_init_color_texture(&texture_color); + render_init_batch_quads(&vao_batch, &vbo_batch, &ebo_batch); -static Render_State_Internal state = {0}; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -void render_init(void) { - global.render.width = 1920; - global.render.height = 1080; - global.render.window = render_init_window(global.render.width, global.render.height); + list_batch = array_list_create(sizeof(Batch_Vertex), 8); - render_init_quad(&state.vao_quad, &state.vbo_quad, &state.ebo_quad); - render_init_line(&state.vao_line, &state.vbo_line); - render_init_shaders(&state); - render_init_color_texture(&state.texture_color); + stbi_set_flip_vertically_on_load(1); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return window; } void render_begin(void) { glClearColor(0.08, 0.1, 0.1, 1); glClear(GL_COLOR_BUFFER_BIT); + + list_batch->len = 0; +} + +static void render_batch(Batch_Vertex *vertices, usize count, u32 texture_id) { + glBindBuffer(GL_ARRAY_BUFFER, vbo_batch); + glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(Batch_Vertex), vertices); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture_id); + + glUseProgram(shader_batch); + glBindVertexArray(vao_batch); + + // count >> 2 s the same as count / 4. + // 4 Vertices per Quad. + // 6 Indices per Quad (two triangles). + glDrawElements(GL_TRIANGLES, (count >> 2) * 6, GL_UNSIGNED_INT, NULL); } -void render_end(void) { - SDL_GL_SwapWindow(global.render.window); +void render_end(SDL_Window *window) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINES); + render_batch(list_batch->items, list_batch->len, texture_batch); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + SDL_GL_SwapWindow(window); } void render_quad(vec2 pos, vec2 size, vec4 color) { - glUseProgram(state.shader_default); + glUseProgram(shader_default); mat4x4 model; mat4x4_identity(model); @@ -38,19 +90,19 @@ void render_quad(vec2 pos, vec2 size, vec4 color) { mat4x4_translate(model, pos[0], pos[1], 0); mat4x4_scale_aniso(model, model, size[0], size[1], 1); - glUniformMatrix4fv(glGetUniformLocation(state.shader_default, "model"), 1, GL_FALSE, &model[0][0]); - glUniform4fv(glad_glGetUniformLocation(state.shader_default, "color"), 1, color); + glUniformMatrix4fv(glGetUniformLocation(shader_default, "model"), 1, GL_FALSE, &model[0][0]); + glUniform4fv(glad_glGetUniformLocation(shader_default, "color"), 1, color); - glBindVertexArray(state.vao_quad); + glBindVertexArray(vao_quad); - glBindTexture(GL_TEXTURE_2D, state.texture_color); + glBindTexture(GL_TEXTURE_2D, texture_color); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL); glBindVertexArray(0); } void render_line_segment(vec2 start, vec2 end, vec4 color) { - glUseProgram(state.shader_default); + glUseProgram(shader_default); glLineWidth(3); f32 x = end[0] - start[0]; @@ -60,13 +112,13 @@ void render_line_segment(vec2 start, vec2 end, vec4 color) { mat4x4 model; mat4x4_translate(model, start[0], start[1], 0); - glUniformMatrix4fv(glGetUniformLocation(state.shader_default, "model"), 1, GL_FALSE, &model[0][0]); - glUniform4fv(glGetUniformLocation(state.shader_default, "color"), 1, color); + glUniformMatrix4fv(glGetUniformLocation(shader_default, "model"), 1, GL_FALSE, &model[0][0]); + glUniform4fv(glGetUniformLocation(shader_default, "color"), 1, color); - glBindTexture(GL_TEXTURE_2D, state.texture_color); - glBindVertexArray(state.vao_line); + glBindTexture(GL_TEXTURE_2D, texture_color); + glBindVertexArray(vao_line); - glBindBuffer(GL_ARRAY_BUFFER, state.vbo_line); + glBindBuffer(GL_ARRAY_BUFFER, vbo_line); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(line), line); glDrawArrays(GL_LINES, 0, 2); @@ -93,3 +145,87 @@ void render_aabb(f32 *aabb, vec4 color) { render_quad_line(&aabb[0], size, color); } +static void append_quad(vec2 position, vec2 size, vec4 texture_coordinates, vec4 color) { + vec4 uvs = {0, 0, 1, 1}; + + if (texture_coordinates != NULL) { + memcpy(uvs, texture_coordinates, sizeof(vec4)); + } + + array_list_append(list_batch, &(Batch_Vertex){ + .position = { position[0], position[1] }, + .uvs = { uvs[0], uvs[1] }, + .color = { color[0], color[1], color[2], color[3] }, + }); + + array_list_append(list_batch, &(Batch_Vertex){ + .position = { position[0] + size[0], position[1] }, + .uvs = { uvs[2], uvs[1] }, + .color = { color[0], color[1], color[2], color[3] }, + }); + + array_list_append(list_batch, &(Batch_Vertex){ + .position = { position[0] + size[0], position[1] + size[1] }, + .uvs = { uvs[2], uvs[3] }, + .color = { color[0], color[1], color[2], color[3] }, + }); + + array_list_append(list_batch, &(Batch_Vertex){ + .position = { position[0], position[1] + size[1] }, + .uvs = { uvs[0], uvs[3] }, + .color = { color[0], color[1], color[2], color[3] }, + }); +} + +static void calculate_sprite_texture_coordinates(vec4 result, f32 row, f32 column, f32 texture_width, f32 texture_height, f32 cell_width, f32 cell_height) { + f32 w = 1.0 / (texture_width / cell_width); + f32 h = 1.0 / (texture_height / cell_height); + f32 x = column * w; + f32 y = row * h; + result[0] = x; + result[1] = y; + result[2] = x + w; + result[3] = y + h; +} + +void render_sprite_sheet_init(Sprite_Sheet *sprite_sheet, const char *path, f32 cell_width, f32 cell_height) { + glGenTextures(1, &sprite_sheet->texture_id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, sprite_sheet->texture_id); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + int width, height, channel_count; + u8 *image_data = stbi_load(path, &width, &height, &channel_count, 0); + if (!image_data) { + ERROR_EXIT("Failed to load image: %s\n", path); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); + stbi_image_free(image_data); + + sprite_sheet->width = (f32)width; + sprite_sheet->height = (f32)height; + sprite_sheet->cell_width = cell_width; + sprite_sheet->cell_height = cell_height; +} + +void render_sprite_sheet_frame(Sprite_Sheet *sprite_sheet, f32 row, f32 column, vec2 position) { + vec4 uvs; + calculate_sprite_texture_coordinates(uvs, row, column, sprite_sheet->width, sprite_sheet->height, sprite_sheet->cell_width, sprite_sheet->cell_height); + + vec2 size = {sprite_sheet->cell_width, sprite_sheet->cell_height}; + vec2 bottom_left = {position[0] - size[0] * 0.5, position[1] - size[1] * 0.5}; + append_quad(bottom_left, size, uvs, (vec4){1, 1, 1, 1}); +} + +f32 render_get_scale() { + return scale; +} + +// NOTE: Temporary setter - will use texture slots later. +void render_set_batch_texture(u32 texture_id) { + texture_batch = texture_id; +} diff --git a/src/engine/render/render_init.c b/src/engine/render/render_init.c index 22b3621..6036342 100644 --- a/src/engine/render/render_init.c +++ b/src/engine/render/render_init.c @@ -20,8 +20,8 @@ SDL_Window *render_init_window(u32 width, u32 height) { "MyGame", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - global.render.width, - global.render.height, + width, + height, SDL_WINDOW_OPENGL ); @@ -42,17 +42,28 @@ SDL_Window *render_init_window(u32 width, u32 height) { return window; } -void render_init_shaders(Render_State_Internal *state) { - state->shader_default = render_shader_create("./shaders/default.vert", "./shaders/default.frag"); +void render_init_shaders(u32 *shader_default, u32 *shader_batch, f32 render_width, f32 render_height) { + *shader_default = render_shader_create("./shaders/default.vert", "./shaders/default.frag"); - mat4x4_ortho(state->projection, 0, global.render.width, 0, global.render.height, -2, 2); + mat4x4 projection; + mat4x4_ortho(projection, 0, render_width, 0, render_height, -2, 2); - glUseProgram(state->shader_default); + glUseProgram(*shader_default); glUniformMatrix4fv( - glGetUniformLocation(state->shader_default, "projection"), + glGetUniformLocation(*shader_default, "projection"), 1, GL_FALSE, - &state->projection[0][0] + &projection[0][0] + ); + + *shader_batch = render_shader_create("shaders/batch_quad_vert.glsl", "shaders/batch_quad_frag.glsl"); + + glUseProgram(*shader_batch); + glUniformMatrix4fv( + glGetUniformLocation(*shader_batch, "projection"), + 1, + GL_FALSE, + &projection[0][0] ); } @@ -103,6 +114,41 @@ void render_init_quad(u32 *vao, u32 *vbo, u32 *ebo) { glBindVertexArray(0); } +void render_init_batch_quads(u32 *vao, u32 *vbo, u32 *ebo) { + glGenVertexArrays(1, vao); + glBindVertexArray(*vao); + + u32 indices[MAX_BATCH_ELEMENTS]; + for (u32 i = 0, offset = 0; i < MAX_BATCH_ELEMENTS; i += 6, offset += 4) { + indices[i + 0] = offset + 0; + indices[i + 1] = offset + 1; + indices[i + 2] = offset + 2; + indices[i + 3] = offset + 2; + indices[i + 4] = offset + 3; + indices[i + 5] = offset + 0; + } + + glGenBuffers(1, vbo); + glBindBuffer(GL_ARRAY_BUFFER, *vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(f32) * MAX_BATCH_VERTICES * 4, NULL, GL_DYNAMIC_DRAW); + + // [x, y], [u, v], [r, g, b, a] + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Batch_Vertex), (void*)offsetof(Batch_Vertex, position)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Batch_Vertex), (void*)offsetof(Batch_Vertex, uvs)); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Batch_Vertex), (void*)offsetof(Batch_Vertex, color)); + + glGenBuffers(1, ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + void render_init_line(u32 *vao, u32 *vbo) { glGenVertexArrays(1, vao); glBindVertexArray(*vao); diff --git a/src/engine/render/render_internal.h b/src/engine/render/render_internal.h index dca89b2..e76e9a8 100644 --- a/src/engine/render/render_internal.h +++ b/src/engine/render/render_internal.h @@ -5,21 +5,11 @@ #include "../types.h" #include "../render.h" -typedef struct render_state_internal { - u32 vao_quad; - u32 vbo_quad; - u32 ebo_quad; - u32 vao_line; - u32 vbo_line; - u32 shader_default; - u32 texture_color; - mat4x4 projection; -} Render_State_Internal; - SDL_Window *render_init_window(u32 width, u32 height); void render_init_quad(u32 *vao, u32 *vbo, u32 *ebo); void render_init_color_texture(u32 *texture); -void render_init_shaders(Render_State_Internal *state); +void render_init_shaders(u32 *shader_default, u32 *shader_batch, f32 render_width, f32 render_height); void render_init_line(u32 *vao, u32 *vbo); +void render_init_batch_quads(u32 *vao, u32 *ebo, u32 *vbo); u32 render_shader_create(const char *path_vert, const char *path_frag); diff --git a/src/main.c b/src/main.c index d20ecac..77322b9 100644 --- a/src/main.c +++ b/src/main.c @@ -12,6 +12,7 @@ #include "engine/physics.h" #include "engine/util.h" #include "engine/entity.h" +#include "engine/array_list.h" typedef enum collision_layer { COLLISION_LAYER_PLAYER = 1, @@ -32,20 +33,16 @@ static void input_handle(Body *body_player) { f32 vely = body_player->velocity[1]; if (global.input.right) { - velx += 1000; + velx += 500; } if (global.input.left) { - velx -= 1000; + velx -= 500; } if (global.input.up && player_is_grounded) { player_is_grounded = false; - vely = 4000; - } - - if (global.input.down) { - vely -= 800; + vely = 2000; } body_player->velocity[0] = velx; @@ -67,18 +64,18 @@ void player_on_hit_static(Body *self, Static_Body *other, Hit hit) { void enemy_on_hit_static(Body *self, Static_Body *other, Hit hit) { if (hit.normal[0] > 0) { - self->velocity[0] = 700; + self->velocity[0] = 300; } if (hit.normal[0] < 0) { - self->velocity[0] = -700; + self->velocity[0] = -300; } } int main(int argc, char *argv[]) { time_init(60); config_init(); - render_init(); + SDL_Window *window = render_init(); physics_init(); entity_init(); @@ -87,19 +84,25 @@ int main(int argc, char *argv[]) { u8 enemy_mask = COLLISION_LAYER_PLAYER | COLLISION_LAYER_TERRAIN; u8 player_mask = COLLISION_LAYER_ENEMY | COLLISION_LAYER_TERRAIN; - usize player_id = entity_create((vec2){100, 800}, (vec2){100, 100}, (vec2){0, 0}, COLLISION_LAYER_PLAYER, player_mask, player_on_hit, player_on_hit_static); + usize player_id = entity_create((vec2){100, 200}, (vec2){24, 24}, (vec2){0, 0}, COLLISION_LAYER_PLAYER, player_mask, player_on_hit, player_on_hit_static); - f32 width = global.render.width; - f32 height = global.render.height; + i32 width, height; + SDL_GetWindowSize(window, &width, &height); + width /= render_get_scale(); + height /= render_get_scale(); - u32 static_body_a_id = physics_static_body_create((vec2){width * 0.5 - 25, height - 25}, (vec2){width - 50, 50}, COLLISION_LAYER_TERRAIN); - u32 static_body_b_id = physics_static_body_create((vec2){width - 25, height * 0.5 + 25}, (vec2){50, height - 50}, COLLISION_LAYER_TERRAIN); - u32 static_body_c_id = physics_static_body_create((vec2){width * 0.5 + 25, 25}, (vec2){width - 50, 50}, COLLISION_LAYER_TERRAIN); - u32 static_body_d_id = physics_static_body_create((vec2){25, height * 0.5 - 25}, (vec2){50, height - 50}, COLLISION_LAYER_TERRAIN); - u32 static_body_e_id = physics_static_body_create((vec2){width * 0.5, height * 0.5}, (vec2){150, 150}, COLLISION_LAYER_TERRAIN); + u32 static_body_a_id = physics_static_body_create((vec2){width * 0.5 - 12.5, height - 12.5}, (vec2){width - 25, 25}, COLLISION_LAYER_TERRAIN); + u32 static_body_b_id = physics_static_body_create((vec2){width - 12.5, height * 0.5 + 12.5}, (vec2){25, height - 25}, COLLISION_LAYER_TERRAIN); + u32 static_body_c_id = physics_static_body_create((vec2){width * 0.5 + 12.5, 12.5}, (vec2){width - 25, 25}, COLLISION_LAYER_TERRAIN); + u32 static_body_d_id = physics_static_body_create((vec2){12.5, height * 0.5 - 12.5}, (vec2){25, height - 25}, COLLISION_LAYER_TERRAIN); + u32 static_body_e_id = physics_static_body_create((vec2){width * 0.5, height * 0.5}, (vec2){25, 25}, COLLISION_LAYER_TERRAIN); - usize entity_a_id = entity_create((vec2){600, 600}, (vec2){50, 50}, (vec2){900, 0}, COLLISION_LAYER_ENEMY, enemy_mask, NULL, enemy_on_hit_static); - usize entity_b_id = entity_create((vec2){800, 800}, (vec2){50, 50}, (vec2){900, 0}, 0, enemy_mask, NULL, enemy_on_hit_static); + usize entity_a_id = entity_create((vec2){300, 200}, (vec2){25, 25}, (vec2){900, 0}, COLLISION_LAYER_ENEMY, enemy_mask, NULL, enemy_on_hit_static); + usize entity_b_id = entity_create((vec2){400, 200}, (vec2){25, 25}, (vec2){900, 0}, 0, enemy_mask, NULL, enemy_on_hit_static); + + Sprite_Sheet sprite_sheet_player; + render_sprite_sheet_init(&sprite_sheet_player, "assets/player.png", 24, 24); + render_set_batch_texture(sprite_sheet_player.texture_id); while (!should_quit) { time_update(); @@ -140,7 +143,12 @@ int main(int argc, char *argv[]) { render_aabb((f32*)physics_body_get(entity_get(entity_a_id)->body_id), WHITE); render_aabb((f32*)physics_body_get(entity_get(entity_b_id)->body_id), WHITE); - render_end(); + render_sprite_sheet_frame(&sprite_sheet_player, 1, 1, physics_body_get(entity_get(entity_a_id)->body_id)->aabb.position); + render_sprite_sheet_frame(&sprite_sheet_player, 1, 2, (vec2){100, 100}); + render_sprite_sheet_frame(&sprite_sheet_player, 1, 4, (vec2){100, 200}); + render_sprite_sheet_frame(&sprite_sheet_player, 0, 0, body_player->aabb.position); + + render_end(window); player_color[0] = 0; player_color[2] = 1; From 5c8c79083151fbbf4184234d22b1596ba28c93fd Mon Sep 17 00:00:00 2001 From: Dylan Falconer Date: Mon, 5 Sep 2022 14:46:25 +1000 Subject: [PATCH 2/3] Remove bv --- src/engine/render.h | 1 - src/engine/render/render.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/engine/render.h b/src/engine/render.h index 2a7b814..86237ed 100644 --- a/src/engine/render.h +++ b/src/engine/render.h @@ -14,7 +14,6 @@ typedef struct sprite_sheet { u32 texture_id; } Sprite_Sheet; -#define Batch_Vertex_Def typedef struct batch_vertex { vec2 position; vec2 uvs; diff --git a/src/engine/render/render.c b/src/engine/render/render.c index 879cfde..42a99fb 100644 --- a/src/engine/render/render.c +++ b/src/engine/render/render.c @@ -28,8 +28,6 @@ static u32 shader_batch; static u32 texture_batch; static Array_List *list_batch; -Batch_Vertex bv = {0}; - SDL_Window *render_init(void) { /// RENDER WIDTH AND VIEWPORT WIDTH SHOULD BE DIFFERENT - PIXEL ART SDL_Window *window = render_init_window(window_width, window_height); From cff62fcd8d72a253627a2e1df397fdebf33a219a Mon Sep 17 00:00:00 2001 From: Dylan Falconer Date: Tue, 6 Sep 2022 13:19:09 +1000 Subject: [PATCH 3/3] Fix vars not static --- src/engine/render/render.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/engine/render/render.c b/src/engine/render/render.c index 42a99fb..065933c 100644 --- a/src/engine/render/render.c +++ b/src/engine/render/render.c @@ -8,11 +8,11 @@ #define STB_IMAGE_IMPLEMENTATION #include -f32 window_width = 1920; -f32 window_height = 1080; -f32 render_width = 640; -f32 render_height = 360; -f32 scale = 3; +static f32 window_width = 1920; +static f32 window_height = 1080; +static f32 render_width = 640; +static f32 render_height = 360; +static f32 scale = 3; static u32 vao_quad; static u32 vbo_quad;