emilk / egui

egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native
https://www.egui.rs/
Apache License 2.0
21.88k stars 1.58k forks source link

epaint software renderer #1129

Open emilk opened 2 years ago

emilk commented 2 years ago

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:

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

tinaun commented 2 years ago

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)

coderedart commented 2 years ago

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

AlexApps99 commented 2 years ago

We can probably checksum them and just compare checksums

coderedart commented 2 years ago

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.

emilk commented 2 years ago

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 commented 2 years ago

@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?

tinaun commented 2 years ago

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

emilk commented 2 years ago

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.

coderedart commented 2 years ago

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.

njust commented 2 years ago

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?

tinaun commented 2 years ago

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

lucasmerlin commented 2 years ago

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.

daniel5151 commented 2 years ago

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.

tinaun commented 2 years ago

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.

lucasmerlin commented 2 years ago

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).

rustytsuki commented 1 year ago

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