Made a super simple Gameboy shader that uses the palette of the old classic gameboy (including green tint!)
The way it works is simple: first I scale down the image, to get a quarter resolution or less (not actual Gameboy resolution). I don’t do anything fancy here, just skip a few pixels. Fancier would be to get a weighted average, somehow combining the different colors, but that would also require more texture reads. The basic approach already gave decent results, so I kept it.
Next I needed to somehow map a full color image to just the four values of the Gameboy classic palette. Since I needed to figure out which colors to cluster in one palette color, I had to figure out a way to calculate the distance between colors. The first thing that came to mind was to take the RGB color values as a 3D vector and calculate the vector distance. But I thought this would give unsatisfactory results, since I deemed the brightness the only interesting value. So I converted the color from RGB to HSL, or, more specifically, just calculated the luminance (or brightness or Value or Intensity, depending on what you prefer. ;) ). This gave a singular value that made it easy to calculate the distance of colors to the four Gameboy classic palette values and cluster them in four groups to map them.
In the end, just using the luminance instead of the RGB for calculating the distance between colors didn’t actually give better results. Simple RGB vector distance has the added benefits of needing fewer calculations and being easier to implement. (if you are familiar with vector math).Here is the comparison:
You can try out the difference for yourself on Shadertoy. (be careful, the videos have sound auto-playing).
I then went and ported this shader to Unreal, which ended up looking like this:
If you want to try this yourself in Unreal, just copy the text from this file and paste it into the UE4 material editor. :)
It has been suggested to add some dithering to the shader, which is a great Idea, I think. I might make a separate dithering shader altogether. :)