{"id":384,"date":"2016-11-21T21:36:33","date_gmt":"2016-11-21T20:36:33","guid":{"rendered":"http:\/\/kunsternst.de\/?p=384"},"modified":"2016-11-21T22:03:15","modified_gmt":"2016-11-21T21:03:15","slug":"gameboy-shader","status":"publish","type":"post","link":"https:\/\/kunsternst.de\/?p=384","title":{"rendered":"Gameboy shader"},"content":{"rendered":"<p style=\"text-align: justify;\">Hey there,<\/p>\n<p style=\"text-align: justify;\">Made a super simple Gameboy shader that uses the palette of the old classic gameboy (including green tint!)<\/p>\n<p style=\"text-align: justify;\">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&#8217;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.<\/p>\n<div id=\"attachment_387\" style=\"width: 115px\" class=\"wp-caption alignright\"><img aria-describedby=\"caption-attachment-387\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-387 size-full\" src=\"http:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/Screen_color_test_Gameboy.png\" alt=\"The color palette of the Gameboy classic, illustrated with the picture of a parrot\" width=\"105\" height=\"120\" \/><p id=\"caption-attachment-387\" class=\"wp-caption-text\">Picture from wikipedia (public domain)<\/p><\/div>\n<p style=\"text-align: justify;\">Next I needed to somehow map a full color image to just\u00a0the four values of the G<a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_video_game_console_palettes#Game_Boy\">ameboy classic palette<\/a>. 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\u00a0was\u00a0to take the <a href=\"https:\/\/en.wikipedia.org\/wiki\/RGB_color_model\">RGB <\/a>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 <a href=\"https:\/\/en.wikipedia.org\/wiki\/HSL_and_HSV\">HSL<\/a>, or, more specifically, just calculated the luminance (or brightness or Value or Intensity, depending on what you prefer. ;) ). \u00a0This 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.<\/p>\n<p style=\"text-align: justify;\">In the end, just using the luminance instead of the RGB for calculating the distance between colors didn&#8217;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:<\/p>\n<div id=\"attachment_388\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-388\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-388 size-medium\" src=\"http:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/luminanceDistance-300x166.png\" alt=\"luminancedistance\" width=\"300\" height=\"166\" srcset=\"https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/luminanceDistance-300x166.png 300w, https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/luminanceDistance-768x426.png 768w, https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/luminanceDistance.png 793w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><p id=\"caption-attachment-388\" class=\"wp-caption-text\">Using just luminance<\/p><\/div>\n<div id=\"attachment_390\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-390\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-390 size-medium\" src=\"http:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/rgbDistance-300x167.png\" alt=\"rgbdistance\" width=\"300\" height=\"167\" srcset=\"https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/rgbDistance-300x167.png 300w, https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/rgbDistance-768x429.png 768w, https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/rgbDistance.png 799w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><p id=\"caption-attachment-390\" class=\"wp-caption-text\">Using RGB<\/p><\/div>\n<div id=\"attachment_389\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-389\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-389 size-medium\" src=\"http:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/nomapping-300x168.png\" alt=\"no mapping\" width=\"300\" height=\"168\" srcset=\"https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/nomapping-300x168.png 300w, https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/nomapping-768x431.png 768w, https:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/nomapping.png 796w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><p id=\"caption-attachment-389\" class=\"wp-caption-text\">original colors (scaled)<\/p><\/div>\n<p>You can try out the difference for yourself on\u00a0<a href=\"https:\/\/www.shadertoy.com\/view\/ltV3Wc\">Shadertoy<\/a>. (be careful, the videos have sound auto-playing).<\/p>\n<p>I then went and ported this shader to Unreal, which ended up looking like this:<\/p>\n<div>\n<div style=\"left: 0px; width: 100%; height: 0px; position: relative; padding-bottom: 73.1048%;\"><iframe src=\"\/\/giphy.com\/embed\/3oz8xrUpBYsrwW4PNm\" frameborder=\"0\" allowfullscreen style=\"top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;\"><\/iframe><\/div>\n<\/div>\n<p>If you want to try this yourself in Unreal, just copy the text from <a href=\"http:\/\/kunsternst.de\/wp-content\/uploads\/2016\/11\/gameboymaterial.txt\">this file<\/a>\u00a0and paste it into the UE4 material editor. :)<\/p>\n<p>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. :)<\/p>\n<p>Cheers,<\/p>\n<p>John<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey there, Made a super simple Gameboy shader that uses the palette of the old classic&hellip;<\/p>\n","protected":false},"author":1,"featured_media":390,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[58],"tags":[56,57,55],"_links":{"self":[{"href":"https:\/\/kunsternst.de\/index.php?rest_route=\/wp\/v2\/posts\/384"}],"collection":[{"href":"https:\/\/kunsternst.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kunsternst.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kunsternst.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kunsternst.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=384"}],"version-history":[{"count":10,"href":"https:\/\/kunsternst.de\/index.php?rest_route=\/wp\/v2\/posts\/384\/revisions"}],"predecessor-version":[{"id":398,"href":"https:\/\/kunsternst.de\/index.php?rest_route=\/wp\/v2\/posts\/384\/revisions\/398"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kunsternst.de\/index.php?rest_route=\/wp\/v2\/media\/390"}],"wp:attachment":[{"href":"https:\/\/kunsternst.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=384"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kunsternst.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=384"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kunsternst.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=384"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}