<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/c4f.Louis-Ingenthron/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/c4f.Louis-Ingenthron/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/c4f.Louis-Ingenthron/Posts</link>
    <language>en</language>
    <pubDate>Thu, 23 May 2013 10:21:50 GMT</pubDate>
    <lastBuildDate>Thu, 23 May 2013 10:21:50 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>2</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>XNA Effects – ASCII Art in 3D</title>
      <description><![CDATA[
<p>In this article, I'll demonstrate how to create a post-processing effect to turn 3D renders into ASCII Art.
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="157">
<p><strong>Louis Ingenthron <br>
FV Productions</strong></p>
</td>
<td valign="top" width="481">
<p><b>Code It:</b> <a href="http://xnaascii.codeplex.com/">http://xnaascii.codeplex.com/</a>
<br>
<b>Run It:</b> <a href="http://xnaascii.codeplex.com/">http://xnaascii.codeplex.com/</a></p>
<p><b>Difficulty:</b> Intermediate <br>
<b>Time Required:</b> 1-4 hours <br>
<b>Cost:</b> FREE <br>
<b>Software Needed: </b><a href="http://www.microsoft.com/express/download/">Visual C# Express</a>,
<a href="http://msdn.microsoft.com/en-us/netframework/default.aspx">.NET Framework 3.5</a>,
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=80782277-D584-42D2-8024-893FCD9D3E82&amp;displaylang=en">
XNA Game Studio 3.1</a> <br>
<b>Hardware:</b> Windows PC</p>
</td>
</tr>
</tbody>
</table>
</p>
<h3>Introduction</h3>
<p>Back in November of 2009, I was met with an interesting challenge. Those of you who frequent the XNA Community Forums have probably heard of Nick Gravelyn. He was an XNA MVP, and now he works for the XNA team. He started a little contest called xna7day,
 which was designed to challenge developers to make a game in 7 days using a pre-defined theme.</p>
<p>The theme in November was “Text Based” and its rule was that you were only allowed to use text in the visuals of your game. I saw some of the cool stuff other developers were working on, including one that looked like it had text characters that could walk
 and talk, like people. But my mind immediately went to a different solution: I wanted to make a game that was fully 3D (effectively breaking the rule of rendering text), but then post-process the render into ASCII art, so it would look like it was text.</p>
<p>In this article, I'm going to show you how to do just that:</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image002_2.jpg"><img title="clip_image002" border="0" alt="clip_image002" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image002_thumb.jpg" width="240" height="180"></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image004_2.jpg"><img title="clip_image004" border="0" alt="clip_image004" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image004_thumb.jpg" width="240" height="180"></a></p>
<h4>Setup</h4>
<p>Alright, let's dive right in. Open up the base project. It should compile and run as is. It's a simple, if ugly, first-person shooter. Play through the first level. Go ahead, I'll wait. Bonus points to anyone who recognizes the level design!</p>
<p>Okay, got a playthrough? Let's start! I separated this into three projects so the ASCII stuff can be extracted into other games. We'll be doing most of our work in the ASCII_Renderer project, so let's open that up and add a new class to the Source\ascii
 folder called “Renderer.” I use the namespace “ASCII3D” for all files in this project, so get rid of the extra folder sub-namespaces. Add these using statements, too:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">using</span> Microsoft.Xna.Framework;
<span class="kwrd">using</span> Microsoft.Xna.Framework.Content;
<span class="kwrd">using</span> Microsoft.Xna.Framework.Graphics; </pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>This is going to be a post-processing effect, so we'll try to make it portable. Add the following empty function declarations:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> Renderer(ContentManager content, <span class="kwrd">int</span> xRes, <span class="kwrd">int</span> yRes)
{ }

<span class="kwrd">public</span> <span class="kwrd">void</span> StartScene()
{ }

<span class="kwrd">public</span> <span class="kwrd">void</span> EndScene()
{ }</pre>
<p>The constructor takes three arguments: The ContentManager, which we will use to load in our font and post-processing shader, and the resolution variables, which will basically tell us how many lines of text to draw and how many characters in each line. Since
 we have these prototyped, we'll make our only edits to the ASCIIFPS project in the Source\Game1.cs file. But first, we need to define and initialize a new Renderer object. Add a new class variable:<b></b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// This is what handles the ASCII conversion</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="kwrd">private</span> Renderer renderer; </pre>
<p>And at the end of the LoadContent function:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// and initialize our ASCII renderer</span>
<span class="rem">// the variables we pass make each character</span>
<span class="rem">// appx 10x14 which seems to be the smallest</span>
<span class="rem">// readable size</span>
renderer = <span class="kwrd">new</span> Renderer(Content, Global.ScreenWidth/10,Global.ScreenHeight/14);</pre>
<p></p>
<p>Finally, call the BeginScene and EndScene functions. Modify Game1's Draw function to look like this:<b></b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Draw(GameTime gameTime)
{
    <span class="rem">// notice we only wrap StartScene and</span>
    <span class="rem">// EndScene if we are UsingASCII</span>
    <span class="kwrd">if</span> (UsingASCII)
        renderer.StartScene();

    currentState.Draw(gameTime);

    <span class="kwrd">if</span> (UsingASCII)
        renderer.EndScene();

    <span class="kwrd">base</span>.Draw(gameTime);
}</pre>
<p>The Boolean variable UsingASCII is defined for us. It defaults to false and can be toggled any time in-game by pressing the [M] key. If you want to default it to true for testing purposes, just change its value in Game1's Initialize function. At this point,
 the Renderer is all hooked up, so changes will go right in.</p>
<p>I skimmed over the other classes earlier in the article, but I need to touch on a few of them. Almost everything in GlobalModules is fairly standard utility stuff. We'll be using it, so you might want to glance at the Global class. The ASCIIFPS has the FPS
 engine in it and is almost entirely irrelevant to this article, except that it offers a fun test-bed for our effect. Feel free to go through the code, but I'll warn you: I wrote it for a 7-day contest, so some of it looks like gibberish and is only incidentally
 functional. Finally, we have the ASCII_Renderer project. This already has two files in it: BitmapFontGenerator and Letter. The latter are for generating a bitmap font map that we'll use in a bit.</p>
<p>The functionality isn't specific to this article, since any artist could easily make this. But I'm no artist, which is why I had the computer do it for me. Basically, BitmapFontGenerator has a static function that will take a texture of letters (see the
 Content project in ASCII_Renderer), trim them, sort them by how much they fill their space, and print them into a new Texture for our functions. Feel free to read through the code for this process; I commented it pretty well.</p>
<h4>Post-Processing Basics</h4>
<p>We need to cover the basics of post-processing before we start coding the next part. When post-processing a scene, you first render the entire scene off-screen on a RenderTarget. Then, you can apply any effects you want to the resolved texture before putting
 it on the screen. That's it. Here's how in XNA:<b></b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Renderer
{
    <span class="kwrd">private</span> RenderTarget2D SrcImage;

    <span class="kwrd">public</span> Renderer(ContentManager content, <span class="kwrd">int</span> xRes, <span class="kwrd">int</span> yRes)
    {
        SrcImage = <span class="kwrd">new</span> RenderTarget2D(Global.Graphics, 
            xRes, yRes, 1, SurfaceFormat.Color);
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> StartScene()
    {
        Global.Graphics.SetRenderTarget(0, SrcImage);
        Global.Graphics.Clear(Color.Black);
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> EndScene()
    {
        Global.Graphics.SetRenderTarget(0, <span class="kwrd">null</span>);
        Global.Graphics.Clear(Color.Black);

        <span class="rem">// TODO: draw the texture from the RenderTarget</span>
    }
}</pre>
<p>We create the RenderTarget2D we need in the constructor. Notice that the size of the RenderTarget is the same as the number of ASCII characters we plan to draw on screen. I'll explain that in the next section. In the StartScene function, we set the RenderTarget
 on the device so that all draw calls will actually draw to it. Then we clear the buffer, because RenderTargets' content from frame to frame is undefined. In EndScene, the RenderTarget is set to null, which is DirectX's way of saying “use the screen's framebuffer.”
 Now we need to actually draw the rendered image. XNA requires shaders for all draw calls, even if they're veiled by BasicEffect and SpriteBatch. We need to create a very simple shader to draw the texture to screen. Create a new Effect file in ASCII_Renderer's
 Content project and name it TextEffect. We'll start it out with this:<b></b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">texture2D sourceTex;
sampler2D SourceTextureSampler = sampler_state
{
    Texture = &lt;sourceTex&gt;;
    MinFilter = point;
    MagFilter = point;
    MipFilter = point;
    AddressU = wrap;
    AddressV = wrap;
};

<span class="kwrd">struct</span> VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TexCoords : TEXCOORD0;
};

<span class="kwrd">struct</span> VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoords : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
    
    output.Position = input.Position;
    output.TexCoords = input.TexCoords;

    <span class="kwrd">return</span> output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float4 sourceColor = tex2D(SourceTextureSampler,input.TexCoords);
    
    <span class="kwrd">return</span> sourceColor;
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}</pre>
<p>There are a couple things I want to note about the base shader. First, notice that we use point filtering. I'll explain why in the next section, but it's important to see where we did it. Next, notice that we took out all the default transformation matrices.
 We're going to be drawing a single full screen quad, so we can just pass in the coordinates in screen-space—no processing required. Now we need to make a few changes to the Renderer class to use this Effect and draw the rendered game. First, we need to add
 some new class variables:<b></b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">private</span> Effect effect;

<span class="kwrd">private</span> VertexPositionTexture[] verts;
<span class="kwrd">private</span> VertexDeclaration vd;</pre>
<p></p>
<p>The vertices are going to be for a simple quad that takes up the whole screen. They should be initialized in the LoadContent function like this:<b>
</b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">effect = content.Load&lt;Effect&gt;(<span class="str">&quot;TextEffect&quot;</span>);

verts = <span class="kwrd">new</span> VertexPositionTexture[6];
verts[0] = <span class="kwrd">new</span> VertexPositionTexture(
    <span class="kwrd">new</span> Vector3(-1, -1, 0), <span class="kwrd">new</span> Vector2(0, 1));
verts[1] = <span class="kwrd">new</span> VertexPositionTexture(
    <span class="kwrd">new</span> Vector3(1, -1, 0), <span class="kwrd">new</span> Vector2(1, 1));
verts[2] = <span class="kwrd">new</span> VertexPositionTexture(
    <span class="kwrd">new</span> Vector3(-1, 1, 0), <span class="kwrd">new</span> Vector2(0, 0));
verts[3] = verts[1];
verts[4] = verts[2];
verts[5] = <span class="kwrd">new</span> VertexPositionTexture(
    <span class="kwrd">new</span> Vector3(1, 1, 0), <span class="kwrd">new</span> Vector2(1, 0));

vd = <span class="kwrd">new</span> VertexDeclaration(
    Global.Graphics, VertexPositionTexture.VertexElements);</pre>
<p></p>
<p>And finally, we add our draw code to the Draw function:<b></b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">effect.Begin();
effect.CurrentTechnique.Passes[0].Begin();

effect.Parameters[<span class="str">&quot;sourceTex&quot;</span>].SetValue(SrcImage.GetTexture());
effect.CommitChanges();
Global.Graphics.RenderState.CullMode = CullMode.None;

Global.Graphics.VertexDeclaration = vd;
Global.Graphics.DrawUserPrimitives&lt;VertexPositionTexture&gt;
     (PrimitiveType.TriangleList, verts, 0, 2);

effect.CurrentTechnique.Passes[0].End();
effect.End();</pre>
<p></p>
<p>We set the texture we got from the RenderTarget, turn off culling (what would be culled in this geometry?), and draw it. Run the project. You should be able to toggle a difference in-game with the [M] key.<b></b></p>
<p><b><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image006_2.jpg"><img title="clip_image006" border="0" alt="clip_image006" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image006_thumb.jpg" width="322" height="242"></a></b></p>
<h3>Drawing Some Text</h3>
<p>“Okay,” you say, “it runs at a lower resolution with the [M] key. So what?” Remember what we set the resolution to in the RenderTarget? Yes, every pixel on this low-resolution version will be a character in the final image. How do we turn these big pixels
 into characters? First we need to define a texture bitmap font. Let's add a Texture2D class variable to Renderer and a const int for the BitmapFontGenerator:
</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> Texture2D text; 
<span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> NUM_SLOTS = 256;</pre>
<p></p>
<p>Then we'll use the BitmapFontGenerator to construct this texture:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">text = BitmapFontGenerator.GenerateTextTexture(content, NUM_SLOTS);</pre>
<p></p>
<p>Okay, that's all for now. Let's go back to the TextEffect.fx. We need to add a few variables:<b></b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float2 dstLetterSize;

<span class="kwrd">int</span> numLetters;

texture2D textTex;
sampler2D TextTextureSampler = sampler_state
{
    Texture = &lt;textTex&gt;;
    MinFilter = point;
    MagFilter = point;
    MipFilter = point;
    AddressU = wrap;
    AddressV = wrap;
};</pre>
<p>The variable “dstLetterSize” will tell us how big the letters on the screen are. The “numLetters” variable will tell us how many letters are in the font texture. And then there's the font texture itself. Here's how we draw actual characters in the Pixel
 Shader:<b></b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
     float4 sourceColor = tex2D(SourceTextureSampler,input.TexCoords);
    
     float2 texCoords = float2(
          input.TexCoords.x-((<span class="kwrd">int</span>)
               (input.TexCoords.x/dstLetterSize.x)*dstLetterSize.x),
          input.TexCoords.y-((<span class="kwrd">int</span>)
               (input.TexCoords.y/dstLetterSize.y)*dstLetterSize.y));
     texCoords /= dstLetterSize;
     texCoords.x /= numLetters;
    
     float4 letterColor = tex2D(TextTextureSampler,texCoords);
    
     <span class="kwrd">return</span> letterColor;
}</pre>
<p></p>
<p>We've already seen the source color line. The next line will get the offset into the letter in letter size by subtracting the rounded-down (or integer-casted) texture coordinates scaled down. The line after that scales it back up to a 0-1 range. So now we
 have the new variable texCoords that is filled with the texture coordinates of the letter in 0-1 terms. We divide the x by numLetters because our texture is one long horizontal line of letters. Finally we get the letter color with these new texture coordinates.
 This letter color is grayscale, and when multiplied by the source color, we've assured that each letter is rendered in its own slot with the color from the original 3D render. The last thing we have to do is set those effect variables we defined from Renderer's
 EndScene function. Where we once just set the source texture, we now set these:<b></b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">effect.Parameters[<span class="str">&quot;dstLetterSize&quot;</span>].SetValue(
     <span class="kwrd">new</span> Vector2(1.0f/(<span class="kwrd">float</span>)SrcImage.Width, 1.0f/(<span class="kwrd">float</span>)SrcImage.Height));
