Basic compute shader

This commit is contained in:
k 2025-05-03 19:35:24 -04:00
parent 5c61995d1c
commit 152277cd77
2 changed files with 188 additions and 7 deletions

125
main.cc
View File

@ -1,12 +1,46 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <iostream>
#include <random>
#include <utility>
#include <vector>
#define X 16 #include "shaders.hpp"
#define Y 16
#define X 10
#define Y 10
#define GRID_SIZE X *Y #define GRID_SIZE X *Y
#define STR_EXPAND(tok) #tok GLuint compileShader(GLenum type, const char *src) {
#define STR(tok) STR_EXPAND(tok) 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;
}
int main() { int main() {
if (!glfwInit()) if (!glfwInit())
@ -16,7 +50,7 @@ int main() {
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
GLFWwindow *w = glfwCreateWindow(800, 800, "game of life", NULL, NULL); GLFWwindow *w = glfwCreateWindow(800, 600, "game of life", NULL, NULL);
if (!w) if (!w)
return -2; return -2;
@ -26,12 +60,91 @@ int main() {
return -3; return -3;
glfwShowWindow(w); glfwShowWindow(w);
glViewport(0, 0, 800, 800); glViewport(0, 0, 800, 637);
/*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);
}
/*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)) { while (!glfwWindowShouldClose(w)) {
glfwPollEvents(); glfwPollEvents();
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT); 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);
glfwSwapBuffers(w); glfwSwapBuffers(w);
std::swap(ri, wi);
} }
glfwTerminate(); glfwTerminate();

68
shaders.hpp Normal file
View File

@ -0,0 +1,68 @@
const char *computeShaderSrc = R"glsl(
#version 430 core
layout (local_size_x = 1, local_size_y = 1) in;
layout (rgba8) uniform writeonly image2D destTex;
uniform sampler2D srcTex;
uniform int X;
uniform int Y;
ivec2 wrapuv (ivec2 uv){
int wrapped_u = (uv.x % X + X) % X;
int wrapped_v = (uv.y % Y + Y) % Y;
return ivec2(wrapped_u, wrapped_v);
}
int alive(ivec2 uv){
uv = wrapuv(uv);
vec4 px = texelFetch(srcTex,uv,0);
return int(px.r > 0.5);
}
void main() {
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
vec4 c = texelFetch(srcTex,uv,0);
int newState = alive(uv-ivec2(1,1));
imageStore(destTex, uv, vec4(newState, newState, newState, 1.0));
}
)glsl";
const char *vertexShaderSrc = R"glsl(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
TexCoord = aTexCoord;
}
)glsl";
const char *fragmentShaderSrc = R"glsl(
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D tex0;
void main()
{
FragColor = texture(tex0, TexCoord);
}
)glsl";
float quadVertices[] = {
1.0f, 1.0f, 0.0f, /*top R*/
1.0f, -1.0f, 0.0f, /*bottom R*/
-1.0f, -1.0f, 0.0f, /*bottom L*/
-1.0f, 1.0f, 0.0f /*top R*/
};
unsigned int quadIndices[] = {
0, 1, 3, /*tl triangle*/
1, 2, 3 /*br triangle*/
};