summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile17
-rw-r--r--main.c261
3 files changed, 280 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5e55c3f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+compute-test
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..cb1ae8e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+CFLAGS=-std=c11 -W -Wall -pedantic -O2
+APP=compute-test
+LIBS=-lglfw -lGLEW -lGL
+OBJS=main.o
+
+.PHONY=all clean test
+
+all: $(APP)
+
+$(APP): $(OBJS)
+ $(CC) -o $(APP) $(OBJS) $(LIBS)
+
+clean:
+ $(RM) $(OBJS) $(APP)
+
+test: $(APP)
+ ./$(APP)
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..22266db
--- /dev/null
+++ b/main.c
@@ -0,0 +1,261 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+#define UNUSED(a) ((void) (a))
+
+static const float
+verts[] = {
+ -0.5, 0.5, 0,
+ 0.5, 0.5, 0,
+ 0.0, -0.5, 0,
+};
+
+static const char *
+vs_src =
+ "#version 320 es\n"
+ "\n"
+ "layout (location = 0) in mediump vec3 pos;\n"
+ "\n"
+ "void main() {\n"
+ " gl_Position = vec4(pos.x, pos.y, pos.z, 1);\n"
+ "}\n";
+
+static const char *
+fs_src =
+ "#version 320 es\n"
+ "\n"
+ "out mediump vec4 color;\n"
+ "\n"
+ "uniform mediump float time;\n"
+ "\n"
+ "void main() {\n"
+ " color = vec4(0.5f + 0.5 * sin(time * 3.141), 0, 0, 1);\n"
+ "}\n";
+
+static void
+error_cb(
+ const int code,
+ const char *text
+) {
+ UNUSED(code);
+ fprintf(stderr, "GLFW Error: %s\n", text);
+}
+
+static void
+key_cb(
+ GLFWwindow *win,
+ int key,
+ int code,
+ int action,
+ int mods
+) {
+ UNUSED(code);
+ UNUSED(mods);
+
+ if (action == GLFW_RELEASE && key == GLFW_KEY_ESCAPE)
+ glfwSetWindowShouldClose(win, GLFW_TRUE);
+}
+
+static void
+framebuffer_size_cb(
+ GLFWwindow *win,
+ const int width,
+ const int height
+) {
+ UNUSED(win);
+
+ fprintf(stderr, "width = %d, height = %d\n", width, height);
+ glViewport(0, 0, width, height);
+}
+
+static void drop_cb(
+ GLFWwindow *win,
+ const int num_paths,
+ const char ** paths
+) {
+ UNUSED(win);
+
+ for (int i = 0; i < num_paths; i++) {
+ fprintf(stderr, "drop path: %s\n", paths[i]);
+ }
+}
+
+static GLuint
+compile_shader(
+ const GLenum type,
+ const char *src
+) {
+ // create shader
+ GLuint r = glCreateShader(type);
+
+ // compile shader
+ glShaderSource(r, 1, &src, NULL);
+ glCompileShader(r);
+
+ // check for error
+ GLint ok;
+ glGetShaderiv(r, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ GLchar log[1024];
+ glGetShaderInfoLog(r, sizeof(log), NULL, log);
+ fprintf(stderr, "Shader Compile Error: %s\n", log);
+ exit(EXIT_FAILURE);
+ }
+
+ // return result
+ return r;
+}
+
+static GLuint
+link_render_program(
+ const char * const vs_src,
+ const char * const fs_src
+) {
+ // create program
+ GLuint r = glCreateProgram();
+
+ // compile shaders
+ GLuint vs = compile_shader(GL_VERTEX_SHADER, vs_src),
+ fs = compile_shader(GL_FRAGMENT_SHADER, fs_src);
+
+ // attach shaders
+ glAttachShader(r, vs);
+ glAttachShader(r, fs);
+
+ // link program
+ glLinkProgram(r);
+
+ // check link status
+ GLint ok;
+ glGetProgramiv(r, GL_LINK_STATUS, &ok);
+ if (!ok) {
+ GLchar log[1024];
+ glGetProgramInfoLog(r, sizeof(log), NULL, log);
+ fprintf(stderr, "Program Link Error: %s\n", log);
+ exit(EXIT_FAILURE);
+ }
+
+ // delete shaders
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ // return result
+ return r;
+}
+
+#if 0
+static GLuint
+link_compute_program(
+ const char * const cs_src
+) {
+ // create program
+ GLuint r = glCreateProgram();
+
+}
+#endif
+
+static GLFWwindow *
+init(void) {
+ // init glfw
+ glfwSetErrorCallback(error_cb);
+ if (!glfwInit())
+ exit(EXIT_FAILURE);
+
+ // set api to GLES 3.2
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+
+ // create window
+ GLFWwindow *win = glfwCreateWindow(640, 480, "Compute Test", NULL, NULL);
+ if (!win) {
+ exit(EXIT_FAILURE);
+ }
+
+ // set gl context
+ glfwMakeContextCurrent(win);
+
+ // init glew
+ // (do this immediately after setting context)
+ GLenum err = glewInit();
+ if (err != GLEW_OK) {
+ fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
+ exit(EXIT_FAILURE);
+ }
+
+ // set swap interval
+ // (after context init)
+ glfwSwapInterval(1);
+
+ // bind event handlers
+ // (after context init)
+ glfwSetKeyCallback(win, key_cb);
+ glfwSetFramebufferSizeCallback(win, framebuffer_size_cb);
+ glfwSetDropCallback(win, drop_cb);
+
+ // return window
+ return win;
+}
+
+int main(int argc, char *argv[]) {
+ UNUSED(argc);
+ UNUSED(argv);
+
+ GLFWwindow *win = init();
+
+ // generate vertex array
+ GLuint vao;
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ // generate vertex buffer
+ GLuint vbo;
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*) 0);
+ glEnableVertexAttribArray(0);
+
+ // unbind vao
+ glBindVertexArray(0);
+
+ // link program
+ GLuint prog = link_render_program(vs_src, fs_src);
+ GLint u_time = glGetUniformLocation(prog, "time");
+
+ // main loop
+ while (!glfwWindowShouldClose(win)) {
+ // clear screen
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // use program, set uniform
+ glUseProgram(prog);
+ glUniform1f(u_time, glfwGetTime());
+
+ // draw
+ glBindVertexArray(vao);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ glBindVertexArray(0);
+
+ // swap buffer
+ glfwSwapBuffers(win);
+
+ // handle events
+ glfwPollEvents();
+ // glfwWaitEvents();
+ }
+
+ // destroy window
+ glfwDestroyWindow(win);
+
+ // fini glfw
+ glfwTerminate();
+
+ // return success
+ return EXIT_SUCCESS;
+}