#include #include #define GL_GLEXT_PROTOTYPES #include #include #include int window = 0; GLuint vbo; GLint proj_uniform, tex_uniform, pixelsize_uniform, search_rect_uniform, barrier_uniform; GLuint texture; int width, height; GLuint program; GdkPixbuf *pixbuf; int x1, y1; int mwidth, mheight; static int init_shaders() { GLuint v, f; GError *error; gsize length; gchar *p; char msg[512]; GLfloat vertices[4 * 5]; GLint status; g_file_get_contents("wimmel.vert", &p, &length, &error); v = glCreateShader(GL_VERTEX_SHADER); glShaderSource(v, 1, (const GLchar **) &p, NULL); glCompileShader(v); glGetShaderiv(v, GL_COMPILE_STATUS, &status); g_free(p); if (!status) { glGetShaderInfoLog(v, sizeof msg, NULL, msg); fprintf(stderr, "vertex shader info: %s\n", msg); return -1; } g_file_get_contents("wimmel.frag", &p, &length, &error); f = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(f, 1, (const GLchar **) &p, NULL); glCompileShader(f); glGetShaderiv(f, GL_COMPILE_STATUS, &status); g_free(p); if (!status) { glGetShaderInfoLog(f, sizeof msg, NULL, msg); fprintf(stderr, "fragment shader info: %s\n", msg); return -1; } program = glCreateProgram(); glAttachShader(program, v); glAttachShader(program, f); glBindAttribLocation(program, 0, "position"); glBindAttribLocation(program, 1, "texcoord"); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); if (!status) { glGetProgramInfoLog(program, sizeof msg, NULL, msg); fprintf(stderr, "link info: %s\n", msg); return -1; } glUseProgram(program); proj_uniform = glGetUniformLocation(program, "proj"); tex_uniform = glGetUniformLocation(program, "tex"); pixelsize_uniform = glGetUniformLocation(program, "pixelsize"); search_rect_uniform = glGetUniformLocation(program, "search_rect"); barrier_uniform = glGetUniformLocation(program, "barrier"); vertices[ 0] = 0.0; vertices[ 1] = 0.0; vertices[ 2] = 0.0; vertices[ 3] = 0.0; vertices[ 4] = 0.0; vertices[ 5] = 0.0; vertices[ 6] = 1.0; vertices[ 7] = 0.0; vertices[ 8] = 0.0; vertices[ 9] = 1.0; vertices[10] = 1.0; vertices[11] = 0.0; vertices[12] = 0.0; vertices[13] = 1.0; vertices[14] = 0.0; vertices[15] = 1.0; vertices[16] = 1.0; vertices[17] = 0.0; vertices[18] = 1.0; vertices[19] = 1.0; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW); return 0; } static void keypress(unsigned char key, int x, int y) { switch (key) { case 27: glutDestroyWindow(window); exit(0); break; } } static void resize(int w, int h) { glViewport(0, 0, w, h); } static void create_texture(GdkPixbuf *pixbuf) { void *data; GLenum format; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); data = gdk_pixbuf_get_pixels(pixbuf); if (gdk_pixbuf_get_has_alpha(pixbuf)) format = GL_RGBA; else format = GL_RGB; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, data); } static void draw(void) { float pixelsize[] = { 1.0 / width, 1.0 / height }; static GLfloat proj[16] = { 2., 0., 0., 0., 0., -2., 0., 0., 0., 0., 1., 0., -1., 1., 0., 1. }; float search[4]; int barrier = mwidth * mheight / 2; static int frames = 0; static int last_time = 0; int elapsed = glutGet(GLUT_ELAPSED_TIME); ++frames; if ((elapsed - last_time) >= 5000) { printf("fps: %d\n", frames / 5); last_time = elapsed; frames = 0; } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUniformMatrix4fv(proj_uniform, 1, GL_FALSE, proj); glUniform1i(tex_uniform, 0); glUniform2fv(pixelsize_uniform, 1, pixelsize); search[0] = 1.0 * x1 / width; search[1] = 1.0 * y1 / height; search[2] = 1.0 * mwidth / width; search[3] = 1.0 * mheight / height; glUniform4fv(search_rect_uniform, 1, search); glUniform1i(barrier_uniform, barrier); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, texture); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), NULL); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (GLfloat *)0 + 3); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glutSwapBuffers(); printf("finished\n"); } int main(int argc, char **argv) { g_type_init(); glutInit(&argc, argv); if (argc <= 1) return 1; glutInitDisplayMode(GLUT_RGBA /*| GLUT_DEPTH */ | GLUT_DOUBLE); glClearColor(0.5f, 0.5f, 0.5f, 1.0f); pixbuf = gdk_pixbuf_new_from_file(argv[1], NULL); if (!pixbuf) return 1; width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); x1 = atoi(argv[2]); y1 = atoi(argv[3]); mwidth = atoi(argv[4]); mheight = atoi(argv[5]); glutInitWindowSize(width, height); window = glutCreateWindow("wimmel"); glutDisplayFunc(draw); glutKeyboardFunc(keypress); glutReshapeFunc(resize); init_shaders(); create_texture(pixbuf); glViewport(0,0,width,height); glutMainLoop(); return 0; }