Merge branch 'snazzy-demo' into 'master'

gtk-demo: Make gltransitions demo a bit snazzier

See merge request GNOME/gtk!2644
This commit is contained in:
Matthias Clasen 2020-09-30 15:00:58 +00:00
commit 97ffd94d20
12 changed files with 155 additions and 94 deletions

View File

@ -0,0 +1,26 @@
uniform float u_time;
void
mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
vec2 pos = (fragCoord.xy * 2.0 - resolution.xy)/ min (resolution.x, resolution.y) ;
float t0 = sin ((u_time + 0.00)*1.0);
float t1 = sin ((u_time + 0.30)*0.4);
float t2 = cos ((u_time + 0.23)*0.9);
float t3 = cos ((u_time + 0.41)*0.6);
float t4 = cos ((u_time + 0.11)*0.3);
vec2 p0 = vec2 (t1, t0) ;
vec2 p1 = vec2 (t2, t3) ;
vec2 p2 = vec2 (t4, t3) ;
float r = 1.0/distance (pos, p0);
float g = 1.0/distance (pos, p1);
float b = 1.0/distance (pos, p2);
float sum = r + g + b;
float alpha = 1.0 - pow (1.0/(sum), 40)*pow (10.0, 40*0.7);
fragColor = vec4 (r*0.5, g*0.5, b*0.5, 1.0) * alpha;
}

View File

@ -138,8 +138,9 @@
<file>gtkshaderstack.h</file> <file>gtkshaderstack.h</file>
<file>gtkshaderbin.h</file> <file>gtkshaderbin.h</file>
<file>gtkshaderbin.c</file> <file>gtkshaderbin.c</file>
<file>fire.glsl</file> <file>ripple.glsl</file>
<file>transition1.glsl</file> <file>background.glsl</file>
<file>transition1.glsl</file>
<file>transition2.glsl</file> <file>transition2.glsl</file>
<file>transition3.glsl</file> <file>transition3.glsl</file>
<file>transition4.glsl</file> <file>transition4.glsl</file>

View File

@ -1,72 +0,0 @@
uniform float u_time;
uniform sampler2D u_texture1;
/* 2D -> [0..1] random number generator */
float random(vec2 st) {
return fract(sin(dot(st.xy,
vec2(12.9898,78.233))) *
43758.5453123);
}
/* Generate a smoothed 2d noise based on random() */
float noise(vec2 v) {
/* Round point v to integer grid grid */
vec2 grid_point = floor(v);
/* Randomize in grid corners */
float corner1 = random(grid_point);
float corner2 = random(grid_point + vec2(1, 0));
float corner3 = random(grid_point + vec2(0, 1));
float corner4 = random(grid_point + vec2(1, 1));
/* Interpolate smoothly between grid points */
vec2 fraction = smoothstep(vec2(0.0), vec2(1.0), fract(v));
return mix(mix(corner1, corner2, fraction.x),
mix(corner3, corner4, fraction.x),
fraction.y);
}
/* fractal brownian motion noice, see https://www.iquilezles.org/www/articles/fbm/fbm.htm */
float fbm(in vec2 x)
{
const float octaveScale = 1.9;
const float G = 0.5;
float f = 1.0;
float a = 1.0;
float t = 0.0;
int numOctaves = 5;
for (int i = 0; i < numOctaves; i++) {
t += a*noise(f*x);
f *= octaveScale;
a *= G;
}
return t;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
vec2 xy = fragCoord / resolution;
float zoom = 3.0 - sin(u_time*0.5)*0.3;
// Normalize coord to height of widget
vec2 p = (vec2 (-resolution.x/2.0 + fragCoord.x, resolution.y - fragCoord.y) / resolution.yy)* zoom;
// Use recursive incantations of fbm
float q1 = fbm(p - vec2(0.8, 0.3) * u_time);
float q2 = fbm(p - vec2(0.5, 1.3) * u_time);
float r = fbm(2.0*p + vec2(q1,q2) - vec2(0.0, 1.0)*u_time*10.0 *0.4);
// Compute intensity, mostly on the bottom
float w = 2.0 * r * p.y;
// Smooth out left/right side and fade in at start
w /= smoothstep(0.0,0.1, xy.x)* smoothstep(0.0,0.1, 1.0-xy.x) * smoothstep(0.0,0.4, u_time);
// Compute colors
vec3 c = vec3(1.0,.2,.05);
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));
}

View File

