Skip to content
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

egui more pixelated than normal? #215

Closed
EriKWDev opened this issue Dec 6, 2024 · 11 comments · Fixed by #217
Closed

egui more pixelated than normal? #215

EriKWDev opened this issue Dec 6, 2024 · 11 comments · Fixed by #217

Comments

@EriKWDev
Copy link
Contributor

EriKWDev commented Dec 6, 2024

I don't know if it is just me but it looks like egui in blade is more pixelated than I am used to and I don't know what the reason is.

Left is egui with wgpu in our game and right is blade

image

image

Not perfectly scientific

@kvark
Copy link
Owner

kvark commented Dec 7, 2024

The best way to answer this question is to capture these 2 scenarios in something like RenderDoc and share the captures.

One thing that is different is the sampler. Blade is using a single Linear sampler. Wgpu's implementation is more comprehensive and it has a map of different samplers chosen based on the image.

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 7, 2024

First, to see that the sampler wasn't the issue I instead created one sampler per GuiTexture

sampler impl
#[derive(blade_macros::ShaderData)]
struct Locals {
    r_vertex_data: blade_graphics::BufferPiece,
    r_texture: blade_graphics::TextureView,
    r_sampler: blade_graphics::Sampler,
}

/// ...

        let sampler = context.create_sampler(blade_graphics::SamplerDesc {
            name,
            address_modes: {
                let mode = match options.wrap_mode {
                    egui::TextureWrapMode::ClampToEdge => blade_graphics::AddressMode::ClampToEdge,
                    egui::TextureWrapMode::Repeat => blade_graphics::AddressMode::Repeat,
                    egui::TextureWrapMode::MirroredRepeat => {
                        blade_graphics::AddressMode::MirrorRepeat
                    }
                };
                [mode; 3]
            },
            mag_filter: match options.magnification {
                egui::TextureFilter::Nearest => blade_graphics::FilterMode::Nearest,
                egui::TextureFilter::Linear => blade_graphics::FilterMode::Linear,
            },
            min_filter: match options.minification {
                egui::TextureFilter::Nearest => blade_graphics::FilterMode::Nearest,
                egui::TextureFilter::Linear => blade_graphics::FilterMode::Linear,
            },
            mipmap_filter: match options.mipmap_mode {
                Some(it) => match it {
                    egui::TextureFilter::Nearest => blade_graphics::FilterMode::Nearest,
                    egui::TextureFilter::Linear => blade_graphics::FilterMode::Linear,
                },
                None => blade_graphics::FilterMode::Linear,
            },
            ..Default::default()
        });

/// ..

                pc.bind(
                    1,
                    &Locals {
                        r_vertex_data: vertex_buf,
                        r_texture: texture.view,
                        r_sampler: texture.sampler,
                    },
                );

(side-note: omg, so easy to change where the sampler is. No bind-group description and creation..)

As this did not solve it I moved on.
I did a little investigation using eframe as it is probably a good reference as it is provided by emilk.

I first locked egui to version 0.28 in both blade and eframe as it was a version that required minimal changes to both, and also locked the window size to 800x600. I created a small gui and replicated it in both.

blade

Screenshot from 2024-12-07 18-49-17

eframe glow

Screenshot from 2024-12-07 19-16-00

eframe wgpu

Screenshot from 2024-12-07 18-49-40

I saw no visible difference between eframe's glow and wgpu renderer so sticking to wgpu going forward.

While I could see a difference upon visual inspection, by using a diff-tool diffchecker.com it is obvious there are differences between blade and eframe wgpu. Background color is off and the text differ:

diff of blade vs eframe wgpu

Screenshot 2024-12-07 at 19-45-20 Compare images to find their differences - Diffchecker

Inspecting in renderdoc we see that blade is rendering to an SRGB-aware surface whereas eframe is using a non-srgb target!

(left: blade now, right: eframe wgpu, 'Q' in Quit is extra noticeably different)

Screenshot from 2024-12-07 19-27-36

This lead me to investigate blade-egui's shader and it became clear to me it was not handling srgb the same way as egui-wgpu. It was doing gamma-correction in the vertex-shader, but to be safe I implemented it exactly the same way as in egui-wgpu.

After implementing that as well as some 'dithering' they are doing in their wgsl shader, the background color now looked much more similar in color. However, there are still noticable differences in the way the text comes out as well as the outline around the 'Quit' button:

(left: blade from #216, still not good, right: eframe wgpu)

image

I tried adjusting the color_space parameter for surface creation in blade but I couldn't get it to create a non-srgb surface.

But it seems the issue might lie somewhere in the srgb-colors...

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 7, 2024

captures, contains the render with current blade main branch, render with blade from #216 as well as render with eframe wgpu. Captured using renderdoc 1.35 on debian

blade_egui_renderdoc_captures.zip

@kvark
Copy link
Owner

kvark commented Dec 8, 2024

Thank you for investigation! I left some notes on #216.
It would also help to get a wgpu API trace, so that I can replay this on different platform.

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 8, 2024

It would also help to get a wgpu API trace, so that I can replay this on different platform.

Trying to create one, just needed to make a change to egui-wgpu and supply a directory upon device request.

However, there seems to be a wpgu regression at the moment that has removed the trace functionality?
gfx-rs/wgpu#5974

[2024-12-08T09:37:35Z ERROR wgpu::backend::wgpu_core] Feature 'trace' has been removed temporarily, see https://github.com/gfx-rs/wgpu/issues/5974

Will see if I can get it to run with older version...

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 8, 2024

I have run into a hoard of different issues with wgpu panicking on destroyed semaphores and egui-winit/egui-wgpu/winit/wgpu versions not being compatible..

Finally have a minimal reproducible that uses a version of wgpu that supports tracing as well as a version of the egui renderer that seems to produce a correct result like eframe.

Available here: https://github.com/ErikWDev/minimal_wgpu_egui

wgpu trace: egui_wgpu_trace.zip

renderdoc capture of real application egui_winit_wgpu__renderdoc_1_35_capture.zip

Sadly, when I tried to replay the wgpu trace it just produced a black screen :/ Don't know how to proceed. Hopefully the minimal code at https://github.com/ErikWDev/minimal_wgpu_egui is good enough

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 8, 2024

A new observation is that I got egui-wgpu to also render to a SRGB target but it still produces what looks like the correct results:

egui wgpu rendering to a SRGB target

image

The plot thickens

@kvark
Copy link
Owner

kvark commented Dec 8, 2024

Do you have the corresponding Blade example? or is the example in your PR does exactly this?
I took a RenderDoc capture locally from your minimal_wgpu_egui and compared it to the capture of Blade (current) that you provided. The target and source formats all match, the samplers all match.
One thing is different though - the blend mode.
wgpu:
snip-wgpu

blade:
snip-blade

So that should be easy to test

@kvark
Copy link
Owner

kvark commented Dec 8, 2024

Ok, found emilk/egui#2071
That explains our difference. It's a bit unfortunate though because any normal pipeline will want to output linear, and egui wants to output gamma. But we can work around it. I can do a small PR.

@kvark
Copy link
Owner

kvark commented Dec 8, 2024

@EriKWDev it would be great to get your feedback on #217 (ideally, a confirmation that it fixes your issue?) before we proceed.

@EriKWDev
Copy link
Contributor Author

EriKWDev commented Dec 8, 2024

Well spotted with the blending function as well as finding the source in egui for the explanation on anti-aliasing in gamma not linear

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants