This commit is contained in:
Zack Buhman 2025-12-09 20:53:59 -06:00
parent d18809c789
commit 26183e813c
9 changed files with 315 additions and 3 deletions

View File

@ -17,6 +17,7 @@ CFLAGS += -Wno-error=unused-but-set-variable
CFLAGS += -Wno-error=unused-variable
CFLAGS += -I$(MAKEFILE_PATH)/include
CFLAGS += -I$(MAKEFILE_PATH)
CFLAGS += -I$(dir $(GLFW))../include
CXXFLAGS += -fno-exceptions
LDFLAGS += -nostdlib++ -lm -static-libgcc
ifeq ($(OS),Windows_NT)

View File

@ -24,6 +24,10 @@ uint make_texture(const void * data,
uint make_framebuffer(uint * texture, int length);
void debug_framebuffer(int width, int height,
int elements,
const char * format);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_src_solution_2025_04_count_fs_glsl_start __asm("_binary_src_solution_2025_04_count_fs_glsl_start");
extern uint32_t _binary_src_solution_2025_04_count_fs_glsl_end __asm("_binary_src_solution_2025_04_count_fs_glsl_end");
extern uint32_t _binary_src_solution_2025_04_count_fs_glsl_size __asm("_binary_src_solution_2025_04_count_fs_glsl_size");
#define src_solution_2025_04_count_fs_glsl_start ((const char *)&_binary_src_solution_2025_04_count_fs_glsl_start)
#define src_solution_2025_04_count_fs_glsl_end ((const char *)&_binary_src_solution_2025_04_count_fs_glsl_end)
#define src_solution_2025_04_count_fs_glsl_size (src_solution_2025_04_count_fs_glsl_end - src_solution_2025_04_count_fs_glsl_start)
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_src_solution_2025_04_simulate_fs_glsl_start __asm("_binary_src_solution_2025_04_simulate_fs_glsl_start");
extern uint32_t _binary_src_solution_2025_04_simulate_fs_glsl_end __asm("_binary_src_solution_2025_04_simulate_fs_glsl_end");
extern uint32_t _binary_src_solution_2025_04_simulate_fs_glsl_size __asm("_binary_src_solution_2025_04_simulate_fs_glsl_size");
#define src_solution_2025_04_simulate_fs_glsl_start ((const char *)&_binary_src_solution_2025_04_simulate_fs_glsl_start)
#define src_solution_2025_04_simulate_fs_glsl_end ((const char *)&_binary_src_solution_2025_04_simulate_fs_glsl_end)
#define src_solution_2025_04_simulate_fs_glsl_size (src_solution_2025_04_simulate_fs_glsl_end - src_solution_2025_04_simulate_fs_glsl_start)
#ifdef __cplusplus
}
#endif

View File

@ -29,6 +29,7 @@ const float triangle_array[] = {
extern void solution_2025_01(unsigned int vertex_array);
extern void solution_2025_03(unsigned int vertex_array);
extern void solution_2025_04(unsigned int vertex_array);
int main()
{
@ -56,6 +57,13 @@ int main()
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
int n;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for (int i=0; i<n; i++) {
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
//printf("Ext %d: %s\n", i, extension);
}
//////////////////////////////////////////////////////////////////////
// buffers
//////////////////////////////////////////////////////////////////////
@ -88,7 +96,8 @@ int main()
glfwSetWindowShouldClose(window, true);
//solution_2025_01(vertex_array);
solution_2025_03(vertex_array);
//solution_2025_03(vertex_array);
solution_2025_04(vertex_array);
break;

View File

@ -85,11 +85,14 @@ uint make_texture(const void * data,
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
float color[3] = {0.0, 0.0, 0.0};
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, type, data);
glBindTexture(GL_TEXTURE_2D, 0);
@ -107,8 +110,33 @@ uint make_framebuffer(uint * texture, int length)
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
//printf("glCheckFramebufferStatus: %x\n", status);
assert(status == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return framebuffer;
}
void debug_framebuffer(int width, int height,
int elements,
const char * format)
{
assert(elements == 1 || elements == 3);
uint gl_format = (elements == 1) ? GL_RED : GL_RGB;
float out[elements * width * height] = {};
glReadPixels(0, 0,
width, height,
gl_format,
GL_FLOAT,
out);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int i = 0; i < elements; i++) {
printf(format, out[(y * width + x) * elements + i]);
}
}
printf("\n");
}
}

View File

@ -0,0 +1,34 @@
#version 330 core
uniform sampler2D input_sampler_a;
uniform sampler2D input_sampler_b;
uniform vec4 dim; // w h halfpx_w halfpx_h
uniform vec2 input_length;
out vec4 fragment_result;
vec2 halfpixel(float x, float y, vec4 dim)
{
return vec2((x * 2.0 + 1.0) * dim.z,
(y * 2.0 + 1.0) * dim.w);
}
float sample(sampler2D sampler, float x, float y)
{
return texture(sampler, halfpixel(x, y, dim)).x;
}
void main()
{
float acc = 0.0;
for (float y = 0.0; y < input_length.y; y += 1.0) {
for (float x = 0.0; x < input_length.x; x += 1.0) {
acc += sample(input_sampler_a, x, y);
acc -= sample(input_sampler_b, x, y);
}
}
fragment_result = vec4(acc);
}

View File

