<?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>MQuandt.Blog &#187; Programming</title>
	<atom:link href="http://mquandt.com/blog/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://mquandt.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 01 Sep 2010 00:06:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
<cloud domain='mquandt.com' port='80' path='/blog/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>TechEd 2010 Academic Day Slides</title>
		<link>http://mquandt.com/blog/2010/08/teched-2010-academic-day-slides/</link>
		<comments>http://mquandt.com/blog/2010/08/teched-2010-academic-day-slides/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 00:06:55 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Students]]></category>
		<category><![CDATA[TechEd]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[academic day]]></category>
		<category><![CDATA[presentations]]></category>
		<category><![CDATA[slides]]></category>
		<category><![CDATA[teched 2010]]></category>
		<category><![CDATA[teched australia]]></category>
		<category><![CDATA[windows phone 7]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/08/teched-2010-academic-day-slides/</guid>
		<description><![CDATA[As promised, here are my slides for my presentation on Windows Phone 7 during Academic Day at TechEd 2010.]]></description>
			<content:encoded><![CDATA[<p>As promised, here are my slides for my presentation on Windows Phone 7 during Academic Day at TechEd 2010.</p>
<p><iframe style="padding-bottom: 0px; background-color: #fcfcfc; padding-left: 0px; width: 98px; padding-right: 0px; height: 115px; padding-top: 0px" title="Preview" marginheight="0" src="http://cid-670fd4ae41402e8a.office.live.com/embedicon.aspx/MSP/TechEd2010^_WP7^_Academic.pptx" frameborder="0" marginwidth="0" scrolling="no"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/08/teched-2010-academic-day-slides/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tech Ed Australia 2010 Day 1</title>
		<link>http://mquandt.com/blog/2010/08/tech-ed-australia-2010-day-1/</link>
		<comments>http://mquandt.com/blog/2010/08/tech-ed-australia-2010-day-1/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 14:16:04 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Students]]></category>
		<category><![CDATA[TechEd]]></category>
		<category><![CDATA[Xbox 360]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[academic day]]></category>
		<category><![CDATA[foxtel]]></category>
		<category><![CDATA[kinect]]></category>
		<category><![CDATA[teched 2010]]></category>
		<category><![CDATA[teched australia]]></category>
		<category><![CDATA[windows phone 7]]></category>
		<category><![CDATA[wp7]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/08/tech-ed-australia-2010-day-1/</guid>
		<description><![CDATA[I was recently invited to speak on a pre-day for faculty and students at TechEd Australia, held on the Gold Coast. The plan is to write up a little bit about each day, although it might not be up the same day, depending on internet availability. So today was Academic Day, in particular, for faculty [...]]]></description>
			<content:encoded><![CDATA[<p>I was recently invited to speak on a pre-day for faculty and students at TechEd Australia, held on the Gold Coast. The plan is to write up a little bit about each day, although it might not be up the same day, depending on internet availability.</p>
<p>So today was Academic Day, in particular, for faculty members, who had been invited to hear about what students want, directly from students. (That was the theme)</p>
<p>A couple of weeks previously, Andrew Parsons (<a href="http://twitter.com/mrandypuppy" target="_blank">@MrAndyPuppy</a>), the local Academic Developer Evangelist asked me to do a presentation on Windows Phone 7, with a split between the experience promised by Microsoft, and developing for the phone. After I learned that I really cannot do a reasonable phone demo in 10 minutes, I cut it down to a demo of pre-made code.</p>
<p>Either way, some big highlights arose today. I managed to get Andy to let me see and use a developer phone, and I must say, awesome, however I cannot go into specifics, nor can I take photos unfortunately.</p>
<p>The other highlight was the awesome keynote presented by Michael Kordahi (<a href="http://twitter.com/delic8genius" target="_blank">@delic8genius</a>) with a special appearance by August De Los Reyos (<a href="http://twitter.com/augustdlr" target="_blank">@augustdlr</a>) presenting his experiences developing User experiences on the Surface, and even the Windows key on the keyboard. Some awesome demos for a theoretical Foxtel experience (Cable TV in Australia) that uses all devices, including a Surface table (jeez they love that thing). They then showed off the big devices for this year, Kinect and Windows Phone 7, and seeing this in person was really awesome. I cannot wait for next week when I will get to try out a device. (Unfortunately they took the device back to Sydney right after the keynote.)</p>
<p>Photos will follow as I can sort them out, and maybe videos depending on what I&#8217;m allowed to post, and what connection I can get.</p>
<p>Exciting days remain ahead, I have to present Windows Phone 7 to students on Thursday, and of course I must experience the great TechEd sessions.</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/08/tech-ed-australia-2010-day-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reconstructing Position from Depth for Fullscreen Quads</title>
		<link>http://mquandt.com/blog/2010/06/reconstructing-position-from-depth-for-fullscreen-quads/</link>
		<comments>http://mquandt.com/blog/2010/06/reconstructing-position-from-depth-for-fullscreen-quads/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 02:56:35 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[depth]]></category>
		<category><![CDATA[frustum ray]]></category>
		<category><![CDATA[techniques]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/?p=108</guid>
		<description><![CDATA[Recently I found an issue with an older article of mine that covered this topic, so I pulled it down until I could find the time to understand and fix the issue. After a bit of work I have fixed it and present this refresh. The key to deferred rendering and other techniques is the [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I found an issue with an older article of mine that covered this topic, so I pulled it down until I could find the time to understand and fix the issue. After a bit of work I have fixed it and present this refresh.</p>
<p>The key to deferred rendering and other techniques is the ability to use a depth map to store world position. As we know a depth map consists of floating point values (optimally) and so normally we would use those values with our Clip Space coordinates and the Inverse of the ViewProjection matrix to get the position in World Space.</p>
<p>However there is another way to do this, and the big benefit is that it does not require a matrix multiplication to do so.</p>
<p>Presented by Crytek during a presentation on Atmospheric Scattering, this method uses just a Multiply + Add to get the position in World Space from our depth value at that point. To do this we need to get the far view frustum corners, in View Space, and pass them to the shader.</p>
<p>  <span id="more-108"></span><br />
<h3>Getting the Corners</h3>
<p>This is easily done in XNA through the BoundingFrustum.GetCorners() method. Note that we only need the far corners, so we can take the last 4 in the 8 element array, and we also need these corners in View space, so be sure to transform them by the View matrix before you pass them through.</p>
<pre class="brush: csharp;">private void getFrustumCorners(out Vector3[] corners)
{
    corners = new Vector3[4];

    Vector3[] temp = CurrentCamera.Frustum.GetCorners();
    for (int i = 0; i &lt; 4; i++)
    {
        corners[i] = Vector3.Transform(temp[i + 4], CurrentCamera.View);
    }
}</pre>
<p>Since we are in the CPU/XNA code, be sure to also pass the depth of the far clip plane, and the camera’s World matrix. (Simply invert the View matrix if you do not already have a World matrix)</p>
<h3>Writing out Depth</h3>
<p>Now for some shader code! First in the depth shader, you need to change how you write out the depth value, instead we take the Linear View Space depth, which means that we need to get the Z value from Position * World * View rather than Position * World * View * Projection.</p>
<pre class="brush: cpp;">float4x4 wv = mul( World, View );
float4 posVS = mul( pos, wv );

output.Position = mul( posVS, Projection );
output.Depth = posVS.z;</pre>
<p>Then in the pixel shader, take this depth value, negate it and divide it by the Far Clipping plane.</p>
<pre class="brush: cpp;">output.Depth = 1.0f - ( -depth / FarClip );</pre>
<p>Now when you want to reconstruct this, we need to find the correct frustum corner inside the vertex shader. (Note: This code only applies if you are rendering a fullscreen quad)</p>
<h3>Preparing and Choosing the Right Corner</h3>
<p>The best way to do this is to pass along the array index as a 3rd value with your texture coordinates. If you do not want to modify the vertex type, you can also apply some maths to determine the right index.</p>
<p>For brevity I will assume that the index is provided with the texture coordinates.</p>
<p>Take that ray and multiply it by the camera World matrix, to move the ray into World space, then pass it to the pixel shader.</p>
<pre class="brush: cpp;">output.FrustRay = mul( FSQ_GetFrustumRay( tcri.z ), CamWorld );</pre>
<h3>Getting the Position</h3>
<p>Now that you have the ray, simply sample the depth texture for the depth value, and multiply it by the ray. Then take that and add it to the camera position to get the point in world space. (Rather than just a direction)</p>
<pre class="brush: cpp;">float depth = 1.0f - tex2D( depthSampler, tc ).x;
float3 pos = CamPosition + depth * frustRay;</pre>
<p>Now you have your position!</p>
<p>I will include the technique to do the same thing with arbitrary world geometry when I write an article on Point Lights or Spotlights. At the moment I am working on implementing shadows, and probably won’t touch those topics until I solve some pressing issues.</p>
<h3>Final Notes</h3>
<p>Here is a code sample for passing the index as a part of the texture coordinate value.</p>
<p>&#160;</p>
<pre class="brush: csharp;">private struct VertexPositionTexCoordRayIndex
{
    private Vector3 position;
    public Vector3 Position
    {
        get { return position; }
        set { position = value; }
    }

    private Vector3 texCoordRayIndex;
    public Vector3 TexCoordRayIndex
    {
        get { return texCoordRayIndex; }
        set { texCoordRayIndex = value; }
    }

    public static int SizeInBytes { get { return sizeof(float) * 6; } }

    public static readonly VertexElement[] VertexElements =
        new VertexElement[] {
            new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
            new VertexElement(0, sizeof(float)*3, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0)
        };

    public VertexPositionTexCoordRayIndex(Vector3 position, Vector3 texcoordRayindex)
    {
        this.position = position;
        this.texCoordRayIndex = texcoordRayindex;
    }
}</pre>
<pre class="brush: csharp;">VertexPositionTexCoordRayIndex[] verts = new VertexPositionTexCoordRayIndex[4];
verts[0] = new VertexPositionTexCoordRayIndex(new Vector3(-1, 1, 1), new Vector3(0, 0, 0));
verts[1] = new VertexPositionTexCoordRayIndex(new Vector3(1, 1, 1), new Vector3(1, 0, 1));
verts[2] = new VertexPositionTexCoordRayIndex(new Vector3(-1, -1, 1), new Vector3(0, 1, 3));
verts[3] = new VertexPositionTexCoordRayIndex(new Vector3(1, -1, 1), new Vector3(1, 1, 2));</pre>
<p>&#160;</p>
<p>Remember that XNA provides the corners in a different order to just 1,2,3,4, so we can explicitly pass the correct index for the vertex we are working with here, and it will be chosen correctly in the shader.</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/06/reconstructing-position-from-depth-for-fullscreen-quads/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Status June 2010</title>
		<link>http://mquandt.com/blog/2010/06/status-june-2010/</link>
		<comments>http://mquandt.com/blog/2010/06/status-june-2010/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 22:52:20 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[light pre pass]]></category>
		<category><![CDATA[status]]></category>
		<category><![CDATA[techniques]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/06/status-june-2010/</guid>
		<description><![CDATA[Hi all, not dead. Apologies for the lack of updates, I am in the process of finishing an internship required for my university course, and it is a challenge to find good time to tackle some XNA issues and write posts. I am currently working on Directional light shadows for my engine, I have cascaded [...]]]></description>
			<content:encoded><![CDATA[<p>Hi all, not dead.</p>
<p>Apologies for the lack of updates, I am in the process of finishing an internship required for my university course, and it is a challenge to find good time to tackle some XNA issues and write posts.</p>
<p>I am currently working on Directional light shadows for my engine, I have cascaded shadow maps implemented, and now I am just tackling some issues I have encountered, which is taking a while – I also need to find a good filtering method.</p>
<p>If I get bored of trying to fix those annoying issues, I will probably jump into re-implementing point lights, and spotlights, and write something about those.</p>
<p>Some housekeeping notes:</p>
<p>I encountered a pretty big issue with the “Reconstructing position from depth” technique, and I have taken that article down from the blog for now. At the moment my own code uses the old “Multiply my the Inverse of the View Projection matrix”, and probably will continue to until I have time to solve that problem.</p>
<p>I have also updated this blog to WordPress 3.0, so let me know if you encounter any issues.</p>
<p>Back to work.</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/06/status-june-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[LPP] Ambient Lights</title>
		<link>http://mquandt.com/blog/2010/04/lpp-ambient-lights/</link>
		<comments>http://mquandt.com/blog/2010/04/lpp-ambient-lights/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 01:32:01 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[ambient lights]]></category>
		<category><![CDATA[light pre pass]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/04/lpp-ambient-lights/</guid>
		<description><![CDATA[Ambient lights are used in modern games to fake the indirect illumination that exists in the real world. By adding a generally very weak light to the scene, we can avoid the 100% black shadows that really should not exist, all at a very low cost compared to proper indirect illumination or baked ambient light [...]]]></description>
			<content:encoded><![CDATA[<p>Ambient lights are used in modern games to fake the indirect illumination that exists in the real world. By adding a generally very weak light to the scene, we can avoid the 100% black shadows that really should not exist, all at a very low cost compared to proper indirect illumination or baked ambient light maps.</p>
<p>I have found that the simplest way to integrate these ambient lights into the Light Pre Pass system, and allow for other elements to change the lights throughout the game is to create a new light type that fits into the normal lighting model.</p>
<p>This is probably the simplest type out there, you just create a full screen quad and render it using a shader that writes the colour information directly to the light buffer. All we have to pass to the shader is the colour and intensity. (you could always pre-compute this, but beware of the byte-&gt;int32 auto promotion C# does)</p>
<p> <span id="more-101"></span>
<p>Here is the C# class:</p>
<pre class="brush: csharp;">public class AmbientLight
{
    public Color Color { get; set; }

    public bool Enabled { get; set; }

    private int intensity = 100;

    public int Intensity
    {
        get { return intensity; }
        set { intensity = value; }
    }

    private Effect shader;

    public AmbientLight(Color col, int intensity)
    {
        this.Color = col;
        this.Enabled = true;
        this.intensity = intensity;
    }

    public void LoadContent(ContentManager content)
    {
        shader = content.Load&lt;Effect&gt;(@&quot;Effects\Lights\l_ambient&quot;);
    }

    public void DrawLight(Renderer caller)
    {
        if (!Enabled)
            return;

        shader.Begin();
        shader.Parameters.TrySet(&quot;LightColor&quot;, Color.ToVector3());
        shader.Parameters.TrySet(&quot;Intensity&quot;, intensity);

        shader.CurrentTechnique.Passes[0].Begin();
        caller.FSQ.Draw();
        shader.CurrentTechnique.Passes[0].End();

        shader.End();
    }
}</pre>
<p>and the shader:</p>
<pre class="brush: cpp;">float3 LightColor;
float Intensity;

float4 vs_main(in float4 pos : POSITION) : POSITION
{
    return pos;
}

float4 ps_main() : COLOR
{
    return float4(LightColor * (Intensity / 100), 0);
}

technique AmbientLight
{
    pass p0
    {
        VertexShader = compile vs_2_0 vs_main();
        PixelShader = compile ps_2_0 ps_main();
    }
}</pre>
<p>I am in the middle of a crunch at work, and so future posts will be slow until it is all over. (That is why this one took a while to come out) I have not had the chance to do much work on my own XNA code, let alone tutorials. <img src='http://mquandt.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Thanks for your patience, I cannot wait to get back to XNA. (and I cannot wait for XNA 4.0 with HiDef)</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/04/lpp-ambient-lights/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>XNA 4.0 &#8211; Reach/HiDef &amp; My Article(s)</title>
		<link>http://mquandt.com/blog/2010/03/xna-4-0-reachhidef-my-articles/</link>
		<comments>http://mquandt.com/blog/2010/03/xna-4-0-reachhidef-my-articles/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 12:34:44 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Xbox 360]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[light pre pass]]></category>
		<category><![CDATA[xna 4.0]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/03/xna-4-0-reachhidef-my-articles/</guid>
		<description><![CDATA[Shawn Hargreaves just posted this: http://blogs.msdn.com/shawnhar/archive/2010/03/12/reach-vs-hidef.aspx I suggest you have a read through it if you are interested in the kinds of things I post on this blog, especially the Light Pre Pass technique. One of the key parts of Shawn’s article are the changes that will be made to Render Targets, and the bucketing [...]]]></description>
			<content:encoded><![CDATA[<p>Shawn Hargreaves just posted this: <a href="http://blogs.msdn.com/shawnhar/archive/2010/03/12/reach-vs-hidef.aspx">http://blogs.msdn.com/shawnhar/archive/2010/03/12/reach-vs-hidef.aspx</a></p>
<p>I suggest you have a read through it if you are interested in the kinds of things I post on this blog, especially the Light Pre Pass technique.</p>
<p>One of the key parts of Shawn’s article are the changes that will be made to Render Targets, and the bucketing of the RenderTarget/Texture formats into the Reach and HiDef profiles.</p>
<p>It would be safe to say that future articles here will require the HiDef feature set. I make use of some of the Render Targets that do not exist in Reach, and while there may be a way to use a Reach Render Target, for the purposes of conveying the technique, I will not be adding extra code to support it. I may however note where alternatives can be used, and hint or mention how to use them.</p>
<p>I know I have previously used BGRA formats in my sample, and in future this will become RGBA, no big deal. I won’t change the 3.1 sample for now, but if I need to change other things to upgrade it to 4.0, then that will be “fixed”.</p>
<p>This shouldn’t be much of a problem, if you are going to be using the articles I plan to write, then you’ll have a computer that works with HiDef, or an XBOX.</p>
<p>As a side note, I no longer have a valid Creators Club subscription, so I have not tested the recent Light Pre-Pass article on the XBOX. If anyone has any issues let me know and I will try and look into it. I plan to get a premium subscription soon and test future articles on the XBOX.</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/03/xna-4-0-reachhidef-my-articles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Light Pre-Pass Round 2</title>
		<link>http://mquandt.com/blog/2010/03/light-pre-pass-round-2/</link>
		<comments>http://mquandt.com/blog/2010/03/light-pre-pass-round-2/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 12:20:58 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[light pre pass]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/03/light-pre-pass-round-2/</guid>
		<description><![CDATA[Those who have been following this blog know that I wrote an article about implementing a Light Pre-Pass renderer last year. Since then I have made numerous improvements and fixes as I have tried the system over different PC configurations. This time around I will be including those changes into the implementation, and also releasing [...]]]></description>
			<content:encoded><![CDATA[<p>Those who have been following this blog know that I wrote an article about implementing a Light Pre-Pass renderer last year. Since then I have made numerous improvements and fixes as I have tried the system over different PC configurations.</p>
<p>This time around I will be including those changes into the implementation, and also releasing sample code for educational use. If you feel you have learned enough from the previous article, then feel free to skip this. For those new to the topic, please use this article instead of the older one.</p>
<p> <span id="more-96"></span>
</p>
<p>This article will focus on the theory, and will attempt to be as API neutral as possible. I will be making some references to XNA SurfaceFormats as this article is aimed more towards XNA developers, but for reference here are the matching Direct3D formats:</p>
<table border="0" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td valign="top" width="200">SurfaceFormat.Color</td>
<td valign="top" width="200">A8R8G8B8</td>
</tr>
<tr>
<td valign="top" width="200">SurfaceFormat.Bgra1010102</td>
<td valign="top" width="200">A2R10G10B10</td>
</tr>
<tr>
<td valign="top" width="200">SurfaceFormat.Single</td>
<td valign="top" width="200">R32F</td>
</tr>
<tr>
<td valign="top" width="200">SurfaceFormat.HalfSingle</td>
<td valign="top" width="200">R16F</td>
</tr>
</tbody>
</table>
<p>See the sample for an XNA implementation.</p>
<h3>General Overview</h3>
<p>For a number of years now, the concept of Deferred Rendering has been a hot topic in games. The ability to have a large number of lights, with a low cost per light is an attractive option. However deferred rendering suffers from the inability to render transparent objects at the same time as opaque objects. A few “solutions” have appeared in recent years that approach deferred rendering in a different way to allow for some level of transparency, however none have solved the problem completely, and all require extra work in some form.</p>
<p>There are a few different types of Deferred Rendering, however the two key forms are Deferred Shading, and Deferred Lighting. These differ in exactly which stage of rendering is deferred.</p>
<p>Deferred Shading defers the entire shading and lighting process, handling geometry rendering once, and then using an Uber Shader to light and shade the objects. One of the key negatives here is that you are limited in your material selection – although there are a few alternative solutions that can help here. Some other negatives include the “Fat Framebuffer” that this technique requires. As Deferred Shading relies on Multiple Render Targets (MRTs) to render the geometry once and store all important details, we are hit with both a memory cost, as well as limitations in DirectX9 which prevent us from applying multi-sampling (AA) to MRTs.    <br />Negatives aside, Deferred Shading allows us to get the benefit of many lights, and still only render the scene once, which can be good for performance in scenes where the triangle count is high, and you do not need a diverse set of materials.</p>
<p>Deferred Lighting on the other hand defers only the lighting step, and requires an extra pass over the geometry to apply the details. The benefit here is that you can apply a unique material to each of your objects, whilst retaining the ability to have many lights. This technique also makes use of MRTs, however it only uses 2 render targets during the Depth + Normals stage, so if you can afford another pass over geometry, you can split those into two passes and gain the ability to run code on older hardware that does not support MRTs.</p>
<h3>Deferred Lighting Overview</h3>
<p>Deferred Lighting consists of 3 key stages:<img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="LPP Pipeline" border="0" alt="LPP Pipeline" src="http://mquandt.com/blog/wp-content/uploads/2010/03/lpp_pipeline_thumb.png" width="481" height="200" /></p>
<ol>
<li>Render the Depth and World Space Normals of the Geometry </li>
<li>Render the lighting term using the Depth + Normals generated previously </li>
<li>Render the Geometry again, this time with unique materials, making use of the lighting term above. </li>
</ol>
<p>Remember that if you retain your hardware depth stencil, you get a performance increase from the early-z tests that modern hardware provides.</p>
<p>One key optimisation that is used in Deferred Shading is to render the lights using bounding volumes, ie a Sphere for a Point Light. This prevents overdraw for areas that are not lit.</p>
<p>I will be following the steps mentioned above, with the aforementioned optimisation, for the rest of this article.</p>
<h3>Stage 1: Depth + Normals</h3>
<p>The key requirement for any lighting calculation is fragment position, and normal. This means that if we want to determine the contribution a light makes to a particular pixel, we need to know where in world space that pixel is, and the normal at that pixel.</p>
<p>As we are deferring the lighting calculations, we need to store this information in a format we can use later. Now to store a position, we could go the naive route and store one component per channel, i.e. R=X, G=Y and B=Z, however this only gives us 8 bits of precision for each component, and each component is a full 32bit floating point number.</p>
<p>Instead we store the depth of the pixel and later reconstruct the position using the depth, and information from the camera.</p>
<p>Unfortunately, as we are working with XNA, we are restricted to D3D9 technology, and even then cannot use the FOURCC driver hacks that modern GPUs provide. This means that we have to write out the depth buffer to a separate render target instead of making use of the depth buffer the graphics card always creates.</p>
<p>So begin by preparing two render targets, the same size as the backbuffer you are going to draw to in the end. Make the depth target use SurfaceFormat.Single, and the Normals target use SurfaceFormat.Bgra1010102.</p>
<p>Of course when implementing this in a game for Windows, you should always verify that the SurfaceFormats are supported, and in the case of the depth buffer you can fall back to HalfSingle if Single is not supported. The Normal buffer can fall back to SurfaceFormat.Color if the 1010102 format is not supported, and you can always take the depth buffer back to Color if you absolutely need to, however note that you will need to add in extra packing code to make use of the full buffer then.</p>
<p>After that, we need to render the visible scene using a special shader that writes the Depth and Normal information to our render targets.</p>
<p>There are two key things to note here:</p>
<ol>
<li>If you decide to subtract the true depth from 1.0f, ensure you reverse that later on. </li>
<li>You need to remap the Normal from [-1, 1] to [0, 1] so that it stores correctly in the render target </li>
</ol>
<p>To accomplish #2, you simply need to use the following equation:</p>
<pre>output.Normal = (( input.Normal + 1.0f ) / 2.0f )</pre>
<p>Later on we will return this value to the [-1, 1] range by using the reverse of the above equation.</p>
<h3>Stage 2: Lighting</h3>
<p>Now that we have the Depth and Normal for each pixel, we can calculate the lighting from every light that touches each pixel. If you plan to include some form of shadow mapping, this is where you would handle rendering the shadow maps, and make use of them when lighting the object.</p>
<p>You can approach lighting in two ways:</p>
<ol>
<li>Render every type of light as a fullscreen quad. </li>
<li>Render each light as an appropriate light volume [<a href="http://developer.nvidia.com/object/6800_leagues_deferred_shading.html">Hargreaves04</a>] </li>
</ol>
<p>We will focus on #2, which allows us to reduce pixel draw and improve performance dramatically.</p>
<p align="left">Although I will only be implementing a Directional Light in the sample, you can use the following primitives to render each type of light:</p>
<table border="0" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td valign="top" width="200">Ambient Light</td>
<td valign="top" width="200">Fullscreen Quad</td>
</tr>
<tr>
<td valign="top" width="200">Directional Light</td>
<td valign="top" width="200">Fullscreen Quad</td>
</tr>
<tr>
<td valign="top" width="200">Point Light</td>
<td valign="top" width="200">Sphere</td>
</tr>
<tr>
<td valign="top" width="200">Spot Light</td>
<td valign="top" width="200">Cone or Box</td>
</tr>
</tbody>
</table>
<p align="left">As you can see, the two light types that do not have a position or volume, are still rendered as fullscreen quads, whilst the other two use approximations of their light volumes to prevent overdraw</p>
<p>In the case of the ambient light, you may choose to implement this as an extra term in your material shader instead, however I choose to implement it as a light object so that I may alter/combine/disable at will.</p>
<p>Here you need to set a new render target, which will hold our Light Buffer. Once that is done, render each visible light volume using a special shader based on the light type.</p>
<p>This is where the magic happens. Inside these special shaders, we reconstruct the world space position of the pixel from the depth value, and using the position and the normal, calculate the lighting term as you would during forward rendering.</p>
<p>There are a couple of ways you can reconstruct the position from the depth value. The most common and obvious way would be to use the X/Y value of the pixel in Post-Projection Space, combined with the depth as Z, and multiply that by the inverse of the ViewProjection matrix. This will give you the position of the pixel in World space, which you can use.</p>
<p>There are other techniques, some which end up cheaper than the matrix multiply mentioned above. For a full overview of most (if not all) of the techniques available for you to use, simply read through these two articles:</p>
<p><a href="http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/">http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/</a> </p>
<p><a href="http://mynameismjp.wordpress.com/2009/05/05/reconstructing-position-from-depth-continued/">http://mynameismjp.wordpress.com/2009/05/05/reconstructing-position-from-depth-continued/</a></p>
<p>In the sample I chose to use the Frustum Ray method, which is a cheaper way to get the position, but requires you to do some processing on the CPU to get the rays ready. In the sample this is calculated every time the camera parameters are set, however realistically you only need to do this any time your bounding frustum changes or moves.</p>
<p>Our light buffer, which is a SurfaceFormat.Color, can take four 8bit integers. The original, and (to my knowledge) recommended layout (from Wolfgang Engel) is to store the <strong>N</strong>.<strong>L</strong> * Color terms in the RGB channels, and the specular term in the Alpha channel. This leaves you with the following layout:</p>
<table border="0" cellspacing="0" cellpadding="2" width="231">
<tbody>
<tr>
<td valign="top" width="31">A</td>
<td valign="top" width="198"><strong>R</strong>.<strong>V</strong> (or <strong>N</strong>.<strong>H</strong> for Blinn-Phong)</td>
</tr>
<tr>
<td valign="top" width="31">R</td>
<td valign="top" width="198"><strong>N</strong>.<strong>L</strong> * Red</td>
</tr>
<tr>
<td valign="top" width="31">G</td>
<td valign="top" width="198"><strong>N</strong>.<strong>L</strong> * Green</td>
</tr>
<tr>
<td valign="top" width="31">B</td>
<td valign="top" width="198"><strong>N</strong>.<strong>L</strong> * Blue</td>
</tr>
</tbody>
</table>
<p>At this point you can also take into account the shadow map for each light, and use that to choose whether this light should illuminate or do nothing to the pixel. Now when rendering the lights, we need to set a couple of Render States to ensure things go smoothly.</p>
<p>First of all, we need to ensure that the depth buffer is disabled. This has to happen because we may need to render lights behind/inside other lights, and if the depth buffer is enabled, the graphics card will reject the contribution from some of those lights via the Early-Z feature.</p>
<p>Since we are using geometry to render the lighting, we need to handle the case when the camera is inside the light volume. Here we change the CullMode render state so that it either culls interior faces when the camera is outside the object, or it culls exterior faces when the camera is inside the object. Normally this would be set to Counter-Clockwise, which remains our default when outside the object.</p>
<p>Simply detect when the camera is inside the object and set the CullMode to Clockwise to handle the other case.</p>
<p>Another issue you may notice with this is when the camera is entering a light volume, especially the point light sphere. At this point, part of the screen is inside the object, and the rest is outside, so we need to set CullMode to None here to handle both cases without creating visual glitches.</p>
<p>Finally we need to enable alpha blending and set the blend mode to Add, this allows multiple lights that illuminate the same pixel to combine correctly (see <a href="http://en.wikipedia.org/wiki/Phong_shading">Phong Shading</a>).</p>
<p>Do not forget to re-enable the Depth Buffer and revert the CullMode to Counter-Clockwise before continuing, otherwise you might encounter hard to debug issues when rendering the materials.</p>
<h3>Stage 3: Materials</h3>
<p>Once the light buffer has been filled with all of the visible lights, you can move on to rendering the final image using each object’s material. First you need to make sure that all of your Render States are back to normal after the changes made during the Lighting stage.</p>
<p>To render the materials, you need to re-render every object that was drawn during the Depth + Normals stage, however this time around each object can use its own shader to draw itself, and can take the Light buffer as a texture, which can then be used as the lighting term when shading.</p>
<p>There are numerous effects that can be used to shade an object. In the sample I will only provide a Blinn-Phong shader, however as long as you understand the basic concepts of lighting in modern graphics, you can adapt the lighting values into any other technique that can use them.</p>
<p>This is where I find the big benefits of this technique appear. By allowing the object to choose its own shader/material, you can regain the diverse range of materials that forward rendering allows, providing your artists with plenty of possibilities. Not only that, but you do not have to manage a monster Uber Shader, balancing it against potentially restrictive instruction/texture count limits. (Depending on your Shader Model)</p>
<p>The sample will show how to implement a Blinn-Phong lighting model, with a textured object.</p>
<p>On the other hand, the big negative of this technique appears here as well. You now have to re-render every object a second time. Depending on your scene, this could be a reasonable performance hit. So ensure you weigh up both options when choosing your renderer for your game, and consider what you will need when choosing.</p>
<h3>Transparency/Anti-aliasing</h3>
<p>Transparency and Anti-Aliasing have traditionally been a major problem when it comes to Deferred Rendering. The need to render a Depth buffer has prevented the ability to do any reasonable form of transparency aside from the basic Invisible/Opaque states. There are a few solutions to this issue, although none solve it perfectly.</p>
<ol>
<li>Render your transparent objects using traditional forward rendering, with a limited number of lights, and composite the transparency scene into your deferred scene. </li>
<li>Use stippling to alternate between layers on a high resolution render target. This is used in the recent articles on Inferred Rendering. </li>
<li>Use Order Independent Transparency/Depth Peeling, which can be fairly expensive. (See DX SDK Feb 2010 Samples) </li>
</ol>
<p>I would recommend using option #1 and constructing your scenes so that the only transparent objects are particles, which can be lit with a small number of lights for little to no visual impact.</p>
<p>Anti-Aliasing has also been a problem for Deferred Renderers, primarily because DirectX 9 does not allow for AA with multiple render targets. DirectX 10 allows this, and fixes the issue, however since my target here is XNA, this is not possible.</p>
<p>Traditionally the AA issue was solved by using an Edge Detection filter + Blur to soften the edges of objects, this is relatively cheap and can be implemented as a post processing effect.</p>
<p>However for those interested in taking advantage of the AA modes of modern graphics cards, with very crisp edges, LPP provides a way to have your cake and eat it. (With a small cost)</p>
<p>As there are only 2 Render Targets needed during the Depth + Normals pass, and one at a time after that, you can split that pass up and render the scene an extra time, this time with AA enabled for each step. Of course if you have high scene complexity this might be extremely expensive and not worth it, but the option is there, and it is up to you and the needs of your game.</p>
<h3>Conclusion</h3>
<p>You now have a backbuffer (or Render Target) filled with your shaded scene, ready for further post processing, or presentation to the user. By using this technique you gain the ability to have thousands of lights in your scene at once, which allows level designers and artists to really let loose with their creativity.</p>
<p>Simply having this sheer number of lights also opens up other possibilities for lighting, including fake indirect lighting, a technique that as not been easy to do dynamically. You can assign point lights to every particle in your scene, and really make your worlds much more vibrant.</p>
<p>Also remember that you have a Depth and Normal buffer available for free (you needed it for LPP anyway) for use in post processing, which allows you to add other techniques like SSAO to your game.</p>
<p>Deferred Rendering seems to be the &quot;cool thing” in game graphics today, and with the Compute Shader/OpenCL becoming readily available, some of these techniques can be adapted to make use of the general purpose capabilities of modern graphics cards.</p>
<p>Whilst there are plenty of benefits, there are also negatives to using this technique, and you really need to think about what you want out of your renderer before making your final decision. There have been plenty of debates in the graphics world about whether Deferred Rendering is better than Forward Rendering, and I am not going to go into one of those today.</p>
<h3>Further Reading</h3>
<p>For more information about Deferred Lighting/Light Pre Pass, you can check out the following books/websites:</p>
<ul>
<li><a href="http://diaryofagraphicsprogrammer.blogspot.com/">http://diaryofagraphicsprogrammer.blogspot.com/</a> </li>
<li>Section8, Chapter 5; ShaderX7, Wolfgang Engel, Course Technology [ISBN: 1584505982] </li>
<li><a title="http://www.bungie.net/images/Inside/publications/siggraph/Engel/LightPrePass.ppt" href="http://www.bungie.net/images/Inside/publications/siggraph/Engel/LightPrePass.ppt">http://www.bungie.net/images/Inside/publications/siggraph/Engel/LightPrePass.ppt</a> (SIGGRAPH 2009) </li>
</ul>
<h3>Sample</h3>
<p>I have written a sample implementation of the Deferred Lighting/Light Pre Pass renderer using XNA 3.1. Feel free to learn from this implementation, and if you have any questions, just ask in the comments.</p>
<p>The code provided in the sample is for Academic Use Only, and cannot be copied into a Commercial program.</p>
<p>This sample shows off 6 directional lights around a single model taken from the DirectX SDK. Feel free to add more lights as you please. I have only implemented Directional lights for this sample, to keep things simple. I will provide information on implementing other lights soon, however in the meanwhile feel free to look at my previous (now obsolete) article for a point light implementation, which should be similar.</p>
<p>You can download the sample <a href="http://cid-670fd4ae41402e8a.skydrive.live.com/self.aspx/Public/LPPSample.zip" target="_blank">here</a>.</p>
<p>Controls:</p>
<p>1 : Show Depth Buffer<br />
  <br />2 : Show Normal Buffer </p>
<p>3 : Show Lights Buffer </p>
<p>4 : Show Material Buffer</p>
<p>W : Move Forward<br />
  <br />S : Move Backward </p>
<p>A : Strafe Left </p>
<p>D : Strafe Right </p>
<p>Left Arrow : Rotate Left </p>
<p>Right Arrow : Rotate Right</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/03/light-pre-pass-round-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Blogging from Word 2010</title>
		<link>http://mquandt.com/blog/2010/02/blogging-from-word-2010/</link>
		<comments>http://mquandt.com/blog/2010/02/blogging-from-word-2010/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 04:56:28 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Website]]></category>
		<category><![CDATA[xna]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/02/blogging-from-word-2010/</guid>
		<description><![CDATA[Just trying out the blogging features in Word 2010. Previously I used Live Writer for blogging, however there are some nice features like Insert Screenshot in Word 2010 that I would like to use. I am almost done with the LPP article, just one more section and the sample to finish. If you are interested [...]]]></description>
			<content:encoded><![CDATA[<p>Just trying out the blogging features in Word 2010. Previously I used Live Writer for blogging, however there are some nice features like Insert Screenshot in Word 2010 that I would like to use.
</p>
<p>I am almost done with the LPP article, just one more section and the sample to finish. If you are interested in more timely and fast updates, follow me on twitter: <a href="http://twitter.com/quandtm">@quandtm</a>
	</p>
<p>One thing I am missing from Writer is tag support, if anyone knows how to get it in Word, please let me know; or conversely if you know of a great plugin for automatically taking and inserting screenshots of the desktop for writer, let me know as well. (I know about the snipping tool, I currently use it, but it has a few steps in between that I don&#8217;t really want)</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/02/blogging-from-word-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An update on LPP + Sample</title>
		<link>http://mquandt.com/blog/2010/02/an-update-on-lpp-sample/</link>
		<comments>http://mquandt.com/blog/2010/02/an-update-on-lpp-sample/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 04:48:41 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[xna]]></category>
		<category><![CDATA[game engine gems]]></category>
		<category><![CDATA[game programming gems]]></category>
		<category><![CDATA[gpu pro]]></category>
		<category><![CDATA[light pre pass]]></category>
		<category><![CDATA[sample code]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/02/an-update-on-lpp-sample/</guid>
		<description><![CDATA[Hi everyone, first of all apologies for the delay. there has been quite a lot going on in my life, but I am working hard on getting the sample done. This time around I wanted to make sure I had a sample ready to go with the article, especially since the article will focus on [...]]]></description>
			<content:encoded><![CDATA[<p>Hi everyone, first of all apologies for the delay. there has been quite a lot going on in my life, but I am working hard on getting the sample done. This time around I wanted to make sure I had a sample ready to go with the article, especially since the article will focus on the technique and theory and have little to no code – although I will certainly focus on XNA when it comes to mentioning issues and benefits to certain parts.</p>
<p>One of the main delays was getting the sample code out of my engine, and cleaning it up so it can be used as a learning tool. Unfortunately most of the code was hacked on as I fixed issues in the LPP renderer, and added features.</p>
<p>I have a fair bit of the article written, however recently I was implementing shadows and realised that I never thought about how they would integrate into the system, so I decided to rewrite my own renderer (which should not take long) and at the same time keep the code clean so it can serve as a sample as well.</p>
<p>This means I will probably also have Directional Light shadows in the sample. This then allows me to write about point lights, and spotlights later on, and include shadows for both.</p>
<p>So again, sorry for the delay, I am working hard to get it out soon.</p>
<p>As an aside, I noticed that Game Programming Gems is getting an 8th Edition, something I was not expecting, so with that, GPU Pro, and Game Engine Gems, I might be able to find some more cool things to write about.</p>
<p>Thank You for your patience.</p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/02/an-update-on-lpp-sample/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Robbie Bach Uni Talk</title>
		<link>http://mquandt.com/blog/2010/01/robbie-bach-uni-talk/</link>
		<comments>http://mquandt.com/blog/2010/01/robbie-bach-uni-talk/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 03:37:11 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Students]]></category>
		<category><![CDATA[Xbox 360]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[natal]]></category>
		<category><![CDATA[natural user interfaces]]></category>
		<category><![CDATA[robbie bach]]></category>
		<category><![CDATA[surface]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[xbox 360]]></category>
		<category><![CDATA[zune]]></category>

		<guid isPermaLink="false">http://mquandt.com/blog/2010/01/robbie-bach-uni-talk/</guid>
		<description><![CDATA[Robbie Bach, President of Microsoft’s Entertainment and Devices division is giving a public talk at the University of Sydney on Tuesday 9th February 2010. For any readers who are in Sydney, this would be a great event to attend. E&#38;D covers everything from the XBOX to the Surface, even Keyboards + Mice from MS hardware. [...]]]></description>
			<content:encoded><![CDATA[<p>Robbie Bach, President of Microsoft’s Entertainment and Devices division is giving a public talk at the University of Sydney on Tuesday 9th February 2010.</p>
<p>For any readers who are in Sydney, this would be a great event to attend. E&amp;D covers everything from the XBOX to the Surface, even Keyboards + Mice from MS hardware.</p>
<p>Hopefully there will be a Natal unit on display, and maybe a demo, although no confirmation yet.</p>
<p>RSVP by emailing kumarman[at]microsoft.com</p>
<p>&#160;</p>
<p> <a href="http://mquandt.com/blog/wp-content/uploads/2010/01/SydUniRobbieBachTalk9thFeb.jpg"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="SydUniRobbieBachTalk9thFeb" border="0" alt="SydUniRobbieBachTalk9thFeb" src="http://mquandt.com/blog/wp-content/uploads/2010/01/SydUniRobbieBachTalk9thFeb_thumb.jpg" width="599" height="846" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mquandt.com/blog/2010/01/robbie-bach-uni-talk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
