<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Shawn Hargreaves Blog</title><subtitle type="html">Game programming with the XNA Framework</subtitle><id>http://blogs.msdn.com/shawnhar/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/shawnhar/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2009-08-14T10:03:10Z</updated><entry><title>Premultiplied alpha content processor</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/11/11/premultiplied-alpha-content-processor.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/11/11/premultiplied-alpha-content-processor.aspx</id><published>2009-11-11T16:10:01Z</published><updated>2009-11-11T16:10:01Z</updated><content type="html">&lt;p&gt;As mentioned in my &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/10/premultiplied-alpha-in-xna-game-studio.aspx" target="_blank"&gt;previous post&lt;/a&gt;, a Content Processor that converts textures into &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx" target="_blank"&gt;premultiplied alpha&lt;/a&gt; format: &lt;/p&gt;  &lt;pre class="mypmacsharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Xna.Framework;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Xna.Framework.Content.Pipeline;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Xna.Framework.Content.Pipeline.Graphics;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Xna.Framework.Content.Pipeline.Processors;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; PremultipliedAlpha
{
    [ContentProcessor]
    &lt;span class="kwrd"&gt;class&lt;/span&gt; PremultipliedAlphaTextureProcessor : TextureProcessor
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            input.ConvertBitmapType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(PixelBitmapContent&amp;lt;Color&amp;gt;));

            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (MipmapChain mipChain &lt;span class="kwrd"&gt;in&lt;/span&gt; input.Faces)
            {
                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (PixelBitmapContent&amp;lt;Color&amp;gt; bitmap &lt;span class="kwrd"&gt;in&lt;/span&gt; mipChain)
                {
                    &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; y = 0; y &amp;lt; bitmap.Height; y++)
                    {
                        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; x = 0; x &amp;lt; bitmap.Width; x++)
                        {
                            Color c = bitmap.GetPixel(x, y);

                            c.R = (&lt;span class="kwrd"&gt;byte&lt;/span&gt;)(c.R * c.A / 255);
                            c.G = (&lt;span class="kwrd"&gt;byte&lt;/span&gt;)(c.G * c.A / 255);
                            c.B = (&lt;span class="kwrd"&gt;byte&lt;/span&gt;)(c.B * c.A / 255);

                            bitmap.SetPixel(x, y, c);
                        }
                    }
                }
            }

            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;base&lt;/span&gt;.Process(input, context);
        }
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;




