From d5ef14c64d948df1f62c3e66f8a18daf4baa508c Mon Sep 17 00:00:00 2001 From: shylie Date: Sun, 3 Aug 2025 14:56:11 -0400 Subject: [PATCH] Palette lookup --- examples/basic.cpp | 26 ++++++++++-- include/sprstk/sprstk.h | 12 +++++- src/sprstk.cpp | 88 ++++++++++++++++++++++++++++++++--------- 3 files changed, 102 insertions(+), 24 deletions(-) diff --git a/examples/basic.cpp b/examples/basic.cpp index 0521862..528fd4f 100644 --- a/examples/basic.cpp +++ b/examples/basic.cpp @@ -3,11 +3,31 @@ namespace { +void init(sprstk* instance, void* userdata) +{ + sprstk_palette pal = {}; + + for (int i = 0; i < 28; i++) + { + pal.colors[i] = 0x7F4F0040; + } + + for (int i = 28; i < 32; i++) + { + pal.colors[i] = 0x00FF0040; + } + + sprstk_set_palette(instance, 0, &pal); +} + void update(sprstk* instance, float dt, void* userdata) { - for (int i = 0; i < 10; i += 2) + for (int i = 0; i < 16; i++) { - sprstk_put(instance, i, 0); + for (int j = 15; j >= 0; j--) + { + sprstk_put(instance, i - 8, j - 8, i + j + 1, 0); + } } } @@ -15,7 +35,7 @@ void update(sprstk* instance, float dt, void* userdata) int main() { - sprstk* instance = sprstk_new({.update = update}, nullptr); + sprstk* instance = sprstk_new({.init = init, .update = update}, nullptr); sprstk_run(instance); diff --git a/include/sprstk/sprstk.h b/include/sprstk/sprstk.h index 0675254..5818b1d 100644 --- a/include/sprstk/sprstk.h +++ b/include/sprstk/sprstk.h @@ -1,6 +1,8 @@ #ifndef SPRSTK_H #define SPRSTK_H +#include + #ifdef __cplusplus extern "C" { @@ -18,14 +20,20 @@ typedef struct { sprstk_quit_fn quit; } sprstk_callbacks; +typedef struct { + uint32_t colors[32]; +} sprstk_palette; + sprstk* sprstk_new(sprstk_callbacks callbacks, void* userdata); void sprstk_del(sprstk* instance); void sprstk_run(sprstk* instance); void sprstk_stop(sprstk* instance); -void sprstk_put(sprstk* instance, unsigned int x, unsigned int y); -void sprstk_putz(sprstk* instance, unsigned int x, unsigned int y, unsigned int z_offset); +void sprstk_put(sprstk* instance, int x, int y, unsigned int layers, unsigned int palette_lookup); +void sprstk_putz(sprstk* instance, int x, int y, unsigned int layers, unsigned int palette_lookup, unsigned int z_offset); + +void sprstk_set_palette(sprstk* instance, unsigned int index, const sprstk_palette* palette); #ifdef __cplusplus } diff --git a/src/sprstk.cpp b/src/sprstk.cpp index 0cb3b48..3051113 100644 --- a/src/sprstk.cpp +++ b/src/sprstk.cpp @@ -30,14 +30,26 @@ layout (std430, binding = 0) restrict readonly buffer TileInfos TileInfo[] tile_infos; }; +struct ColorInfo +{ + uint color[32]; +}; + +layout (std430, binding = 1) restrict readonly buffer ColorInfos +{ + ColorInfo[] color_infos; +}; + const uint indices[6] = { 0, 1, 2, 2, 1, 3 }; void main() { - TileInfo info = tile_infos[gl_WorkGroupID.x]; - uint position_x = bitfieldExtract(info.position, 0, 13); - uint position_y = bitfieldExtract(info.position, 13, 13); - vec2 stack_position = vec2(position_x, position_y); + TileInfo t_info = tile_infos[gl_WorkGroupID.x]; + uint position_x = bitfieldExtract(t_info.position, 0, 10); + uint position_y = bitfieldExtract(t_info.position, 10, 10); + vec2 stack_position = vec2(position_x, position_y) - vec2(512, 512); + + uint layer_count = bitfieldExtract(t_info.position, 20, 5); vec2 positions[4] = { vec2(0, 0), vec2(1, 0), vec2(0, 1), vec2(1, 1) }; for (uint i = 0; i < 4; i++) @@ -47,15 +59,22 @@ void main() positions[i] /= screen_size_and_pixel_scale.xy; } - uint z_offset = bitfieldExtract(info.position, 26, 6); + uint z_offset = bitfieldExtract(t_info.position, 25, 2); + + uint palette_lookup = bitfieldExtract(t_info.position, 27, 5); + ColorInfo c_info = color_infos[palette_lookup]; + float a = bitfieldExtract(c_info.color[int(ceil(gl_LocalInvocationID.x * (32.0 / layer_count)))], 0, 8); + float b = bitfieldExtract(c_info.color[int(ceil(gl_LocalInvocationID.x * (32.0 / layer_count)))], 8, 8); + float g = bitfieldExtract(c_info.color[int(ceil(gl_LocalInvocationID.x * (32.0 / layer_count)))], 16, 8); + float r = bitfieldExtract(c_info.color[int(ceil(gl_LocalInvocationID.x * (32.0 / layer_count)))], 24, 8); for (uint i = 4 * gl_LocalInvocationID.x; i < 4 * gl_LocalInvocationID.x + 4; i++) { vec4 position = vec4(positions[i % 4], float(4 * gl_LocalInvocationID.x + z_offset) / 128, 1); - position.y += 8 * position.z / screen_size_and_pixel_scale.z; + position.y += 24 * position.z / screen_size_and_pixel_scale.z; gl_MeshVerticesNV[i].gl_Position = position; - v_out[i].color = vec4(1, 1, 1, 0.1); + v_out[i].color = vec4(r, g, b, a) / vec4(256, 256, 256, 256); } for (uint i = 6 * gl_LocalInvocationID.x; i < 6 * gl_LocalInvocationID.x + 6; i++) @@ -63,7 +82,7 @@ void main() gl_PrimitiveIndicesNV[i] = 4 * gl_LocalInvocationID.x + indices[i % 6]; } - gl_PrimitiveCountNV = 64; + gl_PrimitiveCountNV = layer_count * 2; } )"; @@ -163,14 +182,32 @@ public: should_stop = true; } - void put(unsigned int x, unsigned int y, unsigned int z_offset = 0) + void put(int x, int y, unsigned int layers, unsigned int palette_lookup, unsigned int z_offset = 0) { - x &= 0b0001111111111111; - y &= 0b0001111111111111; - y <<= 13; - z_offset &= 0b111111; - z_offset <<= 26; - gl.tile_buffer_map[gl.tile_count++] = { x | y | z_offset }; + x += 512; + x &= 0b1111111111; + + y += 512; + y &= 0b1111111111; + y <<= 10; + + layers &= 0b11111; + layers <<= 20; + + z_offset &= 0b11; + z_offset <<= 25; + + palette_lookup &= 0b11111; + palette_lookup <<= 27; + + gl.tile_buffer_map[gl.tile_count++] = { x | y | layers | z_offset | palette_lookup }; + } + + void set_palette(unsigned int index, const sprstk_palette* palette) + { + if (index > (1 << 5)) { return; } + + gl.color_info_map[index] = *palette; } private: @@ -191,6 +228,8 @@ private: unsigned int tile_buffer; TileInfo* tile_buffer_map; unsigned int tile_count; + unsigned int color_buffer; + sprstk_palette* color_info_map; } gl; void init_sdl() @@ -300,6 +339,12 @@ private: gl.tile_count = 0; gl.tile_buffer_map = (TileInfo*)glMapNamedBufferRange(gl.tile_buffer, 0, sizeof(TileInfo) * (1 << 26), GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT); + + glGenBuffers(1, &gl.color_buffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, gl.color_buffer); + glNamedBufferStorage(gl.color_buffer, sizeof(sprstk_palette) * (1 << 5), nullptr, GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT); + + gl.color_info_map = (sprstk_palette*)glMapNamedBufferRange(gl.color_buffer, 0, sizeof(sprstk_palette) * (1 << 5), GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT); } void destroy_gl() @@ -354,14 +399,19 @@ void sprstk_stop(sprstk* instance) instance->stop(); } -void sprstk_put(sprstk* instance, unsigned int x, unsigned int y) +void sprstk_put(sprstk* instance, int x, int y, unsigned int layers, unsigned int palette_lookup) { - instance->put(x, y); + instance->put(x, y, layers, palette_lookup); } -void sprstk_putz(sprstk* instance, unsigned int x, unsigned int y, unsigned int z_offset) +void sprstk_putz(sprstk* instance, int x, int y, unsigned int layers, unsigned int palette_lookup, unsigned int z_offset) { - instance->put(x, y, z_offset); + instance->put(x, y, layers, palette_lookup, z_offset); +} + +void sprstk_set_palette(sprstk* instance, unsigned int index, const sprstk_palette* palette) +{ + instance->set_palette(index, palette); } }