<?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>CodeItNow &#187; General</title>
	<atom:link href="http://www.rorydriscoll.com/category/general/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rorydriscoll.com</link>
	<description></description>
	<lastBuildDate>Mon, 23 Jan 2012 01:50:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Derivative Map Artifacts</title>
		<link>http://www.rorydriscoll.com/2012/01/22/derivative-map-artifacts/</link>
		<comments>http://www.rorydriscoll.com/2012/01/22/derivative-map-artifacts/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 01:50:36 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=1070</guid>
		<description><![CDATA[I had been suffering from some strange artifacts on the edges of my objects when using derivative maps. After much time spent in GPU Perf Studio, I finally realised that my mipmap generation was not correct. It was introducing one extra column of garbage at every level. My use of FXAA and anisotropic filtering was [...]]]></description>
			<content:encoded><![CDATA[<p>I had been suffering from some strange artifacts on the edges of my objects when using derivative maps. After much time spent in GPU Perf Studio, I finally realised that my mipmap generation was not correct. It was introducing one extra column of garbage at every level.</p>
<p>My use of FXAA and anisotropic filtering was just making the problem more evident. I would recommend using regular trilinear filtering for derivative maps anyway.</p>
<p>So, mea culpa and all that. Let the name of Morten Mikkelsen and derivative maps be cleared!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2012/01/22/derivative-map-artifacts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Derivative Maps vs Normal Maps</title>
		<link>http://www.rorydriscoll.com/2012/01/15/derivative-maps-vs-normal-maps/</link>
		<comments>http://www.rorydriscoll.com/2012/01/15/derivative-maps-vs-normal-maps/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 03:41:52 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=1012</guid>
		<description><![CDATA[This post is a quick follow up to my previous post on derivative maps. This time I&#8217;m going to compare the quality and performance of derivative maps with the currently accepted technique, normal maps. I&#8217;ll be using the precomputed derivative maps for comparison since the ddx/ddy technique just isn&#8217;t acceptable in terms of quality. Quality [...]]]></description>
			<content:encoded><![CDATA[<p>This post is a quick follow up to my <a href="http://www.rorydriscoll.com/2012/01/11/derivative-maps/">previous post</a> on derivative maps. This time I&#8217;m going to compare the quality and performance of derivative maps with the currently accepted technique, normal maps.</p>
<p>I&#8217;ll be using the precomputed derivative maps for comparison since the ddx/ddy technique just isn&#8217;t acceptable in terms of quality.</p>
<h2>Quality</h2>
<p>Here&#8217;s the close up shot of the sphere with the moon texture again. This shows the derivative map implementation, and if you mouse over, you&#8217;ll see the normal map version.</p>
<p><img class="mouseover aligncenter size-full wp-image-1018" title="Moon texture comparison" src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/DerivativeMapCompare.png" alt="" width="512" height="512" data-oversrc="http://www.rorydriscoll.com/wp-content/uploads/2012/01/NormalMapCompare.png" /></p>
<p>There are some slight differences because the height of the derivative map doesn&#8217;t quite match the heights used to precompute the normal map, but overall I would say that they are remarkably similar. It looks to me that the normal map is preserving more of the detail though.</p>
<p>Here&#8217;s a high-contrast checkerboard, again with the normal map shown if you mouse over.</p>
<p><img class="mouseover aligncenter size-full wp-image-1022" title="Checkerboard texture comparison" src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/DerivativeMapContrast.png" alt="" width="512" height="512" data-oversrc="http://www.rorydriscoll.com/wp-content/uploads/2012/01/NormalMapContrast.png" /></p>
<p>I&#8217;m no artist, but I would say the the derivative map results are close enough to the normal maps to call the technique viable from a quality standpoint.</p>
<table border="0" bordercolor="#FFCC00" style="background-color:#CCCCCC" width="90%" cellpadding="3" cellspacing="3">
<tr>
<td>
<strong>EDIT:</strong> I had some issues with artifacts which I posted here. It turns out they were (embarrassingly) caused by my mipmap generation which was introducing a row of garbage at each level. Combined with FXAA and anisotropic filtering, this caused the weird vertical stripes I posted before.</p>
<p>I&#8217;ve removed the images since I don&#8217;t want to give the wrong impression of the quality of derivative maps.
</td>
</tr>
</table>
<h2>Performance</h2>
<p>I ran these tests on my Macbook Pro which has an AMD 6750M. The shader in question is a simple shader for filling out the gbuffer render targets. All shaders were compiled using shader model 5. I took the frame times from the Fraps frame counter and the other numbers came from Gpu Perf Studio.</p>
<p>For comparison, I&#8217;ve included an implementation with no normal perturbation at all.</p>
<table class="gridtable">
<tbody>
<tr>
<th><strong>Perturbation</strong></th>
<th><strong>Frame</strong></th>
<th><strong>Pixels</strong></th>
<th><strong>Tex Inst</strong></th>
<th><strong>Tex Busy</strong></th>
<th><strong>ALU Inst</strong></th>
<th><strong>ALU Busy</strong></th>
<th><strong>ALU/Tex</strong></th>
</tr>
<tr>
<td>None</td>
<td>1.08 ms</td>
<td>262144</td>
<td>3</td>
<td>27.5 %</td>
<td>14</td>
<td>32.1 %</td>
<td>4.667</td>
</tr>
<tr>
<td>Normal map</td>
<td>1.37 ms</td>
<td>262144</td>
<td>4</td>
<td>36.5 %</td>
<td>23</td>
<td>52.4 %</td>
<td>5.75</td>
</tr>
<tr>
<td>Derivative map</td>
<td>1.36 ms</td>
<td>262144</td>
<td>9</td>
<td>82.0 %</td>
<td>28</td>
<td>63.8 %</td>
<td>3.11</td>
</tr>
</tbody>
</table>
<p>Despite the extra shader instructions, the derivative map method is basically as fast as normal maps on my hardware. As Mikkelsen predicted, it seems like having one fewer vertex attribute interpolator offsets the cost of the extra ALU instructions.</p>
<p>Note that the derivative map shader has nine texture instructions compared to just four for the normal maps. The extra five instructions are the two sets of ddx/ddy instructions, and the instruction to get the texture dimensions. The pixel shader can issue one texture instruction and one ALU instruction on the same cycle, these are essentially free.</p>
<p>The only performance overhead which has any impact for derivative maps are the five extra ALU instructions.</p>
<h2>Memory</h2>
<p>As I mentioned in my previous post, derivative maps also have the tremendous benefit of not requiring tangent vectors. In my case, with a simple vertex containing position, normal, tangent and one set of texcoords, the tangent takes up 27% of the mesh space.</p>
<p>Given that most games these days have tens of megabytes of mesh data, this would turn into some pretty decent memory savings. There&#8217;s also a minor benefit on the tool-side to not having to spend time generating face tangents and merging them into the vertices.</p>
<h2>Conclusion</h2>
<p>Well, for me it&#8217;s pretty clear. On my setup, derivative maps have a similar quality with the same performance but less memory. This makes them a win in my book. Of course, these numbers will vary wildly based on the API and hardware, so this can&#8217;t be taken as a blanket &#8216;derivative maps are better than normal maps&#8217; statement, but they look promising. Good job Morten Mikkelsen!</p>
<p>I would love to see a similar comparison for the current generation of console hardware (hint, hint!).</p>
<p>If you have DirectX 11, then you should be able to run the demo <a href='http://www.rorydriscoll.com/wp-content/uploads/2012/01/DerivativeMaps.zip'>here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2012/01/15/derivative-maps-vs-normal-maps/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Cubemap Texel Solid Angle</title>
		<link>http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/</link>
		<comments>http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 21:42:18 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=759</guid>
		<description><![CDATA[Warning: This post is going to be pretty math heavy. If you suck at math, then go and read this first, then come back. If you still think that you suck, then I suggest going to Khan Academy and start watching videos. You won&#8217;t regret it! I was reading through the AMD CubeMapGen source last [...]]]></description>
			<content:encoded><![CDATA[<table width="90%" align="center" cellpadding="10" cellspacing="1" bgcolor="#f7f7f7" border="0">
<tr>
<td>
<b>Warning:</b> This post is going to be pretty math heavy. If you suck at math, then go and read <a href="http://www.thebestpageintheuniverse.net/c.cgi?u=math">this</a> first, then come back. If you still think that you suck, then I suggest going to <a href="http://www.khanacademy.org/">Khan Academy</a> and start watching videos. You won&#8217;t regret it!
</td>
</tr>
</table>
<p>I was reading through the <a href="http://code.google.com/p/cubemapgen/">AMD CubeMapGen source</a> last week and came across the code for calculating the solid angle of a cube map texel. This code piqued my interest, since it seemed very terse for what I thought would be a horrific calculation.</p>
<pre class="brush: cpp; title: ; notranslate">
static float32 AreaElement( float32 x, float32 y )
{
	return atan2(x * y, sqrt(x * x + y * y + 1));
}

float32 TexelCoordSolidAngle(int32 a_FaceIdx, float32 a_U, float32 a_V, int32 a_Size)
{
   //scale up to [-1, 1] range (inclusive), offset by 0.5 to point to texel center.
   float32 U = (2.0f * ((float32)a_U + 0.5f) / (float32)a_Size ) - 1.0f;
   float32 V = (2.0f * ((float32)a_V + 0.5f) / (float32)a_Size ) - 1.0f;

   float32 InvResolution = 1.0f / a_Size;

	// U and V are the -1..1 texture coordinate on the current face.
	// Get projected area for this texel
	float32 x0 = U - InvResolution;
	float32 y0 = V - InvResolution;
	float32 x1 = U + InvResolution;
	float32 y1 = V + InvResolution;
	float32 SolidAngle = AreaElement(x0, y0) - AreaElement(x0, y1) - AreaElement(x1, y0) + AreaElement(x1, y1);

	return SolidAngle;
}
</pre>
<p>The source code for this particular part is well documented, and points you towards <a href="http://www.fizzmoll11.com/thesis/thesis.pdf">this thesis</a> by Manne &Ouml;hrstr&ouml;m (<a href="https://twitter.com/#!/manneohrstrom">@manneohrstrom</a>) where he gives a high level overview of the derivation. I was interested in finding out some more of the details, so I had a go myself, and this post is the result.</p>
<h2>Why is it Useful?</h2>
<p><a href="http://www.rorydriscoll.com/wp-content/uploads/2012/01/FilteredEnvMap.png"><img src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/FilteredEnvMap.png" alt="" title="FilteredEnvMap" width="196" height="196" class="alignright size-full wp-image-979" /></a></p>
<p>When processing cube maps (for example, generating a diffuse irradiance map, or spherical harmonic approximation), you need to be able to integrate the texel values over a sphere. </p>
<p>One way of approximating this integral is to use a Monte Carlo estimator. This is a statistical technique that may oversample some texels and undersample other. This seems a bit wasteful considering that we have a finite number of input values. Ideally we&#8217;d like to use each texel value just once.</p>
<p>A naive approach to analytical integration where each texel has the same weight would result in overly bright values in the corner areas. This is because the texels in the corners project to smaller and smaller areas on the sphere. The correct approach is to factor in the solid angle during the integral, and this is what CubeMapGen does.</p>
<h2>The Plan</h2>
<p>Imagine a single cube map face placed at (0,0,1) and scaled such that the texel locations are all in [-1,1]. For any texel in this cube map, we want to project it onto a unit sphere sitting at the origin, then work out the area on the sphere. This area corresponds to the solid angle because the sphere is a unit sphere.</p>
<p>We can repeat this same calculation for any of the other cube map faces by first transforming them into the same range. </p>
<p><a href="http://www.rorydriscoll.com/wp-content/uploads/2012/01/TexelProjection.png"><img src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/TexelProjection.png" alt="" title="TexelProjection" width="400" height="410" class="aligncenter size-full wp-image-870" /></a></p>
<p>This is the high-level game plan for calculating out the solid angle:</p>
<ol>
<li>Determine a formula for projecting a position from texture-space onto the sphere.</li>
<li>Work out how this projected position changes as the texture-space coordinates change in x and y.</li>
<li>Imagining that these position change vectors define two sides of a microscopic quadrilateral, then calculate the microscopic area of this quad using the magnitude of the cross product.</li>
<li>Integrate the microscopic area using the corner coordinates of a texel to calculate its area on the sphere, and solid angle.</li>
</ol>
<h2>The Details</h2>
<p>We start off with the formula for projecting a point from its location on the texture face (x, y, 1) onto the unit sphere. This is just a standard vector normalization.</p>
<p class="ql-center-displayed-equation" style="line-height: 50px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-daa796d4ca2f5ee61899317d00838d61_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#118;&#101;&#99;&#123;&#112;&#125;&#32;&#61;&#32;&#92;&#100;&#102;&#114;&#97;&#99;&#123;&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#120;&#44;&#32;&#121;&#44;&#32;&#49;&#32;&#92;&#101;&#110;&#100;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<table width="90%" align="center" cellpadding="10" cellspacing="1" bgcolor="#f7f7f7" border="0">
<tr>
<td>
<b>Note:</b> I&#8217;ll be switching back and forth between negative and fractional exponents as I see fit. This makes things easier. Remember, <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-c9beaf5c04427d6698cf1443a55c3147_l3.png" class="ql-img-inline-formula" alt="&#120;&#94;&#123;&#45;&#110;&#125;&#32;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#120;&#94;&#110;&#125;" title="Rendered by QuickLaTeX.com" style="vertical-align: -6px;"/>, and <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-fb697885f9d30c8a2d88d78798d88e16_l3.png" class="ql-img-inline-formula" alt="&#120;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#125;&#125;&#32;&#61;&#32;&#92;&#115;&#113;&#114;&#116;&#123;&#120;&#125;" title="Rendered by QuickLaTeX.com" style="vertical-align: -4px;"/>.
</td>
</tr>
</table>
<p>We want to calculate how this projected point changes as the texture-space x and y coordinates change. We can do this separately for each axis using partial derivatives. First we&#8217;ll start by calculating how the projected z component changes along to the texture-space x axis.</p>
<h3>Projected Z Change According to X</h3>
<p>The z-component of p is simply:</p>
<p class="ql-center-displayed-equation" style="line-height: 73px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-6281591c71b267a0c150f46b50d87b3d_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#112;&#95;&#122;&#32;&#38;&#61;&#32;&#92;&#100;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#125;&#125;&#92;&#92; &#38;&#61;&#32;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>We need to differentiate this equation with respect to x. Because of the exponent, we need to use the chain rule to do this. The chain rule is a method for finding the derivative of the composition of two functions. First, we can reformulate the equation a little bit to make the two functions a bit clearer:</p>
<p class="ql-center-displayed-equation" style="line-height: 23px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-31f684ea7c54bd03992ea5baf43c43db_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#112;&#95;&#122;&#32;&#61;&#32;&#117;&#94;&#123;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#125;&#125;&#44;&#32;&#117;&#32;&#61;&#32;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>In our case our first function is a function of <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-43fe27dc3e528266a619764d90fce60b_l3.png" class="ql-img-inline-formula" alt="&#117;" title="Rendered by QuickLaTeX.com" style="vertical-align: 0px;"/> and our second function is a function of <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-ede05c264bba0eda080918aaa09c4658_l3.png" class="ql-img-inline-formula" alt="&#120;" title="Rendered by QuickLaTeX.com" style="vertical-align: 0px;"/> and <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-0af556714940c351c933bba8cf840796_l3.png" class="ql-img-inline-formula" alt="&#121;" title="Rendered by QuickLaTeX.com" style="vertical-align: -4px;"/>. Given this, the chain rule says:</p>
<p class="ql-center-displayed-equation" style="line-height: 39px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-6f170398dabb2f22172e26279dffd4b3_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#112;&#95;&#122;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#112;&#95;&#122;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#117;&#125;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#117;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>We can apply this rule very easily to our reformulated functions:</p>
<p class="ql-center-displayed-equation" style="line-height: 220px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-ae0b2428e50b1171daec7bafca098554_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#112;&#95;&#122;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#117;&#125;&#32;&#38;&#61;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#117;&#94;&#123;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125;&#123;&#50;&#125;&#92;&#92; &#38;&#61;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125; &#92;&#92;&#91;&#49;&#48;&#93; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#117;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#38;&#61;&#50;&#120;&#92;&#92;&#91;&#49;&#48;&#93; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#112;&#95;&#122;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#38;&#61;&#32;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#125;&#123;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>This equation tells us exactly how the z component of the projected point changes as the texture-space position moves along the x axis.</p>
<h3>Projected X Change According to X</h3>
<p>Now we&#8217;ve found the projected z component derivative, it&#8217;s going to make finding the x and y components a little easier. Why? Because we can express the x and y components in terms of the z component.</p>
<p class="ql-center-displayed-equation" style="line-height: 65px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-34d9aaef6cd544ab1461e03a84d2ebd5_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#112;&#95;&#120;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#125;&#125;&#92;&#92; &#38;&#61;&#32;&#120;&#32;&#112;&#95;&#122; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>We don&#8217;t have the same &#8216;composition of functions&#8217; setup that we did last time, so we can&#8217;t use the chain rule to differentiate this. Instead, we can use the product rule. The product rule in our case says:</p>
<p class="ql-center-displayed-equation" style="line-height: 40px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-d9af0578f8cbc7aea136da9efb618f6f_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#112;&#95;&#120;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#38;&#61;&#32;&#112;&#95;&#122;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#40;&#120;&#41;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#43;&#32;&#120;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#40;&#112;&#95;&#122;&#41;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>Applying this to equation for for the projected x component:</p>
<p class="ql-center-displayed-equation" style="line-height: 103px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-f9f74cdc622cf680b43663722f4df5f5_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#112;&#95;&#120;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#50;&#125;&#125;&#125;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#94;&#50;&#125;&#123;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125;&#92;&#92; &#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#121;&#94;&#50;&#43;&#49;&#125;&#123;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<h3>Projected Y Change According to X</h3>
<p>We have a very similar derivation for the projected y derivative:</p>
<p class="ql-center-displayed-equation" style="line-height: 40px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-41dda9503b32046dad5add6b972d74ad_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#112;&#95;&#121;&#32;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#121;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#125;&#125;&#32;&#61;&#32;&#121;&#32;&#112;&#95;&#122; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>We can use the product rule again:</p>
<p class="ql-center-displayed-equation" style="line-height: 85px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-2c4f3ec120ad14b9203f1fe9cda5fa02_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#112;&#95;&#121;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#38;&#61;&#32;&#112;&#95;&#122;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#40;&#121;&#41;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#43;&#32;&#121;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#40;&#112;&#95;&#122;&#41;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#92;&#92; &#38;&#61;&#32;&#45;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#121;&#125;&#123;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<h3>Projected Position Change According to X and Y</h3>
<p>Putting this all together, we have our equation showing how the projected position changes as the texture-space position changes in the x direction. We can use the exact same process to work out how it moves in the y direction.</p>
<p class="ql-center-displayed-equation" style="line-height: 106px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-ab827bfce1e25c4fb911aaea12128a65_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#92;&#118;&#101;&#99;&#123;&#112;&#125;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#121;&#94;&#50;&#43;&#49;&#44;&#45;&#120;&#121;&#44;&#32;&#45;&#120;&#92;&#101;&#110;&#100;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#125;&#123;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125;&#92;&#92; &#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#92;&#118;&#101;&#99;&#123;&#112;&#125;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#121;&#125;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#45;&#120;&#121;&#44;&#32;&#120;&#94;&#50;&#43;&#49;&#44;&#45;&#121;&#92;&#101;&#110;&#100;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#125;&#123;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<h3>Differential Area</h3>
<p>The next step is to calculate the differential (microscopic) area of the projected point using the partial derivatives we just calculated. Clearly at a normal scale, we wouldn&#8217;t be able to take the cross product of two projected vectors on a sphere and expect the magnitude to be the area they define on the sphere. But at this differential scale, we can treat the surface as if it is flat, so this works.</p>
<p>The first thing we need to do is to calculate the cross product of the partial derivatives.</p>
<p class="ql-center-displayed-equation" style="line-height: 96px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-827bec2eba8abd8e22b037b4205ed4ed_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#118;&#101;&#99;&#123;&#114;&#125;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#92;&#118;&#101;&#99;&#123;&#112;&#125;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#120;&#125;&#32;&#92;&#116;&#105;&#109;&#101;&#115;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#92;&#118;&#101;&#99;&#123;&#112;&#125;&#125;&#123;&#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#121;&#125;&#92;&#92; &#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#121;&#94;&#50;&#43;&#49;&#44;&#45;&#120;&#121;&#44;&#32;&#45;&#120;&#92;&#101;&#110;&#100;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125;&#32;&#92;&#116;&#105;&#109;&#101;&#115;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#45;&#120;&#121;&#44;&#32;&#120;&#94;&#50;&#43;&#49;&#44;&#45;&#121;&#92;&#101;&#110;&#100;&#123;&#112;&#109;&#97;&#116;&#114;&#105;&#120;&#125;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>Calculating the cross product for each of the components relatively straightforward.</p>
<p class="ql-center-displayed-equation" style="line-height: 144px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-c99c873a57f6567a11dc346be8ade727_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#114;&#95;&#120;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#94;&#51;&#43;&#120;&#121;&#94;&#50;&#43;&#120;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#52;&#125;&#92;&#92; &#114;&#95;&#121;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#94;&#50;&#121;&#43;&#121;&#94;&#51;&#43;&#121;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#52;&#125;&#92;&#92; &#114;&#95;&#122;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#40;&#121;&#94;&#50;&#43;&#49;&#41;&#40;&#120;&#94;&#50;&#43;&#49;&#41;&#45;&#120;&#94;&#50;&#121;&#94;&#50;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#52;&#125;&#92;&#92; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>If you&#8217;re reading carefully, you&#8217;ll notice that each component has a factor of <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-8d9216d24c360332801b9b01ede93033_l3.png" class="ql-img-inline-formula" alt="&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;" title="Rendered by QuickLaTeX.com" style="vertical-align: -4px;"/> on the top and the bottom, so we can divide through. Combining all the components back together again, we arrive at the final equation for the perpendicular vector.</p>
<p class="ql-center-displayed-equation" style="line-height: 43px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-f822cb9bc3c3b3b3b6ae38d63f92d219_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#118;&#101;&#99;&#123;&#114;&#125;&#32;&#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#40;&#120;&#44;&#121;&#44;&#49;&#41;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#50;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>Now we simply need to take the length of the result of the cross product to find the differential area on the sphere.</p>
<p class="ql-center-displayed-equation" style="line-height: 151px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-d01ca9cd76b91c518393ab4a9ad617bf_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#92;&#112;&#97;&#114;&#116;&#105;&#97;&#108;&#32;&#65;&#32;&#38;&#61;&#32;&#92;&#115;&#113;&#114;&#116;&#123;&#92;&#118;&#101;&#99;&#123;&#114;&#125;&#32;&#92;&#99;&#100;&#111;&#116;&#32;&#92;&#118;&#101;&#99;&#123;&#114;&#125;&#125;&#92;&#92;&#91;&#53;&#93; &#38;&#61;&#32;&#92;&#115;&#113;&#114;&#116;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#52;&#125;&#125;&#92;&#92;&#91;&#53;&#93; &#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#40;&#120;&#94;&#50;&#32;&#43;&#32;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<h3>Solid Angle</h3>
<p>The final step is to integrate the differential area over our range of texture-space values to get the solid angle of the texel. We can start by calculating the integral between <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-9cf2000c782cfe94be6df5f499cd3e24_l3.png" class="ql-img-inline-formula" alt="&#40;&#48;&#44;&#48;&#41;" title="Rendered by QuickLaTeX.com" style="vertical-align: -4px;"/> and some point <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-29dc6bb5c0d77f139941a7a167e1b164_l3.png" class="ql-img-inline-formula" alt="&#40;&#115;&#44;&#116;&#41;" title="Rendered by QuickLaTeX.com" style="vertical-align: -4px;"/> on the cube map face.</p>
<p class="ql-center-displayed-equation" style="line-height: 95px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-de12d8d6b7a16ee514769d04570a8156_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#102;&#40;&#115;&#44;&#116;&#41;&#38;&#61;&#92;&#105;&#110;&#116;&#95;&#123;&#121;&#61;&#48;&#125;&#94;&#116;&#92;&#105;&#110;&#116;&#95;&#123;&#120;&#61;&#48;&#125;&#94;&#115;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#40;&#120;&#94;&#50;&#43;&#121;&#94;&#50;&#43;&#49;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#51;&#125;&#123;&#50;&#125;&#125;&#125;&#32;&#92;&#44;&#92;&#109;&#97;&#116;&#104;&#114;&#109;&#123;&#100;&#125;&#120;&#92;&#44;&#32;&#92;&#109;&#97;&#116;&#104;&#114;&#109;&#123;&#100;&#125;&#121;&#92;&#92; &#38;&#61;&#92;&#109;&#97;&#116;&#104;&#114;&#109;&#123;&#116;&#97;&#110;&#125;&#94;&#123;&#45;&#49;&#125;&#92;&#102;&#114;&#97;&#99;&#123;&#115;&#116;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#115;&#94;&#50;&#43;&#116;&#94;&#50;&#43;&#49;&#125;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>From this formula, we can calculate the area of any texel in the cube map face by adding together the two right-diagonal corners, A and C, and subtracting the left-diagonal corners, B and D. </p>
<p class="ql-center-displayed-equation" style="line-height: 18px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-ab67ae51f09ddb951225dd4437469c3e_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#83;&#61;&#102;&#40;&#65;&#41;&#32;&#45;&#32;&#102;&#40;&#66;&#41;&#32;&#43;&#32;&#102;&#40;&#67;&#41;&#32;&#45;&#32;&#102;&#40;&#68;&#41; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>You can see on the image below that the added areas in green are canceled out by the subtracted areas in red.</p>
<p><a href="http://www.rorydriscoll.com/wp-content/uploads/2012/01/Area.png"><img src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/Area.png" alt="" title="Area" width="400" height="417" class="aligncenter size-full wp-image-893" /></a></p>
<p>That should look familiar, since that&#8217;s exactly what the CubeMapGen code does. If you look at the surrounding source code to TexelCoordSolidAngle, then you&#8217;ll notice that there&#8217;s another method mentioned for calculating the solid angle of a texel. This method is based on Girard&#8217;s theorem, which describes how to calculate the area of a spherical triangle based on the excess of the sum of its interior angles. This method was also suggested to me on Twitter by Ignacio Castaño (<a href="https://twitter.com/#!/castano">@castano</a>). I haven&#8217;t actually tried it, but it looks fascinating!</p>
<h2>Is it Correct?</h2>
<p>It&#8217;s always a bit daunting to get to the end of a derivation like this, and not know if the answer is correct or not. In this case, it&#8217;s pretty easy to verify if this result is correct. </p>
<p>Remember that the texture-space coordinates are in range [-1,1]. If we set our <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-76f553ea5055b27082c28955d9ece578_l3.png" class="ql-img-inline-formula" alt="&#40;&#120;&#44;&#121;&#41;" title="Rendered by QuickLaTeX.com" style="vertical-align: -4px;"/> values to 1, that corresponds to the top right quarter of the cube map face. We know that there are <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-a64f86508ea52835b7fd42736282275d_l3.png" class="ql-img-inline-formula" alt="&#52;&#92;&#112;&#105;" title="Rendered by QuickLaTeX.com" style="vertical-align: -1px;"/> steradians in a sphere, so that means that each face gets <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-0d5f0508005e85f68bfe0ed48e803e40_l3.png" class="ql-img-inline-formula" alt="&#92;&#102;&#114;&#97;&#99;&#123;&#50;&#92;&#112;&#105;&#125;&#123;&#51;&#125;" title="Rendered by QuickLaTeX.com" style="vertical-align: -6px;"/> steradians. Since we&#8217;re only calculating for a quarter of a face we expect our result to be <img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-38b9dcafd63e963896575ed3fca15de1_l3.png" class="ql-img-inline-formula" alt="&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#105;&#125;&#123;&#54;&#125;" title="Rendered by QuickLaTeX.com" style="vertical-align: -6px;"/>.</p>
<p class="ql-center-displayed-equation" style="line-height: 78px;"><span class="ql-right-eqno"> &nbsp; </span><span class="ql-left-eqno"> &nbsp; </span><img src="http://www.rorydriscoll.com/wp-content/ql-cache/quicklatex.com-68598b2241da90f392546ab98484ea91_l3.png"class="ql-img-displayed-equation" alt="&#92;&#98;&#101;&#103;&#105;&#110;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125; &#102;&#40;&#49;&#44;&#49;&#41;&#38;&#61;&#92;&#109;&#97;&#116;&#104;&#114;&#109;&#123;&#116;&#97;&#110;&#125;&#94;&#123;&#45;&#49;&#125;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#51;&#125;&#125;&#92;&#92; &#38;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#92;&#112;&#105;&#125;&#123;&#54;&#125; &#92;&#101;&#110;&#100;&#123;&#97;&#108;&#105;&#103;&#110;&#42;&#125;" title="Rendered by QuickLaTeX.com"/></p>
<p>And it does. Thanks to the various people on twitter (<a href="https://twitter.com/#!/SebLagarde">@SebLagarde</a>, <a href="https://twitter.com/#!/mattpharr">@mattpharr</a>, <a href="https://twitter.com/#!/manneohrstrom">@manneohrstrom</a>, <a href="https://twitter.com/#!/castano">@castano</a> and <a href="https://twitter.com/#!/ChristerEricson">@ChristerEricson</a>) for engaging me in conversation over this.</p>
<p>Please let me know in the comments if you spot an error in this post, or if anything needs to be explained better or more easily.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>UI Anti-Aliasing</title>
		<link>http://www.rorydriscoll.com/2012/01/08/ui-anti-aliasing/</link>
		<comments>http://www.rorydriscoll.com/2012/01/08/ui-anti-aliasing/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 22:30:08 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=576</guid>
		<description><![CDATA[I&#8217;ve been working on making a really simple IMGUI implementation for my engine at home. I like to do a little bit of research when I&#8217;m approaching something new to me like this, so I went hunting around for publicly available implementations. While doing this, I came across Mikko Mononen&#8217;s implementation in Recast. I was [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on making a really simple IMGUI implementation for my engine at home. I like to do a little bit of research when I&#8217;m approaching something new to me like this, so I went hunting around for publicly available implementations. While doing this, I came across <a href="http://digestingduck.blogspot.com/">Mikko Mononen&#8217;s</a> implementation in <a href="http://code.google.com/p/recastnavigation/">Recast</a>.</p>
<p>I was impressed when I ran the demo with how smooth his UI looked. It turns out that he&#8217;s using a little trick (which I&#8217;d never seen before, but I&#8217;m sure is old to many) to smooth of the edges of his UI elements.</p>
<p>Basically, the trick is to create a ring of extra vertices by extruding the edges of the polygon out by a certain amount. These extra vertices take the same color as the originals, but their alpha is set to zero. Mikko calls this &#8216;feathering&#8217;.</p>
<p>In my case, I found that I got good results by feathering just one pixel. Here&#8217;s a quick before/after comparison of the my IMGUI check box at 800% zoom:</p>
<p><a href="http://www.rorydriscoll.com/wp-content/uploads/2012/01/CheckBoxNoAA.png"><img class="aligncenter size-full wp-image-581" title="CheckBoxNoAA" src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/CheckBoxNoAA.png" alt="" width="376" height="160" /></a></p>
<p><a href="http://www.rorydriscoll.com/wp-content/uploads/2012/01/CheckBoxWithAA.png"><img class="aligncenter size-full wp-image-580" title="CheckBoxWithAA" src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/CheckBoxWithAA.png" alt="" width="376" height="160" /></a></p>
<p>And here&#8217;s a 1-to-1 example showing rounded button corners:</p>
<p><a href="http://www.rorydriscoll.com/wp-content/uploads/2012/01/ButtonNoAA.png"><img class="aligncenter size-full wp-image-584" title="ButtonNoAA" src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/ButtonNoAA.png" alt="" width="160" height="60" /></a><a href="http://www.rorydriscoll.com/wp-content/uploads/2012/01/ButtonWithAA.png"><img class="aligncenter size-full wp-image-583" title="ButtonWithAA" src="http://www.rorydriscoll.com/wp-content/uploads/2012/01/ButtonWithAA.png" alt="" width="160" height="60" /></a></p>
<p>It&#8217;s a pretty nice improvement for a very simple technique! If you&#8217;re interested in what the code looks like, then either take a look at <a href="http://code.google.com/p/recastnavigation/source/browse/trunk/RecastDemo/Source/imgui.cpp?r=213">Mikko&#8217;s IMGUI implementation</a>, or you can find the code I use to feather my convex polygons below. </p>
<p>My implementation is a little less efficient since I recalculate each edge normal twice, but I chose to keep it simple for readability.</p>
<div id="gist-1579850" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kt">void</span> <span class="n">CalculateEdgeNormal</span><span class="p">(</span><span class="kt">float</span><span class="o">&amp;</span> <span class="n">nx</span><span class="p">,</span> <span class="kt">float</span><span class="o">&amp;</span> <span class="n">ny</span><span class="p">,</span> <span class="kt">float</span> <span class="n">x0</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y0</span><span class="p">,</span> <span class="kt">float</span> <span class="n">x1</span><span class="p">,</span> <span class="kt">float</span> <span class="n">y1</span><span class="p">)</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>	<span class="k">const</span> <span class="kt">float</span> <span class="n">x01</span> <span class="o">=</span> <span class="n">x1</span> <span class="o">-</span> <span class="n">x0</span><span class="p">;</span></div><div class='line' id='LC4'>	<span class="k">const</span> <span class="kt">float</span> <span class="n">y01</span> <span class="o">=</span> <span class="n">y1</span> <span class="o">-</span> <span class="n">y0</span><span class="p">;</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'>	<span class="k">const</span> <span class="kt">float</span> <span class="n">length</span> <span class="o">=</span> <span class="n">Sqrt</span><span class="p">(</span><span class="n">x01</span> <span class="o">*</span> <span class="n">x01</span> <span class="o">+</span> <span class="n">y01</span> <span class="o">*</span> <span class="n">y01</span><span class="p">);</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'>	<span class="k">const</span> <span class="kt">float</span> <span class="n">dx</span> <span class="o">=</span> <span class="n">x01</span> <span class="o">/</span> <span class="n">length</span><span class="p">;</span></div><div class='line' id='LC9'>	<span class="k">const</span> <span class="kt">float</span> <span class="n">dy</span> <span class="o">=</span> <span class="n">y01</span> <span class="o">/</span> <span class="n">length</span><span class="p">;</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>	<span class="n">nx</span> <span class="o">=</span> <span class="n">dy</span><span class="p">;</span></div><div class='line' id='LC12'>	<span class="n">ny</span> <span class="o">=</span> <span class="o">-</span><span class="n">dx</span><span class="p">;</span></div><div class='line' id='LC13'><span class="p">}</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'><span class="kt">void</span> <span class="n">FeatherConvexPolygon</span><span class="p">(</span><span class="n">Primitives</span><span class="o">&amp;</span> <span class="n">primitives</span><span class="p">,</span> <span class="k">const</span> <span class="n">Vertex</span><span class="o">*</span> <span class="n">vertices</span><span class="p">,</span> <span class="kt">int</span> <span class="n">count</span><span class="p">,</span> <span class="kt">float</span> <span class="n">amount</span><span class="p">,</span> <span class="k">const</span> <span class="n">Texture</span><span class="o">*</span> <span class="n">texture</span><span class="p">)</span></div><div class='line' id='LC16'><span class="p">{</span></div><div class='line' id='LC17'>	<span class="n">Vertex</span><span class="o">*</span> <span class="n">extruded</span> <span class="o">=</span> <span class="n">Memory</span><span class="o">::</span><span class="n">Allocate</span><span class="o">&lt;</span><span class="n">Vertex</span><span class="o">&gt;</span><span class="p">(</span><span class="n">Memory</span><span class="o">::</span><span class="n">Temp</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Vertex</span><span class="p">)</span> <span class="o">*</span> <span class="n">count</span><span class="p">);</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'>	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span></div><div class='line' id='LC20'>	<span class="p">{</span></div><div class='line' id='LC21'>		<span class="k">const</span> <span class="n">Vertex</span><span class="o">&amp;</span> <span class="n">previous</span> <span class="o">=</span> <span class="n">vertices</span><span class="p">[(</span><span class="n">i</span> <span class="o">+</span> <span class="n">count</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">count</span><span class="p">];</span></div><div class='line' id='LC22'>		<span class="k">const</span> <span class="n">Vertex</span><span class="o">&amp;</span> <span class="n">current</span> <span class="o">=</span> <span class="n">vertices</span><span class="p">[</span><span class="n">i</span><span class="p">];</span></div><div class='line' id='LC23'>		<span class="k">const</span> <span class="n">Vertex</span><span class="o">&amp;</span> <span class="n">next</span> <span class="o">=</span> <span class="n">vertices</span><span class="p">[(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">count</span><span class="p">];</span></div><div class='line' id='LC24'><br/></div><div class='line' id='LC25'>		<span class="kt">float</span> <span class="n">nx0</span><span class="p">,</span> <span class="n">ny0</span><span class="p">,</span> <span class="n">nx1</span><span class="p">,</span> <span class="n">ny1</span><span class="p">;</span></div><div class='line' id='LC26'><br/></div><div class='line' id='LC27'>		<span class="n">CalculateEdgeNormal</span><span class="p">(</span><span class="n">nx0</span><span class="p">,</span> <span class="n">ny0</span><span class="p">,</span> <span class="n">previous</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">previous</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">current</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">current</span><span class="p">.</span><span class="n">y</span><span class="p">);</span></div><div class='line' id='LC28'>		<span class="n">CalculateEdgeNormal</span><span class="p">(</span><span class="n">nx1</span><span class="p">,</span> <span class="n">ny1</span><span class="p">,</span> <span class="n">current</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">current</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">next</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">next</span><span class="p">.</span><span class="n">y</span><span class="p">);</span></div><div class='line' id='LC29'><br/></div><div class='line' id='LC30'>		<span class="kt">float</span> <span class="n">nx</span> <span class="o">=</span> <span class="p">(</span><span class="n">nx0</span> <span class="o">+</span> <span class="n">nx1</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5f</span><span class="p">;</span></div><div class='line' id='LC31'>		<span class="kt">float</span> <span class="n">ny</span> <span class="o">=</span> <span class="p">(</span><span class="n">ny0</span> <span class="o">+</span> <span class="n">ny1</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.5f</span><span class="p">;</span></div><div class='line' id='LC32'><br/></div><div class='line' id='LC33'>		<span class="n">extruded</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">Vertex</span><span class="p">(</span><span class="n">current</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">nx</span> <span class="o">*</span> <span class="n">amount</span><span class="p">,</span> <span class="n">current</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">ny</span> <span class="o">*</span> <span class="n">amount</span><span class="p">,</span> <span class="n">Color</span><span class="p">(</span><span class="n">current</span><span class="p">.</span><span class="n">r</span><span class="p">,</span> <span class="n">current</span><span class="p">.</span><span class="n">g</span><span class="p">,</span> <span class="n">current</span><span class="p">.</span><span class="n">b</span><span class="p">,</span> <span class="mf">0.0f</span><span class="p">));</span></div><div class='line' id='LC34'>	<span class="p">}</span></div><div class='line' id='LC35'><br/></div><div class='line' id='LC36'>	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">count</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span></div><div class='line' id='LC37'>	<span class="p">{</span></div><div class='line' id='LC38'>		<span class="k">const</span> <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">count</span><span class="p">;</span></div><div class='line' id='LC39'>		<span class="n">AddQuad</span><span class="p">(</span><span class="n">primitives</span><span class="p">,</span> <span class="n">vertices</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">extruded</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">extruded</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">vertices</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">texture</span><span class="p">);</span></div><div class='line' id='LC40'>	<span class="p">}</span></div><div class='line' id='LC41'><br/></div><div class='line' id='LC42'>	<span class="n">Memory</span><span class="o">::</span><span class="n">Free</span><span class="p">(</span><span class="n">extruded</span><span class="p">);</span></div><div class='line' id='LC43'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1579850/4e77ec03800a74fa9f85ed24211cc2fad85d5d6d/FeatherUI.cpp" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1579850#file_feather_ui.cpp" style="float:right;margin-right:10px;color:#666">FeatherUI.cpp</a>
            <a href="https://gist.github.com/1579850">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2012/01/08/ui-anti-aliasing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MockItNow: Now with Win64 goodness!</title>
		<link>http://www.rorydriscoll.com/2011/02/23/mockitnow-now-with-win64-goodness/</link>
		<comments>http://www.rorydriscoll.com/2011/02/23/mockitnow-now-with-win64-goodness/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 04:32:55 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=557</guid>
		<description><![CDATA[A couple of fine chaps named Julian Adams and Clement Dagneau from my previous company Black Rock Studios (née Climax Racing) took it upon themselves to tackle the daunting task of  porting MockItNow to x64 (MSVC). They&#8217;ve kindly shared their efforts back with the main repository in google code. Feel free to profit from their [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of fine chaps named Julian Adams and Clement Dagneau from my previous company Black Rock Studios (née Climax Racing) took it upon themselves to tackle the daunting task of  porting MockItNow to x64 (MSVC).</p>
<p>They&#8217;ve kindly shared their efforts back with the main repository in <a href="http://code.google.com/p/mockitnow/">google code</a>. Feel free to profit from their hard work!</p>
<p>Thanks a lot Julian &amp; Clement!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2011/02/23/mockitnow-now-with-win64-goodness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Another MockItNow Update</title>
		<link>http://www.rorydriscoll.com/2009/03/13/another-mockitnow-update/</link>
		<comments>http://www.rorydriscoll.com/2009/03/13/another-mockitnow-update/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 03:50:06 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=301</guid>
		<description><![CDATA[I fixed a problem with the EXPECT_THROW macro (I had uploaded the wrong file). Also, I added the ability to stub out results for function arguments passed by pointer. I would recommend downloading the zip file to take a look since there were a few files that had to change this time. I added one [...]]]></description>
			<content:encoded><![CDATA[<p>I fixed a problem with the EXPECT_THROW macro (I had uploaded the wrong file). Also, I added the ability to stub out results for function arguments passed by pointer. I would recommend downloading the zip file to take a look since there were a few files that had to change this time. I added one new example to show the new functionality.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2009/03/13/another-mockitnow-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Books</title>
		<link>http://www.rorydriscoll.com/2009/01/12/books/</link>
		<comments>http://www.rorydriscoll.com/2009/01/12/books/#comments</comments>
		<pubDate>Mon, 12 Jan 2009 08:10:19 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=152</guid>
		<description><![CDATA[A couple of days ago, I stacked the random assortment of books I had lying on my desk at work, and for some reason I decided to take a photo. It&#8217;s a bit of a mixed bag of good and not-so-good books. Every now and then I know I&#8217;m in trouble because I have to [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of days ago, I stacked the random assortment of books I had lying on my desk at work, and for some reason I decided to take a photo. It&#8217;s a bit of a mixed bag of good and not-so-good books.</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-155" title="books" src="http://www.rorydriscoll.com/wp-content/uploads/2009/01/books.jpg" alt="books" width="300" height="400" /></p>
<p>Every now and then I know I&#8217;m in trouble because I have to whip out the yellow maths book to remind myself of something that I have forgotten. I enjoy the challenge of reading the quaternions book, but it&#8217;s pretty hard to motivate myself to really get into that one.</p>
<p>My favourite at the moment is probably Real-Time Rendering (the latest edition which I have at home to be more specific), and my least favourite is probably Clean Code.</p>
<p>Clean Code seems to take the good ideas from other books (like C++ Coding Standards), and then adds some more which don&#8217;t make as much sense (I can&#8217;t think of a specific example off-hand). The customer reviews on Amazon.com are pretty good though. I definitely had an &#8216;uh-oh&#8217; moment when I read the buzzword-laden full title &#8211; Clean Code: A Handbook Of Agile Software Craftmanship.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2009/01/12/books/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Nothing To Report</title>
		<link>http://www.rorydriscoll.com/2008/06/30/nothing-to-report/</link>
		<comments>http://www.rorydriscoll.com/2008/06/30/nothing-to-report/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 06:02:44 +0000</pubDate>
		<dc:creator>Rory</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.rorydriscoll.com/?p=26</guid>
		<description><![CDATA[Well, there&#8217;s not much to report really. I&#8217;ve been spreading myself very thin recently, investigating a few different things, so I thought might be nice to post a status update. Variance Shadow Maps Yes, I&#8217;m jumping on the variance shadow maps boat. They look nice, they&#8217;re easy to implement, and have relatively small overhead over [...]]]></description>
			<content:encoded><![CDATA[<p>Well, there&#8217;s not <em>much</em> to report really. I&#8217;ve been spreading myself very thin recently, investigating a few different things, so I thought might be nice to post a status update.</p>
<h2>Variance Shadow Maps</h2>
<p>Yes, I&#8217;m jumping on the variance shadow maps boat. They look nice, they&#8217;re easy to implement, and have relatively small overhead over traditional shadow maps. I read the article in GPU Gems 3, which is also available <a href="http://www.punkuser.net/vsm/">here</a>, and it was pretty easy to implement from there. It probably took me about 2 hours to go from no shadows at all to variance shadow maps. After a bit of tomfoolery to get rid of the light-leaking I ended up with the image below. I haven&#8217;t implemented any bias yet, so there are some errors there, but the VSMs appear to be working very nicely.</p>
<p style="text-align: center;"><a href="http://www.rorydriscoll.com/wp-content/uploads/2008/06/vsm.jpg"><img class="size-full wp-image-20 aligncenter" title="mat-all" src="http://www.rorydriscoll.com/wp-content/uploads/2008/06/vsm.jpg" alt="" width="400" height="275" /></a></p>
<p><span id="more-26"></span></p>
<h2>Better Tone Mapping</h2>
<p>My current tone mapping algorithm doesn&#8217;t look that good, so I&#8217;ve been investigating any alternatives. I was initially put off Reinhard tone mapping when I first looked at the DirectX HDRLighting sample a long time ago because it treated each channel completely independently. This is a really nasty idea since it can change the hue of the image during tone mapping as each channel gets compressed by a different amount. I recently re-read a <a href="http://www.gamedev.net/reference/articles/article2208.asp">gamedev article</a> and then implemented Reinhard&#8217;s tone mapping using based on the pixel luminance, which gave much nicer results, and didn&#8217;t change the hue. One note on that article though: It says that to convert to RGB from the final luminance you need to multiply by the luminance, which doesn&#8217;t seem right. What I did was to divide by the old luminance and then multiply by the tone mapped luminance. It&#8217;s hard to tell right now if it looks better or worse, it&#8217;s just different.</p>
<p>The image above is using this new tone mapping, but I&#8217;m not doing the dynamic image key calculation at the moment. That basically gives me three variables (image key, midzone luminance, and white luminance) which aren&#8217;t very intuitive to tweak. I&#8217;ve generally been leaving the midzone gray at 0.18 as suggested, and then tweaking the image key and white luminance to get something that looks OK.</p>
<h2>Windows Presentation Foundation</h2>
<p>I&#8217;ve spent a lot of time at work recently improving one of our C# tools, which is Windows Forms based. There are many things I dislike about Windows Forms, like the lack of built-in support for something useful like the command-pattern, the horrible input handling, menu shortcuts, you name it! For my own education, last weekend I started reading about the latest and greatest from Microsoft: The Windows Presentation Foundation. From my brief foray into WPF, it seems that a lot of the the things in Windows Forms that I&#8217;ve spent time trying to fix or circumvent appear to have been addressed.</p>
<p>For example, in Windows Forms, if you don&#8217;t handle a key-press event in a control, then no-one else gets to handle it either, unless they have specifically attached an event handler to that controls key-press event. In WPF they have the notion of tunneling and bubbling commands. This basically means that if you don&#8217;t handle that event then your parent gets a chance to handle it (it bubbles up), and vice-versa for tunneling events.</p>
<p>There seems to be a much greater emphasis of splitting the View from the Model (in the Model-View-Controller sense that is), with only very loose references (or none at all) required to bind everything together. I&#8217;m very interested in finding a good method for splitting the View code from the Controller and Model code, so I&#8217;ve been reading a few articles, some of which you can read here: <a href="http://www.codeproject.com/KB/WPF/MVCtoUnitTestinWPF.aspx">Model-View-Controller</a>, <a href="http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx">Model-View-ViewModel</a>, <a href="http://martinfowler.com/eaaDev/PresentationModel.html">Presentation Model</a>. I really liked Martin Fowler&#8217;s description of Presentation Model in particular. The Model-View-ViewModel paper was also a good read, but I really dislike the resuse of the words Model and View in the terminology (it&#8217;s doubly confusing since I already have C++ classes called Model and View representing a 3D model and a view point respectively). In Windows Forms you seem to be almost forced to keep your View and Controller code tightly bound, but there appears to be much more freedom in WPF.</p>
<p>I also bought a <a href="http://www.amazon.com/gp/product/0672328917/">book</a> about WPF by some bloke from Microsoft called Adam Nathan, which so far has been some good reading (despite the liberal sprinkling of exclamation marks on every page). I&#8217;d love to see a book that combines WPF and something like Model-View-ViewModel to create a real-world, complicated application rather than the fairly simple examples that appear in books and online articles. If anyone knows of a book like this, then please let me know!</p>
<p>Oh, but it&#8217;s not all roses in WPF though. One of the first videos I watched was <a href="http://windowsclient.net/learn/video.aspx?v=32300">this one</a>. If you&#8217;ve seen it, then you probably have the same same thought running around your head that that I did when I first watched it: <em><strong>WTF</strong></em>? You&#8217;re basically allowed to reuse some storage from a dependency property that isn&#8217;t used to affect your control. For example, assuming you&#8217;re not parented to a DockPanel, you can use something like DockPanel.Width to store an arbitrary number. It&#8217;s like the Tag in Windows Forms, but much much worse. Microsoft seem to be touting it like a really cool feature, when it feels more like a dirty hack to me. Using unused properties to store arbitrary data is a really quick way to make your code unmaintainable as far as I&#8217;m concerned. I don&#8217;t want to have to search the code for where someone put the data into the property in order to work out what it is actually storing&#8230; Urgh!</p>
<h2>Articles</h2>
<p>Yeah, I&#8217;m about 80% through writing one about storing function call arguments in MockItNow at the moment. It&#8217;ll be up as soon as I finish the last 80%. That&#8217;s all!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rorydriscoll.com/2008/06/30/nothing-to-report/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

