#include "shadermeh.h" static GLfloat vertex_buffer[] = { -1.0f, -1.0f, 0.0f, /* lower left corner */ 1.0f, 1.0f, 1.0f, +1.0f, -1.0f, 0.0f, /* lower right corner */ 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, /* uper left corner */ 1.0f, 1.0f, 1.0f, +1.0f, +1.0f, 0.0f, /* upper right corner */ 1.0f, 1.0f, 1.0f, }; static double diff_timespec(const struct timespec *time1, const struct timespec *time0) { return (time1->tv_sec - time0->tv_sec) + (time1->tv_nsec - time0->tv_nsec) / 1000000000.0; } static const struct option long_opts[] = { { "width", required_argument, NULL, 'w' }, { "height", required_argument, NULL, 'h' }, { "shader", required_argument, NULL, 's' }, { NULL, 0, NULL, 0 }, }; static const char *short_opts = "w:h:s:"; static const char *usage_str = "shadermeh OPTIONS...\n" "\n" "Possible options:\n" "\n" " --width, -w \n" " --height, -h \n" "\n" " --shader, -s \n" "\n"; int main(int argc, char **argv) { GLuint u_iResolution, u_iTime, u_iTimeDelta, u_iFrame; struct timespec start, frame_start, frame_end; unsigned int width, height, iFrame = 0; const char *shader_file = NULL; GLint major, minor, prog; float iTime, iTimeDelta; GLuint vao, vbo; window *wnd; int i; /******************** parse options ************************/ width = 800; height = 450; for (;;) { i = getopt_long(argc, argv, short_opts, long_opts, NULL); if (i == -1) break; switch (i) { case 'w': width = strtol(optarg, NULL, 10); break; case 'h': height = strtol(optarg, NULL, 10); break; case 's': shader_file = optarg; break; default: fputs(usage_str, stderr); return EXIT_FAILURE; } } if (!shader_file) { fputs(usage_str, stderr); fputs("No shader file specified!\n", stderr); return EXIT_FAILURE; } /********** create window and make context current **********/ wnd = window_create(width, height, "shader meh..."); if (!wnd) { fputs("failed to create window", stderr); return EXIT_FAILURE; } window_make_current(wnd); window_set_vsync(wnd, 1); /******************** load entry points ********************/ glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { fputs("glewInit() error", stderr); window_destroy(wnd); return EXIT_FAILURE; } glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); printf("OpenGL version %d.%d\n", major, minor); /******************** initialization ********************/ glViewport(0, 0, width, height); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); /* vertex buffer object & vertex array object */ glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer), vertex_buffer, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (GLvoid *)(3 * sizeof(GLfloat))); /* shader */ prog = shader_program_load(shader_file); if (!shader_program_get_build_status(prog)) { shader_program_print_info_log(prog); } glUseProgram(prog); /* uniforms */ u_iResolution = glGetUniformLocation(prog, "iResolution"); u_iTime = glGetUniformLocation(prog, "iTime"); u_iTimeDelta = glGetUniformLocation(prog, "iTimeDelta"); u_iFrame = glGetUniformLocation(prog, "iFrame;"); glUniform3f(u_iResolution, width, height, 0.0f); clock_gettime(CLOCK_MONOTONIC_RAW, &start); /******************** drawing loop ********************/ while (window_handle_events()) { clock_gettime(CLOCK_MONOTONIC_RAW, &frame_start); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); window_swap_buffers(wnd); clock_gettime(CLOCK_MONOTONIC_RAW, &frame_end); iFrame += 1; iTimeDelta = diff_timespec(&frame_end, &frame_start); iTime = diff_timespec(&frame_end, &start); glUniform1f(u_iTimeDelta, iTimeDelta); glUniform1f(u_iTime, iTime); glUniform1ui(u_iFrame, iFrame); } /******************** cleanup ********************/ glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(1, &vbo); glBindVertexArray(0); glDeleteVertexArrays(1, &vao); glDeleteProgram(prog); window_make_current(NULL); window_destroy(wnd); return EXIT_SUCCESS; }