effect.Parameters[<span class="str">&quot;numLetters&quot;</span>].SetValue(NUM_SLOTS);
effect.Parameters[<span class="str">&quot;sourceTex&quot;</span>].SetValue(SrcImage.GetTexture());
effect.Parameters[<span class="str">&quot;textTex&quot;</span>].SetValue(text);
effect.CommitChanges();</pre>
<p></p>
<p>Most of these are self explanatory, but the dstLetterSize is a bit more complicated. To get the size of the letter in the 0-1 texture space, you take the total size (0 to 1) divided by the number of letters in that axis which, in our case, is the RenderTarget
 size.<b></b></p>
<p><b></b></p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image008_2.jpg"><img title="clip_image008" border="0" alt="clip_image008" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image008_thumb.jpg" width="322" height="242"></a></p>
<h3>Wheel of Fortune</h3>
<p>‘M's aren't very interesting. In traditional ASCII art, the whole point is that you use characters that take more space or less space to handle shading. Let's add this code after the multiplication of the texCoords.x:<b></b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">float</span> lum = (sourceColor.r&#43;sourceColor.g&#43;sourceColor.b)/3.0; 
<span class="kwrd">float</span> val = max(fullValueColor.r,
     max(fullValueColor.g,fullValueColor.b));
    
<span class="kwrd">int</span> ind = ((numLetters-1)-
     max(0,min((numLetters-1),(<span class="kwrd">int</span>)(lum*numLetters))));

