Deband
- JPulowski
-
Topic Author
Yes, although I believe it will take quite a long time before it is accomplished. Also note that, it would only be applicable for DX10+ applications.aufkrawall wrote: I remember that I read in this forum that for some day it's planned that ReShade can force applications to render in deep color mode. Is this still planned?
Please Log in or Create an account to join the conversation.
- aufkrawall
-
Maximum range of 64 always gave me best reults so far, a higher grain strength of ~150 also seems to have a good effect with it ( grain is still often hardly noticeable in motion).
I also noticed that it makes a very big difference that the banding stays untouched for the deband filter to work best. In Dying Light, you can disable chromatic aberration via mod (I wouldn't recommend as it brings other problems like flickering) and it makes the deband filter work stronger with a lower threshold value.
However, since the CA is applied almost everywhere, a higher threshold value kills also less details than without CA. Of course film grain should be disabled as well in the games.
I'm still very convinced by your MPV port, thanks again for it.

I think it might be a good idea to start a thread with good values for different games and settings.
Please Log in or Create an account to join the conversation.
- sets
-
Please Log in or Create an account to join the conversation.
- JBeckman
-
screenshotcomparison.com/comparison/178613
(From steamcommunity.com/app/384490/discussions/0/366298942103958003/ )
Very subtle most of the time, you might have to hover over the image a few times before you spot it though some are more sensitive to it than others and some games have more problems with color banding than others such as the above example from Necropolis though in other games the skybox tends to be a pretty common problem area.

Please Log in or Create an account to join the conversation.
- Duamutef_MC
-
Please Log in or Create an account to join the conversation.
- mbah.primbon
-
Duamutef_MC wrote: Is there any chance of also using this shader on desktop applications, like browsers or video players? I use my external Geforce card for all image processing.
I ported this shader to MPC-HC tho, idk the other apps/software which support custom shader. If there is another better video player which support shaders, let me know. Since MPC-HC development stopped.
Please Log in or Create an account to join the conversation.
- JBeckman
-
"Updated MPC-HC to version 1.7.17.7" That's from about one week back for K-Lite.
Ah I see now I think, it's a continuation and update of the original version.
Please Log in or Create an account to join the conversation.
- Archdre
-
Please Log in or Create an account to join the conversation.
- Tojkar
-
Please Log in or Create an account to join the conversation.
- Dreamject
-
Hey) Can you share ported shader?mbah.primbon wrote:
Duamutef_MC wrote: Is there any chance of also using this shader on desktop applications, like browsers or video players? I use my external Geforce card for all image processing.
I ported this shader to MPC-HC tho, idk the other apps/software which support custom shader. If there is another better video player which support shaders, let me know. Since MPC-HC development stopped.
Please Log in or Create an account to join the conversation.
- JPulowski
-
Topic Author
I know it has been a long time. I have been busy with other programming topics, mostly CPU oriented stuff. Very recently I have been playing with the deband shader now that I am more experienced in general programming topics. While at it I have decided to try to improve it with my still limited GPU programming knowledge. The deband shader is actually based on the popular flash3kyuu_deband. A while back, madshi made some improvements to the original design and shared them publicly . And I have implemented some of them to increase debanding quality. Basically now there is more sanity checking, which means higher parameters should yield lesser decrease in detail while being able to deband more color banding. I have also simplified the settings, the grain setting no longer exists, we are now using CeeJay's ordered dithering algorithm and it is on by default since turning off just undoes the effect. Other than that the ranges are reduced, I have tested different parameters and basically limited each setting to a range where it makes a significant difference. Before making it public, I want to release it here as a beta and get your feedback. I'd really appreciate it if you could compare it to previous version and tell me what do you think. Thanks.

