GameOfLife/main.cc
2025-05-06 11:47:03 -04:00

161 lines
4.4 KiB
C++

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <random>
#include <thread>
#include <utility>
#include <vector>
#include "shaders.hpp"
#define X 250
#define Y 250
#define GRID_SIZE X *Y
GLuint compileShader(GLenum type, const char *src) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
int success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
std::cerr << "ERROR::SHADER_COMPILATION_ERROR\n" << infoLog << std::endl;
}
return shader;
}
GLuint linkProgram(std::vector<GLuint> shaders) {
GLuint program = glCreateProgram();
for (auto s : shaders)
glAttachShader(program, s);
glLinkProgram(program);
int success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(program, 512, nullptr, infoLog);
std::cerr << "ERROR::PROGRAM_LINK_ERROR\n" << infoLog << std::endl;
}
for (auto s : shaders)
glDeleteShader(s);
return program;
}
void resizeCall(GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
}
int main() {
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow *w = glfwCreateWindow(800, 600, "game of life", NULL, NULL);
if (!w)
return -2;
glfwMakeContextCurrent(w);
if (glewInit() != GLEW_OK)
return -3;
glfwShowWindow(w);
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(w, resizeCall);
/*gen tex*/
GLuint tex[2];
glGenTextures(2, tex);
for (int i = 0; i < 2; ++i) {
glBindTexture(GL_TEXTURE_2D, tex[i]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, X, Y);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
}
/*rnd noise*/
std::vector<GLubyte> data(GRID_SIZE * 4);
std::mt19937 rng;
std::uniform_int_distribution<int> dist(0, 1);
for (int i = 0; i < GRID_SIZE; ++i) {
GLubyte v = dist(rng) * 255;
data[i * 4 + 0] = v; // R channel
data[i * 4 + 1] = v; // G channel
data[i * 4 + 2] = v; // B channel
data[i * 4 + 3] = 255; // A channel
}
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, X, Y, GL_RGBA, GL_UNSIGNED_BYTE,
data.data());
GLuint cmp, rnd, vs, fs;
cmp = linkProgram({compileShader(GL_COMPUTE_SHADER, computeShaderSrc)});
vs = compileShader(GL_VERTEX_SHADER, vertexShaderSrc);
fs = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);
rnd = linkProgram({vs, fs});
/*vtex*/
GLuint VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices,
GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices,
GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(1);
/**/
int ri, wi;
ri = 0;
wi = 1;
while (!glfwWindowShouldClose(w)) {
glfwPollEvents();
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
/*compute*/
glUseProgram(cmp);
glBindImageTexture(0, tex[wi], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
glUniform1i(glGetUniformLocation(cmp, "srcTex"), 0);
glUniform1i(glGetUniformLocation(cmp, "X"), X);
glUniform1i(glGetUniformLocation(cmp, "Y"), Y);
glDispatchCompute(X, Y, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
/*draw*/
glUseProgram(rnd);
glActiveTexture(GL_TEXTURE0);
glUniform1i(glGetUniformLocation(rnd, "tex0"), 0);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *)0);
std::this_thread::sleep_for(std::chrono::duration<double>(.05));
glfwSwapBuffers(w);
std::swap(ri, wi);
}
glfwTerminate();
return 0;
}