#include #include #include #include #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; }