Browse Source

Ready. Set. Go!

rexim 4 years ago
commit
63167ff3eb
7 changed files with 284 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 20 0
      LICENSE
  3. 6 0
      Makefile
  4. 3 0
      README.md
  5. 235 0
      main.c
  6. 7 0
      main.frag
  7. 12 0
      main.vert

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+main

+ 20 - 0
LICENSE

@@ -0,0 +1,20 @@
+Copyright 2021 Alexey Kutepov <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 6 - 0
Makefile

@@ -0,0 +1,6 @@
+GL_PKGS=glfw3 glew
+CFLAGS=-Wall -Wextra
+
+main: main.c
+	$(CC) $(CFLAGS) `pkg-config --cflags $(GL_PKGS)` -o main main.c `pkg-config --libs $(GL_PKGS)`
+

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# OpenGL Template
+
+Just a simple OpenGL template that I use on my streams.

+ 235 - 0
main.c

@@ -0,0 +1,235 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+
+#define GL_GLEXT_PROTOTYPES
+#include <GLFW/glfw3.h>
+
+#define SCREEN_WIDTH 1024
+#define SCREEN_HEIGHT 768
+
+void panic_errno(const char *fmt, ...)
+{
+    fprintf(stderr, "ERROR: ");
+
+    va_list args;
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+
+    fprintf(stderr, ": %s\n", strerror(errno));
+
+    exit(1);
+}
+
+char *slurp_file(const char *file_path)
+{
+#define SLURP_FILE_PANIC panic_errno("Could not read file `%s`", file_path)
+    FILE *f = fopen(file_path, "r");
+    if (f == NULL) SLURP_FILE_PANIC;
+    if (fseek(f, 0, SEEK_END) < 0) SLURP_FILE_PANIC;
+
+    long size = ftell(f);
+    if (size < 0) SLURP_FILE_PANIC;
+
+    char *buffer = malloc(size + 1);
+    if (buffer == NULL) SLURP_FILE_PANIC;
+
+    if (fseek(f, 0, SEEK_SET) < 0) SLURP_FILE_PANIC;
+
+    fread(buffer, 1, size, f);
+    if (ferror(f) < 0) SLURP_FILE_PANIC;
+
+    buffer[size] = '\0';
+
+    if (fclose(f) < 0) SLURP_FILE_PANIC;
+
+    return buffer;
+#undef SLURP_FILE_PANIC
+}
+
+bool compile_shader_source(const GLchar *source, GLenum shader_type, GLuint *shader)
+{
+    *shader = glCreateShader(shader_type);
+    glShaderSource(*shader, 1, &source, NULL);
+    glCompileShader(*shader);
+
+    GLint compiled = 0;
+    glGetShaderiv(*shader, GL_COMPILE_STATUS, &compiled);
+
+    if (!compiled) {
+        GLchar message[1024];
+        GLsizei message_size = 0;
+        glGetShaderInfoLog(*shader, sizeof(message), &message_size, message);
+        fprintf(stderr, "%.*s\n", message_size, message);
+        return false;
+    }
+
+    return true;
+}
+
+bool compile_shader_file(const char *file_path, GLenum shader_type, GLuint *shader)
+{
+    char *source = slurp_file(file_path);
+    bool err = compile_shader_source(source, shader_type, shader);
+    free(source);
+    return err;
+}
+
+bool link_program(GLuint vert_shader, GLuint frag_shader, GLuint *program)
+{
+    *program = glCreateProgram();
+
+    glAttachShader(*program, vert_shader);
+    glAttachShader(*program, frag_shader);
+    glLinkProgram(*program);
+
+    GLint linked = 0;
+    glGetProgramiv(*program, GL_LINK_STATUS, &linked);
+    if (!linked) {
+        GLsizei message_size = 0;
+        GLchar message[1024];
+
+        glGetProgramInfoLog(*program, sizeof(message), &message_size, message);
+        fprintf(stderr, "Program Linking: %.*s\n", message_size, message);
+    }
+
+    glDeleteShader(vert_shader);
+    glDeleteShader(frag_shader);
+
+    return program;
+}
+
+GLuint program = 0;
+GLuint failed_program = 0;
+
+const char *failed_vert_source =
+    "#version 130\n"
+    "\n"
+    "void main(void)\n"
+    "{\n"
+    "    int gray = gl_VertexID ^ (gl_VertexID >> 1);\n"
+    "\n"
+    "    gl_Position = vec4(\n"
+    "        2 * (gray / 2) - 1,\n"
+    "        2 * (gray % 2) - 1,\n"
+    "        0.0,\n"
+    "        1.0);\n"
+    "};\n";
+
+const char *failed_frag_source =
+    "#version 130\n"
+    "\n"
+    "out vec4 color;\n"
+    "\n"
+    "void main(void) {\n"
+    "    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+    "};\n";
+
+
+void init_failed_program(void)
+{
+    GLuint vert = 0;
+    if (!compile_shader_source(failed_vert_source, GL_VERTEX_SHADER, &vert)) {
+        exit(1);
+    }
+
+    GLuint frag = 0;
+    if (!compile_shader_source(failed_frag_source, GL_FRAGMENT_SHADER, &frag)) {
+        exit(1);
+    }
+
+    if (!link_program(vert, frag, &failed_program)) {
+        exit(1);
+    }
+}
+
+void reload_shaders(void)
+{
+    glDeleteProgram(program);
+
+    GLuint vert = 0;
+    if (!compile_shader_file("./main.vert", GL_VERTEX_SHADER, &vert)) {
+        glUseProgram(failed_program);
+        return;
+    }
+
+    GLuint frag = 0;
+    if (!compile_shader_file("./main.frag", GL_FRAGMENT_SHADER, &frag)) {
+        glUseProgram(failed_program);
+        return;
+    }
+
+    if (!link_program(vert, frag, &program)) {
+        glUseProgram(failed_program);
+        return;
+    }
+
+    glUseProgram(program);
+
+    printf("Successfully Reload the Shaders\n");
+}
+
+void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+    (void) window;
+    (void) scancode;
+    (void) action;
+    (void) mods;
+
+    if (key == GLFW_KEY_F5 && action == GLFW_PRESS) {
+        reload_shaders();
+    }
+}
+
+void window_size_callback(GLFWwindow* window, int width, int height)
+{
+    (void) window;
+    glViewport(
+        width / 2 - SCREEN_WIDTH / 2,
+        height / 2 - SCREEN_HEIGHT / 2,
+        SCREEN_WIDTH,
+        SCREEN_HEIGHT);
+}
+
+int main()
+{
+    if (!glfwInit()) {
+        fprintf(stderr, "ERROR: could not initialize GLFW\n");
+        exit(1);
+    }
+
+    GLFWwindow * const window = glfwCreateWindow(
+                                    SCREEN_WIDTH,
+                                    SCREEN_HEIGHT,
+                                    "atomato",
+                                    NULL,
+                                    NULL);
+    if (window == NULL) {
+        fprintf(stderr, "ERROR: could not create a window.\n");
+        glfwTerminate();
+        exit(1);
+    }
+
+    glfwMakeContextCurrent(window);
+
+    init_failed_program();
+    reload_shaders();
+
+    glfwSetKeyCallback(window, key_callback);
+    glfwSetFramebufferSizeCallback(window, window_size_callback);
+
+    while (!glfwWindowShouldClose(window)) {
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        glDrawArrays(GL_QUADS, 0, 4);
+
+        glfwSwapBuffers(window);
+        glfwPollEvents();
+    }
+
+    return 0;
+}

+ 7 - 0
main.frag

@@ -0,0 +1,7 @@
+#version 130
+
+out vec4 color;
+
+void main(void) {
+    color = vec4(0.0, 1.0, 0.0, 1.0);
+};

+ 12 - 0
main.vert

@@ -0,0 +1,12 @@
+#version 130
+
+void main(void)
+{
+    int gray = gl_VertexID ^ (gl_VertexID >> 1);
+
+    gl_Position = vec4(
+        2 * (gray / 2) - 1,
+        2 * (gray % 2) - 1,
+        0.0,
+        1.0);
+};