From b4f8ba0f737212b9a7b734ab7fcd015f7def9161 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 14 Apr 2010 00:40:24 +0100 Subject: [PATCH] effect: Add ColorizeEffect A copy of DesaturateEffect that converts to grayscale and applies a user-defined tint to the render target. --- clutter/Makefile.am | 2 + clutter/clutter-colorize-effect.c | 290 ++++++++++++++++++++++++++++++++++++++ clutter/clutter-colorize-effect.h | 62 ++++++++ clutter/clutter.h | 1 + 4 files changed, 355 insertions(+) create mode 100644 clutter/clutter-colorize-effect.c create mode 100644 clutter/clutter-colorize-effect.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 718de55..7983257 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -92,6 +92,7 @@ source_h = \ $(srcdir)/clutter-click-action.h \ $(srcdir)/clutter-clone.h \ $(srcdir)/clutter-color.h \ + $(srcdir)/clutter-colorize-effect.h \ $(srcdir)/clutter-constraint.h \ $(srcdir)/clutter-container.h \ $(srcdir)/clutter-deprecated.h \ @@ -179,6 +180,7 @@ source_c = \ $(srcdir)/clutter-click-action.c \ $(srcdir)/clutter-clone.c \ $(srcdir)/clutter-color.c \ + $(srcdir)/clutter-colorize-effect.c \ $(srcdir)/clutter-constraint.c \ $(srcdir)/clutter-container.c \ $(srcdir)/clutter-desaturate-effect.c \ diff --git a/clutter/clutter-colorize-effect.c b/clutter/clutter-colorize-effect.c new file mode 100644 index 0000000..e229ee2 --- /dev/null +++ b/clutter/clutter-colorize-effect.c @@ -0,0 +1,290 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-desaturate-effect + * @short_description: A desaturation effect + * @see_also: #ClutterEffect, #ClutterOffscreenEffect + * + * #ClutterColorizeEffect is a sub-class of #ClutterEffect that + * colorizes an actor with the given tint. + * + * #ClutterColorizeEffect uses the programmable pipeline of the GPU + * so it is only available on graphics hardware that supports this + * feature. + * + * #ClutterColorizeEffect is available since Clutter 1.4 + */ + +#define CLUTTER_COLORIZE_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_COLORIZE_EFFECT, ClutterColorizeEffectClass)) +#define CLUTTER_IS_COLORIZE_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_COLORIZE_EFFECT)) +#define CLUTTER_COLORIZE_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_COLORIZE_EFFECT, ClutterColorizeEffectClass)) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-colorize-effect.h" + +#include "cogl/cogl.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" +#include "clutter-shader-effect.h" + +typedef struct _ClutterColorizeEffectClass ClutterColorizeEffectClass; + +struct _ClutterColorizeEffect +{ + ClutterShaderEffect parent_instance; + + /* a back pointer to our actor, so that we can query it */ + ClutterActor *actor; + + /* the tint of the colorization */ + ClutterColor tint; + + guint source_set : 1; +}; + +struct _ClutterColorizeEffectClass +{ + ClutterShaderEffectClass parent_class; +}; + +/* the magic gray vec3 has been taken from the NTSC conversion weights + * as defined by: + * + * "OpenGL Superbible, 4th Edition" + * -- Richard S. Wright Jr, Benjamin Lipchak, Nicholas Haemel + * Addison-Wesley + */ +static const gchar *colorize_glsl_shader = +"uniform sampler2D tex;\n" +"uniform vec3 tint;\n" +"\n" +"void main ()\n" +"{\n" +" vec4 color = gl_Color * texture2D (tex, vec2 (gl_TexCoord[0].xy));\n" +" float gray = dot (color.rgb, vec3 (0.299, 0.587, 0.114));\n" +" gl_FragColor = vec4 (gray * tint, color.a);\n" +"}\n"; + +/* a lame sepia */ +static const ClutterColor default_tint = { 255, 204, 153, 255 }; + +enum +{ + PROP_0, + + PROP_TINT +}; + +G_DEFINE_TYPE (ClutterColorizeEffect, + clutter_colorize_effect, + CLUTTER_TYPE_SHADER_EFFECT); + +static gboolean +clutter_colorize_effect_pre_paint (ClutterEffect *effect) +{ + ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect); + ClutterShaderEffect *shader_effect; + ClutterEffectClass *parent_class; + float tint_r, tint_g, tint_b; + + shader_effect = CLUTTER_SHADER_EFFECT (effect); + if (!self->source_set) + { + CoglHandle shader = clutter_shader_effect_get_shader (shader_effect); + + if (shader == COGL_INVALID_HANDLE) + return FALSE; + + cogl_shader_source (shader, colorize_glsl_shader); + self->source_set = TRUE; + } + + /* we want normalized values here */ + tint_r = self->tint.red / 255.0f; + tint_g = self->tint.green / 255.0f; + tint_b = self->tint.blue / 255.0f; + + /* bind the uniforms to the factor property */ + clutter_shader_effect_set_uniform (shader_effect, + "tex", + G_TYPE_INT, 1, + 0); + clutter_shader_effect_set_uniform (shader_effect, + "tint", + G_TYPE_FLOAT, 3, + tint_r, + tint_g, + tint_b); + + parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class); + return parent_class->pre_paint (effect); +} + +static void +clutter_colorize_effect_finalize (GObject *gobject) +{ + G_OBJECT_CLASS (clutter_colorize_effect_parent_class)->finalize (gobject); +} + +static void +clutter_colorize_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterColorizeEffect *effect = CLUTTER_COLORIZE_EFFECT (gobject); + + switch (prop_id) + { + case PROP_TINT: + clutter_colorize_effect_set_tint (effect, + clutter_value_get_color (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_colorize_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterColorizeEffect *effect = CLUTTER_COLORIZE_EFFECT (gobject); + + switch (prop_id) + { + case PROP_TINT: + clutter_value_set_color (value, &effect->tint); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass) +{ + ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + effect_class->pre_paint = clutter_colorize_effect_pre_paint; + + gobject_class->set_property = clutter_colorize_effect_set_property; + gobject_class->get_property = clutter_colorize_effect_get_property; + gobject_class->finalize = clutter_colorize_effect_finalize; + + /** + * ClutterColorizeEffect:tint: + * + * The tint to apply to the actor + * + * Since: 1.4 + */ + pspec = clutter_param_spec_color ("tint", + "Tint", + "The tint to apply", + &default_tint, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_TINT, pspec); +} + +static void +clutter_colorize_effect_init (ClutterColorizeEffect *self) +{ + self->tint = default_tint; +} + +/** + * clutter_colorize_effect_new: + * @tint: the color to be used + * + * Creates a new #ClutterColorizeEffect to be used with + * clutter_actor_set_effect() + * + * Return value: the newly created #ClutterColorizeEffect or %NULL + * + * Since: 1.4 + */ +ClutterEffect * +clutter_colorize_effect_new (const ClutterColor *tint) +{ + return g_object_new (CLUTTER_TYPE_COLORIZE_EFFECT, + "tint", tint, + NULL); +} + +/** + * clutter_colorize_effect_set_tint: + * @effect: a #ClutterColorizeEffect + * @tint: the color to be used + * + * Sets the tint to be used when colorizing + * + * Since: 1.4 + */ +void +clutter_colorize_effect_set_tint (ClutterColorizeEffect *effect, + const ClutterColor *tint) +{ + g_return_if_fail (CLUTTER_IS_COLORIZE_EFFECT (effect)); + + effect->tint = *tint; + + if (effect->actor != NULL) + clutter_actor_queue_redraw (effect->actor); + + g_object_notify (G_OBJECT (effect), "tint"); +} + +/** + * clutter_colorize_effect_get_tint: + * @effect: a #ClutterColorizeEffect + * @tint: (out): return location for the color used + * + * Retrieves the tint used by @effect + * + * Since: 1.4 + */ +void +clutter_colorize_effect_get_tint (ClutterColorizeEffect *effect, + ClutterColor *tint) +{ + g_return_if_fail (CLUTTER_IS_COLORIZE_EFFECT (effect)); + g_return_if_fail (tint != NULL); + + *tint = effect->tint; +} diff --git a/clutter/clutter-colorize-effect.h b/clutter/clutter-colorize-effect.h new file mode 100644 index 0000000..6942f82 --- /dev/null +++ b/clutter/clutter-colorize-effect.h @@ -0,0 +1,62 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_COLORIZE_EFFECT_H__ +#define __CLUTTER_COLORIZE_EFFECT_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_COLORIZE_EFFECT (clutter_colorize_effect_get_type ()) +#define CLUTTER_COLORIZE_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_COLORIZE_EFFECT, ClutterColorizeEffect)) +#define CLUTTER_IS_COLORIZE_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_COLORIZE_EFFECT)) + +/** + * ClutterColorizeEffect: + * + * ClutterColorizeEffect is an opaque structure + * whose members cannot be directly accessed + * + * SinceL 1.4 + */ +typedef struct _ClutterColorizeEffect ClutterColorizeEffect; + +GType clutter_colorize_effect_get_type (void) G_GNUC_CONST; + +ClutterEffect *clutter_colorize_effect_new (const ClutterColor *tint); + +void clutter_colorize_effect_set_tint (ClutterColorizeEffect *effect, + const ClutterColor *tint); +void clutter_colorize_effect_get_tint (ClutterColorizeEffect *effect, + ClutterColor *tint); + +G_END_DECLS + +#endif /* __CLUTTER_COLORIZE_EFFECT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index e6a8da6..0b948af 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -57,6 +57,7 @@ #include "clutter-click-action.h" #include "clutter-clone.h" #include "clutter-color.h" +#include "clutter-colorize-effect.h" #include "clutter-constraint.h" #include "clutter-container.h" #include "clutter-desaturate-effect.h" -- 2.7.4