@ -0,0 +1,51 @@
#version 330 core
uniform sampler2D input_sampler;
uniform vec4 dim; // w h halfpx_w halfpx_h
out vec4 fragment_result;
in vec2 f_position;
vec2 halfpixel(float x, float y, vec4 dim)
{
return vec2((x * 2.0 + 1.0) * dim.z,
(y * 2.0 + 1.0) * dim.w);
}
float sample(sampler2D sampler, float x, float y)
{
return texture(sampler, halfpixel(x, y, dim)).x;
}
float neighbors(sampler2D sampler, float x, float y)
{
float acc = 0.0;
acc += sample(sampler, x - 1, y - 1);
acc += sample(sampler, x + 0, y - 1);
acc += sample(sampler, x + 1, y - 1);
acc += sample(sampler, x + 1, y + 0);
acc += sample(sampler, x - 1, y + 0);
acc += sample(sampler, x - 1, y + 1);
acc += sample(sampler, x + 0, y + 1);
acc += sample(sampler, x + 1, y + 1);
return acc;
}
vec2 integer_coord(vec2 v, vec4 dim)
{
return ((v * 0.5 + 0.5) - dim.zw) * dim.xy;
}
void main()
{
vec2 c = integer_coord(f_position, dim);
float n = neighbors(input_sampler, c.x, c.y);
float v = sample(input_sampler, c.x, c.y);
float result = (n < 4) ? 0 : v;
fragment_result = vec4(result);
}

View File

@ -0,0 +1,147 @@
#include <stdio.h>
#include "glad.h"
#include "input.h"
#include "opengl.h"
#include "puzzle/2025/04/input.h"
#include "solution/generic.vs.glsl.h"
#include "solution/2025/04/simulate.fs.glsl.h"
#include "solution/2025/04/count.fs.glsl.h"
static const int temp_width = 256;
static const int temp_height = 256;
static void draw(uint vertex_array,
uint framebuffer,
uint * texture,
int texture_count)
{
for (int i = 0; i < texture_count; i++) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, texture[i]);
}
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0, 0, temp_width, temp_height);
const uint draw_buffers0[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, draw_buffers0);
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void solution_2025_04(unsigned int vertex_array)
{
//////////////////////////////////////////////////////////////////////
// textures
//////////////////////////////////////////////////////////////////////
//const char * input_start = puzzle_2025_04_input_start;
//const int input_length = puzzle_2025_04_input_size;
const char * input_start = "..@@.@@@@.\n@@@.@.@.@@\n@@@@@.@.@@\n@.@@@@..@.\n@@.@@@@.@@\n.@@@@@@@.@\n.@.@.@.@@@\n@.@@@.@@@@\n.@@@@@@@@.\n@.@.@@@.@.\n";
const int input_length = 110;
int y = 0;
int x = 0;
int input_width = 0;
int input_height = 0;
float buf[temp_width * temp_height];
for (int i = 0; i < input_length; i++) {
char c = input_start[i];
if (c == '\n') {
y += 1;
input_width = x;
x = 0;
} else {
buf[y * temp_width + x] = (float)(int)(c == '@');
x += 1;
}
}
input_height = y;
//uint texture_a = make_texture(NULL,
uint texture_a = make_texture(buf,
GL_R32F,
temp_width,
temp_height,
GL_RED,
GL_FLOAT);
uint framebuffer_a = make_framebuffer(&texture_a, 1);
uint texture_b = make_texture(NULL,
GL_R32F,
temp_width,
temp_height,
GL_RED,
GL_FLOAT);
uint framebuffer_b = make_framebuffer(&texture_b, 1);
uint texture_output = make_texture(NULL,
GL_R32F,
1,
1,
GL_RED,
GL_FLOAT);
uint framebuffer_output = make_framebuffer(&texture_output, 1);
//////////////////////////////////////////////////////////////////////
// shaders
//////////////////////////////////////////////////////////////////////
uint p__simulate = compile_shader(src_solution_generic_vs_glsl_start,
src_solution_generic_vs_glsl_size,
src_solution_2025_04_simulate_fs_glsl_start,
src_solution_2025_04_simulate_fs_glsl_size);
uint p__simulate__input_sampler = glGetUniformLocation(p__simulate, "input_sampler");
uint p__simulate__dim = glGetUniformLocation(p__simulate, "dim");
uint p__count = compile_shader(src_solution_generic_vs_glsl_start,
src_solution_generic_vs_glsl_size,
src_solution_2025_04_count_fs_glsl_start,
src_solution_2025_04_count_fs_glsl_size);
uint p__count__input_sampler_a = glGetUniformLocation(p__count, "input_sampler_a");
uint p__count__input_sampler_b = glGetUniformLocation(p__count, "input_sampler_b");
uint p__count__dim = glGetUniformLocation(p__count, "dim");
uint p__count__input_length = glGetUniformLocation(p__count, "input_length");
//////////////////////////////////////////////////////////////////////
// part 1
//////////////////////////////////////////////////////////////////////
// simulate
glUseProgram(p__simulate);
glUniform1i(p__simulate__input_sampler, 0);
glUniform4f(p__simulate__dim,
temp_width,
temp_height,
0.5f / temp_width,
0.5f / temp_height);
draw(vertex_array, framebuffer_b, &texture_a, 1);
//debug_framebuffer(input_width, input_height, 1, "%1.0f");
// count
glUseProgram(p__count);
glUniform1i(p__count__input_sampler_a, 0);
glUniform1i(p__count__input_sampler_b, 1);
glUniform4f(p__count__dim,
temp_width,
temp_height,
0.5f / temp_width,
0.5f / temp_height);
glUniform2f(p__count__input_length,
input_width,
input_height);
uint textures[] = {texture_a, texture_b};
draw(vertex_array, framebuffer_output, textures, 2);
//debug_framebuffer(1, 1, 1, "%f");
float out;
glReadPixels(0, 0, 1, 1, GL_RED, GL_FLOAT, &out);
printf("part 1: %d\n", (int)out);
//////////////////////////////////////////////////////////////////////
// part 2
//////////////////////////////////////////////////////////////////////
}