diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 17 | ||||
-rw-r--r-- | main.c | 261 |
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) @@ -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; +} |