texCoords.x &#43;= ind*(1.0/numLetters);</pre>
<p></p>
<p><b></b></p>
<p>The first line gets the luminosity of the source color. The next gets the value. The next line gets the letter index from the luminosity. Subtracting it from (numLetters-1) reverses the index, because we want luminosity=1 to equate to index=0, because that
 has the letter that takes up the most space. Run the game. You'll see it now shows value, but it's still pretty hard to tell what's on the screen:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image010_2.jpg"><img title="clip_image010" border="0" alt="clip_image010" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image010_thumb.jpg" width="322" height="242"></a></p>
<p>The last thing we can do is colorize it. You could just multiply it by the source color and get something like this…</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image012_2.jpg"><img title="clip_image012" border="0" alt="clip_image012" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image012_thumb.jpg" width="322" height="242"></a></p>
<p>…but everything looks too dark because the source color still has its value. Plus we're already practically multiplying it by choosing the letter. So we need to get the full value color first:</p>
<p><b></b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float4 fullValueColor = sourceColor * (1.0/val);</pre>
<p></p>
<p>We just multiply the original color by the inverse of the value. And then multiply that fullValueColor by the letter color in the return:<b></b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">return</span> fullValueColor * letterColor;</pre>
<p></p>
<p>That should produce a nice result:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image014_2.jpg"><img title="clip_image014" border="0" alt="clip_image014" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9994745/clip_image014_thumb.jpg" width="407" height="305"></a><b></b></p>
<h3>Conclusion</h3>
<p>And there it is! We have a real-time 3D render transformed into ASCII art. It's difficult to see and it's not very useful, but it's sure neat, eh? Why not add it as an unlockable easter egg in your next XBL Indie Game? I'm looking forward to seeing how people
 use this effect! If you use it, please <a href="mailto:louisingenthron@fvproductions.org">
