Basic compute shader
This commit is contained in:
parent
5c61995d1c
commit
152277cd77
127
main.cc
127
main.cc
@ -1,12 +1,46 @@
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#define X 16
|
||||
#define Y 16
|
||||
#define GRID_SIZE X*Y
|
||||
#include "shaders.hpp"
|
||||
|
||||
#define STR_EXPAND(tok) #tok
|
||||
#define STR(tok) STR_EXPAND(tok)
|
||||
#define X 10
|
||||
#define Y 10
|
||||
#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;
|
||||
}
|
||||
|
||||
int main() {
|
||||
if (!glfwInit())
|
||||
@ -16,7 +50,7 @@ int main() {
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
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)
|
||||
return -2;
|
||||
|
||||
@ -26,12 +60,91 @@ int main() {
|
||||
return -3;
|
||||
|
||||
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)) {
|
||||
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);
|
||||
|
||||
glfwSwapBuffers(w);
|
||||
std::swap(ri, wi);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
|
||||
68
shaders.hpp
Normal file
68
shaders.hpp
Normal 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*/
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user