(06-30-2014, 07:22 PM)puggsoy Wrote: That looks pretty cool! I might be able to port it to Haxe's version of GLSL (HxSL, which I just discovered) and use it myself. I was wondering a while ago how to go about finding the "closest" colour in a palette, so that should be a great help. Thanks!
That was a tough question to answer, how do you define how close a color is to another?
I do this by mapping colors in HSL space (Hue, Saturation, Luminosity) and comparing the square distance of them, but there's other ways to do it, like mapping it in a different color space, like XYZ or one of the many other color spaces.
Then the method of comparison, the square distance. You could also use a trigonometric comparison, like Cosine similarity, but so far this hasn't caused any artifacts, and is pretty fast.
Posts: 524
Threads: 9
Joined: Jul 2012
07-02-2014, 12:28 PM
(This post was last modified: 07-02-2014, 01:12 PM by TheShyGuy.)
That bitrate shader is pretty cool. I didn't think doing that kind of post processing was that simple.
Do you do the input color->base palette distance check because of how your team works with pixels or because that's just how you support palettes?
Edit:
If it's the latter, why not just convert the original image to a indexing image using a base palette, or generating a base palette. Then, you just send in the indexing image to the shader + the desired (alternate) palette.
paletteUVCoord = sample(indexTexture,UVCoord) / 255
outputColor = sample(altPaletteTexture,paletteUVCoord)
(07-02-2014, 12:28 PM)TheShyGuy Wrote: That bitrate shader is pretty cool. I didn't think doing that kind of post processing was that simple.
Do you do the input color->base palette distance check because of how your team works with pixels or because that's just how you support palettes?
Edit:
If it's the latter, why not just convert the original image to a indexing image using a base palette, or generating a base palette. Then, you just send in the indexing image to the shader + the desired (alternate) palette.
paletteUVCoord = sample(indexTexture,UVCoord) / 255
outputColor = sample(altPaletteTexture,paletteUVCoord)
The shader I made does send in the original palette and the alternate palette and coverts the base image to one that only uses that palette. Then from there you can add an alternative palette, play around with things like brightness, etc.
I do this by iterating through the palette with a loop dependent on a constant called SAMPLES. It's a constant because loops must not be dynamic due to the way GLSL works..
As for generating a base palette, that cannot be done with shaders, but would have to be done with a CPU method that would output a list of colors.
I'll admit I had a bit of trouble answering this, but I hope that was good enough. xD
Posts: 524
Threads: 9
Joined: Jul 2012
07-03-2014, 08:10 PM
(This post was last modified: 07-03-2014, 08:13 PM by TheShyGuy.)
Hehe I understand how to support palettes with shaders =p. I was just wondering if you were doing it your way because you had a reason or because it's just the way you decided to support palettes (which you didn't exactly answer )
Why not generate (or load) a palette on the CPU side and generate (or load) an indexing image (rgba represents a palette index/UV coord). Then, you just send the indexing image + desired palette to the shader. That then means your entire palette shader is as simple as 2 lines:
paletteUVCoord = sample(indexTexture,UVCoord);
paletteColor= sample(altPaletteTexture,paletteUVCoord)
which means you can do a whole lot more with your palette shader due to using less instructions and zero loops.
07-04-2014, 01:02 PM
(This post was last modified: 07-04-2014, 06:57 PM by Mag.)
OK, didn't exactly understand what you meant by indexing image before. So you want to add an extra texture to avoid loops?
There would be no way to determine if the current color is closest to the palette color except by checking every color in the palette. This shader isn't just useful for alternative palettes, but for forcing a base image to only consist of colors in your palette.
Using a texture only for positioning would still require a check to make sure the color is the exact same and you would lose that closest color functionality, which adds just too many features at a low performance cost. That's not to say it's not impossible or impractical, just not as useful.
Code: /**
* returns color in palette closest to inputed color.
*/
vec4 colorPalette(vec4 inColor, sampler2D texPalette) {
vec4 outColor = vec4(0.0);
float minDis = 4.0;
float dis = 3.0;
if (inColor.a > 0.001) {
for (int i = 0; i < SAMPLES; i++) {
vec4 palleteColor = texture2D(texPalette, vec2((float(i) + 0.5) / float(SAMPLES), 0.5));
dis = sqrDistance(rgbToHsl(inColor).rgb, rgbToHsl(palleteColor).rgb);
if (palleteColor.a > 0.001) {
if (dis < minDis) {
minDis = dis;
outColor = palleteColor;
}
}
}
}
return outColor;
}
I did do some changes to my code now on the question of performance and making it more elegant. The starting distance and minimum distance variables have been changed to their highest possible values in the script (sqrDistance of a vec3 color is going to be 3, as pure white is 1 + 1 + 1.). Also changed some of the starting var constructors to their smaller forms.
I need some critique on my pixel art editor, how would any of you guys improve it? I'm going for a modular design where the theme of the suite can change, but how can I improve the current theme?
|