<?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>Software by Tim Green</title>
	<atom:link href="http://www.tg-software.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tg-software.com</link>
	<description>I&#039;m Tim. I make software.</description>
	<lastBuildDate>Fri, 18 May 2012 08:18:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Ambient Occlusion without black halos</title>
		<link>http://www.tg-software.com/ambient-occlusion-without-black-halos/</link>
		<comments>http://www.tg-software.com/ambient-occlusion-without-black-halos/#comments</comments>
		<pubDate>Fri, 18 May 2012 08:18:15 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[ambient occlusion]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[Guess What You're Dead!]]></category>
		<category><![CDATA[SSAO]]></category>
		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=352</guid>
		<description><![CDATA[You all have seen it. The latest and greatest game comes out, you boot it up, set all graphic options to max, and find that everything has this black border around it. Depending on the game/engine, that black border might gradually smear as things move around. This is most likely the result of screen-space ambient [...]]]></description>
			<content:encoded><![CDATA[<p>You all have seen it. The latest and greatest game comes out, you boot it up, set all graphic options to max, and find that everything has this black border around it. Depending on the game/engine, that black border <a title="Temporal SSAO" href="http://youtu.be/fVvaiQMdHYs" target="_blank">might gradually smear as things move around</a>. This is most likely the result of screen-space ambient occlusion, in one form or another. I have added SSAO to Guess What, You're Dead, but in a much more subtle way. No black smearing messes to be found here! Just a darkening of the ambient light, giving a stronger appearance of depth in dark areas (and to a lesser degree in well-lit areas).</p>
<p>I've posted a new video showing off my SSAO implementation. I think it looks pretty much awesome. Check the video further down. First though, I just want to post some of my thoughts about AO.<br />
<span id="more-352"></span><br />
As I understand it, AO is often applied as a sort of post-process, combining a final render of the screen with the results of an AO pass by simply multiplying one by the other. This means the AO will darken the lighting contributions from all lights in the scene. The trouble, though, is that there's already a couple of things that do that: the standard lighting equation, which lessens the illumination from a light hitting a surface at a glancing angle; and shadows, which lessen/block the illumination from a light when there's something in the way. There's really no need to add an extra occlusion factor to the direct illumination.</p>
<p>Instead, ambient occlusion should be exactly that: occlusion of ambient light. Ambient light is a rough approximation of scattering of light, to give the illusion that even though a light is blocked by some object, some of the light has been scattered in the air and a small amount of it is still able to reach the shadowed area. Since this, in principle, comes from all directions, there is no easy way to cast a proper shadow for it, or adjust the illumination based on surface-light angle. Instead, the amount of light that reaches a point is proportional to the "accessibility" of that point, which is found by firing rays in many directions to see if other surfaces are nearby. This is what AO does.</p>
<p>It makes sense to apply AO to the ambient lighting contributions, rather than applying it to the ambient light <em>and</em> direct illumination from light sources. The end result is that it has much less effect where lights are shining directly on a surface, since the direct illumination far outweighs the ambient light. But, it still takes full effect where there is little to no direct illumination and only ambient light, and this is really where it helps. Especially with my game, where every light casts shadows, the direct illumination already has pretty much all the occlusion it could need (granted, the shadows could be a little more accurate, but whatever). Major crevices are darkened simply because (particularly with higher shadow quality) shadows are sampled at a fairly large range, so a point can easily be occluded. With some adjustments I could have even small creases get shadowed (way back in some of the early videos, I even showed this, the shadows were creating a pseudo-AO-looking effect). When there is little or no direct illumination, then the scene starts to look flat, and that's where AO really shines, showing definition where there is otherwise nothing.</p>
<p>So, that's my little rant about AO. It should occlude ambient light, not everything. Because only the ambient light is otherwise missing any sort of occlusion.</p>
<p>Now, watch the video! As always, you can see all of my videos <a title="Tim Green's Youtube channel" href="http://www.youtube.com/user/TGSoftware" target="_blank"><strong>on my Youtube channel.</strong></a></p>
<p><iframe src="http://www.youtube.com/embed/A6HPJs_jTXw" frameborder="0" width="510" height="289"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/ambient-occlusion-without-black-halos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uploaded a project from school</title>
		<link>http://www.tg-software.com/uploaded-a-project-from-school/</link>
		<comments>http://www.tg-software.com/uploaded-a-project-from-school/#comments</comments>
		<pubDate>Tue, 15 May 2012 03:55:04 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=349</guid>
		<description><![CDATA[I was digging through some of my school stuff today, and dug up one of my projects for a computer modeling class. I've decided to share it, so I added it to the Miscellaneous Projects page here. Go check it out!]]></description>
			<content:encoded><![CDATA[<p>I was digging through some of my school stuff today, and dug up one of my projects for a computer modeling class. I've decided to share it, so I added it to the <a title="Miscellaneous Projects" href="http://www.tg-software.com/miscellaneous-projects/">Miscellaneous Projects</a> page here. Go check it out!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/uploaded-a-project-from-school/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Text, coming soon!</title>
		<link>http://www.tg-software.com/text-coming-soon/</link>
		<comments>http://www.tg-software.com/text-coming-soon/#comments</comments>
		<pubDate>Thu, 10 May 2012 06:47:30 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[fonts]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[Guess What You're Dead!]]></category>
		<category><![CDATA[text rendering]]></category>
		<category><![CDATA[texture packing]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=321</guid>
		<description><![CDATA[I am currently in the process of adding in some text rendering support. XNA comes with some basic support, but it requires me to know ahead of time exactly what fonts and sizes I want, and if I change my mind I need to go in and edit a data file, rebuild, and try again. [...]]]></description>
			<content:encoded><![CDATA[<p>I am currently in the process of adding in some text rendering support. XNA comes with some basic support, but it requires me to know ahead of time exactly what fonts and sizes I want, and if I change my mind I need to go in and edit a data file, rebuild, and try again. Also, it seems to be less-than-optimal as far as performance goes (seems to draw each character as a separate draw call and such).</p>
<p>So, I am using the FreeType library to generate fonts at runtime! Had to write a small wrapper around it so I can use it from my C# code, but it's pretty sweet. Each time I request a character for a given font in a given size, a cache is checked to see if that character has already been used. If it has, then no further work needs to be done. If it's not in the cache, then FreeType will render the character into a memory buffer, and then the character is packed into a giant texture containing all cached characters. While it could probably be better, the packing is pretty tight (it's not just based on a fixed size grid) and works plenty well for right now.</p>
<p><a href="http://www.tg-software.com/text-coming-soon/fonttex1/" rel="attachment wp-att-322"><img class="size-medium wp-image-322 alignleft" style="margin-right: 30px;" title="Packed Fonts" src="http://www.tg-software.com/wp-content/uploads/2012/05/fonttex1-300x300.png" alt="" width="300" height="300" /></a>I don't have text rendering happening yet, but I did run a test on the cache to see how the packed textures are working. To the left you can see the results. This is every typeable character on my keyboard, in 4 font faces (2 fonts, with one of them having regular/bold/italic styles), sizes 12/15/18/21/24/27/30/33. The order the characters were added is as follows:</p>
<ul>
<li>Each font was processed in a fixed order;</li>
<li>For each font, the various sizes were processed in order;</li>
<li>For each size, the characters were added in a shuffled order.</li>
</ul>
<p>I haven't done much testing with different cache orders, but I suspect it may be improved by doing larger fonts first. However, my intention is to just add characters as they are needed, rather than taking a big chunk of time up front populating with characters that may or may not be needed. When building this texture, the rectangles of each character is recorded so that drawing a string of text is as simple as drawing a series of quads, making direct lookups in the font texture. If needed, I may extend the system to allow multiple textures if it fills up. Or, I may allow it to remove characters that have not been used for a while. But, unless I find myself running out of space, it should be fine as-is.</p>
<p>I am planning to allow custom effects to be used when drawing text, with hooks for using more textures and such. This should make for a pretty powerful text rendering system.</p>
<p>If the texture packing system works out well, I am also considering using it (or something like it) to make my sprites a little more manageable. Instead of loading every frame of every animation for every type of sprite into video memory all at once (which is a lot, even using DXT compression), I would keep all that in system memory and then pack just frames I need to draw the scene into one or more (most likely more) dynamic textures. Basically, it would work similar to <a title="MegaTexture Wikipedia article" href="http://en.wikipedia.org/wiki/MegaTexture" target="_blank">Virtual Texturing/Mega Textures</a>, except likely simpler. Of course, that depends on how quickly I can copy data into a texture, since it will be happening quite frequently.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/text-coming-soon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Portal Culling in GWYD</title>
		<link>http://www.tg-software.com/portal-culling-in-gwyd/</link>
		<comments>http://www.tg-software.com/portal-culling-in-gwyd/#comments</comments>
		<pubDate>Sat, 05 May 2012 20:33:10 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[Blender]]></category>
		<category><![CDATA[culling]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[Guess What You're Dead!]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[update]]></category>
		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=317</guid>
		<description><![CDATA[I finally caved an implemented a basic portal culling system in Guess What, You're Dead. I was originally avoiding it because it requires setting up portals and zones throughout a level to make it work... and I wasn't sure how I could leverage Blender to do that in a reasonable fashion. Certainly didn't want to [...]]]></description>
			<content:encoded><![CDATA[<p>I finally caved an implemented a basic portal culling system in <a title="Guess What, You’re Dead!" href="http://www.tg-software.com/windows-games/guess-what-youre-dead/">Guess What, You're Dead</a>. I was originally avoiding it because it requires setting up portals and zones throughout a level to make it work... and I wasn't sure how I could leverage Blender to do that in a reasonable fashion. Certainly didn't want to either switch to a different program for creating the levels (which would require rewriting all my exporters and such), or making a tool for setting up portals.</p>
<p>But, I decided to give it a go! In Blender, I can create "Empties" which are basically a non-object with a transform. I can display them as boxes, sets of axes, cones, spheres, images, whatever. By displaying as a box, I can use an Empty to mark out a rectangular area of space (which I've used for setting initial spawn locations for enemies). This works nicely for setting up the zones for a portal system; it limits each zone to a rectangular shape, but that's not so bad. In addition, I can use Empties to mark portals -- just make them thin. Again, it limits the portals to a rectangular shape, but again not a problem. With a couple custom properties set on each portal, I can have my level all set up for portal culling!</p>
<p>Then, in the game code, it was pretty easy to take those Empty markers, set up the relationships between portals and zones, and do the culling. Drastically lowers the amount of stuff I'm drawing in a frame, without having to go back to the occlusion culling stuff I had before (which didn't work out so hot). So now I can cull objects so less geometry is drawn, as well as lights, so fewer light passes need to be done. Got a pretty nice framerate boost!</p>
<p>I've put up a new video on Youtube showing it off. Check it out below, or <a title="Tim Green's Youtube channel" href="http://www.youtube.com/user/TGSoftware" target="_blank"><strong>on my Youtube channel.</strong></a><br />
<span id="more-317"></span><br />
<iframe src="http://www.youtube.com/embed/IGK1BVnSlCI" frameborder="0" width="510" height="289"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/portal-culling-in-gwyd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Guess What, You&#8217;re Dead!&#8221; Updated!</title>
		<link>http://www.tg-software.com/guess-what-youre-dead-updated/</link>
		<comments>http://www.tg-software.com/guess-what-youre-dead-updated/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 03:18:59 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=312</guid>
		<description><![CDATA[Finally, I've put up a new version of "Guess What, You're Dead!" There's several new things happening in the game: Handy-dandy installer for the game. Run it and it should install everything you need (DirectX, .NET 4, XNA 4, etc). New enemy. This is the subject of my most recent video. Improved performance. I've made [...]]]></description>
			<content:encoded><![CDATA[<p>Finally, I've put up a new version of "Guess What, You're Dead!" There's several new things happening in the game:</p>
<ol>
<li>Handy-dandy installer for the game. Run it and it should install everything you need (DirectX, .NET 4, XNA 4, etc).</li>
<li>New enemy. This is the subject of my most recent video.</li>
<li>Improved performance. I've made several large steps towards better performance in the game. Still not where I want it, and it uses a ridiculous amount of video memory, but it's getting better!</li>
<li>Yeah, that's about it... for now!</li>
</ol>
<p>So, <a title="Guess What, You’re Dead!" href="http://www.tg-software.com/windows-games/guess-what-youre-dead/">head over to the Guess What, You're Dead project page, and download the game</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/guess-what-youre-dead-updated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Forget Occlusion Culling! — or, how I made GWYD faster</title>
		<link>http://www.tg-software.com/article_forget-occlusion-culling/</link>
		<comments>http://www.tg-software.com/article_forget-occlusion-culling/#comments</comments>
		<pubDate>Wed, 18 Apr 2012 05:14:29 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=297</guid>
		<description><![CDATA[In this post, I will discuss some recent work I have done in Guess What, You're Dead! to get it running faster. The gist of it is that I got rid of most of the occlusion culling I had added, and I switched to a deferred renderer.]]></description>
			<content:encoded><![CDATA[<p>In this post, I will discuss some recent work I have done in <em>Guess What, You're Dead!</em> to get it running faster. The gist of it is that I got rid of most of the occlusion culling I had added, and I switched to a deferred renderer.<span id="more-297"></span></p>
<h2>Introduction</h2>
<p>First off, I would like to welcome you to my first article type thing! I hope to write more, documenting some of the techniques I use in my various games, and this is a start. I apologize in advance if it is less-than-coherent! Also, I'm deeply sorry that there aren't any pretty pictures.</p>
<p>Okay, now that that's over with, a little background. I've been working on <em>Guess What, You're Dead!</em> for some time now. Until recently, I used a fairly simple forward renderer. For those who aren't aware, the basic process is this:</p>
<ol>
<li>Make a list of everything that I wanted to draw.</li>
<li>Do an initial depth/ambient pass where I draw everything with a small amount of ambient lighting (constant, directionless illumination that helps prevent absolute blackness in poorly-lit areas)</li>
<li>For each visible light, do the following:</li>
<ol>
<li>If it is a shadow-casting light, generate a shadow map containing all shadow casters within the light's range</li>
<li>Draw all geometry, applying lighting and shadows.</li>
</ol>
</ol>
<p>This worked pretty well but without careful culling of objects, it resulted in a lot more geometry getting sent through the graphics pipeline than was necessary. In addition, since I make extensive use of shadow-casting point lights all over my level, each light that gets drawn must have up to six shadow maps generated. A naive approach, using only frustum culling to eliminate objects and lights that were outside the camera's field of view, would easily result in drawing upwards of 800k triangles each frame for my small ~60k triangle level. My framerates were low and something obviously needed to be done.</p>
<h2>Enter Occlusion Culling</h2>
<p>Because of my level's setup, in any average scene a lot of the objects within the camera's frustum is hidden. Obviously, trying to draw something behind a wall is a waste of effort. So, I decided to add in occlusion culling to eliminate objects and lights that could not be seen. The game uses DirectX 9, so using occlusion queries with predicated rendering was out of the question. I do not like the thought of having to manually place portals or otherwise pre-processing visibility, so that too was out. So, I was left with two options:</p>
<ol>
<li>Use a hardware occlusion query for each object, and grab the results during the next frame when they're ready, or</li>
<li>Get a copy of the current screen's depth information and compare an object against this to determine if it is visible.</li>
</ol>
<p>Delaying visibility determination can have awful consequences, especially with lights. I actually did use this for lights at one point, and turning around quickly or turning around a corner would present you with a lovely dark patch before it realized a light was now visible. This was not acceptable to me, so I was left with one option.</p>
<p>With XNA, I do not read access to the actual depth buffer used for rendering, so I added an extra render pass where I would write out the distance from the camera for each pixel drawn. This would go into a small render target that I could then read into system memory, do some extra work, and then do occlusion tests with it. One immediate issue with this is that reading the render target data immediately after drawing the scene is going to stall the pipeline while the GPU catches up. I hoped that with a simple enough bunch of shaders, and limiting the drawing to specially-flagged objects that were most likely to occlude large parts of the scene, this wouldn't be a problem. Reading the depth information averaged about 7-10ms, which is not so good. I could do my occlusion tests very fast, but not fast enough to make up for the time taken to get the depth data. Even if I delayed the read until the start of the next frame, it still took a very long time, which leads me to believe that just reading texture data in general should not be done.</p>
<p>But all was not lost yet. I could write a simple triangle rasterizer to generate my depth information in software, avoiding the expensive texture read. And so I gave this a try. After a little searching around on the internet, I found what appeared to be a very nice bit of code for it. A short time later, it was implemented, worked mostly perfectly, but was still much too slow. I'm sure I could have sped it up, but it would have taken so long!</p>
<p>So then, what could I do instead of occlusion culling (as I've said, I do not want to put in a portal system or some complex visibility pre-process step)?</p>
<h2>Exit Occlusion Culling</h2>
<p>I deleted all of my occlusion-related code and decided to start fresh. The big problem seems to be that I'm drawing way too much geometry each frame. My level doesn't have very much itself, but because of how many passes were required (between the lighting passes and shadow map generation), it became prohibitively large. If occlusion culling is out, what else could I use to reduce the amount of drawing, as well as filter out lights that will have no effect on the scene?</p>
<p>Well, for the first problem, I have in the past written a deferred shading-based renderer. This has a different process compared to the forward renderer described above:</p>
<ol>
<li>Make list of everything to be drawn.</li>
<li>Draw everything into several render targets, writing information like color, depth, normal direction, specular reflectivity, etc. This collection of render targets is known as a <em>G-Buffer.</em></li>
<li>Render ambient into main render target, by reading the color data from the G-Buffer.</li>
<li>For each visible light:</li>
<ol>
<li>If it's a shadow-caster, generate the shadow map as before</li>
<li>Light the scene by drawing a rectangle covering the area that the light affects, using the data in the G-Buffer to calculate the light contribution.</li>
</ol>
</ol>
<p>With this, and by drawing to multiple render targets in a single pass, the geometry is only drawn a single time. I could split it into two passes, where the first does not write to any render targets but just fills the depth buffer (which could speed the G-Buffer generation up), but in either case it's quite a bit less stuff being drawn.</p>
<p>Unfortunately, this was still not enough. It helped a little, but my framerate was still pretty bad. I was still generating a lot of shadow maps every frame.</p>
<h2>Trading Space for Speed</h2>
<p>It seems that my shadow maps may be causing my performance issues. So, let's look at how that works. I won't go over the actual shadow mapping algorithm here, since that is not relevant. I'll limit the discussion to generation of the shadow maps. For a single point light, it goes something like this:</p>
<ol>
<li>For each face of a cube texture:</li>
<ol>
<li>Create a view/projection matrix to view the screen from the light's position in the direction of that cube map face (±X, ±Y, ±Z).</li>
<li>If the frustum created by this matrix is not visible (does not intersect the main camera's frustum), skip this face.</li>
<li>Make a list of all shadow casters within the light's frustum.</li>
<li>Draw those objects into a shadow map cube texture, writing the distance from the light.</li>
</ol>
</ol>
<p>So the scene gets drawn up to six times for every light within the camera's field of view. Not good!</p>
<p>If you look at the level in <em>GWYD</em>, you'll notice that not much moves. The level is static, the plants don't move, the lights don't move, it's pretty much just the sprites and a few objects. So why should I have to re-draw all this static geometry when it was in the same place last time? What if I rendered anything that doesn't move into a separate <em>cache</em> cube texture, and instead of re-drawing those things every frame, just copy the contents of the cache into the main shadow map and re-draw only objects that could move? Worth a try!</p>
<p>Normally, I just have a single cube texture that gets reused for all lights (actually, I have several of various sizes, but that's not important). Now, I'll need each light to have its own dedicated texture in addition to the one I already have. Now my shadow map creation looks like this:</p>
<ol>
<li>For each face of a cube texture:</li>
<ol>
<li>Create a view/projection matrix to view the screen from the light's position in the direction of that cube map face (±X, ±Y, ±Z).</li>
<li>If the frustum created by this matrix is not visible (does not intersect the main camera's frustum), skip this face.</li>
<li>Copy this face from the light's cached shadow map into the current shadow map texture.</li>
<li>Make a list of all non-static shadow casters within the light's frustum.</li>
<li>Draw those objects into a shadow map cube texture, writing the distance from the light. Use a MIN blend mode.</li>
</ol>
</ol>
<p>Note at the last step there, the use of MIN blending. This is important since when we draw the non-static objects, the depth buffer does not contain any of the static geometry. The use of blending will slow it down a little, but that's a small trade-off compared to not having to draw most of the scene.</p>
<p>So this again helps out quite a bit, but I want to do better. I'm still processing lights that were on the other side of a wall and so have no impact on the rendered scene. How can I stop that?</p>
<h2>Re-enter Occlusion Culling</h2>
<p>Yes, that's right. Occlusion culling! That very thing that I claimed did nothing but harm up above a little ways! But, things have progressed since then, so maybe I can figure something out?</p>
<p>Okay, so the big problem with occlusion queries was that it would result in lights not showing up for a frame or two while the result of the query was made available. Well, what if we don't stop the light from drawing entirely? With the deferred shader, drawing a single light is not very time-consuming; it's just a matter of drawing a single quad, applying standard lighting calculations. Pretty much the only cost is from reading from 4 32-bit textures, but I'd be doing almost the same with the forward renderer to get color, do normal mapping, and possibly a specular/gloss map. So that's no big deal.</p>
<p>The big expense with the lights is generating this stupid shadow map every frame, copying the cached map and then drawing non-static objects. Maybe if I can avoid doing that for non-visible lights (or lights that have just become visible) the short delay won't be noticeable. As it turns out, this seems to be the case! So, when rendering my lights, it now looks something like this:</p>
<ol>
<li>If this light's occlusion query is ready, get the results. The light is not visible if the query reports 0 pixels.</li>
<li>If it's a shadow-caster and is visible according to the latest occlusion query results, generate the shadow map as before</li>
<li>If the light's occlusion query was ready, start a new query.</li>
<li>Light the scene by drawing a rectangle covering the area that the light affects, using the data in the G-Buffer to calculate the light contribution.</li>
<ul>
<li>If the light is visible, use the generated shadow map</li>
<li>If it is not visible, use the cached shadow map filled with static objects</li>
</ul>
<li>End the occlusion query, if we started it.</li>
</ol>
<p>We use the cached shadow map, so that the light will still cast mostly correct shadows for the moment between it showing onscreen and the game registering it as visible.</p>
<p>After making this change, my framerate is finally up closer to where I want it. I would like to still make it better, but I might have to look elsewhere (getting the list of objects to draw into the shadow maps is actually showing a couple milliseconds per frame, so I may be able to improve things with a CPU optimization).</p>
<p>Unfortunately, even with still applying shadows using the cached shadow map, there were some noticeable issues. For example, when the center room becomes visible, there was a short period where the walls would be red, since the falling platforms are not static and so do not block the red lights below from affecting the rest of the room.</p>
<h2>Repurposing the Static Shadow Maps</h2>
<p>The solution to this last issue was pretty simple. While still not perfect, it is a much better approximation with less obvious side effects.</p>
<p>When a light's visibility changes, I trigger a refresh of its cached shadow map. If it is no longer visible, I draw the entire scene into the cached map. If it is visible, I draw only static objects. So now, for that ever-so-brief moment between the light coming on-screen and the light's visibility changing, shadows are cast according to where everything was at the moment the light become hidden. This means the falling platforms will generally cast appropriate shadows, blocking the lights below from shining through.</p>
<p>As I said, it is still not entirely perfect. For example, if a large dynamic object is near the light when it becomes hidden, and is no longer there when the light is shown again, there will be a short time where that large shadow will show up. But, that's a trade-off I am okay with.</p>
<h2>But Wait, Something's Missing!</h2>
<p>The astute reader may have noticed that a not-so-small detail is missing here. With the deferred renderer, I'm drawing a quad for each light within the camera's view. I already have the scene drawn, so there's no depth buffering to allow things to block a light from view (and with XNA, I can't reuse the same depth buffer with a different render target without some trickery). Which means that the occlusion query should always report pixels drawn, just that they'll be black and not contribute any light. So then every light will be visible as long as it's within the camera's frustum. And in that case, we're no better off from the original version.</p>
<p>The easy solution is to discard, in the lighting pixel shader, any pixels that are too far away from the light to be affected. And it turns out this works quite nicely! This also has the effect of making hidden lights faster to draw, since they will have most/all of their pixels discarded before the shader gets to any expensive shadow/lighting calculations.</p>
<h2>The Future</h2>
<p>Although I have made vast improvements compared to where I started, there is still more that I can do.</p>
<p>I just got the book <a title="GPU Pro: Advanced Rendering Techniques" href="http://amzn.com/1568814720" target="_blank">GPU Pro</a>, which has one article of particular interest to me (well, a lot of the articles are interesting, but whatever), discussing a shadow mapping technique for omni-directional lights using a tetrahedron mapping instead of a cube. This would allow me to draw the scene only 4 times for each light instead of 6 to generate the shadow maps. The article also provides a way to pack all faces of the tetrahedron into a single texture (I realize a cube can be mapped onto one 2D texture too, but I did not do that). So that's something I want to look into using.</p>
<p>In addition, I may experiment with using a Light Pre-Pass renderer instead of my current Deferred approach. This adds an extra geometry pass, but cuts the number of intermediate render targets in half (only normals and depth, instead of normals, depth, color, misc material stuff).</p>
<p>In terms of this article (or others like it), I'd like to to put together small code samples demonstrating techniques. Unfortunately, I just don't have the time for that right now.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/article_forget-occlusion-culling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New &#8220;Guess What, You&#8217;re Dead!&#8221; Video</title>
		<link>http://www.tg-software.com/new-guess-what-youre-dead-video/</link>
		<comments>http://www.tg-software.com/new-guess-what-youre-dead-video/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 17:02:36 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[Guess What You're Dead!]]></category>
		<category><![CDATA[update]]></category>
		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=283</guid>
		<description><![CDATA[Been doing some work on Guess What, You're Dead! lately. Ideally, I'd like to see it as a full game, instead of a single-level demo type thing. Some of the things I'm working on (either currently, or planned in the near future): improved performance; more enemies; more weapons; more levels; possibly even more story-oriented gameplay! [...]]]></description>
			<content:encoded><![CDATA[<p>Been doing some work on Guess What, You're Dead! lately. Ideally, I'd like to see it as a full game, instead of a single-level demo type thing. Some of the things I'm working on (either currently, or planned in the near future): improved performance; more enemies; more weapons; more levels; possibly even more story-oriented gameplay!</p>
<p>There's a new GWYD video up on Youtube, showing off the walk cycle for a new enemy I'm working on. The footage for the enemy is already recorded, but I still have the tedious task of splitting out each different animation, making them loop, removing backgrounds, etc.</p>
<p>Also featured in the video, is a quick look at the occlusion culling system I am using for determining potentially visible objects and reducing the amount of geometry I send for rendering. If I can find some, I'd like to write up some articles here about some of the techniques I'm using for various things.<br />
<span id="more-283"></span><br />
Here's the video. <a title="Tim Green's Youtube channel" href="http://www.youtube.com/user/TGSoftware" target="_blank"><strong>You can also check it out, along with the others, on Youtube.</strong></a></p>
<p><iframe src="http://www.youtube.com/embed/Uf_9ypS5D98" frameborder="0" width="510" height="289"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/new-guess-what-youre-dead-video/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Guess What, You&#8217;re Dead! on Youtube</title>
		<link>http://www.tg-software.com/guess-what-youre-dead-on-youtube/</link>
		<comments>http://www.tg-software.com/guess-what-youre-dead-on-youtube/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 04:08:34 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=279</guid>
		<description><![CDATA[While developing "Guess What, You're Dead!" I posted several videos onto Facebook, showing the game at various stages of development. Today I found out how to get those video files back onto my computer, and have posted them to Youtube. Check out my new channel here!]]></description>
			<content:encoded><![CDATA[<p>While developing "Guess What, You're Dead!" I posted several videos onto Facebook, showing the game at various stages of development. Today I found out how to get those video files back onto my computer, and have posted them to Youtube. <a title="Tim Green's Youtube channel" href="http://www.youtube.com/user/TGSoftware" target="_blank">Check out my new channel here!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/guess-what-youre-dead-on-youtube/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Goodbye, iPhone!</title>
		<link>http://www.tg-software.com/goodbye-iphone/</link>
		<comments>http://www.tg-software.com/goodbye-iphone/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 14:21:39 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[iPhone Games]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=273</guid>
		<description><![CDATA[Okay, I guess this post is a little bit late. Like, a year late or something. I stopped renewing my developer status for the iPhone App Store some time ago, so my iPhone games are no longer available on the App Store. At this time I have no plans to renew and get back into [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, I guess this post is a little bit late. Like, a year late or something. I stopped renewing my developer status for the iPhone App Store some time ago, so my iPhone games are no longer available on the App Store.</p>
<p>At this time I have no plans to renew and get back into iPhone development, so those projects are probably dead. But, if people really want to see them again, I might be persuaded to re-make them for PC/Mac. Otherwise, I think I'm working on better games now, so I'll stick with those.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/goodbye-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spam == Boring</title>
		<link>http://www.tg-software.com/spam-boring/</link>
		<comments>http://www.tg-software.com/spam-boring/#comments</comments>
		<pubDate>Fri, 10 Feb 2012 05:50:18 +0000</pubDate>
		<dc:creator>SirTimothy</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[boring]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://www.tg-software.com/?p=267</guid>
		<description><![CDATA[I was just about to sort through my endless list of new spam comments, and decided I'm thoroughly bored of my Spam Comments page. So it's gone now. Much easier to just hit Delete than to censor URLs and such.]]></description>
			<content:encoded><![CDATA[<p>I was just about to sort through my endless list of new spam comments, and decided I'm thoroughly bored of my Spam Comments page. So it's gone now. Much easier to just hit Delete than to censor URLs and such.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tg-software.com/spam-boring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

