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

Handle gamma correction properly #19

Merged
merged 1 commit into from
Apr 28, 2019
Merged

Handle gamma correction properly #19

merged 1 commit into from
Apr 28, 2019

Conversation

hecrj
Copy link
Owner

@hecrj hecrj commented Apr 28, 2019

Yesterday, when I was implementing #18, I noticed text was rendering differently using gfx vs wgpu.

Here is how it looked when using OpenGL:

image

Here is how it looked when using Vulkan:

image

It's a subtle difference, but the OpenGL version is way more readable (look at the uppercase I glyph). The difference? Gamma correction.

This made me start researching about color spaces and how to deal with them, which almost drove me to insanity... But I think I figured out the problem, and the solution is quite simple.

Monitors display colors in the sRGB color space. Therefore, if you have a framebuffer with a (0.5, 0.5, 0.5) color value, it will always display the same grey, independently of the format of the framebuffer.

wgpu_glyph stores a cache of glyphs in a texture of alpha values. This value is then combined with the font color in the wgpu_glyph fragment shader. Then, the blending stage happens.

The blending stage basically combines the color outputs of the fragment shader with the color of the target buffer. If your buffer is not marked as Srgb, then the values from the target buffer will be read as if they were linear and combined with the fragment shader outputs directly. Finally, the combined color will be written directly into the target buffer. Thus, you end up with linear values in your frame buffer, which then are displayed by your monitor as if they were sRGB. Bad! This causes grey values to look darker than they should, like you can observe in the Vulkan example above.

However, when the target buffer is marked as Srgb, the values will be read as Srgb and converted into linear before blending. Additionally, the combined color will be converted back into Srgb on write. This is what the OpenGL implementation was doing.

This PR fixes the wgpu graphics backend to use Srgb buffers for textures and render targets, except for the SwapChain which we are currently copying into. It also fixes font and clear color, by converting the Color type (which is sRGB) into linear. I have also added a colors example to test that colors are rendering properly in both graphics backends.

Also added a `colors` example to showcase it.
@hecrj hecrj merged commit 569b88c into master Apr 28, 2019
@hecrj hecrj deleted the fix/gamma-correction branch April 28, 2019 18:05
@hecrj hecrj added the bug Something isn't working label May 28, 2019
@hecrj hecrj self-assigned this Jun 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant