[gtk/snazzy-demo: 1/4] gtk-demo: Make gltransitions demo a bit snazzier




commit e9885f9cdee2121f927f3b5b0c5603cf148acd3b
Author: Alexander Larsson <alexl redhat com>
Date:   Wed Sep 30 11:40:37 2020 +0200

    gtk-demo: Make gltransitions demo a bit snazzier
    
    This adds a bunch of snazz to the gltransitions demo. It is perhaps
    a bit overloaded now, but it demos everything that we can do.
    
    Changes:
     * The fire shader is now not a bin, it just renders an animating
       background with no textures involved.
     * The stacks don't all start on the same page.
     * The shaderbin passes the mouse coordinate to the shader.
     * The shaderbin allows specifying a "border" so that you can
       cause effects outside the bin child (something that is new to gtk4).
     * All the buttons and the stacks are now in shader-bins that runs
       a wobbly-widget effect based on the mouse position that
       wobbles outside the child allocation.

 demos/gtk-demo/demo.gresource.xml |  3 ++-
 demos/gtk-demo/fire.glsl          |  4 +---
 demos/gtk-demo/gltransition.c     | 44 ++++++++++++++++++++++++++++-----------
 demos/gtk-demo/gtkshaderbin.c     | 27 ++++++++++++++++++++++--
 demos/gtk-demo/gtkshaderbin.h     |  3 ++-
 demos/gtk-demo/gtkshaderstack.c   |  9 ++++++++
 demos/gtk-demo/gtkshaderstack.h   |  4 +++-
 demos/gtk-demo/ripple.glsl        | 43 ++++++++++++++++++++++++++++++++++++++
 8 files changed, 117 insertions(+), 20 deletions(-)
---
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index cc9727481c..d279d08af5 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -138,8 +138,9 @@
     <file>gtkshaderstack.h</file>
     <file>gtkshaderbin.h</file>
     <file>gtkshaderbin.c</file>
+    <file>ripple.glsl</file>
     <file>fire.glsl</file>
-    <file>transition1.glsl</file>
+   <file>transition1.glsl</file>
     <file>transition2.glsl</file>
     <file>transition3.glsl</file>
     <file>transition4.glsl</file>
diff --git a/demos/gtk-demo/fire.glsl b/demos/gtk-demo/fire.glsl
index e62fe1bd39..1992688206 100644
--- a/demos/gtk-demo/fire.glsl
+++ b/demos/gtk-demo/fire.glsl
@@ -1,5 +1,4 @@
 uniform float u_time;
-uniform sampler2D u_texture1;
 
 /* 2D -> [0..1] random number generator */
 float random(vec2 st) {
@@ -67,6 +66,5 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec
   vec3 color = 1.0 / (w*w/c + 1.0);
 
   // Mix in widget
-  vec4 widget = GskTexture(u_texture1,uv);
-  fragColor = gsk_premultiply(mix(vec4(color,1), widget, 1.0-color.x));
+  fragColor = gsk_premultiply(vec4(color, color.x));
 }
diff --git a/demos/gtk-demo/gltransition.c b/demos/gtk-demo/gltransition.c
index 24b6f96f30..8106e4ea89 100644
--- a/demos/gtk-demo/gltransition.c
+++ b/demos/gtk-demo/gltransition.c
@@ -85,15 +85,15 @@ clicked_cb (GtkGestureClick *gesture,
 }
 
 static GtkWidget *
-fire_bin_new (void)
+ripple_bin_new (void)
 {
   GtkWidget *bin = gtk_shader_bin_new ();
   static GskGLShader *shader = NULL;
 
   if (shader == NULL)
-    shader = gsk_gl_shader_new_from_resource ("/gltransition/fire.glsl");
+    shader = gsk_gl_shader_new_from_resource ("/gltransition/ripple.glsl");
 
-  gtk_shader_bin_add_shader (GTK_SHADER_BIN (bin), shader, GTK_STATE_FLAG_PRELIGHT, GTK_STATE_FLAG_PRELIGHT);
+  gtk_shader_bin_add_shader (GTK_SHADER_BIN (bin), shader, GTK_STATE_FLAG_PRELIGHT, GTK_STATE_FLAG_PRELIGHT, 
20);
 
   return bin;
 }
