From 99acb8e9c10db23af5a83a3b94d409bcbe6417a8 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 21 Nov 2007 11:55:26 +0000 Subject: [PATCH] 2007-11-21 Emmanuele Bassi * clutter/cogl/cogl.h: Add cogl_fog_set() abstracting the glFog() functions and enabling the GL_FOG flag. * clutter/cogl/gl/cogl.c: Add GL implementation of cogl_fog_set(). * clutter/cogl/gles/cogl.c: Add GL/ES implementation of cogl_fog_set(). * clutter.symbols: Add new symbols. * clutter/clutter-stage.h: Add API to enable depth cueing on the stage using a linear GL fog, and to set the parameters for it (#637). * clutter/clutter-stage.c (clutter_stage_paint): Enable the GL fog if the ClutterStage:use-fog property is true. * tests/test-depth.c: Test the new stage API. --- ChangeLog | 21 ++ clutter.symbols | 6 + clutter/clutter-stage.c | 310 ++++++++++++++++++++++++----- clutter/clutter-stage.h | 55 +++-- clutter/cogl/cogl.h | 6 + clutter/cogl/gl/cogl.c | 56 +++++- clutter/cogl/gles/cogl.c | 32 ++- doc/reference/ChangeLog | 4 + doc/reference/clutter-sections.txt | 15 +- tests/test-depth.c | 33 +-- 10 files changed, 451 insertions(+), 87 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5c9c87d8b..531ddfcb0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2007-11-21 Emmanuele Bassi + + * clutter/cogl/cogl.h: Add cogl_fog_set() abstracting the + glFog() functions and enabling the GL_FOG flag. + + * clutter/cogl/gl/cogl.c: Add GL implementation of cogl_fog_set(). + + * clutter/cogl/gles/cogl.c: Add GL/ES implementation of + cogl_fog_set(). + + * clutter.symbols: Add new symbols. + + * clutter/clutter-stage.h: Add API to enable depth cueing on + the stage using a linear GL fog, and to set the parameters + for it (#637). + + * clutter/clutter-stage.c (clutter_stage_paint): Enable the + GL fog if the ClutterStage:use-fog property is true. + + * tests/test-depth.c: Test the new stage API. + 2007-11-20 Øyvind Kolås * clutter/clutter-main.c: (event_click_count_generate): generalized diff --git a/clutter.symbols b/clutter.symbols index 7a5ef0dbf..67e4296cf 100644 --- a/clutter.symbols +++ b/clutter.symbols @@ -404,6 +404,12 @@ clutter_stage_get_title clutter_stage_set_user_resizable clutter_stage_get_user_resizable clutter_stage_set_key_focus +clutter_stage_set_use_fog +clutter_stage_get_use_fog +clutter_stage_set_fog +clutter_stage_get_fog +clutter_stage_set_fogx +clutter_stage_get_fogx clutter_texture_error_quark clutter_texture_get_type clutter_texture_new diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index e4eefed36..38b637971 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -57,11 +57,13 @@ struct _ClutterStagePrivate { ClutterColor color; ClutterPerspective perspective; + ClutterFog fog; guint is_fullscreen : 1; guint is_offscreen : 1; guint is_cursor_visible : 1; guint is_user_resizable : 1; + guint use_fog : 1; gchar *title; ClutterActor *key_focused_actor; @@ -77,7 +79,8 @@ enum PROP_CURSOR_VISIBLE, PROP_PERSPECTIVE, PROP_TITLE, - PROP_USER_RESIZE + PROP_USER_RESIZE, + PROP_USE_FOG }; enum @@ -98,6 +101,14 @@ clutter_stage_paint (ClutterActor *self) cogl_paint_init (&priv->color); + if (priv->use_fog) + { + cogl_fog_set (&priv->color, + priv->fog.density, + priv->fog.z_near, + priv->fog.z_far); + } + CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self); } @@ -169,6 +180,9 @@ clutter_stage_set_property (GObject *object, case PROP_USER_RESIZE: clutter_stage_set_user_resizable (stage, g_value_get_boolean (value)); break; + case PROP_USE_FOG: + clutter_stage_set_use_fog (stage, g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -214,6 +228,9 @@ clutter_stage_get_property (GObject *object, case PROP_USER_RESIZE: g_value_set_boolean (value, priv->is_user_resizable); break; + case PROP_USE_FOG: + g_value_set_boolean (value, priv->use_fog); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -309,6 +326,22 @@ clutter_stage_class_init (ClutterStageClass *klass) "Stage Title", NULL, CLUTTER_PARAM_READWRITE)); + /** + * ClutterStage:use-fog: + * + * Whether the stage should use a linear GL "fog" for creating the + * depth-cueing effect to enhance the perception of depth by fading + * actors farther from the viewpoing. + * + * Since: 0.6 + */ + g_object_class_install_property (gobject_class, + PROP_USE_FOG, + g_param_spec_boolean ("use-fog", + "Use Fog", + "Whether to enable depth cueing", + FALSE, + CLUTTER_PARAM_READWRITE)); /** * ClutterStage::fullscreen @@ -326,7 +359,6 @@ clutter_stage_class_init (ClutterStageClass *klass) NULL, NULL, clutter_marshal_VOID__VOID, G_TYPE_NONE, 0); - /** * ClutterStage::unfullscreen * @stage: the stage which has left a fullscreen state. @@ -344,8 +376,6 @@ clutter_stage_class_init (ClutterStageClass *klass) NULL, NULL, clutter_marshal_VOID__VOID, G_TYPE_NONE, 0); - - /** * ClutterStage::activate * @stage: the stage which was activated @@ -363,7 +393,6 @@ clutter_stage_class_init (ClutterStageClass *klass) NULL, NULL, clutter_marshal_VOID__VOID, G_TYPE_NONE, 0); - /** * ClutterStage::deactivate * @stage: the stage which was deactivated @@ -399,6 +428,7 @@ clutter_stage_init (ClutterStage *self) priv->is_fullscreen = FALSE; priv->is_user_resizable = FALSE; priv->is_cursor_visible = TRUE; + priv->use_fog = FALSE; priv->color.red = 0xff; priv->color.green = 0xff; @@ -410,6 +440,11 @@ clutter_stage_init (ClutterStage *self) priv->perspective.z_near = CLUTTER_FLOAT_TO_FIXED (0.1); priv->perspective.z_far = CLUTTER_FLOAT_TO_FIXED (100.0); + /* depth cueing */ + priv->fog.density = CLUTTER_FLOAT_TO_FIXED (0.1); + priv->fog.z_near = CLUTTER_FLOAT_TO_FIXED (1.0); + priv->fog.z_far = CLUTTER_FLOAT_TO_FIXED (2.0); + clutter_actor_set_size (CLUTTER_ACTOR (self), 640, 480); clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); clutter_stage_set_key_focus (self, NULL); @@ -460,7 +495,7 @@ clutter_stage_set_color (ClutterStage *stage, priv->color.blue = color->blue; priv->color.alpha = color->alpha; - if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (stage))) + if (CLUTTER_ACTOR_IS_VISIBLE (stage)) clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); g_object_notify (G_OBJECT (stage), "color"); @@ -504,14 +539,13 @@ clutter_stage_set_perspectivex (ClutterStage *stage, ClutterStagePrivate *priv; g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (perspective != NULL); priv = stage->priv; - priv->perspective.fovy = perspective->fovy; - priv->perspective.aspect = perspective->aspect; - priv->perspective.z_near = perspective->z_near; - priv->perspective.z_far = perspective->z_far; - CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES); + priv->perspective = *perspective; + + CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); } /** @@ -525,15 +559,10 @@ void clutter_stage_get_perspectivex (ClutterStage *stage, ClutterPerspective *perspective) { - ClutterStagePrivate *priv; - g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (perspective != NULL); - priv = stage->priv; - perspective->fovy = priv->perspective.fovy; - perspective->aspect = priv->perspective.aspect; - perspective->z_near = priv->perspective.z_near; - perspective->z_far = priv->perspective.z_far; + *perspective = stage->priv->perspective; } /** @@ -560,12 +589,13 @@ clutter_stage_set_perspective (ClutterStage *stage, g_return_if_fail (CLUTTER_IS_STAGE (stage)); priv = stage->priv; + priv->perspective.fovy = CLUTTER_FLOAT_TO_FIXED(fovy); priv->perspective.aspect = CLUTTER_FLOAT_TO_FIXED(aspect); priv->perspective.z_near = CLUTTER_FLOAT_TO_FIXED(z_near); priv->perspective.z_far = CLUTTER_FLOAT_TO_FIXED(z_far); - CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES); + CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); } /** @@ -991,21 +1021,183 @@ clutter_stage_get_key_focus (ClutterStage *stage) return CLUTTER_ACTOR (stage); } +/** + * clutter_stage_get_use_fog: + * @stage: the #ClutterStage + * + * Gets whether the depth cueing effect is enabled on @stage. + * + * Return value: %TRUE if the the depth cueing effect is enabled + * + * Since: 0.6 + */ +gboolean +clutter_stage_get_use_fog (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage->priv->use_fog; +} + +/** + * clutter_stage_set_use_fog: + * @stage: the #ClutterStage + * @fog: %TRUE for enabling the depth cueing effect + * + * Sets whether the depth cueing effect on the stage should be enabled + * or not. + * + * Depth cueing is a 3D effect that makes actors farther away from the + * viewing point less opaque, by fading them with the stage color. + + * The parameters of the GL fog used can be changed using the + * clutter_stage_set_fog() function. + * + * Since: 0.6 + */ +void +clutter_stage_set_use_fog (ClutterStage *stage, + gboolean fog) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (priv->use_fog != fog) + { + priv->use_fog = fog; + + CLUTTER_NOTE (MISC, "%s depth-cueing inside stage", + priv->use_fog ? "enabling" : "disabling"); + + if (CLUTTER_ACTOR_IS_VISIBLE (stage)) + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + g_object_notify (G_OBJECT (stage), "use-fog"); + } +} + +/** + * clutter_stage_get_fog: + * @stage: a #ClutterStage + * @density: return location for the intensity dampening + * @z_near: return location for the starting point of the depth cueing + * @z_far: return location for the ending point of the depth cueing + * + * Retrieves the settings used by the GL fog to create the + * depth cueing effect on the @stage. + * + * Since: 0.6 + */ +void +clutter_stage_get_fog (ClutterStage *stage, + gdouble *density, + gdouble *z_near, + gdouble *z_far) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (density) + *density = CLUTTER_FIXED_TO_FLOAT (priv->fog.density); + if (z_near) + *z_near = CLUTTER_FIXED_TO_FLOAT (priv->fog.z_near); + if (z_far) + *z_far = CLUTTER_FIXED_TO_FLOAT (priv->fog.z_far); +} + +/** + * clutter_stage_set_fog: + * @stage: the #ClutterStage + * @density: density of the intensity dampening + * @z_near: starting point of the depth cueing + * @z_far: ending point of the depth cueing + * + * Sets the GL fog settings used to create the depth cueing effect + * on the @stage. + * + * If the actors are all near the view point you will need a higher @density + * and a smaller interval between @z_near and @z_far. On the other hand, if + * actors are placed far away from the view point you will need a lower + * @density but a bigger interval between @z_near and @z_far. + * + * Since: 0.6 + */ +void +clutter_stage_set_fog (ClutterStage *stage, + gdouble density, + gdouble z_near, + gdouble z_far) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + priv->fog.density = CLUTTER_FLOAT_TO_FIXED (density); + priv->fog.z_near = CLUTTER_FLOAT_TO_FIXED (z_near); + priv->fog.z_far = CLUTTER_FLOAT_TO_FIXED (z_far); + + if (priv->use_fog && CLUTTER_ACTOR_IS_VISIBLE (stage)) + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); +} + +/** + * clutter_stage_set_fogx: + * @stage: the #ClutterStage + * @fog: a #ClutterFog structure + * + * Sets the depth cueing settings for the @stage. This is the fixed point + * version of clutter_stage_set_fog(). + * + * Since: 0.6 + */ +void +clutter_stage_set_fogx (ClutterStage *stage, + ClutterFog *fog) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (fog != NULL); + + priv = stage->priv; + + priv->fog = *fog; + + if (priv->use_fog && CLUTTER_ACTOR_IS_VISIBLE (stage)) + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); +} + +/** + * clutter_stage_get_fogx: + * @stage: the #ClutterStage + * @fog: return location for a #ClutterFog structure + * + * Retrieves the current depth cueing settings from the stage. This is the + * fixed point version of clutter_stage_get_fog(). + * + * Since: 0.6 + */ +void +clutter_stage_get_fogx (ClutterStage *stage, + ClutterFog *fog) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (fog != NULL); + + *fog = stage->priv->fog; +} /*** Perspective boxed type ******/ -/** - * clutter_perspective_copy: - * @perspective: a #ClutterPerspective - * - * Makes a copy of the perspective structure. The result must be - * freed using clutter_perspective_free(). - * - * Return value: an allocated copy of @perspective. - * - * Since: 0.4 - */ -ClutterPerspective * +static ClutterPerspective * clutter_perspective_copy (const ClutterPerspective *perspective) { ClutterPerspective *result; @@ -1018,20 +1210,11 @@ clutter_perspective_copy (const ClutterPerspective *perspective) return result; } -/** - * clutter_perspective_free: - * @perspective: a #ClutterPerspective - * - * Frees a perspective structure created with clutter_perspective_copy(). - * - * Since: 0.4 - */ -void +static void clutter_perspective_free (ClutterPerspective *perspective) { - g_return_if_fail (perspective != NULL); - - g_slice_free (ClutterPerspective, perspective); + if (G_LIKELY (perspective)) + g_slice_free (ClutterPerspective, perspective); } GType @@ -1040,10 +1223,43 @@ clutter_perspective_get_type (void) static GType our_type = 0; if (!our_type) - our_type = g_boxed_type_register_static - ("ClutterPerspective", - (GBoxedCopyFunc) clutter_perspective_copy, - (GBoxedFreeFunc) clutter_perspective_free); + our_type = + g_boxed_type_register_static ("ClutterPerspective", + (GBoxedCopyFunc) clutter_perspective_copy, + (GBoxedFreeFunc) clutter_perspective_free); return our_type; } +static ClutterFog * +clutter_fog_copy (const ClutterFog *fog) +{ + ClutterFog *copy; + + g_return_val_if_fail (fog != NULL, NULL); + + copy = g_slice_new0 (ClutterFog); + *copy = *fog; + + return copy; +} + +static void +clutter_fog_free (ClutterFog *fog) +{ + if (G_LIKELY (fog)) + g_slice_free (ClutterFog, fog); +} + +GType +clutter_fog_get_type (void) +{ + static GType our_type = 0; + + if (G_UNLIKELY (our_type == 0)) + our_type = + g_boxed_type_register_static ("ClutterFog", + (GBoxedCopyFunc) clutter_fog_copy, + (GBoxedFreeFunc) clutter_fog_free); + + return our_type; +} diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index 462fcf110..555591ec2 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -33,8 +33,9 @@ G_BEGIN_DECLS -#define CLUTTER_TYPE_PERSPECTIVE (clutter_perspective_get_type ()) -#define CLUTTER_TYPE_STAGE (clutter_stage_get_type()) +#define CLUTTER_TYPE_PERSPECTIVE (clutter_perspective_get_type ()) +#define CLUTTER_TYPE_FOG (clutter_fog_get_type ()) +#define CLUTTER_TYPE_STAGE (clutter_stage_get_type()) #define CLUTTER_STAGE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ @@ -63,6 +64,8 @@ G_BEGIN_DECLS clutter_actor_get_height (clutter_stage_get_default ()) typedef struct _ClutterPerspective ClutterPerspective; +typedef struct _ClutterFog ClutterFog; + typedef struct _ClutterStage ClutterStage; typedef struct _ClutterStageClass ClutterStageClass; typedef struct _ClutterStagePrivate ClutterStagePrivate; @@ -118,7 +121,7 @@ struct _ClutterStageClass * @z_near: FIXME * @z_far: FIXME * - * Stage perspective definition + * Stage perspective definition. * * Since: 0.4 */ @@ -130,10 +133,26 @@ struct _ClutterPerspective ClutterFixed z_far; }; -GType clutter_perspective_get_type (void) G_GNUC_CONST; -ClutterPerspective *clutter_perspective_copy (const ClutterPerspective *perspective); -void clutter_perspective_free (ClutterPerspective *perspective); +/** + * ClutterFog: + * @density: density of the fog + * @z_near: start point of the depth cueing + * @z_far: end point of the depth cueing + * + * Fog settings used to create the depth cueing effect. This + * structure is useful only when using the fixed point API. + * + * Since: 0.6 + */ +struct _ClutterFog +{ + ClutterFixed density; + ClutterFixed z_near; + ClutterFixed z_far; +}; +GType clutter_perspective_get_type (void) G_GNUC_CONST; +GType clutter_fog_get_type (void) G_GNUC_CONST; GType clutter_stage_get_type (void) G_GNUC_CONST; ClutterActor *clutter_stage_get_default (void); @@ -177,14 +196,26 @@ G_CONST_RETURN gchar *clutter_stage_get_title (ClutterStage *stage); void clutter_stage_set_user_resizable (ClutterStage *stage, gboolean resizable); gboolean clutter_stage_get_user_resizable (ClutterStage *stage); +void clutter_stage_set_use_fog (ClutterStage *stage, + gboolean fog); +gboolean clutter_stage_get_use_fog (ClutterStage *stage); +void clutter_stage_set_fog (ClutterStage *stage, + gdouble density, + gdouble z_near, + gdouble z_far); +void clutter_stage_get_fog (ClutterStage *stage, + gdouble *density, + gdouble *z_near, + gdouble *z_far); +void clutter_stage_set_fogx (ClutterStage *stage, + ClutterFog *fog); +void clutter_stage_get_fogx (ClutterStage *stage, + ClutterFog *fog); /* New experiental calls */ -void -clutter_stage_set_key_focus (ClutterStage *stage, - ClutterActor *actor); - -ClutterActor* -clutter_stage_get_key_focus (ClutterStage *stage); +void clutter_stage_set_key_focus (ClutterStage *stage, + ClutterActor *actor); +ClutterActor * clutter_stage_get_key_focus (ClutterStage *stage); G_END_DECLS diff --git a/clutter/cogl/cogl.h b/clutter/cogl/cogl.h index 80e512e5d..12b23dd53 100644 --- a/clutter/cogl/cogl.h +++ b/clutter/cogl/cogl.h @@ -201,6 +201,12 @@ cogl_get_viewport (ClutterFixed v[4]); void cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha); +void +cogl_fog_set (const ClutterColor *fog_color, + ClutterFixed density, + ClutterFixed z_near, + ClutterFixed z_far); + G_END_DECLS #endif /* __COGL_H__ */ diff --git a/clutter/cogl/gl/cogl.c b/clutter/cogl/gl/cogl.c index c20923447..d96aff61f 100644 --- a/clutter/cogl/gl/cogl.c +++ b/clutter/cogl/gl/cogl.c @@ -165,7 +165,10 @@ cogl_paint_init (const ClutterColor *color) glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDisable (GL_LIGHTING); - glDisable (GL_DEPTH_TEST); + glDisable (GL_FOG); + + glEnable (GL_DEPTH_TEST); + glDepthFunc (GL_LEQUAL); cogl_enable (CGL_ENABLE_BLEND); @@ -234,8 +237,9 @@ cogl_enable (gulong flags) { glEnable (GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - __enable_flags |= CGL_ENABLE_BLEND; + + __enable_flags |= CGL_ENABLE_BLEND; + } } else if (__enable_flags & CGL_ENABLE_BLEND) { @@ -246,21 +250,25 @@ cogl_enable (gulong flags) if (flags & CGL_ENABLE_TEXTURE_2D) { if (!(__enable_flags & CGL_ENABLE_TEXTURE_2D)) - glEnable (GL_TEXTURE_2D); - __enable_flags |= CGL_ENABLE_TEXTURE_2D; + { + glEnable (GL_TEXTURE_2D); + __enable_flags |= CGL_ENABLE_TEXTURE_2D; + } } else if (__enable_flags & CGL_ENABLE_TEXTURE_2D) { glDisable (GL_TEXTURE_2D); - __enable_flags &= ~CGL_ENABLE_TEXTURE_2D; + __enable_flags &= ~CGL_ENABLE_TEXTURE_2D; } #ifdef GL_TEXTURE_RECTANGLE_ARB if (flags & CGL_ENABLE_TEXTURE_RECT) { if (!(__enable_flags & CGL_ENABLE_TEXTURE_RECT)) + { glEnable (GL_TEXTURE_RECTANGLE_ARB); - __enable_flags |= CGL_ENABLE_TEXTURE_RECT; + __enable_flags |= CGL_ENABLE_TEXTURE_RECT; + } } else if (__enable_flags & CGL_ENABLE_TEXTURE_RECT) { @@ -272,14 +280,15 @@ cogl_enable (gulong flags) if (flags & CGL_ENABLE_ALPHA_TEST) { if (!(__enable_flags & CGL_ENABLE_ALPHA_TEST)) - glEnable (GL_ALPHA_TEST); - - __enable_flags |= CGL_ENABLE_ALPHA_TEST; + { + glEnable (GL_ALPHA_TEST); + __enable_flags |= CGL_ENABLE_ALPHA_TEST; + } } else if (__enable_flags & CGL_ENABLE_ALPHA_TEST) { glDisable (GL_ALPHA_TEST); - __enable_flags &= ~CGL_ENABLE_ALPHA_TEST; + __enable_flags &= ~CGL_ENABLE_ALPHA_TEST; } } @@ -712,3 +721,28 @@ cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha) *alpha = value; } } + +void +cogl_fog_set (const ClutterColor *fog_color, + ClutterFixed density, + ClutterFixed start, + ClutterFixed stop) +{ + GLfloat fogColor[4]; + + fogColor[0] = ((float) fog_color->red / 0xff * 1.0); + fogColor[1] = ((float) fog_color->green / 0xff * 1.0); + fogColor[2] = ((float) fog_color->blue / 0xff * 1.0); + fogColor[3] = ((float) fog_color->alpha / 0xff * 1.0); + + glEnable (GL_FOG); + + glFogfv (GL_FOG_COLOR, fogColor); + + glFogi (GL_FOG_MODE, GL_LINEAR); + glHint (GL_FOG_HINT, GL_NICEST); + + glFogf (GL_FOG_DENSITY, CLUTTER_FIXED_TO_FLOAT (density)); + glFogf (GL_FOG_START, CLUTTER_FIXED_TO_FLOAT (start)); + glFogf (GL_FOG_END, CLUTTER_FIXED_TO_FLOAT (stop)); +} diff --git a/clutter/cogl/gles/cogl.c b/clutter/cogl/gles/cogl.c index 172ee122b..c118b6811 100644 --- a/clutter/cogl/gles/cogl.c +++ b/clutter/cogl/gles/cogl.c @@ -115,8 +115,11 @@ cogl_paint_init (const ClutterColor *color) 0xff); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glDisable (GL_LIGHTING); - glDisable (GL_DEPTH_TEST); + glDisable (GL_LIGHTING); + glDisable (GL_FOG); + + glEnable (GL_DEPTH_TEST); + glDepthFunc (GL_LEQUAL); cogl_enable (CGL_ENABLE_BLEND); @@ -602,3 +605,28 @@ cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha) if (alpha) GE( glGetIntegerv(GL_ALPHA_BITS, alpha ) ); } + +void +cogl_fog_set (const ClutterColor *fog_color, + ClutterFixed density, + ClutterFixed z_near, + ClutterFixed z_far) +{ + GLfixed fogColor[4]; + + fogColor[0] = (fog_color->red << 16) / 0xff; + fogColor[1] = (fog_color->green << 16) / 0xff; + fogColor[2] = (fog_color->blue << 16) / 0xff; + fogColor[3] = (fog_color->alpha << 16) / 0xff; + + glEnable (GL_FOG); + + glFogxv (GL_FOG_COLOR, fogColor); + + glFogi (GL_FOG_MODE, GL_LINEAR); + glHint (GL_FOG_HINT, GL_NICEST); + + glFogx (GL_FOG_DENSITY, (GLfixed) density); + glFogx (GL_FOG_START, (GLfixed) z_near); + glFogx (GL_FOG_STOP, (GLfixed) z_far); +} diff --git a/doc/reference/ChangeLog b/doc/reference/ChangeLog index 785ac6227..3ff2735bb 100644 --- a/doc/reference/ChangeLog +++ b/doc/reference/ChangeLog @@ -1,3 +1,7 @@ +2007-11-21 Emmanuele Bassi + + * clutter-sections.txt: Add the new ClutterStage fog API. + 2007-11-19 Emmanuele Bassi * clutter-sections.txt: Add ClutterScore symbols and diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index 0c87d118d..8e48faf8c 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -456,13 +456,11 @@ clutter_stage_hide_cursor clutter_stage_get_actor_at_pos clutter_stage_snapshot clutter_stage_event -clutter_stage_get_key_focus clutter_stage_set_key_focus +clutter_stage_get_key_focus ClutterPerspective -clutter_perspective_copy -clutter_perspective_free clutter_stage_set_perspective clutter_stage_set_perspectivex clutter_stage_get_perspective @@ -473,6 +471,16 @@ clutter_stage_set_title clutter_stage_get_title clutter_stage_set_user_resizable clutter_stage_get_user_resizable + + +ClutterFog +clutter_stage_set_use_fog +clutter_stage_get_use_fog +clutter_stage_set_fog +clutter_stage_get_fog +clutter_stage_set_fogx +clutter_stage_get_fogx + CLUTTER_STAGE CLUTTER_IS_STAGE @@ -485,6 +493,7 @@ CLUTTER_TYPE_PERSPECTIVE ClutterStagePrivate clutter_stage_get_type clutter_perspective_get_type +clutter_fog_get_type
diff --git a/tests/test-depth.c b/tests/test-depth.c index 3c713c125..3b338c80d 100644 --- a/tests/test-depth.c +++ b/tests/test-depth.c @@ -12,14 +12,14 @@ timeline_completed (ClutterTimeline *timeline, if (zoom_in) { - depth_start = 100; - depth_end = 0; + depth_start = 0; + depth_end = -500; zoom_in = FALSE; } else { - depth_start = 0; - depth_end = 100; + depth_start = -500; + depth_end = 0; zoom_in = TRUE; } @@ -37,8 +37,9 @@ main (int argc, char *argv[]) { ClutterTimeline *timeline; ClutterActor *stage; - ClutterActor *hand, *label; + ClutterActor *hand, *label, *rect; ClutterColor stage_color = { 0xcc, 0xcc, 0xcc, 0xff }; + ClutterColor rect_color = { 0, 0, 0, 0x88 }; GdkPixbuf *pixbuf; GError *error; @@ -51,22 +52,29 @@ main (int argc, char *argv[]) stage = clutter_stage_get_default (); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + clutter_stage_set_use_fog (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "button-press-event", G_CALLBACK (clutter_main_quit), NULL); + label = clutter_label_new_with_text ("Mono 26", "Clutter"); + clutter_actor_set_position (label, 40, 140); + clutter_actor_show (label); + hand = clutter_texture_new_from_pixbuf (pixbuf); clutter_actor_set_position (hand, 240, 140); clutter_actor_show (hand); - label = clutter_label_new_with_text ("Mono 26", "Clutter"); - clutter_actor_set_position (label, 100, 100); - clutter_actor_show (label); + rect = clutter_rectangle_new_with_color (&rect_color); + clutter_actor_set_position (rect, 440, 140); + clutter_actor_set_size (rect, 200, 200); + clutter_actor_show (rect); - clutter_container_add (CLUTTER_CONTAINER (stage), hand, label, NULL); + clutter_container_add (CLUTTER_CONTAINER (stage), hand, label, rect, NULL); - /* five seconds, at 50 fps */ - timeline = clutter_timeline_new (250, 50); + /* 3 seconds, at 60 fps */ + timeline = clutter_timeline_new (180, 60); g_signal_connect (timeline, "completed", G_CALLBACK (timeline_completed), NULL); @@ -74,9 +82,10 @@ main (int argc, char *argv[]) d_behave = clutter_behaviour_depth_new (clutter_alpha_new_full (timeline, CLUTTER_ALPHA_RAMP_INC, NULL, NULL), - 0, 100); + -500, 0); clutter_behaviour_apply (d_behave, hand); clutter_behaviour_apply (d_behave, label); + clutter_behaviour_apply (d_behave, rect); clutter_actor_show (stage);