mirror of
https://git.lynn.is/Gwen/pretty-automata.git
synced 2024-05-18 15:21:07 +02:00
182 lines
5.5 KiB
C++
182 lines
5.5 KiB
C++
#include <cstdio>
|
|
|
|
#include <GL/glew.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <vector>
|
|
|
|
GLuint loadShader(const char *source, GLenum shader_type) {
|
|
GLuint shaderId = glCreateShader(shader_type);
|
|
GLint result = GL_FALSE;
|
|
int infoLogLength;
|
|
// Compile Vertex Shader
|
|
glShaderSource(shaderId, 1, &source, nullptr);
|
|
glCompileShader(shaderId);
|
|
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result);
|
|
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLogLength);
|
|
if (infoLogLength > 0) {
|
|
std::vector<char> VertexShaderErrorMessage(infoLogLength + 1);
|
|
glGetShaderInfoLog(shaderId, infoLogLength, nullptr,
|
|
&VertexShaderErrorMessage[0]);
|
|
printf("%s\n", &VertexShaderErrorMessage[0]);
|
|
exit(-1);
|
|
}
|
|
return shaderId;
|
|
}
|
|
|
|
GLuint loadProgram(const std::vector<GLuint> &shaders) {
|
|
GLuint programId = glCreateProgram();
|
|
for (const auto &item : shaders) {
|
|
glAttachShader(programId, item);
|
|
}
|
|
glLinkProgram(programId);
|
|
|
|
GLint result = GL_FALSE;
|
|
int infoLogLength;
|
|
|
|
glGetProgramiv(programId, GL_LINK_STATUS, &result);
|
|
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLength);
|
|
if (infoLogLength > 0) {
|
|
std::vector<char> ProgramErrorMessage(infoLogLength + 1);
|
|
glGetProgramInfoLog(programId, infoLogLength, nullptr,
|
|
&ProgramErrorMessage[0]);
|
|
printf("%s\n", &ProgramErrorMessage[0]);
|
|
}
|
|
return programId;
|
|
}
|
|
|
|
static const char *vertex_shader =
|
|
"#version 460\n"
|
|
"layout(location = 0) in vec3 vertexPosition_modelspace;\n"
|
|
"out vec2 coord;\n"
|
|
"void main(){\n"
|
|
" gl_Position.xyz = vertexPosition_modelspace;\n"
|
|
" gl_Position.w = 1.0;\n"
|
|
" coord.xy = vertexPosition_modelspace.xy;\n"
|
|
"}";
|
|
|
|
static const char *fragment_shader =
|
|
"#version 460\n"
|
|
"out vec3 color;\n"
|
|
"in vec2 coord;\n"
|
|
"layout (std430, binding = 2) restrict readonly buffer shader_data\n"
|
|
"{\n"
|
|
" int c[];\n"
|
|
"};\n"
|
|
|
|
"void main(){\n"
|
|
" int x = int(255. * (coord.x + 1.) / 2.);"
|
|
" color = vec3(c[x]/255., 0.5,0.5);\n"
|
|
"}";
|
|
|
|
static const char *compute_shader =
|
|
"#version 460\n"
|
|
"layout(local_size_x = 1, local_size_y = 1) in;\n"
|
|
"layout (std430, binding = 2) restrict buffer shader_data\n"
|
|
"{\n"
|
|
" int c[];\n"
|
|
"};\n"
|
|
"void main(){\n"
|
|
" c[gl_GlobalInvocationID.x] = (c[gl_GlobalInvocationID.x] + 1) % 256;\n"
|
|
"}\n";
|
|
|
|
int main() {
|
|
glewExperimental = true;
|
|
if (!glfwInit()) {
|
|
fprintf(stderr, "Failed to initialize GLFW\n");
|
|
return -1;
|
|
}
|
|
|
|
glfwWindowHint(GLFW_SAMPLES, 0);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
|
|
GLFWwindow *window =
|
|
glfwCreateWindow(1024, 768, "Tutorial 01", nullptr, nullptr);
|
|
if (window == nullptr) {
|
|
fprintf(stderr,
|
|
"Failed to open GLFW window. If you have an Intel GPU, they are "
|
|
"not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
|
|
glfwTerminate();
|
|
return -1;
|
|
}
|
|
glfwMakeContextCurrent(window); // Initialize GLEW
|
|
glewExperimental = true; // Needed in core profile
|
|
if (glewInit() != GLEW_OK) {
|
|
fprintf(stderr, "Failed to initialize GLEW\n");
|
|
return -1;
|
|
}
|
|
|
|
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
|
|
|
|
GLuint VertexArrayID;
|
|
glGenVertexArrays(1, &VertexArrayID);
|
|
glBindVertexArray(VertexArrayID);
|
|
const GLfloat g_vertex_buffer_data[] = {
|
|
-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
|
};
|
|
GLuint vertexbuffer;
|
|
glGenBuffers(1, &vertexbuffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),
|
|
g_vertex_buffer_data, GL_STATIC_DRAW);
|
|
|
|
GLuint programId = loadProgram({
|
|
loadShader(vertex_shader, GL_VERTEX_SHADER),
|
|
loadShader(fragment_shader, GL_FRAGMENT_SHADER),
|
|
});
|
|
|
|
GLuint computeProgramId = loadProgram({
|
|
loadShader(compute_shader, GL_COMPUTE_SHADER),
|
|
});
|
|
|
|
int c[256];
|
|
|
|
for (size_t i = 0; i < 256; ++i) {
|
|
c[i] = i;
|
|
}
|
|
|
|
GLuint ssbo = 0;
|
|
glGenBuffers(1, &ssbo);
|
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
|
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * 256, &c,
|
|
GL_DYNAMIC_COPY);
|
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
|
|
unsigned int block_index = glGetProgramResourceIndex(
|
|
programId, GL_SHADER_STORAGE_BLOCK, "shader_data");
|
|
GLuint ssbo_binding_point_index = 2;
|
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, ssbo_binding_point_index, ssbo);
|
|
glShaderStorageBlockBinding(programId, block_index, ssbo_binding_point_index);
|
|
|
|
glUseProgram(computeProgramId);
|
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, ssbo_binding_point_index, ssbo);
|
|
unsigned int compute_block_index = glGetProgramResourceIndex(
|
|
programId, GL_SHADER_STORAGE_BLOCK, "shader_data");
|
|
glShaderStorageBlockBinding(computeProgramId, compute_block_index,
|
|
ssbo_binding_point_index);
|
|
|
|
do {
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glUseProgram(computeProgramId);
|
|
glDispatchCompute(255, 1, 1);
|
|
|
|
glUseProgram(programId);
|
|
|
|
glEnableVertexAttribArray(0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
|
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
|
glDisableVertexAttribArray(0);
|
|
|
|
glfwSwapBuffers(window);
|
|
glfwPollEvents();
|
|
|
|
} // Check if the ESC key was pressed or the window was closed
|
|
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
|
|
glfwWindowShouldClose(window) == 0);
|
|
} |