mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 21:51:08 +00:00
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:
commit
97ffd94d20
26
demos/gtk-demo/background.glsl
Normal file
26
demos/gtk-demo/background.glsl
Normal 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;
|
||||
}
|
@ -138,8 +138,9 @@
|
||||
<file>gtkshaderstack.h</file>
|
||||
<file>gtkshaderbin.h</file>
|
||||
<file>gtkshaderbin.c</file>
|
||||
<file>fire.glsl</file>
|
||||
<file>transition1.glsl</file>
|
||||
<file>ripple.glsl</file>
|
||||
<file>background.glsl</file>
|
||||
<file>transition1.glsl</file>
|
||||
<file>transition2.glsl</file>
|
||||
<file>transition3.glsl</file>
|
||||
<file>transition4.glsl</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));
|
||||
}
|
@ -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;
|
||||
@ -150,7 +151,7 @@ make_shader_stack (const char *name,
|
||||
gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), 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_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_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/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 ();
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
43
demos/gtk-demo/ripple.glsl
Normal file
43
demos/gtk-demo/ripple.glsl
Normal 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));
|
||||
}
|
@ -587,7 +587,8 @@ texture_key_hash (gconstpointer v)
|
||||
|
||||
return GPOINTER_TO_UINT (k->pointer)
|
||||
+ (guint)(k->scale*100)
|
||||
+ (guint)k->filter;
|
||||
+ (guint)k->filter * 2 +
|
||||
+ (guint)k->pointer_is_child;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -598,7 +599,9 @@ texture_key_equal (gconstpointer v1, gconstpointer v2)
|
||||
|
||||
return k1->pointer == k2->pointer &&
|
||||
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
|
||||
|
@ -25,6 +25,8 @@ typedef struct {
|
||||
gpointer pointer;
|
||||
float scale;
|
||||
int filter;
|
||||
int pointer_is_child;
|
||||
graphene_rect_t parent_rect; /* Only set if pointer_is_child */
|
||||
} GskTextureKey;
|
||||
|
||||
GskGLDriver * gsk_gl_driver_new (GdkGLContext *context);
|
||||
|
@ -626,6 +626,7 @@ render_fallback_node (GskGLRenderer *self,
|
||||
return;
|
||||
|
||||
key.pointer = node;
|
||||
key.pointer_is_child = FALSE;
|
||||
key.scale = scale;
|
||||
key.filter = GL_NEAREST;
|
||||
|
||||
@ -1922,6 +1923,7 @@ render_blur_node (GskGLRenderer *self,
|
||||
}
|
||||
|
||||
key.pointer = node;
|
||||
key.pointer_is_child = FALSE;
|
||||
key.scale = ops_get_scale (builder);
|
||||
key.filter = GL_NEAREST;
|
||||
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);
|
||||
|
||||
key.pointer = node;
|
||||
key.pointer_is_child = FALSE;
|
||||
key.scale = scale;
|
||||
key.filter = GL_NEAREST;
|
||||
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)
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (child_node);
|
||||
|
||||
upload_texture (self, texture, texture_region_out);
|
||||
*is_offscreen = FALSE;
|
||||
return TRUE;
|
||||
@ -3825,6 +3827,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
|
||||
/* Check if we've already cached the drawn texture. */
|
||||
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.filter = filter;
|
||||
cached_id = gsk_gl_driver_get_texture_for_key (self->gl_driver, &key);
|
||||
|
Loading…
Reference in New Issue
Block a user