@@ -131,6 +131,7 @@ update_paintable (GtkWidget     *widget,
 static GtkWidget *
 make_shader_stack (const char *name,
                    const char *resource_path,
+                   int active_child,
                    GtkWidget  *scale)
 {
   GtkWidget *stack, *child, *widget, *vbox, *hbox, *bin;
@@ -219,6 +220,8 @@ make_shader_stack (const char *name,
 
   gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
 
+  gtk_shader_stack_set_active (GTK_SHADER_STACK (stack), active_child);
+
   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
 
   widget = gtk_center_box_new ();
@@ -245,7 +248,10 @@ make_shader_stack (const char *name,
 
   gtk_box_append (GTK_BOX (vbox), widget);
 
-  gtk_box_append (GTK_BOX (vbox), stack);
+  GtkWidget *bin2 = ripple_bin_new ();
+  gtk_shader_bin_set_child (GTK_SHADER_BIN (bin2), stack);
+
+  gtk_box_append (GTK_BOX (vbox), bin2);
 
   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
   gtk_widget_set_halign (hbox, GTK_ALIGN_CENTER);
@@ -254,13 +260,13 @@ make_shader_stack (const char *name,
 
   button = gtk_button_new_from_icon_name ("go-previous");
   g_signal_connect (button, "clicked", G_CALLBACK (go_back), stack);
-  bin = fire_bin_new ();
+  bin = ripple_bin_new ();
   gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
   gtk_box_append (GTK_BOX (hbox), bin);
 
   button = gtk_button_new_from_icon_name ("go-next");
   g_signal_connect (button, "clicked", G_CALLBACK (go_forward), stack);
-  bin = fire_bin_new ();
+  bin = ripple_bin_new ();
   gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
   gtk_box_append (GTK_BOX (hbox), bin);
 
@@ -270,7 +276,8 @@ make_shader_stack (const char *name,
 static GtkWidget *
 create_gltransition_window (GtkWidget *do_widget)
 {
-  GtkWidget *window, *headerbar, *scale, *grid;
+  GtkWidget *window, *headerbar, *scale, *outer_grid, *grid, *background;
+  GdkPaintable *paintable;
 
   window = gtk_window_new ();
   gtk_window_set_display (GTK_WINDOW (window),  gtk_widget_get_display (do_widget));
@@ -284,8 +291,21 @@ create_gltransition_window (GtkWidget *do_widget)
   gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
   g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
 
+  outer_grid = gtk_grid_new ();
+  gtk_window_set_child (GTK_WINDOW (window), outer_grid);
+
+  paintable = gsk_shader_paintable_new (gsk_gl_shader_new_from_resource ("/gltransition/fire.glsl"), NULL);
+  background = gtk_picture_new_for_paintable (paintable);
+  gtk_widget_add_tick_callback (background, update_paintable, NULL, NULL);
+
+  gtk_grid_attach (GTK_GRID (outer_grid),
+                   background,
+                   0, 0, 1, 1);
+
   grid = gtk_grid_new ();
-  gtk_window_set_child (GTK_WINDOW (window), grid);
+  gtk_grid_attach (GTK_GRID (outer_grid),
+                   grid,
+                   0, 0, 1, 1);
 
   gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
   gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
@@ -299,16 +319,16 @@ create_gltransition_window (GtkWidget *do_widget)
   gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
 
   gtk_grid_attach (GTK_GRID (grid),
-                   make_shader_stack ("Wind", "/gltransition/transition1.glsl", scale),
+                   make_shader_stack ("Wind", "/gltransition/transition1.glsl", 0, scale),
                    0, 0, 1, 1);
   gtk_grid_attach (GTK_GRID (grid),
-                   make_shader_stack ("Radial", "/gltransition/transition2.glsl", scale),
+                   make_shader_stack ("Radial", "/gltransition/transition2.glsl", 1, scale),
                    1, 0, 1, 1);
   gtk_grid_attach (GTK_GRID (grid),
-                   make_shader_stack ("Crosswarp", "/gltransition/transition3.glsl", scale),
+                   make_shader_stack ("Crosswarp", "/gltransition/transition3.glsl", 2, scale),
                    0, 1, 1, 1);
   gtk_grid_attach (GTK_GRID (grid),
-                   make_shader_stack ("Kaleidoscope", "/gltransition/transition4.glsl", scale),
+                   make_shader_stack ("Kaleidoscope", "/gltransition/transition4.glsl", 3, scale),
                    1, 1, 1, 1);
 
   return window;
diff --git a/demos/gtk-demo/gtkshaderbin.c b/demos/gtk-demo/gtkshaderbin.c
index 3a97311c3e..9148e292a3 100644
--- a/demos/gtk-demo/gtkshaderbin.c
+++ b/demos/gtk-demo/gtkshaderbin.c
@@ -4,6 +4,7 @@ typedef struct {
   GskGLShader *shader;
   GtkStateFlags state;
   GtkStateFlags state_mask;
+  float extra_border;
   gboolean compiled;
   gboolean compiled_ok;
 } ShaderInfo;
@@ -16,6 +17,7 @@ struct _GtkShaderBin
   GPtrArray *shaders;
   guint tick_id;
   float time;
+  float mouse_x, mouse_y;
   gint64 first_frame_time;
 };
 
@@ -71,10 +73,25 @@ gtk_shader_bin_tick (GtkWidget     *widget,
   return G_SOURCE_CONTINUE;
 }
 
+static void
+motion_cb (GtkEventControllerMotion *controller,
+           double                    x,
+           double                    y,
+           GtkShaderBin             *self)
+{
+  self->mouse_x = x;
+  self->mouse_y = y;
+}
+
 static void
 gtk_shader_bin_init (GtkShaderBin *self)
 {
+  GtkEventController *controller;
   self->shaders = g_ptr_array_new_with_free_func ((GDestroyNotify)shader_info_free);
+
+  controller = gtk_event_controller_motion_new ();
+  g_signal_connect (controller, "motion", G_CALLBACK (motion_cb), self);
+  gtk_widget_add_controller (GTK_WIDGET (self), controller);
 }
 
 void
@@ -132,12 +149,14 @@ void
 gtk_shader_bin_add_shader (GtkShaderBin *self,
                            GskGLShader  *shader,
                            GtkStateFlags state,
-                           GtkStateFlags state_mask)
+                           GtkStateFlags state_mask,
+                           float         extra_border)
 {
   ShaderInfo *info = g_new0 (ShaderInfo, 1);
   info->shader = g_object_ref (shader);
   info->state = state;
   info->state_mask = state_mask;
+  info->extra_border = extra_border;
 
   g_ptr_array_add (self->shaders, info);
 
@@ -198,10 +217,14 @@ gtk_shader_bin_snapshot (GtkWidget   *widget,
 
       if (self->active_shader->compiled_ok)
         {
+          float border = self->active_shader->extra_border;
+          graphene_vec2_t mouse;
+          graphene_vec2_init (&mouse, self->mouse_x + border, self->mouse_y + border);
           gtk_snapshot_push_gl_shader (snapshot, self->active_shader->shader,
-                                       &GRAPHENE_RECT_INIT(0, 0, width, height),
+                                       &GRAPHENE_RECT_INIT(-border, -border, width+2*border, 
height+2*border),
                                        gsk_gl_shader_format_args (self->active_shader->shader,
                                                                   "u_time", self->time,
+                                                                  "u_mouse", &mouse,
                                                                   NULL));
           gtk_widget_snapshot_child (widget, self->child, snapshot);
           gtk_snapshot_gl_shader_pop_texture (snapshot);
diff --git a/demos/gtk-demo/gtkshaderbin.h b/demos/gtk-demo/gtkshaderbin.h
index eabac8f0d6..32ed18fe6f 100644
--- a/demos/gtk-demo/gtkshaderbin.h
+++ b/demos/gtk-demo/gtkshaderbin.h
@@ -12,7 +12,8 @@ GtkWidget  *gtk_shader_bin_new        (void);
 void        gtk_shader_bin_add_shader (GtkShaderBin *self,
                                        GskGLShader  *shader,
                                        GtkStateFlags state,
-                                       GtkStateFlags state_mask);
+                                       GtkStateFlags state_mask,
+                                       float         extra_border);
 void       gtk_shader_bin_set_child   (GtkShaderBin *self,
                                        GtkWidget    *child);
 GtkWidget *gtk_shader_bin_get_child   (GtkShaderBin *self);
diff --git a/demos/gtk-demo/gtkshaderstack.c b/demos/gtk-demo/gtkshaderstack.c
index 27194df3b1..9b71c22855 100644
--- a/demos/gtk-demo/gtkshaderstack.c
+++ b/demos/gtk-demo/gtkshaderstack.c
@@ -350,3 +350,12 @@ gtk_shader_stack_add_child (GtkShaderStack *self,
   else
     gtk_widget_set_child_visible (child, FALSE);
 }
+
+void
+gtk_shader_stack_set_active (GtkShaderStack *self,
+                             int             index)
+{
+  stop_transition (self);
+  self->current = MIN (index, self->children->len);
+  update_child_visible (self);
+}
diff --git a/demos/gtk-demo/gtkshaderstack.h b/demos/gtk-demo/gtkshaderstack.h
index 9f8e4e45e5..16d1fe9e3f 100644
--- a/demos/gtk-demo/gtkshaderstack.h
+++ b/demos/gtk-demo/gtkshaderstack.h
@@ -14,7 +14,9 @@ void        gtk_shader_stack_set_shader   (GtkShaderStack *self,
 void        gtk_shader_stack_add_child    (GtkShaderStack *self,
                                            GtkWidget      *child);
 void        gtk_shader_stack_transition   (GtkShaderStack *self,
-                                           gboolean       forward);
+                                           gboolean        forward);
+void        gtk_shader_stack_set_active   (GtkShaderStack *self,
+                                           int             index);
 
 G_END_DECLS
 
diff --git a/demos/gtk-demo/ripple.glsl b/demos/gtk-demo/ripple.glsl
new file mode 100644
index 0000000000..028c14c159
--- /dev/null
+++ b/demos/gtk-demo/ripple.glsl
@@ -0,0 +1,43 @@
+uniform float u_time;
+uniform vec2 u_mouse;
+uniform sampler2D u_texture1;
+
+#define PI      3.141592654
+
+float decay(float v, float t)
+{
+  return v * (1.0 / (1.0 + t*t));
+}
+
+void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
+{
+  // Temporary to loop time every 1 sec
+  float time = u_time;
+  // we normalize all the effects according to the min height/width
+  float size = min(resolution.x, resolution.y);
+
+  // Animate one wave over size in 0.3 sec
+  float wave_speed = size / 0.3;
+  float wave_length = size / 1.0;
+  float wave_height = size  * 0.1;
+
+  vec2 center = u_mouse;
+  vec2 direction_from_center = fragCoord - center;
+  float distance_from_center = length(direction_from_center);
+
+  /* Normalize direction */
+  direction_from_center = direction_from_center / distance_from_center;
+
+  float propagation_length = time * wave_speed;
+
+  float t = (propagation_length - distance_from_center) / wave_length;
+  float offset_magnitude = 0;
+  if (t > 0.0)
+    offset_magnitude = decay(wave_height * sin(t * 2.0 * PI), t);
+
+  vec2 offset = direction_from_center * min(offset_magnitude, distance_from_center);
+  vec2 source = fragCoord - offset;
+
+  vec2 uv2 = source / resolution;
+  fragColor = GskTexture(u_texture1, vec2(uv2.x, 1.0-uv2.y));
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]