90 lines
2.5 KiB
Plaintext
90 lines
2.5 KiB
Plaintext
|
#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;
|
||
|
}
|