Allow for up to 4096 sprites

This commit is contained in:
Shylie 2024-06-01 13:25:20 -04:00
parent e5b017ad97
commit a39905c6cb
3 changed files with 44 additions and 31 deletions

View File

@ -9,6 +9,7 @@ extern "C"
} }
#include <iostream> #include <iostream>
#include <string>
#ifdef _WIN32 #ifdef _WIN32
#define WINDOWS_LEAN_AND_MEAN #define WINDOWS_LEAN_AND_MEAN
@ -117,7 +118,7 @@ namespace
if (lua_pcall(L, 0, 0, 0) != LUA_OK) if (lua_pcall(L, 0, 0, 0) != LUA_OK)
{ {
// ignore error for now // ignore error for now
lua_remove(L, -1); lua_pop(L, 1);
} }
} }
@ -130,7 +131,7 @@ namespace
if (lua_pcall(L, 1, 0, 0) != LUA_OK) if (lua_pcall(L, 1, 0, 0) != LUA_OK)
{ {
// ignore error for now // ignore error for now
lua_remove(L, -1); lua_pop(L, 1);
} }
} }
@ -146,7 +147,7 @@ namespace
if (lua_pcall(L, 1, 0, 0) != LUA_OK) if (lua_pcall(L, 1, 0, 0) != LUA_OK)
{ {
// ignore error for now // ignore error for now
lua_remove(L, -1); lua_pop(L, 1);
} }
} }
} }
@ -163,7 +164,7 @@ namespace
if (lua_pcall(L, 1, 0, 0) != LUA_OK) if (lua_pcall(L, 1, 0, 0) != LUA_OK)
{ {
// ignore error for now // ignore error for now
lua_remove(L, -1); lua_pop(L, 1);
} }
} }
} }
@ -189,7 +190,11 @@ int main(int argc, char** argv)
luaL_newlib(L, lglerminal_methods); luaL_newlib(L, lglerminal_methods);
lua_setglobal(L, "glerminal"); lua_setglobal(L, "glerminal");
luaL_dofile(L, "main.lua"); if (luaL_dofile(L, "main.lua") != LUA_OK)
{
const char* str = lua_tostring(L, -1);
lua_pop(L, 1);
}
glerminal_run(init, mainloop, pressed, released); glerminal_run(init, mainloop, pressed, released);

View File

