#include #include #include #include #include typedef struct { char *name; char *source; } ShaderSource; /* a couple of boilerplate defines that are common amongst all the * sample shaders */ /* FRAGMENT_SHADER_BEGIN: generate boilerplate with a local vec4 color already * initialized, from a sampler2D in a variable tex. */ #define FRAGMENT_SHADER_VARS \ "uniform sampler2D tex;" \ "uniform float x_step, y_step;" #define FRAGMENT_SHADER_BEGIN \ "void main (){" \ " vec4 color = texture2D (tex, vec2(cogl_tex_coord_in[0]));" /* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly * blended with the gl specified color (makes the opacity of actors work * correctly). */ #define FRAGMENT_SHADER_END \ " cogl_color_out = color;" \ " cogl_color_out = cogl_color_out * cogl_color_in;" \ "}" static ShaderSource shaders[]= { {"brightness-contrast", FRAGMENT_SHADER_VARS "uniform float brightness, contrast;" FRAGMENT_SHADER_BEGIN " color.rgb /= color.a;" " color.rgb = (color.rgb - vec3(0.5, 0.5, 0.5)) * contrast + " "vec3 (brightness + 0.5, brightness + 0.5, brightness + 0.5);" " color.rgb *= color.a;" FRAGMENT_SHADER_END }, {"box-blur", FRAGMENT_SHADER_VARS #if GPU_SUPPORTS_DYNAMIC_BRANCHING "uniform float radius;" FRAGMENT_SHADER_BEGIN "float u, v;" "int count = 1;" "for (u=-radius;ubutton.button == 1) { new_no = shader_no - 1; if (new_no < 0) new_no = G_N_ELEMENTS (shaders) - 1; } else { new_no = shader_no + 1; if (new_no >= G_N_ELEMENTS (shaders)) new_no = 0; } set_shader_num (new_no); return CLUTTER_EVENT_STOP; } static gboolean key_release_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) { guint keysym = clutter_event_get_key_symbol (event); ClutterModifierType mods = clutter_event_get_state (event); if (keysym == CLUTTER_KEY_q || ((mods & CLUTTER_SHIFT_MASK) && keysym == CLUTTER_KEY_q)) clutter_main_quit (); return CLUTTER_EVENT_STOP; } static gboolean timeout_cb (gpointer user_data) { shader_no++; if (shader_no > (G_N_ELEMENTS (shaders) - 1)) shader_no = 0; set_shader_num (shader_no); return G_SOURCE_CONTINUE; } static gboolean idle_cb (gpointer data) { clutter_actor_queue_redraw (data); return G_SOURCE_CONTINUE; } static gboolean destroy_window_cb (ClutterStage *stage, ClutterEvent *event, gpointer user_data) { clutter_main_quit (); return CLUTTER_EVENT_STOP; } G_MODULE_EXPORT int test_cogl_shader_glsl_main (int argc, char *argv[]) { ClutterActor *stage; char *file; GError *error; ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; stage = clutter_stage_new (); clutter_stage_set_title (CLUTTER_STAGE (stage), "Assembly Shader Test"); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); error = NULL; redhand = cogl_texture_new_from_file (file, COGL_TEXTURE_NO_ATLAS, COGL_PIXEL_FORMAT_ANY, &error); if (redhand == COGL_INVALID_HANDLE) g_error ("image load failed: %s", error->message); material = cogl_material_new (); cogl_material_set_layer (material, 0, redhand); set_shader_num (0); g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), NULL); clutter_actor_set_reactive (stage, TRUE); g_signal_connect (stage, "button-release-event", G_CALLBACK (button_release_cb), NULL); g_signal_connect (stage, "key-release-event", G_CALLBACK (key_release_cb), NULL); g_signal_connect (stage, "delete-event", G_CALLBACK (destroy_window_cb), NULL); timeout_id = clutter_threads_add_timeout (1000, timeout_cb, NULL); clutter_threads_add_idle (idle_cb, stage); clutter_actor_show (stage); clutter_main (); return EXIT_SUCCESS; }