[Cogl] [PATCH] Add a cogl-point-sprites example
Robert Bragg
robert at sixbynine.org
Wed Aug 21 07:05:50 PDT 2013
Cool, this looks good to land to me.
Reviewed-by: Robert Bragg <robert at linux.intel.com>
thanks,
Robert
On Wed, Aug 21, 2013 at 12:04 PM, Neil Roberts <neil at linux.intel.com> wrote:
> 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
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl
More information about the Cogl
mailing list