Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gnome/demos/gtk-demo/   (Gnome Linux Desktop Version 4.23.2©)  Datei vom 30.5.2026 mit Größe 15 kB image not shown  

Quelle  gtkshadertoy.c

  Sprache: C
 

#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <epoxy/gl.h>

#include "gtkshadertoy.h"

const char *default_image_shader =
  "void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n"
  "    // Normalized pixel coordinates (from 0 to 1)\n"
  "    vec2 uv = fragCoord/iResolution.xy;\n"
  "\n"
  "   // Time varying pixel color\n"
  "    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));\n"
  "\n"
  "    if (distance(iMouse.xy, fragCoord.xy) <= 10.0) {\n"
  "        col = vec3(0.0);\n"
  "    }\n"
  "\n"
  "    // Output to screen\n"
  "    fragColor = vec4(col,1.0);\n"
  "}\n";

const char *shadertoy_shader_prefix[] =
{
  [GDK_GL_API_GL] =
    "#version 150 core\n"
    "\n",
  [GDK_GL_API_GLES] =
    "#version 300 es\n"
    "precision highp float;\n"
    "\n",
};

const char *shadertoy_vertex_shader =
  "uniform vec3 iResolution;\n"
  "\n"
  "in vec2 position;\n"
  "out vec2 fragCoord;\n"
  "\n"
  "void main() {\n"
  "    gl_Position = vec4(position, 0.0, 1.0);\n"
  "\n"
  "    // Convert from OpenGL coordinate system (with origin in center\n"
  "    // of screen) to Shadertoy/texture coordinate system (with origin\n"
  "    // in lower left corner)\n"
  "    fragCoord = (gl_Position.xy + vec2(1.0)) / vec2(2.0) * iResolution.xy;\n"
  "}\n";

const char *fragment_prefix =
  "uniform vec3      iResolution;           // viewport resolution (in pixels)\n"
  "uniform float     iTime;                 // shader playback time (in seconds)\n"
  "uniform float     iTimeDelta;            // render time (in seconds)\n"
  "uniform int       iFrame;                // shader playback frame\n"
  "uniform float     iChannelTime[4];       // channel playback time (in seconds)\n"
  "uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)\n"
  "uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click\n"
  "uniform sampler2D iChannel0;\n"
  "uniform sampler2D iChannel1;\n"
  "uniform sampler2D iChannel2;\n"
  "uniform sampler2D iChannel3;\n"
  "uniform vec4      iDate;                 // (year, month, day, time in seconds)\n"
  "uniform float     iSampleRate;           // sound sample rate (i.e., 44100)\n"
  "\n"
  "in vec2 fragCoord;\n"
  "out vec4 vFragColor;\n";


// Fragment shader suffix
const char *fragment_suffix =
  "    void main() {\n"
  "        vec4 c;\n"
  "        mainImage(c, fragCoord);\n"
  "         vFragColor = c;\n"
  "    }\n";

typedef struct {
  char *image_shader;
  gboolean image_shader_dirty;

  gboolean error_set;

  /* Vertex buffers */
  GLuint vao;
  GLuint buffer;

  /* Active program */
  GLuint program;

  /* Location of uniforms for program */
  GLuint resolution_location;
  GLuint time_location;
  GLuint timedelta_location;
  GLuint frame_location;
  GLuint mouse_location;

  /* Current uniform values */
  float resolution[3];
  float time;
  float timedelta;
  float mouse[4];
  int frame;

  /* Animation data */
  gint64 first_frame_time;
  gint64 first_frame;
  guint tick;
} GtkShadertoyPrivate;

G_DEFINE_TYPE_WITH_PRIVATE (GtkShadertoy, gtk_shadertoy, GTK_TYPE_GL_AREA)

static gboolean gtk_shadertoy_render        (GtkGLArea     *area,
                                             GdkGLContext  *context);
static void     gtk_shadertoy_reshape       (GtkGLArea     *area,
                                             int            width,
                                             int            height);
static void     gtk_shadertoy_realize       (GtkWidget     *widget);
static void     gtk_shadertoy_unrealize     (GtkWidget     *widget);
static gboolean gtk_shadertoy_tick          (GtkWidget     *widget,
                                             GdkFrameClock *frame_clock,
                                             gpointer       user_data);

GtkWidget *
gtk_shadertoy_new (void)
{
  return g_object_new (gtk_shadertoy_get_type (),
                       "allowed-apis", GDK_GL_API_GL | GDK_GL_API_GLES,
                       NULL);
}

