#include #include #include #include #include #include #include #include extern char _binary_vertex_glsl_start[]; extern char _binary_vertex_glsl_end[]; extern char _binary_fragment_glsl_start[]; extern char _binary_fragment_glsl_end[]; void error_callback (int error, const char * description) { fprintf(stderr, "error_callback: %s, error == %d\n", description, error); } void key_callback (GLFWwindow * okno, int tipka, int koda, int dejanje, int modifikatorji) { fprintf(stderr, "tipka %d, koda %d, dejanje %d, modifikatorji %d, okno %p\n", tipka, koda, dejanje, modifikatorji, (void *) okno); } int main (void) { GLint vertex_len = _binary_vertex_glsl_end - _binary_vertex_glsl_start; GLint fragment_len = _binary_fragment_glsl_end - _binary_fragment_glsl_start; if (!glfwInit()) { fprintf(stderr, "glfwInit failed\n"); return 1; } glfwSetErrorCallback(error_callback); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // forward compat is ogl 3.0+ GLFWwindow * okno = glfwCreateWindow(800, 600, "okno", NULL, NULL); if (!okno) { fprintf(stderr, "glfwCreateWindow failed\n"); glfwTerminate(); return 2; } glfwMakeContextCurrent(okno); GLenum err = glewInit(); if (err != GLEW_OK) { fprintf(stderr, "glewInit failed: %s\n", glewGetErrorString(err)); return 3; } glfwSwapInterval(1); // vsync glfwSetKeyCallback(okno, key_callback); GLuint program = glCreateProgram(); float points[] = { -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f }; // GLuint points_vbo, vao; glGenBuffers(1, &points_vbo); glBindBuffer(GL_ARRAY_BUFFER, points_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof points, points, GL_STATIC_DRAW); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, points_vbo); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); // const char * vertex = _binary_vertex_glsl_start; const char * fragment = _binary_fragment_glsl_start; #define DO_SHADER(whi, WHI) \ GLuint whi##_shader = glCreateShader(GL_##WHI##_SHADER); \ glShaderSource(whi##_shader, 1, &whi, &whi##_len); \ glCompileShader(whi##_shader); \ GLint whi##_success = 0; \ glGetShaderiv(whi##_shader, GL_COMPILE_STATUS, &whi##_success); \ if (whi##_success == GL_FALSE) { \ GLint logSize = 0; \ glGetShaderiv(whi##_shader, GL_INFO_LOG_LENGTH, &logSize); \ char infoLog[logSize]; \ glGetShaderInfoLog(whi##_shader, logSize, &logSize, infoLog); \ fprintf(stderr, "prevod shaderja ni uspel. dnevnik:\n%s\n", infoLog); \ glDeleteShader(whi##_shader); \ return 4; \ } \ glAttachShader(program, whi##_shader); DO_SHADER(vertex, VERTEX); DO_SHADER(fragment, FRAGMENT); // glBindAttribLocation(program, 0, "vertex_position"); // glLinkProgram(program); GLint isLinked = 0; glGetProgramiv(program, GL_LINK_STATUS, &isLinked); if (isLinked == GL_FALSE) { GLint logSize = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize); char infoLog[logSize]; glGetProgramInfoLog(program, logSize, &logSize, infoLog); fprintf(stderr, "linkanje programa ni uspelo. dnevnik:\n%s\n", infoLog); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(program); return 5; } // glDetachShader(program, vertex_shader); // glDetachShader(program, fragment_shader); // glDeleteShader(fragment_shader); // testiraj, mogoče se to sme // glDeleteShader(vertex_shader); GLuint timeI = glGetUniformLocation(program, "time"); GLuint optI = glGetUniformLocation(program, "OPTIONS"); uint32_t opts = 123456; glClearColor(0.1, 0.2, 0.3, 1); unsigned frame = 0; getchar(); // da vmes odpremo okno v floating načinu s pravilno velikostjo while (!glfwWindowShouldClose(okno)) { int w, h; glfwGetFramebufferSize(okno, &w, &h); glViewport(0, 0, w, h); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(program); // testiraj, mogoče se to sme dat iz loopa gor glUniform1f(timeI, (float) frame/60); glUniform1i(optI, opts++); glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, 6 /* dva triangla po 3 */); glfwSwapBuffers(okno); glfwPollEvents(); // wait / poll frame++; char fn[25]; sprintf(fn, "animacija%04d.ppm", frame); int fd; if ((fd = open(fn, O_CREAT | O_RDWR, 00664)) == -1) { perror("open"); abort(); } if (ftruncate(fd, 128+w*h*3) == -1) { perror("ftruncate"); abort(); } void * p; if ((p = mmap(NULL, 128+w*h*3, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { perror("mmap"); abort(); } sprintf(p, "P6\n\n%57d\n%57d\n255\n", w, h); glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *) p + 128); if (munmap(p, 128+w*h*3) == -1) { perror("munmap"); abort(); } if (close(fd) == -1) { perror("close"); abort(); } } glfwDestroyWindow(okno); glfwTerminate(); return 0; }