/* OpenGL/Shadertoy
* # Keywords : GtkGLArea
*
* Generate pixels using a custom fragment shader .
*
* The names of the uniforms are compatible with the shaders on shadertoy . com , so
* many of the shaders there work here too .
*/
#include <math.h>
#include <gtk/gtk.h>
#include <epoxy/gl.h>
#include "gtkshadertoy.h"
static GtkWidget *demo_window = NULL;
static GtkWidget *shadertoy = NULL;
static GtkTextBuffer *textbuffer = NULL;
static void
run (void )
{
GtkTextIter start, end;
char *text;
gtk_text_buffer_get_bounds (textbuffer, &start, &end);
text = gtk_text_buffer_get_text (textbuffer, &start, &end, FALSE );
gtk_shadertoy_set_image_shader (GTK_SHADERTOY (shadertoy), text);
g_free (text);
}
static void
run_clicked_cb (GtkWidget *button,
gpointer user_data)
{
run ();
}
static void
load_clicked_cb (GtkWidget *button,
gpointer user_data)
{
const char *path = user_data;
GBytes *initial_shader;
initial_shader = g_resources_lookup_data (path, 0 , NULL);
gtk_text_buffer_set_text (textbuffer, g_bytes_get_data (initial_shader, NULL), -1 );
g_bytes_unref (initial_shader);
run ();
}
static void
clear_clicked_cb (GtkWidget *button,
gpointer user_data)
{
gtk_text_buffer_set_text (textbuffer, "" , 0 );
}
static void
close_window (GtkWidget *widget)
{
/* Reset the state */
demo_window = NULL;
shadertoy = NULL;
textbuffer = NULL;
}
static GtkWidget *
new_shadertoy (const char *path)
{
GBytes *shader;
GtkWidget *toy;
toy = gtk_shadertoy_new ();
shader = g_resources_lookup_data (path, 0 , NULL);
gtk_shadertoy_set_image_shader (GTK_SHADERTOY (toy),
g_bytes_get_data (shader, NULL));
g_bytes_unref (shader);
return toy;
}
static GtkWidget *
new_button (const char *path)
{
GtkWidget *button, *toy;
button = gtk_button_new ();
g_signal_connect (button, "clicked" , G_CALLBACK (load_clicked_cb), (char *)path);
toy = new_shadertoy (path);
gtk_widget_set_size_request (toy, 64 , 36 );
gtk_button_set_child (GTK_BUTTON (button), toy);
return button;
}
static GtkWidget *
create_shadertoy_window (GtkWidget *do_widget)
{
GtkWidget *window, *box, *hbox, *button, *textview, *sw, *aspect, *centerbox;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Shadertoy" );
gtk_window_set_default_size (GTK_WINDOW (window), 690 , 740 );
g_signal_connect (window, "destroy" , G_CALLBACK (close_window), NULL);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE );
gtk_widget_set_margin_start (box, 12 );
gtk_widget_set_margin_end (box, 12 );
gtk_widget_set_margin_top (box, 12 );
gtk_widget_set_margin_bottom (box, 12 );
gtk_box_set_spacing (GTK_BOX (box), 6 );
gtk_window_set_child (GTK_WINDOW (window), box);
aspect = gtk_aspect_frame_new (0 .5 , 0 .5 , 1 .77777 , FALSE );
gtk_widget_set_hexpand (aspect, TRUE );
gtk_widget_set_vexpand (aspect, TRUE );
gtk_box_append (GTK_BOX (box), aspect);
shadertoy = new_shadertoy ("/shadertoy/alienplanet.glsl" );
gtk_aspect_frame_set_child (GTK_ASPECT_FRAME (aspect), gtk_graphics_offload_new (shadertoy));
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 250 );
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE );
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_set_hexpand (sw, TRUE );
gtk_box_append (GTK_BOX (box), sw);
textview = gtk_text_view_new ();
gtk_text_view_set_monospace (GTK_TEXT_VIEW (textview), TRUE );
g_object_set (textview,
"left-margin" , 20 ,
"right-margin" , 20 ,
"top-margin" , 20 ,
"bottom-margin" , 20 ,
NULL);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), textview);
textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
gtk_text_buffer_set_text (textbuffer,
gtk_shadertoy_get_image_shader (GTK_SHADERTOY (shadertoy)),
-1 );
centerbox = gtk_center_box_new ();
gtk_box_append (GTK_BOX (box), centerbox);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE );
gtk_box_set_spacing (GTK_BOX (hbox), 6 );
gtk_center_box_set_start_widget (GTK_CENTER_BOX (centerbox), hbox);
button = gtk_button_new_from_icon_name ("view-refresh-symbolic" );
gtk_widget_set_tooltip_text (button, "Restart the demo" );
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
g_signal_connect (button, "clicked" , G_CALLBACK (run_clicked_cb), NULL);
gtk_box_append (GTK_BOX (hbox), button);
button = gtk_button_new_from_icon_name ("edit-clear-all-symbolic" );
gtk_widget_set_tooltip_text (button, "Clear the text view" );
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
g_signal_connect (button, "clicked" , G_CALLBACK (clear_clicked_cb), NULL);
gtk_box_append (GTK_BOX (hbox), button);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE );
gtk_box_set_spacing (GTK_BOX (hbox), 6 );
gtk_center_box_set_end_widget (GTK_CENTER_BOX (centerbox), hbox);
button = new_button ("/shadertoy/alienplanet.glsl" );
gtk_box_append (GTK_BOX (hbox), button);
button = new_button ("/shadertoy/mandelbrot.glsl" );
gtk_box_append (GTK_BOX (hbox), button);
button = new_button ("/shadertoy/neon.glsl" );
gtk_box_append (GTK_BOX (hbox), button);
button = new_button ("/shadertoy/cogs.glsl" );
gtk_box_append (GTK_BOX (hbox), button);
button = new_button ("/shadertoy/glowingstars.glsl" );
gtk_box_append (GTK_BOX (hbox), button);
return window;
}
GtkWidget *
do_shadertoy (GtkWidget *do_widget)
{
if (!demo_window)
demo_window = create_shadertoy_window (do_widget);
if (!gtk_widget_get_visible (demo_window))
gtk_widget_set_visible (demo_window, TRUE );
else
gtk_window_destroy (GTK_WINDOW (demo_window));
return demo_window;
}
Messung V0.5 in Prozent C=98 H=95 G=96
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-07-02)
¤
*© Formatika GbR, Deutschland