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

ClearColor and Sprite same value yields different color #4356

Closed
RobotSnowOtter opened this issue Mar 28, 2022 · 10 comments
Closed

ClearColor and Sprite same value yields different color #4356

RobotSnowOtter opened this issue Mar 28, 2022 · 10 comments
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior

Comments

@RobotSnowOtter
Copy link

Bevy version

Bevy 0.6.1

Operating system & version

Pop!_OS 21.10 x86_64

What you did

Set a sprite and the background to the same rgb value

use bevy::prelude::*;

const BG_COLOR: Color = Color::rgb(0.16, 0.16, 0.16);

fn main() {
    App::new()
        .insert_resource(ClearColor(BG_COLOR))
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn_bundle(OrthographicCameraBundle::new_2d());

    commands.spawn_bundle(SpriteBundle {
        sprite: Sprite {
            color: BG_COLOR,
            custom_size: Some(Vec2::new(50.0, 50.0)),
            ..Default::default()
        },
        ..Default::default()
    });
}

What you expected to happen

The rectangle sprite should be indistinguishable from the background.
Only one color should be visible.

What actually happened

The sprite (center) renders slightly darker than the background.

image

@RobotSnowOtter RobotSnowOtter added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Mar 28, 2022
@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen and removed S-Needs-Triage This issue needs to be labelled labels Mar 28, 2022
@alice-i-cecile
Copy link
Member

Good find. Thanks for the excellent issue and report. Under the hood, I bet this has something to do with linear vs sRGB colors.

@mockersf
Copy link
Member

mockersf commented Mar 28, 2022

Issue is that Color in wgpu is using f64, but we're using f32 then u8, and the difference is in the rounding

@CptPotato
Copy link
Contributor

Issue is that Color in wgpu is using f64, but we're using f32 then u8, and the difference is in the rounding

Is it confirmed that this is a rounding issue? I would have expected the rgb value to be off by one in that case but the values are 38 vs 41 in the screenshot.

Even considering f32 to u8 conversion, you'd expect 0.16 to be 40.8 so either 40 or 41 which matches the background color. Compared to that the sprite is too dark. Though, maybe there are other things at play, too (desktop composition / color management / etc).

@mockersf
Copy link
Member

I can reproduce the issue, and it is fixed by #4357, so I'm fairly certain it's a rounding issue somewhere

@CptPotato
Copy link
Contributor

CptPotato commented Mar 29, 2022

Didn't see the PR, thanks for elaborating. I tried it with a few different colors and they all seem to match up.

Though, I would prefer a different fix if I'm honest. With #4357 I'm not able to set accurate clear colors using Color::rgb_u8(). Anything below (13, 13, 13) is black for example.

I guess it's because the quantization to u8 is done using linear color, not srgb which makes it lose a ton of accuracy for darker colors.

@cart
Copy link
Member

cart commented Mar 29, 2022

I'm relatively certain that this is from our sprite rendering code, which converts the input color to u8s and stores them in a single u32 vertex attribute. (see vertex_color in sprite.wgsl).

If anything this is a "bug" there. One fix would be to pass each float in individually as a vec4 vertex attribute, which would increase the cost of rendering (iirc this "compression" yielded non-trivial performance wins when rendering many sprites).

@CooCooCaCha
Copy link

IMO the most important thing is accurate color. As a user I would expect the colors in my sprite to match my drawing program.

@mockersf
Copy link
Member

If anything this is a "bug" there

I'm not sure this is so much a bug as a "known limitation" that should be documented... This would only be visible when using the sprite color instead of an image, which doesn't feel like the main feature.
If a user want more accurate color, it is possible with the Mesh2dBundle instead of the SpriteBundle

@cart
Copy link
Member

cart commented Mar 29, 2022

I'm not sure this is so much a bug as a "known limitation" that should be documented... This would only be visible when using the sprite color instead of an image, which doesn't feel like the main feature.

"wrong color" is a bug imo (but i agree that this is a matter of perspective). these things should "just work" in a way that is compatible across features. if an artist cant easily say "i want this sprite to be the same color as the background", thats on us to fix i think (and probably takes precedence over optimization, at least for defaults)

@mockersf
Copy link
Member

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn_bundle(OrthographicCameraBundle::new_2d());

    commands.spawn_bundle(SpriteBundle {
        transform: Transform::from_xyz(50.0, 0.0, 0.0),
        sprite: Sprite {
            color: BG_COLOR,
            custom_size: Some(Vec2::new(100.0, 100.0)),
            ..Default::default()
        },
        ..Default::default()
    });

    commands.spawn_bundle(MaterialMesh2dBundle {
        mesh: meshes.add(Mesh::from(shape::Quad::default())).into(),
        transform: Transform::default()
            .with_scale(Vec3::splat(100.0))
            .with_translation(Vec3::new(-50.0, 0.0, 0.0)),
        material: materials.add(ColorMaterial::from(BG_COLOR)),
        ..default()
    });
}

the MaterialMesh2dBundle will have the expected color, SpriteBundle won't

@bors bors bot closed this as completed in f6bc9a0 Mar 30, 2022
aevyrie pushed a commit to aevyrie/bevy that referenced this issue Jun 7, 2022
# Objective

- Fix bevyengine#4356

## Solution

- Do not reduce the color of sprites to 4 u8
ItsDoot pushed a commit to ItsDoot/bevy that referenced this issue Feb 1, 2023
# Objective

- Fix bevyengine#4356

## Solution

- Do not reduce the color of sprites to 4 u8
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 C-Bug An unexpected or incorrect behavior
Projects
None yet
6 participants