[192/906] complete differencematte filter.. I did it quickly, probably still needs...
authorFilippo Argiolas <filippo.argiolas@gmail.com>
Mon, 18 Aug 2008 19:40:26 +0000 (21:40 +0200)
committerMatthew Waters <ystreet00@gmail.com>
Sat, 15 Mar 2014 17:36:26 +0000 (18:36 +0100)
gst/gl/effects/gstgleffectssources.c
gst/gl/effects/gstgleffectssources.h
gst/gl/gstgldifferencematte.c

index ce31a25..63b2969 100644 (file)
@@ -359,6 +359,19 @@ const gchar *interpolate_fragment_source =
   "gl_FragColor = blendcolor + (1.0 - blendcolor.a) * basecolor;"
   "}";
 
+const gchar *texture_interp_fragment_source = 
+  "#extension GL_ARB_texture_rectangle : enable\n"
+  "uniform sampler2DRect base;"
+  "uniform sampler2DRect blend;"
+  "uniform sampler2DRect alpha;"
+  "void main () {"
+  "vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);"
+  "vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);"
+  "vec4 alphacolor = texture2DRect (alpha, gl_TexCoord[0].st);"
+//  "gl_FragColor = alphacolor;"
+  "gl_FragColor = (alphacolor * blendcolor) + (1.0 - alphacolor) * basecolor;"
+  "}";
+
 const gchar *difference_fragment_source =
   "#extension GL_ARB_texture_rectangle : enable\n"
   "uniform sampler2DRect saved;"
index 250c7e8..e2ec79e 100644 (file)
@@ -37,6 +37,7 @@ const gchar *luma_to_curve_fragment_source;
 const gchar *rgb_to_curve_fragment_source;
 const gchar *sin_fragment_source;
 const gchar *interpolate_fragment_source;
+const gchar *texture_interp_fragment_source;
 const gchar *difference_fragment_source;
 
 #endif /* __GST_GL_EFFECTS_SOURCES_H__ */
index bf5bf13..9d6c644 100644 (file)
@@ -46,6 +46,7 @@ struct _GstGLDifferenceMatte
   GLuint savedbgtexture;
   GLuint newbgtexture;
   GLuint midtexture[4];
+  GLuint intexture;
 };
 
 struct _GstGLDifferenceMatteClass
@@ -96,8 +97,17 @@ gst_gl_differencematte_init_gl_resources (GstGLFilter *filter)
   GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter);
   gint i;
 
-  for (i=0; i<3; i++)
+  for (i=0; i<4; i++) {
+    glGenTextures (1, &differencematte->midtexture[i]);
+    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, differencematte->midtexture[i]);
+    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+                filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
     differencematte->shader[i] = gst_gl_shader_new ();
+  }
 
   g_return_if_fail (
     gst_gl_shader_compile_and_check (differencematte->shader[0],
@@ -109,12 +119,13 @@ gst_gl_differencematte_init_gl_resources (GstGLFilter *filter)
                                     GST_GL_SHADER_FRAGMENT_SOURCE));
   
   g_return_if_fail (
-    gst_gl_shader_compile_and_check (differencematte->shader[1],
+    gst_gl_shader_compile_and_check (differencematte->shader[2],
                                      vconv9_fragment_source,
                                     GST_GL_SHADER_FRAGMENT_SOURCE));
+  
   g_return_if_fail (
-    gst_gl_shader_compile_and_check (differencematte->shader[1],
-                                     interpolate_fragment_source,
+    gst_gl_shader_compile_and_check (differencematte->shader[3],
+                                     texture_interp_fragment_source,
                                     GST_GL_SHADER_FRAGMENT_SOURCE));
 }
 
@@ -127,8 +138,10 @@ gst_gl_differencematte_reset_gl_resources (GstGLFilter *filter)
   
   glDeleteTextures (1, &differencematte->savedbgtexture);
   glDeleteTextures (1, &differencematte->newbgtexture);
-  for (i=0; i<3; i++)
+  for (i=0; i<4; i++) {
     g_object_unref (differencematte->shader[i]);
+    glDeleteTextures (1, &differencematte->midtexture[i]);
+  }
 }
 
 static void
@@ -258,8 +271,33 @@ gst_gl_differencematte_save_texture (gint width, gint height, guint texture, gpo
   gst_gl_differencematte_draw_texture (differencematte, texture);
 }
 
+static void init_pixbuf_texture (GstGLDisplay *display, gpointer data)
+{
+  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (data);
+  GstGLFilter *filter = GST_GL_FILTER (data);
+  
+  glDeleteTextures (1, &differencematte->newbgtexture);
+  glGenTextures (1, &differencematte->newbgtexture);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture);
+  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
+                filter->width, filter->height, 0,
+                gdk_pixbuf_get_has_alpha (differencematte->pixbuf) ? GL_RGBA : GL_RGB,
+                GL_UNSIGNED_BYTE, gdk_pixbuf_get_pixels (differencematte->pixbuf));
+
+  if (differencematte->savedbgtexture == 0) {
+    glGenTextures (1, &differencematte->savedbgtexture);
+    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture);
+    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+                 filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  }
+}
+
 static void
-gst_gl_differencematte_callback (gint width, gint height, guint texture, gpointer stuff)
+gst_gl_differencematte_diff (gint width, gint height, guint texture, gpointer stuff)
 {
   GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff);
   
