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 <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 GRID_SIZE X*Y
|
|
||||||
|
|
||||||
#define STR_EXPAND(tok) #tok
|
#define X 10
|
||||||
#define STR(tok) STR_EXPAND(tok)
|
#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() {
|
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
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