Fix a bug with glerminal_layer_scale that caused unintended behavior

This commit is contained in:
Shylie 2024-05-23 10:53:07 -04:00
parent c89563338a
commit 17ea6a7f0a
9 changed files with 164 additions and 55 deletions

View File

@ -31,7 +31,7 @@ target_include_directories(glerminal
) )
target_link_libraries(glerminal target_link_libraries(glerminal
PUBLIC PRIVATE
glfw glfw
) )

View File

@ -24,11 +24,11 @@ namespace
time = 0; time = 0;
} }
for (int i = 0; i < 40; i++) for (int i = 0; i < GRID_WIDTH; i++)
{ {
for (int j = 0; j < 25; j++) for (int j = 0; j < GRID_HEIGHT; j++)
{ {
for (int k = 0; k < 256; k++) for (int k = 0; k < LAYER_COUNT; k++)
{ {
glerminal_set(i, j, k, rand() % 4); glerminal_set(i, j, k, rand() % 4);
glerminal_offset(i, j, k, (rand() * rand()) % 64 - 32, (rand() * rand()) % 64 - 32); glerminal_offset(i, j, k, (rand() * rand()) % 64 - 32, (rand() * rand()) % 64 - 32);

View File

@ -7,32 +7,28 @@ namespace
void init() void init()
{ {
glerminal_load_sprites_file("resources/basic.png"); glerminal_load_sprites_file("resources/basic.png");
for (int i = 0; i < GRID_WIDTH; i++)
{
for (int j = 0; j < GRID_HEIGHT; j++)
{
glerminal_set(i, j, 0, 1);
}
}
} }
void mainloop(float dt) void mainloop(float dt)
{ {
static float time = 1; static float time = 0;
time += dt; time += dt;
time = fmodf(time, 3.1415926f * 2);
if (time < 0.2f) for (int i = 0; i < GRID_WIDTH; i++)
{ {
return; for (int j = 0; j < GRID_HEIGHT; j++)
}
else
{ {
time = 0; glerminal_offset(i, j, 0, cosf(time - i / 3.1415f), sinf(time - j / 3.1415f));
}
for (int i = 0; i < 40; i++)
{
for (int j = 0; j < 25; j++)
{
for (int k = 0; k < 256; k++)
{
glerminal_set(i, j, k, rand() % 3 == 0);
glerminal_offset(i, j, k, (rand() * rand()) % 64 - 32, (rand() * rand()) % 64 - 32);
}
} }
} }

BIN
examples/resources/rogue.png (Stored with Git LFS) Normal file

Binary file not shown.

87
examples/rogue.cpp Normal file
View File

@ -0,0 +1,87 @@
#include <glerminal.h>
#include <cmath>
namespace
{
enum : unsigned char
{
empty,
player,
floor,
wall
};
constexpr unsigned int WALL_LAYERS = LAYER_COUNT - 1;
void init()
{
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<float>(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++)
{
if (i == 0 || j == 0 || i == GRID_WIDTH - 1 || j == GRID_HEIGHT - 1)
{
glerminal_set(i, j, k, floor);
}
else
{
glerminal_set(i, j, k, wall);
}
}
}
}
}
void mainloop(float dt)
{
static float time = 0;
time += dt;
const float cx = GRID_WIDTH / 2.0f * cosf(time / 2) + GRID_WIDTH / 2.0f;
const float cy = GRID_HEIGHT / 2.0f * sinf(time / 2) + GRID_HEIGHT / 2.0f;
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 float dx = (i - cx);
const float dy = (j - cy);
const float dist = sqrtf(dx * dx + dy * dy);
const float angle = atan2f(dy, dx);
const float ox = dist * k / WALL_LAYERS * cosf(angle);
const float oy = dist * k / WALL_LAYERS * sinf(angle);
glerminal_offset(i, j, k, ox * 2, oy * 2);
}
glerminal_set(i, j, WALL_LAYERS, empty);
}
}
glerminal_set(cx, cy, WALL_LAYERS, player);
glerminal_flush();
}
}
int main(int argc, char** argv)
{
glerminal_run(init, mainloop);
}

View File

@ -9,20 +9,20 @@ namespace
{ {
glerminal_load_sprites_file("resources/towers.png"); glerminal_load_sprites_file("resources/towers.png");
for (int i = 0; i < 256; i++) for (int i = 0; i < LAYER_COUNT; i++)
{ {
constexpr unsigned char c = 0; constexpr unsigned char c = 16;
const unsigned char v = (255 - c) * powf((i - 1) / 256.0f, 2.0f) + c; const unsigned char v = (255 - c) * powf((256 / LAYER_COUNT * i - 1) / 256.0f, 2.0f) + c;
const unsigned int j = (0x7F << 24) | (v << 16) | (v << 8) | v; const unsigned int j = (0xFF << 24) | (v << 16) | (v << 8) | v;
glerminal_layer_color(i, j); glerminal_layer_color(i, j);
glerminal_layer_scale(i, i / 256.0f + 1); glerminal_layer_scale(i, i / static_cast<float>(LAYER_COUNT) + 1);
} }
for (int i = 0; i < 40; i++) for (int i = 0; i < GRID_WIDTH; i++)
{ {
for (int j = 0; j < 25; j++) for (int j = 0; j < GRID_HEIGHT; j++)
{ {
const int c = rand() % 224 + 32; const int c = rand() % (LAYER_COUNT * 3 / 4) + LAYER_COUNT / 4;
for (int k = 0; k < c; k++) for (int k = 0; k < c; k++)
{ {
glerminal_set(i, j, k, 1); glerminal_set(i, j, k, 1);
@ -37,18 +37,20 @@ namespace
time += dt; time += dt;
const float cx = 20.0f * cosf(time / 3.1415f) + 20.0f; const float cx = (GRID_WIDTH / 2.0f) * cosf(time / 3.1415f) + (GRID_WIDTH / 2.0f);
const float cy = 12.5f * sinf(time / 3.1415f) + 12.5f; const float cy = (GRID_HEIGHT / 2.0f) * sinf(time / 3.1415f) + (GRID_HEIGHT / 2.0f);
for (int i = 0; i < 40; i++) for (int i = 0; i < GRID_WIDTH; i++)
{ {
for (int j = 0; j < 25; j++) for (int j = 0; j < GRID_WIDTH; j++)
{ {
for (int k = 0; k < 256; k++) for (int k = 0; k < LAYER_COUNT; k++)
{ {
const float ox = 0.01f * k * (i - cx); const float ox = (256.0f / LAYER_COUNT) * 0.0025f * k * (i - cx);
const float oy = 0.01f * k * (j - cy); const float oy = (256.0f / LAYER_COUNT) * 0.0025f * k * (j - cy);
glerminal_offset(i, j, k, ox + (1 + 0.004f * k) * cosf(i + k * 6.2832f / 128.0f + 3.1415f * time), oy + (1 + 0.004f * k) * sinf(j + k * 6.2832f / 128.0f + 3.1415f * time)); const float sx = (1 + (256.0f / LAYER_COUNT) * 0.002f * k) * cosf(i + k * 6.2832f / 128.0f + 3.1415f * time / 1.5f);
const float sy = (1 + (256.0f / LAYER_COUNT) * 0.002f * k) * sinf(j + k * 6.2832f / 128.0f + 3.1415f * time / 1.5f);
glerminal_offset(i, j, k, ox + sx, oy + sy);
} }
} }
} }

View File

@ -6,6 +6,13 @@ extern "C"
{ {
#endif #endif
enum
{
GRID_WIDTH = 40,
GRID_HEIGHT = 25,
LAYER_COUNT = 64
};
typedef void (*glerminal_init_cb)(); typedef void (*glerminal_init_cb)();
typedef void (*glerminal_main_cb)(float dt); typedef void (*glerminal_main_cb)(float dt);
@ -60,8 +67,18 @@ void glerminal_layer_color(unsigned char layer, unsigned int color);
*/ */
void glerminal_layer_scale(unsigned char layer, float scale); void glerminal_layer_scale(unsigned char layer, float scale);
/**
* @brief Load sprites from a png file
* @param filename Name of the png file
*/
void glerminal_load_sprites_file(const char* filename); void glerminal_load_sprites_file(const char* filename);
/**
* @brief Load sprites from memory
* @param width width of the atlas in sprites
* @param height height of the atlas in sprites
* @param buffer the in-memory atlas
*/
void glerminal_load_sprites_buffer(unsigned char width, unsigned char height, const unsigned int* buffer); void glerminal_load_sprites_buffer(unsigned char width, unsigned char height, const unsigned int* buffer);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -15,10 +15,9 @@ namespace glerminal
constexpr unsigned int SCREEN_WIDTH = 1280; constexpr unsigned int SCREEN_WIDTH = 1280;
constexpr unsigned int SCREEN_HEIGHT = 800; constexpr unsigned int SCREEN_HEIGHT = 800;
constexpr unsigned int CELL_SIZE = 8; constexpr unsigned int CELL_SIZE = 8;
constexpr unsigned int CELL_SCALE = 4; constexpr unsigned int LAYER_COUNT = ::LAYER_COUNT;
constexpr unsigned int LAYER_COUNT = 256; constexpr unsigned int GRID_WIDTH = ::GRID_WIDTH;
constexpr unsigned int GRID_WIDTH = SCREEN_WIDTH / (CELL_SIZE * CELL_SCALE); constexpr unsigned int GRID_HEIGHT = ::GRID_HEIGHT;
constexpr unsigned int GRID_HEIGHT = SCREEN_HEIGHT / (CELL_SIZE * CELL_SCALE);
constexpr unsigned int GRID_AREA = GRID_WIDTH * GRID_HEIGHT; constexpr unsigned int GRID_AREA = GRID_WIDTH * GRID_HEIGHT;
class glerminal class glerminal

View File

@ -6,6 +6,7 @@
#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"
namespace namespace
{ {
@ -30,6 +31,10 @@ 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"
"layout (std430, binding = 0) buffer LayerScales"
"{\n"
" float scales[];\n"
"} lss;\n"
"out VS_OUT {\n" "out VS_OUT {\n"
" flat vec2 offset;\n" " flat vec2 offset;\n"
" flat int sprite;\n" " flat int sprite;\n"
@ -38,12 +43,13 @@ namespace
"} vs_out;\n" "} vs_out;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" const int layer = int(floor(gl_InstanceID / " GRID_SIZE_UNIFORM_NAME ".y));\n"
" vs_out.sprite = sprite;\n" " vs_out.sprite = sprite;\n"
" vs_out.offset = offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n" " vs_out.offset = offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n"
" vs_out.layer = int(floor(gl_InstanceID / 1000));\n" " vs_out.layer = layer;\n"
" vs_out.texcoord = vec2(position.x + 1, -position.y);\n" " vs_out.texcoord = vec2(position.x + 1, -position.y);\n"
" vec2 cell_position = vec2(1 + (gl_InstanceID % 1000) - " GRID_SIZE_UNIFORM_NAME ".x * floor((gl_InstanceID % 1000) * " GRID_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID % 1000) * " 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 = vec2((position + cell_position) * " 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(temp.x, -temp.y, 0, 1);\n" " gl_Position = vec4(temp.x, -temp.y, 0, 1);\n"
"}"; "}";
@ -58,25 +64,21 @@ namespace
" vec2 texcoord;\n" " vec2 texcoord;\n"
"} gs_in[];\n" "} gs_in[];\n"
"flat out int sprite;\n" "flat out int sprite;\n"
"layout (std430, binding = 0) buffer LayerScales"
"{\n"
" float scales[];\n"
"} lss;\n"
"out vec2 texcoord;\n" "out vec2 texcoord;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Layer = gs_in[0].layer;\n" " gl_Layer = gs_in[0].layer;\n"
" gl_Position = vec4(gl_in[0].gl_Position.xy * lss.scales[gs_in[0].layer] + gs_in[0].offset, 0, 1);\n" " gl_Position = vec4(gl_in[0].gl_Position.xy + gs_in[0].offset * 2, 0, 1);\n"
" sprite = gs_in[0].sprite;\n" " sprite = gs_in[0].sprite;\n"
" texcoord = gs_in[0].texcoord;\n" " texcoord = gs_in[0].texcoord;\n"
" EmitVertex();\n" " EmitVertex();\n"
" gl_Layer = gs_in[1].layer;\n" " gl_Layer = gs_in[1].layer;\n"
" gl_Position = vec4(gl_in[1].gl_Position.xy * lss.scales[gs_in[1].layer] + gs_in[1].offset, 0, 1);\n" " gl_Position = vec4(gl_in[1].gl_Position.xy + gs_in[1].offset * 2, 0, 1);\n"
" sprite = gs_in[1].sprite;\n" " sprite = gs_in[1].sprite;\n"
" texcoord = gs_in[1].texcoord;\n" " texcoord = gs_in[1].texcoord;\n"
" EmitVertex();\n" " EmitVertex();\n"
" gl_Layer = gs_in[2].layer;\n" " gl_Layer = gs_in[2].layer;\n"
" gl_Position = vec4(gl_in[2].gl_Position.xy * lss.scales[gs_in[2].layer] + gs_in[2].offset, 0, 1);\n" " gl_Position = vec4(gl_in[2].gl_Position.xy + gs_in[2].offset * 2, 0, 1);\n"
" sprite = gs_in[2].sprite;\n" " sprite = gs_in[2].sprite;\n"
" texcoord = gs_in[2].texcoord;\n" " texcoord = gs_in[2].texcoord;\n"
" EmitVertex();\n" " EmitVertex();\n"
@ -112,11 +114,12 @@ namespace
"{\n" "{\n"
" vec4 colors[];\n" " vec4 colors[];\n"
"} lcs;\n" "} lcs;\n"
"uniform int " LAYER_COUNT_UNIFORM_NAME ";\n"
"out vec4 FragColor;\n" "out vec4 FragColor;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" vec3 current_color = vec3(0);\n" " vec3 current_color = vec3(0);\n"
" for (int i = 0; i < 256; i++)\n" " for (int i = 0; i < " LAYER_COUNT_UNIFORM_NAME "; i++)\n"
" {\n" " {\n"
" vec4 texsample = lcs.colors[i] * texture(" LAYERS_UNIFORM_NAME ", vec3(texcoord, i));\n" " vec4 texsample = lcs.colors[i] * texture(" LAYERS_UNIFORM_NAME ", vec3(texcoord, i));\n"
" current_color = mix(current_color, texsample.rgb, texsample.a);\n" " current_color = mix(current_color, texsample.rgb, texsample.a);\n"
@ -199,7 +202,7 @@ namespace glerminal
update_layer_colors(); update_layer_colors();
update_layer_scales(); update_layer_scales();
glViewport(0, 0, GRID_WIDTH * CELL_SIZE, GRID_HEIGHT * CELL_SIZE); glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glUseProgram(m_program); glUseProgram(m_program);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glBindVertexArray(m_vao); glBindVertexArray(m_vao);
@ -511,7 +514,7 @@ namespace glerminal
m_screen_size_uniform_location = glGetUniformLocation(m_program, GRID_SIZE_UNIFORM_NAME); m_screen_size_uniform_location = glGetUniformLocation(m_program, GRID_SIZE_UNIFORM_NAME);
glUseProgram(m_program); glUseProgram(m_program);
glUniform4f(m_screen_size_uniform_location, GRID_WIDTH, GRID_HEIGHT, 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);
// compile // compile
const unsigned int screen_vertex_shader = glCreateShader(GL_VERTEX_SHADER); const unsigned int screen_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
@ -597,13 +600,15 @@ namespace glerminal
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, GRID_WIDTH * CELL_SIZE, GRID_HEIGHT * CELL_SIZE, LAYER_COUNT); glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, SCREEN_WIDTH, SCREEN_HEIGHT, LAYER_COUNT);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_framebuffer_backing_texture, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_framebuffer_backing_texture, 0);
glBindTextureUnit(1, m_framebuffer_backing_texture); glBindTextureUnit(1, m_framebuffer_backing_texture);
// setup uniforms for screen shader // setup uniforms for screen shader
glUseProgram(m_screen_program); glUseProgram(m_screen_program);
glUniform1i(glGetUniformLocation(m_screen_program, LAYER_COUNT_UNIFORM_NAME), LAYER_COUNT);
} }
void glerminal::deinit_glfw() void glerminal::deinit_glfw()