

Here hi will have components of value 0.0 or 1.0 depending if the components of input are lower or higher than 0.5. Return vec4(output.rgb, step(0.5, input.a)) Vec3 output = palette.rgb * lo.r * lo.g * lo.b It looks like this: vec3 hi = step(vec3(0.5), input.rgb) I decided to use the corners of the RGB cube as reference (so, up to 8 colors), and apply a different color from the palette to each quadrant. Since we are interpolating the colors after the palette swap there should not introduce artifacts.īy the way, for testing this I came up with a different palette swap approach. Then we apply simple bilinear interpolation using the result as weights: vec4 output = mix(mix(lox_loy, hix_loy, wuv.x), mix(lox_hiy, hix_hiy,
#Game maker studio shaders palette swap code
This code assumes sharpness is a uniform float, and I remind you that wuv is a vec2. Wuv = norm * vec2(pow(norm2.x, sharpness), pow(norm2.y, sharpness)) + 0.5 Now we are going to apply the sharpen algorithm fromīeefster09 that you linked, but only to the fractional part of the pixel coordinates: vec2 norm = (wuv - 0.5) I start with fuv, but since fuv is in pixels we need to multiply by pixel_size: fuv * pixel_sizeĪnd I want to offset it by whole pixels, so I would something like this: fuv * pixel_size + vec2(off_x, off_y) * pixel_sizeĪs you can see pixel_size is a common factor, so we rewrite that: (fuv + vec2(off_x, off_y)) * pixel_size We are going to do bilinear filter later.įor reference, this is how you would query at uv: vec4 color = palette_swap(texture(TEXTURE, uv)) Īnd I'm making new coordinates to query the texture (i.e. I'm also assuming nearest-neighbor filtering. This would allow you to keep the approach you are currently using, or change if you need. I'm, of course, assuming you have a palette_swap function that takes a vec4 and outputs a vec4.

Vec4 hix_hiy = palette_swap(texture(TEXTURE, (fuv + vec2(1.0, 1.0)) * pixel_size)) Vec4 hix_loy = palette_swap(texture(TEXTURE, (fuv + vec2(1.0, 0.0)) * pixel_size)) Vec4 lox_hiy = palette_swap(texture(TEXTURE, (fuv + vec2(0.0, 1.0)) * pixel_size)) We are going to query the four pixels around the uv and apply pallet swapping to the colors we get: vec4 lox_loy = palette_swap(texture(TEXTURE, (fuv + vec2(0.0, 0.0)) * pixel_size))

Here I'm assuming uv goes from (0.0, 0.0) to (1.0, 1.0), and pixel_size is the inverse of the size of the texture in pixels. Split the uv coordinates into integer and fractional and pixels: vec2 fuv = floor(uv / pixel_size) This is what I have been able to come up with: I'll be writing GLSL because I'm more familiar with it, and it is easier for me to test. I am still very much a novice when it comes to shaders, so any help here would be deeply appreciated!
#Game maker studio shaders palette swap how to
In other words the two aforementioned techniques seem to be completely incompatible with one another, yet I really need both of them.Īs far as I can tell the logical solution would be to perform the palette-swapping and similar effects on the texture before scaling and filtering it, however I have no idea of how to actually do this from within a shader, and what the performance implications of doing so would be. The problem is of course that you cannot do palette-swaps on a texture with bilinear filtering because the colors are all blended together. Here and here are a couple of open-source shaders using this technique. Luckily there is a way of scaling pixel-art that looks much smoother without taking away the crispness, which is to use a texture with bilinear filtering enabled but only use interpolated colors on the boundary between pixels. However, in the game there is quite a lot of floating-point camera scaling and movement going on, resulting in choppy-looking visuals when using nearest-neighbor filtering. (These effects are used in a very dynamic way, which is why they are done using a shader instead of, say, a separate texture-atlas for each color palette). Simple stuff as long as you use nearest-neighbor filtering on the texture. Most of these effects work by comparing the color of a texture coordinate with a reference color, and if they match then the color is swapped for another. I am creating a pixel-art game in MonoGame, and have written a shader to perform various effects on a sprite when rendering it, such as performing palette swaps, highlighting outlines, etc.