@ -85,15 +85,15 @@ clicked_cb (GtkGestureClick *gesture,
} }
static GtkWidget * static GtkWidget *
fire_bin_new (void) ripple_bin_new (void)
{ {
GtkWidget *bin = gtk_shader_bin_new (); GtkWidget *bin = gtk_shader_bin_new ();
static GskGLShader *shader = NULL; static GskGLShader *shader = NULL;
if (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; return bin;
} }
@ -131,6 +131,7 @@ update_paintable (GtkWidget *widget,
static GtkWidget * static GtkWidget *
make_shader_stack (const char *name, make_shader_stack (const char *name,
const char *resource_path, const char *resource_path,
int active_child,
GtkWidget *scale) GtkWidget *scale)
{ {
GtkWidget *stack, *child, *widget, *vbox, *hbox, *bin; GtkWidget *stack, *child, *widget, *vbox, *hbox, *bin;
@ -150,7 +151,7 @@ make_shader_stack (const char *name,
gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader); gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader);
g_object_unref (shader); g_object_unref (shader);
child = gtk_picture_new_for_resource ("/css_pixbufs/background.jpg"); child = gtk_picture_new_for_resource ("/css_blendmodes/ducky.png");
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE); gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child); gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
@ -219,6 +220,8 @@ make_shader_stack (const char *name,
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child); 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); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
widget = gtk_center_box_new (); 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), 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); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign (hbox, GTK_ALIGN_CENTER); 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"); button = gtk_button_new_from_icon_name ("go-previous");
g_signal_connect (button, "clicked", G_CALLBACK (go_back), stack); 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_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
gtk_box_append (GTK_BOX (hbox), bin); gtk_box_append (GTK_BOX (hbox), bin);
button = gtk_button_new_from_icon_name ("go-next"); button = gtk_button_new_from_icon_name ("go-next");
g_signal_connect (button, "clicked", G_CALLBACK (go_forward), stack); 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_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
gtk_box_append (GTK_BOX (hbox), bin); gtk_box_append (GTK_BOX (hbox), bin);
@ -270,7 +276,8 @@ make_shader_stack (const char *name,
static GtkWidget * static GtkWidget *
create_gltransition_window (GtkWidget *do_widget) 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 (); window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget)); 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); gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL); 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/background.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 (); 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_halign (grid, GTK_ALIGN_CENTER);
gtk_widget_set_valign (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_set_column_homogeneous (GTK_GRID (grid), TRUE);
gtk_grid_attach (GTK_GRID (grid), 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); 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), 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); 1, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), 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); 0, 1, 1, 1);
gtk_grid_attach (GTK_GRID (grid), 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); 1, 1, 1, 1);
return window; return window;

View File

@ -4,6 +4,7 @@ typedef struct {
GskGLShader *shader; GskGLShader *shader;
GtkStateFlags state; GtkStateFlags state;
GtkStateFlags state_mask; GtkStateFlags state_mask;
float extra_border;
gboolean compiled; gboolean compiled;
gboolean compiled_ok; gboolean compiled_ok;
} ShaderInfo; } ShaderInfo;
@ -16,6 +17,7 @@ struct _GtkShaderBin
GPtrArray *shaders; GPtrArray *shaders;
guint tick_id; guint tick_id;
float time; float time;
float mouse_x, mouse_y;
gint64 first_frame_time; gint64 first_frame_time;
}; };
@ -71,10 +73,25 @@ gtk_shader_bin_tick (GtkWidget *widget,
return G_SOURCE_CONTINUE; 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 static void
gtk_shader_bin_init (GtkShaderBin *self) gtk_shader_bin_init (GtkShaderBin *self)
{ {
GtkEventController *controller;
self->shaders = g_ptr_array_new_with_free_func ((GDestroyNotify)shader_info_free); 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 void
@ -132,12 +149,14 @@ void
gtk_shader_bin_add_shader (GtkShaderBin *self, gtk_shader_bin_add_shader (GtkShaderBin *self,
GskGLShader *shader, GskGLShader *shader,
GtkStateFlags state, GtkStateFlags state,
GtkStateFlags state_mask) GtkStateFlags state_mask,
float extra_border)
{ {
ShaderInfo *info = g_new0 (ShaderInfo, 1); ShaderInfo *info = g_new0 (ShaderInfo, 1);
info->shader = g_object_ref (shader); info->shader = g_object_ref (shader);
info->state = state; info->state = state;
info->state_mask = state_mask; info->state_mask = state_mask;
info->extra_border = extra_border;
g_ptr_array_add (self->shaders, info); g_ptr_array_add (self->shaders, info);
@ -198,10 +217,14 @@ gtk_shader_bin_snapshot (GtkWidget *widget,
if (self->active_shader->compiled_ok) 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, 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, gsk_gl_shader_format_args (self->active_shader->shader,
"u_time", self->time, "u_time", self->time,
"u_mouse", &mouse,
NULL)); NULL));
gtk_widget_snapshot_child (widget, self->child, snapshot); gtk_widget_snapshot_child (widget, self->child, snapshot);
gtk_snapshot_gl_shader_pop_texture (snapshot); gtk_snapshot_gl_shader_pop_texture (snapshot);

View File

@ -12,7 +12,8 @@ GtkWidget *gtk_shader_bin_new (void);
void gtk_shader_bin_add_shader (GtkShaderBin *self, void gtk_shader_bin_add_shader (GtkShaderBin *self,
GskGLShader *shader, GskGLShader *shader,
GtkStateFlags state, GtkStateFlags state,
GtkStateFlags state_mask); GtkStateFlags state_mask,
float extra_border);
void gtk_shader_bin_set_child (GtkShaderBin *self, void gtk_shader_bin_set_child (GtkShaderBin *self,
GtkWidget *child); GtkWidget *child);
GtkWidget *gtk_shader_bin_get_child (GtkShaderBin *self); GtkWidget *gtk_shader_bin_get_child (GtkShaderBin *self);

View File

@ -350,3 +350,12 @@ gtk_shader_stack_add_child (GtkShaderStack *self,
else else
gtk_widget_set_child_visible (child, FALSE); 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);
}

View File

@ -14,7 +14,9 @@ void gtk_shader_stack_set_shader (GtkShaderStack *self,
void gtk_shader_stack_add_child (GtkShaderStack *self, void gtk_shader_stack_add_child (GtkShaderStack *self,
GtkWidget *child); GtkWidget *child);
void gtk_shader_stack_transition (GtkShaderStack *self, void gtk_shader_stack_transition (GtkShaderStack *self,
gboolean forward); gboolean forward);
void gtk_shader_stack_set_active (GtkShaderStack *self,
int index);
G_END_DECLS G_END_DECLS

View File

@ -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));
}

