Example #1
0
void
cogl_get_projection_matrix (CoglMatrix *matrix)
{
  cogl_framebuffer_get_projection_matrix (cogl_get_draw_framebuffer (), matrix);
}
Example #2
0
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;
}