I couldn't find anything that actually seemed to do the job of cleanly dithering in Dragon's Dogma so I tried my hand at making a dither shader myself.

Config:

**Code:**

#define M_PI 3.14159265358979323846

bool UseDither <

string UIName = "------------ TPDF Dither -------------";

> = {true};

float DitherBitDepth < // the bit depth of your monitor

string UIName = "Bit Depth";

string UIWidget = "Spinner";

float UIMin = 6.0;

float UIMax = 10.0;

float UIStep = 1.0;

> = { 8.0 };

bool DitherTemporal < // moving or static noise?

string UIName = "Temporal";

> = { true };

bool DitherDouble < // double noise for triangular distribution

string UIName = "Double Noise";

> = { true };

bool ShowNoise < // for debugging

string UIName = "Show Noise";

> = { false };

Helper function:

**Code:**

float3 mccool_rand(float2 ij) // Sylvain Lefebvre 2004-07-03

{

const float4 a=float4(M_PI * M_PI * M_PI * M_PI, exp(4.0), pow(13.0, M_PI / 2.0), sqrt(1997.0));

float4 result =float4(ij,ij);

for(int i = 0; i < 3; i++)

{

result.x = frac(dot(result, a));

result.y = frac(dot(result, a));

result.z = frac(dot(result, a));

}

return (result.xyz);

}

Shader:

**Code:**

float4 PS_Process_Dither (VS_OUTPUT_POST IN, float2 vPos : VPOS, float2 tex : TEXCOORD0) : COLOR

{

float4 color;

color.xyz = tex2D (SamplerColor, IN.txcoord.xy).xyz;

if (UseDither == true)

{

float2 tex = IN.txcoord.xy;

float3 noise;

if (DitherTemporal == true) {

float t = frac(Timer.x);

noise = mccool_rand(tex + t * 0.07);

if (DitherDouble == true) {

noise += mccool_rand(tex + t * 0.11);

}

} else {

noise = mccool_rand(tex);

if (DitherDouble == true) {

noise += mccool_rand(tex + 0.6849);

}

}

float steps = (1.0 / (pow(2, DitherBitDepth) - 1.0));

float steps_half = steps * 0.5;

float black = 0.5 * steps * steps;

float step1 = steps + 1.0;

float biggest = 0.75 * ((step1 * step1) - 1.0);

float3 dither_shift = steps * noise - steps_half;

color.xyz += dither_shift * 10.0 * min( color.xyz + black, biggest ); // why * 10.0? It seems to work out just right but also makes me feel weird

if (ShowNoise == true)

color.xyz = noise;

}

color.w = 1.0;

return color;

}

Made for use in effect.txt.

It's only a triangular distribution when you have "Double Noise" on. Maybe you like the uniform distribution with it turned off better, give it a try.

Don't forget to make sure you have the right bit depth. My TN monitor I believe is 6 bit and tries its best to appear 8 bit, in the end 7 bit dither worked best.

I'm inexperienced when it comes to shader programming and computer graphics so I might be making mistakes but this code gives me good results!

When do you want this? When your image isn't dithered you might notice banding in gradients and lighting. Film grain and noise in general will help remove banding, but a good dither shouldn't make the image noisy, it should just remove banding and give the perception of high colour resolution.

Reference used:

https://32ipi028l5q82yhj72224m8j-wpengi ... Lottes.pdfhttps://www.gamedev.net/forums/topic/46 ... s-in-hlsl/http://loopit.dk/banding_in_games.pdfhttps://en.wikipedia.org/wiki/Dither