Properly fixed texture bleeding

This commit is contained in:
Shylie 2024-06-02 14:34:07 -04:00
parent 71c052b38f
commit da1f32a014
4 changed files with 65 additions and 34 deletions

View File

@ -35,7 +35,7 @@ void glerminal_flush();
* @param layer layer of the cell in the range [0, 8)
* @param sprite sprite's index in the range [0, 256)
*/
void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite);
void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite);
/**
* @brief Get a cell's sprite
* @param x position of the cell in the range [0, 40)
@ -43,7 +43,7 @@ void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsign
* @param layer layer of the cell in the range [0, 8)
* @return sprite index currently assigned to the cell
*/
unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char layer);
unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned short layer);
/**
* @brief Set a cell's offset
* @param x position of the cell in the range [0, 40)

View File

@ -41,7 +41,7 @@ namespace
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 char sprite = luaL_checkinteger(L, 4) - 1;
const unsigned short sprite = luaL_checkinteger(L, 4) - 1;
glerminal_set(x, y, layer, sprite);
return 0;
@ -108,31 +108,50 @@ namespace
{ nullptr, nullptr }
};
int message_handler(lua_State* L)
{
const char* error_message = lua_tostring(L, -1);
luaL_traceback(L, L, error_message, 0);
const char* err = lua_tostring(L, -1);
lua_remove(L, -2);
return true;
}
lua_State* L;
void init()
{
lua_pushcfunction(L, message_handler);
const int handler = lua_gettop(L);
lua_getglobal(L, "glerminal");
lua_getfield(L, -1, "init");
lua_remove(L, -2);
if (lua_pcall(L, 0, 0, 0) != LUA_OK)
if (lua_pcall(L, 0, 0, handler) != LUA_OK)
{
// ignore error for now
std::cout << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1);
}
lua_remove(L, handler);
}
void mainloop(float dt)
{
lua_pushcfunction(L, message_handler);
const int handler = lua_gettop(L);
lua_getglobal(L, "glerminal");
lua_getfield(L, -1, "main");
lua_remove(L, -2);
lua_pushnumber(L, dt);
if (lua_pcall(L, 1, 0, 0) != LUA_OK)
if (lua_pcall(L, 1, 0, handler) != LUA_OK)
{
// ignore error for now
std::cout << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1);
}
lua_remove(L, handler);
}
void pressed(int key)
@ -140,15 +159,18 @@ namespace
const char* const name = glfwGetKeyName(key, 0);
if (name)
{
lua_pushcfunction(L, message_handler);
const int handler = lua_gettop(L);
lua_getglobal(L, "glerminal");
lua_getfield(L, -1, "pressed");
lua_remove(L, -2);
lua_pushstring(L, name);
if (lua_pcall(L, 1, 0, 0) != LUA_OK)
if (lua_pcall(L, 1, 0, handler) != LUA_OK)
{
// ignore error for now
std::cout << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1);
}
lua_remove(L, handler);
}
}
@ -157,15 +179,18 @@ namespace
const char* const name = glfwGetKeyName(key, 0);
if (name)
{
lua_pushcfunction(L, message_handler);
const int handler = lua_gettop(L);
lua_getglobal(L, "glerminal");
lua_getfield(L, -1, "released");
lua_remove(L, -2);
lua_pushstring(L, name);
if (lua_pcall(L, 1, 0, 0) != LUA_OK)
if (lua_pcall(L, 1, 0, handler) != LUA_OK)
{
// ignore error for now
std::cout << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1);
}
lua_remove(L, handler);
}
}
}

View File

@ -41,8 +41,8 @@ namespace glerminal
void flush();
void set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite);
unsigned char get(unsigned char x, unsigned char y, unsigned char layer) const;
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);
@ -84,7 +84,7 @@ namespace glerminal
// library state
unsigned int m_sprites[CELL_SIZE * CELL_SIZE * MAX_SPRITES];
unsigned int m_sprites[(CELL_SIZE + 2) * (CELL_SIZE + 2) * MAX_SPRITES];
glerminal_main_cb m_main;
glerminal_keys_cb m_pressed, m_released;

View File

@ -54,7 +54,7 @@ namespace
" vs_out.sprite = sprite;\n"
" vs_out.layer = layer;\n"
" vs_out.layer_color = lcs.colors[layer];\n"
" vs_out.texcoord = (vec2((sprite + int(position.x + 1)) % " ATLAS_WIDTH_UNIFORM_NAME ", (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) + vec2((position.x + 0.5) / -32, (position.y + 0.5) / 32)) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ");\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"
" gl_Position = vec4(scaled_offset.x + temp.x, scaled_offset.y - temp.y, 0, 1);\n"
@ -89,7 +89,7 @@ namespace
" gl_Layer = layer;\n"
" vec2 scaled_offset = 2 * offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n"
" vs_out.sprite = sprite;\n"
" vs_out.texcoord = (vec2((sprite + int(position.x + 1)) % " ATLAS_WIDTH_UNIFORM_NAME ", (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) + vec2((position.x + 0.5) / -32, (position.y + 0.5) / 32)) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ");\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"
@ -294,10 +294,13 @@ namespace glerminal
glBlitNamedFramebuffer(m_screen_framebuffer, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glfwSwapInterval(0);
glfwSwapBuffers(m_window);
glfwSwapInterval(1);
glfwSwapBuffers(m_window);
}
void glerminal::set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite)
void glerminal::set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite)
{
if (x < GRID_WIDTH && y < GRID_HEIGHT && layer < LAYER_COUNT)
{
@ -305,7 +308,7 @@ namespace glerminal
}
}
unsigned char glerminal::get(unsigned char x, unsigned char y, unsigned char layer) const
unsigned short glerminal::get(unsigned char x, unsigned char y, unsigned char layer) const
{
if (x < GRID_WIDTH && y < GRID_HEIGHT && layer < LAYER_COUNT)
{
@ -341,21 +344,25 @@ namespace glerminal
void glerminal::load_atlas(unsigned char w, unsigned char h, const unsigned int* data)
{
// each row of the atlas
for (int j = 0; j < h; j++)
for (int src_atlas_row = 0; src_atlas_row < h; src_atlas_row++)
{
// each column of the atlas
for (int i = 0; i < w; i++)
for (int src_atlas_col = 0; src_atlas_col < w; src_atlas_col++)
{
// each row of the individual sprite
for (int k = 0; k < CELL_SIZE; k++)
for (int sprite_row = 0; sprite_row < CELL_SIZE; sprite_row++)
{
// offset from base address in source atlas layout
const unsigned int src_offset = i + k * w + j * w * CELL_SIZE;
// offset from base address in glerminal atlas layout
const unsigned int dst_offset = i + k * MAX_SPRITES_ROW + j * MAX_SPRITES_ROW * CELL_SIZE;
const unsigned int sprite_index = src_atlas_col + src_atlas_row * w;
const unsigned int dst_atlas_row = sprite_index / MAX_SPRITES_ROW;
const unsigned int dst_atlas_col = sprite_index % MAX_SPRITES_ROW;
memcpy(m_sprites + CELL_SIZE * dst_offset, data + CELL_SIZE * src_offset, CELL_SIZE * sizeof(unsigned int));
// offset from base address in source atlas layout
const unsigned int src_offset = CELL_SIZE * (src_atlas_col + sprite_row * w + src_atlas_row * w * CELL_SIZE);
const unsigned int dst_column = dst_atlas_col * (CELL_SIZE + 2) + 1;
const unsigned int dst_row = MAX_SPRITES_ROW * (CELL_SIZE + 2) * ((sprite_row + 1) + dst_atlas_row * (CELL_SIZE + 2));
// offset from base address in glerminal atlas layout
const unsigned int dst_offset = dst_column + dst_row;
memcpy(m_sprites + dst_offset, data + src_offset, CELL_SIZE * sizeof(unsigned int));
}
}
}
@ -365,7 +372,6 @@ namespace glerminal
{
glfwInit();
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
@ -691,7 +697,7 @@ namespace glerminal
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTextureStorage2D(m_sprites_texture, 1, GL_RGBA8, MAX_SPRITES_ROW * CELL_SIZE, MAX_SPRITES_ROW * CELL_SIZE);
glTextureStorage2D(m_sprites_texture, 1, GL_RGBA8, MAX_SPRITES_ROW * (CELL_SIZE + 2), MAX_SPRITES_ROW * (CELL_SIZE + 2));
update_sprites();
@ -765,7 +771,7 @@ namespace glerminal
void glerminal::update_sprites()
{
glTextureSubImage2D(m_sprites_texture, 0, 0, 0, CELL_SIZE * MAX_SPRITES_ROW, CELL_SIZE * MAX_SPRITES_ROW, GL_RGBA, GL_UNSIGNED_BYTE, m_sprites);
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()
@ -822,14 +828,14 @@ void glerminal_flush()
GLERMINAL_G->flush();
}
void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite)
void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite)
{
if (!GLERMINAL_G) { return; }
GLERMINAL_G->set(x, y, layer, sprite);
}
unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char layer)
unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned short layer)
{
if (!GLERMINAL_G) { return 0; }