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

MSAA Changes colors and adds borders around sprites #419

Closed
TheNeikos opened this issue Sep 2, 2020 · 10 comments
Closed

MSAA Changes colors and adds borders around sprites #419

TheNeikos opened this issue Sep 2, 2020 · 10 comments
Labels
A-Rendering Drawing game state to the screen

Comments

@TheNeikos
Copy link
Contributor

TheNeikos commented Sep 2, 2020

When setting a Msaa level above 1 sample the color changes:

Msaa 1:
image

Msaa 2:
image

Msaa 4:
image

Code:

use bevy::prelude::*;
use bevy::render::pass::ClearColor;

fn main() {
    env_logger::init();
    App::build()
        .add_resource(Msaa { samples: 4 })
        .add_resource(ClearColor(Color::rgb(0.5, 0.5, 0.0)))
        .add_default_plugins()
        .add_startup_system(setup.system())
        .run();
}

struct Square(u64);

fn setup(
    mut commands: Commands,
    mut materials: ResMut<Assets<ColorMaterial>>,
    asset_server: Res<AssetServer>,
) {
    commands
        .spawn(Camera2dComponents::default())
        .spawn(UiCameraComponents::default())
        .spawn((Square(1), Translation::new(0., 20., 0.)))
        .with_children(|parent| {
            parent.spawn(SpriteComponents {
                material: materials.add(Color::rgb(1.0, 0.2, 0.2).into()),
                sprite: Sprite {
                    size: Vec2::new(25., 25.),
                },
                translation: Translation::new(0., 0., 0.),
                ..Default::default()
            });
        });
}

My platform is Linux with an NVIDIA Corporation GP107GLM [Quadro P620] GPU

@GabCampbell GabCampbell added the A-Rendering Drawing game state to the screen label Sep 2, 2020
@julhe
Copy link
Contributor

julhe commented Sep 2, 2020

Hmm, I can't reproduce this under Windows 10 x64 with a AMD R9 390.

Could you test this https://github.com/gfx-rs/wgpu-rs/tree/master/examples/msaa-line? Change the MSAA level with the left and right arrow key and see if the problem is also present there.

@TheNeikos
Copy link
Contributor Author

@julhe No, it doesn't happen there

@TheNeikos
Copy link
Contributor Author

TheNeikos commented Sep 12, 2020

Another test on Win10 with an GTX 1060:

Msaa 1:
image

Msaa 4:
image

Msaa 8:
image

It getting blurrier doesn't make too much sense imo as the sprite itself should be directly on a pixel edge (and isn't Msaa meant to make things crisp?)

Another weird thing is the background. It is set to rgb(0.5, 0.5, 0.0) which translated to non-float values would be rgb(128, 128, 0) (or 127 depending on rounding mode). But at Msaa 1 it displays it with rgb(187, 187, 0)! Which is also what I'm getting on Windows. So it seems that I got it the wrong way around! Msaa { 1 } actually clears everything in the wrong color on Linux, and on Windows it seems to be always wrong.

Am I understanding this correctly?

@cart
Copy link
Member

cart commented Sep 12, 2020

As @StarArawn mentioned on discord, the weird multisampling behavior might be related to: gfx-rs/wgpu#725. I think we should treat this issue as scoped to that problem.

A little bit of blurriness is to be expected with MSAA. It makes jagged edges crisper by taking multiple samples and blending them together (which is the literal definition of a blur operation). This makes jagged edges crisper, but it can make already straight lines a little bit blurry.

I do think we have another issue though. I also get the same "incorrect color" results on my computer (linux, proprietary nvidia drivers). I'm pretty sure the incorrect "base" colors are related to bevy rendering with the srgb color space. I have a feeling we aren't doing a proper conversion here. The math certainly lines up with improper color handling.

Desired linear color value: 0.5
SRGB to Linear Conversion: ((0.5 + 0.055) / 1.055) ^ 2.4 = 0.214
Rendering with Color::rgb(0.214, 0.214, 0.0) and color picking = rgb(128, 128, 0)

So by using an SRGB->Linear conversion before rendering, we get the expected output.

I'm pretty sure we're locked into an SRGB swap chain, so we might need to do these conversions internally.

@cart
Copy link
Member

cart commented Sep 12, 2020

As a followup, loaded images do use the correct colors (and also use the SRGB image type), so I think the fix to the "base color" problem is it convert the Color type before uploading to the shader.

@TheNeikos
Copy link
Contributor Author

TheNeikos commented Sep 13, 2020

@cart I understand that some things might get a bit more blurry, but it also adds a discolored edge to sprites which it imo should not do

For example, in my game this is what it looks with Msaa 8:
image

and without:
image

@cart
Copy link
Member

cart commented Sep 13, 2020

@TheNeikos hmm yeah thats not desirable. I'm honestly uncertain if thats a bevy issue, a wgpu issue, or a general MSAA issue.

@cwfitzgerald
Copy link

Fully agree that this is just gfx-rs/wgpu#725. It manifests exactly as the photos show; borked srgb conversion of the background plus bad MSAA. It's been a long-standing issue with intel (at least on linux), and just needs to be worked around at some layer.

@rparrett
Copy link
Contributor

rparrett commented Jan 5, 2022

gfx-rs/wgpu#725 is apparently fixed since wgpu 0.11.

Anyone affected still able to reproduce with bevy main?

@cart
Copy link
Member

cart commented May 25, 2022

I think its probably safe to close this for now and then re-open if this resurfaces.

@cart cart closed this as completed May 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen
Projects
None yet
Development

No branches or pull requests

6 participants