static void
drag_begin_cb (GtkGestureDrag *drag,
               double          x,
               double          y,
               gpointer        user_data)
{
  GtkShadertoy *shadertoy = GTK_SHADERTOY (user_data);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
  int height = gtk_widget_get_height (GTK_WIDGET (shadertoy));
  int scale = gtk_widget_get_scale_factor (GTK_WIDGET (shadertoy));

 priv->mouse[0] = x * scale;
 priv->mouse[1] = (height - y) * scale;
 priv->mouse[2] = priv->mouse[0];
 priv->mouse[3] = priv->mouse[1];
}

static void
drag_update_cb (GtkGestureDrag *drag,
                double          dx,
                double          dy,
                gpointer        user_data)
{
  GtkShadertoy *shadertoy = GTK_SHADERTOY (user_data);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
  int width = gtk_widget_get_width (GTK_WIDGET (shadertoy));
  int height = gtk_widget_get_height (GTK_WIDGET (shadertoy));
  int scale = gtk_widget_get_scale_factor (GTK_WIDGET (shadertoy));
  double x, y;

  gtk_gesture_drag_get_start_point (drag, &x, &y);
  x += dx;
  y += dy;

  if (x >= 0 && x < width &&
      y >= 0 && y < height)
    {
      priv->mouse[0] = x * scale;
      priv->mouse[1] = (height - y) * scale;
    }
}

static void
drag_end_cb (GtkGestureDrag *drag,
             double          dx,
             double          dy,
             gpointer        user_data)
{
  GtkShadertoy *shadertoy = GTK_SHADERTOY (user_data);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);

  priv->mouse[2] = -priv->mouse[2];
  priv->mouse[3] = -priv->mouse[3];
}

static void
gtk_shadertoy_init (GtkShadertoy *shadertoy)
{
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
  GtkGesture *drag;

  priv->image_shader = g_strdup (default_image_shader);
  priv->tick = gtk_widget_add_tick_callback (GTK_WIDGET (shadertoy), gtk_shadertoy_tick, shadertoy, NULL);

  drag = gtk_gesture_drag_new ();
  gtk_widget_add_controller (GTK_WIDGET (shadertoy), GTK_EVENT_CONTROLLER (drag));
  g_signal_connect (drag, "drag-begin", (GCallback)drag_begin_cb, shadertoy);
  g_signal_connect (drag, "drag-update", (GCallback)drag_update_cb, shadertoy);
  g_signal_connect (drag, "drag-end", (GCallback)drag_end_cb, shadertoy);
}

static void
gtk_shadertoy_finalize (GObject *obj)
{
  GtkShadertoy *shadertoy = GTK_SHADERTOY (obj);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);

  gtk_widget_remove_tick_callback (GTK_WIDGET (shadertoy), priv->tick);
  g_free (priv->image_shader);

  G_OBJECT_CLASS (gtk_shadertoy_parent_class)->finalize (obj);
}

static void
gtk_shadertoy_class_init (GtkShadertoyClass *klass)
{
  GTK_GL_AREA_CLASS (klass)->render = gtk_shadertoy_render;
  GTK_GL_AREA_CLASS (klass)->resize = gtk_shadertoy_reshape;

  GTK_WIDGET_CLASS (klass)->realize = gtk_shadertoy_realize;
  GTK_WIDGET_CLASS (klass)->unrealize = gtk_shadertoy_unrealize;

  G_OBJECT_CLASS (klass)->finalize = gtk_shadertoy_finalize;
}

/* new window size or exposure */
static void
gtk_shadertoy_reshape (GtkGLArea *area, int width, int height)
{
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private ((GtkShadertoy *) area);

  priv->resolution[0] = width;
  priv->resolution[1] = height;
  priv->resolution[2] = 1.0/* screen aspect ratio */

  /* Set the viewport */
  glViewport (00, (GLint) width, (GLint) height);
}

static GLuint
create_shader (int         type,
               const char *src,
               GError    **error)
{
  GLuint shader;
  int status;

  shader = glCreateShader (type);
  glShaderSource (shader, 1, &src, NULL);
  glCompileShader (shader);

  glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
  if (status == GL_FALSE)
    {
      int log_len;
      char *buffer;

      glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &log_len);

      buffer = g_malloc (log_len + 1);
      glGetShaderInfoLog (shader, log_len, NULL, buffer);

      g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
                   "Compile failure in %s shader:\n%s",
                   type == GL_VERTEX_SHADER ? "vertex" : "fragment",
                   buffer);

      g_free (buffer);

      glDeleteShader (shader);

      return 0;
    }

  return shader;
}

