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

<channel>
	<title>Sgt. Conker &#187; Occlusion</title>
	<atom:link href="http://www.sgtconker.com/tag/occlusion/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sgtconker.com</link>
	<description>We are &#34;absolutely fine&#34;</description>
	<lastBuildDate>Wed, 06 Jul 2011 13:29:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Article: Lens Flare Occlusion using Texture Masking and XNA</title>
		<link>http://www.sgtconker.com/2010/01/article-lens-flare-occlusion-using-texture-masking-and-xna/</link>
		<comments>http://www.sgtconker.com/2010/01/article-lens-flare-occlusion-using-texture-masking-and-xna/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 18:40:28 +0000</pubDate>
		<dc:creator>Sgt. Conker</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[Lens flare]]></category>
		<category><![CDATA[Occlusion]]></category>

		<guid isPermaLink="false">http://www.sgtconker.com/?p=846</guid>
		<description><![CDATA[by Dave Charlile
Introduction
One of my side projects for the past couple of years has been a realtime fractal planet generator.  It’s a huge project and not one I expect to ever really finish.  But it has provided a great place for me to learn XNA and 3D programming techniques.

One thing every planet generator [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: center;">by <a href="http://www.crappycoding.com">Dave Charlile</a></h4>
<p><strong>Introduction</strong></p>
<p>One of my side projects for the past couple of years has been a realtime fractal planet generator.  It’s a huge project and not one I expect to ever really finish.  But it has provided a great place for me to learn XNA and 3D programming techniques.</p>
<p><span id="more-846"></span><br />
One thing every planet generator needs is a nice bright sun and ubiquitous lens flares.  While the concept of lens flares is fairly simple, one thing that isn’t quite so simple is how to deal with occluding geometry.  For example, if you’re walking around in your world and a hill or mountain comes between you and the sun the lens flares and glowing effects need to be reduced or eliminated depending on how much the light source is occluded by the intervening geometry.</p>
<p>A fairly modern method of doing this involves using hardware occlusion queries to determine how many pixels occlude the sun.  Microsoft has an XNA sample that shows how to use this technique.  It’s fairly straightforward with very few drawbacks, one of which is that your occlusion information is always at least one frame old.  In practice this doesn’t really present much of a problem since you can’t really detect the lens flares fading out a couple frames late.</p>
<p>Another drawback, and one which makes this method unsuitable for my planet generation system, is that it will only work if you draw all of your geometry using a single depth buffer range.  For 99% of games that is fine, but for a planetary system, at least one with accurately sized planets, the depth buffer simply doesn’t have enough precision to work properly.</p>
<p>My solution to the depth buffer issue is to draw the planets farthest to nearest, each with its own full-range depth buffer.  Since planets never overlap (I don’t simulate planetary collisions) nearby planets will always properly occlude far planets.  Because of this I can change znear and zfar and clear the depth buffer before drawing each planet, so each gets the entire depth buffer precision all to itself.  Actually, as you move closer and closer to the planet I also alter znear and zfar even more so the geometry closest to the camera receives the most depth buffer precision.  But that doesn’t really apply to what we’re discussing here.</p>
<p>Since the depth buffer is cleared for each planet, the hardware occlusion query won’t work properly for determining the sun’s occlusion.  This is because the query is counting the number of pixels that pass the depth buffer test.  Now, this applies to only to Windows.  The Xbox 360 occlusion query counts the number of pixels drawn, so that may work even with depth buffer clearing, but since I don’t own an Xbox yet I haven’t been able to test it.  So, for Windows at least, we need a way to do this without caring about the depth buffer.</p>
<p>One solution I thought about was to cast several rays from the camera position towards the sun and check for occluding geometry.  I quickly dismissed it as being way too complex for my old brain and did some Internet searching for other ideas.  I eventually ran across an article from Game Programming Gems 2 that seemed like the perfect solution.  It was also the perfect opportunity for me to move to the next level in my understanding of vertex and pixel shaders and using different render targets.</p>
<p>The remainder of this article discusses my XNA implementation of the ideas presented in the “Texture Masking for Faster Lens Flare” article.  I’ll be modifying Microsoft’s XNA Lens Flare Sample to include both the hardware occlusion query implemented in the original sample application, as well as my texture masking version.  And you’ll be able to switch between the different methods for comparison.</p>
<p><strong>Implementation</strong></p>
<p>Let’s start by downloading and installing the XNA Lens Flare Sample.  Unzip the file to your projects folder and open it up in Visual Studio.  If you’re using XNA 3.x you’ll need to let Visual Studio upgrade the project for you.  Now build it and run it and move around in the world a bit to examine how the lens flare reacts to camera positioning and occluding geometry.</p>
<p>The lens flare in the sample is implemented using a game component.  Open the LensFlareComponent class and skim through the code and comments if you want in order to get a feel for how things are working with the hardware occlusion query technique.  Our implementation is basically a duplicate of this class with the changes we need for the texture masking technique.  But before we get to that let’s walk through what we need to accomplish.</p>
<p>The basic idea is that we need to figure out how much of the sun is visible, and we want to do it entirely on the graphics hardware so we don’t have to pull data back into main memory which can really slow things down. We need to end up with a single value between 0 and 1 that will be used as an alpha value to fade out the sun. To accomplish this we’re going to use render targets, a couple of special shaders, and a “sun camera”.</p>
<p>The sun camera is a camera that has the same location as the normal scene camera, is always pointing at the sun, and is zoomed in so the sun always fills the camera’s entire viewport.  The math for this is fairly simple but we’ll get to that later.  Once we have the camera established we go through the following steps, which we’ll discuss in detail shortly.</p>
<ul>
<li> 1. Enable a 32x32 pixel render target and clear it to white.</li>
<li> 2. Render the scene from the sun camera’s point of view, using a special shader that just writes black pixels.  We’ll end up with a 32x32 image with white pixels where the sun is, and black pixels where the sun is occluded.</li>
<li> 3. Enable a 1x1 render target and clear it to black.</li>
<li> 4. Render the 32x32 image to the 1x1 target using a special shader to count up the white pixels.  This will give us our value between 0 and 1 stored in the pixel in the 1x1 render target.  The more white pixels there are, the closer this value will be to 1, and the brighter the lens flare will be.  If the sun is fully occluded we’ll end up with a value of 0 (all black pixels), and if the sun is fully visible we’ll end up with a value of 1 (all white pixels).</li>
<li> 5. Change back to the normal screen render target and render the scene normally.</li>
<li> 6. Render the lens flare and sun glow using the intensity value in the 1x1 render target in order to fade the flare accordingly.</li>
</ul>
<p>Now let’s go through the steps one by one in detail.  First open up the included sample project in Visual Studio.  Open up the LensFlareComponent2 class and the Game class since we’ll be switching back and forth between the two.</p>
<p>At this time I should point out that I’ll just be going over the major pieces of the code.  Details such as declaring variables will generally be left out.  The sample code is commented pretty well, so if you follow along in the included project files those types of details should be easy to fill in.</p>
<p>Enable a 32x32 pixel render target and clear it to white.</p>
<p>This step is handled by the LensFlareComponent2.IntensityMapBegin() method.</p>
<pre class="brush: csharp; title: ;">
      public void IntensityMapBegin()
      {
        if (!Enabled) return;

        // activate intensity map render target and clear to white
        GraphicsDevice.SetRenderTarget(0, SunRenderTarget);
        GraphicsDevice.Clear(Color.White);

        // disable depth buffer and alpha blending
        GraphicsDevice.RenderState.DepthBufferEnable = false;
        GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
        GraphicsDevice.RenderState.AlphaBlendEnable = false;

        IsValid = false;
      }
</pre>
<p>The first thing we do is set the active render target to SunRenderTarget, which we created in LoadContent() method.  This is a 32x32 render target but you can vary the size if more or less accuracy is required.  The Texture Masking article has us draw the sun to this texture to get our white pixels, but since the idea is for the sun to completely fill the texture, why not just clear it to white and save some draw calls? Also, we don’t care about depth buffer compares, or even writing to the depth buffer, or alpha blending, so we disable those render states.</p>
<p>Render the scene from the sun camera’s point of view</p>
<p>Now imagine a camera pointed directly at the sun, and zoomed in so the sun fills the entire viewport.  If there is anything at all blocking out part of the sun - leaves, trees, rocks, mountains, clouds, whatever - it will be visible from this camera.  Now imagine what the camera is seeing is the 32x32 render target we created previously, and the sun is the white we filled it in with. Now if we draw the rest of the scene using this point of view and write black pixels to the render target wherever we happen to draw something, we’ll end up with an “intensity map” that shows white where sunlight can shine through, and black where it’s occluded by something.  For example:</p>
<p><img class="alignnone size-full wp-image-847" title="lens1" src="http://www.sgtconker.com/wp-content/uploads/2010/01/lens1.png" alt="lens1" width="256" height="256" /></p>
<p>The code to draw to the render target is in Game.DrawTerrainIntensityMap().</p>
<pre class="brush: csharp; title: ;">
        private void DrawTerrainIntensityMap()
        {
          // the sample terrain model is rotated 90 degrees, so we need to do the same rotation
          // manually since we're using our own effect
          Matrix Rotation = Matrix.CreateRotationX(MathHelper.ToRadians(-90.0f));

          // create world view projection matrix based on the sun camera
          Matrix WorldViewProjection = Rotation * lensFlare2.SunView * lensFlare2.SunProjection;

          // draw each model mesh
          foreach (ModelMesh mesh in terrainIntensityMap.Meshes)
          {
            // set shader parameters for each effect instance in the mesh
            foreach (Effect effect in mesh.Effects)
            {
              effect.Parameters[&quot;WorldViewProj&quot;].SetValue(WorldViewProjection);
              effect.Parameters[&quot;Color&quot;].SetValue(0.0f);
              effect.Parameters[&quot;Alpha&quot;].SetValue(1.0f);
            }

            // draw the mesh
            mesh.Draw();
          }
        }
</pre>
<p>The sample terrain model is rotated 90 degrees, so we need to handle that first by creating a rotation matrix.  Next we create the WorldViewProjection matrix which is a concatenation of the rotation matrix and the sun camera’s view and projection matrices.  These are the matrices that give us the sun camera’s point of view, and we’ll discuss how to create them later.  Next we go through each of the meshes in the terrain model and set the effect parameters for each effect.  And finally we draw the each mesh.</p>
<p>Basically we need to do everything we’d normally do to draw the scene for the current frame, but from the sun camera’s point of view.  In a more robust implementation we’d likely want to cull the scene to the sun camera’s view frustum.  We could also draw a much less detailed version of the scene, using lower resolution models for example.  We just need to end up with a fairly decent approximation of what the sun camera sees when it’s looking at the sun.</p>
<p>Now, when we’re drawing the scene here we’re not using our normal shaders.  Instead we use a shader that just writes black pixels.</p>
<pre class="brush: csharp; title: ;">
float4x4 WorldViewProj;
float3 Color;
float Alpha;

struct VertexInput
{
  float4 Position : POSITION0;
};

struct VertexOutput
{
  float4 Position : POSITION0;
};

VertexOutput VertexShader(VertexInput i)
{
  VertexOutput o = (VertexOutput) 0;

  o.Position = mul(i.Position, WorldViewProj);

  return o;
}

float4 PixelShader() : COLOR0
{
  return float4(Color.rgb, Alpha);
}
</pre>
<p>The vertex shader takes in a vertex, multiplies it by the WorldViewProjection matrix to get the screen coordinates, and passes it to the pixel shader.  The pixel shader simply returns the color using the Color and Alpha values that are set by the application.  In this case Color is black, and Alpha is 1.  This has the effect of drawing in black everything that’s thrown at it.</p>
<p>Enable a 1x1 render target and clear it to black.</p>
<p>Now that we have our intensity map we need to determine what percentage of it is white.  We’re going to do that by counting the white pixels.  But first we need a place on the GPU to store the result, and that is the purpose of the 1x1 render target.  This functionality takes place in the LensFlareComponent2.IntensityMapEnd() method.</p>
<pre class="brush: csharp; title: ;">
        // switch to the 1x1 render target which will hold the results
        GraphicsDevice.SetRenderTarget(0, IntensityRenderTarget);
        GraphicsDevice.Clear(Color.Black);

        // disable depth buffer - we want to write out every pixel, and we have no need to update depth
        GraphicsDevice.RenderState.DepthBufferEnable = false;
        GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
</pre>
<p>First we set the render target to IntensityRenderTarget which we created in the LoadContent() method.  This is a floating point render target with the HalfSingle format.  Next we clear it to black because we want to start it out at 0.  Finally, we don’t need or want the depth buffer since we’re going to write out every single pixel, so we disable that as well.</p>
<p>Render the 32x32 image to the 1x1 target using a special shader to count up the white pixels.</p>
<p>The next step is adding up all the white pixels in the 32x32 intensity map, and storing the result in the single pixel in the 1x1 render target.  We can do this using another special shader and alpha blending.  Alpha blending takes a source color and blends it with a target color.  There are several ways of blending the colors that serve different purposes.  We want to add up color values, so we’ll set the blend operation to BlendFunction.Add, and the source blend and destination blend values to Blend.One.  This tells the GPU to take the source color and add it to the target color.  The source color in this case is a pixel from the intensity map, and the target is the single pixel in the 1x1 render target.</p>
<pre class="brush: csharp; title: ;">
        // this is a key part of the process - the pixel shader will return 0 for black pixels and
        // 1/(32x32) for white pixels.  We want to add up all those white pixels, and we can use
        // alpha blending to add the new pixel value to the existing pixel value.
        GraphicsDevice.RenderState.AlphaBlendEnable = true;
        GraphicsDevice.RenderState.AlphaBlendOperation = BlendFunction.Add;
        GraphicsDevice.RenderState.SourceBlend = Blend.One;
        GraphicsDevice.RenderState.DestinationBlend = Blend.One;
</pre>
<p>Now we’re going to render a bunch of vertices - one for each pixel in the intensity map.  We’ve created this list of points by calling GenerateOcclusionPoints() in the LoadContent() method.  Each point has the required vertex position, which we don’t care about so it’s always 0, followed by a texture coordinate.  The texture coordinate points to the appropriate pixel in the intensity map.  To rephrase a bit - each vertex points to one of the pixels in the intensity map - 32x32 vertices, 32x32 pixels.  Once the list of points is set up it’s then used to create a vertex buffer.  Back to IntensityMapEnd(), we tell the GPU to use the vertex buffer.</p>
<pre class="brush: csharp; title: ;">
        // set up for the vertices we'll be processing
        GraphicsDevice.VertexDeclaration = IntensityMapVertexDeclaration;
        GraphicsDevice.Vertices[0].SetSource(OcclusionPoints, 0, VertexPositionTexture.SizeInBytes);
</pre>
<p>We now need to set up a couple of parameters for the shader.</p>
<pre class="brush: csharp; title: ;">
       IntensitySumEffect.Parameters[&quot;Source&quot;].SetValue(SunRenderTarget.GetTexture());
       IntensitySumEffect.Parameters[&quot;Scale&quot;].SetValue(1.0f / (float)(MapSize * MapSize));
</pre>
<p>The Source texture is the 32x32 intensity map.  The Scale tells the shader how much a white pixel is worth.  For example, if we’re using a 32x32 source texture then there are 32 * 32, or 1024 pixels in the image.  Each white pixel has a value of 1, so if we had an entirely white intensity map we’d end up with a value of 1024 when adding up all the pixels.  But we need a value of 1 in this case, representing full intensity.  So instead of counting white as 1, we need to count it as 1/1024.  When adding up 1024 white pixels we then get a value of 1024/1024, or 1.  So, again, the Scale parameter tells the shader the value of a white pixel - in this case 1/(32*32), or 1/1024.</p>
<p>Finally, we execute the shader.</p>
<pre class="brush: csharp; title: ;">
        // run the shader to add up the white pixels
        IntensitySumEffect.Begin();
        IntensitySumEffect.CurrentTechnique.Passes[0].Begin();

        GraphicsDevice.DrawPrimitives(PrimitiveType.PointList, 0, MapSize * MapSize);

        IntensitySumEffect.CurrentTechnique.Passes[0].End();
        IntensitySumEffect.End();
</pre>
<p>We tell the GPU to treat the OcclusionPoints vertex buffer as a list of points, and that there are 1024 of them.  Now let’s take a look at the shader.</p>
<pre class="brush: csharp; title: ;">
float Scale;
texture Source;

sampler MapSampler = sampler_state {
  texture = &lt;Source&gt;;
  magfilter = POINT;
  minfilter = POINT;
  mipfilter = NONE;
};

struct VertexInput
{
  float4 Position : Position;
  float2 Texture : TexCoord0;
};

struct VertexOutput
{
  float4 Position : Position;
  float2 Texture : TexCoord0;
};

VertexOutput VertexShader(VertexInput i)
{
  VertexOutput o;
  o.Position = float4(-1.0, 1.0, 0, 1);  // we’re outputting a single pixel, so always return that pixel in clip space
  o.Texture = i.Texture;

  return o;
}

float4 PixelShader(float2 T : TEXCOORD0) : COLOR0
{
  return tex2D(MapSampler, T) * Scale;
}
</pre>
<p>Note that the texture sampler is using POINT for minfilter and magfilter, and no mipmap filter.  We want the raw unfiltered pixel data here.</p>
<p>The pixel shader is always outputting to the same pixel in the 1x1 render target. The clip space coordinate for this is -1, 1, so the vertex shader always returns this as the position.  The texture coordinates are passed through to the pixel shader.</p>
<p>The pixel shader samples the 32x32 intensity map at the appropriate coordinates.  This will give us a color of 0 or 1.  We multiply that value by the Scale factor (1/1024), set the alpha value to 1 and return that value.  In other words, the pixel shader will return a color of either 0 or 1/1024.</p>
<p>After this the alpha blending unit takes over and adds the color to the current value in the render target pixel.   When all 1024 source pixels have been processed we have the sum of the white pixels stored in the 1x1 target!</p>
<p>Change back to the normal screen render target and render the scene normally.</p>
<p>Back in IntensityMapEnd(), we switch back to the main render target and get the 1x1 texture for use in the next and final step.</p>
<pre class="brush: csharp; title: ;">
        // switch back to the main render target and grab the new intensity texture
        GraphicsDevice.SetRenderTarget(0, null);
        IntensityTexture = IntensityRenderTarget.GetTexture();
</pre>
<p>Finally at the end of the method any render states that were messed with are restored and control returns back to the caller which now needs to the render the scene normally.</p>
<p>Let’s take a quick look at Game.Draw() to see how this fits together so far.</p>
<pre class="brush: csharp; title: ;">
        protected override void Draw(GameTime gameTime)
        {
          GraphicsDevice.RenderState.CullMode = CullMode.None;

          // draw intensity map
          if (NewFlare)
          {
            lensFlare2.IntensityMapBegin();
            DrawTerrainIntensityMap();
            lensFlare2.IntensityMapEnd();
          }

          // draw terrain
          GraphicsDevice.Clear(Color.CornflowerBlue);
          DrawTerrain();

          // flares are game components so they get drawn as part of the main draw
          base.Draw(gameTime);
        }
</pre>
<p>What we’ve covered up to this point is in red.  IntensityMapBegin() switches to the 32x32 render target.  DrawTerrainIntensityMap() uses the sun camera to draw black pixels to the render target.  IntensityMapEnd() counts up the white pixels and stores them in the 1x1 render target.<br />
Finally we clear the device and draw the scene like normal.</p>
<p>Render the lens flare and sun glow using the intensity value in the 1x1 render target.</p>
<p>So, how does the lens flare draw itself?  Part of base.Draw() loops through all drawable game components and calls the Draw() method for each.  The biggest change in the flare drawing involves using the intensity value.  We do this using a custom sprite batch pixel shader.</p>
<pre class="brush: csharp; title: ;">
float4 Color;

sampler SpriteSampler : register(s0);    // texture the sprite batch is drawing
sampler IntensitySampler : register(s1); // 1x1 intensity texture

float4 PixelShader(float2 texCoord : TEXCOORD0) : COLOR0
{
  // sample the sprite texture
  float4 SpriteColor = tex2D(SpriteSampler, texCoord);

  // sample the intensity value from the 1x1 texture
  float4 Intensity = tex2D(IntensitySampler, float2(0.5, 0.5));

  // use the sampled intensity value as the alpha channel
  SpriteColor.a *= Intensity;

  // combine with shading color
  SpriteColor *= Color;

  return SpriteColor;
}
</pre>
<p>First we sample the sprite texture, then the top left texel of the intensity map.  The sprite color alpha is multiplied by the intensity value, and then then by the shading color.</p>
<p>Finally a quick look at the LensFlareComponent2.DrawGlow() method to show how the shader is used.</p>
<pre class="brush: csharp; title: ;">
         spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);

          GraphicsDevice.Textures[1] = IntensityTexture;
          IntensityFlareEffect.Parameters[&quot;Color&quot;].SetValue(color);
          IntensityFlareEffect.Begin();
          IntensityFlareEffect.CurrentTechnique.Passes[0].Begin();

          spriteBatch.Draw(glowSprite, lightPosition, null, new Color(color), 0,
                           origin, scale, SpriteEffects.None, 0);

          IntensityFlareEffect.CurrentTechnique.Passes[0].End();
          IntensityFlareEffect.End();

          spriteBatch.End();
</pre>
<p>After beginning the sprite batch the intensity texture is assigned to texture channel 1 and the shading color set to white (no shading).  We then draw the sun glow sprite and end the batch.  That’s all there is to it.</p>
<p>One Final Detail</p>
<p>I promised earlier to go over the math involved in setting up the sun camera to point at the sun and zoom so the sun fills the viewport.  So, here goes.  All of these calculations are done in Game.Update().</p>
<p>The sun camera “look at” matrix is straightforward.</p>
<pre class="brush: csharp; title: ;">SunView = Matrix.CreateLookAt(CameraPosition, LightPosition, Vector3.Up);</pre>
<p>The camera has the same position as the main camera, so we want to look from that position toward the light.  See, straightforward.</p>
<p>The projection matrix is where the fun starts.  We know the aspect ratio is 1 since we’re looking at a square area, but we also need the proper field of view angle so we’re zoomed in properly.</p>
<p><img class="alignnone size-medium wp-image-848" title="lens2" src="http://www.sgtconker.com/wp-content/uploads/2010/01/lens2-300x93.png" alt="lens2" width="300" height="93" /></p>
<p>C is the center of the sun, O is a point on the edge of the sun where the angle at C is a right angle, and E is the camera (eye) position, which we assume to be zero.  If we normalize O and C so they’re unit vectors, their dot product gives us the cosine of the angle at E.  Taking the inverse of the cosine gives us the actual angle.  But, that’s really only half the angle because we want to be viewing the entire sun.  Multiplying it by 2 gives us the full field of view angle required to have the sun fill up the viewport.</p>
<p>Once we have that angle, creating the projection matrix becomes:</p>
<pre class="brush: csharp; title: ;">double Angle = 2.0 * Math.Acos(Vector3.Dot(SunCenter, SunOuter));
      SunProjection = Matrix.CreatePerspectiveFieldOfView((float)Angle, 1.0f, 0.1f, 20000.0f);</pre>
<p>The near and far plane distances aren’t too important since we’re not doing anything with the depth buffer.  There’s probably a better way to do this, but this is the brute force approach I came up with and it works well enough.</p>
<p>Sample Code</p>
<p>The sample code includes the entire LensFlareComponent2 class as well as well as some simple terrain.  You can move around with the WASD keys, rotate the camera with the arrow keys, and use the F key to toggle between the new lens flare and the original Microsoft sample that uses hardware occlusion queries.  The original sample code was released under the Microsoft Permissive License.</p>
<p><a href="http://www.sgtconker.com/Downloads/articles/lensflareocclusion.zip">Download Sample Project</a></p>
<p>Conclusion<br />
It’s been a long ride to make it this far.  I hope this was helpful in demonstrating not only a useful occlusion technique, but also how powerful shaders can be.   Using a shader to output data to a texture, then using that texture as input to another operation - the possibilities this opens up are limitless.</p>
<p>References</p>
<p>Maughan, Chris. 2001. "Texture Masking for Faster Lens Flare." In Game Programming Gems 2, edited by Mark DeLoura, pp. 474–480. Charles River Media.<br />
<a href="http://creators.xna.com/en-US/sample/lensflare"> XNA Lens Flare Sample</a><br />
<a href="www.opensource.org/licenses/ms-pl.html"> Microsoft Permissive License</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sgtconker.com/2010/01/article-lens-flare-occlusion-using-texture-masking-and-xna/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

