A long time ago I thought it would be a good idea to multiply up the values of the luminance in order to categorise them better, yet I did not think it possible to use arrays in HLSL shaders. I have been proved wrong. It is possible. So that is what I did:
float3 dithering(float2 texcoord)
{
uint positionX = uint(texcoord.x * SCREEN_WIDTH);
uint positionY = uint(texcoord.y * SCREEN_HEIGHT);
float currentLuminosity = luminosity(tex2D(s0,texcoord).rgb);
int lumIndex = currentLuminosity * 4.999999f;
int oddX = positionX & 1;
int oddY = positionY & 1;
int val[5];
val[0] = 0; // >= 0.0f, < 0.2f
val[1] = 1 - (oddX | oddY); // >= 0.2f, < 0.4f
val[2] = 1 - (oddX ^ oddY); // >= 0.4f, < 0.6f
val[3] = 1 - (oddX & oddY); // >= 0.6f, < 0.8f
val[4] = 1; // >= 0.8f
return float3(val[lumIndex], val[lumIndex], val[lumIndex]);
}
You may note that positionX & 1 and positionY & 1 have been turned into variables, this is because they are re-used and it makes it look neater.
I have also modified the code to use an exclusive-or for the middle values. I thought this was more appropriate as it gives equal parts white and black in both the horizontal and vertical planes, and not just one of them like it was before.
Here is the resulting image:
float3 colourDithering(float2 texcoord)
{
uint positionX = uint(texcoord.x * SCREEN_WIDTH);
uint positionY = uint(texcoord.y * SCREEN_HEIGHT);
float3 inC = tex2D(s0, texcoord).rgb;
float3 index = inC * 4.999999f;
int oddX = positionX & 1;
int oddY = positionY & 1;
int val[5];
val[0] = 0; // >= 0.0f, < 0.2f
val[1] = 1 - (oddX | oddY); // >= 0.2f, < 0.4f
val[2] = 1 - (oddX ^ oddY); // >= 0.4f, < 0.6f
val[3] = 1 - (oddX & oddY); // >= 0.6f, < 0.8f
val[4] = 1; // >= 0.8f
return float3(val[int(index.r)], val[int(index.g)], val[int(index.b)]);
}