Jump to content
The Dark Mod Forums

Gamma correction, re-revisited


duzenko

Gamma poll  

10 members have voted

  1. 1. Is the 'dark' picture in post 4 too dark?

    • Yes
      5
    • No
      5
  2. 2. Is the 'bright' picture overbleached?

    • Yes
      6
    • No
      4


Recommended Posts

Ok, how about this.

We add a trivial shader, which only applies r_gamma and r_brightness to the scene. If postprocessing is off, we just run it over the whole screen. If it is on, we run it after postprocessing is over. We run it as the very final step in any case!

So we can finally remove stupid monitor tables and Linux equivalents. Color banding still here, of course. Ambient tweaks and SRGB stay as experimental stuff.

 

Speaking about color banding with SRGB. There should be no color banding if you display srgb buffer "as is". Such buffer is already in gamma space, native for the monitor. The difference from RGB is that shader automatically converts inputs from gamma space to linear space and outputs from linear back to gamma. But if you want to do any additional gamma adjustments, then you are screwed without high precision buffers.

Link to comment
Share on other sites

14 hours ago, stgatilov said:

Ok, how about this.

We add a trivial shader, which only applies r_gamma and r_brightness to the scene. If postprocessing is off, we just run it over the whole screen. If it is on, we run it after postprocessing is over. We run it as the very final step in any case!

So we can finally remove stupid monitor tables and Linux equivalents. Color banding still here, of course. Ambient tweaks and SRGB stay as experimental stuff.

No objections from me since I use neither. I do use ambient min brightness, wouldn't want that lost.

Quote

Speaking about color banding with SRGB. There should be no color banding if you display srgb buffer "as is". Such buffer is already in gamma space, native for the monitor. The difference from RGB is that shader automatically converts inputs from gamma space to linear space and outputs from linear back to gamma. But if you want to do any additional gamma adjustments, then you are screwed without high precision buffers.

After playing with this for months, I am more frustrated and confused than ever

The default framebuffer (the one we blit to) is always linear. Unless I'm completely mistaken, it means there must be a conversion and there's no way we can send sRGB frame to monitor without that.

And there's still the issue of the digital GPU-monitor interface, which is normalized for all DWM windows and is most likely linear as well. Not that I'm an expert in that, but speculating here.

Link to comment
Share on other sites

12 minutes ago, duzenko said:

No objections from me since I use neither. I do use ambient min brightness, wouldn't want that lost.

The cvars will works as usual.

One thing I also want to try is to optionally add a clever dithering to make color banding unnoticeable. Not a good thing for TDM with its visual style, but perhaps some players would prefer it to obvious color banding.

 

Quote

The default framebuffer (the one we blit to) is always linear. Unless I'm completely mistaken, it means there must be a conversion and there's no way we can send sRGB frame to monitor without that.

I'm afraid there is some sort of misunderstanding here.

The "linear space" is where we can sum colors with mathematical addition and that would work like how light intensities add in the real world. It is also called RGB, but this is even more confusing, because when people hear RGB, they think it is what was always around, which is exactly opposite. The "gamma space" is also called SRGB, this is the representation which monitors expect from rendering output (omitting some minor details like different gamma value in different monitors). SRGB is what has been all around us since the beginning. Almost all image files are stored in SRGB space, they look correct when you open them in ordinary image editor since it just sends this data to monitor. Textures of a modern gamma-correct game may also be represented in linear space: in this case opening them in something stupid like paint would show them as too dark. Although they are most likely in such formats that point won't open them.

The old approach of rendering is: everything is in 8-bit SRGB (gamma space). No conversion is done when opening ordinary image files, no conversion necessary after rendering is done. However, when renderer computes lighting, it adds intensities with simple addition straight in the gamma space (SRGB). It is incorrect, so lights blending and quadratic falloff look wrong. It would be correct if rendering was in linear space, but it is not. This is how Doom 3 is working, and this is how TDM normally works.

The first solution to the problem is rendering everything in linear space (RGB). Then you store all textures in linear space (i.e. they look wrong when you open them in paint), you store all FBOs in linear space. At the very end of rendering, you do gamma correction as the final pass, thus converting color from linear space to gamma space in order to send it to monitor. To avoid color banding from final gamma correction, you use HDR, i.e. high-precision color formats.

The second solution is to use SRGB support in OpenGL. You mark incoming textures as SRGB, and mark your FBO as SRGB. It does not magically changes anything, because in TDM they are all SRGB regardless of whether you mark them or not. But now blending and texture filtering have convert from gamma space to linear space before operation, and from linear space back to gamma space after operation. Thus, intensities are adding up properly. Moveover, when you fetch data from texture marked as SRGB in your shader, OpenGL automatically converts it from gamma space to linear space before returning it. If you write output color to SRGB buffer (and have enabled something on that FBO), then OpenGL automatically converts it from linear space into gamma space. So whatever you have in your shader is in linear space (and most likely in 32-bit float), but all data out of shader is in gamma space (and most likely 8-bit since if you use more precision than the first solution is better).