View File

@ -587,7 +587,8 @@ texture_key_hash (gconstpointer v)
return GPOINTER_TO_UINT (k->pointer) return GPOINTER_TO_UINT (k->pointer)
+ (guint)(k->scale*100) + (guint)(k->scale*100)
+ (guint)k->filter; + (guint)k->filter * 2 +
+ (guint)k->pointer_is_child;
} }
static gboolean static gboolean
@ -598,7 +599,9 @@ texture_key_equal (gconstpointer v1, gconstpointer v2)
return k1->pointer == k2->pointer && return k1->pointer == k2->pointer &&
k1->scale == k2->scale && k1->scale == k2->scale &&
k1->filter == k2->filter; k1->filter == k2->filter &&
k1->pointer_is_child == k2->pointer_is_child &&
(!k1->pointer_is_child || graphene_rect_equal (&k1->parent_rect, &k2->parent_rect));
} }
int int

View File

@ -25,6 +25,8 @@ typedef struct {
gpointer pointer; gpointer pointer;
float scale; float scale;
int filter; int filter;
int pointer_is_child;
graphene_rect_t parent_rect; /* Only set if pointer_is_child */
} GskTextureKey; } GskTextureKey;
GskGLDriver * gsk_gl_driver_new (GdkGLContext *context); GskGLDriver * gsk_gl_driver_new (GdkGLContext *context);

View File

@ -626,6 +626,7 @@ render_fallback_node (GskGLRenderer *self,
return; return;
key.pointer = node; key.pointer = node;
key.pointer_is_child = FALSE;
key.scale = scale; key.scale = scale;
key.filter = GL_NEAREST; key.filter = GL_NEAREST;
@ -1922,6 +1923,7 @@ render_blur_node (GskGLRenderer *self,
} }
key.pointer = node; key.pointer = node;
key.pointer_is_child = FALSE;
key.scale = ops_get_scale (builder); key.scale = ops_get_scale (builder);
key.filter = GL_NEAREST; key.filter = GL_NEAREST;
blurred_region.texture_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key); blurred_region.texture_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
@ -1982,6 +1984,7 @@ render_inset_shadow_node (GskGLRenderer *self,
texture_height = ceilf ((node_outline->bounds.size.height + blur_extra) * scale); texture_height = ceilf ((node_outline->bounds.size.height + blur_extra) * scale);
key.pointer = node; key.pointer = node;
key.pointer_is_child = FALSE;
key.scale = scale; key.scale = scale;
key.filter = GL_NEAREST; key.filter = GL_NEAREST;
blurred_texture_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key); blurred_texture_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
@ -3812,7 +3815,6 @@ add_offscreen_ops (GskGLRenderer *self,
(flags & FORCE_OFFSCREEN) == 0) (flags & FORCE_OFFSCREEN) == 0)
{ {
GdkTexture *texture = gsk_texture_node_get_texture (child_node); GdkTexture *texture = gsk_texture_node_get_texture (child_node);
upload_texture (self, texture, texture_region_out); upload_texture (self, texture, texture_region_out);
*is_offscreen = FALSE; *is_offscreen = FALSE;
return TRUE; return TRUE;
@ -3825,6 +3827,7 @@ add_offscreen_ops (GskGLRenderer *self,
/* Check if we've already cached the drawn texture. */ /* Check if we've already cached the drawn texture. */
key.pointer = child_node; key.pointer = child_node;
key.pointer_is_child = TRUE; /* Don't conflict with the child using the cache too */
key.scale = ops_get_scale (builder); key.scale = ops_get_scale (builder);
key.filter = filter; key.filter = filter;
cached_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key); cached_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);