static gboolean
init_shaders (GtkShadertoy *shadertoy,
              const char *vertex_source,
              const char *fragment_source,
              GError **error)
{
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
  GLuint vertex, fragment;
  GLuint program = 0;
  int status;
  gboolean res = TRUE;

  vertex = create_shader (GL_VERTEX_SHADER, vertex_source, error);
  if (vertex == 0)
    return FALSE;

  fragment = create_shader (GL_FRAGMENT_SHADER, fragment_source, error);
  if (fragment == 0)
    {
      glDeleteShader (vertex);
      return FALSE;
    }

  program = glCreateProgram ();
  glAttachShader (program, vertex);
  glAttachShader (program, fragment);

  glLinkProgram (program);

  glGetProgramiv (program, GL_LINK_STATUS, &status);
  if (status == GL_FALSE)
    {
      int log_len;
      char *buffer;

      glGetProgramiv (program, GL_INFO_LOG_LENGTH, &log_len);

      buffer = g_malloc (log_len + 1);
      glGetProgramInfoLog (program, log_len, NULL, buffer);

      g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED,
                   "Linking failure:\n%s", buffer);
      res = FALSE;

      g_free (buffer);

      glDeleteProgram (program);

      goto out;
    }

  if (priv->program != 0)
    glDeleteProgram (priv->program);

  priv->program = program;
  priv->resolution_location = glGetUniformLocation (program, "iResolution");
  priv->time_location = glGetUniformLocation (program, "iTime");
  priv->timedelta_location = glGetUniformLocation (program, "iTimeDelta");
  priv->frame_location = glGetUniformLocation (program, "iFrame");
  priv->mouse_location = glGetUniformLocation (program, "iMouse");

  glDetachShader (program, vertex);
  glDetachShader (program, fragment);

out:
  /* These are now owned by the program and can be deleted */
  glDeleteShader (vertex);
  glDeleteShader (fragment);

  return res;
}

static void
gtk_shadertoy_realize_shader (GtkShadertoy *shadertoy)
{
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
  GdkGLAPI api;
  char *vertex_shader, *fragment_shader;
  GError *error = NULL;

  api = gtk_gl_area_get_api (GTK_GL_AREA (shadertoy));
  g_return_if_fail (api > 0 && api < G_N_ELEMENTS (shadertoy_shader_prefix));

  vertex_shader = g_strconcat (shadertoy_shader_prefix[api], shadertoy_vertex_shader, NULL);
  fragment_shader = g_strconcat (shadertoy_shader_prefix[api], fragment_prefix, priv->image_shader, fragment_suffix, NULL);
  if (!init_shaders (shadertoy, vertex_shader, fragment_shader, &error))
    {
      priv->error_set = TRUE;
      gtk_gl_area_set_error (GTK_GL_AREA (shadertoy), error);
      g_error_free (error);
    }
  g_free (vertex_shader);
  g_free (fragment_shader);

  /* Start new shader at time zero */
  priv->first_frame_time = 0;
  priv->first_frame = 0;

  priv->image_shader_dirty = FALSE;
}

static gboolean
gtk_shadertoy_render (GtkGLArea    *area,
                      GdkGLContext *context)
{
  GtkShadertoy *shadertoy = GTK_SHADERTOY (area);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);

  if (gtk_gl_area_get_error (area) != NULL)
    return FALSE;

  if (priv->image_shader_dirty)
    gtk_shadertoy_realize_shader (shadertoy);

  /* Clear the viewport */
  glClearColor (0.00.00.01.0);
  glClear (GL_COLOR_BUFFER_BIT);

  glUseProgram (priv->program);

  /* Update uniforms */
  if (priv->resolution_location != -1)
    glUniform3fv (priv->resolution_location, 1, priv->resolution);
  if (priv->time_location != -1)
    glUniform1f (priv->time_location, priv->time);
  if (priv->timedelta_location != -1)
    glUniform1f (priv->timedelta_location, priv->timedelta);
  if (priv->frame_location != -1)
    glUniform1i (priv->frame_location, priv->frame);
  if (priv->mouse_location != -1)
    glUniform4fv (priv->mouse_location, 1, priv->mouse);

  /* Use the vertices in our buffer */
  glBindBuffer (GL_ARRAY_BUFFER, priv->buffer);
  glEnableVertexAttribArray (0);
  glVertexAttribPointer (04, GL_FLOAT, GL_FALSE, 00);

  glDrawArrays (GL_TRIANGLES, 06);

  /* We finished using the buffers and program */
  glDisableVertexAttribArray (0);
  glBindBuffer (GL_ARRAY_BUFFER, 0);
  glUseProgram (0);

  /* Flush the contents of the pipeline */
  glFlush ();

  return TRUE;
}