So you are wrong saying that default framebuffer is linear. It always contains SRGB (gamma space) data. And our textures always contain SRGB data. The only problem is that we incorrectly deal with this SRGB data all over the renderer. And using the SRGB extension in OpenGL allows to fix that, forcing OpenGL to auto-convert to linear space and back around every operation which could add colors.

Link to comment
Share on other sites

54 minutes ago, stgatilov said:

I'm afraid there is some sort of misunderstanding here.

The "linear space" is where we can sum colors with mathematical addition and that would work like how light intensities add in the real world. It is also called RGB, but this is even more confusing, because when people hear RGB, they think it is what was always around, which is exactly opposite. The "gamma space" is also called SRGB, this is the representation which monitors expect from rendering output (omitting some minor details like different gamma value in different monitors). SRGB is what has been all around us since the beginning. Almost all image files are stored in SRGB space, they look correct when you open them in ordinary image editor since it just sends this data to monitor. Textures of a modern gamma-correct game may also be represented in linear space: in this case opening them in something stupid like paint would show them as too dark. Although they are most likely in such formats that point won't open them.

The old approach of rendering is: everything is in 8-bit SRGB (gamma space). No conversion is done when opening ordinary image files, no conversion necessary after rendering is done. However, when renderer computes lighting, it adds intensities with simple addition straight in the gamma space (SRGB). It is incorrect, so lights blending and quadratic falloff look wrong. It would be correct if rendering was in linear space, but it is not. This is how Doom 3 is working, and this is how TDM normally works.

The first solution to the problem is rendering everything in linear space (RGB). Then you store all textures in linear space (i.e. they look wrong when you open them in paint), you store all FBOs in linear space. At the very end of rendering, you do gamma correction as the final pass, thus converting color from linear space to gamma space in order to send it to monitor. To avoid color banding from final gamma correction, you use HDR, i.e. high-precision color formats.

The second solution is to use SRGB support in OpenGL. You mark incoming textures as SRGB, and mark your FBO as SRGB. It does not magically changes anything, because in TDM they are all SRGB regardless of whether you mark them or not. But now blending and texture filtering have convert from gamma space to linear space before operation, and from linear space back to gamma space after operation. Thus, intensities are adding up properly. Moveover, when you fetch data from texture marked as SRGB in your shader, OpenGL automatically converts it from gamma space to linear space before returning it. If you write output color to SRGB buffer (and have enabled something on that FBO), then OpenGL automatically converts it from linear space into gamma space. So whatever you have in your shader is in linear space (and most likely in 32-bit float), but all data out of shader is in gamma space (and most likely 8-bit since if you use more precision than the first solution is better).

So you are wrong saying that default framebuffer is linear. It always contains SRGB (gamma space) data. And our textures always contain SRGB data. The only problem is that we incorrectly deal with this SRGB data all over the renderer. And using the SRGB extension in OpenGL allows to fix that, forcing OpenGL to auto-convert to linear space and back around every operation which could add colors.

That's a lot of text

Some I agree with, but mostly doubt. Maybe I'm just confused, so let me ask.

Quote

So you are wrong saying that default framebuffer is linear. It always contains SRGB (gamma space) data.

  1. Suppose that true. How come blitting from sRGB FBO to default darkens the picture?
  2. How come rendering in linear FBO and blitting to default produces the same result as rendering in default FBO?
Link to comment
Share on other sites

1 hour ago, duzenko said:

Suppose that true. How come blitting from sRGB FBO to default darkens the picture?

Well, I guess when I said "default FBO is gamma space", I was meaning that you must put gamma-space values there, since they are treated as such by the monitor. I did not mean that OpenGL automatically ensures that it gets gamma-space data, although I think there should be way to achieve it.

I think the main explanation is that OpenGL thinks default FBO is RGB since you did not tell it otherwise and OpenGL does not do any conversions without you telling it to do them. The FBO which you are blitting from contains gamma-space values, and you told OpenGL it is SRGB (by setting image format and enabling GL_FRAMEBUFFER_SRGB), so it auto-converts its data from gamma-space to linear-space during blitting. But you did not tell OpenGL that default FBO is SRGB, so it assumes it is linear and it does not do any conversion.

Looking at https://stackoverflow.com/a/46117749/556899, you have to pass some flags to WGL to ensure that default FBO is SRGB-capable, then enable GL_FRAMEBUFFER_SRGB. Did you do both of it?

Quote

How come rendering in linear FBO and blitting to default produces the same result as rendering in default FBO?

