summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wimmel.frag27
-rw-r--r--wimmel.vert10
-rw-r--r--wimmel_gl.c243
3 files changed, 280 insertions, 0 deletions
diff --git a/wimmel.frag b/wimmel.frag
new file mode 100644
index 0000000..d4cb7ef
--- /dev/null
+++ b/wimmel.frag
@@ -0,0 +1,27 @@
+varying vec2 v_texcoord;
+uniform sampler2D tex;
+uniform vec2 pixelsize;
+uniform vec4 search_rect;
+uniform int barrier;
+
+void
+main()
+{
+ float i, j;
+ float width = search_rect[2];
+ float height = search_rect[3];
+ int diff = 0;
+
+ for (i = 0.0; i < width && diff < barrier; i += pixelsize.x) {
+ for (j = 0.0; j < height && diff < barrier; j += pixelsize.y) {
+ vec4 match = texture2D(tex, search_rect.xy + vec2(i,j));
+ vec4 orig = texture2D(tex, v_texcoord + vec2(i,j));
+
+ diff += int(any(greaterThan(abs(orig - match), vec4(0.2))));
+ }
+ }
+
+ gl_FragColor = vec4(float(diff < barrier), 0.0, 0.0, 0.0);
+}
+
+// vim:ft=c:
diff --git a/wimmel.vert b/wimmel.vert
new file mode 100644
index 0000000..fe26ecc
--- /dev/null
+++ b/wimmel.vert
@@ -0,0 +1,10 @@
+uniform mat4 proj;
+attribute vec4 position;
+attribute vec2 texcoord;
+varying vec2 v_texcoord;
+
+void main()
+{
+ gl_Position = proj * position;
+ v_texcoord = texcoord;
+}
diff --git a/wimmel_gl.c b/wimmel_gl.c
new file mode 100644
index 0000000..4d6456e
--- /dev/null
+++ b/wimmel_gl.c
@@ -0,0 +1,243 @@
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glut.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+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;
+}