/usr/share/gtk-doc/html/clutter-cookbook/textures-reflection.html is in libclutter-1.0-doc 1.20.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | <html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>6. Creating a reflection of a texture</title><link rel="stylesheet" type="text/css" href="style.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="The Clutter Cookbook"><link rel="up" href="textures.html" title="Chapter 4. Textures"><link rel="prev" href="textures-sub-textures.html" title="5. Creating sub-textures from an existing texture"><link rel="next" href="textures-crossfade.html" title="7. Cross-fading between two images"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6. Creating a reflection of a texture</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="textures-sub-textures.html">Prev</a> </td><th width="60%" align="center">Chapter 4. Textures</th><td width="20%" align="right"> <a accesskey="n" href="textures-crossfade.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="textures-reflection"></a>6. Creating a reflection of a texture</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp73308608"></a>6.1. Problem</h3></div></div></div><p>You want to create the reflection of a texture.</p><p>The reflection is going to be positioned below the original
texture, and is going to fade out as if the original was placed on
a glassy surface.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp73310512"></a>6.2. Solution</h3></div></div></div><p>You can use a ClutterClone actor and override its paint
implementation with a custom one:</p><div class="informalexample"><pre class="programlisting">static void
_clone_paint_cb (ClutterActor *actor)
{
/* ... */
/* get the Cogl material of the source texture */
material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (source));
/* get the size of the actor, which will be used to size the reflection */
clutter_actor_get_allocation_box (actor, &box);
clutter_actor_box_get_size (&box, &width, &height);
/* get the composite opacity of the actor */
opacity = clutter_actor_get_paint_opacity (actor);
/* figure out the two colors for the reflection: the first is
* full color and the second is the same, but at 0 opacity
*/
cogl_color_init_from_4f (&color_1, 1.0, 1.0, 1.0, opacity / 255.);
cogl_color_premultiply (&color_1);
cogl_color_init_from_4f (&color_2, 1.0, 1.0, 1.0, 0.0);
cogl_color_premultiply (&color_2);
/* describe the four vertices of the quad; since it has
* to be a reflection, we need to invert it as well
*/
vertices[0].x = 0; vertices[0].y = 0; vertices[0].z = 0;
vertices[0].tx = 0.0; vertices[0].ty = 1.0;
vertices[0].color = color_1;
vertices[1].x = width; vertices[1].y = 0; vertices[1].z = 0;
vertices[1].tx = 1.0; vertices[1].ty = 1.0;
vertices[1].color = color_1;
vertices[2].x = width; vertices[2].y = height; vertices[2].z = 0;
vertices[2].tx = 1.0; vertices[2].ty = 0.0;
vertices[2].color = color_2;
vertices[3].x = 0; vertices[3].y = height; vertices[3].z = 0;
vertices[3].tx = 0.0; vertices[3].ty = 0.0;
vertices[3].color = color_2;
/* paint the same texture but with a different geometry */
cogl_set_source (material);
cogl_polygon (vertices, 4, TRUE);
/* ... */
}
int
main (int argc, char *argv[])
{
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
/* ... get stage etc. */
ClutterActor *texture;
GError *error = NULL;
texture = clutter_texture_new ();
/* load the image from a file */
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
image_path,
&error);
ClutterActor *clone;
clone = clutter_clone_new (texture);
g_signal_connect (clone,
"paint",
G_CALLBACK (_clone_paint_cb),
NULL);
/* ... clutter_main () etc. */
}</pre></div><div class="screenshot"><div class="mediaobject"><img src="images/textures-reflection.png" alt="A texture and its reflection below"></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp73318480"></a>6.3. Discussion</h3></div></div></div><p>The essence of painting a reflection of a texture lies in reusing
the same material used by the original. This not only allows painting
always an up to date version of the original, but it also saves
resources.</p><p>In the code example above we take the <span class="type">CoglMaterial</span>
out of the source <span class="type">ClutterTexture</span> and we ask the Cogl
pipeline to paint it by using <code class="function">cogl_set_source()</code>. The
main difference between this code and the equivalent code inside the
<span class="type">ClutterTexture</span> <code class="function">paint()</code> implementation
is that we also specify the texture vertices and their color by using the
<span class="type">CoglTextureVertex</span> structure and the
<code class="function">cogl_polygon()</code> function.</p><p>The <span class="type">CoglTextureVertex</span> structure contains three fields
for the position of the vertex in 3D space:</p><div class="informalexample"><pre class="programlisting">typedef struct _CoglTextureVertex {
float x;
float y;
float z;
...</pre></div><p>It also contains the normalized texture coordinate (also known as
texture element, or <span class="emphasis"><em>texel</em></span>):</p><div class="informalexample"><pre class="programlisting"> ...
float tx;
float ty;
...</pre></div><p>And, finally, the color of the vertex, expressed as a
<span class="type">CoglColor</span>:</p><div class="informalexample"><pre class="programlisting"> ...
CoglColor color;
} CoglTextureVertex;</pre></div><p>The example code sets the position of the vertices in clockwise
order starting from the top left corner, and sets the coordinate of the
texels in counter-clockwise order, starting with the bottom left corner.
This makes sure that the copy of the original texture appears as being
flipped vertically.</p><p>The gradual fading out to the background color is done by setting
the color of the top vertices to be fully opaque, and the color of the
bottom ones to be fully transparent; GL will then automatically create a
gradient that will be applied when painting the material.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The color values must be pre-multiplied with their alpha
component, otherwise the bleding will not be correct. You can either
multiply the values by yourself when creating the color or, better yet,
use the <code class="function">cogl_color_premultiply()</code> that Cogl provides
for this operation.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp73333552"></a>6.4. Full example</h3></div></div></div><div class="example"><a name="textures-reflection-example"></a><p class="title"><b>Example 4.3. Creating a glassy reflection of a texture</b></p><div class="example-contents"><pre class="programlisting"> #include <stdlib.h>
#include <clutter/clutter.h>
/* pixels between the source and its reflection */
#define V_PADDING 4
static void
_clone_paint_cb (ClutterActor *actor)
{
ClutterActor *source;
ClutterActorBox box;
CoglHandle material;
gfloat width, height;
guint8 opacity;
CoglColor color_1, color_2;
CoglTextureVertex vertices[4];
/* if we don't have a source actor, don't paint */
source = clutter_clone_get_source (CLUTTER_CLONE (actor));
if (source == NULL)
goto out;
/* if the source texture does not have any content, don't paint */
material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (source));
if (material == NULL)
goto out;
/* get the size of the reflection */
clutter_actor_get_allocation_box (actor, &box);
clutter_actor_box_get_size (&box, &width, &height);
/* get the composite opacity of the actor */
opacity = clutter_actor_get_paint_opacity (actor);
/* figure out the two colors for the reflection: the first is
* full color and the second is the same, but at 0 opacity
*/
cogl_color_init_from_4f (&color_1, 1.0, 1.0, 1.0, opacity / 255.);
cogl_color_premultiply (&color_1);
cogl_color_init_from_4f (&color_2, 1.0, 1.0, 1.0, 0.0);
cogl_color_premultiply (&color_2);
/* now describe the four vertices of the quad; since it has
* to be a reflection, we need to invert it as well
*/
vertices[0].x = 0; vertices[0].y = 0; vertices[0].z = 0;
vertices[0].tx = 0.0; vertices[0].ty = 1.0;
vertices[0].color = color_1;
vertices[1].x = width; vertices[1].y = 0; vertices[1].z = 0;
vertices[1].tx = 1.0; vertices[1].ty = 1.0;
vertices[1].color = color_1;
vertices[2].x = width; vertices[2].y = height; vertices[2].z = 0;
vertices[2].tx = 1.0; vertices[2].ty = 0.0;
vertices[2].color = color_2;
vertices[3].x = 0; vertices[3].y = height; vertices[3].z = 0;
vertices[3].tx = 0.0; vertices[3].ty = 0.0;
vertices[3].color = color_2;
/* paint the same texture but with a different geometry */
cogl_set_source (material);
cogl_polygon (vertices, 4, TRUE);
out:
/* prevent the default clone handler from running */
g_signal_stop_emission_by_name (actor, "paint");
}
int
main (int argc, char *argv[])
{
ClutterActor *stage;
ClutterActor *texture;
GError *error = NULL;
ClutterActor *clone;
gfloat y_offset;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
stage = clutter_stage_new ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Reflection");
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
texture = clutter_texture_new ();
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
"redhand.png",
&error);
clutter_actor_add_constraint (texture, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
clutter_actor_add_constraint (texture, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.2));
y_offset = clutter_actor_get_height (texture) + V_PADDING;
clone = clutter_clone_new (texture);
clutter_actor_add_constraint (clone, clutter_bind_constraint_new (texture, CLUTTER_BIND_X, 0.0));
clutter_actor_add_constraint (clone, clutter_bind_constraint_new (texture, CLUTTER_BIND_Y, y_offset));
g_signal_connect (clone,
"paint",
G_CALLBACK (_clone_paint_cb),
NULL);
clutter_container_add (CLUTTER_CONTAINER (stage), texture, clone, NULL);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}
</pre></div></div><br class="example-break"></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="textures-sub-textures.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="textures.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="textures-crossfade.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Creating sub-textures from an existing texture </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 7. Cross-fading between two images</td></tr></table></div></body></html>
|