a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit af6ac03f1b4677f5e225fa5e614f7fa8022ac7b6
parent 7c6c6306a7bffb0d09ebc80f04e5aef237767a71
Author: amin <dev@aminmesbah.com>
Date:   Tue, 16 Jul 2019 00:29:55 +0000

Load tile textures from a tileset

FossilOrigin-Name: 9fd417b44aba46077ffaca5014e1e9dc1328943cea31bf1a20cd3f5fb15fe168
Diffstat:
Mshader/main_f.glsl | 10+++++++---
Mshader/main_v.glsl | 2+-
Msrc/game.c | 1+
Msrc/platform_linux.c | 4++--
Msrc/platform_windows.c | 4++--
Msrc/render.c | 56+++++++++++++++++++++++++++++++++++++++++++++++++++-----
6 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/shader/main_f.glsl b/shader/main_f.glsl @@ -2,8 +2,9 @@ // NOTE(amin): this is necessary for webgl compat precision highp float; +precision highp sampler2DArray; -// TODO: dynamically instert the version header after loading the file +// TODO: dynamically insert the version header after loading the file in vec4 vertex_color; in vec2 tex_coord; @@ -11,9 +12,12 @@ in vec2 tex_coord; out vec4 frag_color; uniform float tex_interp; -uniform sampler2D main_texture; +uniform sampler2DArray tileset; void main() { - frag_color = mix(vertex_color, texture(main_texture, tex_coord), tex_interp); + // TODO: make this an input + float tile_id = 16.0f; + vec4 tile_texel = texture(tileset, vec3(tex_coord, tile_id)); + frag_color = mix(vertex_color, tile_texel, tex_interp); } diff --git a/shader/main_v.glsl b/shader/main_v.glsl @@ -1,6 +1,6 @@ #version 300 es -// TODO: dynamically instert the version header after loading the file +// TODO: dynamically insert the version header after loading the file layout (location = 0) in vec2 position; layout (location = 1) in vec2 a_tex_coords; diff --git a/src/game.c b/src/game.c @@ -183,6 +183,7 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer) struct Shader main_shader = {0}; if (!shader_compile(v_source, f_source, &main_shader)) { + exit(1); // TODO: handle error } platform.platform_memory_free(v_source); diff --git a/src/platform_linux.c b/src/platform_linux.c @@ -30,8 +30,8 @@ int main(void) return -1; } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); diff --git a/src/platform_windows.c b/src/platform_windows.c @@ -31,8 +31,8 @@ int main(void) return -1; } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); diff --git a/src/render.c b/src/render.c @@ -50,16 +50,62 @@ internal void renderer_init(struct RendererState *renderer, struct Image *images for (u32 i = 0; i < num_images; i++) { struct Image img = images[i]; + u8 bytes_per_texel = 4; + v2u tile_dim = {64, 64}; + v2u tileset_dim = {img.dim.x / tile_dim.x, img.dim.y / tile_dim.y}; + u32 texture_id; glGenTextures(1, &texture_id); - glBindTexture(GL_TEXTURE_2D, texture_id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.dim.width, img.dim.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data); - glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D_ARRAY, texture_id); + glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, tile_dim.x, tile_dim.y, tileset_dim.x * tileset_dim.y); + size_t marker = mem_st_get_marker(allocator); + { + u8 *tile_data = mem_st_alloc_buffer(allocator, u8, tile_dim.x * tile_dim.y * bytes_per_texel); + for (u32 tile_y = 0; tile_y < tileset_dim.y; tile_y++) + { + for (u32 tile_x = 0; tile_x < tileset_dim.x; tile_x++) + { + // NOTE(amin): We must copy the disparate interleaved + // texels associated with a given tile in the image to a + // contiguous memory region. + for (u32 texel_y = 0; texel_y < tile_dim.y; texel_y++) + { + for (u32 texel_x = 0; texel_x < tile_dim.x; texel_x++) + { + v2u texel_index_in_image = { + (tile_x * tile_dim.x) + texel_x, + (tile_y * tile_dim.y) + texel_y, + }; + assert(texel_index_in_image.x < tileset_dim.x * tile_dim.x); + assert(texel_index_in_image.y < tileset_dim.y * tile_dim.y); + u32 linearized_texel_i = texel_index_in_image.x + (texel_index_in_image.y * tileset_dim.x * tile_dim.x); + u32 *texel = (u32 *)(img.data + (linearized_texel_i * bytes_per_texel)); + ((u32 *)tile_data)[texel_x + (texel_y * tile_dim.x)] = *texel; + } + } + u32 tile_id = tile_x + (tile_y * tileset_dim.x); + glTexSubImage3D( + GL_TEXTURE_2D_ARRAY, + 0, 0, 0, + tile_id, + tile_dim.x, + tile_dim.y, + 1, + GL_RGBA, + GL_UNSIGNED_BYTE, + tile_data); + } + } + } + mem_st_free_to_marker(allocator, marker); + + // TODO: fix the _hideous_ aliasing that happens when scaling down. + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glActiveTexture(GL_TEXTURE0); }