diff --git a/examples/rogue.cpp b/examples/rogue.cpp index 8d430e5..8e3e160 100644 --- a/examples/rogue.cpp +++ b/examples/rogue.cpp @@ -18,21 +18,15 @@ namespace { glerminal_load_sprites_file("resources/rogue.png"); - for (int i = 0; i < WALL_LAYERS; i++) - { - const unsigned char v = (i + 1) * (256 / WALL_LAYERS) - 1; - const unsigned int j = (0xFF << 24) | (v << 16) | (v << 8) | v; - glerminal_layer_color(i, j); - - glerminal_layer_scale(i, (i / static_cast(WALL_LAYERS)) + 1); - } - for (int i = 0; i < GRID_WIDTH; i++) { for (int j = 0; j < GRID_HEIGHT; j++) { for (int k = 0; k < WALL_LAYERS; k++) { + const unsigned char v = (k + 1) * (256 / WALL_LAYERS) - 1; + const unsigned int c = (0xFF << 24) | (v << 16) | (v << 8) | v; + if (i == 0 || j == 0 || i == GRID_WIDTH - 1 || j == GRID_HEIGHT - 1) { glerminal_set(i, j, k, floor); @@ -41,6 +35,9 @@ namespace { glerminal_set(i, j, k, wall); } + + glerminal_color(i, j, k, c); + glerminal_scale(i, j, k, (k / static_cast(WALL_LAYERS)) + 1); } } } diff --git a/examples/towers.cpp b/examples/towers.cpp index f346be8..49e4ca5 100644 --- a/examples/towers.cpp +++ b/examples/towers.cpp @@ -11,14 +11,6 @@ namespace glerminal_load_sprites_file("resources/towers.png"); - for (int i = 0; i < LAYER_COUNT; i++) - { - constexpr unsigned char c = 16; - const unsigned char v = (255 - c) * powf((256 / LAYER_COUNT * i - 1) / 256.0f, 2.0f) + c; - const unsigned int j = (0xFF << 24) | (v << 16) | (v << 8) | v; - glerminal_layer_color(i, j); - glerminal_layer_scale(i, i / static_cast(LAYER_COUNT) + 1); - } for (int i = 0; i < GRID_WIDTH; i++) { @@ -29,6 +21,15 @@ namespace { glerminal_set(i, j, k, 1); } + + for (int k = 0; k < LAYER_COUNT; k++) + { + constexpr unsigned char min = 16; + const unsigned char v = (255 - min) * powf((256 / LAYER_COUNT * k - 1) / 256.0f, 2.0f) + min; + const unsigned int col = (0xFF << 24) | (v << 16) | (v << 8) | v; + glerminal_color(i, j, k, col); + glerminal_scale(i, j, k, k / static_cast(LAYER_COUNT) + 1); + } } } } diff --git a/include/glerminal.h b/include/glerminal.h index 9d86275..dafb7b9 100644 --- a/include/glerminal.h +++ b/include/glerminal.h @@ -59,13 +59,13 @@ void glerminal_offset(unsigned char x, unsigned char y, unsigned char layer, flo * @param layer The layer to modify * @param color The new color */ -void glerminal_layer_color(unsigned char layer, unsigned int color); +void glerminal_color(unsigned char x, unsigned char y, unsigned char layer, unsigned int color); /** * @brief Set a layer's scale * @param layer The layer to modify * @param scale The new scale */ -void glerminal_layer_scale(unsigned char layer, float scale); +void glerminal_scale(unsigned char x, unsigned char y, unsigned char layer, float scale); /** * @brief Load sprites from a png file diff --git a/source/glerminal-main.cpp b/source/glerminal-main.cpp index af94735..32d6562 100644 --- a/source/glerminal-main.cpp +++ b/source/glerminal-main.cpp @@ -71,18 +71,22 @@ namespace int lglerminal_layer_color(lua_State* L) { - const unsigned char layer = luaL_checkinteger(L, 1) - 1; - const unsigned int color = luaL_checkinteger(L, 2); - glerminal_layer_color(layer, color); + const unsigned char x = luaL_checkinteger(L, 1) - 1; + const unsigned char y = luaL_checkinteger(L, 2) - 1; + const unsigned char layer = luaL_checkinteger(L, 3) - 1; + const unsigned int color = luaL_checkinteger(L, 4); + glerminal_color(x, y, layer, color); return 0; } int lglerminal_layer_scale(lua_State* L) { - const unsigned char layer = luaL_checkinteger(L, 1) - 1; - const float scale = luaL_checknumber(L, 2); - glerminal_layer_scale(layer, scale); + const unsigned char x = luaL_checkinteger(L, 1) - 1; + const unsigned char y = luaL_checkinteger(L, 2) - 1; + const unsigned char layer = luaL_checkinteger(L, 3) - 1; + const float scale = luaL_checknumber(L, 4); + glerminal_scale(x, y, layer, scale); return 0; } @@ -110,14 +114,11 @@ namespace int message_handler(lua_State* L) { - const char* error_message = lua_tostring(L, -1); - - luaL_traceback(L, L, error_message, 1); - - const char* err = lua_tostring(L, -1); - + luaL_traceback(L, L, lua_tostring(L, -1), 1); lua_remove(L, -2); + glerminal_quit(); + return true; } diff --git a/source/glerminal-private.h b/source/glerminal-private.h index c8c84ef..805e047 100644 --- a/source/glerminal-private.h +++ b/source/glerminal-private.h @@ -44,8 +44,8 @@ namespace glerminal void set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite); unsigned short get(unsigned char x, unsigned char y, unsigned char layer) const; void offset(unsigned char x, unsigned char y, unsigned char layer, float x_offset, float y_offset); - void layer_color(unsigned char layer, unsigned int color); - void layer_scale(unsigned char layer, float scale); + void color(unsigned char x, unsigned char y, unsigned char layer, unsigned int color); + void scale(unsigned char x, unsigned char y, unsigned char layer, float scale); void load_atlas(unsigned char w, unsigned char h, const unsigned int* data); private: @@ -67,8 +67,8 @@ namespace glerminal unsigned int m_framebuffer_backing_texture; unsigned int m_screen_framebuffer; unsigned int m_screen_framebuffer_backing_texture; - unsigned int m_layer_colors_buffer; - unsigned int m_layer_scales_buffer; + unsigned int m_colors_instance_vbo; + unsigned int m_scales_instance_vbo; unsigned int m_screen_size_uniform_location; unsigned int m_palette_uniform_location; @@ -76,11 +76,8 @@ namespace glerminal unsigned short m_cells[GRID_AREA * LAYER_COUNT]; float m_offsets[GRID_AREA * LAYER_COUNT * 2]; - - // per-layer data - - float m_layer_colors[LAYER_COUNT * 4]; - float m_layer_scales[LAYER_COUNT]; + unsigned char m_colors[GRID_AREA * LAYER_COUNT * 4]; + float m_scales[GRID_AREA * LAYER_COUNT]; // library state @@ -100,8 +97,8 @@ namespace glerminal void deinit_gl(); void update_sprites(); - void update_layer_colors(); - void update_layer_scales(); + void update_colors(); + void update_scales(); static void glfw_key_handler(GLFWwindow* window, int key, int scancode, int action, int mods); }; diff --git a/source/glerminal.cpp b/source/glerminal.cpp index 93a7542..df6208a 100644 --- a/source/glerminal.cpp +++ b/source/glerminal.cpp @@ -31,16 +31,10 @@ namespace "layout (location = 0) in vec2 position;\n" "layout (location = 1) in vec2 offset;\n" "layout (location = 2) in int sprite;\n" + "layout (location = 3) in vec4 color;\n" + "layout (location = 4) in float scale;\n" "uniform vec4 " GRID_SIZE_UNIFORM_NAME ";\n" "uniform int " ATLAS_WIDTH_UNIFORM_NAME ";\n" - "layout (std430, binding = 0) buffer LayerScales" - "{\n" - " float scales[];\n" - "} lss;\n" - "layout (std430, binding = 1) buffer LayerColors" - "{\n" - " vec4 colors[];\n" - "} lcs;\n" "out VS_OUT {\n" " flat int sprite;\n" " flat int layer;\n" @@ -53,10 +47,10 @@ namespace " vec2 scaled_offset = 2 * offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n" " vs_out.sprite = sprite;\n" " vs_out.layer = layer;\n" - " vs_out.layer_color = lcs.colors[layer];\n" + " vs_out.layer_color = color;\n" " vs_out.texcoord = vec2(sprite % " ATLAS_WIDTH_UNIFORM_NAME " + position.x + 1, (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ") + vec2(-(2 * position.x + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16, (2 * position.y + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16);\n" - " vec2 cell_position = vec2(lss.scales[layer] + (gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) - " GRID_SIZE_UNIFORM_NAME ".x * floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z));\n" - " vec2 temp = ((position + vec2(-0.5, 0.5)) * lss.scales[layer] + cell_position + vec2(0.5, -0.5)) * " GRID_SIZE_UNIFORM_NAME ".zw * 2 + vec2(-1, 1);\n" + " vec2 cell_position = vec2(scale + (gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) - " GRID_SIZE_UNIFORM_NAME ".x * floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z));\n" + " vec2 temp = ((position + vec2(-0.5, 0.5)) * scale + cell_position + vec2(0.5, -0.5)) * " GRID_SIZE_UNIFORM_NAME ".zw * 2 + vec2(-1, 1);\n" " gl_Position = vec4(scaled_offset.x + temp.x, scaled_offset.y - temp.y, 0, 1);\n" "}"; @@ -68,16 +62,10 @@ namespace "layout (location = 0) in vec2 position;\n" "layout (location = 1) in vec2 offset;\n" "layout (location = 2) in int sprite;\n" + "layout (location = 3) in vec4 color;\n" + "layout (location = 4) in float scale;\n" "uniform vec4 " GRID_SIZE_UNIFORM_NAME ";\n" "uniform int " ATLAS_WIDTH_UNIFORM_NAME ";\n" - "layout (std430, binding = 0) buffer LayerScales" - "{\n" - " float scales[];\n" - "} lss;\n" - "layout (std430, binding = 1) buffer LayerColors" - "{\n" - " vec4 colors[];\n" - "} lcs;\n" "out VS_OUT {\n" " flat int sprite;\n" " flat vec4 layer_color;\n" @@ -90,9 +78,9 @@ namespace " vec2 scaled_offset = 2 * offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n" " vs_out.sprite = sprite;\n" " vs_out.texcoord = vec2(sprite % " ATLAS_WIDTH_UNIFORM_NAME " + position.x + 1, (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ") + vec2(-(2 * position.x + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16, (2 * position.y + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16);\n" - " vs_out.layer_color = lcs.colors[layer];\n" - " vec2 cell_position = vec2(lss.scales[layer] + (gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) - " GRID_SIZE_UNIFORM_NAME ".x * floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z));\n" - " vec2 temp = ((position + vec2(-0.5, 0.5)) * lss.scales[layer] + cell_position + vec2(0.5, -0.5)) * " GRID_SIZE_UNIFORM_NAME ".zw * 2 + vec2(-1, 1);\n" + " vs_out.layer_color = color;\n" + " vec2 cell_position = vec2(scale + (gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) - " GRID_SIZE_UNIFORM_NAME ".x * floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z));\n" + " vec2 temp = ((position + vec2(-0.5, 0.5)) * scale + cell_position + vec2(0.5, -0.5)) * " GRID_SIZE_UNIFORM_NAME ".zw * 2 + vec2(-1, 1);\n" " gl_Position = vec4(scaled_offset.x + temp.x, scaled_offset.y - temp.y, 0, 1);\n" "}"; @@ -208,8 +196,8 @@ namespace glerminal m_cells{ }, m_offsets{ }, m_sprites{ }, - m_layer_colors{ }, - m_layer_scales{ } + m_colors{ }, + m_scales{ } #ifdef GLERMINAL_OPENGL_DEBUG_CONTEXT , m_log("log.txt") #endif @@ -232,8 +220,8 @@ namespace glerminal for (int i = 0; i < LAYER_COUNT; i++) { - m_layer_colors[i * 4 + 0] = m_layer_colors[i * 4 + 1] = m_layer_colors[i * 4 + 2] = m_layer_colors[i * 4 + 3] = 1; - m_layer_scales[i] = 1; + m_colors[i * 4 + 0] = m_colors[i * 4 + 1] = m_colors[i * 4 + 2] = m_colors[i * 4 + 3] = 1; + m_scales[i] = 1; } init_glfw(); @@ -274,11 +262,11 @@ namespace glerminal void glerminal::flush() { - glNamedBufferData(m_sprites_instance_vbo, sizeof(m_cells), m_cells, GL_STREAM_DRAW); - glNamedBufferData(m_offsets_instance_vbo, sizeof(m_offsets), m_offsets, GL_STREAM_DRAW); + glNamedBufferSubData(m_sprites_instance_vbo, 0, sizeof(m_cells), m_cells); + glNamedBufferSubData(m_offsets_instance_vbo, 0, sizeof(m_offsets), m_offsets); update_sprites(); - update_layer_colors(); - update_layer_scales(); + update_colors(); + update_scales(); glUseProgram(m_program); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); @@ -330,17 +318,17 @@ namespace glerminal } } - void glerminal::layer_color(unsigned char layer, unsigned int color) + void glerminal::color(unsigned char x, unsigned char y, unsigned char layer, unsigned int color) { - m_layer_colors[layer * 4 + 0] = ((color >> 0) & 0xFF) / 255.0f; - m_layer_colors[layer * 4 + 1] = ((color >> 8) & 0xFF) / 255.0f; - m_layer_colors[layer * 4 + 2] = ((color >> 16) & 0xFF) / 255.0f; - m_layer_colors[layer * 4 + 3] = ((color >> 24) & 0xFF) / 255.0f; + m_colors[4 * (x + y * GRID_WIDTH + layer * GRID_AREA) + 0] = ((color >> 0) & 0xFF); + m_colors[4 * (x + y * GRID_WIDTH + layer * GRID_AREA) + 1] = ((color >> 8) & 0xFF); + m_colors[4 * (x + y * GRID_WIDTH + layer * GRID_AREA) + 2] = ((color >> 16) & 0xFF); + m_colors[4 * (x + y * GRID_WIDTH + layer * GRID_AREA) + 3] = ((color >> 24) & 0xFF); } - void glerminal::layer_scale(unsigned char layer, float scale) + void glerminal::scale(unsigned char x, unsigned char y, unsigned char layer, float scale) { - m_layer_scales[layer] = scale; + m_scales[x + y * GRID_WIDTH + layer * GRID_AREA] = scale; } void glerminal::load_atlas(unsigned char w, unsigned char h, const unsigned int* data) @@ -407,7 +395,6 @@ namespace glerminal void glerminal::init_gl() { glfwMakeContextCurrent(m_window); - glfwSwapInterval(1); if (!gladLoadGLLoader(reinterpret_cast(glfwGetProcAddress))) { @@ -482,8 +469,8 @@ namespace glerminal glGenBuffers(1, &m_vbo); glGenBuffers(1, &m_sprites_instance_vbo); glGenBuffers(1, &m_offsets_instance_vbo); - glGenBuffers(1, &m_layer_colors_buffer); - glGenBuffers(1, &m_layer_scales_buffer); + glGenBuffers(1, &m_colors_instance_vbo); + glGenBuffers(1, &m_scales_instance_vbo); // create vertex array object glGenVertexArrays(1, &m_vao); @@ -491,23 +478,35 @@ namespace glerminal // set up static vertex attributes glBindBuffer(GL_ARRAY_BUFFER, m_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(VBO_VERTICES), VBO_VERTICES, GL_STATIC_DRAW); + glBufferStorage(GL_ARRAY_BUFFER, sizeof(VBO_VERTICES), VBO_VERTICES, GL_NONE); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(*VBO_VERTICES), reinterpret_cast(0)); // set up instanced vertex attributes glBindBuffer(GL_ARRAY_BUFFER, m_offsets_instance_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(m_offsets), m_offsets, GL_STREAM_DRAW); + glBufferStorage(GL_ARRAY_BUFFER, sizeof(m_offsets), m_offsets, GL_DYNAMIC_STORAGE_BIT); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(*m_offsets), reinterpret_cast(0)); glVertexAttribDivisor(1, 1); glBindBuffer(GL_ARRAY_BUFFER, m_sprites_instance_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(m_cells), m_cells, GL_STREAM_DRAW); + glBufferStorage(GL_ARRAY_BUFFER, sizeof(m_cells), m_cells, GL_DYNAMIC_STORAGE_BIT); glEnableVertexAttribArray(2); glVertexAttribIPointer(2, 1, GL_UNSIGNED_SHORT, 1 * sizeof(*m_cells), reinterpret_cast(0)); glVertexAttribDivisor(2, 1); + glBindBuffer(GL_ARRAY_BUFFER, m_colors_instance_vbo); + glBufferStorage(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_STORAGE_BIT); + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, 4 * sizeof(*m_colors), reinterpret_cast(0)); + glVertexAttribDivisor(3, 1); + + glBindBuffer(GL_ARRAY_BUFFER, m_scales_instance_vbo); + glBufferStorage(GL_ARRAY_BUFFER, sizeof(m_scales), m_scales, GL_DYNAMIC_STORAGE_BIT); + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, 1 * sizeof(*m_scales), reinterpret_cast(0)); + glVertexAttribDivisor(4, 1); + // set up static vertex attributes glGenVertexArrays(1, &m_screen_vao); glBindVertexArray(m_screen_vao); @@ -518,14 +517,6 @@ namespace glerminal glBindVertexArray(0); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_layer_scales_buffer); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_layer_scales), m_layer_scales, GL_DYNAMIC_READ); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_layer_scales_buffer); - - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_layer_colors_buffer); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_layer_colors), m_layer_colors, GL_DYNAMIC_READ); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_layer_colors_buffer); - // -- setup shader program -- // test for features const bool vertex_shader_layer_supported = @@ -765,8 +756,8 @@ namespace glerminal glDeleteBuffers(1, &m_vbo); glDeleteBuffers(1, &m_sprites_instance_vbo); glDeleteBuffers(1, &m_offsets_instance_vbo); - glDeleteBuffers(1, &m_layer_colors_buffer); - glDeleteBuffers(1, &m_layer_scales_buffer); + glDeleteBuffers(1, &m_colors_instance_vbo); + glDeleteBuffers(1, &m_scales_instance_vbo); glDeleteProgram(m_program); } @@ -775,14 +766,14 @@ namespace glerminal glTextureSubImage2D(m_sprites_texture, 0, 0, 0, (CELL_SIZE + 2) * MAX_SPRITES_ROW, (CELL_SIZE + 2) * MAX_SPRITES_ROW, GL_RGBA, GL_UNSIGNED_BYTE, m_sprites); } - void glerminal::update_layer_colors() + void glerminal::update_colors() { - glNamedBufferData(m_layer_colors_buffer, sizeof(m_layer_colors), m_layer_colors, GL_DYNAMIC_READ); + glNamedBufferSubData(m_colors_instance_vbo, 0, sizeof(m_colors), m_colors); } - void glerminal::update_layer_scales() + void glerminal::update_scales() { - glNamedBufferData(m_layer_scales_buffer, sizeof(m_layer_scales), m_layer_scales, GL_DYNAMIC_READ); + glNamedBufferSubData(m_scales_instance_vbo, 0, sizeof(m_scales), m_scales); } void glerminal::glfw_key_handler(GLFWwindow* window, int key, int scancode, int action, int mods) @@ -850,18 +841,18 @@ void glerminal_offset(unsigned char x, unsigned char y, unsigned char layer, flo GLERMINAL_G->offset(x, y, layer, x_offset, y_offset); } -void glerminal_layer_color(unsigned char layer, unsigned int color) +void glerminal_color(unsigned char x, unsigned char y, unsigned char layer, unsigned int color) { if (!GLERMINAL_G) { return; } - GLERMINAL_G->layer_color(layer, color); + GLERMINAL_G->color(x, y, layer, color); } -void glerminal_layer_scale(unsigned char layer, float scale) +void glerminal_scale(unsigned char x, unsigned char y, unsigned char layer, float scale) { if (!GLERMINAL_G) { return; } - GLERMINAL_G->layer_scale(layer, scale); + GLERMINAL_G->scale(x, y, layer, scale); } int glerminal_load_sprites_file(const char* filename)