send me an email</a> with a screenshot!</p>
<h3>About The Author</h3>
<p>Louis Ingenthron is a Game Developer in Orlando, FL. He works on commercial Console and PC titles, but runs his own Indie Games company, FV Productions, on the side. He is best known for his open source XNA rhythm game Unsigned and specializes in real-time
 Graphics programming. He has been working with XNA since the 2.0 Beta and with .NET C# for just as long. He is also familiar with several other development languages, such as C, C&#43;&#43;, and Java. Occasionally, he can even be found doing web development and Flash.
 Louis also writes for MSDN's Coding4Fun website, contributing articles on a monthly basis.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Louis-Ingenthron/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:bfa52c016c3640c7a8699e7600c99302">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/XNA-Effects--ASCII-Art-in-3D</comments>
      <itunes:summary>
In this article, I&#39;ll demonstrate how to create a post-processing effect to turn 3D renders into ASCII Art.




Louis Ingenthron 
FV Productions 


Code It: http://xnaascii.codeplex.com/

Run It: http://xnaascii.codeplex.com/ 
Difficulty: Intermediate 
Time Required: 1-4 hours 
Cost: FREE 
Software Needed: Visual C# Express,
.NET Framework 3.5,

XNA Game Studio 3.1 
Hardware: Windows PC 




 
Introduction
Back in November of 2009, I was met with an interesting challenge. Those of you who frequent the XNA Community Forums have probably heard of Nick Gravelyn. He was an XNA MVP, and now he works for the XNA team. He started a little contest called xna7day,
 which was designed to challenge developers to make a game in 7 days using a pre-defined theme. 
The theme in November was “Text Based” and its rule was that you were only allowed to use text in the visuals of your game. I saw some of the cool stuff other developers were working on, including one that looked like it had text characters that could walk
 and talk, like people. But my mind immediately went to a different solution: I wanted to make a game that was fully 3D (effectively breaking the rule of rendering text), but then post-process the render into ASCII art, so it would look like it was text. 
In this article, I&#39;m going to show you how to do just that: 
 