@@ -285,29 +323,97 @@ gst_gl_differencematte_callback (gint width, gint height, guint texture, gpointe
   gst_gl_differencematte_draw_texture (differencematte, texture);
 }
 
-static void init_pixbuf_texture (GstGLDisplay *display, gpointer data)
+static void
+gst_gl_differencematte_hblur (gint width, gint height, guint texture, gpointer stuff)
 {
-  GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (data);
-  GstGLFilter *filter = GST_GL_FILTER (data);
+  GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff);
+  gfloat gauss_kernel[9] = { 
+    0.026995, 0.064759, 0.120985,
+    0.176033, 0.199471, 0.176033,
+    0.120985, 0.064759, 0.026995
+  };
+
   
-  glDeleteTextures (1, &differencematte->newbgtexture);
-  glGenTextures (1, &differencematte->newbgtexture);
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+
+  gst_gl_shader_use (differencematte->shader[1]);
+
+  glActiveTexture (GL_TEXTURE0);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
+  glDisable(GL_TEXTURE_RECTANGLE_ARB);
+  
+  gst_gl_shader_set_uniform_1i (differencematte->shader[1], "tex", 0);
+
+  gst_gl_shader_set_uniform_1fv (differencematte->shader[1], "kernel", 9, gauss_kernel);
+  gst_gl_shader_set_uniform_1f (differencematte->shader[1], "norm_const", 0.977016f);
+  gst_gl_shader_set_uniform_1f (differencematte->shader[1], "norm_offset", 0.0f);
+
+  gst_gl_differencematte_draw_texture (differencematte, texture);
+}
+
+static void
+gst_gl_differencematte_vblur (gint width, gint height, guint texture, gpointer stuff)
+{
+  GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff);
+  gfloat gauss_kernel[9] = { 
+    0.026995, 0.064759, 0.120985,
+    0.176033, 0.199471, 0.176033,
+    0.120985, 0.064759, 0.026995
+  };
+  
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+
+  gst_gl_shader_use (differencematte->shader[2]);
+
+  glActiveTexture (GL_TEXTURE0);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
+  glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+  gst_gl_shader_set_uniform_1i (differencematte->shader[2], "tex", 0);
+
+  gst_gl_shader_set_uniform_1fv (differencematte->shader[2], "kernel", 9, gauss_kernel);
+  gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_const", 0.977016f);
+  gst_gl_shader_set_uniform_1f (differencematte->shader[2], "norm_offset", 0.0f);
+  
+  gst_gl_differencematte_draw_texture (differencematte, texture);
+}
+
+static void
+gst_gl_differencematte_interp (gint width, gint height, guint texture, gpointer stuff)
+{
+  GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff);
+  
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+
+  gst_gl_shader_use (differencematte->shader[3]);
+
+  glActiveTexture (GL_TEXTURE0);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
+  glDisable(GL_TEXTURE_RECTANGLE_ARB);
+  
+  gst_gl_shader_set_uniform_1i (differencematte->shader[3], "base", 0);
+
+  glActiveTexture (GL_TEXTURE1);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
   glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture);
-  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
-                filter->width, filter->height, 0,
-                gdk_pixbuf_get_has_alpha (differencematte->pixbuf) ? GL_RGBA : GL_RGB,
-                GL_UNSIGNED_BYTE, gdk_pixbuf_get_pixels (differencematte->pixbuf));
+  glDisable (GL_TEXTURE_RECTANGLE_ARB);
 
-  if (differencematte->savedbgtexture == 0) {
-    glGenTextures (1, &differencematte->savedbgtexture);
-    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture);
-    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-                 filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  }
+  gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 1);
+
+  glActiveTexture (GL_TEXTURE2);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->midtexture[2]);
+  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+
+  gst_gl_shader_set_uniform_1i (differencematte->shader[3], "alpha", 2);
+
+  gst_gl_differencematte_draw_texture (differencematte, texture);
 }
 
 static gboolean
@@ -318,6 +424,8 @@ gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
   GdkPixbuf *pixbuf;
   GError *error = NULL;
 
+  differencematte->intexture = inbuf->texture;
+
   if (differencematte->bg_has_changed && (differencematte->location != NULL)) {
     pixbuf = gdk_pixbuf_new_from_file (differencematte->location, &error);
     if (pixbuf) {
@@ -343,8 +451,20 @@ gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
     differencematte->bg_has_changed = FALSE;
   }
 
-  gst_gl_filter_render_to_target (filter, inbuf->texture, outbuf->texture,
-                                 gst_gl_differencematte_callback, differencematte);
+  gst_gl_filter_render_to_target (filter, inbuf->texture, differencematte->midtexture[0],
+                                 gst_gl_differencematte_diff, differencematte);
+  gst_gl_filter_render_to_target (filter, 
+                                  differencematte->midtexture[0],
+                                  differencematte->midtexture[1],
+                                 gst_gl_differencematte_hblur, differencematte);
+  gst_gl_filter_render_to_target (filter, 
+                                  differencematte->midtexture[1],
+                                  differencematte->midtexture[2],
+                                 gst_gl_differencematte_vblur, differencematte);
+  gst_gl_filter_render_to_target (filter, 
+                                  inbuf->texture,
+                                  outbuf->texture,
+                                 gst_gl_differencematte_interp, differencematte);
 
   return TRUE;
 }