/** * crank_make_mesh_sphere_uv_p3: * @cogl_context: A CoglContext. * @uc: Number of vertices in u-direction. * @vc: Number of vertices in v-direction. This excludes two vertices at bottom * and top. * * Constructs a #CoglPrimivive for a sphere. * This only contains a position information. * * Returns: (transfer full): A #CoglPrimitive for a sphere. */ CoglPrimitive* crank_make_mesh_sphere_uv_p3 (CoglContext *cogl_context, const guint uc, const guint vc) { CoglPrimitive *primitive; CoglIndices *indices; CoglVertexP3 *vdata; TriIndices *idata; guint lvdata; guint lidata; vdata = crank_make_v_p3_sphere_uv (uc, vc, &lvdata); idata = crank_make_indices_sphere_uv (uc, vc, &lidata); indices = cogl_indices_new (cogl_context, COGL_INDICES_TYPE_UNSIGNED_SHORT, idata, lidata * 3); primitive = cogl_primitive_new_p3 (cogl_context, COGL_VERTICES_MODE_TRIANGLES, lvdata, vdata); cogl_primitive_set_indices (primitive, indices, lidata * 3); cogl_object_unref (indices); g_free (vdata); g_free (idata); return primitive; }
CoglPrimitive * cogl_primitive_copy (CoglPrimitive *primitive) { CoglPrimitive *copy; copy = cogl_primitive_new_with_attributes (primitive->mode, primitive->n_vertices, primitive->attributes, primitive->n_attributes); cogl_primitive_set_indices (copy, primitive->indices, primitive->n_vertices); cogl_primitive_set_first_vertex (copy, primitive->first_vertex); return copy; }
static CoglPrimitive * _cogl_path_get_fill_primitive (CoglPath *path) { if (path->data->fill_primitive) return path->data->fill_primitive; _cogl_path_build_fill_attribute_buffer (path); path->data->fill_primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, path->data->fill_vbo_n_indices, path->data->fill_attributes, COGL_PATH_N_ATTRIBUTES); cogl_primitive_set_indices (path->data->fill_primitive, path->data->fill_vbo_indices, path->data->fill_vbo_n_indices); return path->data->fill_primitive; }
static void emit_vertex_buffer_geometry (CoglFramebuffer *fb, CoglPipeline *pipeline, CoglPangoDisplayListNode *node) { CoglContext *ctx = fb->context; /* It's expensive to go through the Cogl journal for large runs * of text in part because the journal transforms the quads in software * to avoid changing the modelview matrix. So for larger runs of text * we load the vertices into a VBO, and this has the added advantage * that if the text doesn't change from frame to frame the VBO can * be re-used avoiding the repeated cost of validating the data and * mapping it into the GPU... */ if (node->d.texture.primitive == NULL) { CoglAttributeBuffer *buffer; CoglVertexP2T2 *verts, *v; int n_verts; CoglBool allocated = FALSE; CoglAttribute *attributes[2]; CoglPrimitive *prim; int i; CoglError *ignore_error = NULL; n_verts = node->d.texture.rectangles->len * 4; buffer = cogl_attribute_buffer_new_with_size (ctx, n_verts * sizeof (CoglVertexP2T2)); if ((verts = cogl_buffer_map (COGL_BUFFER (buffer), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD, &ignore_error)) == NULL) { cogl_error_free (ignore_error); verts = g_new (CoglVertexP2T2, n_verts); allocated = TRUE; } v = verts; /* Copy the rectangles into the buffer and expand into four vertices instead of just two */ for (i = 0; i < node->d.texture.rectangles->len; i++) { const CoglPangoDisplayListRectangle *rectangle = &g_array_index (node->d.texture.rectangles, CoglPangoDisplayListRectangle, i); v->x = rectangle->x_1; v->y = rectangle->y_1; v->s = rectangle->s_1; v->t = rectangle->t_1; v++; v->x = rectangle->x_1; v->y = rectangle->y_2; v->s = rectangle->s_1; v->t = rectangle->t_2; v++; v->x = rectangle->x_2; v->y = rectangle->y_2; v->s = rectangle->s_2; v->t = rectangle->t_2; v++; v->x = rectangle->x_2; v->y = rectangle->y_1; v->s = rectangle->s_2; v->t = rectangle->t_1; v++; } if (allocated) { cogl_buffer_set_data (COGL_BUFFER (buffer), 0, /* offset */ verts, sizeof (CoglVertexP2T2) * n_verts, NULL); g_free (verts); } else cogl_buffer_unmap (COGL_BUFFER (buffer)); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (CoglVertexP2T2), G_STRUCT_OFFSET (CoglVertexP2T2, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP2T2), G_STRUCT_OFFSET (CoglVertexP2T2, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, n_verts, attributes, 2 /* n_attributes */); #ifdef CLUTTER_COGL_HAS_GL if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS)) cogl_primitive_set_mode (prim, GL_QUADS); else #endif { /* GLES doesn't support GL_QUADS so instead we use a VBO with indexed vertices to generate GL_TRIANGLES from the quads */ CoglIndices *indices = cogl_get_rectangle_indices (ctx, node->d.texture.rectangles->len); cogl_primitive_set_indices (prim, indices, node->d.texture.rectangles->len * 6); } node->d.texture.primitive = prim; cogl_object_unref (buffer); cogl_object_unref (attributes[0]); cogl_object_unref (attributes[1]); } cogl_primitive_draw (node->d.texture.primitive, fb, pipeline); }
static void clutter_deform_effect_init_arrays (ClutterDeformEffect *self) { ClutterDeformEffectPrivate *priv = self->priv; gint x, y, direction, n_indices; CoglAttribute *attributes[3]; guint16 *static_indices; CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); CoglIndices *indices; guint16 *idx; int i; clutter_deform_effect_free_arrays (self); n_indices = ((2 + 2 * priv->x_tiles) * priv->y_tiles + (priv->y_tiles - 1)); static_indices = g_new (guint16, n_indices); #define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) /* compute all the triangles from the various tiles */ direction = 1; idx = static_indices; idx[0] = MESH_INDEX (0, 0); idx[1] = MESH_INDEX (0, 1); idx += 2; for (y = 0; y < priv->y_tiles; y++) { for (x = 0; x < priv->x_tiles; x++) { if (direction) { idx[0] = MESH_INDEX (x + 1, y); idx[1] = MESH_INDEX (x + 1, y + 1); } else { idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); } idx += 2; } if (y == (priv->y_tiles - 1)) break; if (direction) { idx[0] = MESH_INDEX (priv->x_tiles, y + 1); idx[1] = MESH_INDEX (priv->x_tiles, y + 1); idx[2] = MESH_INDEX (priv->x_tiles, y + 2); } else { idx[0] = MESH_INDEX (0, y + 1); idx[1] = MESH_INDEX (0, y + 1); idx[2] = MESH_INDEX (0, y + 2); } idx += 3; direction = !direction; } #undef MESH_INDEX indices = cogl_indices_new (ctx, COGL_INDICES_TYPE_UNSIGNED_SHORT, static_indices, n_indices); g_free (static_indices); priv->n_vertices = (priv->x_tiles + 1) * (priv->y_tiles + 1); priv->buffer = cogl_attribute_buffer_new (ctx, sizeof (CoglVertexP3T2C4) * priv->n_vertices, NULL); /* The application is expected to continuously modify the vertices so we should give a hint to Cogl about that */ cogl_buffer_set_update_hint (COGL_BUFFER (priv->buffer), COGL_BUFFER_UPDATE_HINT_DYNAMIC); attributes[0] = cogl_attribute_new (priv->buffer, "cogl_position_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, x), 3, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (priv->buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[2] = cogl_attribute_new (priv->buffer, "cogl_color_in", sizeof (CoglVertexP3T2C4), G_STRUCT_OFFSET (CoglVertexP3T2C4, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP, priv->n_vertices, attributes, 3 /* n_attributes */); cogl_primitive_set_indices (priv->primitive, indices, n_indices); if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES)) { priv->lines_primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP, priv->n_vertices, attributes, 2 /* n_attributes */); cogl_primitive_set_indices (priv->lines_primitive, indices, n_indices); } cogl_object_unref (indices); for (i = 0; i < 3; i++) cogl_object_unref (attributes[i]); priv->is_dirty = TRUE; }
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; }
static RutDiamondSlice * diamond_slice_new (RutContext *ctx, float size, int tex_width, int tex_height) { RutDiamondSlice *diamond_slice = g_slice_new (RutDiamondSlice); float width = size; float height = size; #define DIAMOND_SLICE_CORNER_RADIUS 20 CoglMatrix matrix; float tex_aspect; rut_object_init (&diamond_slice->_parent, &rut_diamond_slice_type); diamond_slice->ref_count = 1; diamond_slice->size = size; { /* x0,y0,x1,y1 and s0,t0,s1,t1 define the postion and texture * coordinates for the center rectangle... */ float x0 = DIAMOND_SLICE_CORNER_RADIUS; float y0 = DIAMOND_SLICE_CORNER_RADIUS; float x1 = width - DIAMOND_SLICE_CORNER_RADIUS; float y1 = height - DIAMOND_SLICE_CORNER_RADIUS; /* The center region of the nine-slice can simply map to the * degenerate center of the circle */ float s0 = 0.5; float t0 = 0.5; float s1 = 0.5; float t1 = 0.5; int n_vertices; int i; /* * 0,0 x0,0 x1,0 width,0 * 0,0 s0,0 s1,0 1,0 * 0 1 2 3 * * 0,y0 x0,y0 x1,y0 width,y0 * 0,t0 s0,t0 s1,t0 1,t0 * 4 5 6 7 * * 0,y1 x0,y1 x1,y1 width,y1 * 0,t1 s0,t1 s1,t1 1,t1 * 8 9 10 11 * * 0,height x0,height x1,height width,height * 0,1 s0,1 s1,1 1,1 * 12 13 14 15 */ VertexP2T2T2 vertices[] = { { 0, 0, 0, 0, 0, 0 }, { x0, 0, s0, 0, x0, 0}, { x1, 0, s1, 0, x1, 0}, { width, 0, 1, 0, width, 0}, { 0, y0, 0, t0, 0, y0}, { x0, y0, s0, t0, x0, y0}, { x1, y0, s1, t0, x1, y0}, { width, y0, 1, t0, width, y0}, { 0, y1, 0, t1, 0, y1}, { x0, y1, s0, t1, x0, y1}, { x1, y1, s1, t1, x1, y1}, { width, y1, 1, t1, width, y1}, { 0, height, 0, 1, 0, height}, { x0, height, s0, 1, x0, height}, { x1, height, s1, 1, x1, height}, { width, height, 1, 1, width, height}, }; cogl_matrix_init_identity (&diamond_slice->rotate_matrix); cogl_matrix_rotate (&diamond_slice->rotate_matrix, 45, 0, 0, 1); cogl_matrix_translate (&diamond_slice->rotate_matrix, - width / 2.0, - height / 2.0, 0); n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2); for (i = 0; i < n_vertices; i++) { float z = 0, w = 1; cogl_matrix_transform_point (&diamond_slice->rotate_matrix, &vertices[i].x, &vertices[i].y, &z, &w); #ifdef MESA_CONST_ATTRIB_BUG_WORKAROUND vertices[i].Nx = 0; vertices[i].Ny = 0; vertices[i].Nz = 1; vertices[i].Tx = 1; vertices[i].Ty = 0; vertices[i].Tz = 0; #endif } cogl_matrix_init_identity (&matrix); { float s_scale = 1.0, t_scale = 1.0; float s0, t0; float diagonal_size_scale = 1.0 / (sinf (G_PI_4) * 2.0); tex_aspect = (float)tex_width / (float)tex_height; if (tex_aspect < 1) /* taller than it is wide */ t_scale *= tex_aspect; else /* wider than it is tall */ { float inverse_aspect = 1.0f / tex_aspect; s_scale *= inverse_aspect; } s_scale *= diagonal_size_scale; t_scale *= diagonal_size_scale; s0 = 0.5 - (s_scale / 2.0); t0 = 0.5 - (t_scale / 2.0); cogl_matrix_translate (&matrix, s0, t0, 0); cogl_matrix_scale (&matrix, s_scale / width, t_scale / height, 1); cogl_matrix_translate (&matrix, width / 2.0, height / 2.0, 1); cogl_matrix_rotate (&matrix, 45, 0, 0, 1); cogl_matrix_translate (&matrix, -width / 2.0, -height / 2.0, 1); } n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2); for (i = 0; i < n_vertices; i++) { float z = 0, w = 1; cogl_matrix_transform_point (&matrix, &vertices[i].s1, &vertices[i].t1, &z, &w); } diamond_slice->primitive = primitive_new_p2t2t2 (ctx->cogl_context, COGL_VERTICES_MODE_TRIANGLES, n_vertices, vertices); /* The vertices uploaded only map to the key intersection points of the * 9-slice grid which isn't a topology that GPUs can handle directly so * this specifies an array of indices that allow the GPU to interpret the * vertices as a list of triangles... */ cogl_primitive_set_indices (diamond_slice->primitive, ctx->nine_slice_indices, sizeof (_rut_nine_slice_indices_data) / sizeof (_rut_nine_slice_indices_data[0])); } return diamond_slice; }
CoglPrimitive * rut_camera_create_frustum_primitive (RutCamera *camera) { RutVertex4 vertices[8] = { /* near plane in projection space */ {-1, -1, -1, 1, }, { 1, -1, -1, 1, }, { 1, 1, -1, 1, }, {-1, 1, -1, 1, }, /* far plane in projection space */ {-1, -1, 1, 1, }, { 1, -1, 1, 1, }, { 1, 1, 1, 1, }, {-1, 1, 1, 1, } }; const CoglMatrix *projection_inv; CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[1]; CoglPrimitive *primitive; CoglIndices *indices; unsigned char indices_data[24] = { 0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,5, 2,6, 3,7 }; int i; projection_inv = rut_camera_get_inverse_projection (camera); for (i = 0; i < 8; i++) { cogl_matrix_transform_point (projection_inv, &vertices[i].x, &vertices[i].y, &vertices[i].z, &vertices[i].w); vertices[i].x /= vertices[i].w; vertices[i].y /= vertices[i].w; vertices[i].z /= vertices[i].w; vertices[i].w /= 1.0f; } attribute_buffer = cogl_attribute_buffer_new (rut_cogl_context, 8 * sizeof (RutVertex4), vertices); attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (RutVertex4), offsetof (RutVertex4, x), 3, COGL_ATTRIBUTE_TYPE_FLOAT); indices = cogl_indices_new (rut_cogl_context, COGL_INDICES_TYPE_UNSIGNED_BYTE, indices_data, G_N_ELEMENTS (indices_data)); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINES, 8, attributes, 1); cogl_primitive_set_indices (primitive, indices, G_N_ELEMENTS(indices_data)); cogl_object_unref (attribute_buffer); cogl_object_unref (attributes[0]); cogl_object_unref (indices); return primitive; }
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplGtk3Cogl_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); cogl_framebuffer_orthographic(g_Framebuffer, 0, 0, io.DisplaySize.x, io.DisplaySize.y, -1, 1); CoglContext *context = cogl_framebuffer_get_context(g_Framebuffer); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; int idx_buffer_offset = 0; CoglAttributeBuffer *vertices = cogl_attribute_buffer_new(context, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), cmd_list->VtxBuffer.Data); #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) CoglAttribute *attrs[3] = { cogl_attribute_new(vertices, "cogl_position_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, pos), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_tex_coord0_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, uv), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_color_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, col), 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE) }; #undef OFFSETOF CoglPrimitive *primitive = cogl_primitive_new_with_attributes(COGL_VERTICES_MODE_TRIANGLES, cmd_list->VtxBuffer.Size, attrs, 3); CoglIndices *indices = cogl_indices_new(context, sizeof(ImDrawIdx) == 2 ? COGL_INDICES_TYPE_UNSIGNED_SHORT : COGL_INDICES_TYPE_UNSIGNED_INT, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; cogl_indices_set_offset(indices, sizeof(ImDrawIdx) * idx_buffer_offset); cogl_primitive_set_indices(primitive, indices, pcmd->ElemCount); if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { bool has_texture = pcmd->TextureId != NULL; CoglPipeline *pipeline = has_texture ? (cogl_is_pipeline(pcmd->TextureId) ? (CoglPipeline *) pcmd->TextureId : g_ImagePipeline) : g_ColorPipeline; if (has_texture && pipeline == g_ImagePipeline) { cogl_pipeline_set_layer_texture(g_ImagePipeline, 0, COGL_TEXTURE(pcmd->TextureId)); } cogl_framebuffer_push_scissor_clip(g_Framebuffer, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); cogl_primitive_draw(primitive, g_Framebuffer, pipeline); cogl_framebuffer_pop_clip(g_Framebuffer); } idx_buffer_offset += pcmd->ElemCount; } for (int i = 0; i < 3; i++) cogl_object_unref(attrs[i]); cogl_object_unref(primitive); cogl_object_unref(vertices); cogl_object_unref(indices); } }
static void draw_frame (TestState *state) { CoglTexture *tex = create_texture_3d (test_ctx); CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); typedef struct { float x, y, s, t, r; } Vert; CoglPrimitive *primitive; CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[2]; Vert *verts, *v; int i; cogl_pipeline_set_layer_texture (pipeline, 0, tex); cogl_object_unref (tex); cogl_pipeline_set_layer_filters (pipeline, 0, COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); /* Render the texture repeated horizontally twice using a regular cogl rectangle. This should end up with the r texture coordinates as zero */ cogl_framebuffer_draw_textured_rectangle (test_fb, pipeline, 0.0f, 0.0f, TEX_WIDTH * 2, TEX_HEIGHT, 0.0f, 0.0f, 2.0f, 1.0f); /* Render all of the images in the texture using coordinates from a CoglPrimitive */ v = verts = g_new (Vert, 4 * TEX_DEPTH); for (i = 0; i < TEX_DEPTH; i++) { float r = (i + 0.5f) / TEX_DEPTH; v->x = i * TEX_WIDTH; v->y = TEX_HEIGHT; v->s = 0; v->t = 0; v->r = r; v++; v->x = i * TEX_WIDTH; v->y = TEX_HEIGHT * 2; v->s = 0; v->t = 1; v->r = r; v++; v->x = i * TEX_WIDTH + TEX_WIDTH; v->y = TEX_HEIGHT * 2; v->s = 1; v->t = 1; v->r = r; v++; v->x = i * TEX_WIDTH + TEX_WIDTH; v->y = TEX_HEIGHT; v->s = 1; v->t = 0; v->r = r; v++; } attribute_buffer = cogl_attribute_buffer_new (test_ctx, 4 * TEX_DEPTH * sizeof (Vert), verts); attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (Vert), G_STRUCT_OFFSET (Vert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord_in", sizeof (Vert), G_STRUCT_OFFSET (Vert, s), 3, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 6 * TEX_DEPTH, attributes, 2 /* n_attributes */); cogl_primitive_set_indices (primitive, cogl_get_rectangle_indices (test_ctx, TEX_DEPTH), 6 * TEX_DEPTH); cogl_primitive_draw (primitive, test_fb, pipeline); g_free (verts); cogl_object_unref (primitive); cogl_object_unref (attributes[0]); cogl_object_unref (attributes[1]); cogl_object_unref (attribute_buffer); cogl_object_unref (pipeline); }
static gboolean mash_ply_loader_load (MashDataLoader *data_loader, MashDataFlags flags, const gchar *filename, GError **error) { CoglContext *context; CoglIndices *indices; MashPlyLoader *self = MASH_PLY_LOADER (data_loader); MashPlyLoaderPrivate *priv; MashPlyLoaderData data; gchar *display_name; gboolean ret; priv = self->priv; context = es_get_cogl_context (); data.error = NULL; data.n_vertex_bytes = 0; data.available_props = 0; data.got_props = 0; data.vertices = g_byte_array_new (); data.faces = NULL; data.min_vertex.x = G_MAXFLOAT; data.min_vertex.y = G_MAXFLOAT; data.min_vertex.z = G_MAXFLOAT; data.max_vertex.x = -G_MAXFLOAT; data.max_vertex.y = -G_MAXFLOAT; data.max_vertex.z = -G_MAXFLOAT; data.flags = flags; display_name = g_filename_display_name (filename); if ((data.ply = ply_open (filename, mash_ply_loader_error_cb, &data)) == NULL) mash_ply_loader_check_unknown_error (&data); else { if (!ply_read_header (data.ply)) mash_ply_loader_check_unknown_error (&data); else { int i; for (i = 0; i < G_N_ELEMENTS (mash_ply_loader_properties); i++) if (ply_set_read_cb (data.ply, "vertex", mash_ply_loader_properties[i].name, mash_ply_loader_vertex_read_cb, &data, i)) { data.prop_map[i] = data.n_vertex_bytes; data.n_vertex_bytes += mash_ply_loader_properties[i].size; data.available_props |= 1 << i; } /* Align the size of a vertex to 32 bits */ data.n_vertex_bytes = (data.n_vertex_bytes + 3) & ~(guint) 3; if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) != MASH_PLY_LOADER_VERTEX_PROPS) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing the vertex properties", display_name); else if (!ply_set_read_cb (data.ply, "face", "vertex_indices", mash_ply_loader_face_read_cb, &data, i)) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing face property " "'vertex_indices'", display_name); else if (mash_ply_loader_get_indices_type (&data, &data.error) && !ply_read (data.ply)) mash_ply_loader_check_unknown_error (&data); } ply_close (data.ply); } if (data.error) { g_propagate_error (error, data.error); ret = FALSE; } else if (data.faces->len < 3) { g_set_error (error, MASH_DATA_ERROR, MASH_DATA_ERROR_INVALID, "No faces found in %s", display_name); ret = FALSE; } else { CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[4]; int n_attributes = 0, i; /* Get rid of the old primitive (if any) */ mash_ply_loader_free_primitive (self); /* Create a new attribute buffer for the vertices */ attribute_buffer = cogl_attribute_buffer_new (context, data.vertices->len, data.vertices->data); /* And describe the attributes */ if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) == MASH_PLY_LOADER_VERTEX_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_position_in", data.n_vertex_bytes, data.prop_map[0], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_NORMAL_PROPS) == MASH_PLY_LOADER_NORMAL_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_normal_in", data.n_vertex_bytes, data.prop_map[3], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_TEX_COORD_PROPS) == MASH_PLY_LOADER_TEX_COORD_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord0_in", data.n_vertex_bytes, data.prop_map[6], 2, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_COLOR_PROPS) == MASH_PLY_LOADER_COLOR_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_color_in", data.n_vertex_bytes, data.prop_map[8], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, data.vertices->len, attributes, n_attributes); for (i = 0; i < n_attributes; i++) cogl_object_unref (attributes[i]); indices = cogl_indices_new (context, data.indices_type, data.faces->data, data.faces->len); cogl_primitive_set_indices (priv->primitive, indices, data.faces->len); cogl_object_unref (indices); priv->min_vertex = data.min_vertex; priv->max_vertex = data.max_vertex; ret = TRUE; } g_free (display_name); g_byte_array_free (data.vertices, TRUE); if (data.faces) g_array_free (data.faces, TRUE); return ret; }