void Animation::loadShader(const char *fragment_path) { std::string fragShaderStr = readFile(fragment_path); const gchar *fragShaderSrc = fragShaderStr.c_str(); // Pop off the old shader: unloadShader(); printf("Loading shader: '%s' \n", fragment_path); // Setup the GLSL Fragment shaders that we'll use to generate colors // Build a GLSL Fragment shader to affect the color output (to the screen at least for now) shaderEffect = clutter_shader_effect_new(CLUTTER_FRAGMENT_SHADER); clutter_shader_effect_set_shader_source(CLUTTER_SHADER_EFFECT(shaderEffect), fragShaderSrc); // Start fuckups: // ClutterEffect *effect = clutter_blur_effect_new (); // works // ClutterEffect *effect = clutter_sensatron_effect_new (); // clutter_sensatron_effect_set_shader_source(CLUTTER_SENSATRON_EFFECT(effect), fragShaderSrc); // Now, let's try attaching a texture to this bitch!! // CoglTexture *texture = cogl_texture_new_from_file(textureFile, // COGL_TEXTURE_NONE, // COGL_PIXEL_FORMAT_ANY, // &error); // Try attaching the texture to the effect (on the 1th layer?): // cogl_pipeline_set_layer_texture (priv->pipeline, 1, texture); // CoglPipeline *target; // target = COGL_PIPELINE (clutter_offscreen_effect_get_target ((ClutterOffscreenEffect)shaderEffect)); // End fuckups // Bind uniforms to the shader so we can hand variables into them animationTime = 0.0; currentSpeed = 100; clutter_shader_effect_set_uniform(CLUTTER_SHADER_EFFECT(shaderEffect), "iGlobalTime", G_TYPE_FLOAT, 1, animationTime); clutter_shader_effect_set_uniform(CLUTTER_SHADER_EFFECT(shaderEffect), "iResolution", G_TYPE_FLOAT, 2, HEIGHT*osd_scale, WIDTH*osd_scale); clutter_shader_effect_set_uniform(CLUTTER_SHADER_EFFECT(shaderEffect), "iMouse", G_TYPE_FLOAT, 2, input_x*osd_scale, input_y*osd_scale); // clutter_shader_effect_set_uniform(CLUTTER_SHADER_EFFECT(shaderEffect), "iChannel0", CLUTTER_TYPE_SHADER_FLOAT, 1, audioTexture); // clutter_shader_effect_set_uniform(CLUTTER_SHADER_EFFECT(shaderEffect), "iChannel1", CLUTTER_TYPE_SHADER_FLOAT, 1, noiseTexture); // Set the effect live on the on screen display actor... clutter_actor_add_effect(shaderOutput, shaderEffect); // clutter_actor_add_effect(shaderOutput, effect); shaderLoaded = true; }
static void clutter_shader_effect_set_actor (ClutterActorMeta *meta, ClutterActor *actor) { ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (meta); ClutterShaderEffectPrivate *priv = self->priv; ClutterActorMetaClass *parent; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (meta, FALSE); return; } parent = CLUTTER_ACTOR_META_CLASS (clutter_shader_effect_parent_class); parent->set_actor (meta, actor); /* we keep a back pointer here */ priv->actor = clutter_actor_meta_get_actor (meta); if (priv->actor == NULL) return; CLUTTER_NOTE (SHADER, "Preparing shader effect of type '%s'", G_OBJECT_TYPE_NAME (meta)); }
static void shader_paint (ClutterEffect *effect, ClutterEffectPaintFlags flags) { ClutterShaderEffect *shader = CLUTTER_SHADER_EFFECT (effect); float tex_width; ClutterActor *actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (g_test_verbose ()) g_debug ("shader_paint"); clutter_shader_effect_set_shader_source (shader, "uniform sampler2D tex;\n" "uniform float step;\n" "void main (void)\n" "{\n" " gl_FragColor = texture2D(tex, vec2 (gl_TexCoord[0].s + step,\n" " gl_TexCoord[0].t));\n" "}\n"); tex_width = clutter_actor_get_width (actor); clutter_shader_effect_set_uniform (shader, "tex", G_TYPE_INT, 1, 0); clutter_shader_effect_set_uniform (shader, "step", G_TYPE_FLOAT, 1, SHIFT_STEP / tex_width); CLUTTER_EFFECT_CLASS (shift_effect_parent_class)->paint (effect, flags); }
static void clutter_shader_effect_finalize (GObject *gobject) { ClutterShaderEffect *effect = CLUTTER_SHADER_EFFECT (gobject); clutter_shader_effect_clear (effect, TRUE); G_OBJECT_CLASS (clutter_shader_effect_parent_class)->finalize (gobject); }
static void clutter_shader_effect_set_property (GObject *gobject, guint prop_id, const GValue *value, GParamSpec *pspec) { ClutterShaderEffectPrivate *priv = CLUTTER_SHADER_EFFECT (gobject)->priv; switch (prop_id) { case PROP_SHADER_TYPE: priv->shader_type = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); break; } }
static void clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect) { ClutterShaderEffectPrivate *priv = CLUTTER_SHADER_EFFECT (effect)->priv; ClutterOffscreenEffectClass *parent; CoglHandle material; /* we haven't been prepared or we don't have support for * GLSL shaders in Clutter */ if (priv->program == COGL_INVALID_HANDLE || priv->shader == COGL_INVALID_HANDLE) goto out; if (!priv->source_set) goto out; if (!priv->is_compiled) { CLUTTER_NOTE (SHADER, "Compiling shader effect"); cogl_shader_compile (priv->shader); if (!cogl_shader_is_compiled (priv->shader)) { gchar *log_buf = cogl_shader_get_info_log (priv->shader); g_warning ("Unable to compile the GLSL shader: %s", log_buf); g_free (log_buf); cogl_handle_unref (priv->shader); priv->shader = COGL_INVALID_HANDLE; cogl_handle_unref (priv->program); priv->shader = COGL_INVALID_HANDLE; goto out; } cogl_program_attach_shader (priv->program, priv->shader); cogl_handle_unref (priv->shader); cogl_program_link (priv->program); priv->is_compiled = TRUE; } CLUTTER_NOTE (SHADER, "Applying the shader effect of type '%s'", G_OBJECT_TYPE_NAME (effect)); clutter_shader_effect_update_uniforms (CLUTTER_SHADER_EFFECT (effect)); /* associate the program to the offscreen target material */ material = clutter_offscreen_effect_get_target (effect); cogl_material_set_user_program (material, priv->program); out: /* paint the offscreen buffer */ parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class); parent->paint_target (effect); }
// handleNewFrame is the function that is called ever 120 milliseconds via the timeline! // This is where ALL animation updates will happen. void Animation::handleNewFrame(ClutterTimeline *timeline, gint frame_num, gpointer user_data) { // Rebuild the struct from the pointer we handed in: AnimationData *data; data = (AnimationData *) user_data; TCLControl *tcl = data->tcl; // tcl is STILL a pointer to the main TCLControl object Animation *animation = data->animationObject; // Error object for GDK/Clutter calls that need them error = NULL; shaderAnimation(tcl); // Send the updated color buffer to the strands if (tcl->enabled) { tcl->Update(); } // Dump the colors from the color buffer into the ClutterContent delegate! if (pixbuf != NULL) { clutter_image_set_data(CLUTTER_IMAGE(colors), gdk_pixbuf_get_pixels (pixbuf), COGL_PIXEL_FORMAT_RGB_888, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), gdk_pixbuf_get_rowstride (pixbuf), &error); } // clutter_actor_set_content(lightDisplay, colors); // Bind that delegate to the lightDisplay // Update the shader uniforms: // Populate the audioImage with the FFT data: // executeFFT(audioPixels, audioRowstride); // Actually load our FFT Texture colors onto the actor // clutter_image_set_data (CLUTTER_IMAGE (audioImage), // gdk_pixbuf_get_pixels (audiopixbuf), // gdk_pixbuf_get_has_alpha (audiopixbuf) // ? COGL_PIXEL_FORMAT_RGBA_8888 // : COGL_PIXEL_FORMAT_RGB_888, // gdk_pixbuf_get_width (audiopixbuf), // gdk_pixbuf_get_height (audiopixbuf), // gdk_pixbuf_get_rowstride (audiopixbuf), // &error); // clutter_actor_set_content (shaderOutput, audioImage); // Use the timeline delta to determine how much time to add to the clock: int delta = clutter_timeline_get_delta(timeline); if (animation->currentSpeed > 500 || animation->currentSpeed<-500) { animation->currentSpeed = 100; } animationTime += delta/1000.0 * (animation->currentSpeed/100.0); // printf("Current speed: %i, animation time: %f\n", animation->currentSpeed, animationTime); // Update the random noiseImage: // for (unsigned int i=0; i<noiseTextureSize; i++) { // noiseTexture[i] = getrandf(); // } if (animation->shaderLoaded ) { // Only update the shader when a shader is actually SET clutter_shader_effect_set_uniform(CLUTTER_SHADER_EFFECT(shaderEffect), "iGlobalTime", G_TYPE_FLOAT, 1, animationTime); clutter_shader_effect_set_uniform(CLUTTER_SHADER_EFFECT(shaderEffect), "iMouse", G_TYPE_FLOAT, 2, input_y*1.0, input_x*1.0); } }