<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Simple shader to scale pixel art</title>
		<link>http://www.allegro.cc/forums/view/612318</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Wed, 03 Apr 2013 02:40:17 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>EDIT: Downloads updated</p><p>I was thinking about the best way to scale pixel art. Obviously any non-integral scale factor will produce &quot;bad&quot; results, but I wanted to see if I could come up with something that was better than nearest sampling and linear interpolation. The idea I had was to essentially do anti-aliasing on the image: i.e. treat each pixel of the source image as a square polygon and then draw an output pixel by blending between the source image pixels in proportion to the area of the output pixel that they cover. Here&#39;s a result of that line of thought... I think it looks better than both linear and nearest sampling and I think I&#39;m going to use it for my games.</p><p>You&#39;re going to need a 5.1 branch Allegro to compile this (5.1.6 snapshot works). The code and shaders are in public domain.</p><p><a href="https://www.allegro.cc/files/attachment/607350">Source</a><br /><a href="https://www.allegro.cc/files/attachment/607351">Windows Binary</a></p><p>To run the example binary you&#39;re going to need the D3D runtime installed to use the D3D backend (if you play video games made in this century you&#39;ll have it installed most likely), otherwise use allegro.cfg to specify the OpenGL backend (<tt>[graphics] driver = opengl</tt>).</p><p>Controls:</p><p>Left/Right - Switch the filtering method (nearest/linear/shader)<br />B - Toggle bitmap (Between a <i>Sūpā Metoroido</i> screenshot I lifted from Wikipedia and a pixel grid pattern)<br />Window border - You can resize the window!</p><p>Screenshots:</p><p>Nearest filtering:<br /><span class="remote-thumbnail"><span class="json">{"name":"607339","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/3\/03283239c326659faf9429d8653ecdbe.png","w":812,"h":631,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/3\/03283239c326659faf9429d8653ecdbe"}</span><img src="http://www.allegro.cc//djungxnpq2nug.cloudfront.net/image/cache/0/3/03283239c326659faf9429d8653ecdbe-240.jpg" alt="607339" width="240" height="186" /></span><br />Linear filtering:<br /><span class="remote-thumbnail"><span class="json">{"name":"607340","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/9\/791531d4f0750c65e2d2509f0a0c46a3.png","w":812,"h":631,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/9\/791531d4f0750c65e2d2509f0a0c46a3"}</span><img src="http://www.allegro.cc//djungxnpq2nug.cloudfront.net/image/cache/7/9/791531d4f0750c65e2d2509f0a0c46a3-240.jpg" alt="607340" width="240" height="186" /></span><br />Shader filtering:<br /><span class="remote-thumbnail"><span class="json">{"name":"607338","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/7\/174a467f732be49c17926e9bdcabdc41.png","w":812,"h":631,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/7\/174a467f732be49c17926e9bdcabdc41"}</span><img src="http://www.allegro.cc//djungxnpq2nug.cloudfront.net/image/cache/1/7/174a467f732be49c17926e9bdcabdc41-240.jpg" alt="607338" width="240" height="186" /></span></p><p>EDIT: There was a bug in the shader code that made the output not be identical to nearest filtering for integral scale factors. It is now fixed, I think.</p><p>EDIT2: Sample from the center of the pixel, not from the corner. Hopefully fixing the variability in output across platforms.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Mon, 01 Apr 2013 00:03:02 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>This look nice!</p><p>You are basicaly interpolating only at the &quot;borders&quot; of the scaled pixel (based on the actual area this scaled pixel covers in the resulting image)?</p><p>I&#39;ve had a look at the GLSL code but I am not <i>that</i> keen on interpreting it.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (pkrcel)</author>
		<pubDate>Mon, 01 Apr 2013 01:59:35 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979459#target">pkrcel</a> said:</div><div class="quote"><p> You are basicaly interpolating only at the &quot;borders&quot; of the scaled pixel (based on the actual area this scaled pixel covers in the resulting image)?</p></div></div><p>Yes, exactly.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Mon, 01 Apr 2013 03:32:45 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Looks quite nice in the screenshot but there&#39;s something wrong with the y offset here:<br /><span class="remote-thumbnail"><span class="json">{"name":"607342","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/b\/8b39f7a5e67af62cd9426259d5425f16.png","w":800,"h":600,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/b\/8b39f7a5e67af62cd9426259d5425f16"}</span><img src="http://www.allegro.cc//djungxnpq2nug.cloudfront.net/image/cache/8/b/8b39f7a5e67af62cd9426259d5425f16-240.jpg" alt="607342" width="240" height="180" /></span></p><p>I&#39;m also curious why you need to recreate the shader on resize.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Peter Wang)</author>
		<pubDate>Mon, 01 Apr 2013 04:26:52 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979462#target">Peter Wang</a> said:</div><div class="quote"><p> Looks quite nice in the screenshot but there&#39;s something wrong with the y offset here:</p></div></div><p>Is this with OpenGL or Direct3D? I&#39;m having bizzare outputs with Direct3D at the moment (on a different computer than where I tested this initially)... not 100% sure why.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p> I&#39;m also curious why you need to recreate the shader on resize.
