[tests] Adds an interactive unit test for multi-texturing
This simply gives an example of blending a red o-hand logo with an alpha mask and a changing light map.
This commit is contained in:
parent
ea643ca0f8
commit
fc7a86fd0d
@ -1,5 +1,8 @@
|
||||
|
||||
EXTRA_DIST = \
|
||||
redhand.png \
|
||||
redhand_alpha.png \
|
||||
light0.png \
|
||||
light1.png \
|
||||
test-script.json
|
||||
|
||||
|
BIN
tests/data/light0.png
Normal file
BIN
tests/data/light0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
tests/data/light1.png
Normal file
BIN
tests/data/light1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
tests/data/redhand_alpha.png
Normal file
BIN
tests/data/redhand_alpha.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
@ -31,6 +31,7 @@ UNIT_TESTS = \
|
||||
test-cogl-tex-getset.c \
|
||||
test-cogl-offscreen.c \
|
||||
test-cogl-tex-polygon.c \
|
||||
test-cogl-multi-texture.c \
|
||||
test-stage-read-pixels.c \
|
||||
test-random-text.c \
|
||||
test-clip.c \
|
||||
@ -51,6 +52,12 @@ test-script.json:
|
||||
ln -sf $(top_srcdir)/tests/data/test-script.json
|
||||
redhand.png:
|
||||
ln -sf $(top_srcdir)/tests/data/redhand.png
|
||||
redhand_alpha.png:
|
||||
ln -sf $(top_srcdir)/tests/data/redhand_alpha.png
|
||||
light0.png:
|
||||
ln -sf $(top_srcdir)/tests/data/light0.png
|
||||
light1.png:
|
||||
ln -sf $(top_srcdir)/tests/data/light1.png
|
||||
|
||||
# For convenience, this provides a way to easily run individual unit tests:
|
||||
.PHONY: wrappers
|
||||
@ -62,7 +69,7 @@ wrappers: test-interactive$(EXEEXT)
|
||||
|
||||
# NB: BUILT_SOURCES here a misnomer. We aren't building source, just inserting
|
||||
# a phony rule that will generate symlink scripts for running individual tests
|
||||
BUILT_SOURCES = wrappers redhand.png test-script.json
|
||||
BUILT_SOURCES = wrappers redhand.png redhand_alpha.png light0.png light1.png test-script.json
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/ -I$(top_srcdir)/clutter -I$(top_builddir)/clutter
|
||||
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
||||
|
250
tests/interactive/test-cogl-multi-texture.c
Normal file
250
tests/interactive/test-cogl-multi-texture.c
Normal file
@ -0,0 +1,250 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#define TIMELINE_FRAME_COUNT 200
|
||||
|
||||
typedef struct _MultiTextureState
|
||||
{
|
||||
ClutterActor *group;
|
||||
CoglHandle multi_tex;
|
||||
CoglHandle alpha_tex;
|
||||
CoglHandle redhand_tex;
|
||||
CoglHandle light_tex0;
|
||||
CoglHandle light_tex1;
|
||||
ClutterFixed *tex_coords;
|
||||
|
||||
/* For handling light switching */
|
||||
guint last_light_change;
|
||||
gboolean light_on;
|
||||
|
||||
/* For handling texture coord sliding */
|
||||
guint last_frame_no;
|
||||
gint light_x_dir;
|
||||
gint light_y_dir;
|
||||
gint light_x_pos;
|
||||
gint light_y_pos;
|
||||
|
||||
} MultiTextureState;
|
||||
|
||||
|
||||
static void
|
||||
frame_cb (ClutterTimeline *timeline,
|
||||
gint frame_no,
|
||||
gpointer data)
|
||||
{
|
||||
MultiTextureState *state = data;
|
||||
ClutterFixed *tex_coords = &state->tex_coords[8];
|
||||
int prev_frame_delta;
|
||||
int light_duration;
|
||||
|
||||
light_duration = frame_no - state->last_light_change;
|
||||
if (light_duration < 0)
|
||||
light_duration += TIMELINE_FRAME_COUNT;
|
||||
|
||||
if (light_duration > 10)
|
||||
{
|
||||
if (state->light_on)
|
||||
{
|
||||
cogl_multi_texture_layer_set_texture (state->multi_tex,
|
||||
2,
|
||||
state->light_tex1);
|
||||
state->light_on = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_multi_texture_layer_set_texture (state->multi_tex,
|
||||
2,
|
||||
state->light_tex0);
|
||||
state->light_on = TRUE;
|
||||
}
|
||||
state->last_light_change = frame_no;
|
||||
}
|
||||
|
||||
/* slide the texture coordinates */
|
||||
|
||||
/* This is worked out as if the texture has a virtual resolution
|
||||
* of TIMELINE_FRAME_COUNT x TIMELINE_FRAME_COUNT.
|
||||
*
|
||||
* We are always showing an apature of the texture that is
|
||||
* (TIMELINE_FRAME_COUNT/2) x (TIMELINE_FRAME_COUNT/2)
|
||||
*
|
||||
* To remain within the texture we don't let the tx1, ty1 positions
|
||||
* go past ((TIMELINE_FRAME_COUNT/2), (TIMELINE_FRAME_COUNT/2))
|
||||
*/
|
||||
prev_frame_delta = frame_no - state->last_frame_no;
|
||||
if (prev_frame_delta < 0)
|
||||
prev_frame_delta += TIMELINE_FRAME_COUNT;
|
||||
|
||||
state->light_x_pos += prev_frame_delta * state->light_x_dir;
|
||||
if (state->light_x_pos > TIMELINE_FRAME_COUNT/2)
|
||||
{
|
||||
state->light_x_pos = TIMELINE_FRAME_COUNT/2;
|
||||
state->light_x_dir = -state->light_x_dir;
|
||||
}
|
||||
else if (state->light_x_pos < 0)
|
||||
{
|
||||
state->light_x_pos = 0;
|
||||
state->light_x_dir = 1;
|
||||
}
|
||||
|
||||
state->light_y_pos += prev_frame_delta * state->light_y_dir;
|
||||
if (state->light_y_pos > TIMELINE_FRAME_COUNT/2)
|
||||
{
|
||||
state->light_y_pos = TIMELINE_FRAME_COUNT/2;
|
||||
state->light_y_dir = -state->light_y_dir;
|
||||
}
|
||||
else if (state->light_y_pos < 0)
|
||||
{
|
||||
state->light_y_pos = 0;
|
||||
state->light_y_dir = 1;
|
||||
}
|
||||
|
||||
#define CI_F CLUTTER_INT_TO_FIXED
|
||||
tex_coords[0] = (CI_F(1)/TIMELINE_FRAME_COUNT) * state->light_x_pos;
|
||||
tex_coords[1] = (CI_F(1)/TIMELINE_FRAME_COUNT) * state->light_y_pos;
|
||||
tex_coords[2] = tex_coords[0] + CI_F(1)/2;
|
||||
tex_coords[3] = tex_coords[1] + CI_F(1)/2;
|
||||
#undef CI_F
|
||||
|
||||
state->last_frame_no = frame_no;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
multi_texture_paint (ClutterActor *actor, gpointer data)
|
||||
{
|
||||
MultiTextureState *state = data;
|
||||
|
||||
cogl_multi_texture_rectangle (state->multi_tex,
|
||||
CLUTTER_INT_TO_FIXED(0),
|
||||
CLUTTER_INT_TO_FIXED(0),
|
||||
CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
|
||||
CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
|
||||
state->tex_coords);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_multi_texture_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
ClutterAlpha *alpha;
|
||||
ClutterBehaviour *r_behave;
|
||||
ClutterActor *stage;
|
||||
ClutterColor stage_color = { 0x15, 0x93, 0x15, 0xff };
|
||||
MultiTextureState *state = g_new0 (MultiTextureState, 1);
|
||||
CoglHandle layer;
|
||||
ClutterGeometry geom;
|
||||
ClutterFixed tex_coords[] =
|
||||
{
|
||||
/* tx1 ty1 tx2 ty2 */
|
||||
0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1),
|
||||
0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1),
|
||||
0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1)
|
||||
};
|
||||
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_actor_get_geometry (stage, &geom);
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage),
|
||||
&stage_color);
|
||||
|
||||
/* We create a non-descript actor that we know doesn't have a
|
||||
* default paint handler, so that we can easily control
|
||||
* painting in a paint signal handler, without having to
|
||||
* sub-class anything etc. */
|
||||
state->group = clutter_group_new ();
|
||||
clutter_actor_set_position (state->group, geom.width/2, geom.height/2);
|
||||
g_signal_connect (state->group, "paint",
|
||||
G_CALLBACK(multi_texture_paint), state);
|
||||
|
||||
state->alpha_tex =
|
||||
cogl_texture_new_from_file ("./redhand_alpha.png",
|
||||
-1, /* disable slicing */
|
||||
TRUE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
state->redhand_tex =
|
||||
cogl_texture_new_from_file ("./redhand.png",
|
||||
-1, /* disable slicing */
|
||||
TRUE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
state->light_tex0 =
|
||||
cogl_texture_new_from_file ("./light0.png",
|
||||
-1, /* disable slicing */
|
||||
TRUE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
state->light_tex1 =
|
||||
cogl_texture_new_from_file ("./light1.png",
|
||||
-1, /* disable slicing */
|
||||
TRUE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
|
||||
state->multi_tex = cogl_multi_texture_new ();
|
||||
|
||||
cogl_multi_texture_layer_set_texture (state->multi_tex, 0,
|
||||
state->alpha_tex);
|
||||
cogl_multi_texture_layer_set_texture (state->multi_tex, 1,
|
||||
state->redhand_tex);
|
||||
cogl_multi_texture_layer_set_texture (state->multi_tex, 2,
|
||||
state->light_tex0);
|
||||
|
||||
state->tex_coords = tex_coords;
|
||||
|
||||
/* pick a random starting direction */
|
||||
state->light_x_dir = rand() % 5;
|
||||
state->light_y_dir = rand() % 5;
|
||||
|
||||
clutter_actor_set_anchor_point (state->group, 86, 125);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER(stage),
|
||||
state->group);
|
||||
|
||||
|
||||
timeline = clutter_timeline_new (TIMELINE_FRAME_COUNT, 26); /* num frames, fps */
|
||||
g_object_set (timeline, "loop", TRUE, NULL);
|
||||
|
||||
g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), state);
|
||||
|
||||
/* Set an alpha func to power behaviour - ramp is constant rise/fall */
|
||||
alpha = clutter_alpha_new_for_mode (CLUTTER_LINEAR);
|
||||
clutter_alpha_set_timeline (alpha, timeline);
|
||||
|
||||
/* Create a behaviour for that alpha */
|
||||
r_behave = clutter_behaviour_rotate_new (alpha,
|
||||
CLUTTER_Y_AXIS,
|
||||
CLUTTER_ROTATE_CW,
|
||||
0.0, 360.0);
|
||||
|
||||
/* Apply it to our actor */
|
||||
clutter_behaviour_apply (r_behave, state->group);
|
||||
|
||||
/* start the timeline and thus the animations */
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main();
|
||||
|
||||
cogl_multi_texture_unref (state->multi_tex);
|
||||
cogl_texture_unref (state->alpha_tex);
|
||||
cogl_texture_unref (state->redhand_tex);
|
||||
cogl_texture_unref (state->light_tex0);
|
||||
cogl_texture_unref (state->light_tex1);
|
||||
g_free (state);
|
||||
|
||||
g_object_unref (r_behave);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user