novideo_srgb icon indicating copy to clipboard operation
novideo_srgb copied to clipboard

Grayscale is too bright

Open Terepin opened this issue 3 years ago • 11 comments

When I set calibration to sRGB brightness is too high, wich breaks brightness calibration games as I can no longer make the sign disappear (like in Alien Isolation or Metro Redux). If I use the same profile in DisplayCal's Profile Loader it calibrates properly. PXL_20220208_095856241 PXL_20220208_095936845

Terepin avatar Feb 08 '22 10:02 Terepin

When you open the ICC profile in DisplayCal, the sRGB tone curve is selected? Was the ICC profile created by DisplayCal? Probably best to attach it.

Though the sRGB tone curve usually isn't meant for usage in games/video, it looks overbright even vs. BT.1886 with non-OLED display. Pretty sure that this is also the case when calibrating display with that tone curve selected in DisplayCal.

aufkrawall avatar Feb 10 '22 16:02 aufkrawall

ULTRAGEAR #1 2022-01-14 13-21 0.3127x 0.329y sRGB F-S XYZLUT+MTX.zip Yes, it was created in DisplayCal using sRGB profile.

I read pretty much everywhere that sRGB is used for SDR content and that monitors should be calibrated to it. Also, I compared it to monitor's own sRGB clamp and it was still too bright.

Terepin avatar Feb 10 '22 16:02 Terepin

I can confirm that with your profile, novideo_srgb is brighter with sRGB tone curve than loading it as 1D LUT via GPU gamma ramps. You could try creating a new calibration in e.g. single curve + matrix format. I've noticed that there is an extreme amount of grayscale adjustment with your profile, did you calibrate your display's white point to native 6500K (in monitor OSD, not just via software)? I think that is generally recommended.

The confusing thing is that what is called sRGB tone curve isn't necessarily correct for consumer sRGB/rec709 content. E.g. OLED TVs by default are pracically pure power gamma 2.4 curve, which is really vastly different. With sRGB tone curve, you basically butcher a picture's average contrast to make details in dark areas better visible that probably weren't meant to be visible.

aufkrawall avatar Feb 10 '22 17:02 aufkrawall

Investigating stuff like this is kinda hard without something like a capture card (or a lot of experimentation), but if I had to guess, this is probably a side effect of the LUT-Matrix-LUT architecture of the color space transform. The problem is that the EOTF rises very slowly near black, which means that a lot of near-black values end up landing between just two regamma LUT entries (i.e. 0 and 1 out of 1023, assuming the display has true blacks) in the regamma LUT at the end. So it's impossible to control the luminance of near-black values properly, as they are the result of linear interpolation between just those two entries. Not sure if/how this can be mitigated.

ledoge avatar Feb 10 '22 17:02 ledoge

I can confirm that with your profile, novideo_srgb is brighter with sRGB tone curve than loading it as 1D LUT via GPU gamma ramps. You could try creating a new calibration in e.g. single curve + matrix format. I've noticed that there is an extreme amount of grayscale adjustment with your profile, did you calibrate your display's white point to native 6500K (in monitor OSD, not just via software)? I think that is generally recommended.

The confusing thing is that what is called sRGB tone curve isn't necessarily correct for consumer sRGB/rec709 content. E.g. OLED TVs by default are pracically pure power gamma 2.4 curve, which is really vastly different. With sRGB tone curve, you basically butcher a picture's average contrast to make details in dark areas better visible that probably weren't meant to be visible.

Correct, I left the greyscale correction to the ICC profile. But I do have profile that I created with white point set on my monitor and it suffers from the same problem. ULTRAGEAR #1 2021-07-16 21-03 0.3127x 0.329y sRGB F-S XYZLUT+MTX.zip

Terepin avatar Feb 11 '22 11:02 Terepin

Did a bit of testing (new calibration with sRGB tone curve selected in DisplayCal), it is more distinct with a profile in XYZ format vs. single curve. But also single curve novideo_srgb is brighter than sRGB curve applied via VCGT gamma ramps.

it might be the same effect that I could see vs. full calibration via 3D LUT: https://github.com/ledoge/novideo_srgb/issues/10#issuecomment-1008307421

If I got ledoge right (topic's not that easy for us laymen, appreciating any information though :) ), it is a limitation of that driver API we have to live with (or use additional gamma correction via VCGT/3D LUT).

aufkrawall avatar Feb 21 '22 15:02 aufkrawall

or use additional gamma correction via VCGT

I'm not sure if this can really help (do feel free to try it and report back though!).

I believe the gamma deviations (not just near black) vs. using a VCGT calibration stem from the fact that the calibration "pipeline" used by novideo_srgb is simply too different from a normal VCGT calibrated workflow. Normally you'd have some program outputting 8 bit color values, which would then go through the VCGT with 256 entries, so each color value would map to one VCGT entry.

The GPU pipeline consists of 3 steps: a de-gamma LUT to convert the values to linear light, a 3x4 matrix (which does not affect grayscale) and a re-gamma LUT to gamma-encode the values for the monitor. With a VCGT calibration, the de-gamma LUT and matrix are identity mappings (i.e. they do nothing or are maybe bypassed entirely in hardware) and the re-gamma LUT is populated with the VCGT values. With novideo_srgb, the de-gamma LUT is set to e.g. the sRGB EOTF values to linearize the gamma-encoded values, and the re-gamma LUT is then responsible for both gamma-encoding the values for the monitor again according to the ICC profile and applying the VCGT data on top of that. There is no simple 1:1 mapping here due to the fact that the EOTF in the de-gamma LUT is highly non-linear and "compresses" and "stretches" the values. The fact that the LUTs have 1024 entries instead of 256 makes this even worse, as 8 bit values cannot be mapped directly to 10 bit values, so as a result there'll always be some interpolation happening at the de-gamma stage already, unlike the simple VCGT case where it's a 1:1 mapping from input to output values with no interpolation.

I think this 8 vs 10 bit issue can be mitigated at least partially by "optimizing" the LUT values to produce the correct results for 8 bit values (though this won't work with near-black values in the re-gamma LUT), but this would then result in worse accuracy with 10 bit inputs (I suspect this is what the drivers do for VCGT calibrations – there's no interpolation between VCGT values happening with 8 bit colors, at least). Might be worth adding a toggle for, since most people probably aren't using any 10 bit applications, though I did some testing and it didn't seem to improve results much. Either way, I don't think anything can be done about near-black values specifically.

ledoge avatar Feb 21 '22 16:02 ledoge

Thanks for providing us with the technical backgrounds!

or use additional gamma correction via VCGT

I'm not sure if this can really help (do feel free to try it and report back though!).

I wouldn't know how to test this, or does the validation feature in DisplayCal not override GPU gamma ramps? But I'm actually willing to accept those rather minor deviations anyway (at least they don't look too bad to me with gamma 2.2/2.4 and single curve profile), as I find the alternative of Windows introducing very visible banding with GPU gamma ramps far worse. :)

aufkrawall avatar Feb 22 '22 15:02 aufkrawall

It is safe to assume that this won't get fixed due to API limitation?

Terepin avatar Mar 25 '22 07:03 Terepin

It might be better when using a profile with a large number of grayscale patches + no VCGT data (as that seems to produce slightly wrong results, at least the last time I tested it) and a recent build with the added 8-bit optimization. Other than that, I don't think there's anything that can be done.

ledoge avatar Mar 25 '22 08:03 ledoge

I have found a solution to this! Basically, use the standard sRGB preset, but enable gamma mapping. :)

Terepin avatar Aug 13 '22 16:08 Terepin