<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sgt. Conker &#187; Graphics</title>
	<atom:link href="http://www.sgtconker.com/category/xna/graphics/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sgtconker.com</link>
	<description>We are &#34;absolutely fine&#34;</description>
	<lastBuildDate>Wed, 06 Jul 2011 13:29:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Catalin on 2D Skeletal Animations</title>
		<link>http://www.sgtconker.com/2011/06/catalin-on-2d-skeletal-animations/</link>
		<comments>http://www.sgtconker.com/2011/06/catalin-on-2d-skeletal-animations/#comments</comments>
		<pubDate>Fri, 17 Jun 2011 19:15:16 +0000</pubDate>
		<dc:creator>Captain boki</dc:creator>
				<category><![CDATA[2D]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Catalin Zima]]></category>
		<category><![CDATA[Skeletons]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/2011/06/catalin-on-2d-skeletal-animations/</guid>
		<description><![CDATA[Catalin “Too Proud To Self-promote” Zima (you might know him as our local XNA MVP Captain ZSquare) has a nice write-up of 2D Skeletal Animations over at his blog. So, if you ever wondered what the benefits of skeletal animations in the 2D world as compared to our beloved sprite sheets are, his post would [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.catalinzima.com/">Catalin “Too Proud To Self-promote” Zima</a> (you might know him as our local XNA MVP Captain ZSquare) has a nice write-up of <a href="http://www.catalinzima.com/2011/06/2d-skeletal-animations/">2D Skeletal Animations over at his blog</a>. So, if you ever wondered what the benefits of skeletal animations in the 2D world as compared to our beloved sprite sheets are, <a href="http://www.catalinzima.com/2011/06/2d-skeletal-animations/">his post would be your starting point</a> to explore this very topic.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2011/06/catalin-on-2d-skeletal-animations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nuclex Framework, Community Character Voting and Morph Targets</title>
		<link>http://www.sgtconker.com/2011/02/nuclex-framework-community-character-voting-and-morph-targets/</link>
		<comments>http://www.sgtconker.com/2011/02/nuclex-framework-community-character-voting-and-morph-targets/#comments</comments>
		<pubDate>Sat, 05 Feb 2011 21:58:47 +0000</pubDate>
		<dc:creator>Captain boki</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[FatCow]]></category>
		<category><![CDATA[Nuclex]]></category>
		<category><![CDATA[VoteForGeorge]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/2011/02/nuclex-framework-community-character-voting-and-morph-targets/</guid>
		<description><![CDATA[Markus “Cygon4” Ewald&#160;announces the immediate availability of an intermediate release of his Nuclex Framework, adding: “There are still outstanding issues, but the previous release is already getting a beard and I'm getting reports for issues already solved  ”
Amit Ginni Patpatia of FatCow Games AS fame reminds the community to vote for a character for [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.nuclex.org/">Markus “Cygon4” Ewald</a>&#160;<a href="http://twitter.com/#!/Cygon4/status/33875462933454849">announces the immediate availability</a> of an <a href="http://nuclexframework.codeplex.com/releases/view/60431">intermediate release of his Nuclex Framework</a>, <a href="http://twitter.com/#!/Cygon4/status/33875616000385025">adding</a>: “<q cite="http://twitter.com/#!/Cygon4/status/33875616000385025">There are still outstanding issues, but the previous release is already getting a beard and I'm getting reports for issues already solved <img src='http://www.sgtconker.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </q>”</p>
<p><a href="http://twitter.com/#!/AmitGinni/status/33904490679640064">Amit Ginni Patpatia</a> of <a href="http://www.fatcowgames.net/">FatCow Games AS</a> fame reminds the <a href="http://networkedblogs.com/dIWpw">community to vote for a character</a> for an upcoming game.</p>
<p>Last but not least <a href="http://twitter.com/#!/mvinetwork/status/33927577106124801">Barnaby Smith</a>&#160;<a href="http://twitter.com/#!/mvinetwork/status/33927577106124801">pokes me</a> about an <a href="http://mvinetwork.co.uk/2011/02/02/xna-morph-targets/">XNA 3.1 Morph Target implementation he put online</a>: “<q cite="http://mvinetwork.co.uk/2011/02/02/xna-morph-targets/">This example uses multiple vertex streams and blends between them using a vertex shader. This approach is a differing method to CPU or VTF based implementations and does not require the calculation of vertex textures, making it quite simple and straightforward.</q>”</p>
<p> <iframe title="YouTube video player" height="390" src="http://www.youtube.com/embed/e6PLtA7wgg0?rel=0" frameborder="0" width="480" allowfullscreen="allowfullscreen"></iframe>
<p><a href="http://mvinetwork.co.uk/2011/02/02/xna-morph-targets/">Source code and more details can be found at his post</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2011/02/nuclex-framework-community-character-voting-and-morph-targets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Screen-space deformations in XNA for Windows Phone 7</title>
		<link>http://www.sgtconker.com/2011/01/screen-space-deformations-in-xna-for-windows-phone-7/</link>
		<comments>http://www.sgtconker.com/2011/01/screen-space-deformations-in-xna-for-windows-phone-7/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 21:56:40 +0000</pubDate>
		<dc:creator>Captain boki</dc:creator>
				<category><![CDATA[2D]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Windows Phone 7]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/2011/01/screen-space-deformations-in-xna-for-windows-phone-7/</guid>
		<description><![CDATA[Captain ZSquare shares his technique to do screen-space deformations on Windows Phone 7. Introduces Catalin:
Working on our games, we came across the need to do some screen-space deformations for all sorts of special effects like explosions, ‘drunk filter’, warp effects and other similar stuff. But since we’re targeting Windows Phone 7, we don’t have access [...]]]></description>
			<content:encoded><![CDATA[<p>Captain ZSquare shares his technique to do <a href="http://www.amusedsloth.com/2011/01/screen-space-deformations-in-xna-for-windows-phone-7/">screen-space deformations on Windows Phone 7</a>. Introduces Catalin:</p>
<blockquote cite="http://www.amusedsloth.com/2011/01/screen-space-deformations-in-xna-for-windows-phone-7/"><p>Working on our games, we came across the need to do some screen-space deformations for all sorts of special effects like explosions, ‘drunk filter’, warp effects and other similar stuff. But since we’re targeting Windows Phone 7, we don’t have access to any custom shaders (which is a bummer), so we had to be creative. In the end, the solution turned out to be rather simple, and the performance is good enough (if you don’t go overboard with the effects, of course).</p>
</blockquote>
<p>See <a href="http://www.amusedsloth.com/2011/01/screen-space-deformations-in-xna-for-windows-phone-7/">the post for screen shoots <em>and</em> code</a>!</p>
<p><em>Lets see if Captain ZSquare <a href="http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass/">reposts</a> this one <a href="http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass-2/">with a screen shoot</a>, too <img src='http://www.sgtconker.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2011/01/screen-space-deformations-in-xna-for-windows-phone-7/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>XNA 4.0 Light Pre-Pass</title>
		<link>http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass-2/</link>
		<comments>http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass-2/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 09:08:38 +0000</pubDate>
		<dc:creator>Captain ZSquare</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Coluna]]></category>
		<category><![CDATA[light pre pass]]></category>
		<category><![CDATA[Rendering]]></category>
		<category><![CDATA[XNA 4.0]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1947</guid>
		<description><![CDATA[Jorge Coluna posted an article on his site about implementing the Light Pre-Pass technique for rendering in XNA 4.0

Read all about it here.
]]></description>
			<content:encoded><![CDATA[<p>Jorge Coluna posted an article on<a href="http://jcoluna.wordpress.com/"> his site</a> about implementing the Light Pre-Pass technique for rendering in XNA 4.0</p>
<p><a href="http://jcoluna.wordpress.com/2011/01/18/xna-4-0-light-pre-pass/"><img class="alignnone" title="Light Pre-Pass in XNA 4.0" src="http://jcoluna.files.wordpress.com/2011/01/shot-lpp-11.jpg" alt="Light Pre-Pass in XNA 4.0" width="467" height="275" /></a></p>
<p>Read all about it <a href="http://jcoluna.wordpress.com/2011/01/18/xna-4-0-light-pre-pass/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XNA 4.0 Light Pre-Pass</title>
		<link>http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass/</link>
		<comments>http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass/#comments</comments>
		<pubDate>Fri, 21 Jan 2011 05:42:22 +0000</pubDate>
		<dc:creator>Captain boki</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[light pre pass]]></category>
		<category><![CDATA[VoteForGeorge]]></category>
		<category><![CDATA[XNA 4.0]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass/</guid>
		<description><![CDATA[Jorge Coluna shares the code and an article of his Light Pre-Pass technique for XNA 4.0. Says the Jorge:
The discussion between pros and cons of different techniques for real-time lighting has been running for years. Forward rendering, deferred shading and light pre-pass are some of the most famous techniques nowadays. Their definitions and variations can [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jcoluna.wordpress.com/">Jorge Coluna</a> shares the code and an article of his <a href="http://jcoluna.wordpress.com/2011/01/18/xna-4-0-light-pre-pass/">Light Pre-Pass technique</a> for XNA 4.0. Says the Jorge:</p>
<blockquote cite="http://jcoluna.wordpress.com/2011/01/18/xna-4-0-light-pre-pass/"><p>The discussion between pros and cons of different techniques for real-time lighting has been running for years. Forward rendering, <a href="http://en.wikipedia.org/wiki/Deferred_shading">deferred shading</a> and <a href="http://diaryofagraphicsprogrammer.blogspot.com/2008/03/light-pre-pass-renderer.html">light pre-pass</a> are some of the most famous techniques nowadays. Their definitions and variations can be found with a simple search on internet, with all the most complex mathematics, notations and formulas possible. Therefore I will not focus on this.</p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2011/01/xna-4-0-light-pre-pass/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>XNA Morphing Meshes Tutorial</title>
		<link>http://www.sgtconker.com/2010/11/xna-morphing-meshes-tutorial/</link>
		<comments>http://www.sgtconker.com/2010/11/xna-morphing-meshes-tutorial/#comments</comments>
		<pubDate>Fri, 05 Nov 2010 20:36:08 +0000</pubDate>
		<dc:creator>Captain ZSquare</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Morphing Meshes]]></category>
		<category><![CDATA[The Cansin]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1864</guid>
		<description><![CDATA[The Cansin posted a new and interesting tutorial about morphing meshes in XNA
With documentation and source code available, the tutorial takes you through the steps of implementing morphing meshes.
Check it out here.
]]></description>
			<content:encoded><![CDATA[<p>The Cansin posted a new and interesting tutorial about morphing meshes in XNA</p>
<p>With documentation and source code available, the tutorial takes you through the steps of implementing morphing meshes.</p>
<p>Check it out <a href="http://thecansin.com/2010/11/xna-morphing-meshes-tutorial/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/11/xna-morphing-meshes-tutorial/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Article: Shaders &#8211; Texturing</title>
		<link>http://www.sgtconker.com/2010/09/article-shaders-texturing/</link>
		<comments>http://www.sgtconker.com/2010/09/article-shaders-texturing/#comments</comments>
		<pubDate>Tue, 21 Sep 2010 19:34:06 +0000</pubDate>
		<dc:creator>Absolutely Fine Tutorial Contest</dc:creator>
				<category><![CDATA[2010 Contest Entries]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Contest]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Absolutely Fine Tutorial Contest]]></category>
		<category><![CDATA[Article]]></category>
		<category><![CDATA[Daniel Greenheck]]></category>
		<category><![CDATA[digitseven]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1792</guid>
		<description><![CDATA[by Daniel Greenheck
This tutorial will cover attaching an image (I'll be using the word texture from now on) to a model to give it a much more detailed look.  Texturing is an essential of creating a realistic scene because it  allows us to give objects very fine detail. Without textures, everything  in [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by <a href="http://digitseven.com">Daniel Greenheck</a></h4>
<div class="wp-caption alignnone" style="width: 561px"><img title="A simple box with a stone black texture" src="http://digitseven.com/images/texturedbox.png" alt="" width="551" height="520" /><p class="wp-caption-text">A simple box with a stone black texture</p></div>
<p>This tutorial will cover attaching an image (I'll be using the word <em>texture </em>from now on) to a model to give it a much more detailed look.  Texturing is an essential of creating a realistic scene because it  allows us to give objects very fine detail. Without textures, everything  in the scene would basically be one color, look very flat and just be  generally boring. The right textures can even give an object the  illusion of depth, further increasing the realism. The stone box above  looks like it has deep cracks in it between the blocks, but that's just  an illusion. The entire box is defined using eight vertices. To  geometrically represent those cracks, it would take thousands of  vertices, something that definitely isn't feasible.</p>
<p><span id="more-1792"></span><br />
So how do we  take a texture and apply it to an object? The whole process is quite  simple. If you remember back to the diffuse shader tutorial, we started  using the VertexPositionNormalTexture structure for our vertices. At the  time I told you to ignore the texture part but now we'll be making full  use of this! Following the normal data in the constructor of VertexPositionNormalTexture, it asks for a set of <strong>texture coordinates</strong>:  a Vector2 used to tell  how our shaders how the texture is attached to the model. What are  texture coordinates you ask?</p>
<blockquote>
<h3>An Explanation of Texture Coordinates</h3>
<p>Texture coordinates are very  simple concept. Take a look at this diagram below; it's a breakdown of  the stone box pictured above.</p>
<div><img src="http://digitseven.com/images/coordinatesdiagram.jpg" alt="" /></div>
<p>As I mentioned before, texture coordinates are a Vector2. The horizontal axis of  the image is assigned to the <em>U</em> component and the vertical <em>t</em>o  the<em> V </em>component. Each component represents the proportion of  distance from the origin along that axis. In simpler terms, the value of  U and V each normally range from 0.0 - 1.0, the origin being the  upper-left corner of the image.<br />
When we specify the texture  coordinates for a vertex, we're telling it what part of the texture  attaches there. Looking at the example I provided above, we'll take the  lower-left triangle on the front face. To attach the texture so it  covers the entire face, my texture coordinates would be as follows:</p>
<blockquote><p><em>Upper-Left Front Vertex</em>: The  origin of the image should attach directly to that point, so <strong>(0 , 0)</strong>.<br />
<em>Bottom-Left Front Vertex</em>: The  lower-left corner of the image should attach here, so<strong> (0 , 1)</strong>.<br />
<em>Bottom-Right  Front Vertex</em>: Following the same principle as the first two, <strong>(1 ,  1)</strong>.</p></blockquote>
<p>Just to keep this simple,  I'm using one's and zero's. If you wanted to use just the upper-left  quadrant of the image, (using the same triangle again) I would use these  texture coordinates:</p>
<blockquote><p><em>Upper-Left  Front Vertex</em>: The origin of the image should  attach directly to that point, so <strong>(0 , 0)</strong>.<br />
<em>Bottom-Left Front Vertex</em>: We're only going halfway down the V axis  this time<strong> (0 , .5)</strong>.<br />
<em>Bottom-Right Front Vertex</em>:  The middle of the image should attach here, so <strong>(.5 , .5)</strong>.</p></blockquote>
<p>Since we're only using half the image now, it would give a  stretching effect. Once you get your shader working properly,  experiment with adjust your texture coordinates to see what effects  different values give.</p></blockquote>
<p>The shader will then go through each triangle on the scene, the pixel shader interpolating the texture coordinates between all the vertices of each triangle. That's how you can specify only three attachment points on a triangle, but get the image spread across the entire surface. Once you get the texture coordinates for the pixel, it will sample the texture at those coordinates, returning the pixel color (which you can adjust by the amount of light that hits it, etc.) That's it! Let's take a look at the shader code.</p>
<h2>The All-Purpose Shader</h2>
<p>I've  added the texture code to the shader we've been building up over the  last few tutorials. If you scan the code, you'll  probably notice how <em>little </em>code I added. In fact I only added  about 4 lines of code to implement texturing, none of them being math-oriented either (thank  the heavens). Now we have a basic shader that can  handle ambient, diffuse and specular lighting while also allowing you to  add textures to your models.</p>
<pre class="brush: csharp; title: ;">
float4x4 World;
float4x4 View;
float4x4 Projection;

float4 AmbientColor;
float AmbientIntensity;

float4 DiffuseColor;
float DiffuseIntensity;
float3 DiffuseLightDirection;

float4 SpecularColor;
float SpecularIntensity;
float Shinniness;
float3 CameraPosition;

// Texturing variables
Texture ModelTexture;        // Our texture which will be mapped onto our object

// Pass coordinates to our texture sampler to get a color for a certain pixel
sampler TextureSampler = sampler_state {
    texture = &lt;ModelTexture&gt; ;
    magfilter = LINEAR;
    minfilter = LINEAR;
    mipfilter= LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;};

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;
    float2 TexCoords : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 Normal : TEXCOORD0;
    float3 CameraView : TEXCOORD1;
    float2 TexCoords :TEXCOORD2;
};

VertexShaderOutput VertexShader( VertexShaderInput input )
{
    VertexShaderOutput output;

    float4 worldPosition = mul( input.Position, World );
    float4 viewPosition = mul( worldPosition, View );
    output.Position = mul( viewPosition, Projection );

    output.Normal = mul( input.Normal, World );
    output.CameraView = normalize( CameraPosition - worldPosition );

    // Just pass the texture coordinates to the vertex shader output.
    // When they transfer to the pixel shader, they will be interpolated
    // per pixel.
    output.TexCoords = input.TexCoords;

    return output;
}

float4 PixelShader( VertexShaderOutput input ) : COLOR0
{
    // Sample our texture at the specified texture coordinates to get the texture color
    float4 texColor = tex2D( TextureSampler, input.TexCoords );

    float3 lightdir = normalize( DiffuseLightDirection );
    float3 norm = normalize( input.Normal );
    float3 halfAngle = normalize( lightdir + input.CameraView );
    float specular = pow( saturate( dot( norm, halfAngle ) ), Shinniness ) * SpecularColor * SpecularIntensity;

    float4 diffuse = dot( lightdir, input.Normal ) * DiffuseIntensity * DiffuseColor;
    float4 ambient = AmbientIntensity * AmbientColor;

    return texColor * ( diffuse + ambient + specular );
}

technique Texturing
{
    pass Pass0
    {
        VertexShader = compile vs_1_1 VertexShader();
        PixelShader = compile ps_2_0 PixelShader();
    }
}
</pre>
<h2>Changes to The Vertex In/Out Structures</h2>
<p>Nothing major happened here. All we did was add a <em>float2 </em>to each structure to store our texture coordinates. I've just assigned the next TEXCOORDS semantic that was available. The input structure will contain texture coordinates for the vertices and the output structure will contain the interpolated texture coordinates for the pixel shaders, which is what we want.</p>
<h2>Two New Variables</h2>
<pre class="brush: csharp; title: ;">
// Texturing variables
Texture ModelTexture;        // Our texture which will be mapped onto our object

// Pass coordinates to our texture sampler to get a color for a certain pixel
sampler TextureSampler = sampler_state {
    texture = &lt;ModelTexture&gt; ;
    magfilter = LINEAR;
    minfilter = LINEAR;
    mipfilter= LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;};
</pre>
<p>1. <strong>ModelTexture </strong>- This is where the texture is stored.  We call SetValue() on the XNA side with a reference to Texture or Texture2D to set the texture we want our  shader to sample.</p>
<p>2. <strong>TextureSampler </strong>-  This handy little device allows us to pass in a pair of texture  coordinates and get the color of the texture at that point. It may look  complicated to declare but it really isn't. There's a whole boatload of  arguments )separated by semicolons) you can specify for a <em>sampler </em>but  I've just chosen six here. The first is a reference to the texture we  want to sample, so we put <strong>ModelTexture </strong>between &lt;&gt;. The next  three are filters applied to the texture. If you want to learn what  they do, you'll have to do a little research on your own (Google!). The  next two, <strong>AddressU </strong>and <strong>AddressV</strong>, have several states:</p>
<ul>
<li><em>WRAP </em>- If the values exceed 1, the texture is repeated  along that axis. So if AddressU was set to WRAP and the U coordinate was  5, it would repeat 5 times along the U axis.</li>
<li><em>CLAMP </em>- The  values are clamped between 0 and 1. If they precede 0, they are set to  0. If they exceed 1, they are set to 1.</li>
<li><em>MIRROR </em>- Similar to WRAP, but each consecutive tile is a mirrored from  the last along the axis perpendicular to the mirrored axis.</li>
</ul>
<h2>Vertex Shader</h2>
<p>The only line I added here was passing the vertex shader coordinates to the output structure so they could be interpolated in the pixel shader.</p>
<h2>Pixel Shader</h2>
<p>Once in the pixel shader, we can finally sample our texture for what we need. By calling tex2D() on our texture sampler and the interpolated texture coordinates from our input data, we get back a float4 which represents the color of the texture at that pixel. Perfect! Now what to do with it?<br />
In the previous shaders, everytime I added a new lighting component, I would add it to the total sum. With texture color this is different. The texture color is independent of the light; it is an intrinsic property of the object we are working with. If our box is textured with a stone wall, it's going to be colored like a stone wall if the lights are on or off. By multiplying our texture color by the sum of the lighting components, we can get our desired effect of having a darker color when it's dark and a lighter color when it's bright.</p>
<h2>The XNA Side of Things</h2>
<p>There isn't a whole lot to do on the  XNA side to use our new shader. Make sure to reference to your new  shader and change the technique name to "Texturing" or whatever you chose. Since our shader now  needs a texture, you're also going to need to declare a Texture2D variable. In <em>the  LoadContent() </em>method, load whatever texture you please into the  texture variable from the content pipeline. Then in the main <em>Draw()</em> method of your game, set the value of <strong>ModelTexture </strong>to the Texture2D variable you declared  so the shader knows what texture to draw. You should now have a  textured model on the screen!</p>
<h2>Conclusion</h2>
<p>Congratulations! If you've followed the tutorials to this point, you've  created a shader that basically replicates the functionality of the BasicEffect class in XNA.  "What?! They already wrote this stuff?" Easy there. You may have  replicated some existing functionality, but you now have a superb  understanding of how shaders work ( Hopefully. Or you are just amazingly  confused at what I've been talking about this entire time which is a  very real possibility) and a fully tweakable shader.<br />
By adding  texturing to our all-purpose shader, you can now give an amazing amount  of detail to characters, buildings, cars, trees, weapons or whatever  else might be inhabiting your game world. Texturing gives objects the  illusion of depth and detail without defining extra geometry. If you  continue your shader education, you will find some amazing techniques  used to give the illusion of depth and detail such as bump mapping and  parallax mapping. And guess what? Both of those techniques use special  textures that are sampled in nearly the same way we did with this  shader.<br />
I will be covering more advanced shaders from now on, so  make sure you have the details in the tutorials up to this point down  pat. Feel free to experiment with the code we've written to get a firmer  grasp on what each part of it does. Try to write a shader to give your  model a unique effect not covered here. Good luck and happy programming!</p>
<p><strong>Download source: <a href="http://digitseven.com/Documents/Texturing.zip">Texturing.zip</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/09/article-shaders-texturing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Article: Shaders &#8211; Specular Lighting</title>
		<link>http://www.sgtconker.com/2010/09/article-shaders-specular-lighting/</link>
		<comments>http://www.sgtconker.com/2010/09/article-shaders-specular-lighting/#comments</comments>
		<pubDate>Tue, 21 Sep 2010 19:15:52 +0000</pubDate>
		<dc:creator>Absolutely Fine Tutorial Contest</dc:creator>
				<category><![CDATA[2010 Contest Entries]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Contest]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Absolutely Fine Tutorial Contest]]></category>
		<category><![CDATA[Article]]></category>
		<category><![CDATA[Daniel Greenheck]]></category>
		<category><![CDATA[digitseven]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1789</guid>
		<description><![CDATA[by Daniel Greenheck
What should I be familiar with before I go through this tutorial?
- The content discussed in the introduction, ambient and diffuse tutorials.
One Thing Before I Begin...
To keep things succinct, I will no longer explain or comment things explained in previous tutorials. Throughout these series of tutorials, I'm going to expect you've gone through [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by <a href="http://digitseven.com">Daniel Greenheck</a></h4>
<p><strong><em>What should I be familiar with before I go through this tutorial?</em></strong><br />
- The content discussed in the <a href="http://www.sgtconker.com/2010/09/article-shaders-introduction/">introduction</a>, <a href="http://www.sgtconker.com/2010/09/article-shaders-ambient-lighting/">ambient</a> and <a href="http://www.sgtconker.com/2010/09/article-shaders-diffuse-lighting-2/">diffuse </a>tutorials.</p>
<h2>One Thing Before I Begin...</h2>
<p>To keep things succinct, I will no longer explain or comment things explained in previous tutorials. Throughout these series of tutorials, I'm going to expect you've gone through the previous tutorials. No sense in beating a dead horse. So if you look at the variables section and only see the Specular variables, rest assured the others are still in the actual program. I just think it will be easier for you as a reader if I only present you with new information. That aside, let's begin!</p>
<h2>What is Specular Lighting?</h2>
<p>Specular lighting in one word: shiny. The world specular in itself  means a mirror-like surface, so you can imagine that anything that has  specular lighting is very reflective, causing it to have shiny  highlights. If you place a polished chrome ball under a direct light  source, you'll probably see a big shiny spot blinding you; this is the  specular highlight. Specular reflections  are caused by the reflection of the actual light source itself. If  the surface isn't flat however, it will warp the light and you'll  usually see it as a small dot of bright light or curved lines of light.  When you're out on a sunny day, look around at smooth, metallic objects  and notice their specular highlights. Try and determine how the light is  coming in and being reflected off the surface to your eye. The more you  understand about real-world lighting, the better you'll understand what  we're trying to replicate in our shaders.</p>
<div><img src="http://digitseven.com/images/595002557_8aa8f72677.jpg" alt="" /><br />
<span style="font-size: xx-small;">The perfect example of specular  lighting. Notice the highlight is really the reflection of the sun.</span></div>
<h2><span id="more-1789"></span></h2>
<h2>The Specular Shader</h2>
<p>As usual, I once again present you with the entire specular shader. If you skipped my intro to this article, which I can't blame you for, I'll remind you that I left out the commenting on anything non-specular to save space and make the presentation a little nicer. If you don't know what the other parts of the program do, go back and read the Ambient and Diffuse shaders.</p>
<pre class="brush: csharp; title: ;">
float4x4 World;
float4x4 View;
float4x4 Projection;

float4 AmbientColor;
float AmbientIntensity;

float4 DiffuseColor;
float DiffuseIntensity;
float3 DiffuseLightDirection;

// Specular Variables
float4 SpecularColor;
float SpecularIntensity;
float Shinniness;                // Sharpness the specular highlights. Higher number = sharper highlight
float3 CameraPosition;

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 Normal : TEXCOORD0;
    float3 CameraView : TEXCOORD1;
};

VertexShaderOutput VertexShader( VertexShaderInput input )
{
    VertexShaderOutput output;

    float4 worldPosition = mul( input.Position, World );
    float4 viewPosition = mul( worldPosition, View );
    output.Position = mul( viewPosition, Projection );

    output.Normal = mul( input.Normal, World );

    // Get the vector from the camera to the vertex for the specular component by
    // subtracting the world position from the camera
    output.CameraView = normalize( CameraPosition - worldPosition );

    return output;
}

float4 PixelShader( VertexShaderOutput input ) : COLOR0
{
    // Normalize our variables
    float3 lightdir = normalize( DiffuseLightDirection );
    float3 norm = normalize( input.Normal );

    // Calculate the half angle: the half the angle between our light direction and camera view
    float3 halfAngle = normalize( lightdir + input.CameraView );

    // Take the dot product between the normal of the pixel and the half angle. The closer the two
    // vectors are to pointing in the same direction, the higher the dot product. Take that to the [Shinniness]
    // power to make the highlight strong in the middle and fade out as you get towards the edges.
    float specular = pow( saturate( dot( norm, halfAngle ) ), Shinniness ) * SpecularColor * SpecularIntensity;

    float4 diffuse = dot( lightdir, input.Normal ) * DiffuseIntensity * DiffuseColor;
    float4 ambient = AmbientIntensity * AmbientColor;

    return saturate( diffuse + ambient + specular );
}

technique Specular
{
    pass Pass0
    {
        VertexShader = compile vs_1_1 VertexShader();
        PixelShader = compile ps_2_0 PixelShader();
    }
}
</pre>
<p>There's four things of interest we've added to the program:</p>
<ol>
<li>Four new variables: <strong>SpecularColor</strong>,  <strong>SpecularIntensity</strong>, <strong>Shinniness </strong>and <strong>CameraPosition</strong>.</li>
<li>In the output  structure, we added a new <em>float3 </em>for CameraView.</li>
<li>In the vertex  shader, we calculate our <strong>CameraView </strong>by subtracting the <strong>WorldPosition </strong>of the vertex from our <strong>CameraPosition.</strong></li>
<li>The pixel shaders  does some calculations to calculate the specular component. They look  pretty confusing right now, but don't worry, we'll break them down.</li>
</ol>
<h2>New Specular Variables</h2>
<pre class="brush: csharp; title: ;">
float4 SpecularColor;
float SpecularIntensity;
float Shinniness;                // Sharpness the specular highlights. Higher number = sharper highlight
float3 CameraPosition;
</pre>
<p>The first two variables are the same as the Ambient and Diffuse variables of similar name: they adjust the color and intensity of the specular light, respectively. The next variable is brand new however: <strong>Shinniness</strong>. This is a floating point number that adjusts the size and sharpness of the specular light. If you have a higher value, you're going to get a very intense, small highlight. If you set it to a lower value, the specular highlight will be broader, but overall not as sharp. Play with different values to get the effect you want. The range of values you'll want to stay within is 10 and 2000, though you can really pick whatever you want.</p>
<p>The next variable is the current position of the camera in the scene, a.k.a. the "eye" you are looking through. Since the specular highlights you see depend on your angle with the object and the light source, we'll need to update this variable every frame. For example: If you walk around a freshly-waxed car, you'll notice the specular highlights on the body and windows don't stay in the same spot. Depending on your position, the sun will be reflected to your eye off different parts of the car and at different angles.</p>
<h2>Adding the CameraView to the Output Structure</h2>
<pre class="brush: csharp; title: ;">
struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 Normal : TEXCOORD0;
    float3 CameraView : TEXCOORD1;
};
</pre>
<p>We've added one new parameter to our <em>VertexShaderOutput</em>: CameraView. All we are passing here is a unit vector which represents the direction from the camera to the current vertex.</p>
<h2>Vertex Shader</h2>
<pre class="brush: csharp; title: ;">
VertexShaderOutput VertexShader( VertexShaderInput input )
{
    VertexShaderOutput output;

    float4 worldPosition = mul( input.Position, World );
    float4 viewPosition = mul( worldPosition, View );
    output.Position = mul( viewPosition, Projection );

    output.Normal = mul( input.Normal, World );

    // Get the vector from the camera to the vertex for the specular component by
    // subtracting the world position from the camera
    output.CameraView = normalize( CameraPosition - worldPosition );

    return output;
}
</pre>
<p>Compared to the diffuse shader, everything is the almost exactly the same. The only new thing we added is calculating the <strong>CameraView</strong>, which I just mentioned above. We just take the <strong>CameraPosition </strong>and subtract the position of the vertex in <em>world space</em>. Vector algebra determines that this gives the vector from the camera to the vertex. Then we normalize that to get a unit vector. Simple! We'll be using <strong>CameraView </strong>next...</p>
<h2>Pixel Shader</h2>
<pre class="brush: csharp; title: ;">
float4 PixelShader( VertexShaderOutput input ) : COLOR0
{
    // Normalize our variables
    float3 lightDir = normalize( DiffuseLightDirection );
    float3 norm = normalize( input.Normal );

    // Calculate the half angle: the half the angle between our light direction and camera view
    float3 halfAngle = normalize( lightDir + input.CameraView );
    // Take the dot product between the normal of the pixel and the half angle. The closer the two
    // vectors are to pointing in the same direction, the higher the dot product. Take that to the [Shinniness]
    // power to make the highlight strong in the middle and fade out as you get towards the edges.
    float specular = pow( saturate( dot( norm, halfAngle ) ), Shinniness ) * SpecularColor * SpecularIntensity;

    float4 diffuse = dot( lightdir, input.Normal ) * DiffuseIntensity * DiffuseColor;
    float4 ambient = AmbientIntensity * AmbientColor;

    return saturate( diffuse + ambient + specular );
}
</pre>
<div><img src="http://digitseven.com/images/specularlighting.png" alt="" /> <img src="http://digitseven.com/images/example.jpg" alt="" /></div>
<p>The  picture on the left is my cartoon depiction of what is going on. We have  an eyeball representing the camera position, the sun representing where the light is coming in from, and a little red box to act as our scene object. I've labeled each vector, all which you can  find in the pixel shader code. Take this time to locate all of them now  so you can follow along as we pick apart the code. The picture on the  right is what the eyeball in the cartoon would actually see.<br />
First, we stored the normalized <strong>DiffuseLightDirection</strong> in <strong>lightDir</strong>.  Anything but a unit vector will give us weird results. We follow that  by normalizing the <em>normal </em>of the current pixel (Remember we're  normalize in the pixel shader because we want the interpolated normal of  the pixel. If normalized in the vertex shader, it would still  interpolate is it went to the pixel shader and therefore wouldn't be a  normalized vector anymore.) and storing that in <strong>norm</strong>. Next, we  calculate the <strong>halfAngle </strong>by adding together <strong>lightDir </strong>and <strong>CameraView </strong>(vector from the camera to the box). If you look at the picture,  you can see <strong>halfAngle </strong>directly bisects the angle from <strong>lightDir</strong> to<strong> </strong><strong>CameraView</strong>. Okay. Now all our variables are defined.  Now we can finally calculate our specular component.<br />
If you  remember, in the diffuse component we took the dot product of the normal  and the light direction to find out how much light actually hit the  surface. The specular light uses the same concept, except it now also  depends on the position of the camera (or "eye"). Instead of taking the  dot product between the normal and the light direction, we're going to  take the dot product of normal and the half angle. Why? Physics break!</p>
<blockquote>
<h3>A Brief Digression on Optics</h3>
<p>If you really want to understand how shaders  work, a very thorough understanding of optical properties is an  absolute must. Knowing the real-world phenomena we are trying to  simulate and how they physically work gives you a much better idea of  what we're trying to accomplish. I'll give you a little optics  background so you can understand what's going on in this tutorial.  However, I would highly suggest looking at more sources to further your  understanding.<br />
<em><strong>When light strikes a surface at a certain  vector, called the angle of incidence, it bounces off the surface,  reflecting across the normal of the point on the surface it hits.</strong></em> If the normals of a surface are all pointing in the <em>same </em>direction  (think mirror), the reflected light will all be reflected at the same  angle, so the light rays will still be parallel to eachother. This keeps  the image intact when it gets reflected back to your eye. If the  normals of the surface are all pointing in <em>different </em>directions  (think rough boulder), the reflected light is scattered in all different  directions, some light rays even bouncing back towards the light  source. The rays are <span style="text-decoration: underline;">no longer parallel to eachother</span>, so  different parts of the image are shooting off in all different  directions. This is why you don't see a reflected image in a boulder  like you do in a mirror. The shinnier the surface, the less scattering  and the closer you get to a mirror. I've provided a picture below that  demonstrates what I've just explained.</p>
<div><img src="http://digitseven.com/images/optics.png" alt="" /></div>
<p>The <strong>Shinniness </strong>variable helps  us define how smooth or rough a surface is. The rougher the surface, the  smaller the value. You'll see why in a minute. In the cartoon diagram  with the red box, the light travels from the sun, reflects across the  normal of the pixel and makes it to our eye. However, our eye isn't  exactly at the receiving end of the reflected ray; it's slightly above.  Yet in the 3D rendering we can see it still gets light. Why is this?  Because in that picture, the box isn't perfectly smooth, so we can  assume that there will be some scattering to the eye. It's really all  just guess and check if you think about it. Comforting isn't it?</p></blockquote>
<p>Now that we know some laws of optics, we can start where we left off. We  take the dot product of <strong>norm </strong>and <strong>halfAngle </strong>to see how  much direct light the eye will get. The larger the angle between the  two, the further away our eye is from the "predicted" path of the  reflected rays; therefore we will get less specular/reflective light. We  take the result of that and take it to the <strong>Shinniness </strong>power. If  you think about an exponential graph, the higher the exponent, the  quicker a number below 1 goes to zero. This is a way to simulate how  rough surfaces can scatter light more than smooth surfaces. A smaller  power, a rougher surface, more scattering. A higher power, a smoother  surface, less scattering. We multiply that result by <strong>SpecularColor </strong>and  <strong>SpecularIntensity </strong>like our other light types and voila! We now  have specular light. We just add the specular component to our final sum  at the end of the pixel shader and our model should now be specularly  lit.</p>
<p>If you want to know how to set the variables from XNA,  be sure to check out the <strong>Diffuse </strong>or <strong>Ambient </strong>light  tutorial.</p>
<h2>Conclusion</h2>
<p>Specular lighting is a step towards the more complicated aspects of  programming shaders. By adding it into your 3D application, you can see  it definitely adds a lot of realism. Once you start getting into  advanced lighting techniques, you really need to know your stuff:  vectors, optics, matrix multiplication, etc. etc. I'll put up some  resources on optics on the <a href="http://digitseven.com/links.aspx">Links</a> page if you want to learn a bit more. There's already some links for  matrices. As these tutorials get more complex, I'll probably be making a  lot more mistakes so be sure to send me an email at <strong>dan@digitseven.com</strong>.  And of course, if you have any questions about anything I've covered,  please email me and I'll do my best to help you out. Also, make sure you <a href="http://digitseven.com/default.aspx">sign up for the newsletter</a> on the home page to stay updated with my latest posts Enjoy!</p>
<p><strong>Download the source: <a href="http://digitseven.com/Documents/SpecularLight.zip">SpecularLighting.zip</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/09/article-shaders-specular-lighting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Article: Shaders &#8211; Diffuse Lighting</title>
		<link>http://www.sgtconker.com/2010/09/article-shaders-diffuse-lighting-2/</link>
		<comments>http://www.sgtconker.com/2010/09/article-shaders-diffuse-lighting-2/#comments</comments>
		<pubDate>Tue, 21 Sep 2010 19:04:11 +0000</pubDate>
		<dc:creator>Absolutely Fine Tutorial Contest</dc:creator>
				<category><![CDATA[2010 Contest Entries]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Contest]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Absolutely Fine Tutorial Contest]]></category>
		<category><![CDATA[Article]]></category>
		<category><![CDATA[Daniel Greenheck]]></category>
		<category><![CDATA[digitseven]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1785</guid>
		<description><![CDATA[by Daniel Greenheck
What should I be familiar with before I go through this tutorial?
- The content discussed in the introduction and ambient shader tutorials.
- A simple knowledge of vectors, matrices and dot products (click on the links for Wiki articles) will REALLY help you understand  some of the light calculations going on. although I'll [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by <a href="http://digitseven.com">Daniel Greenheck</a></h4>
<p>What should I be familiar with before I go through this tutorial?<br />
- The content discussed in the <a href="http://www.sgtconker.com/2010/09/article-shaders-introduction/">introduction</a> and <a href="http://www.sgtconker.com/2010/09/article-shaders-ambient-lighting/">ambient</a> shader tutorials.<br />
- A simple knowledge of vectors, <a href="http://en.wikipedia.org/wiki/Matrix_%28mathematics%29">matrices</a> and <a href="http://en.wikipedia.org/wiki/Dot_product" target="_blank">dot products</a> (click on the links for Wiki articles) will REALLY help you understand  some of the light calculations going on. although I'll do my best to  explain those topics in this tutorial.</p>
<h2>What is Diffuse Lighting?</h2>
<p>Diffuse lighting can best be described as directional light. There are three types of diffuse lighting: directional, point light and spotlight. I have a picture of each below in respective order. Directional light comes down at the same angle no matter where you are standing; the light has no position, just direction. Point light is like a light bulb, it all emanates  from a single point equally in all directions. A spot light is like an oriented floodlight or a flashlight. Diffuse light also creates shadows, but that's a much more advanced topic we won't dive in to until later.</p>
<p><img class="alignnone" title="http://digitseven.com/images/directional.jpg" src="http://digitseven.com/images/directional.jpg" alt="" width="479" height="362" /></p>
<p><span id="more-1785"></span></p>
<p><img class="alignnone" title="Point" src="http://digitseven.com/images/point.jpg" alt="" width="500" height="333" /></p>
<p><img class="alignnone" title="spot" src="http://digitseven.com/images/point_spotlight_dynamic.jpg" alt="" width="640" height="480" /></p>
<h2>The Diffuse Shader</h2>
<p>Once again, here's the entire diffuse shader for you to look at. You can probably notice it has all the same elements of the ambient shader, along with a few extra parts.</p>
<pre class="brush: csharp; title: ;">
// Matrices
float4x4 World;
float4x4 View;
float4x4 Projection;

// Ambient Variables
float4 AmbientColor;
float AmbientIntensity;

// Diffuse Variables
float4 DiffuseColor;
float DiffuseIntensity;
float3 DiffuseLightDirection;

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 Normal : TEXCOORD1;
};

VertexShaderOutput VertexShader( VertexShaderInput input )
{
    VertexShaderOutput output;

    // Transform our position by the matricies
    float4 worldPosition = mul( input.Position, World );
    float4 viewPosition = mul( worldPosition, View );
    output.Position = mul( viewPosition, Projection );

    // Transform the normal from model space to world space
    output.Normal = normalize( mul( input.Normal, World ) );

    return output;
}

float4 PixelShader( VertexShaderOutput input ) : COLOR0
{
    // Determine the diffuse component by finding the angle between the light and the normal.
    // The smaller the angle between the normal and the light direction, the closer the dot
    // product will be to 1, and the brighter the pixel will be.
    float4 diffuse = dot( DiffuseLightDirection, input.Normal ) * DiffuseIntensity * DiffuseColor;

    // Calculate our ambient component
    float4 ambient = AmbientIntensity * AmbientColor;

    // Return the total light component as a combination of the diffuse and ambient.
    // Saturate it to keep the color between 0 and 1.
    return saturate( diffuse + ambient );
}

technique Diffuse
{
    pass Pass0
    {
        VertexShader = compile vs_1_1 VertexShader();
        // We upgraded to pixel shader 2.0 so we can used more advanced commands
        PixelShader = compile ps_2_0 PixelShader();
    }
}
</pre>
<p>So what's the same?</p>
<ol>
<li><span style="text-decoration: underline;">Variables</span>: All three      matrices (<strong>World</strong>, <strong>View</strong>, <strong>Projection</strong>), <strong>AmbientColor </strong>and      <strong>AmbientIntensity </strong>are back.</li>
<li><span style="text-decoration: underline;">Structures</span>: Position      makes an appearance once again.</li>
<li><span style="text-decoration: underline;">Vertex Shader</span>: The      vertices are still transformed using the <strong>World</strong>, <strong>View </strong>and  <strong>Projection </strong>matrices.</li>
<li><span style="text-decoration: underline;">Pixel  Shader</span>: The      ambient lighting component is still calculated.</li>
</ol>
<p>Now, let's take a  look at what's new.</p>
<ol>
<li>We have three new variables for our diffuse light: <strong>DiffuseColor</strong>,  <strong>DiffuseIntensity</strong>, <strong>DiffuseLightDirection</strong>. Direction is the  only new concept here.</li>
<li>A <em>float3 </em>called  Normal has been added to both the input and output structures for the  vertex shader.</li>
<li>In our vertex shader, we do  a transformation on the normal from <em>VertexShaderInput </em>and pass  that on to the pixel shader.</li>
<li>In our pixel  shader, we calculate the diffuse component of the light.</li>
<li>We changed the pixel shader version from 1_1 to 2_0 to allow  us to do more advanced features in the pixel shader (i.e. normalize a  vector).</li>
</ol>
<p>Let's take a look at each of those  additions in detail. First we need to take a little side step to talk  about normals...</p>
<h2>Juat a Normal Kind of Light</h2>
<p>When we did ambient light, it didn't  matter where the light was coming from or how the light hit a certain  face. We just assumed each face was hit by the same amount of light,  giving the effect of everything being the same color. With diffuse  lighting, however, we now have a light coming in at a specific  direction, so each face isn't going to get hit by the same amount of  light. Imagine placing a small object by your desk lamp (and if you  don't have one of those, imagine that too). You'd notice right away that  the side facing the light gets more light than the side facing away,  resulting in a brighter color. This is because the <strong>normal</strong> of the  face aimed towards the light is pointed more directly at the light  source. A normal is a pretty simple concept. Here's a 3D model with the  normals shown as red rays coming out of the faces.<br />
<img src="http://digitseven.com/images/boxnormals.jpg" alt="" /><br />
Each  of those rays is <em>orthogonal </em>to the face it comes out of (fancy  term for perpendicular.) Our model uses normals like these and compares  it with the light direction to see how much light the face should get.  If a normal is pointing either perpendicular or completely away from the  light source, there's not a chance even a ray of light will directly  hit the face. We'll get back to normals later. All you  need to know is <span style="text-decoration: underline;">normals are used for calculating how much light a  face should get.</span> Let's get back into our shader code now.</p>
<h2>Variable Declaration</h2>
<pre class="brush: csharp; title: ;">
// Matrices
float4x4 World;
float4x4 View;
float4x4 Projection;

// Ambient Variables
float4 AmbientColor;
float AmbientIntensity;

// Diffuse Variables
float4 DiffuseColor;
float DiffuseIntensity;
float3 DiffuseLightDirection;
</pre>
<p>The matrices and ambient variables  we covered in the last tutorial haven't changed at all, so I won't go  over those. However, we've added three new variables for our  diffuse lighting. The first two- <strong>DiffuseColor </strong>and <strong>DiffuseIntensity</strong>-  are analogs to <strong>AmbientColor </strong>and <strong>AmbientIntensity</strong>. They  control the color and brightness our diffuse light, respectively. Our  next variable, however, is brand spankin' new: <strong>DiffuseLightDirection</strong>.  From the name you can probably construe it defines the direction our  light will shine down at. And that's exactly what it is. There's one  peculiarity you should know about defining light direction though:<em><strong> </strong>the light shines down in the opposite direction you define it.</em> So if you want your light to shine straight down on your object,  naturally you would think to assign float3(0, -1, 0) to your <strong>DiffuseLightDirection</strong>.  But nope, that will cause the light to shine straight up.</p>
<h2>The Vertex Shader Input and Output Structures</h2>
<pre class="brush: csharp; title: ;">
struct VertexShaderInput    // Input for the vertex shader
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;
};

struct VertexShaderOutput    // Output for the vertex shader
{
    float4 Position : POSITION0;
    float3 Normal : TEXCOORD0;
};
</pre>
<p>Since we now know that we need normals from  our model for our shader, I went ahead and added a <em>float3 </em>(equivalent  of a Vector3 in XNA) to our <em>VertexShaderInput </em>structure to  represent the normal for the vertex. One problem you probably noticed is  that the normals I described above were for <strong>surfaces</strong> not <strong>vertices.</strong> Well this isn't a problem at all! To find the vertex normal, you simply  average the normals of all the faces that that use that vertex. I  described the actual code below when I get into the XNA part, so don't  worry. The normal parameter was also added to the <em>VertexShaderOutput</em>,  but we're going to be doing some work on it in the vertex shader so it  isn't the same as the normal we pass in through <em>VertexShaderInput</em>.  We'll look at the vertex shader next to see how we're actually  modifying the normal.</p>
<h2>Vertex Shader</h2>
<pre class="brush: csharp; title: ;">
VertexShaderOutput VertexShader( VertexShaderInput input )
{
    // Initialize our vertex shader output
    VertexShaderOutput output;

    // Transform our position by the matricies
    float4 worldPosition = mul( input.Position, World );
    float4 viewPosition = mul( worldPosition, View );
    output.Position = mul( viewPosition, Projection );

    // Transform the normal from model space to world space
    output.Normal = normalize( mul( input.Normal, World ) );

    return output;
}
</pre>
<p>You'll notice there's a lot of familiar code here already. The transformations  on the vertex position are exactly the same as they were in the ambient  shader. The only new line we added takes the input normal, transforms  it by the <strong>World </strong>matrix and normalizes the result. Let's break  that down... Inside the parentheses, we take the vertex normal we passed  in and multiply it with the <strong>World </strong>matrix. We do this for the  same reason we multiply our position with the <strong>World </strong>matrix: our  normal is defined in <em>model space</em> (relative to the model origin)  and we need to get it into <em>world space</em>, since that's where our  light direction is defined. Our model could be rotated and translated  and all sorts of stuff- which is all taken care of in the <strong>World </strong>matrix-  so we need to apply those transformations to the normal too. After we  get our normal in <em>world space</em>, we normalize it. Don't confuse  "normal" with "normalize" either. A "normal" defines which way a face or  vertex is pointing. "Normalizing" a vector makes it <em>unit length</em>,  or have a length of 1. Unit vectors are used to specify direction  without magnitude. Two normal vectors pointing in the same direction  with different magnitudes would somehow mean that one face is pointing  in a direction with more force than the other, which really makes no  sense at all. After calculating the output normal, we now have  everything we need to calculate diffuse light in our pixel shader.</p>
<h2>Pixel Shader</h2>
<pre class="brush: csharp; title: ;">
float4 PixelShader( VertexShaderOutput input ) : COLOR0
{
    // Normalize our light direction
    float3 normLightDirection = normalize( DiffuseLightDirection );

    // Determine the diffuse component by finding the angle between the light and the normal.
    // The smaller the angle between the normal and the light direction, the closer the dot
    // product will be to 1, and the brighter the pixel will be.
    float4 diffuse = dot( normLightDirection, input.Normal ) * DiffuseIntensity * DiffuseColor;

    // Calculate our ambient component like we did with the ambient shader.
    float4 ambient = AmbientIntensity * AmbientColor;

    // Return the total light component as a combination of the diffuse and ambient.
    // Saturate it to keep the color within 1.
    return saturate( diffuse + ambient );
}
</pre>
<p>We've finally made it to the last step of the shader! Once again, we've copied over a lot of stuff  from the ambient lighting pixel shader. In fact, we've copied all of it.  We've also added two things: normalizing our light direction at the  pixel-shader-level forThe only thing we've added is the calculation of  our diffuse component. Since we want per-pixel diffuse lighting, we've  put the calculation for the diffuse component in the pixel shader. To  calculate how much light the pixel gets from our diffuse light, we take  the dot product of the diffuse light direction with the transformed  vertex normal and multiply it with <strong>DiffuseIntensity </strong>and <strong>DiffuseColor</strong>.  Wow, that's a mouthful! First, you might be wondering what a dot  product is. Read this little section first. If you already know what a  dot product is, feel free to skip it.</p>
<blockquote>
<h3>A brief digression on the Dot Product</h3>
<p>The <strong>dot  product</strong> is something we haven't come across yet. What it does is  compare the angle between two vectors and returns a <em>float.</em> If the  vectors are both <em>unit length</em>, you'll get a result between -1 and  1. If they aren't, you'll get a wildly varying value that you really  can't do anything with. A dot product of 20 could mean a billion things.  Now you know why we normalized our light direction and vertex normal.</p>
<p>If Vector1 and Vector2...</p>
<blockquote><p>- are pointing in the exact  same direction then <strong>dot( V1, V2 ) = 1</strong><br />
- are perpendicular to  each other then<strong> dot( V1, V2 ) = 0</strong><br />
- are pointing in exact  opposite directions then <strong>dot( V1, V2 ) = -1</strong></p></blockquote>
</blockquote>
<blockquote><p>Those are just the exact cases. Everything in between will vary  depending on where it's pointing. The closer they are to pointing in the  same direction, the closer to 1. The opposite holds with pointing in  the opposite direction. If you're confused, check out the Links section  on the navigation bar for more information on dot products.</p></blockquote>
<p>Now that we have dot products out of the way, we can finally apply it to our diffuse  calculation. When our normal is pointing in the opposite direction of  the <strong>DiffuseLightDirection </strong>(remember that our light direction is  defined opposite of what you think it should be), our dot product will  be 1. Multiply that with <strong>DiffuseColor </strong>and <strong>DiffuseIntensity </strong>and  we'll end up with our maximum possible value for the diffuse component.  If the normal and light direction are perpendicular, the dot product  will be zero and we'll get no light. This makes sense since a side  perpendicular to a light source isn't going to get hit by light rays.<br />
Phew! Now that we finally have our diffuse and ambient components, all  we do is add them together. Before we return the sum however, we want to  put apply the saturate() function. This caps any component of our pixel  color between 0 and 1. If the dot product was negative, we'd have  negative color values which would throw an error.</p>
<h2>Adding Normals to Our Models</h2>
<p>The biggest change we need on the XNA side is adding our normal  data to ou vertices. For the ambient shader I used the VertexPositionColor  structure for storing my vertices. Unfortunately, this doesn't have  anywhere to store normal information. So I've upgraded the vertices on  my box to VertexPositionNormalTexture,  leaving the texture coordinates blank for now. Remember that shaders  don't care if there's extra information there; they just take what they  need and move on. I'll be covering a texture shader within the next few  tutorials so let's go ahead and use that structure. Now, for calculating  the normals. This can vary greatly depending on what you have: a list  of verticies, a list of indexed vertices, a model. I won't cover the  first case and normally any model you find will already have the normals  in it, so I'm going to give a brief overview of indexed vertices  defined in the <strong>TriangleList </strong>format. I apologize if you defined  your verticies in a different fashion, but don't get too upset. A quick  check over at the <a href="http://forums.xna.com/forums/">XNA Forums</a> or a Google search should help you out with that. Here's a step-by-step  guide on how to calculate normals for indexed vertices which use the <strong>TriangleList </strong>method.</p>
<ol>
<li>Create you vertices and indices as you  normally would.</li>
<li>Loop through your indices <strong>three </strong>at a  time. Since your indicies are defined using a <strong>TriangleList</strong>, you  know each three consecutive indices represent a triangle in your model.</li>
<li>Get  the three vertices from I1, I2 and I3 and name them V1, V2 and V3.</li>
<li>Create  two Vector3's: <strong>VectorA </strong>= <em>V2.Position - V1.Position</em> and <strong>VectorB </strong>= <em>V3.Position - V1.Position.</em></li>
<li>Take the cross product  of <strong>VectorB </strong>with <strong>VectorA </strong>(order matters) and normalize that  result. This will give you your face normal.</li>
<li>Now go back and  add that face normal to V1.Normal, V2.Normal and V3.Normal.</li>
<li>Repeat  for every three indices and voila, each vertex now has it's vertex  normal.</li>
</ol>
<p>By adding the face normal to each vertex that  made up the face, we've effectively averaged together all the face  normals for each vertex, which is the definition of a vertex normal.Once you get that implemented, our models should now  have all the necessary information to draw them with diffuse light.</p>
<h2>Setting Our Shader Variables</h2>
<pre class="brush: csharp; title: ;">

    // Set the parameters of the shader

    diffuseEffect.Parameters[ &quot;World&quot; ].SetValue( Matrix.CreateRotationY( (float)gameTime.TotalGameTime.TotalSeconds )  );

    diffuseEffect.Parameters[ &quot;View&quot; ].SetValue( viewMatrix );

    diffuseEffect.Parameters[ &quot;Projection&quot; ].SetValue( projectionMatrix );

    diffuseEffect.Parameters[ &quot;AmbientColor&quot; ].SetValue( new Vector4( 1, 1, 1, 1 ) );

    diffuseEffect.Parameters[ &quot;AmbientIntensity&quot; ].SetValue( .3f );

    diffuseEffect.Parameters[ &quot;DiffuseColor&quot; ].SetValue( new Vector4( 0, 1, 0, 1 ) );

    diffuseEffect.Parameters[ &quot;DiffuseIntensity&quot; ].SetValue( .8f );
    diffuseEffect.Parameters[ &quot;DiffuseLightDirection&quot; ].SetValue( new Vector3( .7f, 1f, -.8f ) );
</pre>
<p>Nothing has really changed here. We've just tacked on three more SetValue()'s for our three diffuse  variables. Set your <strong>DiffuseColor, </strong><strong>DiffuseIntensity </strong>and <strong>DiffuseLightDirection</strong> (we normalize it here to avoid the calculation in the shader. And  remember, it's opposite of the direction the light shines at!) and  you're almost good to go!</p>
<h2>Drawing Vertices With Our Diffuse Effect</h2>
<p>Once again, not much has changed here. Make sure you change your  VertexDeclaration and DrawUserPrimitives call to VertexPositionNormalTexture so the graphics  card knows we've added normal data. If you skip that, you'll probably  end up with nothing but black blob. Everything should be ready to go  now... so go ahead, hit F5 and watch that cube spin in it's shaded,  rainbowed glory! You should get something similar to this video:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/s1nqiD0nDCY?fs=1&amp;hl=en_US" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="480" height="385" src="http://www.youtube.com/v/s1nqiD0nDCY?fs=1&amp;hl=en_US" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h2>Conclusion</h2>
<p>So there we go, another shader down.  By now I hope you're starting to get a feel for how these shaders work  and what goes into them. You should start seeing a pattern as you go  along: vertex shaders transforming data, pixel shaders using the  transformed data to calculate colors. Every vertex shader and pixel  shader you come across is going to work like that for the most part.  I'll be covering specular light in the next tutorial, which will give  you a nice shiny effect on your objects. I might have to ditch the cube  for a sphere... I don't think he'll take kindly to that news... Anyway,  best of luck to you in your programming! If you happen to catch any  errors or need any clarifications, be sure to send me an email at <strong>dan@digitseven.com</strong>,  I'd be more than happy to help. Make sure to <a href="http://digitseven.com/default.aspx">sign up for the newsletter</a> to stay updated with my latest tutorials and code uploads!</p>
<p><strong>Download the source: <a href="http://digitseven.com/Documents/DiffuseLight.zip">DiffuseLighting.zip</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/09/article-shaders-diffuse-lighting-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Article: Arbitrarily Shaped Secondary 2D Viewports</title>
		<link>http://www.sgtconker.com/2010/09/article-arbitrarily-shaped-secondary-2d-viewports/</link>
		<comments>http://www.sgtconker.com/2010/09/article-arbitrarily-shaped-secondary-2d-viewports/#comments</comments>
		<pubDate>Mon, 13 Sep 2010 20:42:24 +0000</pubDate>
		<dc:creator>Absolutely Fine Tutorial Contest</dc:creator>
				<category><![CDATA[2010 Contest Entries]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Contest]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Shaders]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Absolutely Fine Tutorial Contest]]></category>
		<category><![CDATA[Arbitrary Shaped]]></category>
		<category><![CDATA[Harry Trautmann]]></category>
		<category><![CDATA[Inkscape]]></category>
		<category><![CDATA[Secondary Viewports]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=1760</guid>
		<description><![CDATA[by Harry Trautmann

This tutorial shows a technique to implement a secondary 2D viewport which has a shape that does not need to be rectangular, but can be customized by the programmer. Even moving sprite shapes are possible. Utilized code techniques: secondary rendertarget (of XNA Game Studio 3.1) and an alphamap by a pixelshader (PS 2.0).
This [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by Harry Trautmann</h4>
<p style="text-align: center;"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/ScreenSecondViewport.png"><img class="aligncenter" title="Arbitrary Shaped Viewports" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/ScreenSecondViewport.png" alt="" width="479" height="361" /></a></p>
<p>This tutorial shows a technique to implement a secondary 2D viewport which has a shape that does not need to be rectangular, but can be customized by the programmer. Even moving sprite shapes are possible. Utilized code techniques: secondary rendertarget (of XNA Game Studio 3.1) and an alphamap by a pixelshader (PS 2.0).</p>
<p>This tutorial is for beginner to intermediate level programmers. At least you should know the oo basics and know the nitty-gritty about the XNA framework. Also, basic shader programming is explained somewhere else (e. g. here: <a href="http://www.sgtconker.com/2009/11/crash-course-in-hlsl/">http://www.sgtconker.com/2009/11/crash-course-in-hlsl/</a>)</p>
<h2><span id="more-1760"></span>What is a Secondary Viewport?</h2>
<p>Normally games let the player watch one scene at a given time. In a jump'n'run game the player's avatar is somewhere in the middle of the screen, and the game always displays a cut-out part of the world depending on the avatar´s position. This cut-out part is the primary (main) viewport.</p>
<p>A secondary viewport would be some kind of a window inside of the main viewport that shows either the same scene by another view or a completely different scene.</p>
<h2>What could a secondary viewport be useful for?</h2>
<p>I can think of at least 5 applications:</p>
<ol>
<li>Surveillance cameras: the player can behold faraway places while the screen mainly displays some totally other scene. E. g. this could be useful in multiplayer games where one could be able to place such cameras inside of the enemy´s base for spy actions.</li>
<li>Dimension gates: through the door you see a scene of some fantasy land that gets real when you enter.</li>
<li>Microscope: works by applying some magnifying factor.</li>
<li>Mirrors: as the player´s avatar walks by, the secondary viewport shows it horizontally mirrorred and somewhat displaced.</li>
<li>Special FX: do you remember the intro of some old James Bond movie, where some scenes where shown inside of the shape of a dancer? In principle this can be done with a secondary viewport, when the alpha map is a moving sprite.</li>
</ol>
<p>These are just some suggestions for where secondary viewports are useful. Nevertheless this tutorial concentrates on showing how the shape of the viewport can be free from a rectangular nature.</p>
<h2>Principle</h2>
<p>The secondary viewport consists of a secondary <em>RenderTarget</em> object and an alphamap. The alphamap consists of a texture which defines its shape and a pixelshader that modulates pixels by the alphamap texture. The drawing process of the secondary viewport follows these steps:</p>
<ol>
<li>The spectated scene gets rendered onto the secondary rendertarget.</li>
<li>A texture of the secondary rendertarget is kept. It will be drawn later on.</li>
<li>Then the main scene is drawn onto the videocard´s own rendertarget (main rendertarget).</li>
<li> Finally the texture of the spectated scene is drawn onto the main rendertarget by applying the alphamap as a shader effect.</li>
</ol>
<h2>Create the Background Scene</h2>
<p>First we need a scene that we can spectate by the secondary viewport. Understanding the scene implementation itself is not required to comprehend the rest of the tutorial. So to avoid too much confusion we keep the scene code rather simple and encapsulate it mostly into the Star class. Since it is really easy to understand we just skim over some hotspots. Here (<a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/SecondaryViewport-SceneOnly.zip">SecondaryViewport-SceneOnly.zip</a>) is the code that produces the plain scene. In case you are unsure, if some code belongs to the scene or to the viewport implementation, you can compare this project and the project we will build for the viewport to see the differences.</p>
<h3>Idea</h3>
<div class="wp-caption aligncenter" style="width: 492px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/ScreenSceneOnly.png"><img class=" " title="Scene Only" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/ScreenSceneOnly.png" alt="" width="482" height="361" /></a><p class="wp-caption-text">Figure 1: Only the Scene - no secondary viewport yet</p></div>
<p>A field of randomly sized, randomly moving sprite stars will do the trick. The <em>Game1</em> object will have an array of <em>Star</em> objects that will get updated and drawn. Figure 1 shows the resulting scene that yet misses the secondary viewport.</p>
<h3>The <em>Star</em> class</h3>
<p>To keep the scene code as far as possible separated from the code that actually implements the secondary viewport, we have the <em>Star</em> class. A <em>Star</em> object keeps track of its position, rotation, moving speed, moving direction and has a unique (also random) color. Each <em>Star</em> object can only move inside of a rectangular area that gets set in the constructor.</p>
<p>Only few things are notably about this class. First all objects share the same texture graphic. The first created <em>Star</em> object loads the static <em>Texture2D</em> member during its constructor call. The same thing applies to the <em>Random</em> value generator.</p>
<pre class="brush: csharp; title: ;">
protected static Texture2D _texStar = null;
protected static Random _randGen = null;
</pre>
<p>These static objects get created in the constructor call of the first Star object.</p>
<pre class="brush: csharp; title: ;">
if (_texStar == null)
        _texStar = game.Content.Load&lt;Texture2D&gt;(&quot;textures//star&quot;);
if (_randGen == null)
        _randGen = new Random();
</pre>
<p>Then in Update, the movement direction of a Star object gets reversed when the position collides with one of the initially set movement boundaries.</p>
<pre class="brush: csharp; title: ;">
if (_pos.X &lt;= _bounds.X || _pos.X &gt;= _bounds.X + _bounds.Width) {
        _move.X *= -1.0f;
        _pos.X = MathHelper.Clamp(_pos.X, _bounds.X, _bounds.X + _bounds.Width);
}// fi
if (_pos.Y &lt;= _bounds.Y || _pos.Y &gt;= _bounds.Y + _bounds.Height) {
        _move.Y *= -1.0f;
        _pos.Y = MathHelper.Clamp(_pos.Y, _bounds.Y, _bounds.Y + _bounds.Height);
}// fi
</pre>
<p>Last, also in Update, the rotation gets clipped to some value inside of the range 0 to 2 pi.</p>
<pre class="brush: csharp; title: ;">
_rot += (float) (_rotInc * gametime.ElapsedGameTime.TotalMilliseconds);
if (_rot &lt; 0.0f) {
        _rot = MathHelper.TwoPi + (_rot % MathHelper.TwoPi);
} else {
        _rot = _rot % MathHelper.TwoPi;
}// fi
</pre>
<h2>Creating the Scene</h2>
<p>The Game1 object has an array of Star objects.</p>
<pre class="brush: csharp; title: ;">
protected Star[] _stars;
</pre>
<p>It gets created inside of the LoadContent method. Each Star´s movement gets limited to the main window´s ClientBounds rectangle.</p>
<pre class="brush: csharp; title: ;">
Rectangle rcWin = new Rectangle(0, 0, Window.ClientBounds.Width,
                                             Window.ClientBounds.Height);
_stars = new Star[_StarCount];
for (int i = 0; i &lt; _StarCount; i++)
        _stars[i] = new Star(this, rcWin);
</pre>
<p>Note, that in LoadContent a font gets loaded ("Arial" should be available on any Windows system). It´s used for drawing some coordinates on the screen so the user can orientate easier.</p>
<pre class="brush: csharp; title: ;">
_font = Content.Load&lt;SpriteFont&gt;(&quot;fonts\\Arial10&quot;);
</pre>
<h2>Updating the Scene</h2>
<p>Straightforward. For each Star its Update method gets called.</p>
<pre class="brush: csharp; title: ;">
for (int i = 0; i &lt; _StarCount; i++)
        _stars[i].Update(gameTime);
</pre>
<h2>Drawing the Scene</h2>
<p>Each Star has its Draw method called and now and then we draw some coordinate values.</p>
<pre class="brush: csharp; title: ;">
GraphicsDevice.Clear(Color.White);
_spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate,
        SaveStateMode.None);
        // The stars know how to draw by themselves.
        for (int i = 0; i &lt; _StarCount; i++)
                _stars[i].Draw(_spriteBatch);
        // For easier orientation draw some coordinate values.
        float chunksW = Window.ClientBounds.Width / 5;
        float chunksH = Window.ClientBounds.Height / 5;
        for (int x=0; x &lt; 5; x++)
                for (int y = 0; y &lt; 5; y++) {
                        _spriteBatch.DrawString(_font, x.ToString() + &quot;/&quot; + y.ToString(),
                                new Vector2(chunksW * (0.5f + x), chunksH * (0.5f + y)), Color.Black);
                }// for
        _spriteBatch.End();
</pre>
<h2>Create the Alphamap Texture</h2>
<p>Now that we have a scene, let´s create the texture for the alphamap. This texture defines the actual shape of the secondary viewport. The texture gets interpreted as a grayscale image. The darker a pixel is in this image, the more transparent the pixel of an image onto which the alphamap gets applied will be. This means a pixel of the alphamap that is completely black, will modulate an incoming pixel to be completely transparent and a pixel of the alphamap that is completely white will modulate an incoming pixel to be completely opaque (i. e. retaining its original color value).<br />
Notes:</p>
<ul>
<li>The alpha value of a pixel in the alphamap texture gets ignored completely. Of course you could use the alpha value of the pixels instead of grayscale, but its easier to see the shape of the map in the image editor by using grayscale.</li>
<li> You can use any image editor to create the alphamap. Personally I favour <a href="http://www.inkscape.org/">Inkscape</a> which can be used by a GNU license. If you never worked with a vector graphics editor before you may find the following tips useful when creating the alphamap texture.</li>
</ul>
<h3>1. Show the layers</h3>
<p>Select the main menu option "Layer / Layers..." (figure 2). It displays the "Layers" window where you can see the layers of the current Inkscape image. Think of a layer being like a transparent sheet on an overhead light projector. The "plus" button creates a new layer, the "minus" button deletes the selected layer. By clicking on the "eye" symbol everything drawn on that layer gets hidden or shown. Create a new layer and rename it by clicking on its name e. g. as "background".</p>
<div class="wp-caption aligncenter" style="width: 438px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/inkscape_1_1_layers.png"><img title="Inkscape Layers" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/inkscape_1_1_layers.png" alt="" width="428" height="412" /></a><p class="wp-caption-text">Figure 2: Main menu option &quot;Layer / Layers...&quot; in Inkscape.</p></div>
<h3>2. Create a black background</h3>
<p>Select the "background" layer. Then click on the black color at the bottom of the Inkscape window to have black assigned as the color that fills any shape you will draw. On the left side of the Inkscape window you find the "Toolbox" toolbar. Click the "square" button ("Create rectangles and squares") and draw a square onto the image. The results should look similar to figure 3.</p>
<div class="wp-caption alignnone" style="width: 476px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_2_1.png"><img class=" " title="Black BAckground" src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_2_1.png" alt="" width="466" height="502" /></a><p class="wp-caption-text">Figure 3: Step 2, drawing a rectangular background for the alphamap.</p></div>
<h3>3. Create a sphere</h3>
<p>Create another layer (e. g. called "alphashape"). Make sure, that layer is selected. Select the white color at the bottom of the Inkscape window. Then click the "circle" tool ("Create circles, ellipses, and arcs") in the toolbox and draw a spherical object inside of the black background rectangle. The results should look similar to figure 4.</p>
<p><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_3_1.png"><img class="alignnone" title="Figure 4: Step 3, rectangular background with sphere on it." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_3_1.png" alt="Figure 4: Step 3, rectangular background with sphere on it." width="464" height="502" /></a></p>
<h3>4. Apply a gradient to the sphere shape</h3>
<p>First show the "Fill and Stroke" colors by selecting the main menu option "Object / Fill and Stroke...". Above the "Layers" window another window named "Fill and Stroke" should be displayed now. Make sure the "Fill" tab and inside of the drawing area the white sphere are selected (You may need to click the 'select' tool ("Select and transform objects") in the toolbox first to select the sphere). Now click the 'gradient' tool ("Create and edit gradients") in the toolbox. Then press the left mouse button in the center of the white sphere and drag the cursor towards its edge. The results should look similar to figure 5. Since we want to have most of our alphamap opaque, we have to modify the gradient. Press the "Edit..." button ("Edit the stops of the gradient") of the 'tool controls' bar (figure 6). In the appearing "Gradient editor" window press the "Add stop" button. Behold new control points appearing on the gradient lines (figure 7). Close the gradient editor window and click on one of these new points to have it selected in the "Fill and Stroke" window. Now set the "Opacity, %" gauge to "100.0" (figure 8). Finally press the left mouse button onto the new gradient point and drag it towards the edge of the spherical object (figure 9).</p>
<div class="wp-caption alignnone" style="width: 476px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_1.png"><img class=" " title="Figure 5: Step 4a, a simple gradient applied to the sphere." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_1.png" alt="" width="466" height="501" /></a><p class="wp-caption-text">Figure 5: Step 4a, a simple gradient applied to the sphere.</p></div>
<div class="wp-caption alignnone" style="width: 593px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_2.png"><img title="Figure 6: Step 4b, the gradient edit button." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_2.png" alt="" width="583" height="83" /></a><p class="wp-caption-text">Figure 6: Step 4b, the gradient edit button.</p></div>
<div class="wp-caption alignnone" style="width: 432px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_3.png"><img title="Figure 7: Step 4c, the new points on the gradient lines." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_3.png" alt="" width="422" height="258" /></a><p class="wp-caption-text">Figure 7: Step 4c, the new points on the gradient lines.</p></div>
<div class="wp-caption alignnone" style="width: 700px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_4.png"><img title="Figure 8: Step 4d, modify new gradient step." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_4.png" alt="" width="690" height="247" /></a><p class="wp-caption-text">Figure 8: Step 4d, modify new gradient step.</p></div>
<div class="wp-caption alignnone" style="width: 396px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_5.png"><img title="Figure 9: Step 4e, repositioning gradient step points." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_5.png" alt="" width="386" height="252" /></a><p class="wp-caption-text">Figure 9: Step 4e, repositioning gradient step points.</p></div>
<h3>5. Export the image as PNG</h3>
<p>Select the black background rectangle we created in the second step. Select the main menu entry "File / Document Properties...". Inside of the appearing "Document Properties" window in the "Custom size" box press the little plus button and then the "Resize page to drawing or selection" (figure 10). Close the "Document Properties" window. Select the main menu option "File / Export Bitmap...". Press the "Page" button to have the size of the exported bitmap fixed to the page size. Press the "Browse..." button and enter a filename and storage location for the bitmap file. Also do not forget to select PNG as file format and have the filename have a ".png" suffix. Press "Save" to close the file selection dialog. Finally press the "Export" button to actually have the image exported.</p>
<div class="wp-caption alignnone" style="width: 588px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_6.png"><img class=" " title="Figure 10: the button to have the page resized is a little bit hidden." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/Inkscape_4_6.png" alt="" width="578" height="389" /></a><p class="wp-caption-text">Figure 10: the button to have the page resized is a little bit hidden.</p></div>
<h3>6. Import the texture into the Visual C# Project</h3>
<p>Back in the MS VC# IDE do not forget to add the alphamap image to the "Content" in the project explorer.</p>
<h2>Implement the Viewport</h2>
<p>Note that in this sample the main scene and the spectated scene are the same. Therefore it is not necessary to render the scene twice. Instead the main scene gets rendered once onto the texture of the secondary rendertarget, and then this texture gets rendered twice. Otherwise, if there would be many complex objects in the scene (though obviously not the case in this tutorial), the need to render the scene itself twice could become a serious performance hit.</p>
<p>The idea in this sample is to draw a magnified cut-out of the main scene as the secondary viewport. With the mouse you can steer the cut-out rectangle.</p>
<h3>New Members of Game1</h3>
<p>The Game1 class gets some new members that are necessary for the secondary viewport.<br />
The actual secondary rendertarget. Note that this is a memory space inside of the graphics card memory.</p>
<pre class="brush: csharp; title: ;">
protected RenderTarget2D _rendtarg2;
</pre>
<p>This Texture2D object that will hold the alphamap texture that we created in the last step:</p>
<pre class="brush: csharp; title: ;">
protected Texture2D _texAlphamap;
</pre>
<p>The member that will hold the compiled pixel shader effect:</p>
<pre class="brush: csharp; title: ;">
protected Effect _fxAlphamap;
</pre>
<p>A Rectangle member will hold the rectangular cut-out of the main scene that defines the source of the secondary viewport:</p>
<pre class="brush: csharp; title: ;">
protected Rectangle _rcSrc;
</pre>
<h3>Changes to the Game1 class</h3>
<p>In <em><strong>Initialize</strong> </em>the cursor gets shown to make tracing the cut-out source easier for the user.</p>
<pre class="brush: csharp; title: ;">
IsMouseVisible = true;
</pre>
<p>In <strong><em>LoadContent</em></strong> we need to load the alphamap texture and shader effect.</p>
<pre class="brush: csharp; title: ;">
_texAlphamap = Content.Load&lt;Texture2D&gt;(&quot;textures\\alphamap&quot;);
_fxAlphamap = Content.Load&lt;Effect&gt;(&quot;shaders\\AlphaMapping&quot;);
</pre>
<p>Also in <em>LoadContent </em>the secondary rendertarget is created here by calling CreateRenderTarget:</p>
<pre class="brush: csharp; title: ;">
CreateRenderTarget();
[/csharp

Note that the secondary rendertarget always needs to be of the current size of the &lt;em&gt;GraphicsDevice&lt;/em&gt;´s backbuffer. Therefore, if you implement some screen resolution / fullscreen mode switches you will also have to call &lt;em&gt;CreateRenderTarget &lt;/em&gt;again to fit the secondary rendertarget to the new size of the backbuffer.

In &lt;strong&gt;&lt;em&gt;Update &lt;/em&gt;&lt;/strong&gt;the positional change of the mouse cursor defines the source position of the secondary viewport. The &lt;em&gt;MathHelper.Clamp&lt;/em&gt; calls make sure that the source rectangle does cover space outside of the main window.
[csharp]
        // Keep track of where the mouse is and update the viewport source.
        MouseState mouse = Mouse.GetState();
        float factor = 0.33f;
        int w = (int)Math.Round(Window.ClientBounds.Width * factor);
        int h = (int)Math.Round(Window.ClientBounds.Height * factor);
        int w2 = (int)Math.Round(Window.ClientBounds.Width * factor * 0.5f);
        int h2 = (int)Math.Round(Window.ClientBounds.Height * factor * 0.5f);
        _rcSrc = new Rectangle(mouse.X - w2, mouse.Y - h2, w, h);
        _rcSrc.X = (int)MathHelper.Clamp(_rcSrc.X, 0, Window.ClientBounds.Width – w);
        _rcSrc.Y = (int)MathHelper.Clamp(_rcSrc.Y, 0, Window.ClientBounds.Height - h);
</pre>
<p>The most and most important changes to <em>Game1 </em>appear in <em><strong>Draw</strong></em>.</p>
<p>As stated above, the main scene only gets rendered once – and not onto the main rendertarget, but onto the secondary rendertarget (<em>_rendtarg2</em>). So before drawing our scene we need to set the secondary rendertarget as the current one. In order to be able to reset the main rendertarget to be the current one, we have to keep a reference in the local variable <em>rtTemp</em>.</p>
<pre class="brush: csharp; title: ;">
RenderTarget2D rtTemp = null;
rtTemp = (RenderTarget2D)_graphics.GraphicsDevice.GetRenderTarget(0);
_graphics.GraphicsDevice.SetRenderTarget(0, _rendtarg2);
</pre>
<p>After regularly drawing the scene, we keep a <em>Texture2D </em>of what we just drew. But since <em>GetTexture </em>is only possible on a <em>RenderTarget2D </em>that is not the current one, we first have to reset to the original rendertarget.</p>
<pre class="brush: csharp; title: ;">
_graphics.GraphicsDevice.SetRenderTarget(0, rtTemp);
texTemp = _rendtarg2.GetTexture();
</pre>
<p>Now we´re ready to assemble the graphical output as it is to be seen by the user. So we clear the (original) rendertarget to black (just to be safe) and paint the <em>Texture2D </em>that we just rendered on it. Note that the texture gets tinted into some light blue so that it´s easier to distinguish it from the secondary viewport graphics.</p>
<pre class="brush: csharp; title: ;">
GraphicsDevice.Clear(Color.Black);
_spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate,
                              SaveStateMode.None);
_spriteBatch.Draw(texTemp,
                         Vector2.Zero, null,
                         new Color(225, 245, 255, 255),
                         0.0f, Vector2.Zero,
                         Vector2.One,
                         SpriteEffects.None, 0.0f);
_spriteBatch.End();
</pre>
<p>Finally the secondary viewport will be rendered atop of the main scene. Note that the drawing code is outsourced into a method of its own: <em>Draw2ndViewport</em>. Why? Admitted, in this sample it does not make much sense. But assuming you write a program build atop of this sample, which needs to have more than one secondary viewport (e. g. an ingame monitor wall with say 4 monitors showing what goes on elsewhere), it is easier to have a method dedicated to draw a single secondary viewport.<br />
So what does Draw2ndViewport need as input?</p>
<ol>
<li> rcOut defines the output rectangle of the secondary viewport, i. e. Its size and where it gets drawn at. We calculate this Rectangle just before the call of Draw2ndView.</li>
<li> rcSrc defines the rectangular cut-out source of the secondary viewport. Remember that we calculated this Rectangle in Update.</li>
<li> rcScreen is a Rectangle holding the size of the screen onto which the secondary viewport is to be drawn. It gets used for calculating mapping factors from incoming image space to output space. Here it is set to the main window´s extends. We calculate this Rectangle just before the call of Draw2ndView.</li>
<li> tex is the reference to the texture to be drawn. If drawing cut-out´s of a scene, then a single texture reference can be reused for this parameter.</li>
</ol>
<p>So the Draw2ndView call looks like this:</p>
<pre class="brush: csharp; title: ;">
Rectangle outrect = new Rectangle(
                     (int)Math.Round(Window.ClientBounds.Width * 0.25f),
                     0,
                     (int)Math.Round(Window.ClientBounds.Width * 0.5f),
                     (int)Math.Round(Window.ClientBounds.Height * 0.5f));
Rectangle screenrect = new Rectangle(0, 0,
                     Window.ClientBounds.Width, Window.ClientBounds.Height);
Draw2ndViewport(outrect, _rcSrc, screenrect, texTemp);
</pre>
<p>For now treat <em>Draw2ndViewport </em>as a black box. After explaining the pixelshader its workings are easier to understand, and we come back to it.</p>
<h3>How the Pixelshader works</h3>
<p>The alphamap pixelshader ("AlphaMapping.fx") has three parameter members that need to be set outside, before the effect can be applied.</p>
<ol>
<li><em>float4 srcRect</em>: these 4 <em>float</em> values defines the source area inside of the incoming image. The values can be between <em>0.0f</em> and <em>1.0f</em> as usual for texel coordinates.</li>
<li><em>float4 destRect</em>: these 4 float values define the destination area inside of the shaded image. These values too are to be inside of <em>0.0f</em> and <em>1.0f</em>.</li>
<li><em>texture AlphaMap</em>: is to hold the reference to the alphamap texture.</li>
</ol>
<p>The shader has two samplers, the first for the incoming image and the other for the alphamap.</p>
<pre class="brush: csharp; title: ;">
sampler IncomingSampler;
sampler AlphaMapSampler = sampler_state {
        Texture = &lt;AlphaMap&gt;;
        MinFilter = Linear;
        MagFilter = Linear;
        MipFilter = Linear;
        AddressU  = Mirror;
        AddressV  = Mirror;
};
</pre>
<p>The actual work of modulating pixels of the incoming image by corresponding pixels of the alphamap texture happens inside of the <em>PS_AlphaMap</em> function.</p>
<pre class="brush: csharp; title: ;">
float4 PS_AlphaMap(float2 texCoord: TEXCOORD0) : COLOR
</pre>
<p>The function receives texture coordinate inside of the texture image to be processed. Again these two float values are between<em> 0.0f</em> and <em>1.0f</em>. It returns four <em>float </em>values defining the color that the pixel at that coordinate position is to have.<br />
First we get whatever color is at the original position of the incoming texture image. <em>colOut </em>will hold the color value that <em>PS_AlphaMap</em> returns.</p>
<pre class="brush: csharp; title: ;">
float4 colOut = tex2D(IncomingSampler, texCoord);
</pre>
<p>Then we check, if the incoming coordinate is inside of the output area to be modulated by the alphamap.</p>
<pre class="brush: csharp; title: ;">
if ((texCoord[0] &gt;= destRect[0]) &amp;&amp; (texCoord[0] &lt; (destRect[0] + destRect[2])) &amp;&amp;
      (texCoord[1] &gt;= destRect[1]) &amp;&amp; (texCoord[1] &lt; (destRect[1] + destRect[3]))){
</pre>
<p>If it is not inside of the destination area, the read color is assured to stay like it is. Therefore the a value is set to opaque.</p>
<pre class="brush: csharp; title: ;">
} else {
      colOut.a = 0.0f;
}// fi
</pre>
<p>But if the coordinate is inside of the destination area, its color value gets modulated by the alphamap before returning it. Then it is necessary to respect that the source of the output color could be some other pixel than the one we currently have the coordinates for in <em>texCoord</em>. Depending on the size of the incoming texture image and the size of the destination rectangle the new source coordinate gets calculated and stored in <em>newSrc</em>. Remember that all these values are relative share values between <em>0.0f</em> and <em>1.0f</em>. Afterwards <em>colOut </em>is filled with the color of the pixel at this new coordinates in the incoming texture image.</p>
<pre class="brush: csharp; title: ;">
float2 newSrc;
float shareX = (texCoord[0] - destRect[0]) / destRect[2];
float shareY = (texCoord[1] - destRect[1]) / destRect[3];
newSrc[0] = srcRect[0] + shareX * srcRect[2];
newSrc[1] = srcRect[1] + shareY * srcRect[3];
colOut = tex2D(IncomingSampler, newSrc);
</pre>
<p>Now we have to read the color value of the alphamap that corresponds to the incoming coordinates relative to the destination rectangle size.</p>
<pre class="brush: csharp; title: ;">
float2 mappedTC;
float4 colAlphaMap;
mappedTC[0] = ((texCoord[0] - destRect[0]) / destRect[2]);
mappedTC[1] = ((texCoord[1] - destRect[1]) / destRect[3]);
colAlphaMap = tex2D(AlphaMapSampler, mappedTC);
</pre>
<p>Finally the current incoming color value gets modulated by the alphamap color value. This is done by simply multiplying the a parts of the colors and leaving the r, g, b of the incoming value as they are. Note that since the alphamap texture should be grayscale the r, g, b values should be the same for a single pixel in the alphamap texture. Therefore in the pixelshader only the r value of a pixel´s color is processed, r and b get ignored.</p>
<pre class="brush: csharp; title: ;">
colOut.a = colOut.a * colAlphaMap.r;
</pre>
<p>Finally in the technique <em>AlphaMapShader </em>the <em>Pass0 </em>defines that the <em>AlphaMapSampler </em>and the <em>PS_AlphaMap</em> functions are to be used.</p>
<pre class="brush: csharp; title: ;">
technique AlphaMapShader {
        pass Pass0 {
                AlphaBlendEnable = True;
                SrcBlend = SrcAlpha;
                DestBlend = InvSrcAlpha;
                Sampler[0] = (AlphaMapSampler);
                PixelShader = compile ps_2_0 PS_AlphaMap();
        }// Pass0
} // AlphaMapShader
</pre>
<h3>Draw 2nd Viewport</h3>
<p>So back in <em>Game1 </em>we only need to explain what <em>Draw2ndView </em>does. Actually it only sets  the parameters of the pixelshader and draws the given texture image by applying the alphamap shader – all wrapped in the <em>SpriteBatch</em>´s <em>Begin </em>and <em>End </em>methods.<br />
Setting the AlphaMap shader parameter:</p>
<pre class="brush: csharp; title: ;">
_fxAlphamap.Parameters[&quot;AlphaMap&quot;].SetValue(_texAlphamap);
</pre>
<p>For setting the srcRect shader parameter we first need to have the source rectangle mapped to share values between 0.0f and 1.0f relative to the texture´s size.</p>
<pre class="brush: csharp; title: ;">
float[] srcRect = new float[4] {
        (float) rcSrc.X / (float)tex.Width,
        (float) rcSrc.Y / (float)tex.Height,
        (float) rcSrc.Width / (float)tex.Width,
        (float) rcSrc.Height / (float)tex.Height
};
_fxAlphamap.Parameters[&quot;srcRect&quot;].SetValue(srcRect);
</pre>
<p>Setting the <em>destRect </em>shader parameter also needs mapping the values to share values, but this time relative to the output screen´s size.</p>
<pre class="brush: csharp; title: ;">
float[] destRect = new float[4];
destRect[0] = (rcOut.X + rcScreen.X) / (float)rcScreen.Width;
destRect[1] = (rcOut.Y + rcScreen.Y) / (float)rcScreen.Height;
destRect[2] = (rcOut.Width) / (float)rcScreen.Width;
destRect[3] = (rcOut.Height) / (float)rcScreen.Height;
_fxAlphamap.Parameters[&quot;destRect&quot;].SetValue(destRect);
</pre>
<p>After setting these parameters drawing the given texture by applying the shader is straightforward just like with other shaders.</p>
<pre class="brush: csharp; title: ;">
_fxAlphamap.CurrentTechnique = _fxAlphamap.Techniques[&quot;AlphaMapShader&quot;];
_fxAlphamap.Begin();
_fxAlphamap.CurrentTechnique.Passes[0].Begin();
        _spriteBatch.Draw(tex,
                        new Vector2(),
                        null,
                        Color.White,
                        0.0f, Vector2.Zero,
                        Vector2.One,
                        SpriteEffects.None, 0.0f);
_fxAlphamap.CurrentTechnique.Passes[0].End();
_fxAlphamap.End();
</pre>
<p>Figure 11 shows what the result looks like.</p>
<div class="wp-caption alignnone" style="width: 489px"><a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/ScreenSecondViewport.png"><img class=" " title="Figure 11: the scene with a magnifying secondary viewport." src="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/ScreenSecondViewport.png" alt="" width="479" height="361" /></a><p class="wp-caption-text">Figure 11: the scene with a magnifying secondary viewport.</p></div>
<p>Find the sample code here: <a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/SecondaryViewport.zip">SecondaryViewport.zip</a>.</p>
<h2>Ideas for Extensions</h2>
<p>Homework for you!</p>
<ul>
<li>The mousewheel could steer the zoom. The zoom is controlled by the size of the rectangle defining the cut-out of the main scene.</li>
<li>Of course the spherical form of the alphamap is only a suggestion. It´s easy to reproduce, therefore it seemed appropriate for this tutorial. Actually having a completely customized alphamap shape is what this tutorial is about – go ahead and change it to whatever form you like!</li>
<li>As mentioned in the intro, the alphamap could also be a moving 2D sprite. I extended the sample of this tutorial to reflect, how this could be established. You can get the code here: <a href="http://www.sgtconker.com/wp-content/uploads/contest/2010/harry/SecondaryViewport-MovingSprite.zip">SecondaryViewport-MovingSprite.zip</a>.</li>
</ul>
<h2>License</h2>
<p>This text and any referred code is licensed under a "Creative Commons Attribution 3.0 Unported" license, which can be read here: <a href="http://creativecommons.org/licenses/by/3.0/">http://creativecommons.org/licenses/by/3.0/</a></p>
<p>The author of all text, any code and any assets found in this tutorial likes to be referred by Harry Trautmann, <a href="http://codemachinery.net">http://codemachinery.net</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/09/article-arbitrarily-shaped-secondary-2d-viewports/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

