Skip to content

Painting with opacity #7623

@Treeniks

Description

@Treeniks

I'm trying to work out how to do replicate egui's painting demo with a highlighter-like stroke.

That is, a thick stroke (32.0 width or higher) with a half-transparent color.

With the simple demo and naively giving the stroke color transparency, it looks all wrong because the different shapes overlap at the seams:
Image

I have tried a few things to fix this, none of them have worked all that well.

  • combining all egui::Shape::LineSegment into a single egui::Shape::Vec changed nothing
  • using a different library like lyon to first create a mesh and then using egui::Shape::Mesh, same result
    • although lyon had the additional benefit of supporting line caps and line joins, those would be nice to haves in egui as well
    • both vertex colors and using a texture had the same result
    • I guess lyon also generates overlaps in the mesh
  • using ui.set_opacity before painting, no difference

My understanding is that egui paints the shapes as they come in, meaning a "paint shapes, then apply opacity globally" isn't really a thing egui can do currently. In Qt, I can use a Canvas to draw things and then apply opacity to the whole canvas, but I believe that would require some kind of multi-pass rendering and thus isn't doable with egui?

Shape::Path, Shape::Mesh and Shape::Vec could have some way to set a global opacity to the whole shape. I assume this would require significant changes to how these are handled though.

Another option is the ability to do the painting into a separate texture and just display that as an image. Then I can draw opaque shapes into the texture and apply one global opacity to the whole image. It would be impossible to use different opacities in a single drawing, but it's more than enough for my use case. This seems related to #4432, just that my usecase isn't for testing and so egui_kittest::Harness isn't really the right tool here. I tried getting this done manually with egui_glow, but I don't understand the rendering well enough and didn't really get anywhere.

I did a little test using tiny_skia. It's very unperformant because it doesn't use the GPU, but rendering out an image with skia and then displaying that with a global opacity did work. skia also looked correct even if I just gave the stroke itself opacity, so tiny_skia already deals with this itself it seems.

Lastly, maybe there is a way to create a mask of the previous shapes to prevent drawing of overlapping areas?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions