161 lines
4.4 KiB
C++
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;
|
|
}
|