summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..146d10b
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,211 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/glew.h>
+#include <GL/gl.h>
+#include <GLFW/glfw3.h>
+
+static void opengl_error(GLenum err, const char *file, int line)
+{
+ switch (err) {
+ case GL_INVALID_ENUM: fprintf(stderr, "[warning] OpenGL error: INVALID_ENUM %s:%d\n", file, line); break;
+ case GL_INVALID_VALUE: fprintf(stderr, "[warning] OpenGL error: INVALID_VALUE %s:%d\n", file, line); break;
+ case GL_INVALID_OPERATION: fprintf(stderr, "[warning] OpenGL error: INVALID_OPERATION %s:%d\n", file, line); break;
+ case GL_STACK_OVERFLOW: fprintf(stderr, "[warning] OpenGL error: STACK_OVERFLOW %s:%d\n", file, line); break;
+ case GL_STACK_UNDERFLOW: fprintf(stderr, "[warning] OpenGL error: STACK_UNDERFLOW %s:%d\n", file, line); break;
+ case GL_OUT_OF_MEMORY: fprintf(stderr, "[warning] OpenGL error: OUT_OF_MEMORY %s:%d\n", file, line); break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION: fprintf(stderr, "[warning] OpenGL error: INVALID_FRAMEBUFFER_OPERATION %s:%d\n", file, line); break;
+ default: break;
+ }
+}
+void opengl_debug(const char *file, int line)
+{
+ GLenum err = glGetError();
+
+ if (err != GL_NO_ERROR)
+ opengl_error(err, file, line);
+}
+
+struct shader {
+ const char *name;
+ GLenum type;
+ const char *src;
+ size_t len;
+};
+
+static void framebuffer_size_callback(GLFWwindow *handle, int width, int height)
+{
+ (void) handle;
+ glViewport(0, 0, width, height);
+}
+
+GLuint shader_program_create(const char *name, struct shader *shaders, size_t num_shaders)
+{
+ GLuint prog_id = glCreateProgram();
+ GLuint shader_ids[num_shaders];
+
+ for (size_t i = 0; i < num_shaders; i++) {
+ GLint len = shaders[i].len;
+
+ shader_ids[i] = glCreateShader(shaders[i].type);
+ glShaderSource(shader_ids[i], 1, &shaders[i].src, &len);
+ glCompileShader(shader_ids[i]);
+
+ GLint compile_success;
+ glGetShaderiv(shader_ids[i], GL_COMPILE_STATUS, &compile_success);
+
+ if (!compile_success) {
+ char error[BUFSIZ];
+ glGetShaderInfoLog(shader_ids[i], BUFSIZ, NULL, error);
+ fprintf(stderr, "[error] failed to compile %s shader: %s", shaders[i].name, error);
+ exit(EXIT_FAILURE);
+ }
+
+ glAttachShader(prog_id, shader_ids[i]);
+ }
+
+ glLinkProgram(prog_id);
+
+ for (size_t i = 0; i < num_shaders; i++)
+ glDeleteShader(shader_ids[i]);
+
+ GLint link_success;
+ glGetProgramiv(prog_id, GL_LINK_STATUS, &link_success);
+ if (!link_success) {
+ char error[BUFSIZ];
+ glGetProgramInfoLog(prog_id, BUFSIZ, NULL, error);
+ fprintf(stderr, "[error] failed to link %s shader program: %s\n", name, error);
+ exit(EXIT_FAILURE);
+ }
+
+ return prog_id;
+}
+
+#define GL_DEBUG opengl_debug(__FILE__, __LINE__);
+
+int main()
+{
+ if (!glfwInit()) {
+ fprintf(stderr, "[error] failed to initialize GLFW\n");
+ exit(EXIT_FAILURE);
+ }
+
+ atexit(glfwTerminate);
+
+ // glfwWindowHint(GLFW_SAMPLES, 8);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+
+ int win_w = 900;
+ int win_h = 900;
+
+ GLFWwindow *window = glfwCreateWindow(win_w, win_h, "Juxtapos", NULL, NULL);
+ if (window == NULL) {
+ fprintf(stderr, "[error] failed to create window\n");
+ exit(EXIT_FAILURE);
+ }
+
+ glfwMakeContextCurrent(window);
+
+ if (glewInit() != GLEW_OK) {
+ fprintf(stderr, "[error] failed to initialize GLEW\n");
+ exit(EXIT_FAILURE);
+ }
+
+ glViewport(0, 0, win_w, win_h);
+ glfwSetFramebufferSizeCallback(window, &framebuffer_size_callback);
+
+ // dimensions of the image
+ int tex_w = 512, tex_h = 512;
+ GLuint wood_texture;
+ glGenTextures(1, &wood_texture);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, wood_texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_w, tex_h, 0, GL_RGBA, GL_FLOAT, NULL);
+ glBindImageTexture(0, wood_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
+
+ /*
+ int work_grp_cnt[3];
+ glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &work_grp_cnt[0]);
+ glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &work_grp_cnt[1]);
+ glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &work_grp_cnt[2]);
+ printf("max global (total) work group counts x:%i y:%i z:%i\n",
+ work_grp_cnt[0], work_grp_cnt[1], work_grp_cnt[2]);
+
+ int work_grp_inv;
+ glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &work_grp_inv);
+ printf("max local work group invocations %i\n", work_grp_inv); */
+
+ const char wood_shader_src[] = {
+#include "wood.glsl.h"
+ };
+
+ GLuint wood_shader = shader_program_create("wood", (struct shader []) {
+ { "wood", GL_COMPUTE_SHADER, wood_shader_src, sizeof wood_shader_src },
+ }, 1);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, wood_texture);
+ glUseProgram(wood_shader);
+ glDispatchCompute(tex_w, tex_h, 1);
+
+ const char fragment_shader_src[] = {
+#include "fragment.glsl.h"
+ };
+ const char vertex_shader_src[] = {
+#include "vertex.glsl.h"
+ };
+
+ GLuint main_shader = shader_program_create("main", (struct shader []) {
+ { "vertex", GL_VERTEX_SHADER, vertex_shader_src, sizeof vertex_shader_src },
+ { "fragment", GL_FRAGMENT_SHADER, fragment_shader_src, sizeof fragment_shader_src },
+ }, 2);
+
+ GLfloat quad[4][2] = {
+ { -0.5, +0.5 },
+ { -0.5, -0.5 },
+ { +0.5, +0.5 },
+ { +0.5, -0.5 },
+ };
+
+ GLuint vao, vbo;
+ glGenVertexArrays(1, &vao);
+ glGenBuffers(1, &vbo);
+
+ glBindVertexArray(vao);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof quad, quad, GL_STATIC_DRAW);
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof *quad, 0);
+ glEnableVertexAttribArray(0);
+
+ unsigned int skyblue = 0x87ceeb;
+ glClearColor(
+ ((skyblue >> 16) & 0xff) / 255.0,
+ ((skyblue >> 8) & 0xff) / 255.0,
+ ((skyblue >> 0) & 0xff) / 255.0, 1.0);
+
+ glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
+ while (!glfwWindowShouldClose(window)) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // preview wood texture
+ glUseProgram(main_shader);
+ glBindVertexArray(vao);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, wood_texture);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glfwSwapBuffers(window);
+ glfwPollEvents();
+ }
+
+ glDeleteProgram(wood_shader);
+}