static void paint_matrix_pipeline (CoglPipeline *pipeline) { CoglMatrix matrices[4]; float matrix_floats[16 * 4]; int uniform_location; int i; for (i = 0; i < 4; i++) cogl_matrix_init_identity (matrices + i); /* Use the first matrix to make the color red */ cogl_matrix_translate (matrices + 0, 1.0f, 0.0f, 0.0f); /* Rotate the vertex so that it ends up green */ cogl_matrix_rotate (matrices + 1, 90.0f, 0.0f, 0.0f, 1.0f); /* Scale the vertex so it ends up halved */ cogl_matrix_scale (matrices + 2, 0.5f, 0.5f, 0.5f); /* Add a blue component in the final matrix. The final matrix is uploaded as transposed so we need to transpose first to cancel that out */ cogl_matrix_translate (matrices + 3, 0.0f, 0.0f, 1.0f); cogl_matrix_transpose (matrices + 3); for (i = 0; i < 4; i++) memcpy (matrix_floats + i * 16, cogl_matrix_get_array (matrices + i), sizeof (float) * 16); /* Set the first three matrices as transposed */ uniform_location = cogl_pipeline_get_uniform_location (pipeline, "matrix_array"); cogl_pipeline_set_uniform_matrix (pipeline, uniform_location, 4, /* dimensions */ 3, /* count */ FALSE, /* not transposed */ matrix_floats); /* Set the last matrix as untransposed */ uniform_location = cogl_pipeline_get_uniform_location (pipeline, "matrix_array[3]"); cogl_pipeline_set_uniform_matrix (pipeline, uniform_location, 4, /* dimensions */ 1, /* count */ TRUE, /* transposed */ matrix_floats + 16 * 3); paint_pipeline (pipeline, 12); }
static void transpose_matrix (const CoglMatrix *matrix, CoglMatrix *transpose) { const float *matrix_p = cogl_matrix_get_array (matrix); float matrix_array[16]; int i, j; /* This should probably be in Cogl */ for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) matrix_array[i * 4 + j] = matrix_p[j * 4 + i]; cogl_matrix_init_from_array (transpose, matrix_array); }
static void flush_to_fixed_api_gl (gboolean is_identity, const CoglMatrix *matrix, void *user_data) { CoglMatrixStack *stack = user_data; if (is_identity) { if (!stack->flushed_identity) GE (glLoadIdentity ()); stack->flushed_identity = TRUE; } else { GE (glLoadMatrixf (cogl_matrix_get_array (matrix)) ); stack->flushed_identity = FALSE; } }
static void _cogl_matrix_stack_flush_matrix_to_gl_builtin (CoglContext *ctx, gboolean is_identity, CoglMatrix *matrix, CoglMatrixMode mode) { g_assert (ctx->driver == COGL_DRIVER_GL || ctx->driver == COGL_DRIVER_GLES1); #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) if (ctx->flushed_matrix_mode != mode) { GLenum gl_mode = 0; switch (mode) { case COGL_MATRIX_MODELVIEW: gl_mode = GL_MODELVIEW; break; case COGL_MATRIX_PROJECTION: gl_mode = GL_PROJECTION; break; case COGL_MATRIX_TEXTURE: gl_mode = GL_TEXTURE; break; } GE (ctx, glMatrixMode (gl_mode)); ctx->flushed_matrix_mode = mode; } if (is_identity) GE (ctx, glLoadIdentity ()); else GE (ctx, glLoadMatrixf (cogl_matrix_get_array (matrix))); #endif }
static void _cogl_matrix_flush_to_gl_builtin (CoglContext *ctx, CoglBool is_identity, CoglMatrix *matrix, CoglMatrixMode mode) { g_assert (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)); #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) if (ctx->flushed_matrix_mode != mode) { GLenum gl_mode = 0; switch (mode) { case COGL_MATRIX_MODELVIEW: gl_mode = GL_MODELVIEW; break; case COGL_MATRIX_PROJECTION: gl_mode = GL_PROJECTION; break; case COGL_MATRIX_TEXTURE: gl_mode = GL_TEXTURE; break; } GE (ctx, glMatrixMode (gl_mode)); ctx->flushed_matrix_mode = mode; } if (is_identity) GE (ctx, glLoadIdentity ()); else GE (ctx, glLoadMatrixf (cogl_matrix_get_array (matrix))); #endif }
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; }