Determining Brightest/Darkest Pixel?

More
1 month 6 days ago #1 by t1234
I've been tinkering with this psuedo cel shading shader that I downloaded from this thread: reshade.me/forum/shader-suggestions/4196...similar-to-retroarch . The way I understand it works is that for pixels with a luminosity within a certain threshold have the luminosity raised to pure white (or pure black if within the lower threshold). I want to know if there's a way to add a pass to the shader that goes over the image and checks what the luminosity of the brightest pixel in the image is and the luminosity of the darkest pixel, and set those as upper and lower limits respectively.

(Shader settings are set to extreme values for demonstration purposes)

Demonstration images:
Default Game Image without shader:


Screenshot with shader strength set to maximum to show how shader does its work by overlaying white or black (if I understand correctly):

Screenshot with maximum shader thresholds and shader strength:


By default the shader raises highlights to pure white rather than the actual max white value of the current frame, causing blown out highlights. And similar for black values.


My work so far:
I found that by editing cHSL.z line 155:
if     (cHSL.z > (WhtCutoff - (1.0 - WhtMax))) { cHSL.y  *= SatModify; cHSL.z = WhtMax; }
WhtMax being a new variable in the user config menu with values between 0.0 and 1.0.
This allowed me to change the maximum luminosity value. To actually see the effects I also had to subtract the difference from the WhtCutoff value. Otherwise, the shader would only be looking at values above the new max white value, see that they're above the WhtCutoff, and then not do anything.
Additionally, I changed cHSL.y so that it takes into account saturation like how the black values are already handled by the shader so that the pixel maintains its non-white hue.

Default Game:


Shader with Default Max White:

Notice the overly bright highlights on the sleeves for instance.

Manual Max White Adjustment:


This adjustment fixes the overly bright highlights, but these settings won't look right in different brighter scenes. Ideally, the max white value could be dynamically and automatically adjusted.

I also did something similar for the darker colors but I won't bog you down with the details.

The issue however is that manually editing the value too high or too low can make the highlights and such brighter or darker than the default look of the game which can cause clipping on the default extreme white or black values.
What I would like is for the shader to automatically dynamically adjust for the minimum and maximum black and white values that change depending on the scene instead of having the user edit the values.

Stuff that hasn't worked:
Shaders like levels.fx or lightroom end up affecting the image as a whole when changing the white level while keeping relative brightness levels the same which is isn't what I want. Using lightroom to change the peak highlights seems to negatively affect other colors lower on the luminosity scale too.

Summary:
I want to find a way for the shader to automatically find the default highest bright value and adjust accordingly so that the image highlights are not raised above the default max bright value (causing blown out highlights) and are also not lowered below the maximum default (and causing clipping). If someone can show me how to figure it out for the max luminosity value, I can probably figure out how to adapt it for the minimum luminosity value (the black levels).

Proposed Solution:
I believe a way this can be done is to have the shader iterate through every individual pixel, convert the RGB values to HSV to figure out the luminosity (like how the shader already does to check if it's in the luminosity thresholds), and then compare that luminosity value to the current WhtMax value. If the current pixel's luminosity is higher than the current WhtMax value, it sets the MaxWht value to the current pixel's luminosity. Alternatively, to adapt it for the minimum BlkMin, I would just compare the current pixel's luminosity to the current BlkMin and if it's lower, set BlkMin to the current pixel's luminosity. This process would be done on each frame to account for changing scenes.

However, figuring out how to tell reshade to iterate through each pixel and check the luminosity values is beyond my knowledge and ability. I'm also not sure if it's possible or will have acceptable performance.

Can anyone assist me?

Please Log in or Create an account to join the conversation.