static void _rut_camera_flush_transforms (RutCamera *camera) { const CoglMatrix *projection; CoglFramebuffer *fb = camera->fb; CameraFlushState *state; /* While a camera is in a suspended state then we don't expect to * _flush() and use that camera before it is restored. */ g_return_if_fail (camera->suspended == FALSE); state = cogl_object_get_user_data (COGL_OBJECT (fb), &fb_camera_key); if (!state) { state = g_slice_new (CameraFlushState); cogl_object_set_user_data (COGL_OBJECT (fb), &fb_camera_key, state, free_camera_flush_state); } else if (state->current_camera == camera && camera->transform_age == state->transform_age) goto done; if (camera->in_frame) { g_warning ("Un-balanced rut_camera_flush/_end calls: " "repeat _flush() calls before _end()"); } cogl_framebuffer_set_viewport (fb, camera->viewport[0], camera->viewport[1], camera->viewport[2], camera->viewport[3]); projection = rut_camera_get_projection (camera); cogl_framebuffer_set_projection_matrix (fb, projection); cogl_framebuffer_set_modelview_matrix (fb, &camera->view); state->current_camera = camera; state->transform_age = camera->transform_age; done: camera->in_frame = TRUE; }
static void setup_orthographic_modelview (void) { CoglMatrix matrix; int fb_width = cogl_framebuffer_get_width (test_fb); int fb_height = cogl_framebuffer_get_height (test_fb); /* Set up a non-identity modelview matrix. When the journal is * flushed it will usually flush the identity matrix. Using the * non-default matrix ensures that we test that Cogl restores the * matrix we asked for. The matrix sets up an orthographic transform * in the modelview matrix */ cogl_matrix_init_identity (&matrix); cogl_matrix_orthographic (&matrix, 0.0f, 0.0f, /* x_1 y_1 */ fb_width, fb_height, -1.0f, /* nearval */ 1.0f /* farval */); cogl_framebuffer_set_modelview_matrix (test_fb, &matrix); }
int main (int argc, char **argv) { CoglContext *ctx; CoglOnscreen *onscreen; CoglFramebuffer *fb; GError *error = NULL; Data data; PangoRectangle hello_label_size; float fovy, aspect, z_near, z_2d, z_far; CoglDepthState depth_state; CoglBool has_swap_notify; ctx = cogl_context_new (NULL, &error); if (!ctx) { fprintf (stderr, "Failed to create context: %s\n", error->message); return 1; } onscreen = cogl_onscreen_new (ctx, 640, 480); fb = COGL_FRAMEBUFFER (onscreen); data.fb = fb; data.framebuffer_width = cogl_framebuffer_get_width (fb); data.framebuffer_height = cogl_framebuffer_get_height (fb); data.timer = g_timer_new (); cogl_onscreen_show (onscreen); cogl_framebuffer_set_viewport (fb, 0, 0, data.framebuffer_width, data.framebuffer_height); fovy = 60; /* y-axis field of view */ aspect = (float)data.framebuffer_width/(float)data.framebuffer_height; z_near = 0.1; /* distance to near clipping plane */ z_2d = 1000; /* position to 2d plane */ z_far = 2000; /* distance to far clipping plane */ cogl_framebuffer_perspective (fb, fovy, aspect, z_near, z_far); /* Since the pango renderer emits geometry in pixel/device coordinates * and the anti aliasing is implemented with the assumption that the * geometry *really* does end up pixel aligned, we setup a modelview * matrix so that for geometry in the plane z = 0 we exactly map x * coordinates in the range [0,stage_width] and y coordinates in the * range [0,stage_height] to the framebuffer extents with (0,0) being * the top left. * * This is roughly what Clutter does for a ClutterStage, but this * demonstrates how it is done manually using Cogl. */ cogl_matrix_init_identity (&data.view); cogl_matrix_view_2d_in_perspective (&data.view, fovy, aspect, z_near, z_2d, data.framebuffer_width, data.framebuffer_height); cogl_framebuffer_set_modelview_matrix (fb, &data.view); /* Initialize some convenient constants */ cogl_matrix_init_identity (&identity); cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff); /* rectangle indices allow the GPU to interpret a list of quads (the * faces of our cube) as a list of triangles. * * Since this is a very common thing to do * cogl_get_rectangle_indices() is a convenience function for * accessing internal index buffers that can be shared. */ data.indices = cogl_get_rectangle_indices (ctx, 6 /* n_rectangles */); data.prim = cogl_primitive_new_p3t2 (ctx, COGL_VERTICES_MODE_TRIANGLES, G_N_ELEMENTS (vertices), vertices); /* Each face will have 6 indices so we have 6 * 6 indices in total... */ cogl_primitive_set_indices (data.prim, data.indices, 6 * 6); /* Load a jpeg crate texture from a file */ printf ("crate.jpg (CC by-nc-nd http://bit.ly/9kP45T) ShadowRunner27 http://bit.ly/m1YXLh\n"); data.texture = cogl_texture_new_from_file (COGL_EXAMPLES_DATA "crate.jpg", COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, &error); if (!data.texture) g_error ("Failed to load texture: %s", error->message); /* a CoglPipeline conceptually describes all the state for vertex * processing, fragment processing and blending geometry. When * drawing the geometry for the crate this pipeline says to sample a * single texture during fragment processing... */ data.crate_pipeline = cogl_pipeline_new (ctx); cogl_pipeline_set_layer_texture (data.crate_pipeline, 0, data.texture); /* Since the box is made of multiple triangles that will overlap * when drawn and we don't control the order they are drawn in, we * enable depth testing to make sure that triangles that shouldn't * be visible get culled by the GPU. */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (data.crate_pipeline, &depth_state, NULL); /* Setup a Pango font map and context */ data.pango_font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new (ctx)); cogl_pango_font_map_set_use_mipmapping (data.pango_font_map, TRUE); data.pango_context = pango_font_map_create_context (PANGO_FONT_MAP (data.pango_font_map)); data.pango_font_desc = pango_font_description_new (); pango_font_description_set_family (data.pango_font_desc, "Sans"); pango_font_description_set_size (data.pango_font_desc, 30 * PANGO_SCALE); /* Setup the "Hello Cogl" text */ data.hello_label = pango_layout_new (data.pango_context); pango_layout_set_font_description (data.hello_label, data.pango_font_desc); pango_layout_set_text (data.hello_label, "Hello Cogl", -1); pango_layout_get_extents (data.hello_label, NULL, &hello_label_size); data.hello_label_width = PANGO_PIXELS (hello_label_size.width); data.hello_label_height = PANGO_PIXELS (hello_label_size.height); data.swap_ready = TRUE; has_swap_notify = cogl_has_feature (ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT); if (has_swap_notify) cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (fb), swap_notify_cb, &data); while (1) { CoglPollFD *poll_fds; int n_poll_fds; int64_t timeout; if (data.swap_ready) { paint (&data); cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout); if (!has_swap_notify) { /* If the winsys doesn't support swap event notification then we'll just redraw constantly */ data.swap_ready = TRUE; timeout = 0; } g_poll ((GPollFD *) poll_fds, n_poll_fds, timeout == -1 ? -1 : timeout / 1000); cogl_poll_dispatch (ctx, poll_fds, n_poll_fds); } return 0; }
void cogl_set_modelview_matrix (CoglMatrix *matrix) { cogl_framebuffer_set_modelview_matrix (cogl_get_draw_framebuffer (), matrix); }
static void rig_journal_flush (GArray *journal, RigPaintContext *paint_ctx) { RutPaintContext *rut_paint_ctx = &paint_ctx->_parent; RutCamera *camera = rut_paint_ctx->camera; CoglFramebuffer *fb = rut_camera_get_framebuffer (camera); int start, dir, end; int i; /* TODO: use an inline qsort implementation */ g_array_sort (journal, (void *)sort_entry_cb); /* We draw opaque geometry front-to-back so we are more likely to be * able to discard later fragments earlier by depth testing. * * We draw transparent geometry back-to-front so it blends * correctly. */ if ( paint_ctx->pass == RIG_PASS_COLOR_BLENDED) { start = 0; dir = 1; end = journal->len; } else { start = journal->len - 1; dir = -1; end = -1; } cogl_framebuffer_push_matrix (fb); for (i = start; i != end; i += dir) { RigJournalEntry *entry = &g_array_index (journal, RigJournalEntry, i); RutEntity *entity = entry->entity; RutComponent *geometry = rut_entity_get_component (entity, RUT_COMPONENT_TYPE_GEOMETRY); CoglPipeline *pipeline; CoglPrimitive *primitive; float normal_matrix[9]; RutMaterial *material; pipeline = get_entity_pipeline (paint_ctx->engine, entity, geometry, paint_ctx->pass); if (paint_ctx->pass == RIG_PASS_DOF_DEPTH || paint_ctx->pass == RIG_PASS_SHADOW) { /* FIXME: avoid updating these uniforms for every primitive if * the focal parameters haven't change! */ set_focal_parameters (pipeline, camera->focal_distance, camera->depth_of_field); } else if (paint_ctx->pass == RIG_PASS_COLOR_UNBLENDED || paint_ctx->pass == RIG_PASS_COLOR_BLENDED) { int location; RutLight *light = rut_entity_get_component (paint_ctx->engine->light, RUT_COMPONENT_TYPE_LIGHT); /* FIXME: only update the lighting uniforms when the light has * actually moved! */ rut_light_set_uniforms (light, pipeline); /* FIXME: only update the material uniforms when the material has * actually changed! */ material = rut_entity_get_component (entity, RUT_COMPONENT_TYPE_MATERIAL); if (material) rut_material_flush_uniforms (material, pipeline); get_normal_matrix (&entry->matrix, normal_matrix); location = cogl_pipeline_get_uniform_location (pipeline, "normal_matrix"); cogl_pipeline_set_uniform_matrix (pipeline, location, 3, /* dimensions */ 1, /* count */ FALSE, /* don't transpose again */ normal_matrix); } if (rut_object_is (geometry, RUT_INTERFACE_ID_PRIMABLE)) { primitive = rut_primable_get_primitive (geometry); cogl_framebuffer_set_modelview_matrix (fb, &entry->matrix); cogl_framebuffer_draw_primitive (fb, pipeline, primitive); } else if (rut_object_get_type (geometry) == &rut_text_type && paint_ctx->pass == RIG_PASS_COLOR_BLENDED) { cogl_framebuffer_set_modelview_matrix (fb, &entry->matrix); rut_paintable_paint (geometry, rut_paint_ctx); } cogl_object_unref (pipeline); rut_refable_unref (entry->entity); } cogl_framebuffer_pop_matrix (fb); g_array_set_size (journal, 0); }