Same as above. You did not tell OpenGL that default FBO is gamma-space, so it assumes it is linear (while it clearly is not) and does not do any conversion.

 

Link to comment
Share on other sites

Attached patch for moving gamma/brightness changes to shader. I'm afraid I cannot apply it to all cases (case r_postprocess 2 is not working now as it seems). I have hardly managed to get it working without postprocessing...

One side effect is that main menu is not affected by gamma/brightness changes. Not sure if it is good or bad.

P.S. As for dithering, it can help only if you apply it when you draw the thing which shows color banding, e.g. when you draw sky and clouds. In the final pass, it is useless.

gammashader.patch

Link to comment
Share on other sites

3 hours ago, stgatilov said:

Well, I guess when I said "default FBO is gamma space", I was meaning that you must put gamma-space values there, since they are treated as such by the monitor. I did not mean that OpenGL automatically ensures that it gets gamma-space data, although I think there should be way to achieve it.

I think the main explanation is that OpenGL thinks default FBO is RGB since you did not tell it otherwise and OpenGL does not do any conversions without you telling it to do them. The FBO which you are blitting from contains gamma-space values, and you told OpenGL it is SRGB (by setting image format and enabling GL_FRAMEBUFFER_SRGB), so it auto-converts its data from gamma-space to linear-space during blitting. But you did not tell OpenGL that default FBO is SRGB, so it assumes it is linear and it does not do any conversion.

Looking at https://stackoverflow.com/a/46117749/556899, you have to pass some flags to WGL to ensure that default FBO is SRGB-capable, then enable GL_FRAMEBUFFER_SRGB. Did you do both of it?

Same as above. You did not tell OpenGL that default FBO is gamma-space, so it assumes it is linear (while it clearly is not) and does not do any conversion.

 

Ok, that makes sense. We can try and play with this, as clearly my attempts were half-assed.

It would be cool to see what difference sRGB does on render pictures.

I vaguely recall reading somewhere on the Internet that sRGB makes no effect on default FBOs. Maybe it's not true.

Link to comment
Share on other sites

@stgatilov

Please review revision 8530

  • mark default FBO as sRGB-capable (via WGL flags - Linux needs to be fixed separately)
  • r_fboSRGB applies on next restart. Its start state is cached in glConfig
  • SRGB correction is enabled accordingly - on startup - and never toggled in runtime

To me it gives zero visual difference on bright shots.

@all