const char *
gtk_shadertoy_get_image_shader (GtkShadertoy *shadertoy)
{
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);

  return priv->image_shader;
}

void
gtk_shadertoy_set_image_shader (GtkShadertoy *shadertoy,
                                const char   *shader)
{
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);

  g_free (priv->image_shader);
  priv->image_shader = g_strdup (shader);

  /* Don't override error we didn't set it ourselves */
  if (priv->error_set)
    {
      gtk_gl_area_set_error (GTK_GL_AREA (shadertoy), NULL);
      priv->error_set = FALSE;
    }
  priv->image_shader_dirty = TRUE;
}

static void
gtk_shadertoy_realize (GtkWidget *widget)
{
  GtkGLArea *glarea = GTK_GL_AREA (widget);
  GtkShadertoy *shadertoy = GTK_SHADERTOY (widget);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);

  /* Draw two triangles across whole screen */
  const GLfloat vertex_data[] = {
    -1.0f, -1.0f, 0.f, 1.f,
    -1.0f,  1.0f, 0.f, 1.f,
    1.0f,  1.0f, 0.f, 1.f,

    -1.0f, -1.0f, 0.f, 1.f,
    1.0f,  1.0f, 0.f, 1.f,
    1.0f, -1.0f, 0.f, 1.f,
  };

  GTK_WIDGET_CLASS (gtk_shadertoy_parent_class)->realize (widget);

  gtk_gl_area_make_current (glarea);
  if (gtk_gl_area_get_error (glarea) != NULL)
    return;

  glGenVertexArrays (1, &priv->vao);
  glBindVertexArray (priv->vao);

  glGenBuffers (1, &priv->buffer);
  glBindBuffer (GL_ARRAY_BUFFER, priv->buffer);
  glBufferData (GL_ARRAY_BUFFER, sizeof (vertex_data), vertex_data, GL_STATIC_DRAW);
  glBindBuffer (GL_ARRAY_BUFFER, 0);

  gtk_shadertoy_realize_shader (shadertoy);
}

static void
gtk_shadertoy_unrealize (GtkWidget *widget)
{
  GtkGLArea *glarea = GTK_GL_AREA (widget);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private ((GtkShadertoy *) widget);

  gtk_gl_area_make_current (glarea);
  if (gtk_gl_area_get_error (glarea) == NULL)
    {
      if (priv->buffer != 0)
        glDeleteBuffers (1, &priv->buffer);

      if (priv->vao != 0)
        glDeleteVertexArrays (1, &priv->vao);

      if (priv->program != 0)
        glDeleteProgram (priv->program);
    }

  GTK_WIDGET_CLASS (gtk_shadertoy_parent_class)->unrealize (widget);
}

static gboolean
gtk_shadertoy_tick (GtkWidget     *widget,
                    GdkFrameClock *frame_clock,
                    gpointer       user_data)
{
  GtkShadertoy *shadertoy = GTK_SHADERTOY (widget);
  GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
  gint64 frame_time;
  gint64 frame;
  float previous_time;

  frame = gdk_frame_clock_get_frame_counter (frame_clock);
  frame_time = gdk_frame_clock_get_frame_time (frame_clock);

  if (priv->first_frame_time == 0)
    {
      priv->first_frame_time = frame_time;
      priv->first_frame = frame;
      previous_time = 0;
    }
  else
    previous_time = priv->time;

  priv->time = (frame_time - priv->first_frame_time) / 1000000.0f;
  priv->frame = frame - priv->first_frame;
  priv->timedelta = priv->time - previous_time;

  gtk_widget_queue_draw (widget);

  return G_SOURCE_CONTINUE;
}

Messung V0.5 in Prozent
C=99 H=94 G=96

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-07-02) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.