-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Textured Backgrounds for Widgets and Areas #1758
Comments
Blur is difficult, as it requires a post-processing pass which complicates the egui rendering by a lot. But adding custom Once #1516 is solved this could be as easy as |
I'm not sure this is globally portable. This would require a compositor. For X11, at least, it's not guaranteed that a compositor is running at all, meaning that you would have to implement composition from scratch. |
Compositor is required for window level transparency. I am talking within egui itself. Basically, a container just draws a rectangle and fills it with background color atm. But, by allowing containers to instead take a paint callback which will draw the rectangle and use fragment shader to mix frame buffer and maybe background color of style to create blur effect. Egui itself has no idea about what is happening. It just takes a shape paint callback when container needs to draw its background. The callback could simply be drawing a texture or blur effect or whatever as the background of the window. |
I was able to accomplish this - see here. For anyone else who wants to accomplish it, the idea is basically this: register two textures at window size, let's call them Note that if you use You'll need a basic blur shader which takes a texture as input and performs a gaussian blur (you can optimize this in a few ways, primarily as a Separable Filter and/or by performing many simple box blurs). I'll call this shader Basically, you go:
Pass 1 should perform a clear operation on The reason you need two render passes and textures here is because you generally can't write to a texture while also reading from it. If anyone sees any way to do this with just one texture/pass, I'd love to hear it! For me, I used WGPU. Since a struct RenderPassExposed<'a> {
id: wgpu_core::command::RenderPass,
pub parent: &'a mut wgpu::CommandEncoder,
}
pub trait NewRenderPass<'a> {
fn encoder(&mut self) -> &'a mut wgpu::CommandEncoder;
fn begin_new_render_pass(&mut self, descriptor: &wgpu::RenderPassDescriptor<'a, '_>);
}
impl<'a> NewRenderPass<'a> for wgpu::RenderPass<'a> {
fn begin_new_render_pass(
&mut self,
descriptor: &wgpu::RenderPassDescriptor<'a, '_>
) {
*self = self.encoder().begin_render_pass(descriptor);
}
fn encoder(&mut self) -> &'a mut wgpu::CommandEncoder {
unsafe {
std::mem::transmute::<
&mut wgpu::RenderPass,
&mut RenderPassExposed,
>(self).parent
}
}
} Then in *render_pass = render_pass.begin_new_render_pass(&wgpu::RenderPassDescriptor {
// ...
} I thought a lot about how you could possibly pass the encoder to a callback, but I literally don't see any way since it's being mutably borrowed by the render_pass. I'm assuming that Let me know if that makes sense @coderedart. I can draft a simple example repo in OpenGL (or WGPU) if you're interested. I'm also working on some more in-depth tutorials for egui where I'll probably go over it in a lot more in depth (as well as other stuff like popout-window context menus) :) Regarding implementing this into egui itself, the existence of blur requires rendering to a separate texture in some capacity (the window surface texture [known in opengl as "default framebuffer"] cannot be read from, only written to as a color attachment). This is additional overhead that IMO users shouldn't be forced to opt into. These issues also prevents abstracting away blur-regions into something like a library, since it requires a totally different render pipeline. One last aside: one major optimization is to perform filter separation on the |
Is your feature request related to a problem? Please describe.
Colors of a widget decided by the
Style
. sometimes, we require more customization to create great looking games / apps.Describe the solution you'd like
allow widgets / areas to decide what they want to draw as their background. I would say the present custom paint callbacks should be a good way to let users do whatever they want.
Describe alternatives you've considered
the obvious simpler alternative is to use a image (
TextureID
) as a background. but sometimes we need to use the already drawn background pixels (game scenes / other widgets) to derive the present widget's background pixels. for example, blur themes popular in KDE desktop ricing. basically the background of a widget is transparent BUT the stuff behind the widget is slightly blurred.https://reddit.com/r/unixporn should have more examples, but a simple screenshot is here to clearly show what i mean by blur
Additional context
if using paint callbacks seems too risky / unsafe. just using a texture as a background of widget and being able to set transparency / blur in egui Style is fine too. once i realized how cool blur Styles in egui would look, i just can't stop imagining all the themes people would share.
The text was updated successfully, but these errors were encountered: