Please use english language
It is currently 14 Dec 2017, 13:22

All times are UTC





Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Triangular Dither
PostPosted: 04 Dec 2017, 17:57 
Offline
User avatar

Joined: 11 May 2014, 10:48
Posts: 34
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.

Image

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


Attachments:
File comment: Drag and drop effect.txt based on Ultimate Shader Addon for ENB
effect.txt [9 KiB]
Downloaded 6 times

_________________
i5 4690k @ 4.5GHz, Sapphire Tri-X R9 290, 8GB DDR3, 1920x1200

Reforged ENB for Dragon's Dogma
Top
 Profile  
 
Tomoko
 Post subject: Re: Triangular Dither
PostPosted: 05 Dec 2017, 12:24 
Offline
*master*
User avatar

Joined: 08 Nov 2012, 15:24
Posts: 131
This is something I worked on for the last update to my ENB, though I chose to err on the side of less noise (and thus potentially more perceptual banding) in the face of some comments I received about my previous implementation.

Is there any reason you chose effect.txt? In my testing, it applied before enbgamedepthoffield.fx, so any dithering implemented there would be blurred over after a distance. I put my implementation there because of that.

_________________
Try my mods! | Resonant ENB for Dragon's Dogma | IAXE2 for Fallout 4 | Luminous ENB for Skyrim SE


Top
 Profile  
 
 Post subject: Re: Triangular Dither
PostPosted: 05 Dec 2017, 19:21 
Offline
User avatar

Joined: 11 May 2014, 10:48
Posts: 34
I chose effect.txt just because that's where the Ultimate Shader Addon for ENB put it, but considering the effectiveness of that dither shader maybe I shouldn't have assumed dither should be there. Upon further consideration I'm pretty confident my implementation doesn't quite check out mathematically but every time I try to fix it it ends up being too noisy for my tastes (unless I up the bit depth to clearly wrong values).

_________________
i5 4690k @ 4.5GHz, Sapphire Tri-X R9 290, 8GB DDR3, 1920x1200

Reforged ENB for Dragon's Dogma


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group