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

RGB values in color picker don't match float values #77

Closed
zrksyd opened this issue Aug 17, 2022 · 5 comments · Fixed by #80
Closed

RGB values in color picker don't match float values #77

zrksyd opened this issue Aug 17, 2022 · 5 comments · Fixed by #80

Comments

@zrksyd
Copy link
Contributor

zrksyd commented Aug 17, 2022

The RGB values for material vectors are incorrect. Typing in 0.5 for one of the fields then looking at the color picker will show 188 instead of 128. It seems something to do with SRGB conversion. For some vectors like subsurface scattering, what I do is convert the original color from RGB to HSV, change the hue, and then convert it back to RGB. I thought the color picker would help ease that process but with the values being inaccurate I still have to convert to HSV myself.
image

@ScanMountGoat
Copy link
Owner

ScanMountGoat commented Aug 20, 2022

The material parameter values are treated as linear values in the shaders in game. The color picker control seems to be doing a conversion to sRGB internally. The displayed color in the color picker is also being converted to sRGB. If you select a color like (188, 188, 188), the color picker will show that as the RGB color. The sliders are still showing the correct linear values that will be applied in game as is.

There are a number of ways to handle this, and I wouldn't consider what egui is doing here "incorrect". I can see how this behavior might be confusing, so I'll try and look into finding a better way of doing this.

The problem is that there is rarely a direct correlation between the selected color and the model color on screen due to lighting and post processing. Calculating the output color given the user inputs is relatively straightforward. Finding the correct input color given a desired output is mathematically challenging. The color picker is just supposed to be easier to understand than RGB float values and help users interactively select values close to what they want.

@ScanMountGoat ScanMountGoat changed the title Bug with material colors RGB values in color picker don't match float values Aug 20, 2022
@zrksyd
Copy link
Contributor Author

zrksyd commented Aug 20, 2022

What if you "fake it" let me give an example.
Let's say your float is 0.5. You do some formula (I don't know the sRGB formula, I guessed and checked for this example) to get 0.216.
Use this 0.216 value for the color picker, but don't display that value to the user to avoid confusion.

@ScanMountGoat
Copy link
Owner

It sounds like you're proposing to apply the sRGB -> linear conversion to the value before passing it into the color picker. A float value of 0.5 would display as an RGB value of 127 or 128 depending on how the math works out. This seems like a reasonable approach. You can look into the options egui provides for color pickers. There might be one that does this already. https://docs.rs/egui/latest/egui/widgets/color_picker/index.html

@zrksyd
Copy link
Contributor Author

zrksyd commented Aug 21, 2022

So this works, although I had to work around the fact that the SRGB function uses u8 instead of f32. Is the use of 256 fine? I tried 255 at first, but putting 0.5 gave 127, 0.25 gave 63, etc. and that just felt off to me.

fn edit_vector4_rgba(ui: &mut Ui, data: &mut Vector4) -> bool {
    // TODO: Edit alpha for params with alpha?
    let mut color = [
        (256.0 * data.x) as u8,
        (256.0 * data.y) as u8,
        (256.0 * data.z) as u8,
    ];
    if ui.color_edit_button_srgb(&mut color).changed() {
        data.x = (color[0] as f32) / 256.0;
        data.y = (color[1] as f32) / 256.0;
        data.z = (color[2] as f32) / 256.0;
        true
    } else {
        false
    }
}

fn edit_color4f_rgba(ui: &mut Ui, data: &mut Color4f) -> bool {
    // TODO: Still show the color if the alpha is 0?
    let mut color = [
        (256.0 * data.r) as u8,
        (256.0 * data.g) as u8,
        (256.0 * data.b) as u8,
        (256.0 * data.a) as u8,
    ];
    if ui
        .color_edit_button_srgba_unmultiplied(&mut color)
        .changed()
    {
        data.r = (color[0] as f32) / 256.0;
        data.g = (color[1] as f32) / 256.0;
        data.b = (color[2] as f32) / 256.0;
        data.a = (color[3] as f32) / 256.0;
        true
    } else {
        false
    }
}

@ScanMountGoat
Copy link
Owner

0u8 should map to 0.0 and 255u8 should map to 1.0. It's ok to not be able to perfectly recreate values in between since there are only 8 bits.

@ScanMountGoat ScanMountGoat linked a pull request Aug 21, 2022 that will close this issue
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