#include #include #include #include #include typedef struct { char *name; char *source; } ShaderSource; /* These variables are used instead of the standard GLSL variables on GLES 2 */ #ifdef COGL_HAS_GLES2 #define GLES2_VARS \ "precision mediump float;\n" \ "varying vec2 tex_coord[1];\n" \ "varying vec4 frag_color;\n" #define TEX_COORD "tex_coord[0]" #define COLOR_VAR "frag_color" #else /* COGL_HAS_GLES2 */ #define GLES2_VARS "" #define TEX_COORD "gl_TexCoord[0]" #define COLOR_VAR "gl_Color" #endif /* COGL_HAS_GLES2 */ /* 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 \ GLES2_VARS \ "uniform sampler2D tex;" \ "uniform float x_step, y_step;" \ #define FRAGMENT_SHADER_BEGIN \ "void main (){" \ " vec4 color = texture2D (tex, vec2(" TEX_COORD "));" /* 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 \ " gl_FragColor = color;" \ " gl_FragColor = gl_FragColor * " COLOR_VAR ";" \ "}" 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 FALSE; } static gboolean key_release_cb (ClutterActor *actor, ClutterEvent *event, void *user_data) { if (event->key.keyval == CLUTTER_Q || event->key.keyval == CLUTTER_q) clutter_main_quit (); return FALSE; } static gboolean timeout_cb (void *user_data) { shader_no++; if (shader_no > (G_N_ELEMENTS (shaders) - 1)) shader_no = 0; set_shader_num (shader_no); return TRUE; } static gboolean idle_cb (void *data) { clutter_actor_queue_redraw (data); return TRUE; } static gboolean destroy_window_cb (ClutterStage *stage, ClutterEvent *event, void *user_data) { clutter_main_quit (); return TRUE; } 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 }; clutter_init (&argc, &argv); 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, 0, 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 = g_timeout_add (1000, timeout_cb, NULL); g_idle_add (idle_cb, stage); clutter_actor_show_all (stage); clutter_main (); return EXIT_SUCCESS; }