Setup
Alright, let&#39;s dive right in. Open up the base project. It should compile and run as is. It&#39;s a simple, if ugly, first-person shooter. Play through the first level. Go ahead, I&#39;ll wait. Bonus points to anyone who recognizes the level design! 
Okay, got a playthrough? Let&#39;s start! I separated this into three projects so the ASCII stuff can be extracted into other games. We&#39;ll be doing most of our work in the ASCII_Renderer project, so let&#39;s open that up and add a new class to the Source\ascii
 folder called “Renderer.” I use the namespace “ASCII3D” for all files in this project, so get rid of the extra folder sub-namespaces. Add these using statemen</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/XNA-Effects--ASCII-Art-in-3D</link>
      <pubDate>Wed, 14 Apr 2010 13:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/XNA-Effects--ASCII-Art-in-3D</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9994745_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9994745_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Louis Ingenthron </dc:creator>
      <itunes:author>Louis Ingenthron </itunes:author>
      <slash:comments>11</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/XNA-Effects--ASCII-Art-in-3D/RSS</wfw:commentRss>
      <category>Gaming</category>
      <category>Media</category>
      <category>XNA</category>
      <category>Mash Up</category>
      <category>XNA framework</category>
    </item>
  <item>
      <title>Making an Ocean with XNA</title>
      <description><![CDATA[
<p>In this article, Louis Ingenthron will show you how to create a simple endless ocean for an XNA C# game.</p>
<h3>Introduction</h3>
<p>Every game needs boundaries, such as a window separating the player from space or a brick wall. When I first played Splinter Cell: Double Agent's Cozumel Cruise level, I spent a good 5 minutes just looking at the ocean that kept the player in bounds. It
 was a beautiful sunset with waves moving across the ocean endlessly outward... and it was neat.</p>
<p>When I was tasked with creating a great ocean for a Caribbean pirate game, I knew it had to look great, like Splinter Cell's. Too many games, especially indie games, just put a cheap texture or two on a blue quad. But in my opinion, having a great looking
 boundary like an ocean can really tie your environment together and add a layer of polish.</p>
<p>Now, just to clarify: we aren't going for the ocean in Crysis here. We want something that looks good and seems to be endless, so most of our work will be in the DirectX 9 Shaders. We will be using C# and XNA to build a project around it (XNA is fantastic
 for rapid development and tech demos, as well as its full Indie Games Distribution system).</p>
<h4>Getting Started</h4>
<p>Let's take a look at the base project. You should be able to compile and run it on the spot. When you get in, you will be able to turn the camera with the mouse and move with WASD (or use the first gamepad with standard FPS controls if you converted to run
 on Xbox360), but all that's there is the skybox at an infinite distance away. I won't go into rendering skyboxes in this article because there are
<a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2/Skybox.php">many</a>
<a href="http://www.miszalok.de/C_3D_XNA/C6_Skybox/XNAC6_e.htm">articles</a> <a href="http://www.toymaker.info/Games/XNA/html/xna_skybox.html">
about it</a> <a href="http://www.dotnetkicks.com/xna/Skybox_in_XNA_using_only_Two_Triangles">
already</a>. But you should be familiar with the concept of Cube Maps, which are basically six square textures representing the six faces of a cube.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image002_2.jpg"><img title="clip_image002" border="0" alt="clip_image002" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image002_thumb.jpg" width="422" height="317"></a></p>
<p>So, let's get right into the code. We'll start with a big blue plane. Open up Ocean.cs. You will notice that we already have some code in here. We have some vertices set up in the Load() function and a vertex declaration created (Again, in this article I
 assume you have a basic understanding of 3D rendering). These vertices will create two triangles that make a very large XZ plane at Y=0. Since our ocean will be processed only in the pixel shader, the plane should be much larger than your far-clip plane set
 up in your projection matrix. So let's draw the plane. In the Ocean's Draw() function, add these lines:</p>
<p><b>C# </b></p>
<pre class="csharpcode">Global.Graphics.VertexDeclaration = OceanVD;
Global.Graphics.DrawUserPrimitives&lt;VertexPositionNormalTexture&gt;
    (PrimitiveType.TriangleList, OceanVerts, 0, 2);</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>This code tells the graphics device what kind of vertex we are using, and tells it to draw two consecutive triangles. But XNA uses only Shaders; it doesn't support fixed function.</p>
<p>Let's go over to our Solution Explorer. Right click on the Content project in our game project, and click Add -&gt; New Item. Choose the &quot;Effect File&quot; template and name it OceanShader.fx. We are just testing to get the quads on there now, so we won't do much
 in this effect file yet. I cleaned up the pre-generated comments and changed the pixel shader return value to float4(0,0,1,1) to make it blue instead of red.</p>
