[Cogl] [PATCH] Add a cogl-point-sprites example
Neil Roberts
neil at linux.intel.com
Wed Aug 21 04:04:02 PDT 2013
This updates the old point sprites interactive test from Clutter to be
a standalone Cogl example using the 2.0 API.
---
examples/Makefile.am | 4 +-
examples/cogl-point-sprites.c | 325 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 328 insertions(+), 1 deletion(-)
create mode 100644 examples/cogl-point-sprites.c
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 63682af..d9198a9 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -32,7 +32,7 @@ cogl_info_SOURCES = cogl-info.c
cogl_info_LDADD = $(common_ldadd)
if USE_GLIB
-programs += cogl-hello cogl-msaa cogl-gles2-context
+programs += cogl-hello cogl-msaa cogl-gles2-context cogl-point-sprites
examples_datadir = $(pkgdatadir)/examples-data
examples_data_DATA =
@@ -40,6 +40,8 @@ cogl_hello_SOURCES = cogl-hello.c
cogl_hello_LDADD = $(common_ldadd)
cogl_msaa_SOURCES = cogl-msaa.c
cogl_msaa_LDADD = $(common_ldadd)
+cogl_point_sprites_SOURCES = cogl-point-sprites.c
+cogl_point_sprites_LDADD = $(common_ldadd)
if BUILD_COGL_PANGO
programs += cogl-crate
diff --git a/examples/cogl-point-sprites.c b/examples/cogl-point-sprites.c
new file mode 100644
index 0000000..8f90805
--- /dev/null
+++ b/examples/cogl-point-sprites.c
@@ -0,0 +1,325 @@
+#include <cogl/cogl.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <math.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
+{
+ uint8_t red, green, blue, alpha;
+} Color;
+
+typedef struct
+{
+ float size;
+ float x, y;
+ float start_x, start_y;
+ Color color;
+
+ /* Velocities are in units per second */
+ float initial_x_velocity;
+ float initial_y_velocity;
+
+ GTimer *timer;
+} Firework;
+
+typedef struct
+{
+ float x, y;
+ Color color;
+ Color base_color;
+} Spark;
+
+typedef struct
+{
+ Firework fireworks[N_FIREWORKS];
+
+ int next_spark_num;
+ Spark sparks[N_SPARKS];
+ GTimer *last_spark_time;
+
+ CoglContext *context;
+ CoglFramebuffer *fb;
+ CoglPipeline *pipeline;
+ CoglPrimitive *primitive;
+ CoglAttributeBuffer *attribute_buffer;
+} Data;
+
+static CoglTexture *
+generate_round_texture (CoglContext *context)
+{
+ uint8_t *p, *data;
+ int x, y;
+ CoglTexture2D *tex;
+
+ p = data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4);
+
+ /* Generate a white 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_2d_new_from_data (context,
+ TEXTURE_SIZE, TEXTURE_SIZE,
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+ COGL_PIXEL_FORMAT_ANY,
+ TEXTURE_SIZE * 4,
+ data,
+ NULL /* error */);
+
+ g_free (data);
+
+ return COGL_TEXTURE (tex);
+}
+
+static void
+paint (Data *data)
+{
+ int i;
+ float diff_time;
+
+ /* 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 (Color));
+ ((uint8_t *) &firework->color)[g_random_int_range (0, 3)] = 255;
+ }
+ else
+ {
+ memset (&firework->color, 255, sizeof (Color));
+ ((uint8_t *) &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);
+ }
+
+ cogl_buffer_set_data (COGL_BUFFER (data->attribute_buffer),
+ 0, /* offset */
+ data->sparks,
+ sizeof (data->sparks),
+ NULL /* error */);
+
+ cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
+
+ cogl_primitive_draw (data->primitive,
+ data->fb,
+ data->pipeline);
+
+ cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb));
+}
+
+static void
+create_primitive (Data *data)
+{
+ CoglAttribute *attributes[2];
+ int i;
+
+ data->attribute_buffer =
+ cogl_attribute_buffer_new_with_size (data->context,
+ sizeof (data->sparks));
+ cogl_buffer_set_update_hint (COGL_BUFFER (data->attribute_buffer),
+ COGL_BUFFER_UPDATE_HINT_DYNAMIC);
+
+ attributes[0] = cogl_attribute_new (data->attribute_buffer,
+ "cogl_position_in",
+ sizeof (Spark),
+ G_STRUCT_OFFSET (Spark, x),
+ 2, /* n_components */
+ COGL_ATTRIBUTE_TYPE_FLOAT);
+ attributes[1] = cogl_attribute_new (data->attribute_buffer,
+ "cogl_color_in",
+ sizeof (Spark),
+ G_STRUCT_OFFSET (Spark, color),
+ 4, /* n_components */
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
+
+ data->primitive =
+ cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_POINTS,
+ N_SPARKS,
+ attributes,
+ G_N_ELEMENTS (attributes));
+
+ for (i = 0; i < G_N_ELEMENTS (attributes); i++)
+ cogl_object_unref (attributes[i]);
+}
+
+static void
+frame_event_cb (CoglOnscreen *onscreen,
+ CoglFrameEvent event,
+ CoglFrameInfo *info,
+ void *user_data)
+{
+ Data *data = user_data;
+
+ if (event == COGL_FRAME_EVENT_SYNC)
+ paint (data);
+}
+
+int
+main (int argc, char *argv[])
+{
+ CoglTexture *tex;
+ CoglOnscreen *onscreen;
+ GSource *cogl_source;
+ GMainLoop *loop;
+ Data data;
+ int i;
+
+ data.context = cogl_context_new (NULL, NULL);
+
+ create_primitive (&data);
+
+ data.pipeline = cogl_pipeline_new (data.context);
+ data.last_spark_time = g_timer_new ();
+ data.next_spark_num = 0;
+ cogl_pipeline_set_point_size (data.pipeline, TEXTURE_SIZE);
+
+ tex = generate_round_texture (data.context);
+ cogl_pipeline_set_layer_texture (data.pipeline, 0, tex);
+ cogl_object_unref (tex);
+
+ cogl_pipeline_set_layer_point_sprite_coords_enabled (data.pipeline,
+ 0, /* layer */
+ TRUE,
+ NULL /* 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;
+ }
+
+ onscreen = cogl_onscreen_new (data.context, 800, 600);
+ cogl_onscreen_show (onscreen);
+ data.fb = COGL_FRAMEBUFFER (onscreen);
+
+ cogl_source = cogl_glib_source_new (data.context, G_PRIORITY_DEFAULT);
+
+ g_source_attach (cogl_source, NULL);
+
+ cogl_onscreen_add_frame_callback (onscreen,
+ frame_event_cb,
+ &data,
+ NULL /* destroy notify */);
+
+ loop = g_main_loop_new (NULL, TRUE);
+
+ paint (&data);
+
+ g_main_loop_run (loop);
+
+ g_main_loop_unref (loop);
+
+ g_source_destroy (cogl_source);
+
+ cogl_object_unref (data.pipeline);
+ cogl_object_unref (data.attribute_buffer);
+ cogl_object_unref (data.primitive);
+ cogl_object_unref (onscreen);
+ cogl_object_unref (data.context);
+
+ g_timer_destroy (data.last_spark_time);
+
+ for (i = 0; i < N_FIREWORKS; i++)
+ g_timer_destroy (data.fireworks[i].timer);
+
+ return 0;
+}
--
1.8.3.1
More information about the Cogl
mailing list