#include "Conversion.fxh" // technique from http://alex-charlton.com/posts/Dithering_on_the_GPU/ uniform float3 palette[8]; static const int paletteSize = 8; static const int indexMatrix4x4[16] = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5 }; float indexValue(float2 screenCoords) { int x = int(screenCoords.x % 4); int y = int(screenCoords.y % 4); return indexMatrix4x4[(x + y * 4)] / 16.0; } float hueDistance(float h1, float h2) { float diff = abs(h1 - h2); return min(abs(1.0 - diff), diff); } void closestColors(float hue, out float3 ret[2]) { float3 closest = float3(-2, 0, 0); float3 secondClosest = float3(-2, 0, 0); float3 temp; for (int i = 0; i < paletteSize; i++) { temp = palette[i]; float tempDistance = hueDistance(temp.x, hue); if (tempDistance < hueDistance(closest.x, hue)) { secondClosest = closest; closest = temp; } else { if (tempDistance < hueDistance(secondClosest.x, hue)) { secondClosest = temp; } } } ret[0] = closest; ret[1] = secondClosest; } float3 dither(float3 color, float2 screenCoords) { float3 colors[2]; float3 hsl = RGBtoHSL(color); closestColors(hsl.x, colors); float3 closestColor = colors[0]; float3 secondClosestColor = colors[1]; float d = indexValue(screenCoords); float hueDiff = hueDistance(hsl.x, closestColor.x) / hueDistance(secondClosestColor.x, secondClosestColor.x); return HSLtoRGB(hueDiff < d ? closestColor : secondClosestColor); } // brightColor refers to undithered max color // float3 dither(float3 color, float3 brightColor, float2 screenCoords) // { // float brightHue = RGBtoHSL(brightColor.x); // float colorHue = RGBtoHSL(color.x); // float halfDistance = hueDistance(0.0, brightHue) / 2.0; // float3 closestColor = (colorHue < halfDistance) ? float3(0.0, 0.0, 0.0) : brightColor; // float3 secondClosestColor = brightColor - closestColor; // float d = indexValue(screenCoords); // float distance = abs(closestColor - color); // return (distance < d) ? closestColor : secondClosestColor; // } float3 dither(float color, float2 screenCoords) { float closestColor = (color < 0.5) ? 0 : 1; float secondClosestColor = 1 - closestColor; float d = indexValue(screenCoords); float distance = abs(closestColor - color); return (distance < d) ? closestColor : secondClosestColor; }