.mypmacsharpcode, .mypmacsharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.mypmacsharpcode pre { margin: 0em; }
.mypmacsharpcode .rem { color: #008000; }
.mypmacsharpcode .kwrd { color: #0000ff; }
.mypmacsharpcode .str { color: #006080; }
.mypmacsharpcode .op { color: #0000c0; }
.mypmacsharpcode .preproc { color: #cc6633; }
.mypmacsharpcode .asp { background-color: #ffff00; }
.mypmacsharpcode .html { color: #800000; }
.mypmacsharpcode .attr { color: #ff0000; }
.mypmacsharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.mypmacsharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9920870" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Premultiplied alpha in XNA Game Studio</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/11/10/premultiplied-alpha-in-xna-game-studio.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/11/10/premultiplied-alpha-in-xna-game-studio.aspx</id><published>2009-11-11T03:24:36Z</published><updated>2009-11-11T03:24:36Z</updated><content type="html">&lt;p&gt;It is possible to use &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx" target="_blank"&gt;premultiplied alpha&lt;/a&gt; with XNA Game Studio, but the bad news is we don't do much to help you with it.&lt;/p&gt;  &lt;p&gt;Why not?&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Yeah&lt;/em&gt;.&amp;#160; Our bad.&amp;#160; In fact one of my biggest regrets about the design of the XNA Framework is that we didn't do more to make this easier!&lt;/p&gt;  &lt;p&gt;To use premultiplied alpha, you must do three things:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;1 – Set The Blend State&lt;/h3&gt;  &lt;p&gt;Premultiplied alpha blending is configured like this:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    graphicsDevice.RenderState.AlphaBlendEnable = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
    graphicsDevice.RenderState.SourceBlend = Blend.One; 
    graphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha; &lt;/pre&gt;

&lt;p&gt;Or if you are using SpriteBatch:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
    graphicsDevice.RenderState.SourceBlend = Blend.One; &lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;2 – Premultiply Your Colors&lt;/h3&gt;

&lt;p&gt;Premultiplied blending only works if all your color values are in premultiplied format. But most paint programs and image file formats do not use premultiplied alpha! So we must find a good place to apply this conversion.&lt;/p&gt;

&lt;p&gt;For most games, both 2D and 3D, the flow of color data goes something like this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;img title="Untitled" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="Untitled" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/PremultipliedalphainXNAGameStudio_7D77/Untitled_8410bd1f-6787-4a26-b502-0743587b7402.png" width="731" border="0" /&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Color values are edited in a paint program, then saved into a .bmp or .png file, which is built into .xnb format by the Content Pipeline, then loaded into a Texture2D object. 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;Other colors may be used to tint the texture. These can be specified as part of the vertex data, or passed as the color parameter to SpriteBatch.Draw. 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;Still more colors may be computed on the fly (eg. realtime lighting). 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;All these colors are passed into the shader, which could do all kinds of interesting things with them, but most often just multiplies them together. 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;The shader produces a final combined color, which is passed to the alpha blending operation. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are several options for where in this process we choose to convert from conventional to premultiplied format. Two in particular I think can be sensible depending on the situation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;table cellspacing="0" cellpadding="4" width="680" border="1"&gt;&lt;tbody&gt;
      &lt;tr&gt;
        &lt;td width="332"&gt;&lt;strong&gt;Convert colors at the end of the pixel shader&lt;/strong&gt;&lt;/td&gt;

        &lt;td width="346"&gt;&lt;strong&gt;Convert colors in a custom Content Processor&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="330"&gt;Add &amp;quot;&lt;em&gt;result.rgb *= result.a&lt;/em&gt;&amp;quot; right before the end of all your shaders&lt;/td&gt;

        &lt;td width="348"&gt;Write a PremultipliedAlphaTextureProcessor, which automatically converts all your textures to premultiplied format while they are being built&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="328"&gt;Requires custom pixel shaders&lt;/td&gt;

        &lt;td width="350"&gt;Does not require custom shaders, so works with SpriteBatch, BasicEffect, etc.&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="327"&gt;Premultiplication happens after the shader has processed any tint colors, so tints are still specified in conventional, non-premultiplied format&lt;/td&gt;

        &lt;td width="351"&gt;All runtime colors, including tint values, are specified in premultiplied format&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="327"&gt;Alpha blending is done with premultiplied colors, so &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/07/premultiplied-alpha-and-image-composition.aspx" target="_blank"&gt;image composition&lt;/a&gt; works properly, but texture filtering happens before the premultiply conversion, so &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/02/texture-filtering-alpha-cutouts.aspx" target="_blank"&gt;alpha cutouts&lt;/a&gt; remain a problem&lt;/td&gt;

        &lt;td width="352"&gt;All rendering uses premultiplied colors, so both &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/07/premultiplied-alpha-and-image-composition.aspx" target="_blank"&gt;image composition&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/02/texture-filtering-alpha-cutouts.aspx" target="_blank"&gt;alpha cutouts&lt;/a&gt; work nicely&lt;/td&gt;
      &lt;/tr&gt;

      &lt;tr&gt;
        &lt;td width="327"&gt;Reasonably easy retrofit to existing code, or even just specific parts of that code, as long as you have custom shaders&lt;/td&gt;

        &lt;td width="352"&gt;Affects everywhere you do color math, which may be a lot of places, so it can be a pain to retrofit if you don't plan this from the start&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;
&lt;/blockquote&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;3 – Use The Right Math&lt;/h3&gt;

&lt;p&gt;Any time you do computations on color values, you need to use the right math for the type of colors you are dealing with. Some things to bear in mind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Keep track of which data is in which format. Mixing premultiplied with conventional colors is a recipe for chaos! 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;This distinction is only important for colors that have fractional or zero alpha. Opaque colors are the same in both formats, so nothing changes for computations that use RGB color without alpha. 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;Conventional colors change opacity by leaving RGB alone while decreasing alpha. For instance to draw a half transparent orange sprite we would specify a tint of (255, 128, 0, 128). But with premultiplied colors, we must also decrease the RGB values, so that same tint would be specified as (128, 64, 0, 128). 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;By far the most common color operation is tinting, which is done by multiplying two colors together (for instance this is how SpriteBatch.Draw combines its texture and color parameter). Color multiplication works the same for premultiplied and conventional colors, as long as both operands are in the same format. 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;This means that SpriteBatch works as-is with premultiplied data. 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;BasicEffect diffuse lighting and vertex coloring also use color multiplication, and therefore work correctly with premultiplied data. 
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;The BasicEffect specular lighting and fog computations will not work correctly with premultiplied data. If you want specular lighting or fog while using premultiplied alpha, you will have to write a custom shader. &lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9920589" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Premultiplied alpha and image composition</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/11/07/premultiplied-alpha-and-image-composition.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/11/07/premultiplied-alpha-and-image-composition.aspx</id><published>2009-11-07T20:34:28Z</published><updated>2009-11-07T20:34:28Z</updated><content type="html">&lt;p&gt;From &lt;a href="http://en.wikipedia.org/wiki/Alpha_compositing" target="_blank"&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&amp;quot;Alpha compositing is the process of combining an image with a background to create the appearance of partial transparency. It is often useful to render image elements in separate passes, and then combine the resulting multiple 2D images into a single, final image in a process called compositing.&amp;quot;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Example&lt;/h3&gt;  &lt;p&gt;I am making a Pong game. I start by clearing my background to CornflowerBlue (100, 149, 237). I then draw a translucent grey box (128, 128, 128, 128) at the top of the screen, which will form the background of my score display. With conventional alpha blending:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;((128, 128, 128) * 0.5)&amp;#160; +&amp;#160; ((100, 149, 237) * (1 - 0.5))&amp;#160; =&amp;#160; (114, 138, 182)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Well and good. But over time, my overlays get more complex, including a map, radar, waypoint indicators, mission objectives, leaderboard rankings, etc. (what can I say, this is a &lt;em&gt;complex &lt;/em&gt;Pong game :-)&amp;#160; To avoid redrawing so much stuff every frame, wouldn't it be cool if I could draw the overlays just once to a rendertarget, then copy the resulting static image over the top of my animating gameplay?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;A Problem&lt;/h3&gt;  &lt;p&gt;Unfortunately, this doesn't work using conventional alpha blending:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Clear rendertarget to (0, 0, 0, 0)&lt;/p&gt;    &lt;p&gt;Blend 50% grey into the rendertarget:&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((128, 128, 128, 128) * 0.5)&amp;#160; +&amp;#160; ((0, 0, 0, 0) * (1 - 0.5))&amp;#160; =&amp;#160; (64, 64, 64, 64)&lt;/p&gt;    &lt;p&gt;Clear backbuffer to CornflowerBlue (100, 149, 237)&lt;/p&gt;    &lt;p&gt;Blend rendertarget over the backbuffer:&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((64, 64, 64) * 0.25)&amp;#160; +&amp;#160; ((100, 149, 237) * (1 - 0.25))&amp;#160; =&amp;#160; (91, 127, 194)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Whoah! That's not even remotely the same result as before. The blend operation is happening twice: first when we draw into the rendertarget, then again when we draw the rendertarget into the backbuffer. Our alpha value ends up getting squared, so 0.5 becomes 0.25.&lt;/p&gt;  &lt;p&gt;We could fix this by removing one of the blend operations:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Disable blending while drawing to the rendertarget&lt;/li&gt;    &lt;li&gt;Or disable blending while drawing the rendertarget over the backbuffer&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;But these are rarely good solutions, since you most likely need blending in both places&amp;#160; (the overlays in my Pong game are built from many layers of alpha blended graphics, and the gameplay scene should be visible behind them).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Some Math&lt;/h3&gt;  &lt;p&gt;Given a series of drawing operations which blend over the top of each other:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;result = a -&amp;gt; b -&amp;gt; c -&amp;gt; d&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;we would like to be able to group a set of calls from the middle of this sequence, storing their result in a rendertarget, then later replace that set of calls with the contents of the rendertarget:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;tmp = b -&amp;gt; c&lt;/p&gt;    &lt;p&gt;result = a -&amp;gt; tmp -&amp;gt; d&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The problem is that this changes the order of the blend operations. What was:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;result = blend(blend(blend(a, b), c), d)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;becomes:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;result = blend(blend(a, blend(b, c)), d)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Because conventional alpha blending is not associative, changing the order of evaluation changes the result.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The Solution&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx" target="_blank"&gt;Premultiplied alpha blending&lt;/a&gt; is associative, so any number of blending operations can be grouped and reordered without affecting the final result.&lt;/p&gt;  &lt;p&gt;To use premultiplied alpha, we make two changes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Convert our source colors into premultiplied format, so translucent grey becomes (64, 64, 64, 128) rather than (128, 128, 128, 128)      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Change RenderState.SourceBlend from Blend.SourceAlpha to Blend.One &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Working through the same example as before:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Clear rendertarget to (0, 0, 0, 0)&lt;/p&gt;    &lt;p&gt;Blend 50% grey into the rendertarget:&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (64, 64, 64, 128) +&amp;#160; ((0, 0, 0, 0) * (1 - 0.5))&amp;#160; =&amp;#160; (64, 64, 64, 128)&lt;/p&gt;    &lt;p&gt;Clear backbuffer to CornflowerBlue (100, 149, 237)&lt;/p&gt;    &lt;p&gt;Blend rendertarget over the backbuffer:&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (64, 64, 64) +&amp;#160; ((100, 149, 237) * (1 - 0.5))&amp;#160; =&amp;#160; (114, 138, 182)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Tada! That's the same result as when we were drawing everything directly to the backbuffer.&lt;/p&gt;  &lt;p&gt;Premultiplied alpha r0x0rz.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Historical Aside&lt;/h3&gt;  &lt;p&gt;Alvy Ray Smith writes about the &lt;a href="http://www.alvyray.com/memos/7_alpha.pdf" target="_blank"&gt;invention of the alpha channel&lt;/a&gt; and &lt;a href="http://www.alvyray.com/memos/4_comp.pdf" target="_blank"&gt;image composition&lt;/a&gt;. I find it interesting that this was invented in the 1970s, and fully grokked as of the classic &lt;a href="http://portal.acm.org/citation.cfm?id=808606" target="_blank"&gt;Porter-Duff paper&lt;/a&gt; in 1984, yet here we are a quarter of a century later, still having a hard time making composition work right because for some reason premultiplied alpha never became as widely understood as it deserves to be.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9919127" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Premultiplied alpha</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx</id><published>2009-11-06T19:39:49Z</published><updated>2009-11-06T19:39:49Z</updated><content type="html">&lt;p&gt;Remember when you first figured out Santa Claus wasn't real? The growing doubt, tempered by the fact that all your friends believed in him, and surely they can't ALL be wrong, then the gradual realization that everybody was in fact wrong...&lt;/p&gt;  &lt;p&gt;Well, I've got another one for you: the way most people do alpha blending is bogus!&lt;/p&gt;  &lt;p&gt;At a fundamental level, alpha has no special meaning at all. Graphics cards manipulate numeric values, but what they do with these values is entirely determined by what shader code you write and which render states you set. The hardware works with Vector4 data types. Because these often represent colors, it is natural to use the first three components for red, green, and blue. That leaves a spare component, called alpha, which can be used for absolutely anything we like.&lt;/p&gt;  &lt;p&gt;Some people use alpha to store shininess, or ambient occlusion, or a collision material ID. In the &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/02/17/motogp-particles.aspx" target="_blank"&gt;MotoGP particle system&lt;/a&gt; I used it to pass a per-particle random number into my vertex shader physics. But most often, alpha is used to represent transparency. It is important to understand that this is just a convention, and there are several different ways it can be done.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Conventional Alpha Blending&lt;/h3&gt;  &lt;p&gt;The majority of programmers, programs, programming APIs, file formats, etc, define transparency as:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;RGB specifies the color of the object &lt;/li&gt;    &lt;li&gt;Alpha specifies how solid it is &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In math:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;blend(source, dest)&amp;#160; =&amp;#160; (source.rgb * source.a) + (dest.rgb * (1 - source.a)) &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In code:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    RenderState.SourceBlend = Blend.SourceAlpha; 
    RenderState.DestinationBlend = Blend.InverseSourceAlpha; &lt;/pre&gt;

&lt;p&gt;In this world, RGB and alpha are independent. You can change one without affecting the other. Even when an object is fully transparent it still has the same RGB as if it was opaque. Thus 100% transparency can be represented by many different color values.&lt;/p&gt;

&lt;p&gt;There isn't really a direct physical analogy for this. I guess it's similar to how a magic cloak of invisibility works in a fantasy universe, where I can be wearing the same red sweater as I am right now, and it remains red even though it currently happens to be invisible.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Premultiplied Alpha Blending&lt;/h3&gt;

&lt;p&gt;Here's a different way to think about transparency:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;RGB specifies how much color the object contributes to the scene &lt;/li&gt;

  &lt;li&gt;Alpha specifies how much it obscures whatever is behind it &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In math:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;blend(source, dest)&amp;#160; =&amp;#160; source.rgb + (dest.rgb * (1 - source.a)) &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In code:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    RenderState.SourceBlend = Blend.One; 
    RenderState.DestinationBlend = Blend.InverseSourceAlpha; &lt;/pre&gt;

&lt;p&gt;In this world, RGB and alpha are linked. To make an object transparent you must reduce both its RGB (to contribute less color) and also its alpha (to obscure less of whatever is behind it). Fully transparent objects no longer have any RGB color, so there is only one value that represents 100% transparency (RGB and alpha all zero).&lt;/p&gt;

&lt;p&gt;This is more like how light behaves in the real world. What is the RGB of my car windscreen? &lt;em&gt;None: it is transparent, so has no color&lt;/em&gt;. How about my sunglasses? &lt;em&gt;These have a fractional alpha value (letting some light some through, while blocking some) and also contribute some RGB for that nice rose-tinted glow&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To use premultiplied alpha, in addition to setting the appropriate renderstates, you must also convert your source graphics into premultiplied format. Drawing a non premultiplied color with premultiplied blending will not give sensible results!&lt;/p&gt;

&lt;p&gt;To convert a non premultiplied color into premultiplied format:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;color.rgb *= color.a&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;(hence why this is called &amp;quot;premultiplied&amp;quot; format)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Look at the blend equations for conventional vs. premultiplied alpha. If you substitute this color format conversion into the premultiplied blend function, you get the conventional blend function, so either way produces the same end result. The difference is that premultiplied alpha applies the (source.rgb * source.a) computation as a preprocess rather than inside the blending hardware.&lt;/p&gt;

&lt;p&gt;I will write more about how to convert graphics into premultiplied format in a later post.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Why premultiplied r0x0rz&lt;/h3&gt;

&lt;p&gt;Premultiplied alpha is better than conventional blending for several reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It works properly when filtering alpha cutouts &lt;em&gt;(see below)&lt;/em&gt; 

    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;It works properly when doing image composition &lt;em&gt;(stay tuned for my next post)&lt;/em&gt; 

    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;It is a superset of both conventional and additive blending. If you set alpha to zero while RGB is non zero, you get an additive blend. This can be handy for particle systems that want to smoothly transition from additive glowing sparks to dark pieces of soot as the particles age.
    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;It plays nice with &lt;a href="http://blogs.msdn.com/shawnhar/archive/2008/10/28/texture-compression.aspx" target="_blank"&gt;DXT compression&lt;/a&gt;, which only supports transparent pixels with an RGB of zero. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Premultiplied alpha cutouts&lt;/h3&gt;

&lt;p&gt;Remember how &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/11/02/texture-filtering-alpha-cutouts.aspx" target="_blank"&gt;filtering can produce ugly fringes around the edges of alpha cutouts&lt;/a&gt;? Not a problem when using premultiplied alpha! Revisiting the example from my previous post:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;tree&amp;#160; =&amp;#160; (0, 255, 0, 255)&lt;/p&gt;

  &lt;p&gt;border&amp;#160; =&amp;#160; (0, 0, 0, 0)&lt;/p&gt;

  &lt;p&gt;background&amp;#160; =&amp;#160; (0, 0, 255)&lt;/p&gt;

  &lt;p&gt;filtered&amp;#160; =&amp;#160; (tree + border) / 2&amp;#160; =&amp;#160; (0, 128, 0, 128)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With conventional alpha blending, the result is darker than we wanted:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;result&amp;#160; =&amp;#160; lerp(background, filtered.rgb, filtered.a)&amp;#160; =&amp;#160; (0, 64, 128)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But premultiplied blending produces the right answer:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;result&amp;#160; =&amp;#160; filtered.rgb + (background * filtered.a)&amp;#160; =&amp;#160; (0, 128, 128)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This works because texture filtering and premultiplied blending are both linear transforms, and are therefore associative:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;blend(filter(a, b),&amp;#160; c)&amp;#160; ==&amp;#160; filter(blend(a, c),&amp;#160; blend(b, c)) &lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9918762" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Texture filtering: alpha cutouts</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/11/02/texture-filtering-alpha-cutouts.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/11/02/texture-filtering-alpha-cutouts.aspx</id><published>2009-11-02T15:21:26Z</published><updated>2009-11-02T15:21:26Z</updated><content type="html">&lt;p&gt;Consider a cutout texture that contains a solid shape surrounded by transparency. Let's say this is a tree, although it could equally well be a &lt;a href="http://blogs.msdn.com/shawnhar/archive/2007/03/07/return-of-the-son-of-programmer-art.aspx" target="_blank"&gt;cat&lt;/a&gt; or an overweight Italian plumber. Our tree is opaque and colored green:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;tree&amp;#160; =&amp;#160; (0, 255, 0, 255)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The surrounding pixels are transparent:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;border&amp;#160; =&amp;#160; (0, 0, 0, 0)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We are drawing over the top of a blue sky:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;background&amp;#160; =&amp;#160; (0, 0, 255)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If we draw without filtering, everything works as expected. Opaque pixels will replace the background, leaving solid green, while the transparent pixels have no effect, leaving solid blue.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Problem&lt;/h3&gt;  &lt;p&gt;What if the texture needs to be &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/09/08/texture-filtering.aspx" target="_blank"&gt;filtered&lt;/a&gt;? For instance our tree could be positioned in such a way that some destination pixels are covered half by opaque green and half by the transparent border. First the filtering hardware interpolates between these two parts of the texture:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;filtered&amp;#160; =&amp;#160; (tree + border) / 2&amp;#160; =&amp;#160; (0, 128, 0, 128)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now the alpha blending hardware combines this filtered color with our blue background:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;result&amp;#160; =&amp;#160; lerp(background, filtered.rgb, filtered.a)&amp;#160; =&amp;#160; (0, 64, 128)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Huh? Halfway between a green tree and blue background should be (0, 128, 128), not (0, 64, 128). The output is darker than we wanted.&lt;/p&gt;  &lt;p&gt;It seems logical that if a pixel has zero alpha, its RGB value should be irrelevant, right? Not so when filtering is enabled...&lt;/p&gt;  &lt;p&gt;Filtering applies equally to the RGB and alpha channels. When used on the alpha channel of a cutout texture it will produce new fractional alpha values around the edge of the shape, which makes things look nice and antialiased. But filtering also produces new RGB colors, part way in between the RGB of the solid and transparent parts of the texture. Thus the RGB values of supposedly transparent pixels can bleed into our final image.&lt;/p&gt;  &lt;p&gt;This most often results in dark borders around alpha cutouts, since the RGB of transparent pixels is often black. Depending on the texture, the bleeding could alternatively be white, pink, etc.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Alternative Explanation For The Mathematically Inclined&lt;/h3&gt;  &lt;p&gt;What we really wanted was:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;filter( blend(tree, background),&amp;#160; blend(border, background) )&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;But instead we got:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;blend( filter(tree, border),&amp;#160; background )&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Because texture filtering and alpha blending are not associative, these do not produce the same result.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Workaround&lt;/h3&gt;  &lt;p&gt;What if we change our tree texture to have green in the RGB channels of its transparent areas, replacing (0, 0, 0, 0) with (0, 255, 0, 0)? We will still get color bleeding around the edges, but because the transparent RGB now matches the color of the main image, this will not look so ugly.&lt;/p&gt;  &lt;p&gt;This workaround can be useful, but is far from perfect:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Not every paint program is able to edit the RGB values of transparent pixels.      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Even if your paint program supports this, beware of codecs that may discard these colors when saving out the image, incorrectly figuring that since these pixels are transparent, their RGB values must be irrelevant (for some reason .png codecs seem especially bad at this).      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Can't use &lt;a href="http://blogs.msdn.com/shawnhar/archive/2008/10/28/texture-compression.aspx" target="_blank"&gt;DXT1 compression&lt;/a&gt;, which only supports transparent pixels with an RGB of zero. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you get bored of having to manually fix-up alpha cutout textures, you could automate it using a custom content processor. This could check your textures as part of the build process, automatically replacing the RGB of transparent pixels with a copy of the RGB from the closest opaque pixel.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Solution&lt;/h3&gt;  &lt;p&gt;The best way to fix this is by using premultiplied alpha.&amp;#160; &lt;em&gt;Stay tuned for my next post...&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9916173" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>New Game Studio samples</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/10/22/new-game-studio-samples.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/10/22/new-game-studio-samples.aspx</id><published>2009-10-22T17:31:43Z</published><updated>2009-10-22T17:31:43Z</updated><content type="html">&lt;p&gt;Hot off the press, &lt;a href="http://creators.xna.com/en-US/sample/primitives3D" target="_blank"&gt;this sample&lt;/a&gt; provides handy classes for generating cubes, spheres, and teapots (great for debug rendering!) while &lt;a href="http://creators.xna.com/en-US/tutorial/skinnedmodelextensions" target="_blank"&gt;this one&lt;/a&gt; shows how to do various hopefully useful things with skinned character models.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Notice how Skinned Model Extensions reuses code from the Primitives3D sample for drawing the collision spheres? You'd almost think Primitives3D was created because halfway through writing the skinning stuff I realized I had no way to display that data :-)&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9911549" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Texture filtering: mipmapped sprite sheets</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/10/22/texture-filtering-mipmapped-sprite-sheets.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/10/22/texture-filtering-mipmapped-sprite-sheets.aspx</id><published>2009-10-22T17:23:40Z</published><updated>2009-10-22T17:23:40Z</updated><content type="html">&lt;p&gt;&lt;a&gt;Beringela&lt;/a&gt; comments on my &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/10/21/texture-filtering-sprite-sheets.aspx" target="_blank"&gt;previous post&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&amp;quot;Why don't spritesheets (with an edge around each sprite) and mipmaps go well together and are there any workarounds other than not using spritesheets or not using mipmaps?&amp;quot;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Let's work through an example, which I shall simplify down to one dimension for clarity. Let's say we have two textures, sized 4x1:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="200" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="52"&gt;&lt;strong&gt;A&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="48"&gt;&lt;strong&gt;B&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="49"&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="49"&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;and 2x1:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="100" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="49"&gt;&lt;strong&gt;E&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="49"&gt;&lt;strong&gt;F&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;With gutters, we could pack these into a 10x1 sprite sheet:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="450" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="52"&gt;&lt;em&gt;a&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="43"&gt;&lt;strong&gt;A&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="44"&gt;&lt;strong&gt;B&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="44"&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="44"&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="44"&gt;&lt;em&gt;d&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="44"&gt;&lt;em&gt;e&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="45"&gt;&lt;strong&gt;E&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="45"&gt;&lt;strong&gt;F&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="43"&gt;&lt;em&gt;f&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;Now let's compute the first mip level:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="399" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="78"&gt;A&lt;/td&gt;          &lt;td valign="top" align="center" width="93"&gt;(B+C)/2&lt;/td&gt;          &lt;td valign="top" align="center" width="75"&gt;D&lt;/td&gt;          &lt;td valign="top" align="center" width="76"&gt;E&lt;/td&gt;          &lt;td valign="top" align="center" width="75"&gt;F&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;Hmm. That does somewhat resemble the original sheet, but it no longer has proper gutters, so filtering will bleed from one sprite to the other.&lt;/p&gt;  &lt;p&gt;Real trouble starts with the second mip level:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;/p&gt;    &lt;table cellspacing="0" cellpadding="2" width="350" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="174"&gt;(A*2 + B + C + D) / 5&lt;/td&gt;          &lt;td valign="top" align="center" width="174"&gt;(D + E*2 + F*2) / 5&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;Our second sprite has disappeared entirely! That rightmost pixel includes colors E and F from sprite #2, but also some amount of color D from sprite #1.&lt;/p&gt;  &lt;p&gt;And of course the final mip is entirely meaningless:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;/p&gt;    &lt;table cellspacing="0" cellpadding="2" width="300" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="298"&gt;(A*2 + B + C + D*2 + E*2 + F*2) / 10&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;There are two ways you can try to make sprite sheets and mipmaps play together:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;em&gt;Wishful thinking&lt;/em&gt;: include gutters wider than a single pixel, cross your fingers, and hope it turns out ok. Any time you see color bleeding problems, increase the gutter size until they go away.       &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;&lt;em&gt;The scientific approach&lt;/em&gt;: restrict all sprites in a sheet to be the same size, so you can terminate your mip chain at the point where an individual sprite has reached 1x1. Calculate the gutter size so you will still have an entire pixel gutter at this smallest mip level, with corresponding larger gutters for larger mips. Generate mip images separately for each sprite, rather than for the sheet as a whole, and regenerate the gutter with different colors for each mip. This is a considerable pain, and wastes a lot of memory (you end up with significantly more gutter pixels than actual data!) but it does work.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Personally, I would avoid using mipmaps and sprite sheets at the same time. Sprite sheets are never &lt;em&gt;necessary&lt;/em&gt;: they're just an optimization to reduce texture switching. When an optimization ends up causing this amount of trouble, you have to wonder if it's really worth it?&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9911536" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Texture filtering: sprite sheets</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/10/21/texture-filtering-sprite-sheets.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/10/21/texture-filtering-sprite-sheets.aspx</id><published>2009-10-21T18:25:36Z</published><updated>2009-10-21T18:25:36Z</updated><content type="html">&lt;p&gt;You can control what happens when &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/10/20/texture-filtering-the-edge-of-the-world.aspx" target="_blank"&gt;texture filtering reads from past the edge of a texture&lt;/a&gt; using the SamplerState.AddressU and AddressV properties. But what if you are using a sprite sheet? The sampler address modes know nothing about how your sprites have been packed together, so when you filter a sprite from a sheet, the GPU will happily sample from outside the area you told it to draw. This causes colors from one sprite to show up along the edges of whatever happens to be packed next to it, which is unlikely to be what you wanted!&lt;/p&gt;  &lt;p&gt;Possible solutions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Don't use sprite sheets. This is especially a good idea if you want &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/09/14/texture-filtering-mipmaps.aspx" target="_blank"&gt;mipmaps&lt;/a&gt;, as it is near impossible to make sprite sheets and mipmaps play nice together.       &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Don't use filtering. &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/09/08/texture-filtering.aspx" target="_blank"&gt;Point sampling&lt;/a&gt; will never read past the edge of the region you specify, so it has no problem with sprite sheets. But then, point sampling tends to look rather ugly, and who wants that?       &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Roll your own filtering in the pixel shader. If you set the GPU to point sampling mode, you could write a shader that implements bilinear filtering by averaging several point samples, and this shader could know about your sprite sheet and thus avoid reading from outside the current sprite. This is likely to be slower than not using sprite sheets at all, though, so not usually a good idea.      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Add a gutter region around each sprite. Given this 3x3 source image: &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="100" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="30"&gt;&lt;strong&gt;A&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="34"&gt;&lt;strong&gt;B&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="34"&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" align="center" width="30"&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="34"&gt;&lt;strong&gt;E&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="34"&gt;&lt;strong&gt;F&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" align="center" width="30"&gt;&lt;strong&gt;G&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="34"&gt;&lt;strong&gt;H&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="34"&gt;&lt;strong&gt;I&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;    &lt;p&gt;Expand it to 5x5:&lt;/p&gt;    &lt;table cellspacing="0" cellpadding="2" width="166" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="32"&gt;&lt;em&gt;a&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;a&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;b&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;c&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;c&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;a&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;A&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;B&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;c&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;d&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;E&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;F&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;f&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;g&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;G&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;H&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;strong&gt;I&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;i&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;g&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;g&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;h&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="33"&gt;&lt;em&gt;i&lt;/em&gt;&lt;/td&gt;          &lt;td valign="top" align="center" width="34"&gt;&lt;em&gt;i&lt;/em&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;    &lt;p&gt;Pack the 5x5 version into your sprite sheet, but just draw the inner 3x3 (shown in bold). Now the filtering hardware can happily read past the edge of the specified region, and will pick up sensible color values from the gutter pixels (shown in italic).&lt;/p&gt;    &lt;p&gt;Adding gutters by hand soon gets boring, but this is easy to automate. Our &lt;a href="http://creators.xna.com/en-US/sample/spritesheet" target="_blank"&gt;Sprite Sheet sample&lt;/a&gt; provides a content processor that will pack any number of textures into a sprite sheet, automatically adding the necessary gutters to make filtering work correctly.&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9910801" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Texture filtering: the edge of the world</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/10/20/texture-filtering-the-edge-of-the-world.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/10/20/texture-filtering-the-edge-of-the-world.aspx</id><published>2009-10-20T23:20:38Z</published><updated>2009-10-20T23:20:38Z</updated><content type="html">&lt;p&gt;&lt;em&gt;Long time no post.&amp;#160; But don't worry, &lt;/em&gt;&lt;a href="http://www.youtube.com/watch?v=dGFXGwHsD_A" target="_blank"&gt;&lt;em&gt;I'm not dead yet&lt;/em&gt;&lt;/a&gt;&lt;em&gt;...&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;One of the more surprising things about &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/09/08/texture-filtering.aspx" target="_blank"&gt;texture filtering&lt;/a&gt; is how easily it can read past the edge of the texture. Consider a 4x1 texture containing four color values:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="250" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="60"&gt;A&lt;/td&gt;          &lt;td valign="top" align="center" width="62"&gt;B&lt;/td&gt;          &lt;td valign="top" align="center" width="62"&gt;C&lt;/td&gt;          &lt;td valign="top" align="center" width="64"&gt;D&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;If we draw this using SpriteBatch with an integer destination location and no scaling or rotation, these values will be copied directly to the screen. But if we draw with scaling, rotation, or a fractional destination location, the output colors will be computed by filtering between the four input values. As long as our source texture coordinates lie in the range 0-1, these filtering computations should never read past the edge of the texture, right?&lt;/p&gt;  &lt;p&gt;Right?&lt;/p&gt;  &lt;p&gt;&lt;em&gt;(you can probably guess this isn't right, on account of how much of this article is still to read :-)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Consider what happens if we scale up to cover an 8x1 destination region. The output pixels will be:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="500" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="62"&gt;A&lt;/td&gt;          &lt;td valign="top" align="center" width="66"&gt;(A+B)/2&lt;/td&gt;          &lt;td valign="top" align="center" width="59"&gt;B&lt;/td&gt;          &lt;td valign="top" align="center" width="66"&gt;(B+C)/2&lt;/td&gt;          &lt;td valign="top" align="center" width="59"&gt;C&lt;/td&gt;          &lt;td valign="top" align="center" width="66"&gt;(C+D)/2&lt;/td&gt;          &lt;td valign="top" align="center" width="59"&gt;D&lt;/td&gt;          &lt;td valign="top" align="center" width="61"&gt;&lt;strong&gt;???&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;What should go in that last cell?&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;We could just repeat D again, but that seems kind of odd. If we are drawing a tile map with the same sprite repeated many times to cover a grid, it would cause an ugly discontinuity where one tile joins the next.      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;We could continue the interpolation pattern, wrapping around to fill this last cell with (D+A)/2. This would look good along the joins between tiles, but not so good if we were drawing a character where it could cause colors from one side of the sprite to wrap around and appear on the other! &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The right solution depends on what you are drawing, so there is no universally correct behavior. You can choose which you want by setting the SamplerState.AddressU and AddressV properties to TextureAddressMode.Clamp or TextureAddressMode.Wrap.&lt;/p&gt;  &lt;p&gt;Many people assume these addressing modes are only important if your texture coordinates go outside the range 0-1, but as we see here, filtering can read past the edge of the texture even when the source texture coordinates lie inside it.&lt;/p&gt;  &lt;p&gt;AddressU and AddressV are usually set to the same value, but they do not have to be. For instance the sky.fx shader from our &lt;a href="http://creators.xna.com/en-US/sample/generatedgeometry" target="_blank"&gt;Generated Geometry sample&lt;/a&gt; sets AddressU to Wrap and AddressV to Clamp, because the sky is a cylinder which should wrap from left to right, but we do not want stray pixels from the bottom of the ground wrapping around and appearing directly overhead!&lt;/p&gt;  &lt;p&gt;Scaling is not the only way to run into these issues. Consider what happens if we slide our sprite half a pixel sideways. Now the four output colors are:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="324" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" align="center" width="85"&gt;(A+B)/2&lt;/td&gt;          &lt;td valign="top" align="center" width="85"&gt;(B+C)/2&lt;/td&gt;          &lt;td valign="top" align="center" width="85"&gt;(C+D)/2&lt;/td&gt;          &lt;td valign="top" align="center" width="67"&gt;&lt;strong&gt;???&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;Same dilemma.&amp;#160; Should that last cell contain D, or (D+A)/2?&lt;/p&gt;  &lt;p&gt;Drawing at fractional positions is especially confusing because we intuitively expect the result to be something like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;table cellspacing="0" cellpadding="2" width="400" border="1"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td align="center" width="75"&gt;A (half alpha)&lt;/td&gt;          &lt;td align="center" width="82"&gt;(A+B)/2&lt;/td&gt;          &lt;td align="center" width="83"&gt;(B+C)/2&lt;/td&gt;          &lt;td align="center" width="84"&gt;(C+D)/2&lt;/td&gt;          &lt;td align="center" width="74"&gt;D (half alpha)&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/blockquote&gt;  &lt;p&gt;But that's not how it works.&amp;#160; &lt;em&gt;Exercise for the reader: what would go wrong if it did?&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I think the confusing part is that there isn't actually any such thing as drawing at a fractional screen position. Screen pixels can either be written or left alone: you can't change just half a pixel (at least not without alpha blending, which introduces its &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/02/18/depth-sorting-alpha-blended-objects.aspx" target="_blank"&gt;own set of problems&lt;/a&gt;). So when we ask the GPU to draw at a fractional location, it rounds to the nearest integer, then slides the texture in the opposite direction to make the output appear fractionally positioned. This produces coordinate values outside the original range.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;quot;But I want my sprite to be rendered like in your last example, with half alpha on both edges!&amp;quot;&lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Easy: just make sure the outermost pixels of your texture have zero alpha (give it a single pixel transparent border). Now when you filter using TextureAddressMode.Clamp, the edges will smoothly fade to zero no matter how things are positioned.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;em&gt;&amp;quot;Couldn't I do that automatically using TextureAddressMode.Border?&amp;quot;&lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Why yes, indeed you could. But border address mode is not supported by all graphics cards.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;em&gt;&amp;quot;What about rotation?&amp;quot;&lt;/em&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Hopefully by now it will be obvious that filtered rotation can read from outside the source texture region, just like scaling and fractional positioning.&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9910253" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Texture filtering: anisotropy</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/09/24/texture-filtering-anisotropy.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/09/24/texture-filtering-anisotropy.aspx</id><published>2009-09-25T02:00:18Z</published><updated>2009-09-25T02:00:18Z</updated><content type="html">&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/09/14/texture-filtering-mipmaps.aspx" target="_blank"&gt;Mipmapping&lt;/a&gt; allows textures to be scaled down by any amount while maintaining high quality filtering and cache-friendly memory access patterns. But mipmaps don't work so well when different axes are scaled by different amounts:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;#160;&lt;img title="Untitled" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="125" alt="Untitled" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Anisotropicfiltering_9F72/Untitled_fa820c4d-c299-4885-a46a-7484451da0bf.png" width="295" border="0" /&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;How do we choose which mip level to use for the elongated cat?&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;By default the GPU will select mipmaps according to whichever axis has the smallest scale. This is efficient and avoids aliasing artifacts, but can lead to unwanted blurriness along the larger axis.      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;You can use SamplerState.MipMapLevelOfDetailBias to force selection of a larger mip level, which reduces blurriness at the cost of aliasing artifacts and poor cache efficiency. Basically heading back toward the bad old days when we had no mipmaps at all. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Non uniform scaling is rare in 2D (&lt;em&gt;although my cat has been eating so much lately, he is well on the way to horizontally scaling up his belly exactly like the above image &lt;/em&gt;:-) but it happens all the time in 3D:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;#160;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="180" alt="Untitled8" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Anisotropicfiltering_9F72/Untitled8_6a1c4ddd-afcc-4959-a4fd-d1a561dab791.png" width="185" border="0" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Any time you apply a perspective transform to a textured triangle which is not exactly facing the camera, non uniform scaling will result.&lt;/p&gt;  &lt;p&gt;Anisotropic filtering improves the quality of these situations by recognizing when textures are being scaled differently in different directions, and taking a larger number of samples to compensate.&lt;/p&gt;  &lt;p&gt;To enable it:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    device.SamplerStates[0].MinFilter = TextureFilter.Anisotropic;
    device.SamplerStates[0].MagFilter = TextureFilter.Linear;
    device.SamplerStates[0].MipFilter = TextureFilter.Linear;
    device.SamplerStates[0].MaxAnisotropy = &amp;lt;n&amp;gt;;&lt;/pre&gt;

&lt;p&gt;MaxAnisotropy is typically set to 2 or 4. Some recent cards support as high as 16, so check the caps to see how high yours can go.&lt;/p&gt;

&lt;p&gt;How it works:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Compute the aspect ratio between the larger and smaller scaling axes&lt;/li&gt;

  &lt;li&gt;If this is greater than MaxAnisotropy, clamp to MaxAnisotropy&lt;/li&gt;

  &lt;li&gt;Choose mip level according to this value (which will usually be whichever axis is larger)&lt;/li&gt;

  &lt;li&gt;To avoid aliasing, sample the texture multiple times along a line determined by the axis which is being shrunk the most, averaging the results&lt;/li&gt;

  &lt;li&gt;The number of samples depends on the ratio between the larger and smaller axes&lt;/li&gt;

  &lt;li&gt;GPUs are smart: if the scaling happens to be uniform, they will only take a single sample even when anisotropic filtering is enabled&lt;/li&gt;

  &lt;li&gt;Thanks to the aspect ratio clamping, there will never be more than MaxAnisotropy samples per destination pixel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How does it look? Here is our favorite landscape with mipmaps but no anisotropic filtering:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;img height="333" alt="image11" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Anisotropicfiltering_9F72/image11_38ecf7e8-d4b4-40da-baa4-43dd7b4da357.png" width="585" border="0" /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; And now with mipmaps plus anisotropic filtering:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;img height="333" alt="image14" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Anisotropicfiltering_9F72/image14_03e61e73-6df2-42bb-9095-3e1e5e96f7e1.png" width="585" border="0" /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both images are free from noisy aliasing, but the anisotropic version has better texture detail on surfaces which are angled relative to the camera, and is less blurry.&lt;/p&gt;

&lt;p&gt;So why doesn't everyone use anisotropic filtering all the time?&lt;/p&gt;

&lt;p&gt;Because this quality improvement comes at a price! Sometimes a high price. All these extra samples take time for the texture unit to compute, and cost extra memory bandwidth too.&lt;/p&gt;

&lt;p&gt;Or it might be free. If your game is &lt;a href="http://blogs.msdn.com/shawnhar/archive/2008/04/07/how-to-tell-if-you-are-cpu-or-gpu-bound.aspx" target="_blank"&gt;CPU bound&lt;/a&gt;, or &lt;a href="http://blogs.msdn.com/shawnhar/archive/2008/04/11/santa-s-production-line.aspx" target="_blank"&gt;bottlenecked by a different part of the GPU&lt;/a&gt;, anisotropic texture fetches might not actually slow things down at all. So try turning it on and see what happens. If it is too slow with a high MaxAnisotropy setting, try a smaller value to find the right balance between quality and performance.&lt;/p&gt;

&lt;p&gt;Back when I was working on &lt;a href="http://www.talula.demon.co.uk/blogindex.html#motogp" target="_blank"&gt;MotoGP&lt;/a&gt;, we wanted anisotropic filtering for quality reasons, but couldn't afford to use it everywhere. We ended up tweaking MaxAnisotropy differently for every texture, setting it to 4 for billboard adverts where the quality improvement was especially noticeable, to 3 for most of the road surface and grass, and 2 for less important things like trees and crowds. We sometimes even used different settings for each layer of a multitexturing shader, for instance a high anisotropy for the base texture but none at all for the &lt;a href="http://blogs.msdn.com/shawnhar/archive/2008/11/03/detail-textures.aspx" target="_blank"&gt;detail texture&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9899217" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Texture filtering: mipmaps</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/09/14/texture-filtering-mipmaps.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/09/14/texture-filtering-mipmaps.aspx</id><published>2009-09-14T23:10:52Z</published><updated>2009-09-14T23:10:52Z</updated><content type="html">&lt;p&gt;In my &lt;a href="http://blogs.msdn.com/shawnhar/archive/2009/09/08/texture-filtering.aspx" target="_blank"&gt;previous article about texture filtering&lt;/a&gt; I mentioned that scaling down images using&amp;#160; point sampling, or scaling to less than half size using linear filtering, looks bad because some source pixels are discarded.&lt;/p&gt;  &lt;p&gt;Why exactly is this a problem?&lt;/p&gt;  &lt;p&gt;Try this thought experiment:&lt;/p&gt;  &lt;p&gt;We have a 256x256 texture, which is being scaled down by a factor of 1/256, so the entire image covers just a single screen pixel. What color should this pixel be?&lt;/p&gt;  &lt;p&gt;If we use point sampling, only one pixel of the 256x256 image will be used, and the others discarded. This can give pretty random results depending on which specific pixel happens to be chosen!&lt;/p&gt;  &lt;p&gt;Consider what happens if we tile our texture, so the scaled down image is repeated 100 times. If each repetition lines up exactly with one screen pixel, they will all choose the same source pixel, but if repetitions and screen pixels do not line up (maybe you are scaling down by 1/255 or 1/257 rather than 1/256, or using a 3D perspective projection), each repetition will end up choosing a different random location in the source texture. This is basically the same thing as:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt; each destination pixel:
        destination = sourceTexture.GetPixel(random.GetNext(), random.GetNext());&lt;/pre&gt;

&lt;p&gt;which is not going to give the best looking results&amp;#160; :-)&lt;/p&gt;

&lt;p&gt;It would obviously be better if we could average all the pixels from the source texture, rather than having to choose just one of them. But averaging 256x256 color values is too slow to do in realtime.&lt;/p&gt;

&lt;p&gt;When you can't afford to compute something on the fly, it is time to precalculate...&lt;/p&gt;

&lt;p&gt;A mipmap is a precalculated copy of an image that has been shrunk to a lower resolution using a more accurate, higher quality filtering algorithm than would be possible in realtime on the GPU. Mipmaps are arranged in a chain where each image is half the size of the previous one, for instance:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Original = 256x256 &lt;/li&gt;

  &lt;li&gt;Mip 1 = 128x128 &lt;/li&gt;

  &lt;li&gt;Mip 2 = 64x64 &lt;/li&gt;

  &lt;li&gt;Mip 3 = 32x32 &lt;/li&gt;

  &lt;li&gt;Mip 4 = 16x16 &lt;/li&gt;

  &lt;li&gt;Mip 5 = 8x8 &lt;/li&gt;

  &lt;li&gt;Mip 6 = 4x4 &lt;/li&gt;

  &lt;li&gt;Mip 7 = 2x2 &lt;/li&gt;

  &lt;li&gt;Mip 8 = 1x1 &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The GPU will automatically choose the appropriate image depending on how much the texture is being shrunk down.&lt;/p&gt;

&lt;p&gt;To draw with mipmaps, you need two things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You must include mipmap data when creating your textures (for instance by setting the &lt;em&gt;Generate Mipmaps &lt;/em&gt;&lt;a href="http://blogs.msdn.com/shawnhar/archive/2007/11/26/content-processor-parameters-in-xna-game-studio-2-0.aspx" target="_blank"&gt;content processor parameter&lt;/a&gt;) 

    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;You must set SamplerState.MipFilter 
    &lt;ul&gt;
      &lt;li&gt;TextureFilter.None = do not use mipmaps &lt;/li&gt;

      &lt;li&gt;TextureFilter.Point = low quality (but sometimes faster) mipmapping &lt;/li&gt;

      &lt;li&gt;TextureFilter.Linear = higher quality mipmapping &lt;/li&gt;

      &lt;li&gt;If you draw using BasicEffect, this will automatically set MipFilter = Linear &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference between Point and Linear mip filtering is how the mipmap level is chosen:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;MipFilter = Point 
    &lt;ul&gt;
      &lt;li&gt;Chooses the appropriate mip level depending on how much the texture is being shrunk &lt;/li&gt;

      &lt;li&gt;If this is a fractional value, rounds up to the next larger mip level &lt;/li&gt;

      &lt;li&gt;This means the mip image may still need to be shrunk by a small amount &lt;/li&gt;

      &lt;li&gt;But linear filtering is good for shrinking as long as we don't go below half size &lt;/li&gt;

      &lt;li&gt;To shrink below half size, we'd just choose a smaller mip level instead &lt;/li&gt;

      &lt;li&gt;There can sometimes be visible artifacts when switching between mip levels &lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;MipFilter = Linear 
    &lt;ul&gt;
      &lt;li&gt;Samples from both the next larger and next smaller mip levels &lt;/li&gt;

      &lt;li&gt;Interpolates between them based on how close the current image scale is to the two mip levels &lt;/li&gt;

      &lt;li&gt;Avoids artifacts along boundaries between mip levels &lt;/li&gt;

      &lt;li&gt;But we must now sample 8 rather than 4 source pixels for each destination, so this can cost more &lt;a href="http://blogs.msdn.com/shawnhar/archive/2008/04/11/santa-s-production-line.aspx" target="_blank"&gt;if your app is texture fetch limited&lt;/a&gt; &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see this in action. Here is the linear filtered terrain from my previous post:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;img height="333" alt="image" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Understandingtexturefiltering_835E/image_84aa8b78-5272-4651-95df-13402aa525d4.png" width="585" border="0" /&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now using mipmaps:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;img height="333" alt="image" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Understandingtexturefiltering_835E/image_03027d15-da70-4104-80dc-89fed43562f6.png" width="585" border="0" /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note how the distant hills appear smooth and free from noisy aliasing. &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Popular urban myth #1&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;&amp;quot;Mipmaps take up too much memory&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Actually, mipmaps use little extra memory, thanks to the power of powers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Mip 1 = 1/4 the original size&lt;/li&gt;

  &lt;li&gt;Mip 2 = 1/16 the original size&lt;/li&gt;

  &lt;li&gt;Mip 3 = 1/64 the original size&lt;/li&gt;

  &lt;li&gt;Mip 4 = 1/256 the original size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you continue this sequence, you'll see that an entire mipmap chain all the way down to 1x1 takes up just 1/3 more memory than the original texture. So it's a negligible overhead, especially once you get past that first mip.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Popular urban myth #2&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;&amp;quot;Mipmaps are slower for the GPU to render&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In fact, they are often much faster! If you aren't scaling down a texture, having mipmaps won't cost anything. But when you are scaling down, mipmaps can save crazy amounts of memory bandwidth.&lt;/p&gt;

&lt;p&gt;Remember our example of a tiled 256x256 texture, where each repeat is being scaled down to 1x1 (a common situation in things like terrain rendering). Without mipmaps, every destination pixel will sample a radically different location in the source texture, so the GPU must jump around fetching colors from different areas of memory. GPUs typically have very small texture caches, relying on the fact that textures tend to be accessed sequentially, so this access pattern will thrash the cache and can bring even a high end card to its knees. But with mipmaps, the GPU can simply load a small mip level which will easily fit in the cache, and can then render many destination pixels without having to go back to main memory.&lt;/p&gt;

&lt;p&gt;So mipmaps are not just for reducing aliasing: they can actually speed up rendering, too.&lt;/p&gt;

&lt;p&gt;Shawn's Recommendation™: &lt;em&gt;if you are going to draw a texture in 3D, or planning to scale it down to less than half size, you should always use mipmaps&lt;/em&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9895118" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Texture filtering</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/09/08/texture-filtering.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/09/08/texture-filtering.aspx</id><published>2009-09-08T19:33:12Z</published><updated>2009-09-08T19:33:12Z</updated><content type="html">&lt;p&gt;Any time we draw graphics using textures, we must figure out how to map one grid of pixels (the texture) onto a different grid of pixels (the screen). This process is called filtering.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;The Identity Transform&lt;/h3&gt;  &lt;p&gt;The pixel mapping is trivial if:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The texture is not being scaled &lt;/li&gt;    &lt;li&gt;The texture is not rotated, or only rotated in 90 degree increments &lt;/li&gt;    &lt;li&gt;The texture is being drawn at an integer destination location &lt;/li&gt;    &lt;li&gt;The texture may be flipped horizontally or vertically &lt;/li&gt;    &lt;li&gt;There are no more complex transforms (shears, perspective, etc) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In this case the source and destination pixel grids line up exactly, so pixel values can be copied directly across.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Filtering In Theory&lt;/h3&gt;  &lt;p&gt;When the source and destination pixel grids do not line up, we must somehow compute new destination pixel values from the source data. In mathematical terms, you can think of this as a two step process:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Based on the source pixel values, try to guess what the original continuously varying analog image might have been &lt;/li&gt;    &lt;li&gt;Quantize this imaginary analog image back down to digital format, sampling at the destination pixel locations based on our chosen definition of &lt;a href=" http://blogs.msdn.com/shawnhar/archive/2009/08/25/what-is-a-pixel.aspx" target="_blank"&gt;what a pixel is&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Of course this isn't actually implemented as two stages: both parts are combined in a single computation.&lt;/p&gt;  &lt;p&gt;It can sometimes also be useful to think of filtering as a choice between two different operations:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;When scaling up an image, we must invent new destination pixel values by trying to guess what should go in between the source pixels &lt;/li&gt;    &lt;li&gt;When scaling down an image, we must combine several source pixels to produce a single destination value &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There are many ways this can be done. For instance when I resize an image in Paint.NET I can choose between three filtering modes: nearest neighbor, bilinear, or bicubic. Many algorithms are tuned to work with specific types of image, for instance &lt;a href="http://en.wikipedia.org/wiki/Hqx" target="_blank"&gt;hqx filtering&lt;/a&gt; gives great results when scaling up retro game graphics, but would be a terrible choice for digital photographs.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Filtering In Practice &lt;/h3&gt;  &lt;p&gt;Realtime graphics hardware supports just four filtering modes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Point &lt;em&gt;(also called nearest neighbor)&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;Linear &lt;em&gt;(also called bilinear)&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;Mipmapping &lt;em&gt;(also called trilinear)&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;Anisotropic &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;These are specified by three SamplerState properties:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;MinFilter controls how textures are minified (scaled down) &lt;/li&gt;    &lt;li&gt;MagFilter controls how textures are magnified (scaled up) &lt;/li&gt;    &lt;li&gt;MipFilter controls whether mipmapping is used &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The attentive reader may wonder why the TextureFilter enum also includes GaussianQuad and PyramidalQuad options. Ignore these: they're a historical legacy. I guess someone once thought they might be useful, but I don't know any graphics cards that actually bother to implement them!&lt;/p&gt;  &lt;p&gt;Note that &lt;a&gt;these&lt;/a&gt; are just the built-in filtering modes. Any time a shader performs a texture lookup, the hardware automatically applies these filtering computations and returns a filtered value. If you want some other kind of filtering, you can implement it yourself in a shader by doing several texture lookups at slightly different locations to read the values of multiple source pixels, then applying your own filtering computation. This is more expensive than the built-in hardware filtering, but necessary if you want to use more advanced filters such as &lt;a href="http://creators.xna.com/en-US/sample/bloom" target="_blank"&gt;Gaussian blur&lt;/a&gt; or &lt;a href="http://creators.xna.com/en-US/sample/nonrealisticrendering" target="_blank"&gt;edge detection&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Point Sampling&lt;/h3&gt;  &lt;p&gt;Point sampling uses a trivially simple filter function. For each destination pixel, it rounds to the closest matching location in the source pixel grid, then takes the value of that single source pixel. Implications:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;When magnifying an image, pixels become large and blocky &lt;/li&gt;    &lt;li&gt;When shrinking, many source pixel values are discarded, which causes aliasing and shimmery speckled noise&lt;/li&gt;    &lt;li&gt;When drawing sprites at fractional destination positions, point sampling has the same effect as if you rounded to an integer location before drawing&lt;/li&gt;    &lt;li&gt;When rotating sprites, some pixel locations will round up while others round down, which causes shimmery aliasing &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For example, here is a textured terrain using point sampling:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;img height="333" alt="image" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Understandingtexturefiltering_835E/image_6c687549-22e3-406c-b18e-39028bdfa2d0.png" width="585" border="0" /&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Note how the closest pixels (where the texture is magnified) are large and blocky, while the distant hills (where the texture is minified) look like they're covered in random green and brown noise as opposed to a proper texture! This noise looks especially ugly when the camera moves.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Linear Filtering&lt;/h3&gt;  &lt;p&gt;For each destination pixel, linear filtering works out the closest matching location in the source pixel grid. It then reads four pixel values from around this location, and interpolates between them. Implications:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;When magnifying an image, it produces smooth gradients in between pixels&lt;/li&gt;    &lt;li&gt;When shrinking, four source pixels are averaged to produce each destination value, so images can be shrunk to half size before any source pixels are discarded&lt;/li&gt;    &lt;li&gt;When rotating or drawing sprites at fractional destination positions, averaging between adjacent pixels creates the illusion of smooth movement with subpixel accuracy, but at the cost of a slight blurring&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The same terrain as above, using linear filtering:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;img height="333" alt="image" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Understandingtexturefiltering_835E/image_84aa8b78-5272-4651-95df-13402aa525d4.png" width="585" border="0" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Note how the closest pixels are smoothed out, and the mid ground is less noisy than with point sampling, but the distant hills still look pretty nasty. This is because with a maximum of four source samples per destination (two vertical and two horizontal), we can only shrink to half size before we have to start skipping some source pixels. Scaling to less than half size still causes the same aliasing as with point sampling.&lt;/p&gt;  &lt;p&gt;We could fix this by averaging more than four source pixels, right? But sampling pixel values is expensive, and graphics cards have to balance the conflicting goals of high visual quality but also high performance. Linear filtering is a classic compromise: good enough to look great when used wisely, but still far from perfect.&lt;/p&gt;  &lt;p&gt;Consider, for instance, this 3x3 image, scaled up using point sampling:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;img title="Untitled" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="60" alt="Untitled" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Understandingtexturefiltering_835E/Untitled_2d1634c1-03e2-447c-a5e7-c90733bb09c4.png" width="60" border="0" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If I&amp;#160; scale it up on my GPU using linear filtering, I get:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;#160;&lt;img title="Untitled" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="60" alt="Untitled" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Understandingtexturefiltering_835E/Untitled_9dc14a09-3727-4a88-b5ac-997956f26576.png" width="60" border="0" /&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That's not horrible, but also not exactly beautiful. If I scale up the same image in Paint.NET using a bicubic filter, I get a much smoother result:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;img title="Untitled" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="60" alt="Untitled" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Understandingtexturefiltering_835E/Untitled_ee693c31-3654-4a27-bc4b-873e43dd36f9.png" width="60" border="0" /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Paint.NET produces better results than my GPU because it uses a more sophisticated filter algorithm that examines more than four source pixels when computing each destination value.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Coming up: mipmaps, anisotropic filtering, and the challenges presented by alpha cutouts and sprite sheet borders...&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9892666" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>What is a pixel?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/08/25/what-is-a-pixel.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/08/25/what-is-a-pixel.aspx</id><published>2009-08-25T21:17:12Z</published><updated>2009-08-25T21:17:12Z</updated><content type="html">&lt;p&gt;I wanted to write about premultiplied alpha, but realized I need to explain some things about filtering first. And then I realized that to properly explain filtering, I need to start with an even more fundamental theoretical question: what is a pixel?&lt;/p&gt;  &lt;p&gt;From &lt;a href="http://en.wikipedia.org/wiki/Pixel" target="_blank"&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&amp;quot;A pixel is the smallest item of information in an image. Pixels are normally arranged in a 2-dimensional grid, and are often represented using dots or squares. Each pixel is a sample of an original image, where more samples typically provide more-accurate representations of the original.&amp;quot;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That's not a bad definition, but it's a little vague, especially the &amp;quot;&lt;em&gt;often represented using dots or squares&lt;/em&gt;&amp;quot; part. Trouble is, when we try to make this more precise, we realize there are actually several different kinds of pixels in common use!&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;A pixel is a tiny square. Images are grids of tightly packed pixels, with no gaps or overlap between adjacent squares.      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;A pixel is a geometric point of zero size. When a continuously varying analog source image is converted to digital format, its color is sampled at each pixel location. Color values from in between these locations are not recorded.      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;A pixel is a circular dot with soft edges. These dots may or may not be larger than the pixel grid spacing: if they are larger, adjacent pixels will overlap. When digitizing an image, all colors within the pixel region are combined, using a falloff curve that weights their contribution according to distance from the pixel center. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Which version is true?&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;This matches what we see in programs like Photoshop, where we can zoom into an image and see the pixels scale up to large squares. It also matches what we are used to from early computers and game machines, where low resolutions had large and blocky pixels. But it's not really true in most cases today.&amp;#160; &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Matches how mathematicians like to view the world, but no actual hardware works like this.     &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;Digital cameras, scanners, monitors, and printers all work this way, or some variant of it. Unfortunately there is no consistency about how much pixels overlap or what falloff curve is used. Some devices vary the concept even further, for instance an LCD uses separate dots with different center locations for the red, green, and blue color components.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Why does this matter?&lt;/p&gt;  &lt;p&gt;Much of the time it does not. Many people write code assuming the mathematically elegant zero sized pixels of #2, and this often works fine even though it doesn't truly match their hardware.&lt;/p&gt;  &lt;p&gt;One time it does matter is when quantizing an image, by converting analog to digital, or shrinking a digital image to a lower resolution. Any time we do such things, we must choose how the new pixel values will be calculated, which requires a specific definition of exactly what a pixel is.&lt;/p&gt;  &lt;p&gt;Another time this matters is when scaling a digital image up to a higher resolution. In some ways this is impossible. We are trying to add more pixels, but these pixel values aren't stored in the source image, and we can't recreate missing data out of thin air! But this is too common and useful an operation to just throw our hands in the air and give up because of a minor technical issue like the problem being fundamentally unsolvable :-) So, we guess. The better we guess, the better the resulting scaled image will look. The more we know about how the source image was created, the more accurate a guess we can make, but in practice we usually know very little, as images don't typically include data describing what pixel falloff curves they were created from.&lt;/p&gt;  &lt;p&gt;So we muddle through with no real standard for what a pixel actually is, and everybody just makes the best guesses they can. Or more often, ignores the question entirely...&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9883944" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Combining shaders</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/08/17/combining-shaders.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/08/17/combining-shaders.aspx</id><published>2009-08-18T01:37:00Z</published><updated>2009-08-18T01:37:00Z</updated><content type="html">&lt;p&gt;&lt;i&gt;&amp;quot;So, I have this shader that does normalmapping, and this other shader that does skinned animation. How can I use them both to render an animated normalmapped character?&amp;quot;&lt;/i&gt;&lt;/p&gt;  &lt;p&gt;Welcome, my friend, to one of the fundamental unsolved problems of graphics programming...&lt;/p&gt;  &lt;p&gt;It seems a reasonable expectation that if you have two effects which work separately, it should be easy to combine them, no? After all, that's exactly what happens in a program like Photoshop. I can add a drop shadow, then a blur, then apply a contrast adjustment, and everything Just Works™. Why not the same for GPU shaders?&lt;/p&gt;  &lt;p&gt;To understand the problem, we need to understand the underlying programming model. An app like Photoshop has a very simple model:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Data is a bitmap image (a 2D array of color values) &lt;/li&gt;    &lt;li&gt;Filters are functions which take in one bitmap and output a different bitmap &lt;/li&gt;    &lt;li&gt;Any number of filters can be stacked by passing the output from one filter as the input of another &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This programming model is conceptually simple, mostly because it only deals with one data type. It is trivial to chain filters together when their input and output are the same type.&lt;/p&gt;  &lt;p&gt;The GPU shader programming model is more flexible, and thus more complex. A slightly simplified diagram:&lt;/p&gt;  &lt;p&gt;&lt;img title="Untitled" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="290" alt="Untitled" src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Combiningshaders_9249/Untitled_828488b1-adbc-41c9-8b64-a9afda45bcf2.png" width="634" border="0" mce_src="http://blogs.msdn.com/blogfiles/shawnhar/WindowsLiveWriter/Combiningshaders_9249/Untitled_828488b1-adbc-41c9-8b64-a9afda45bcf2.png" /&gt;&lt;/p&gt;  &lt;p&gt;The blue boxes represent input data. Red are customizable processing operations, and yellow is the final output. Let's walk through what happens each time you draw something, starting at the left of the diagram and working to the right:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The GPU reads vertex data and indices &lt;/li&gt;    &lt;li&gt;These values are combined to form one or more triangles &lt;/li&gt;    &lt;li&gt;Your &lt;b&gt;vertex shader program&lt;/b&gt; runs once for each vertex       &lt;ul&gt;       &lt;li&gt;Inputs: vertex data + effect parameter values &lt;/li&gt;        &lt;li&gt;Outputs: position + colors + texture coordinate values &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;The GPU takes the position values output by the vertex shader, and works out what screen pixels are covered by each triangle &lt;/li&gt;    &lt;li&gt;It interpolates color and texture coordinate values over the surface of the triangle, generating smooth gradients between the three corner vertices &lt;/li&gt;    &lt;li&gt;Your &lt;b&gt;pixel shader program&lt;/b&gt; runs once for each pixel covered by the triangle       &lt;ul&gt;       &lt;li&gt;Inputs: colors and texture coordinates (produced by interpolation of the vertex shader output values) + effect parameter values + textures &lt;/li&gt;        &lt;li&gt;Outputs: color &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;The color produced by the pixel shader is combined with the previous color at that location in the rendertarget, by applying a user specified &lt;b&gt;blend function&lt;/b&gt; &lt;/li&gt;    &lt;li&gt;The resulting color is stored into the output rendertarget &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Yikes! Note that although the final output is a 2D bitmap (same as for a Photoshop filter), the input is a combination of vertex data, indices, effect parameters, and textures. The input and output types are not the same, which means there is no generalized way to pass the output from one shader as the input of another, and thus no way to automatically combine multiple shaders.&lt;/p&gt;  &lt;p&gt;In fact the only universal way to combine two shaders is to understand how they work individually, then write a new shader that contains all the functionality you are interested in. This is the price we pay for flexibility. Because shader programs can do so many different things in so many different ways, the right way to merge them is different for every pair of shaders. For instance to use animation alongside normalmapping, it is necessary to animate the tangent vectors used by the normalmap computation, which requires changes to both the animation and normalmapping shader code.&lt;/p&gt;  &lt;p&gt;However, there are specific cases in which Photoshop style layering is possible, if you impose extra constraints on the programming model by restricting all your shaders to work in a similar way:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;When processing rectangular 2D regions (most often fullscreen), you can feed the output rendertarget from one drawing operation as an input texture to another. This is only possible when all the interesting work is done in the pixel shader, with SpriteBatch often used to provide the vertex data, indices, and vertex shader. Restricting the geometry pipeline to 2D quads enables Photoshop style composition using a separate shader per layer. Check out &lt;a href="http://creators.xna.com/en-US/sample/bloom" target="_blank" mce_href="http://creators.xna.com/en-US/sample/bloom"&gt;this sample&lt;/a&gt; for an example.       &lt;p&gt;&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;If you have several pixel shaders which produce different color values for the same model, and the desired way to combine these colors is a simple arithmetic operation (typically addition, multiplication, or interpolation), you can draw several times directly to the backbuffer, one pass per shader, and use alpha blending to combine the shader outputs. The first pass will typically use opaque blending with standard depth buffer states, while subsequent passes use some other blend function, depth compare set to equal, and depth writes disabled. This can be a good solution for scenes with large numbers of lights, where each pass adds the contribution of a single light to the color already in the backbuffer. See &lt;a href="http://creators.xna.com/en-US/sample/shader_series5" target="_blank" mce_href="http://creators.xna.com/en-US/sample/shader_series5"&gt;this sample&lt;/a&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In a previous job I designed a system for &lt;a href="http://www.talula.demon.co.uk/hlsl_fragments/hlsl_fragments.html" target="_blank" mce_href="http://www.talula.demon.co.uk/hlsl_fragments/hlsl_fragments.html"&gt;automatically combining shader fragments&lt;/a&gt; in more flexible ways than are possible using rendertargets or alpha blending. This worked well, but was complex both to implement and when adding new shader fragments, and there were still many things it could not handle.&lt;/p&gt;  &lt;p&gt;So there you have it. Combining shaders turns out to be harder than you might expect, and is usually a manual process. But on the plus side, I guess this makes good job security for us shader programmers :-)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9873070" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry><entry><title>Why does my content rebuild every time?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/shawnhar/archive/2009/08/14/why-does-my-content-rebuild-every-time.aspx" /><id>http://blogs.msdn.com/shawnhar/archive/2009/08/14/why-does-my-content-rebuild-every-time.aspx</id><published>2009-08-14T20:03:10Z</published><updated>2009-08-14T20:03:10Z</updated><content type="html">&lt;p&gt;The XNA Framework Content Pipeline tries to use incremental rebuilds wherever possible. This means if you add a hundred content files, build your project, change just one of those files, then build again, only that specific file needs to be rebuilt.&lt;/p&gt;  &lt;p&gt;In a perfect world this would work 100% of the time, but in reality we sometimes rebuild more content than is strictly necessary. Most often this happens if you make a change to a custom processor assembly. The pipeline does not keep track of which assemblies were involved in building which pieces of content, so if any custom assembly changes, all content will be rebuilt. Unwanted rebuilds may also occur when changing project settings, if you have circular project references, or if the Content Pipeline cache file is somehow getting deleted.&lt;/p&gt;  &lt;p&gt;If you think your content is rebuilding more often than it should, you can find out why by turning up the MSBuild output verbosity. If you rebuild-all with the Skinned Model sample, the Visual Studio output pane will normally show something like:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    Building dude.fbx -&amp;gt; SkinningSample\bin\x86\Debug\Content\dude.xnb 
    Building head.tga -&amp;gt; SkinningSample\bin\x86\Debug\Content\head_0.xnb 
    Building SkinnedModel.fx -&amp;gt; SkinningSample\bin\x86\Debug\Content\SkinnedModel_0.xnb 
    Building jacket.tga -&amp;gt; SkinningSample\bin\x86\Debug\Content\jacket_0.xnb 
    Building pants.tga -&amp;gt; SkinningSample\bin\x86\Debug\Content\pants_0.xnb 
    Building upBodyC.tga -&amp;gt; SkinningSample\bin\x86\Debug\Content\upBodyC_0.xnb &lt;/pre&gt;

&lt;p&gt;Open the &lt;em&gt;Tools / Options &lt;/em&gt;menu in Visual Studio. If you are using C# Express, make sure the &lt;em&gt;Show all settings &lt;/em&gt;box is checked. Expand &lt;em&gt;Projects and Solutions&lt;/em&gt;, select the &lt;em&gt;Build and Run &lt;/em&gt;node, and change the &lt;em&gt;MSBuild project build output verbosity &lt;/em&gt;setting from &lt;em&gt;Minimal &lt;/em&gt;to &lt;em&gt;Normal&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now when we rebuild-all, the output pane shows:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    Target CoreCompile: 
        Building dude.fbx -&amp;gt; SkinningSample\bin\x86\Debug\Content\dude.xnb 
        Rebuilding because asset &lt;span class="kwrd"&gt;is&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; 
        Importing dude.fbx with Microsoft.Xna.Framework.Content.Pipeline.FbxImporter 
        Serializing obj\x86\Debug\dude_0.xml 
        Processing dude.fbx with SkinnedModelPipeline.SkinnedModelProcessor 
        Compiling SkinningSample\bin\x86\Debug\Content\dude.xnb 
&lt;em&gt;        (etc)&lt;/em&gt;&lt;/pre&gt;

&lt;p&gt;If we make a change to SkinningData.cs, which changes the custom pipeline assembly, the next build will show:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    Target CoreCompile: 
        Rebuilding all content because pipeline assembly SkinnedModelPipeline.dll has changed 
        Building dude.fbx -&amp;gt; SkinningSample\bin\x86\Debug\Content\dude.xnb 
        Importing dude.fbx with Microsoft.Xna.Framework.Content.Pipeline.FbxImporter 
        Serializing obj\x86\Debug\dude_0.xml 
        Processing dude.fbx with SkinnedModelPipeline.SkinnedModelProcessor 
        Compiling SkinningSample\bin\x86\Debug\Content\dude.xnb 
&lt;em&gt;        (etc)&lt;/em&gt;&lt;/pre&gt;

&lt;p&gt;If you find that content keeps rebuilding because assemblies are changing, consider splitting these assembles to separate game logic (which tends to change often) from content data types (which change less often). If your content project can avoid referencing your game logic assembly, it will no longer need to rebuild each time that code changes.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9870304" width="1" height="1"&gt;</content><author><name>ShawnHargreaves</name><uri>http://blogs.msdn.com/members/ShawnHargreaves.aspx</uri></author></entry></feed>