st: Generate shadows from the silhouette of the source texture
As first mentioned in commit 672171093
, the CSS spec defines shadow
colors independently from the colors casting the shadow. It's not
a physical light simulation so a shadow is allowed to be a different
color from texture casting it.
This means we only care about the shape of the source where alpha
values of zero are adjacent to alpha values of non-zero. And all such
non-zero pixels should be treated as fully opaque for the purpose of
shadow generation. While this would be wrong for a physical light
simulation it does allow us to cast shadows around semi-translucent
shapes and better support CSS.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4477
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1918>
This commit is contained in:
parent
b3c7a855c6
commit
918c063693
@ -394,7 +394,10 @@ _st_create_shadow_pipeline (StShadow *shadow_spec,
|
|||||||
float sigma;
|
float sigma;
|
||||||
int src_height, dst_height;
|
int src_height, dst_height;
|
||||||
int src_width, dst_width;
|
int src_width, dst_width;
|
||||||
|
CoglPipeline *texture_pipeline;
|
||||||
|
|
||||||
|
static CoglPipelineKey texture_pipeline_key =
|
||||||
|
"st-create-shadow-pipeline-saturate-alpha";
|
||||||
static CoglPipeline *shadow_pipeline_template = NULL;
|
static CoglPipeline *shadow_pipeline_template = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (shadow_spec != NULL, NULL);
|
g_return_val_if_fail (shadow_spec != NULL, NULL);
|
||||||
@ -433,10 +436,34 @@ _st_create_shadow_pipeline (StShadow *shadow_spec,
|
|||||||
});
|
});
|
||||||
|
|
||||||
/* Texture */
|
/* Texture */
|
||||||
texture_node = clutter_texture_node_new (src_texture,
|
texture_pipeline = cogl_context_get_named_pipeline (ctx,
|
||||||
0,
|
&texture_pipeline_key);
|
||||||
CLUTTER_SCALING_FILTER_NEAREST,
|
|
||||||
CLUTTER_SCALING_FILTER_NEAREST);
|
if (G_UNLIKELY (texture_pipeline == NULL))
|
||||||
|
{
|
||||||
|
CoglSnippet *snippet;
|
||||||
|
|
||||||
|
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
|
||||||
|
"",
|
||||||
|
"if (cogl_color_out.a > 0.0)\n"
|
||||||
|
" cogl_color_out.a = 1.0;");
|
||||||
|
|
||||||
|
texture_pipeline = cogl_pipeline_new (ctx);
|
||||||
|
cogl_pipeline_add_snippet (texture_pipeline, snippet);
|
||||||
|
cogl_object_unref (snippet);
|
||||||
|
|
||||||
|
cogl_context_set_named_pipeline (ctx,
|
||||||
|
&texture_pipeline_key,
|
||||||
|
texture_pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No need to unref texture_pipeline since the named pipeline hash
|
||||||
|
* doesn't change its ref count from 1. Also no need to copy texture_pipeline
|
||||||
|
* since we'll be completely finished with it after clutter_paint_node_paint.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cogl_pipeline_set_layer_texture (texture_pipeline, 0, src_texture);
|
||||||
|
texture_node = clutter_pipeline_node_new (texture_pipeline);
|
||||||
clutter_paint_node_add_child (blur_node, texture_node);
|
clutter_paint_node_add_child (blur_node, texture_node);
|
||||||
clutter_paint_node_add_rectangle (texture_node,
|
clutter_paint_node_add_rectangle (texture_node,
|
||||||
&(ClutterActorBox) {
|
&(ClutterActorBox) {
|
||||||
|
Loading…
Reference in New Issue
Block a user