Feel free to experiment with r_gamma and r_postprocessing (I don't use either of those).

Link to comment
Share on other sites

14 minutes ago, stgatilov said:

Just a small error. See revision 8531 😁

Oops right you are

Can you see how colors are broken with sRGB? Why is that?

My version: DWM does not know about internal FBO format and assumes its color space always be linear.

Link to comment
Share on other sites

12 minutes ago, duzenko said:

Can you see how colors are broken with sRGB? Why is that?

I don't see anything unexpected. Everything gets brighter, since you efficiently apply gamma conversion on the final output, which is a bit stronger than what setting r_gamma 2 in TDM gives. Of course, this is too much, so everything becomes very bright. When such gamma correction is done, colors become weaker, and can also change slightly. What did you expect?

The best thing that you can achieve with SRGB is that intensities are added/blended in a more physically correct way. To achieve it, you have to mark all textures as SRGB, and all FBOs as SRGB. Then the output should be more or less the same in terms of brightness. You cannot control gamma level with SRGB in a way how tone mapping or monitor tables allow it.

Link to comment
Share on other sites

1 minute ago, stgatilov said:

I don't see anything unexpected. Everything gets brighter, since you efficiently apply gamma conversion on the final output, which is a bit stronger than what setting r_gamma 2 in TDM gives. Of course, this is too much, so everything becomes very bright. When such gamma correction is done, colors become weaker, and can also change slightly. What did you expect?

The best thing that you can achieve with SRGB is that intensities are added/blended in a more physically correct way. To achieve it, you have to mark all textures as SRGB, and all FBOs as SRGB. Then the output should be more or less the same in terms of brightness. You cannot control gamma level with SRGB in a way how tone mapping or monitor tables allow it.

Alright - if you think it's good then I'll leave it be

Do we still need to mark all textures sRGB?

Link to comment
Share on other sites

On 1/25/2020 at 12:02 AM, duzenko said:

Do we still need to mark all textures sRGB?

I think yes. They are intended for displaying in ordinary image viewers, so they are in gamma space.

Imagine that you take this texture and draw it with full white lighting. If you treat texture as gamma-space and FBO is in gamma-space, then you texture data will go into FBO "as is", and will be displayed just like ordinary viewers display it. Looks like something intended.

Link to comment
Share on other sites

Quote

What are the current issues with this? It sounded like it's half-working?

I'm not sure how taxing it is for performance. The intent was to add one render from FBO to FBO, but it might be that more work is done.

It does not work when postprocessing is enabled. It it is not hard to run the tonemap shader after postprocessing, better do it.

I'm not sure about multisampling and nontrivial render-scale, although I probably tested it.

One uncertain thing is that with shader, gamma/brightness do not affect main menu. For me that's OK, I guess we can live with it unless we hear other opinions.

Link to comment
Share on other sites

On 1/22/2020 at 5:12 PM, stgatilov said:

Attached patch for moving gamma/brightness changes to shader. I'm afraid I cannot apply it to all cases (case r_postprocess 2 is not working now as it seems). I have hardly managed to get it working without postprocessing...

One side effect is that main menu is not affected by gamma/brightness changes. Not sure if it is good or bad.

P.S. As for dithering, it can help only if you apply it when you draw the thing which shows color banding, e.g. when you draw sky and clouds. In the final pass, it is useless.

gammashader.patch 4.25 kB · 1 download

How do I go about with this?

I tried Tortoise -> Apply patch in Windows Explorer with this file but all I can see is an empty diff window and no file changes

image.thumb.png.f16b3ae5701e699999c0839c6be84bf9.png

Link to comment
Share on other sites

On 2/2/2020 at 2:26 PM, duzenko said:

How do I go about with this?

Put the patch into root directory of darkmod_src. Then right-button it and choose TortoiseSVN -> Apply Patch. Aside from the window that you show, you should see another small window on top of it with thelist of changes files. Click "Patch all items" there.

Link to comment
Share on other sites

5 hours ago, stgatilov said:

Put the patch into root directory of darkmod_src. Then right-button it and choose TortoiseSVN -> Apply Patch. Aside from the window that you show, you should see another small window on top of it with thelist of changes files. Click "Patch all items" there.

That worked! :awesome:

Link to comment
Share on other sites

On 1/30/2020 at 4:32 PM, stgatilov said:

I'm not sure how taxing it is for performance. The intent was to add one render from FBO to FBO, but it might be that more work is done.

It does not work when postprocessing is enabled. It it is not hard to run the tonemap shader after postprocessing, better do it.

I'm not sure about multisampling and nontrivial render-scale, although I probably tested it.

One uncertain thing is that with shader, gamma/brightness do not affect main menu. For me that's OK, I guess we can live with it unless we hear other opinions.

Looking good to me. Do I need to commit from my side?

Link to comment
Share on other sites

On 2/5/2020 at 5:57 AM, stgatilov said:

Could you make it work even when postprocessing is enabled?

Done

However AA and FBO scaling are still not compatible

Our options:

  • add one more FB->texture copy
  • use a texture attachment for PP FBO instead of a RB
  • integrate tone-mapping into the PP shader

I don't have a preference - you choose

Link to comment
Share on other sites

2 hours ago, stgatilov said:

You mean they are always incompatible or only with postprocessing enabled?

Sorry

I meant either of them causes some kind of visual issues when the tonemapping and post-processing shaders are active at the same time.

Link to comment
Share on other sites

  • 6 months later...
On 12/10/2019 at 2:11 AM, duzenko said:

Do you want to try 2.08 alpha? It would make sense to post your problem report in the support forum.

Hey, thanks for the offer, Duzenko! Sorry it took me so long to see your post 😕 I see 2.08 is actually released now, so I'm re-installing TDM from scratch and will see how 2.08 goes, brightness/gamma-wise. Will let you know how it goes.

I uninstalled TDM a while back because it was on my C:\ drive (SSD), and some other issues. Am going to try and put 2.08 on my D:\ drive instead, and not in 'Program Files' -- so I can hopefully avoid an issue I had before of not being able to save games (related to Admin rights). The TDM website suggests the following path, so I will do that: "c:\games\darkmod" (only changing to d:\, of course)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent Status Updates

    • Petike the Taffer

      I've finally managed to log in to The Dark Mod Wiki. I'm back in the saddle and before the holidays start in full, I'll be adding a few new FM articles and doing other updates. Written in Stone is already done.
      · 1 reply
    • nbohr1more

      TDM 15th Anniversary Contest is now active! Please declare your participation: https://forums.thedarkmod.com/index.php?/topic/22413-the-dark-mod-15th-anniversary-contest-entry-thread/
       
      · 0 replies
    • JackFarmer

      @TheUnbeholden
      You cannot receive PMs. Could you please be so kind and check your mailbox if it is full (or maybe you switched off the function)?
      · 1 reply
    • OrbWeaver

      I like the new frob highlight but it would nice if it was less "flickery" while moving over objects (especially barred metal doors).
      · 4 replies
    • nbohr1more

      Please vote in the 15th Anniversary Contest Theme Poll
       
      · 0 replies
×
×
  • Create New...