bool ImGui_ImplGtk3Cogl_CreateDeviceObjects() { g_ColorPipeline = cogl_pipeline_new(g_Context); g_ImagePipeline = cogl_pipeline_new(g_Context); CoglError *error = NULL; if (!cogl_pipeline_set_blend(g_ColorPipeline, "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))" "A = ADD(SRC_COLOR[A], DST_COLOR*(1-SRC_COLOR[A]))", &error)) { g_warning("Blending: %s", error->message); g_error_free(error); return false; } cogl_pipeline_set_cull_face_mode(g_ColorPipeline, COGL_PIPELINE_CULL_FACE_MODE_NONE); CoglDepthState depth_state; cogl_depth_state_init(&depth_state); cogl_depth_state_set_test_enabled(&depth_state, FALSE); if (!cogl_pipeline_set_depth_state(g_ColorPipeline, &depth_state, &error)) { g_warning("Depth: %s", error->message); g_error_free(error); return false; } if (!cogl_pipeline_set_blend(g_ImagePipeline, "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))" "A = ADD(SRC_COLOR[A], DST_COLOR*(1-SRC_COLOR[A]))", &error)) { g_warning("Blending: %s", error->message); g_error_free(error); return false; } cogl_pipeline_set_cull_face_mode(g_ImagePipeline, COGL_PIPELINE_CULL_FACE_MODE_NONE); if (!cogl_pipeline_set_depth_state(g_ImagePipeline, &depth_state, &error)) { g_warning("Depth: %s", error->message); g_error_free(error); return false; } ImGui_ImplGtk3Cogl_CreateFontsTexture(); /* Disable depth buffer since we're not using it. */ //cogl_framebuffer_set_depth_write_enabled(g_Framebuffer, FALSE); return true; }
static gboolean draw_rectangle (TestState *state, int x, int y, TestDepthState *rect_state) { guint8 Cr = MASK_RED (rect_state->color); guint8 Cg = MASK_GREEN (rect_state->color); guint8 Cb = MASK_BLUE (rect_state->color); guint8 Ca = MASK_ALPHA (rect_state->color); CoglHandle pipeline; CoglDepthState depth_state; cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, rect_state->test_enable); cogl_depth_state_set_test_function (&depth_state, rect_state->test_function); cogl_depth_state_set_write_enabled (&depth_state, rect_state->write_enable); cogl_depth_state_set_range (&depth_state, rect_state->range_near, rect_state->range_far); pipeline = cogl_pipeline_new (); if (!cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL)) { cogl_object_unref (pipeline); return FALSE; } cogl_pipeline_set_color4ub (pipeline, Cr, Cg, Cb, Ca); cogl_set_source (pipeline); cogl_push_matrix (); cogl_translate (0, 0, rect_state->depth); cogl_rectangle (x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_pop_matrix (); cogl_object_unref (pipeline); return TRUE; }
static void draw_entity_camera_frustum (RigEngine *engine, RutEntity *entity, CoglFramebuffer *fb) { RutCamera *camera = rut_entity_get_component (entity, RUT_COMPONENT_TYPE_CAMERA); CoglPrimitive *primitive = rut_camera_create_frustum_primitive (camera); CoglPipeline *pipeline = cogl_pipeline_new (rut_cogl_context); CoglDepthState depth_state; /* enable depth testing */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); rut_util_draw_jittered_primitive3f (fb, primitive, 0.8, 0.6, 0.1); cogl_object_unref (primitive); cogl_object_unref (pipeline); }
static void clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) { ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); ClutterDeformEffectPrivate *priv = self->priv; CoglHandle material; CoglPipeline *pipeline; CoglDepthState depth_state; CoglFramebuffer *fb = cogl_get_draw_framebuffer (); if (priv->is_dirty) { ClutterRect rect; gboolean mapped_buffer; CoglVertexP3T2C4 *verts; ClutterActor *actor; gfloat width, height; guint opacity; gint i, j; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); opacity = clutter_actor_get_paint_opacity (actor); /* if we don't have a target size, fall back to the actor's * allocation, though wrong it might be */ if (clutter_offscreen_effect_get_target_rect (effect, &rect)) { width = clutter_rect_get_width (&rect); height = clutter_rect_get_height (&rect); } else clutter_actor_get_size (actor, &width, &height); /* XXX ideally, the sub-classes should tell us what they * changed in the texture vertices; we then would be able to * avoid resubmitting the same data, if it did not change. for * the time being, we resubmit everything */ verts = cogl_buffer_map (COGL_BUFFER (priv->buffer), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD); /* If the map failed then we'll resort to allocating a temporary buffer */ if (verts == NULL) { mapped_buffer = FALSE; verts = g_malloc (sizeof (*verts) * priv->n_vertices); } else mapped_buffer = TRUE; for (i = 0; i < priv->y_tiles + 1; i++) { for (j = 0; j < priv->x_tiles + 1; j++) { CoglVertexP3T2C4 *vertex_out; CoglTextureVertex vertex; /* CoglTextureVertex isn't an ideal structure to use for this because it contains a CoglColor. The internal layout of CoglColor is mean to be private so Clutter can not pass a pointer to it as a vertex attribute. Also it contains padding so we end up storing more data in the vertex buffer than we need to. Instead we let the application modify a dummy vertex and then copy the details back out to a more well-defined struct */ vertex.tx = (float) j / priv->x_tiles; vertex.ty = (float) i / priv->y_tiles; vertex.x = width * vertex.tx; vertex.y = height * vertex.ty; vertex.z = 0.0f; cogl_color_init_from_4ub (&vertex.color, 255, 255, 255, opacity); clutter_deform_effect_deform_vertex (self, width, height, &vertex); vertex_out = verts + i * (priv->x_tiles + 1) + j; vertex_out->x = vertex.x; vertex_out->y = vertex.y; vertex_out->z = vertex.z; vertex_out->s = vertex.tx; vertex_out->t = vertex.ty; vertex_out->r = cogl_color_get_red_byte (&vertex.color); vertex_out->g = cogl_color_get_green_byte (&vertex.color); vertex_out->b = cogl_color_get_blue_byte (&vertex.color); vertex_out->a = cogl_color_get_alpha_byte (&vertex.color); } } if (mapped_buffer) cogl_buffer_unmap (COGL_BUFFER (priv->buffer)); else { cogl_buffer_set_data (COGL_BUFFER (priv->buffer), 0, /* offset */ verts, sizeof (*verts) * priv->n_vertices); g_free (verts); } priv->is_dirty = FALSE; } material = clutter_offscreen_effect_get_target (effect); pipeline = COGL_PIPELINE (material); /* enable depth testing */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); /* enable backface culling if we have a back material */ if (priv->back_pipeline != NULL) cogl_pipeline_set_cull_face_mode (pipeline, COGL_PIPELINE_CULL_FACE_MODE_BACK); /* draw the front */ if (material != NULL) cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive); /* draw the back */ if (priv->back_pipeline != NULL) { CoglPipeline *back_pipeline; /* We probably shouldn't be modifying the user's material so instead we make a temporary copy */ back_pipeline = cogl_pipeline_copy (priv->back_pipeline); cogl_pipeline_set_depth_state (back_pipeline, &depth_state, NULL); cogl_pipeline_set_cull_face_mode (back_pipeline, COGL_PIPELINE_CULL_FACE_MODE_FRONT); cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive); cogl_object_unref (back_pipeline); } if (G_UNLIKELY (priv->lines_primitive != NULL)) { CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx); cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0); cogl_framebuffer_draw_primitive (fb, lines_pipeline, priv->lines_primitive); cogl_object_unref (lines_pipeline); } }
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 CoglBool draw_rectangle (TestState *state, int x, int y, TestDepthState *rect_state, CoglBool legacy_mode) { uint8_t Cr = MASK_RED (rect_state->color); uint8_t Cg = MASK_GREEN (rect_state->color); uint8_t Cb = MASK_BLUE (rect_state->color); uint8_t Ca = MASK_ALPHA (rect_state->color); CoglPipeline *pipeline; CoglDepthState depth_state; cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, rect_state->test_enable); cogl_depth_state_set_test_function (&depth_state, rect_state->test_function); cogl_depth_state_set_write_enabled (&depth_state, rect_state->write_enable); cogl_depth_state_set_range (&depth_state, rect_state->range_near, rect_state->range_far); pipeline = cogl_pipeline_new (test_ctx); if (!cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL)) { cogl_object_unref (pipeline); return FALSE; } if (!legacy_mode) { cogl_pipeline_set_color4ub (pipeline, Cr, Cg, Cb, Ca); cogl_framebuffer_set_depth_write_enabled (test_fb, rect_state->fb_write_enable); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, 0, 0, rect_state->depth); cogl_framebuffer_draw_rectangle (test_fb, pipeline, x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_framebuffer_pop_matrix (test_fb); } else { cogl_push_framebuffer (test_fb); cogl_push_matrix (); cogl_set_source_color4ub (Cr, Cg, Cb, Ca); cogl_translate (0, 0, rect_state->depth); cogl_rectangle (x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_pop_matrix (); cogl_pop_framebuffer (); } cogl_object_unref (pipeline); return TRUE; }
static CoglPipeline * create_1d_gaussian_blur_pipeline (RutContext *ctx, int n_taps) { static GHashTable *pipeline_cache = NULL; CoglPipeline *pipeline; CoglSnippet *snippet; GString *shader; CoglDepthState depth_state; int i; /* initialize the pipeline cache. The shaders are only dependent on the * number of taps, not the sigma, so we cache the corresponding pipelines * in a hash table 'n_taps' => 'pipeline' */ if (G_UNLIKELY (pipeline_cache == NULL)) { pipeline_cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, /* key destroy notify */ (GDestroyNotify) cogl_object_unref); } pipeline = g_hash_table_lookup (pipeline_cache, GINT_TO_POINTER (n_taps)); if (pipeline) return cogl_object_ref (pipeline); shader = g_string_new (NULL); g_string_append_printf (shader, "uniform vec2 pixel_step;\n" "uniform float factors[%i];\n", n_taps); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, shader->str, NULL /* post */); g_string_set_size (shader, 0); pipeline = cogl_pipeline_new (ctx->cogl_context); cogl_pipeline_set_layer_null_texture (pipeline, 0, /* layer_num */ COGL_TEXTURE_TYPE_2D); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, /* layer_num */ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); cogl_pipeline_set_layer_filters (pipeline, 0, /* layer_num */ COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); for (i = 0; i < n_taps; i++) { g_string_append (shader, "cogl_texel "); if (i == 0) g_string_append (shader, "="); else g_string_append (shader, "+="); g_string_append_printf (shader, " texture2D (cogl_sampler, " "cogl_tex_coord.st"); if (i != (n_taps - 1) / 2) g_string_append_printf (shader, " + pixel_step * %f", (float) (i - ((n_taps - 1) / 2))); g_string_append_printf (shader, ") * factors[%i];\n", i); } cogl_snippet_set_replace (snippet, shader->str); g_string_free (shader, TRUE); cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); cogl_object_unref (snippet); cogl_pipeline_set_blend (pipeline, "RGBA=ADD(SRC_COLOR, 0)", NULL); cogl_depth_state_init (&depth_state); cogl_depth_state_set_write_enabled (&depth_state, FALSE); cogl_depth_state_set_test_enabled (&depth_state, FALSE); cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); g_hash_table_insert (pipeline_cache, GINT_TO_POINTER (n_taps), pipeline); return pipeline; }
static CoglPipeline * get_entity_color_pipeline (RigEngine *engine, RutEntity *entity, RutComponent *geometry, CoglBool blended) { CoglSnippet *snippet; CoglDepthState depth_state; RutMaterial *material; CoglTexture *texture = NULL; CoglTexture *normal_map = NULL; CoglTexture *alpha_mask = NULL; CoglPipeline *pipeline; CoglFramebuffer *shadow_fb; if (blended) pipeline = rut_entity_get_pipeline_cache (entity, CACHE_SLOT_COLOR_BLENDED); else pipeline = rut_entity_get_pipeline_cache (entity, CACHE_SLOT_COLOR_UNBLENDED); if (pipeline) { cogl_object_ref (pipeline); goto FOUND; } pipeline = cogl_pipeline_new (engine->ctx->cogl_context); material = rut_entity_get_component (entity, RUT_COMPONENT_TYPE_MATERIAL); if (material) { RutAsset *texture_asset = rut_material_get_texture_asset (material); RutAsset *normal_map_asset = rut_material_get_normal_map_asset (material); RutAsset *alpha_mask_asset = rut_material_get_alpha_mask_asset (material); if (texture_asset) texture = rut_asset_get_texture (texture_asset); if (texture) cogl_pipeline_set_layer_texture (pipeline, 1, texture); if (normal_map_asset) normal_map = rut_asset_get_texture (normal_map_asset); if (alpha_mask_asset) alpha_mask = rut_asset_get_texture (alpha_mask_asset); } #if 0 /* NB: Our texture colours aren't premultiplied */ cogl_pipeline_set_blend (pipeline, "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))" "A = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))", NULL); #endif #if 0 if (rut_object_get_type (geometry) == &rut_shape_type) rut_geometry_component_update_pipeline (geometry, pipeline); pipeline = cogl_pipeline_new (rut_cogl_context); #endif cogl_pipeline_set_color4f (pipeline, 0.8f, 0.8f, 0.8f, 1.f); /* enable depth testing */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); if (blended) cogl_depth_state_set_write_enabled (&depth_state, FALSE); cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); /* Vertex shader setup for lighting */ cogl_pipeline_add_snippet (pipeline, engine->lighting_vertex_snippet); if (normal_map) cogl_pipeline_add_snippet (pipeline, engine->normal_map_vertex_snippet); if (rut_entity_get_receive_shadow (entity)) cogl_pipeline_add_snippet (pipeline, engine->shadow_mapping_vertex_snippet); /* and fragment shader */ /* XXX: ideally we wouldn't have to rely on conditionals + discards * in the fragment shader to differentiate blended and unblended * regions and instead we should let users mark out opaque regions * in geometry. */ cogl_pipeline_add_snippet (pipeline, blended ? engine->blended_discard_snippet : engine->unblended_discard_snippet); cogl_pipeline_add_snippet (pipeline, engine->unpremultiply_snippet); if (material) { if (alpha_mask) { /* We don't want this layer to be automatically modulated with the * previous layers so we set its combine mode to "REPLACE" so it * will be skipped past and we can sample its texture manually */ cogl_pipeline_set_layer_combine (pipeline, 2, "RGBA=REPLACE(PREVIOUS)", NULL); cogl_pipeline_set_layer_texture (pipeline, 2, alpha_mask); cogl_pipeline_add_snippet (pipeline, engine->alpha_mask_snippet); } if (normal_map) { /* We don't want this layer to be automatically modulated with the * previous layers so we set its combine mode to "REPLACE" so it * will be skipped past and we can sample its texture manually */ cogl_pipeline_set_layer_combine (pipeline, 5, "RGBA=REPLACE(PREVIOUS)", NULL); cogl_pipeline_set_layer_texture (pipeline, 5, normal_map); snippet = engine->normal_map_fragment_snippet; } else { snippet = engine->material_lighting_snippet; } } else { snippet = engine->simple_lighting_snippet; } cogl_pipeline_add_snippet (pipeline, snippet); if (rut_entity_get_receive_shadow (entity)) { /* Hook the shadow map sampling */ cogl_pipeline_set_layer_texture (pipeline, 7, engine->shadow_map); /* For debugging the shadow mapping... */ //cogl_pipeline_set_layer_texture (pipeline, 7, engine->shadow_color); //cogl_pipeline_set_layer_texture (pipeline, 7, engine->gradient); /* We don't want this layer to be automatically modulated with the * previous layers so we set its combine mode to "REPLACE" so it * will be skipped past and we can sample its texture manually */ cogl_pipeline_set_layer_combine (pipeline, 7, "RGBA=REPLACE(PREVIOUS)", NULL); /* Handle shadow mapping */ cogl_pipeline_add_snippet (pipeline, engine->shadow_mapping_fragment_snippet); } cogl_pipeline_add_snippet (pipeline, engine->premultiply_snippet); if (rut_object_get_type (geometry) == &rut_shape_type) { CoglTexture *shape_texture; if (rut_shape_get_shaped (RUT_SHAPE (geometry))) { shape_texture = rut_shape_get_shape_texture (RUT_SHAPE (geometry)); cogl_pipeline_set_layer_texture (pipeline, 0, shape_texture); } rut_shape_add_reshaped_callback (RUT_SHAPE (geometry), reshape_cb, NULL, NULL); } else if (rut_object_get_type (geometry) == &rut_diamond_type) rut_diamond_apply_mask (RUT_DIAMOND (geometry), pipeline); if (!blended) { cogl_pipeline_set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); rut_entity_set_pipeline_cache (entity, CACHE_SLOT_COLOR_UNBLENDED, pipeline); } else { rut_entity_set_pipeline_cache (entity, CACHE_SLOT_COLOR_BLENDED, pipeline); } FOUND: /* FIXME: there's lots to optimize about this! */ shadow_fb = COGL_FRAMEBUFFER (engine->shadow_fb); /* update uniforms in pipelines */ { CoglMatrix light_shadow_matrix, light_projection; CoglMatrix model_transform; const float *light_matrix; int location; cogl_framebuffer_get_projection_matrix (shadow_fb, &light_projection); /* XXX: This is pretty bad that we are having to do this. It would * be nicer if cogl exposed matrix-stacks publicly so we could * maintain the entity model_matrix incrementally as we traverse * the scenegraph. */ rut_graphable_get_transform (entity, &model_transform); get_light_modelviewprojection (&model_transform, engine->light, &light_projection, &light_shadow_matrix); light_matrix = cogl_matrix_get_array (&light_shadow_matrix); location = cogl_pipeline_get_uniform_location (pipeline, "light_shadow_matrix"); cogl_pipeline_set_uniform_matrix (pipeline, location, 4, 1, FALSE, light_matrix); } return pipeline; }
static CoglPipeline * get_entity_mask_pipeline (RigEngine *engine, RutEntity *entity, RutComponent *geometry) { CoglPipeline *pipeline; pipeline = rut_entity_get_pipeline_cache (entity, CACHE_SLOT_SHADOW); if (pipeline) return cogl_object_ref (pipeline); /* TODO: move into init() somewhere */ if (G_UNLIKELY (!engine->dof_pipeline_template)) { CoglPipeline *pipeline; CoglDepthState depth_state; CoglSnippet *snippet; pipeline = cogl_pipeline_new (engine->ctx->cogl_context); cogl_pipeline_set_color_mask (pipeline, COGL_COLOR_MASK_ALPHA); cogl_pipeline_set_blend (pipeline, "RGBA=ADD(SRC_COLOR, 0)", NULL); cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, /* definitions */ "uniform float dof_focal_distance;\n" "uniform float dof_depth_of_field;\n" "varying float dof_blur;\n", //"varying vec4 world_pos;\n", /* compute the amount of bluriness we want */ "vec4 world_pos = cogl_modelview_matrix * cogl_position_in;\n" //"world_pos = cogl_modelview_matrix * cogl_position_in;\n" "dof_blur = 1.0 - clamp (abs (world_pos.z - dof_focal_distance) /\n" " dof_depth_of_field, 0.0, 1.0);\n" ); cogl_pipeline_add_snippet (pipeline, snippet); cogl_object_unref (snippet); /* This was used to debug the focal distance and bluriness amount in the DoF * effect: */ #if 0 cogl_pipeline_set_color_mask (pipeline, COGL_COLOR_MASK_ALL); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "varying vec4 world_pos;\n" "varying float dof_blur;", "cogl_color_out = vec4(dof_blur,0,0,1);\n" //"cogl_color_out = vec4(1.0, 0.0, 0.0, 1.0);\n" //"if (world_pos.z < -30.0) cogl_color_out = vec4(0,1,0,1);\n" //"if (abs (world_pos.z + 30.f) < 0.1) cogl_color_out = vec4(0,1,0,1);\n" "cogl_color_out.a = dof_blur;\n" //"cogl_color_out.a = 1.0;\n" ); cogl_pipeline_add_snippet (pipeline, snippet); cogl_object_unref (snippet); #endif engine->dof_pipeline_template = pipeline; } /* TODO: move into init() somewhere */ if (G_UNLIKELY (!engine->dof_diamond_pipeline)) { CoglPipeline *dof_diamond_pipeline = cogl_pipeline_copy (engine->dof_pipeline_template); CoglSnippet *snippet; cogl_pipeline_set_layer_texture (dof_diamond_pipeline, 0, engine->ctx->circle_texture); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, /* declarations */ "varying float dof_blur;", /* post */ "if (cogl_color_out.a <= 0.0)\n" " discard;\n" "\n" "cogl_color_out.a = dof_blur;\n"); cogl_pipeline_add_snippet (dof_diamond_pipeline, snippet); cogl_object_unref (snippet); engine->dof_diamond_pipeline = dof_diamond_pipeline; } /* TODO: move into init() somewhere */ if (G_UNLIKELY (!engine->dof_unshaped_pipeline)) { CoglPipeline *dof_unshaped_pipeline = cogl_pipeline_copy (engine->dof_pipeline_template); CoglSnippet *snippet; snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, /* declarations */ "varying float dof_blur;", /* post */ "if (cogl_color_out.a < 0.25)\n" " discard;\n" "\n" "cogl_color_out.a = dof_blur;\n"); cogl_pipeline_add_snippet (dof_unshaped_pipeline, snippet); cogl_object_unref (snippet); engine->dof_unshaped_pipeline = dof_unshaped_pipeline; } /* TODO: move into init() somewhere */ if (G_UNLIKELY (!engine->dof_pipeline)) { CoglPipeline *dof_pipeline = cogl_pipeline_copy (engine->dof_pipeline_template); CoglSnippet *snippet; /* store the bluriness in the alpha channel */ snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "varying float dof_blur;", "cogl_color_out.a = dof_blur;\n" ); cogl_pipeline_add_snippet (dof_pipeline, snippet); cogl_object_unref (snippet); engine->dof_pipeline = dof_pipeline; } if (rut_object_get_type (geometry) == &rut_diamond_type) { pipeline = cogl_object_ref (engine->dof_diamond_pipeline); } else if (rut_object_get_type (geometry) == &rut_shape_type) { RutMaterial *material = rut_entity_get_component (entity, RUT_COMPONENT_TYPE_MATERIAL); pipeline = cogl_pipeline_copy (engine->dof_unshaped_pipeline); if (rut_shape_get_shaped (RUT_SHAPE (geometry))) { CoglTexture *shape_texture = rut_shape_get_shape_texture (RUT_SHAPE (geometry)); cogl_pipeline_set_layer_texture (pipeline, 0, shape_texture); } if (material) { RutAsset *texture_asset = rut_material_get_texture_asset (material); RutAsset *alpha_mask_asset = rut_material_get_alpha_mask_asset (material); if (texture_asset) cogl_pipeline_set_layer_texture (pipeline, 1, rut_asset_get_texture (texture_asset)); if (alpha_mask_asset) { /* We don't want this layer to be automatically modulated with the * previous layers so we set its combine mode to "REPLACE" so it * will be skipped past and we can sample its texture manually */ cogl_pipeline_set_layer_combine (pipeline, 2, "RGBA=REPLACE(PREVIOUS)", NULL); cogl_pipeline_set_layer_texture (pipeline, 2, rut_asset_get_texture (alpha_mask_asset)); cogl_pipeline_add_snippet (pipeline, engine->alpha_mask_snippet); } } } else pipeline = cogl_object_ref (engine->dof_pipeline); rut_entity_set_pipeline_cache (entity, CACHE_SLOT_SHADOW, pipeline); return pipeline; }