<p>Now, let's go back to Ocean.cs. We need to add a new class variable for the shader. This is encompassed by the Microsoft.Xna.Framework.Graphics.Effect class. We add this to the top of the class:<b>
</b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// the ocean's required content</span>
<span class="kwrd">private</span> Effect oceanEffect; </pre>
<p>And we actually link that to our FX file in the load function with this:<b> </b>
</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// load the shader</span>
oceanEffect = Content.Load&lt;Effect&gt;(<span class="str">&quot;OceanShader&quot;</span>); </pre>
<p></p>
<p>Now we just need to set the shader variables in the draw function and tell the shader to begin and end. Our draw function now looks like this:<b>
</b></p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">void</span> Draw(GameTime gameTime, Camera cam, 
        TextureCube skyTexture, Matrix proj)
{
    <span class="rem">// start the shader</span>
    oceanEffect.Begin();
    oceanEffect.CurrentTechnique.Passes[0].Begin();

    <span class="rem">// set the transforms</span>
    oceanEffect.Parameters[<span class="str">&quot;World&quot;</span>].SetValue(Matrix.Identity);
    oceanEffect.Parameters[<span class="str">&quot;View&quot;</span>].SetValue(cam.GetViewMatrix());
    oceanEffect.Parameters[<span class="str">&quot;Projection&quot;</span>].SetValue(proj);

    oceanEffect.CommitChanges();

    <span class="rem">// draw our geometry</span>
    Global.Graphics.VertexDeclaration = OceanVD;
    Global.Graphics.DrawUserPrimitives&lt;VertexPositionNormalTexture&gt;
        (PrimitiveType.TriangleList, OceanVerts, 0, 2);

    <span class="rem">// and we're done!</span>
    oceanEffect.CurrentTechnique.Passes[0].End();
    oceanEffect.End();
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Before we draw, we must first begin an Effect and an EffectPass. Since we only have one pass in our shader, we can just begin the first one. Next, we set the Transform matrices defined in the shader (<a href="http://drunkenhyena.com/cgi-bin/view_cpp_article.pl?chapter=2;article=27">Read
 here</a> for more information on the transform matrices). Then we tell the Effect to CommitChanges(), which basically flushes the parameter changes down the tube to the graphics card so we can draw. Now we see our old code to draw the plane. Finally, we end
 the EffectPass and the Effect. The program should run now, with a big blue plane where your ocean is.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image004_2.jpg"><img title="clip_image004" border="0" alt="clip_image004" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image004_thumb.jpg" width="423" height="317"></a></p>
<h4>Skymap Reflections</h4>
<p>One of the best ways to make water look really neat is to add reflection. Ever seen a snow-covered mountain reflected on the surface of a lake? It's gorgeous. Let's make our ocean reflect the sky. Go back to the OceanShader.fx file. This is where we will
 do the majority of our work. We need to give the shader the sky cubemap. Add this parameter to the top of the FX file:<b>
</b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">textureCUBE cubeTex;
samplerCUBE CubeTextureSampler = sampler_state
{
    Texture = &lt;cubeTex&gt;;
    MinFilter = anisotropic;
    MagFilter = anisotropic;
    MipFilter = anisotropic;
    AddressU = wrap;
    AddressV = wrap;
};</pre>
<p>Next, we need to replace the Vertex structures with ones that match the actual vertices. They should look something like this:<b>
</b></p>
<p><b>HLSL </b></p>
<pre class="csharpcode"><span class="kwrd">struct</span> VertexShaderInput
{
    float3 Position            : POSITION0;
    float3 normal              : NORMAL0;
    float2 texCoord            : TEXCOORD0;
};

<span class="kwrd">struct</span> VertexShaderOutput
{
    float4 Position            : POSITION0;
    float2 texCoord            : TEXCOORD0;
    float3 worldPos         : TEXCOORD1;
};</pre>
<p>We've now added two variables. The texCoord is pretty simple. We just pass it along (and multiply it). The worldPos is already calculated for us, so we can just assign it. Since it's an ocean, we can just assume that the normal vector is straight up (why
 would we have a slanted ocean?). Our vertex shader should look like this:<b> </b>
</p>
<p><b>HLSL </b></p>
<pre class="csharpcode">VertexShaderOutput output;

float4 worldPosition = mul(float4(input.Position,1), World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
    
output.texCoord = input.texCoord*100;
output.worldPos = worldPosition.xyz;

<span class="kwrd">return</span> output;</pre>
<p>To do reflections, we need one more variable. A reflection off a surface requires a source vector and a surface normal vector. We can create our source vector by subtracting the camera position from the input's world position. To get the camera position,
 we could extract it from the View Matrix, but that's a pain. Instead, we'll just add a float3 variable to the top of our FX file like so:<b>
</b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float3 EyePos; </pre>
<p></p>
<p>Now we update our pixel shader function:<b> </b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float3 diffuseColor = float4(0,0,1,1);
float3 normal = float3(0,1,0);
float3 cubeTexCoords = reflect(input.worldPos-EyePos,normal);
float3 cubeTex = texCUBE(CubeTextureSampler,cubeTexCoords).rgb;

<span class="kwrd">return</span> float4((cubeTex*0.8)&#43;(diffuseColor*0.2),1); </pre>
<p></p>
<p>So what is this actually doing? First we set up the diffuseColor, which is the color of the ocean itself, blue, which keeps it from looking like a big mirror. Next we assume the normal is straight up (We'll change this later). Then we need to get the texture
 coordinates for the skymap. We will reflect the vector from the eye off of the surface normal. Cubemaps take 3-component vectors, and don't even need them to be normalized, so that's all we need there. Then we use those coordinates and actually store the texture
 lookup's RGB values (what sky has an alpha?). Finally, we combine 80% of the reflected sky color with 20% of the diffuse color. Can we run it now? Well, no. We defined those variables up top, but never set them. Let's go back to the Ocean.cs and add in some
 more parameter mutators:<b> </b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">oceanEffect.Parameters[<span class="str">&quot;EyePos&quot;</span>].SetValue(cam.Position);
<span class="rem">// set the sky texture</span>
oceanEffect.Parameters[<span class="str">&quot;cubeTex&quot;</span>].SetValue(skyTexture); </pre>
<p></p>
<p>Now we can run it! You should see a big flat body of blue water that reflects the sky. Cool, huh? But it's not very watery yet, is it?</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image006_2.jpg"><img title="clip_image006" border="0" alt="clip_image006" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image006_thumb.jpg" width="428" height="321"></a></p>
<h3>Normal Mapping</h3>
<p>Let's add some chop to the surface. Four normal maps are already be included in the Content project, so we just need to add a Texture2D array to our Ocean class and load in these textures. We'll call the texture array OceanNormalMaps:<b>
</b></p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">private</span> Texture2D[] OceanNormalMaps; </pre>
<p>And load them in the Load() function like this:<b> </b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// load the normal maps</span>
OceanNormalMaps = <span class="kwrd">new</span> Texture2D[4];
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; 4; i&#43;&#43;)
    OceanNormalMaps[i] = Content.Load&lt;Texture2D&gt;(<span class="str">&quot;Ocean&quot;</span> &#43; (i &#43; 1) &#43; <span class="str">&quot;_N&quot;</span>);</pre>
<p></p>
<p>What are we going to do with these textures? It's simple really: we'll lerp between them. Switch to the FX file and add two new texture registers (we'll only be lerping between two at any given time) and a float for the actual lerping value:<b>
</b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">float</span> textureLerp;

texture2D normalTex;
sampler2D NormalTextureSampler = sampler_state
{
    Texture = &lt;normalTex&gt;;
    MinFilter = anisotropic;
    MagFilter = anisotropic;
    MipFilter = anisotropic;
    AddressU = wrap;
    AddressV = wrap;
};

texture2D normalTex2;
sampler2D NormalTextureSampler2 = sampler_state
{
    Texture = &lt;normalTex2&gt;;
    MinFilter = anisotropic;
    MagFilter = anisotropic;
    MipFilter = anisotropic;
    AddressU = wrap;
    AddressV = wrap;
};</pre>
<p>Next, we change our pixel shader code:<b> </b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float3 diffuseColor = float4(0,0,1,1);
    
float4 normalTexture1 = tex2D(NormalTextureSampler, input.texCoord);
float4 normalTexture2 = tex2D(NormalTextureSampler2, input.texCoord);
float4 normalTexture = (textureLerp*normalTexture1)&#43;
            ((1-textureLerp)*normalTexture2);
    
float3 normal = ((normalTexture)*2)-1;
normal.xyz = normal.xzy;
normal = normalize(normal);
    
float3 cubeTexCoords = reflect(input.worldPos-EyePos,normal);
    
float3 cubeTex = texCUBE(CubeTextureSampler,cubeTexCoords).rgb;
    
<span class="kwrd">return</span> float4((cubeTex*0.8)&#43;(diffuseColor*0.2),1); </pre>
<p>Alright, let's take a look at this. The first new thing we do is sample the new normal maps and lerp between them with the value declared earlier. Nothing too complex there. But then we need to convert the RGB value into a normal. You'll notice that we take
 the RGB, multiply by 2 and subtract by one. This simply takes the compressed RGB [0:1] value and converts it to [-1:1] for a full range of normals. The next line re-orders the normal's components. This is because the normal map is traditionally on the XY plane,
 but our ocean is on the XZ plane—so we swap the Y and Z components. Finally, we normalize our normal. Always normalize your normals! Everything after that is the same as before. Let's go set these variables we defined and get this thing working. Go back to
 Ocean.cs and add this code to the draw:<b> </b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// choose and set the ocean textures</span>
<span class="kwrd">int</span> oceanTexIndex = ((<span class="kwrd">int</span>)(gameTime.TotalGameTime.TotalSeconds) % 4);
oceanEffect.Parameters[<span class="str">&quot;normalTex&quot;</span>].SetValue(
    OceanNormalMaps[(oceanTexIndex &#43; 1) % 4]);

oceanEffect.Parameters[<span class="str">&quot;normalTex2&quot;</span>].SetValue(
    OceanNormalMaps[(oceanTexIndex) % 4]);

oceanEffect.Parameters[<span class="str">&quot;textureLerp&quot;</span>].SetValue(
    (((((<span class="kwrd">float</span>)gameTime.TotalGameTime.TotalSeconds) - 
    (<span class="kwrd">int</span>)(gameTime.TotalGameTime.TotalSeconds)) * 2 - 1) * 0.5f) 
    &#43; 0.5f); </pre>
<p>You can do the math on this if you want, but basically it just cycles through the four textures and sets the lerp value so it's a continuous shift. After all that, you should have an interesting image when you run the program!</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image008_2.jpg"><img title="clip_image008" border="0" alt="clip_image008" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image008_thumb.jpg" width="428" height="321"></a></p>
<h3>Animate and Blend</h3>
<p>Now we have something that resembles water. But when was the last time you saw water that just moved up and down—especially in the ocean? Let's animate this a bit! The first thing we'll do is make the texture coordinates scroll based on time. Let's add a
 time float to the top of the FX file:<b> </b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">float</span> time = 0;</pre>
<p></p>
<p><b></b></p>
<p>Next, let's scroll the texture coordinates in the normal map lookup:<b> </b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float4 normalTexture1 = tex2D(NormalTextureSampler, 
    input.texCoord&#43;float2(time,time));
float4 normalTexture2 = tex2D(NormalTextureSampler2, 
    input.texCoord&#43;float2(time,time));</pre>
<p></p>
<p>Now, simply set the time parameter in the Ocean.cs's Draw():<b></b></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// set the time used for moving waves</span>
oceanEffect.Parameters[<span class="str">&quot;time&quot;</span>].SetValue(
    (<span class="kwrd">float</span>)gameTime.TotalGameTime.TotalSeconds * 0.02f);</pre>
<p></p>
<p>Your water should be moving now if you run it.</p>
<p>There is one more enhancement we can do. What's better than having one moving surface? How about two? It's basically parallax normal mapping. We will change our pixel shader code to look like this:<b>
</b></p>
<p><b>HLSL <br>
</b></p>
<pre class="csharpcode">float3 diffuseColor = float4(0,0,1,1);
    
float4 normalTexture1 = tex2D(NormalTextureSampler, 
    input.texCoord*0.1&#43;float2(time,time));

float4 normalTexture2 = tex2D(NormalTextureSampler2, 
    input.texCoord*0.1&#43;float2(time,time));

float4 normalTexture = (textureLerp*normalTexture1) &#43;
    ((1-textureLerp)*normalTexture2);

float4 normalTexture3 = tex2D(NormalTextureSampler, 
    input.texCoord*2&#43;float2(-time,-time*2));

float4 normalTexture4 = tex2D(NormalTextureSampler2, 
    input.texCoord*2&#43;float2(-time,-time*2));

float4 normalTextureDetail = (textureLerp*normalTexture3) &#43;
    ((1-textureLerp)*normalTexture4);
    
float3 normal = (((0.5*normalTexture) &#43; 
    (0.5*normalTextureDetail))*2) - 1;

normal.xyz = normal.xzy;
normal = normalize(normal);
    
float3 cubeTexCoords = reflect(input.worldPos-EyePos,normal);
    
float3 cubeTex = texCUBE(CubeTextureSampler,cubeTexCoords).rgb;
    
<span class="kwrd">return</span> float4((cubeTex*0.8)&#43;(diffuseColor*0.2),1); </pre>
<p>What we did here is add two separate, lerping texture coordinates together. The 1 and 2 have been scaled by 0.1, making the waves much larger. The 3 and 4 lookups are scaled by 2 so they are much smaller, and move much faster in the opposite direction. This
 makes it look like the ocean has an overall current and some smaller waves simulating wind. The pixels are then combined before being converted to normals. Go ahead and run it. You should see your nice, new ocean!</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image010_2.jpg"><img title="clip_image010" border="0" alt="clip_image010" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9954238/clip_image010_thumb.jpg" width="428" height="321"></a></p>
<h3>Conclusion</h3>
<p>And there you have it: a nice, infinite ocean! Since the majority of the work is done in the pixel shader, it will go on to the very end of the depth buffer and tile infinitely. Also, this is best when you are only looking out at it. It becomes somewhat
 apparent to the user if you are looking at the level on the ocean and only the sky, not the level, reflects properly. You may also notice that the ocean looks a bit cartoony in our example, but the good news is that this is merely an effect of the skybox being
 done in a soft pastel style. A more realistic skybox means a more realistic ocean.</p>
<p>I'm looking forward to seeing how people use this effect! If you use it, please
<a href="mailto:louisingenthron@fvproductions.org">send me an email</a> with a screenshot.</p>
<h3>About The Author</h3>
<p>Louis Ingenthron is a Game Developer in Orlando, FL. He works on commercial Console and PC titles, but runs his own Indie Games company,
<a href="http://fvproductions.org/">FV Productions</a>, on the side. He is best known for his open source XNA rhythm game Unsigned and specializes in real-time Graphics programming. He has been working with XNA since the 2.0 Beta and with .NET C# for just as
 long. He is also familiar with several other development languages, such as C, C&#43;&#43;, and Java. Occasionally, he can even be found doing web development and Flash. Louis also writes for MSDN's Coding4Fun website, contributing articles on a monthly basis.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Louis-Ingenthron/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:aaaa00bc9a6a41a4a0699e7600ca3a30">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Making-an-Ocean-with-XNA</comments>
      <itunes:summary>
In this article, Louis Ingenthron will show you how to create a simple endless ocean for an XNA C# game. 
Introduction
Every game needs boundaries, such as a window separating the player from space or a brick wall. When I first played Splinter Cell: Double Agent&#39;s Cozumel Cruise level, I spent a good 5 minutes just looking at the ocean that kept the player in bounds. It
 was a beautiful sunset with waves moving across the ocean endlessly outward... and it was neat. 
When I was tasked with creating a great ocean for a Caribbean pirate game, I knew it had to look great, like Splinter Cell&#39;s. Too many games, especially indie games, just put a cheap texture or two on a blue quad. But in my opinion, having a great looking
 boundary like an ocean can really tie your environment together and add a layer of polish. 
Now, just to clarify: we aren&#39;t going for the ocean in Crysis here. We want something that looks good and seems to be endless, so most of our work will be in the DirectX 9 Shaders. We will be using C# and XNA to build a project around it (XNA is fantastic
 for rapid development and tech demos, as well as its full Indie Games Distribution system). 
Getting Started
Let&#39;s take a look at the base project. You should be able to compile and run it on the spot. When you get in, you will be able to turn the camera with the mouse and move with WASD (or use the first gamepad with standard FPS controls if you converted to run
 on Xbox360), but all that&#39;s there is the skybox at an infinite distance away. I won&#39;t go into rendering skyboxes in this article because there are
many
articles 
about it 
already. But you should be familiar with the concept of Cube Maps, which are basically six square textures representing the six faces of a cube. 
 
So, let&#39;s get right into the code. We&#39;ll start with a big blue plane. Open up Ocean.cs. You will notice that we already have some code in here. We have some vertices set up in the Load() function and a vertex declaration created (Again</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Making-an-Ocean-with-XNA</link>
      <pubDate>Wed, 27 Jan 2010 16:00:45 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Making-an-Ocean-with-XNA</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9954238_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9954238_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Louis Ingenthron </dc:creator>
      <itunes:author>Louis Ingenthron </itunes:author>
      <slash:comments>5</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Making-an-Ocean-with-XNA/RSS</wfw:commentRss>
      <category>Gaming</category>
      <category>XNA</category>
      <category>XNA framework</category>
      <category>HSL</category>
    </item>    
</channel>
</rss>