h3r2tic / tony-mc-mapface

A cool-headed display transform
Apache License 2.0
335 stars 10 forks source link

Black is not black anymore? #6

Open AnonN10 opened 1 year ago

AnonN10 commented 1 year ago

There is a black patch of screen that clipped through a solid sphere, where no light goes in, therefore it should be pitch black. The tonemapper seems to skew the blacks towards dark-gray, losing effective LDR range a bit and removing contrast from the image. After inspecting LUT in renderdoc, I've noticed that the pixel at (0, 0, 0) is not actually black, but has a value 0.00014.

LUT: image

With tonemapper: image

Without tonemapper: image

h3r2tic commented 1 year ago

Ah, quantization, what hast thou done?

Yeah, it would probably be a good idea to special-case that. Thanks for noticing and finding the cause!

Froyok commented 10 months ago

I wonder if this could be related to the same issue I noticed a while ago and mentioned on Mastodon: https://mastodon.gamedev.place/@froyok/109921004547221001

Froyok commented 3 months ago

Commenting again on this, I decided to "fix" it (well, more like compensate) in a quick and dirty way. The minimum value is 0.00014 in the LUT and the maximum 0.99805, so it's not a perfect 0-1 range, therefor I scaled the color result after the LUT is applied.

Which look something like this:

vec3 Tonemap_Tony_RemapRange( vec3 TonyColor )
{
    // Tony LUT min value is 0.00014 instead of 0.0
    // Max value is 0.99805 and not 1.0.
    const float Scale = 1.0 / ( 0.99805 - 0.00014 );
    return Saturate( ( TonyColor - 0.00018 ) * Scale );
}

Which that you get back true blacks. Haven't noticed change with highlights/pure white pixels (but that's harder to distinguish anyway).

[EDIT] Okay scratch that, this stupid fix introduces other issues (some clipping notably). So I advise against it.