Page 1 of 2
[HLSL Code] Basic Dithering
Posted: 22 Sep 2016, 23:49
by kingeric1992
Dithering under enbeffect.fx for HDR to rgba8888
up close:
So here is a basic noise generator.
Code: Select all
// ALU noise in Next-gen post processing in COD:AW
float InterleavedGradientNoise( float2 uv )
{
float3 magic = { 0.06711056, 0.00583715, 52.9829189 };
return frac( magic.z * frac( dot( uv, magic.xy ) ) );
}
And here is the dithering part. Just add it right before pixel shader output/return.
3 different alternatives here, linear, non-linear, energy-preserved
Code: Select all
float dither_amp = 1.0;
float noise = lerp(-0.5, 0.5, InterleavedGradientNoise( vPos )) * dither_amp; //or other noise method
//linear
color.xyz = color + noise / 255.0;
//non-linear
// color.xyz = pow( pow( color.xyz, 1.0 / 2.2) + noise / 255.0, 2.2);
//Energy-preserved
// color.xyz = pow(color.xyz, 1.0/2.2);
// color.xyz = color.xyz + noise * min(color.xyz + 0.5 * pow(1.0/255.0, 2.2), 0.75 * (pow(256.0/255.0, 2.2) - 1.0));
// color.xyz = pow(color.xyz, 2.2);
Here is a demo comparison on linear, srgb space, and energy-preserving dither:
shadertoy (low quality noise pattern for a better view on artifacts)
[gdc16] Advanced Techniques and Optimization of HDR Color Pipelines
Noted that the difference between these methods are less obvious on higher bit depth.
and a demo implementation on reference enbeffect.fx.
- enbeffect.fx
- update 23/9. adds different modes, amplitude control.
- (17.29 KiB) Downloaded 686 times
Re: [HLSL Code] Basic Dithering
Posted: 23 Sep 2016, 08:48
by roxahris
Another method for [s]dithering[/s] noise generation is Valve's.
Code: Select all
float3 ScreenSpaceDither( float2 vScreenPos : SV_Position0 ) : SV_Target
{
// Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR
float3 vDither = dot( float2( 171.0, 231.0 ), vScreenPos.xy+Timer.x*16777216) ;
vDither.rgb = frac( vDither.rgb / float3( 103.0, 71.0, 97.0 ) );
return vDither.rgb;
There's also the SweetFX dithering code, which works well in these situations. Though chromatic noise is down to your preference.
But I think gamma correction is really important when you do this, otherwise it looks like ugly noise unless you put it after the conversion.
Take a look at this - I think it's at the least related to his algorithms there. I tested the fast version with my Dragon's Dogma ENB and the results were really good. (Made the previous code look really awful by comparison, oops.)
Re: [HLSL Code] Basic Dithering
Posted: 23 Sep 2016, 14:02
by kingeric1992
As I said, you can change the noise function to your liking. (noise != dither)
Btw, doing dithering alone in effect.txt or sweetfx will not get the full potential of the technique, aka 0.5 = average of 0 and 1.
It merely adds noise so that the edge is less obvious, the overall block average is still the same as the ldr input, hence the banding will still occurred. Unless you're talking about a full-blown deband shader that generate the additional precision (the 0.5) by itself.
post update: adds alternative method and comparison.
Re: [HLSL Code] Basic Dithering
Posted: 23 Sep 2016, 16:29
by ENBSeries
I recommend to use multiplicative operation to avoid bugs like on night sky in Fallout 4. Who knows what kind of post processing applied, may be black levels greatly increased by effect.txt.
Re: [HLSL Code] Basic Dithering
Posted: 24 Sep 2016, 14:49
by kingeric1992
What happened to the night sky in fo4? My understanding on dithering is still about bumping the value up and down to hit neighboring steps.
Re: [HLSL Code] Basic Dithering
Posted: 24 Sep 2016, 15:42
by ENBSeries
You may check vanilla fallout 4 sky, it have dithering pattern visible on it. Was reported several times in the past for fixing. Of course you can just add math which ignores dithering when value is 0.
Re: [HLSL Code] Basic Dithering
Posted: 25 Sep 2016, 11:31
by roxahris
Oh. Is it wrong to think that adding noise to an image in such a way is dithering it? If it's just based on the texture coordinate it'll be a repeating pattern anyway, so I don't see what the difference is, barring that an RGB dithering pattern isn't one dimensional.
I'm not suggesting to use SweetFX to add dithering, of course that's pointless. I'm talking about the algorithm included in it, which I'll post here for posterity, as it's also a good alternative.
Code: Select all
//SweetFX dithering by CeeJay.dk.
float dither_bit = 8.0; //Bit-depth of output. Normally 8 but some LCD monitors are 7 or even 6-bit.
//Calculate grid position
float grid_position = frac( dot( vScreenPos.xy - float2(0.5,0.5) , 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.0,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
return dither_shift_RGB; //0.5/255.0 + dither_shift_RGB;
Re: [HLSL Code] Basic Dithering
Posted: 25 Sep 2016, 14:02
by Marty McFly
SweetFX dither does the same, roughly. For best LDR artifact removal, a full deband shader is still best. Take a look at the ReShade Framework, there is a very good one already included. Port to ENB is elementary, I can do it, if needed.
Also, this here is not just "noise" per se, look at the zoomed in picture, it's some sort of zig zag pattern. And it gets rid of obvious banding nicely because the amount of noise is just as large as the single steps between the evenly colored areas. You can't deband 4 bit colors with that obviously.
Re: [HLSL Code] Basic Dithering
Posted: 25 Sep 2016, 14:56
by kingeric1992
@roxahris
It is still dithering, considering dithering means adding ripple to input.
But if you simply add noise to a data that was already compressed, the local sum of dithering will match to the discrete compressed data and not the uncompressed continuous raw input, which means banding will be visible at small gradient over a large area.
Visually, it would be like applying smoothing on steps, where the dither amplitude as smooth range. If the step width >> smoothing range, the result would looked more like steps instead of a continues slope.
@marty
Believe it or not, the noise parms & function are exact the same in the comparison pic with noise peak-to peak amplitude == 1/255. In fact, the tiny noise appears in the implementation on effect.txt is not supposed to be there at all....it might be caused by non-linear step size from gamma correction.
I tried...
Re: [HLSL Code] Basic Dithering
Posted: 25 Sep 2016, 15:58
by roxahris
Would that explain why some versions of the Valve algorithm I've seen have an offset like dither * 2 - 0.5, then? I've noticed that kind of smoothed-step problem before, but I worked around it by doing something like that too.
I'm not talking about LDR data at all. I don't see the point in using Deband with ENB unless the effect shader can't access the HDR data in the first place, which I don't think is the case for any recent releases. All it will do is smooth details and add noise, which brings us back full circle.