</p></div></div><p>It crashed for Direct3D otherwise... possibly an Allegro bug.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Mon, 01 Apr 2013 05:27:16 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>You know, a similar effect can be achieved by first enlarging with nearest-neighbour filtering by 300% or 400%, then scaling back down with linear filtering. This is the technique I was going to use back when I was considering making some very-low-resolution games. <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kris Asick)</author>
		<pubDate>Mon, 01 Apr 2013 05:38:59 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979465#target">Kris Asick</a> said:</div><div class="quote"><p> You know, a similar effect can be achieved by first enlarging with nearest-neighbour filtering by 300% or 400%, then scaling back down with linear filtering. This is the technique I was going to use back when I was considering making some very-low-resolution games. <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" /></p></div></div><p>This is exactly the same, except you first (conceptually) enlarge it infinitely. In fact, this is how I first tested that this might produce something nice. The shader approach has the advantage of using less memory, however.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Mon, 01 Apr 2013 05:41:13 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Doesn&#39;t resizing the display cause a device reset? Pretty sure it does. If so, then you have to create shaders and any other GPU resources that Allegro doesn&#39;t do for you. So pretty much anything except bitmaps Allegro created.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Trent Gamblin)</author>
		<pubDate>Mon, 01 Apr 2013 06:07:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I was using OpenGL on Linux with nvidia proprietary driver.</p><p>As usual, it would be nice for Allegro to handle the device reset (and other platform specific quirks) for you - if it&#39;s reasonable.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Peter Wang)</author>
		<pubDate>Mon, 01 Apr 2013 08:59:48 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979471#target">Peter Wang</a> said:</div><div class="quote"><p> I was using OpenGL on Linux with nvidia proprietary driver.</p></div></div><p>That is disturbing. I&#39;ll have to run these shaders through more stringent tests rather than just compiling for my drivers... hopefully it&#39;s some error in the shader and not a fundamental limitation of the approach.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Mon, 01 Apr 2013 09:18:13 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Yea, that last one looks really nice. <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Mark Oates)</author>
		<pubDate>Mon, 01 Apr 2013 18:13:18 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979466#target">SiegeLord</a> said:</div><div class="quote"><p>This is exactly the same, except you first (conceptually) enlarge it infinitely. In fact, this is how I first tested that this might produce something nice. The shader approach has the advantage of using less memory, however.</p></div></div><p>
I&#39;ll agree on the using less memory thing. <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" /></p><p>I did discover at one point though that once you expand the image past the size you intend to resize to during enlargement, going any bigger has no effect on the image quality. IE: 320x240 -&gt; 1280x960 -&gt; 1024x768 looks exactly the same as 320x240 -&gt; 2560x1920 -&gt; 1024x768 <img src="http://www.allegro.cc/forums/smileys/tongue.gif" alt=":P" /></p><p>One advantage to doing it that way is you don&#39;t need to use shaders, granted, now that I actually know how to use shaders myself, I don&#39;t think I&#39;d go back to not using them for things like this. <img src="http://www.allegro.cc/forums/smileys/cool.gif" alt="8-)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kris Asick)</author>
		<pubDate>Mon, 01 Apr 2013 19:06:35 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Peter, could you re-download the shaders and try again? I altered how the texture sampling happens... it fixed my issues with D3D, so it might fix them for you as well.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Tue, 02 Apr 2013 03:20:31 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I don&#39;t know if this is anything like it, but one algorithm that produces pretty good results, especially when scaling up by a small amount is a weighted average scale. It&#39;d probably be easy and fast with a shader...</p><p>Basically say for example you&#39;re scaling up by 1/4, so an extra pixel for every 3 pixels... the 4th pixel would be 1/2 taken from the 3rd pixel and 1/2 taken from the 5th (IIRC, it&#39;s been a while since I implemented it.)</p><p>It doesn&#39;t produce very much blur, at least compared to linear filtering.</p><p>EDIT: Have an old blog post showing some screenshots: <a href="http://www.nooskewl.com/content/monster-2-wiz-scaling">http://www.nooskewl.com/content/monster-2-wiz-scaling</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Trent Gamblin)</author>
		<pubDate>Tue, 02 Apr 2013 03:31:34 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979547#target">Trent Gamblin</a> said:</div><div class="quote"><p> EDIT: Have an old blog post showing some screenshots: <a href="http://www.nooskewl.com/content/monster-2-wiz-scaling">http://www.nooskewl.com/content/monster-2-wiz-scaling</a></p></div></div><p>Yep, that&#39;s exactly the same algorithm, as far as I can tell.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Tue, 02 Apr 2013 04:08:04 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Ah. I had forgotten all about it TBH. I may have another crack at it in shaders instead of software at some point. (BTW, I got the idea from MattyMatt.)
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Trent Gamblin)</author>
		<pubDate>Tue, 02 Apr 2013 06:27:12 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979545#target">SiegeLord</a> said:</div><div class="quote"><p>Peter, could you re-download the shaders and try again? I altered how the texture sampling happens... it fixed my issues with D3D, so it might fix them for you as well.</p></div></div><p>

Works.</p><p>Attached screenshots from a quick-ish hack of Dune Dynasty, 1.5x zoom. It&#39;s supposed have no effect at integer scales, yes?  (Don&#39;t worry about the elements outside the game viewport; those are drawn at scale=2.0 but using the shader with scale=1.5.)
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Peter Wang)</author>
		<pubDate>Tue, 02 Apr 2013 14:28:00 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/612318/979590#target">Peter Wang</a> said:</div><div class="quote"><p> It&#39;s supposed have no effect at integer scales, yes?
</p></div></div><p>That&#39;s correct.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p> Attached screenshots from a quick-ish hack of Dune Dynasty, 1.5x zoom. 
</p></div></div><p>Is the first one (*48.png) with the shader and the second with nearest?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Wed, 03 Apr 2013 00:23:45 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Yes. I should compare it with linear interpolation as well.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Peter Wang)</author>
		<pubDate>Wed, 03 Apr 2013 02:40:17 +0000</pubDate>
	</item>
</rss>
