mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
Add an interactive test for cogl point sprites
The test draws some fireworks with trailing sparks that fade out. http://bugzilla.openedhand.com/show_bug.cgi?id=2047
This commit is contained in:
parent
ab05f6bfb1
commit
ad6d597445
@ -54,7 +54,8 @@ UNIT_TESTS = \
|
||||
test-drag.c \
|
||||
test-constraints.c \
|
||||
test-scrolling.c \
|
||||
test-bind.c
|
||||
test-bind.c \
|
||||
test-cogl-point-sprites.c
|
||||
|
||||
if X11_TESTS
|
||||
UNIT_TESTS += test-pixmap.c
|
||||
|
280
tests/interactive/test-cogl-point-sprites.c
Normal file
280
tests/interactive/test-cogl-point-sprites.c
Normal file
@ -0,0 +1,280 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <math.h>
|
||||
#include <gmodule.h>
|
||||
#include <string.h>
|
||||
|
||||
#define N_FIREWORKS 32
|
||||
/* Units per second per second */
|
||||
#define GRAVITY -1.5f
|
||||
|
||||
#define N_SPARKS (N_FIREWORKS * 32) /* Must be a power of two */
|
||||
#define TIME_PER_SPARK 0.01f /* in seconds */
|
||||
|
||||
#define TEXTURE_SIZE 32
|
||||
|
||||
typedef struct _Firework Firework;
|
||||
|
||||
struct _Firework
|
||||
{
|
||||
float size;
|
||||
float x, y;
|
||||
float start_x, start_y;
|
||||
ClutterColor color;
|
||||
|
||||
/* Velocities are in units per second */
|
||||
float initial_x_velocity;
|
||||
float initial_y_velocity;
|
||||
|
||||
GTimer *timer;
|
||||
};
|
||||
|
||||
typedef struct _Spark Spark;
|
||||
|
||||
struct _Spark
|
||||
{
|
||||
float x, y;
|
||||
ClutterColor color;
|
||||
ClutterColor base_color;
|
||||
};
|
||||
|
||||
typedef struct _Data Data;
|
||||
|
||||
struct _Data
|
||||
{
|
||||
Firework fireworks[N_FIREWORKS];
|
||||
|
||||
int next_spark_num;
|
||||
Spark sparks[N_SPARKS];
|
||||
GTimer *last_spark_time;
|
||||
|
||||
CoglMaterial *material;
|
||||
};
|
||||
|
||||
static CoglHandle
|
||||
generate_round_texture (void)
|
||||
{
|
||||
guint8 *p, *data;
|
||||
int x, y;
|
||||
CoglHandle tex;
|
||||
|
||||
p = data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4);
|
||||
|
||||
/* Generate a yellow circle which gets transparent towards the edges */
|
||||
for (y = 0; y < TEXTURE_SIZE; y++)
|
||||
for (x = 0; x < TEXTURE_SIZE; x++)
|
||||
{
|
||||
int dx = x - TEXTURE_SIZE / 2;
|
||||
int dy = y - TEXTURE_SIZE / 2;
|
||||
float value = sqrtf (dx * dx + dy * dy) * 255.0 / (TEXTURE_SIZE / 2);
|
||||
if (value > 255.0f)
|
||||
value = 255.0f;
|
||||
value = 255.0f - value;
|
||||
*(p++) = value;
|
||||
*(p++) = value;
|
||||
*(p++) = value;
|
||||
*(p++) = value;
|
||||
}
|
||||
|
||||
tex = cogl_texture_new_from_data (TEXTURE_SIZE, TEXTURE_SIZE,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
TEXTURE_SIZE * 4,
|
||||
data);
|
||||
|
||||
g_free (data);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
static void
|
||||
paint_cb (ClutterActor *stage, Data *data)
|
||||
{
|
||||
CoglMatrix old_matrix, new_matrix;
|
||||
int i;
|
||||
float diff_time;
|
||||
CoglHandle vbo;
|
||||
|
||||
cogl_get_projection_matrix (&old_matrix);
|
||||
/* Use an orthogonal projection from -1 -> 1 in both axes */
|
||||
cogl_matrix_init_identity (&new_matrix);
|
||||
cogl_set_projection_matrix (&new_matrix);
|
||||
|
||||
cogl_push_matrix ();
|
||||
cogl_set_modelview_matrix (&new_matrix);
|
||||
|
||||
/* Update all of the firework's positions */
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
{
|
||||
Firework *firework = data->fireworks + i;
|
||||
|
||||
if ((fabsf (firework->x - firework->start_x) > 2.0f) ||
|
||||
firework->y < -1.0f)
|
||||
{
|
||||
firework->size = g_random_double_range (0.001f, 0.1f);
|
||||
firework->start_x = 1.0f + firework->size;
|
||||
firework->start_y = -1.0f;
|
||||
firework->initial_x_velocity = g_random_double_range (-0.1f, -2.0f);
|
||||
firework->initial_y_velocity = g_random_double_range (0.1f, 4.0f);
|
||||
g_timer_reset (firework->timer);
|
||||
|
||||
/* Pick a random color out of six */
|
||||
if (g_random_boolean ())
|
||||
{
|
||||
memset (&firework->color, 0, sizeof (ClutterColor));
|
||||
((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (&firework->color, 255, sizeof (ClutterColor));
|
||||
((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 0;
|
||||
}
|
||||
firework->color.alpha = 255;
|
||||
|
||||
/* Fire some of the fireworks from the other side */
|
||||
if (g_random_boolean ())
|
||||
{
|
||||
firework->start_x = -firework->start_x;
|
||||
firework->initial_x_velocity = -firework->initial_x_velocity;
|
||||
}
|
||||
}
|
||||
|
||||
diff_time = g_timer_elapsed (firework->timer, NULL);
|
||||
|
||||
firework->x = (firework->start_x +
|
||||
firework->initial_x_velocity * diff_time);
|
||||
|
||||
firework->y = ((firework->initial_y_velocity * diff_time +
|
||||
0.5f * GRAVITY * diff_time * diff_time) +
|
||||
firework->start_y);
|
||||
}
|
||||
|
||||
diff_time = g_timer_elapsed (data->last_spark_time, NULL);
|
||||
if (diff_time < 0.0f || diff_time >= TIME_PER_SPARK)
|
||||
{
|
||||
/* Add a new spark for each firework, overwriting the oldest ones */
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
{
|
||||
Spark *spark = data->sparks + data->next_spark_num;
|
||||
Firework *firework = data->fireworks + i;
|
||||
|
||||
spark->x = (firework->x +
|
||||
g_random_double_range (-firework->size / 2.0f,
|
||||
firework->size / 2.0f));
|
||||
spark->y = (firework->y +
|
||||
g_random_double_range (-firework->size / 2.0f,
|
||||
firework->size / 2.0f));
|
||||
spark->base_color = firework->color;
|
||||
|
||||
data->next_spark_num = (data->next_spark_num + 1) & (N_SPARKS - 1);
|
||||
}
|
||||
|
||||
/* Update the colour of each spark */
|
||||
for (i = 0; i < N_SPARKS; i++)
|
||||
{
|
||||
float color_value;
|
||||
|
||||
/* First spark is the oldest */
|
||||
Spark *spark = data->sparks + ((data->next_spark_num + i)
|
||||
& (N_SPARKS - 1));
|
||||
|
||||
color_value = i / (N_SPARKS - 1.0f);
|
||||
spark->color.red = spark->base_color.red * color_value;
|
||||
spark->color.green = spark->base_color.green * color_value;
|
||||
spark->color.blue = spark->base_color.blue * color_value;
|
||||
spark->color.alpha = 255.0f * color_value;
|
||||
}
|
||||
|
||||
g_timer_reset (data->last_spark_time);
|
||||
}
|
||||
|
||||
vbo = cogl_vertex_buffer_new (N_SPARKS);
|
||||
cogl_vertex_buffer_add (vbo, "gl_Vertex", 2,
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
|
||||
sizeof (Spark),
|
||||
&data->sparks[0].x);
|
||||
cogl_vertex_buffer_add (vbo, "gl_Color", 4,
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, TRUE,
|
||||
sizeof (Spark),
|
||||
&data->sparks[0].color.red);
|
||||
cogl_vertex_buffer_submit (vbo);
|
||||
|
||||
cogl_set_source (data->material);
|
||||
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_POINTS, 0, N_SPARKS);
|
||||
|
||||
cogl_handle_unref (vbo);
|
||||
|
||||
cogl_set_projection_matrix (&old_matrix);
|
||||
cogl_pop_matrix ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_cb (gpointer data)
|
||||
{
|
||||
clutter_actor_queue_redraw (data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_point_sprites_main (int argc, char *argv[])
|
||||
{
|
||||
static const ClutterColor black = { 0, 0, 0, 255 };
|
||||
ClutterActor *stage;
|
||||
CoglHandle tex;
|
||||
Data data;
|
||||
GError *error = NULL;
|
||||
int i;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
data.material = cogl_material_new ();
|
||||
data.last_spark_time = g_timer_new ();
|
||||
|
||||
cogl_material_set_point_size (data.material, TEXTURE_SIZE);
|
||||
|
||||
tex = generate_round_texture ();
|
||||
cogl_material_set_layer (data.material, 0, tex);
|
||||
cogl_handle_unref (tex);
|
||||
|
||||
if (!cogl_material_set_layer_point_sprite_coords_enabled (data.material,
|
||||
0, TRUE,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to enable point sprite coords: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
{
|
||||
data.fireworks[i].x = -FLT_MAX;
|
||||
data.fireworks[i].y = FLT_MAX;
|
||||
data.fireworks[i].size = 0.0f;
|
||||
data.fireworks[i].timer = g_timer_new ();
|
||||
}
|
||||
|
||||
for (i = 0; i < N_SPARKS; i++)
|
||||
{
|
||||
data.sparks[i].x = 2.0f;
|
||||
data.sparks[i].y = 2.0f;
|
||||
}
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &black);
|
||||
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), &data);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
g_idle_add (idle_cb, stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
cogl_object_unref (data.material);
|
||||
g_timer_destroy (data.last_spark_time);
|
||||
|
||||
for (i = 0; i < N_FIREWORKS; i++)
|
||||
g_timer_destroy (data.fireworks[i].timer);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user