@ -14,6 +14,8 @@
namespace glerminal namespace glerminal
{ {
constexpr unsigned int CELL_SIZE = 8; constexpr unsigned int CELL_SIZE = 8;
constexpr unsigned int MAX_SPRITES_ROW = 64;
constexpr unsigned int MAX_SPRITES = MAX_SPRITES_ROW * MAX_SPRITES_ROW;
constexpr unsigned int GRID_WIDTH = ::GRID_WIDTH; constexpr unsigned int GRID_WIDTH = ::GRID_WIDTH;
constexpr unsigned int GRID_HEIGHT = ::GRID_HEIGHT; constexpr unsigned int GRID_HEIGHT = ::GRID_HEIGHT;
constexpr unsigned int LAYER_COUNT = ::LAYER_COUNT; constexpr unsigned int LAYER_COUNT = ::LAYER_COUNT;
@ -72,7 +74,7 @@ namespace glerminal
// per-cell data // per-cell data
unsigned char m_cells[GRID_AREA * LAYER_COUNT]; unsigned short m_cells[GRID_AREA * LAYER_COUNT];
float m_offsets[GRID_AREA * LAYER_COUNT * 2]; float m_offsets[GRID_AREA * LAYER_COUNT * 2];
// per-layer data // per-layer data
@ -82,7 +84,7 @@ namespace glerminal
// library state // library state
unsigned int m_sprites[CELL_SIZE * CELL_SIZE * (1 << (8 * sizeof(*m_cells)))]; unsigned int m_sprites[CELL_SIZE * CELL_SIZE * MAX_SPRITES];
glerminal_main_cb m_main; glerminal_main_cb m_main;
glerminal_keys_cb m_pressed, m_released; glerminal_keys_cb m_pressed, m_released;

View File

@ -1,12 +1,13 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#define STBI_ONLY_PNG #define STBI_ONLY_PNG
#define STBI_MAX_DIMENSIONS 128 #define STBI_MAX_DIMENSIONS 512
#include "glerminal-private.h" #include "glerminal-private.h"
#define GRID_SIZE_UNIFORM_NAME "grid_size" #define GRID_SIZE_UNIFORM_NAME "grid_size"
#define SPRITES_UNIFORM_NAME "sprites" #define SPRITES_UNIFORM_NAME "sprites"
#define LAYERS_UNIFORM_NAME "layers" #define LAYERS_UNIFORM_NAME "layers"
#define LAYER_COUNT_UNIFORM_NAME "layer_count" #define LAYER_COUNT_UNIFORM_NAME "layer_count"
#define ATLAS_WIDTH_UNIFORM_NAME "atlas_width"
namespace namespace
{ {
@ -31,6 +32,7 @@ namespace
"layout (location = 1) in vec2 offset;\n" "layout (location = 1) in vec2 offset;\n"
"layout (location = 2) in int sprite;\n" "layout (location = 2) in int sprite;\n"
"uniform vec4 " GRID_SIZE_UNIFORM_NAME ";\n" "uniform vec4 " GRID_SIZE_UNIFORM_NAME ";\n"
"uniform int " ATLAS_WIDTH_UNIFORM_NAME ";\n"
"layout (std430, binding = 0) buffer LayerScales" "layout (std430, binding = 0) buffer LayerScales"
"{\n" "{\n"
" float scales[];\n" " float scales[];\n"
@ -52,7 +54,7 @@ namespace
" vs_out.sprite = sprite;\n" " vs_out.sprite = sprite;\n"
" vs_out.layer = layer;\n" " vs_out.layer = layer;\n"
" vs_out.layer_color = lcs.colors[layer];\n" " vs_out.layer_color = lcs.colors[layer];\n"
" vs_out.texcoord = vec2(position.x + 1, -position.y);\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) / -16, (position.y + 0.5) / 16)) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ");\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 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 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" " gl_Position = vec4(scaled_offset.x + temp.x, scaled_offset.y - temp.y, 0, 1);\n"
@ -67,6 +69,7 @@ namespace
"layout (location = 1) in vec2 offset;\n" "layout (location = 1) in vec2 offset;\n"
"layout (location = 2) in int sprite;\n" "layout (location = 2) in int sprite;\n"
"uniform vec4 " GRID_SIZE_UNIFORM_NAME ";\n" "uniform vec4 " GRID_SIZE_UNIFORM_NAME ";\n"
"uniform int " ATLAS_WIDTH_UNIFORM_NAME ";\n"
"layout (std430, binding = 0) buffer LayerScales" "layout (std430, binding = 0) buffer LayerScales"
"{\n" "{\n"
" float scales[];\n" " float scales[];\n"
@ -86,7 +89,7 @@ namespace
" gl_Layer = layer;\n" " gl_Layer = layer;\n"
" vec2 scaled_offset = 2 * offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n" " vec2 scaled_offset = 2 * offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n"
" vs_out.sprite = sprite;\n" " vs_out.sprite = sprite;\n"
" vs_out.texcoord = vec2(position.x + 1, -position.y);\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) / -16, (position.y + 0.5) / 16)) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ");\n"
" vs_out.layer_color = lcs.colors[layer];\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 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 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"
@ -139,11 +142,11 @@ namespace
"flat in int sprite;\n" "flat in int sprite;\n"
"flat vec4 layer_color;\n" "flat vec4 layer_color;\n"
"in vec2 texcoord;\n" "in vec2 texcoord;\n"
"layout (binding = 0) uniform sampler2DArray " SPRITES_UNIFORM_NAME ";\n" "layout (binding = 2) uniform sampler2D " SPRITES_UNIFORM_NAME ";\n"
"out vec4 FragColor;\n" "out vec4 FragColor;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" FragColor = layer_color * texture(" SPRITES_UNIFORM_NAME ", vec3(texcoord, sprite));\n" " FragColor = layer_color * texture(" SPRITES_UNIFORM_NAME ", texcoord);\n"
"}"; "}";
// note: AMD_vertex_shader_layer support required // note: AMD_vertex_shader_layer support required
@ -154,11 +157,11 @@ namespace
" flat vec4 layer_color;\n" " flat vec4 layer_color;\n"
" vec2 texcoord;\n" " vec2 texcoord;\n"
"} fs_in;\n" "} fs_in;\n"
"layout (binding = 0) uniform sampler2DArray " SPRITES_UNIFORM_NAME ";\n" "layout (binding = 2) uniform sampler2D " SPRITES_UNIFORM_NAME ";\n"
"out vec4 FragColor;\n" "out vec4 FragColor;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" FragColor = fs_in.layer_color * texture(" SPRITES_UNIFORM_NAME ", vec3(fs_in.texcoord, fs_in.sprite));\n" " FragColor = fs_in.layer_color * texture(" SPRITES_UNIFORM_NAME ", fs_in.texcoord);\n"
"}"; "}";
constexpr const char* FRAGMENT_SHADER_SOURCE_PTR = FRAGMENT_SHADER_SOURCE; constexpr const char* FRAGMENT_SHADER_SOURCE_PTR = FRAGMENT_SHADER_SOURCE;
@ -261,8 +264,6 @@ namespace glerminal
m_main(current - last); m_main(current - last);
last = current; last = current;
glfwSwapBuffers(m_window);
} }
} }
@ -295,7 +296,9 @@ namespace glerminal
glfwSwapBuffers(m_window); glfwSwapBuffers(m_window);
glBlitNamedFramebuffer(m_screen_framebuffer, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); //glBlitNamedFramebuffer(m_screen_framebuffer, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
//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 char sprite)
@ -351,10 +354,10 @@ namespace glerminal
// each row of the individual sprite // each row of the individual sprite
for (int k = 0; k < CELL_SIZE; k++) for (int k = 0; k < CELL_SIZE; k++)
{ {
// offset from base address in atlas layout // offset from base address in source atlas layout
const unsigned int src_offset = i + k * w + j * w * CELL_SIZE; const unsigned int src_offset = i + k * w + j * w * CELL_SIZE;
// offset from base address in array layout // offset from base address in glerminal atlas layout
const unsigned int dst_offset = k + i * CELL_SIZE + j * w * CELL_SIZE; const unsigned int dst_offset = i + k * MAX_SPRITES_ROW + j * MAX_SPRITES_ROW * CELL_SIZE;
memcpy(m_sprites + CELL_SIZE * dst_offset, data + CELL_SIZE * src_offset, CELL_SIZE * sizeof(unsigned int)); memcpy(m_sprites + CELL_SIZE * dst_offset, data + CELL_SIZE * src_offset, CELL_SIZE * sizeof(unsigned int));
} }
@ -499,7 +502,7 @@ namespace glerminal
glBindBuffer(GL_ARRAY_BUFFER, m_sprites_instance_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_sprites_instance_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(m_cells), m_cells, GL_STREAM_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(m_cells), m_cells, GL_STREAM_DRAW);
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
glVertexAttribIPointer(2, 1, GL_UNSIGNED_BYTE, 1 * sizeof(*m_cells), reinterpret_cast<void*>(0)); glVertexAttribIPointer(2, 1, GL_UNSIGNED_SHORT, 1 * sizeof(*m_cells), reinterpret_cast<void*>(0));
glVertexAttribDivisor(2, 1); glVertexAttribDivisor(2, 1);
// set up static vertex attributes // set up static vertex attributes
@ -617,6 +620,7 @@ namespace glerminal
glUseProgram(m_program); glUseProgram(m_program);
glUniform4f(m_screen_size_uniform_location, GRID_WIDTH, GRID_AREA, 1.0f / GRID_WIDTH, 1.0f / GRID_HEIGHT); glUniform4f(m_screen_size_uniform_location, GRID_WIDTH, GRID_AREA, 1.0f / GRID_WIDTH, 1.0f / GRID_HEIGHT);
glUniform1i(glGetUniformLocation(m_program, ATLAS_WIDTH_UNIFORM_NAME), MAX_SPRITES_ROW);
// compile // compile
const unsigned int screen_vertex_shader = glCreateShader(GL_VERTEX_SHADER); const unsigned int screen_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
@ -680,20 +684,23 @@ namespace glerminal
// -- setup textures -- // -- setup textures --
glGenTextures(1, &m_sprites_texture); glGenTextures(1, &m_sprites_texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_sprites_texture); glBindTexture(GL_TEXTURE_2D, m_sprites_texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_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);
update_sprites(); update_sprites();
glBindTextureUnit(0, m_sprites_texture); glBindTextureUnit(2, m_sprites_texture);
const auto err = glGetError();
// -- setup framebuffer -- // -- setup framebuffer --
glGenFramebuffers(1, &m_framebuffer); glGenFramebuffers(1, &m_framebuffer);
@ -762,8 +769,7 @@ namespace glerminal
void glerminal::update_sprites() void glerminal::update_sprites()
{ {
glBindTexture(GL_TEXTURE_2D_ARRAY, m_sprites_texture); glTextureSubImage2D(m_sprites_texture, 0, 0, 0, CELL_SIZE * MAX_SPRITES_ROW, CELL_SIZE * MAX_SPRITES_ROW, GL_RGBA, GL_UNSIGNED_BYTE, m_sprites);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, CELL_SIZE, CELL_SIZE, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_sprites);
} }
void glerminal::update_layer_colors() void glerminal::update_layer_colors()