/**
* Deband shader by haasn
* https://github.com/haasn/gentoo-conf/blob/xor/home/nand/.mpv/shaders/deband-pre.glsl
*
* Copyright (c) 2015 Niklas Haas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modified and optimized for ReShade by JPulowski
* https://reshade.me/forum/shader-presentation/768-deband
*
* Do not distribute without giving credit to the original author(s).
*
* 1.0 - Initial release
* 1.1 - Replaced the algorithm with the one from MPV
* 1.1a - Minor optimizations
* Removed unnecessary lines and replaced them with ReShadeFX intrinsic counterparts
* 2.0 - Replaced "grain" with CeeJay.dk's ordered dithering algorithm and enabled it by default
* The configuration is now more simpler and straightforward
* Some minor code changes and optimizations
* Improved the algorithm and made it more robust by adding some of the madshi's
* improvements to flash3kyuu_deband which should cause an increase in quality. Higher
* iterations/ranges should now yield higher quality debanding without too much decrease
* in quality.
* Changed licensing text and original source code URL
*/
#include "ReShadeUI.fxh"
uniform float Threshold < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.6;
ui_max = 3.4;
ui_step = 0.1;
ui_label = "Cut-Off Threshold";
ui_tooltip = "Higher numbers increase the debanding strength dramatically but progressively diminish image details. In pixel shaders a 8-bit color step equals to 1.0/255.0";
> = 1.6;
uniform float Range < __UNIFORM_SLIDER_FLOAT1
ui_min = 1.0;
ui_max = 32.0;
ui_step = 1.0;
ui_label = "Initial Radius";
ui_tooltip = "The radius increases linearly for each iteration. A higher radius will find more gradients, but a lower radius will smooth more aggressively.";
> = 24.0;
uniform int Iterations < __UNIFORM_SLIDER_INT1
ui_min = 1; ui_max = 4;
ui_tooltip = "The number of debanding steps to perform per sample. Each step reduces a bit more banding, but takes time to compute.";
> = 1;
#include "ReShade.fxh"
uniform int drandom < source = "random"; min = 0; max = 5000; >;
float rand(float x)
{
return frac(x / 41.0);
}
float permute(float x)
{
return ((34.0 * x + 1.0) * x) % 289.0;
}
void analyze_pixels(float3 ori, sampler2D tex, float2 pos, float2 range, float2 dir, out float3 ref_avg, out float3 ref_avg_diff, out float3 ref_max_diff, out float3 ref_mid_diff1, out float3 ref_mid_diff2)
{
// Sample at quarter-turn intervals around the source pixel
// South-east
float3 ref = tex2D(tex, float2(pos + range * float2(dir.x, dir.y))).rgb;
float3 diff = abs(ori - ref);
ref_max_diff = diff;
ref_avg = ref;
ref_mid_diff1 = ref;
// North-west
ref = tex2D(tex, float2(pos + range * float2(-dir.x, -dir.y))).rgb;
diff = abs(ori - ref);
ref_max_diff = max(ref_max_diff, diff);
ref_avg += ref;
ref_mid_diff1 = abs(((ref_mid_diff1 + ref) * 0.5) - ori);
// North-east
ref = tex2D(tex, float2(pos + range * float2(-dir.y, dir.x))).rgb;
diff = abs(ori - ref);
ref_max_diff = max(ref_max_diff, diff);
ref_avg += ref;
ref_mid_diff2 = ref;
// South-west
ref = tex2D(tex, float2(pos + range * float2( dir.y, -dir.x))).rgb;
diff = abs(ori - ref);
ref_max_diff = max(ref_max_diff, diff);
ref_avg += ref;
ref_mid_diff2 = abs(((ref_mid_diff2 + ref) * 0.5) - ori);
ref_avg *= 0.25; // Normalize avg
ref_avg_diff = abs(ori - ref_avg);
}
float3 PS_Deband(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
// Initialize the PRNG by hashing the position + a random uniform
float3 m = float3(texcoord, drandom * 0.0002) + 1.0;
float h = permute(permute(permute(m.x) + m.y) + m.z);
float3 ref_avg; // Average of 4 reference pixels
float3 ref_avg_diff; // The difference between the average of 4 reference pixels and the original pixel
float3 ref_max_diff; // The maximum difference between one of the 4 reference pixels and the original pixel
float3 ref_mid_diff1; // The difference between the average of SE and NW reference pixels and the original pixel
float3 ref_mid_diff2; // The difference between the average of NE and SW reference pixels and the original pixel
float3 ori = tex2D(ReShade::BackBuffer, texcoord).rgb; // Original pixel
float3 res; // Final pixel
// Compute a random angle
float dir = rand(permute(h)) * 6.2831853;
float2 o = float2(cos(dir), sin(dir));
for (int i = 1; i <= Iterations; ++i)
{
// Compute a random distance
float dist = rand(h) * Range * i;
float2 pt = dist * ReShade::PixelSize;
analyze_pixels(ori, ReShade::BackBuffer, texcoord, pt, o,
ref_avg,
ref_avg_diff,
ref_max_diff,
ref_mid_diff1,
ref_mid_diff2);
// Thresholds roughly based on madshi's "medium" settings
float3 ref_avg_diff_threshold = Threshold / 255.0 * i;
float3 ref_max_diff_threshold = 4.0 / 255.0 * i;
float3 ref_mid_diff_threshold = 2.0 / 255.0 * i;
// Fuzzy logic based pixel selection
float3 factor = pow(saturate(3.0 * (1.0 - ref_avg_diff / ref_avg_diff_threshold)) *
saturate(3.0 * (1.0 - ref_max_diff / ref_max_diff_threshold)) *
saturate(3.0 * (1.0 - ref_mid_diff1 / ref_mid_diff_threshold)) *
saturate(3.0 * (1.0 - ref_mid_diff2 / ref_mid_diff_threshold)), 0.1);
res = lerp(ori, ref_avg, factor);
h = permute(h);
}
const float dither_bit = 8.0; //Number of bits per channel. Should be 8 for most monitors.
/*------------------------.
| :: Ordered Dithering :: |
'------------------------*/
//Calculate grid position
float grid_position = frac(dot(texcoord, (ReShade::ScreenSize * float2(1.0 / 16.0, 10.0 / 36.0)) + 0.25));
//Calculate how big the shift should be
float dither_shift = 0.25 * (1.0 / (pow(2, dither_bit) - 1.0));
//Shift the individual colors differently, thus making it even harder to see the dithering pattern
float3 dither_shift_RGB = float3(dither_shift, -dither_shift, dither_shift); //subpixel dithering
//modify shift acording to grid position.
dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position.
//shift the color by dither_shift
res += dither_shift_RGB;
return res;
}
technique Deband <
ui_tooltip = "Alleviates color banding by trying to approximate original color values.";
>
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_Deband;
}
}
Please Log in or Create an account to join the conversation.
- Wicked Sick
-
this made me laugh haha
Man, can you still keep the noise? I liked it very much... I am going to try it later to see how it looks
Please Log in or Create an account to join the conversation.
- lowenz
-
'cause you are.....Wicked Sick? :vWicked Sick wrote: "Basically now there is more sanity checking"
this made me laugh haha
Please Log in or Create an account to join the conversation.
- Tojkar
-
+1 for this. Please make the grain optional but maybe default to the dithering.Wicked Sick wrote: "Basically now there is more sanity checking"
Man, can you still keep the noise? I liked it very much... I am going to try it later to see how it looks
Please Log in or Create an account to join the conversation.
- JPulowski
-
Topic Author
May I ask why? The only reason why grain was there in the first place was to randomize quantization errors a.k.a. random dithering. It was not there for artistic purposes. For that you can use a film grain shader, which is pretty much the same thing. Or if you really liked the particular grain pattern in the shader, it is a simple uniform noise, I can put it here so you can use it by adding it as another shader. CeeJay's dithering algorithms are optimized for 8-bit output, so you don't need to jiggle the grain slider to find the sweetspot. I have also tested ordered and random dithering to see if there was an improvement in quality, there wasn't except a minor decrease in performance. Ordered dithering is also used in DisplayDepth shader as well, so it's pretty solid.Tojkar wrote:
+1 for this. Please make the grain optional but maybe default to the dithering.Wicked Sick wrote: "Basically now there is more sanity checking"
Man, can you still keep the noise? I liked it very much... I am going to try it later to see how it looks
Please Log in or Create an account to join the conversation.
- Enterprise24
-
Please Log in or Create an account to join the conversation.
- JPulowski
-
Topic Author
Please Log in or Create an account to join the conversation.
- Enterprise24
-
Please Log in or Create an account to join the conversation.
- JPulowski
-
Topic Author
Please Log in or Create an account to join the conversation.
- Duran.te
-
JPulowski wrote: I'd really appreciate it if you could compare it to previous version and tell me what do you think.
- You called?
So, these (perfectly aligned) shots were taken in Mirror's Edge Catalyst, using intentional over-saturation (for better banding spotting) and a bit of sharpening (for the details).
From top to bottom they are:
-Debanding Off
-Old version
-New version
Debanding settings were slightly edited by changing (on both versions) Initial Radius values to 12.000 and the Interations ones to 12 (which is four time the max settable value on the new shader).
This choice were taken to better show the difference of the behaviour between the 2 shaders versions.
You can clearly see the loss of detail on the left / bottom-left part of the screen with the old version.
The lack of extra-grain setting is not felt at all, since the new dithering algorithm does his job well.
For the ones who still wants that setting for aesthetics, there are a lot of grain - generating shaders out there, two of which are found in the standard shaders repository.
Please Log in or Create an account to join the conversation.