egui icon indicating copy to clipboard operation
egui copied to clipboard

epaint software renderer

Open emilk opened this issue 2 years ago • 15 comments

I would like to have a software rasterizer for epaint, so that you can take the output shapes from egui and turn it into an image.

This would be useful for many areas:

  • Generating regressions tests (make sure the GUI looks the same before/after)
  • Generating example images
  • Provide a reference for GPU renderers to compare themselves to.

Primarily I would want it to be simple and accurate rather than fast. However, a fast rasterizer would also be nice (e.g. for using egui where there is no GPU).

I wrote a software renderer for Dear ImGui a few years ago (in C++) which could probably be used as a starting point: https://github.com/emilk/imgui_software_renderer

emilk avatar Jan 17 '22 17:01 emilk

I wrote a proof of concept using tiny-skia - https://gist.github.com/tinaun/f2177e6c70f5c6602ff9863e4f05e9e4

the approach I'm using for the text rendering is giving pretty bad results though (https://i.imgur.com/nqiiwYi.png) - and I don't know if the api it presents is a good match for drawing vertex colored meshes (I haven't implemented Shape::Mesh rendering yet)

tinaun avatar Jan 25 '22 23:01 tinaun

won't including the images bloat the git repo or docs.rs ? or will there be some kind of git lfs setup?

coderedart avatar Jan 26 '22 01:01 coderedart

We can probably checksum them and just compare checksums

AlexApps99 avatar Jan 26 '22 07:01 AlexApps99

Git already does the hashing, but the docs.rs has a size limit. And if we go through different images fast enough, git repo starts increasing in size too.

there's oxipng to compress images, but idk about how high the CPU usage is.

coderedart avatar Jan 26 '22 17:01 coderedart

Please try to keep to the issue topic! How to store images for the docs is an interesting problem, but can be discussed in Discussions or on Discord!

emilk avatar Jan 26 '22 20:01 emilk

@tinaun That's a very impressive start! Perhaps the text rendering just needs a half-pixel offset? It's a shame tiny-skia doesn't have the ability to render meshes built-in, but perhaps just those parts could be copied from https://github.com/emilk/imgui_software_renderer

How is the performance?

emilk avatar Jan 26 '22 20:01 emilk

at least on my MacBook, the example in my demo runs in about 1.2 ms, with larger examples like the demo ui taking 6-10 ms per call - I don't have any super old hardware to test on but because tiny-skia is single core performance bound most processors above one ghz should be able to reach 30fps, hopefully.

moving the text bounds did improve things a little (https://i.imgur.com/rbI8u3g.png) - I think I'm running into Srgb/gamma issues since the text feels less vibrant than the live demos

for mesh rendering I'm thinking of looking at euc

tinaun avatar Jan 27 '22 19:01 tinaun

That's sounds like really good performance!

For the gamma issue, you might try changing .srgba_pixels(1.0) into .srgba_pixels(1.0 / 2.2) and see if it helps.

emilk avatar Jan 29 '22 16:01 emilk

could be related links: https://github.com/gfx-rs/wgpu/issues/644 https://github.com/gfx-rs/wgpu/blob/master/.github/workflows/ci.yml#L147 https://docs.mesa3d.org/drivers/llvmpipe.html for opengl.

coderedart avatar Feb 05 '22 08:02 coderedart

Any update on this? I'd love to see a software renderer as a built-in fallback for egui apps. Maybe piet is also worth to consider?

njust avatar Mar 15 '22 19:03 njust

I've looked at Piet, but it also lacks a gradient fill option with 2d control points - only linear and radial gradients are supported. in addition, all of the backends for Piet besides the svg backend use a system library for the actual drawing steps, and I would prefer to keep this as dependency light as possible

I might play around with using a radial gradient between mutliple control points to simulate interpolation, but i'd still be drawing each triangle in the mesh twice, once for the texture and once for the vertex color

anyway I've published my current progress here as egui_rasterizer - its not on crates.io yet, and I want to either publish it as a feature in egui or its own separate crate by the release of 0.19

tinaun avatar Jun 13 '22 10:06 tinaun

I made a renderer with skia-safe: https://github.com/lucasmerlin/egui_skia. It works well when rendering on the gpu but unfortunately it looks wrong when rendering on the cpu. I'm not sure why though, maybe someone has an idea?

View Image Bildschirmfoto 2022-08-11 um 20 09 58

In contrast to @tinaun's solution I draw the vertices with skia's .draw_vertices so that part is less complicated. Skia is a pretty huge dependency though, so this might not be the right thing for everyone.

lucasmerlin avatar Aug 11 '22 18:08 lucasmerlin

Just chiming in to mention this is something I'm also interested in seeing supported!

I've got a WIP project that's hooking into the libretro API, and while libretro does support hardware rendering on some platforms, I'm hoping to keep things as compatible as possible by targeting the base software framebuffer API.

I've got a POC working with @lucasmerlin's code (where I'm seeing the same CPU rendering issues...), and I might take a stab at trying out egui_rasterizer as well.

daniel5151 avatar Aug 27 '22 23:08 daniel5151

I asked the maintainer of tiny_skia about adding an equivalent to skia's .draw_vertices() and their response was "I don't know why anyone would use this feature", so I think moving away from skia/piet style drawing apis and just rendering the triangles manually would be the way to go, I guess.

tinaun avatar Aug 29 '22 03:08 tinaun

I fixed the cpu rendering issues I had with egui_skia. Turns out it was a skia bug, there are problems when you render identical uv coordinates (e.g. 0,0 0,0 0,0), which egui does when drawing shapes. I was able to work around that by splitting the meshes. To enable the fix, there is a feature cpu_fix, so performance when using the gpu is not affected.

Also, egui_skia is now published on creates.io. The cpu example works okay on my M1 but the metal example is a lot snappier (as one would expect).

lucasmerlin avatar Sep 01 '22 12:09 lucasmerlin

So nice, this is holy grail of my working new project. Now I've been using skia software mode instead. https://github.com/rustytsuki/egui_skia_auto_fallback_demo

rustytsuki avatar Feb 08 '23 15:02 rustytsuki