<?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>Holy Ghost Stories</title>
	<atom:link href="http://www.jeffwofford.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.jeffwofford.com</link>
	<description>Faith, technology, and everything in between.</description>
	<lastBuildDate>Sun, 13 Jun 2010 03:08:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Porting a Fixed-Function Game to a Programmable Pipeline: Part 3</title>
		<link>http://www.jeffwofford.com/?p=698</link>
		<comments>http://www.jeffwofford.com/?p=698#comments</comments>
		<pubDate>Sun, 13 Jun 2010 00:51:22 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Crush the Castle]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=698</guid>
		<description><![CDATA[I&#8217;m porting Crush the Castle from a fixed-function, OpenGL 1 renderer to a programmable, OpenGL 2 renderer. In the last couple of posts I described how I separated my initial fixed-function renderer into three distinct classes: An abstract Renderer interface that the game itself talks to A concrete implementation of the Renderer interface that uses [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jeffwofford.com/wp/wp-content/uploads/2009/10/CrushTheCastle-shot01.png"><img class="alignright size-medium wp-image-419" title="Crush the Castle: iPhone" src="http://www.jeffwofford.com/wp/wp-content/uploads/2009/10/CrushTheCastle-shot01-300x156.png" alt="Crush the Castle: iPhone" width="300" height="156" /></a>I&#8217;m porting <a title="Crush the Castle [iTunes]" href="http://itunes.com/apps/crushthecastle">Crush the Castle</a> from a fixed-function, OpenGL 1 renderer to a programmable, OpenGL 2 renderer. In the <a title="Part 1 in this series" href="http://www.jeffwofford.com/?p=635">last couple</a> of <a title="Part 2 in this series" href="http://www.jeffwofford.com/?p=637">posts</a> I described how I separated my initial fixed-function renderer into three distinct classes:</p>
<ol>
<li>An abstract Renderer interface that the game itself talks to</li>
<li>A concrete implementation of the Renderer interface that uses fixed-function OpenGL 1 (RendererGLES1)</li>
<li>Another implementation of Renderer that uses programmable OpenGL 2 (RendererGLES2)</li>
</ol>
<p>Today I&#8217;d like to show you what I had to do to port the fixed-function version of the renderer to use the programmable pipeline in OpenGL ES 2.0.</p>
<h2><span id="more-698"></span>More Power, More Responsibility</h2>
<p>The good news about a programmable rendering pipeline is that it offers far greater power. With a <em>fixed-function</em> pipeline you can only do what the API lets you do. If the API supports bump mapping, you can do bump mapping. If the API supports fog, you can apply fog. But with a <em>programmable</em> pipeline, your engine can render anything that you can code. You&#8217;re in total control of how every vertex and pixel is displayed.</p>
<p>The bad news about a programmable pipeline is that it requires a lot more work. Fixed-function pipelines do a lot for you. Call glRotate(), for example, and OpenGL will set up a rotation matrix for you and concatenate it with the existing matrix. Request that a light be applied to your models and suddenly they&#8217;re glowing with the sunset. Not so in a programmable pipeline. If you want to see sunlight, <em>you&#8217;ve </em>got to code it. If you want transform matrices (and believe me, you do), you&#8217;ve got to program them.</p>
<p>So a programmable pipeline offers more power. But it also puts more responsibility on you, the programmer.</p>
<p>This is even more true in OpenGL ES 2.0—the rendering API that the iPad and later iPhones/iPod Touches use. All new versions of OpenGL add support for vertex and fragment programs. But the &#8220;ES&#8221; version of OpenGL 2.0—the mobile, stripped-down version—not only adds this support, it strips out support for anything else.</p>
<p>This is the hardest part about moving from a fixed function renderer to a programmable renderer on the iPhone/iPad. The move to shaders takes away some of the functionality that OpenGL ES 1.0 provided.</p>
<h2>Changes from OpenGL ES 1.0 to OpenGL ES 2.0</h2>
<p>The biggest changes that I encountered when moving <em>Crush the Castle </em>from version 1 to version 2 of OpenGL ES involved how vertex attributes are sent to the hardware, the self-management of matrices, and of course, programming the actual shaders. Here&#8217;s a list of all the changes I had to make to my fixed-function renderer. A lot of these might not make sense now, but I&#8217;ll talk about them all in more detail later.</p>
<ul>
<li>Implemented my own 4&#215;4 matrix class with support for translation, rotation, scaling, and concatenation</li>
<li>Implemented my own orthographic and perspective projection math</li>
<li>Created a class to implement matrix stacks</li>
<li>Replaced occasional calls to glColor4f() (used to apply a single color to all vertices in a draw call) with a vertex program &#8220;uniform&#8221; variable</li>
<li>Got rid of glEnableClientState() calls</li>
<li>Converted gl*Pointer() calls (like glVertexPointer() and glTexCoordPointer()) to glVertexAttribPointer() calls</li>
<li>Added the loading, compiling, linking, validating, and using of vertex and fragment shaders</li>
</ul>
<p>Some features stayed just the same.</p>
<ul>
<li>Texture creation, loading, and binding</li>
<li>Alpha blending settings</li>
<li>Vertex buffer object creation with glBufferData() and the like</li>
<li>Setting the viewport with glViewport()</li>
<li>glGetError()</li>
<li>glClear(), glClearColor(), and the like</li>
<li>glDrawArrays() and glDrawElements()</li>
</ul>
<p>Now <em>Crush the Castle</em> does not use every feature in OpenGL ES 1. No doubt there are many other fixed-function features that I would have needed to convert if I had been using them. So mileage may vary. But these are the ones I had to convert, and next time I&#8217;ll go into more detail about what I had to do to convert each one.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=698</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Back from the Bing</title>
		<link>http://www.jeffwofford.com/?p=681</link>
		<comments>http://www.jeffwofford.com/?p=681#comments</comments>
		<pubDate>Thu, 10 Jun 2010 20:21:10 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=681</guid>
		<description><![CDATA[All right Google, nevermind. I thought you were obnoxious. But after trying Bing for a few hours I see you&#8217;re still the best thing going. Google&#8217;s recent interface changes may be noisy and toadying. But at least their search engine works. Bing&#8217;s doesn&#8217;t. Not well anyway. Example. I needed to know how to insert newlines [...]]]></description>
			<content:encoded><![CDATA[<p>All right Google, <a title="&quot;Goodbye Google&quot;" href="http://www.jeffwofford.com/?p=673">nevermind</a>. I thought you were obnoxious. But after trying Bing for a few hours I see you&#8217;re still the best thing going.</p>
<p>Google&#8217;s recent interface changes may be noisy and toadying. But at least their search engine works. Bing&#8217;s doesn&#8217;t. Not well anyway.</p>
<p><span id="more-681"></span>Example. I needed to know how to insert newlines into a text document by using find and replace in Xcode. So I do a search in Bing:</p>
<blockquote><p>&#8220;xcode find and replace newline&#8221;</p></blockquote>
<p>Bing proceeds to tell me all sorts of interesting things about such diverse topics as finding, replacing, and newlines. Unfortunately, none of the results have anything to do with Xcode. In fact, they all seem to have a lot to do with Microsoft products. Fully half of the top six results are from Microsoft sites. Hmm.</p>
<p>So I begrudgingly drag myself back over to Google&#8217;s ugly mug and repeat my request. Google—as I don&#8217;t need to tell you—took me right where I needed to go.</p>
<p>I&#8217;m disappointed in Google&#8217;s front end designers for wanting to be like Bing&#8217;s front end designers. But Google&#8217;s back end programmers won&#8217;t let me leave.</p>
<p>Sorry Google. I&#8217;m back.</p>
<p>&#8230;</p>
<p>The solution to my find-and-replace-inserting-newlines problem turned out to be <a title="&quot;A stupid Xcode trick, for find and replace with carriage returns&quot; [Michael Gracie]" href="http://michaelgracie.com/2009/10/09/a-stupid-xcode-trick-for-find-and-replace-with-carriage-returns/">really weird</a>, BTW. Big props to Michael Gracie for coming up with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=681</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Goodbye Google</title>
		<link>http://www.jeffwofford.com/?p=673</link>
		<comments>http://www.jeffwofford.com/?p=673#comments</comments>
		<pubDate>Thu, 10 Jun 2010 14:41:48 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[culture]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[thinking]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=673</guid>
		<description><![CDATA[I never imagined this day would come. It seemed like Google would be my conduit to the internet forever. Why not? Who could beat it? I never guessed that I would leave Google not for another, superior search engine, but simply because Google had turned fickle and annoying. After remaining essentially unchanged for over a [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-medium wp-image-711" title="Google" src="http://www.jeffwofford.com/wp/wp-content/uploads/2010/06/google-300x105.jpg" alt="Google" width="300" height="105" />I never imagined this day would come. It seemed like Google would be my conduit to the internet forever. Why not? Who could beat it?</p>
<p>I never guessed that I would leave Google not for another, superior search engine, but simply because Google had turned fickle and annoying.</p>
<p><span id="more-673"></span>After remaining essentially unchanged for over a decade, the Google interface started morphing a few months ago.</p>
<p>At first the change was innocuous enough, maybe even an improvement. The main Google search page would hide all clutter—the nav bar, the extra links—unless the user moved the mouse over it. If you just jumped to the page, typed a query, and hit Return, you saw the most unobtrusive Google imaginable. Perfect.</p>
<p>On the annoying side, the slightest mouse movement would cause the clutter to fade back in. This had the unfortunate effect of making the clutter more conspicuous than it had been when it was static. I&#8217;ve said this to UI designers (including myself) for years, and I&#8217;ll say it again: <strong>A consistent bad thing is better than an inconsistent good thing.</strong> Clutter is bad, but if it doesn&#8217;t change, the user stops seeing it after a while. Getting rid of clutter entirely is good, but if it pops back in at unexpected times, that&#8217;s even worse.</p>
<p>So Google became mildly annoying.</p>
<p>A couple of weeks ago Google changed its search results page. They moved their filtering features to the left side of the page, pushing the search results out to the right. At first this felt weird and arbitrary, but soon I was enjoying the filtering links—like quickly focusing on a particular size of image. I got used to the new layout.</p>
<p>Today, <a title="Google" href="http://www.google.com">this</a>. Big, garish, noisy images filling my screen. Images that make it harder for my eye to parse the screen. Images that waste my retina-processing neuron cycles when I&#8217;m trying to focus on other thoughts. Images that take more bandwidth, that take time to download, and that therefore cause my search page to change while I&#8217;m in the middle of using it.</p>
<p>Now that&#8217;s annoying.</p>
<p>You know, I&#8217;m not against decoration. I don&#8217;t mind if some arbitrary webpage is full of colors and shapes.</p>
<p>But Google search is not just a webpage. It has become part of how human beings live. It is part of our brains. Any little change to it changes the way billions of people think and feel.</p>
<p>&#8220;So,&#8221; maybe Google is thinking, &#8220;if we have that kind of responsibility for how people&#8217;s brains work, maybe we should use our power to show calming, happy, warm images that will help to soothe and inspire them.&#8221;</p>
<p>No Google. That&#8217;s not your job. Your job is to take my brain from an initial question (&#8220;What was Mark Twain&#8217;s real name?&#8221;) to a set of potential answers. Your responsibility as a search engine is to do nothing but to help my neurons move along on their current course. Not to edit that course. Not to soothe it.</p>
<p>Less is more here. Less helps you do no harm. Less helps you do no evil.</p>
<p>Of course, the real reason that Google is making all these changes is nothing to do with their sense of responsibility. It&#8217;s everything to do with <a href="http://www.theatlanticwire.com/opinions/view/opinion/Bing-Google-Models-Facelift-After-Microsoft-3499">fighting back against Bing</a>. Bing has been gaining market share at Google&#8217;s expense. Google figures Bing has got something they haven&#8217;t. They study the Bing site, figure out what that is. They take those ideas and apply them to Google.</p>
<p>And maybe it will work. Maybe people&#8217;s brains <a title="Your Brain on Computers [New York Times]" href="http://www.nytimes.com/2010/06/07/technology/07brain.html"><em>like</em> the noise</a> of imagery, the momentary distraction of a <a title="Bing's background image du jour" href="http://www.bing.com/fd/hpk2/BelemTower_EN-US50063318.jpg">backlit castle</a>. Maybe Bing has the right idea.</p>
<p>But as a Google user, all I can say is that a more Bing-ish Google is less of a Google. If Google has decided that Bing has what users want, why I don&#8217;t take Google&#8217;s recommendation and just move to Bing?</p>
<p>So that&#8217;s what I did a few moments ago. Homepage changed.</p>
<p>Goodbye Google. Thanks for all your help.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=673</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The Things You Learn in the Strangest Places</title>
		<link>http://www.jeffwofford.com/?p=644</link>
		<comments>http://www.jeffwofford.com/?p=644#comments</comments>
		<pubDate>Tue, 08 Jun 2010 19:29:06 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[family]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=644</guid>
		<description><![CDATA[My daughter Kathleen loves foxes. Until last Friday she had never owned one. We bought her one that afternoon. Not a real one of course. As Dr. Desoto rightly observes in William Steig&#8217;s excellent story, foxes are &#8220;wicked, wicked creatures.&#8221; Instead we bought her a small, hard, painted plastic fox that she picked out specially. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jeffwofford.com/wp/wp-content/uploads/2010/06/Jardines-Naturalists-Library-fox.jpg"><img class="alignright size-medium wp-image-647" style="border: 2px solid #443300;" title="The Dog-Fox from Jardine's Naturalist's Library (1836)" src="http://www.jeffwofford.com/wp/wp-content/uploads/2010/06/Jardines-Naturalists-Library-fox-300x187.jpg" alt="Dog-Fox" width="300" height="187" /></a>My daughter Kathleen loves foxes. Until last Friday she had never owned one. We bought her one that afternoon. Not a real one of course. As Dr. Desoto rightly observes in <a title="William Steig's official biography" href="http://us.macmillan.com/author/williamsteig/">William Steig&#8217;s</a> excellent <a title="Dr. Desoto [Wikipedia]" href="http://en.wikipedia.org/wiki/Doctor_De_Soto">story</a>, foxes are &#8220;wicked, wicked creatures.&#8221;</p>
<p>Instead we bought her a small, hard, painted plastic fox that she picked out specially. She adored it.</p>
<p>That night as she got ready for bed she debated whether to name it &#8220;Reddy&#8221; or &#8220;Redders.&#8221; But while thus occupied, she accidentally dropped the fox into the toilet—a toilet already in mid-flush.</p>
<p>We heard her heartbroken wail as she raced down the hall. Redders—Reddy—was gone.</p>
<p><span id="more-644"></span>Kathleen is only four. The mystery and terror of the commode—that strange, great, glimmering cavity that takes away parts of ourselves and sends them to some unknown hell or heaven—has not entirely left her. She cried a long time at the loss of her precious fox and the awful way he went.</p>
<p>It soon became clear, however, that Redders had not entirely passed into the great beyond. Evidence for the presence of his unsettled ghost came in the form of high waters at the next flushing. Redders was still with us, somewhere, somehow, and vividly expressing his unease.</p>
<p>As father of the family and man of the house, naturally it falls to me to take care of any little household operational problem that arises. So it was I who plunged the toilet in the hopes that Redder&#8217;s progress would be decisively advanced or reversed. The loo flowed a little better after that. I left the problem to sort itself out.</p>
<p><a href="http://patimg2.uspto.gov/.piw?Docid=04320756&amp;homeurl=http%3A%2F%2Fpatft.uspto.gov%2Fnetacgi%2Fnph-Parser%3FSect1%3DPTO1%2526Sect2%3DHITOFF%2526d%3DPALL%2526p%3D1%2526u%3D%25252Fnetahtml%25252FPTO%25252Fsrchnum.htm%2526r%3D1%2526f%3DG%2526l%3D50%2526s1%3D4,320,756.PN.%2526OS%3DPN%2F4,320,756%2526RS%3DPN%2F4,320,756&amp;PageNum=&amp;Rtype=&amp;SectionNum=&amp;idkey=NONE&amp;Input=View+first+page"><img class="alignleft size-medium wp-image-645" title="Patent No. 4,320,756—the Toilet Snorkel" src="http://www.jeffwofford.com/wp/wp-content/uploads/2010/06/toilet-snorkel-300x226.jpg" alt="Toilet Snorkel" width="300" height="226" /></a>By the next evening the whole family could see that the problem had <em>not</em> sorted itself out. The toilet would no longer drain. Any further attempts to flush would only result in the most unseemly kind of spillage. Even plunging proved precarious. I put a sign on the loo—DO NOT USE—and looked without enthusiasm for the opportunity to probe further into the matter.</p>
<p>That opportunity came this morning. And I am here to tell you, now that the problem has resolved, that it really is remarkable the things you learn in the most unexpected places.</p>
<p>I am not very handy around the house. I&#8217;m handier around <a title="Some of my posts on programming" href="http://www.jeffwofford.com/?cat=15">C++ and OpenGL.</a> One of the nice things about working with computers is that I hardly ever cut my hands, crush my thumbs, drop heavy things on my toes, <a title="&quot;Listening to the Voices in Your Head&quot;" href="http://www.jeffwofford.com/?p=40">put out my eyes</a>, or experience any of the other misfortunes that seem to occur when I interact with the physical world.</p>
<p>Moreover, I had never unclogged a really serious stoppage before. It&#8217;s the sort of thing I remember my dad doing when I was growing up. And I helped sometimes. But I didn&#8217;t remember how he did it. I wasn&#8217;t sure I could figure it out.</p>
<p>I thought of asking him to come over—&#8221;Bring out the big guns,&#8221; as I put it to my wife. My dad lives a few miles down the road—it wouldn&#8217;t be the first time he has come to our rescue in household emergencies. But I&#8217;m nearly forty. I&#8217;m quite a big boy now. I figured this was something I needed to do myself. For my manhood, you know.</p>
<p>I had a vague notion of pouring Liquid Plumbr down the potty. I didn&#8217;t think Redders would appreciate that. Any acid that would dissolve a plastic fox would surely be a dire hazard in my ungainly hands, and any that wouldn&#8217;t was useless. Moreover, I harbored some hope of saving the fox and returning him to the one who loved him.</p>
<p>I will spare you the details of how I cleared the blockage. It involved quite a bit of splashing, not all of an entirely liquid sort. The plunger was no use. The flexible cleaning tool that I bought for the job offered little help. About six towels became involved at various points. A chorus of <a title="The Patent Leather Beetle" href="http://www.fcps.edu/islandcreekes/ecology/patent-leather_beetle.htm">patent leather beetles</a> appeared during Act II and scrambled around the stage. (I&#8217;ve always liked patent leather beetles. I like them less now that I know what they eat.) I had to unscrew the entire commode from the floor, tip it over, and look up into its—erm—bottom. On the bright side (so to speak) this did enable me to confirm that <em>Redders was still there.</em></p>
<p>Other details I won&#8217;t mention involve carrying the entire commode out onto the back lawn and spraying it like it had never been sprayed before. After laying the potty on its side and blasting water into it for five or ten minutes, I looked once more into the bowl. There lay Redders, suddenly, surprisingly, thankfully liberated.</p>
<p>I looked for high fives from my wife and children—especially Kathleen—but they didn&#8217;t seem eager to approach me.</p>
<p>Redders received a good washing, beginning with a long bleach bath. Kathleen was at last reunited with her fox, her special fox. And he is no less special to her despite the places he&#8217;s been.</p>
<p>The whole exercise took perhaps an hour and a half. That gave me plenty of time to observe and reflect. As I said before I learned some surprising lessons: one about psychology, another about service, one about fatherhood, and the last about engineering.</p>
<ol>
<li><strong>You can get used to anything. </strong>In the early minutes of my expedition the smell, the splashing, and the slurping sounds when I— no, no, I must spare you the details. Anyway, I really thought I might throw up. But after half an hour or so I got used to the odor. I&#8217;m quite serious when I say that it almost became pleasant. And it seems to me that here is an analogy for life. There are things we do as adults that seem perfectly normal to us, but if the eight-year-old versions of ourselves saw those things they would go heaving into the bushes. Just as I got used to the smell of effluvia, we all get used to our lives. A human being can adapt to almost anything, for better and for worse. If you live in muck long enough you even begin to like it. I&#8217;ve seen this principle at work in relationships, for example. And in employment situations. And with people and their habits. Maybe you have to.</li>
<li><strong>A dirty job isn&#8217;t so bad if it&#8217;s for someone you love. </strong>Tedium is  tedium. Disgusting muck is disgusting muck. But serving someone else  makes the tedium and muck far, far easier to bear.</li>
<li><strong>Dads hate poo as much as you do. </strong>My dad always seems to dive into any job without fear or reticence. No doubt part of that courage came from growing up on an east Texas ranch where dirt and bruises and the excrement of livestock were part of the daily grind. But even though I&#8217;m a soft suburbanite who brushes Ritz crackers from his <a title="Perry Ellis" href="http://www.perryellis.com/">Perry Ellis</a> shirts while tapping on his keyboard or delivering a lecture on memory allocation, my kids seem to see me in the same way. &#8220;It&#8217;s no big deal for dad to get covered in poo,&#8221; they say. &#8220;Grown men like to smear themselves in grime now and then.&#8221; Today I learned, and hope my kids learn, that dads don&#8217;t do hard, irksome, or disgusting jobs because they like it, or even because they&#8217;re indifferent to it. They do it because they have to.</li>
<li><strong>The toilet is</strong> <strong>a marvelous invention.</strong> Really simple once you understand it. No electricity. Quite reliable. The physics of the thing—all gravity, seals, and siphons—is really a wonder when you come to see it. Every child should learn how a toilet works before they leave for college.</li>
</ol>
<p>One final thought.  If you do decide, as I have, to teach your children about the mechanics of the crapper, I think it&#8217;s better to start with a diagram rather than a working demonstration.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=644</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Porting a Fixed-Function Game to a Programmable Pipeline: Part 2</title>
		<link>http://www.jeffwofford.com/?p=637</link>
		<comments>http://www.jeffwofford.com/?p=637#comments</comments>
		<pubDate>Sat, 29 May 2010 19:30:43 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Crush the Castle]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=637</guid>
		<description><![CDATA[This series of posts is about converting an existing OpenGL 1 renderer into a &#8220;dual,&#8221; abstract renderer that can speak to either OpenGL 1 or OpenGL 2 depending on what the hardware supports. In the particular case that I&#8217;m working on, I&#8217;m taking Crush the Castle, which was written for OpenGL 1 hardware on the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jeffwofford.com/wp/wp-content/uploads/2009/10/CrushTheCastle-shot01.png"><img class="alignright size-medium wp-image-419" title="Crush the Castle: iPhone" src="http://www.jeffwofford.com/wp/wp-content/uploads/2009/10/CrushTheCastle-shot01-300x156.png" alt="Crush the Castle: iPhone" width="300" height="156" /></a>This <a title="Porting a Fixed-Function Game to a Programmable Pipeline" href="http://www.jeffwofford.com/?p=635">series of posts</a> is about converting an existing OpenGL 1 renderer into a &#8220;dual,&#8221; abstract renderer that can speak to either OpenGL 1 or OpenGL 2 depending on what the hardware supports. In the particular case that I&#8217;m working on, I&#8217;m taking <a title="Crush the Castle [iTunes]" href="http://www.jeffwofford.com/?p=635">Crush the Castle</a>, which was written for OpenGL 1 hardware on the earlier iPhones and iPod Touches, and I&#8217;m expanding it so that it can also support the OpenGL 2 hardware on later iPhones, iPod Touches, and iPads.</p>
<p><a title="Part 1 in this series" href="http://www.jeffwofford.com/?p=635"><span id="more-637"></span>Last time</a> I talked about taking my existing iPhone OpenGL renderer and refactoring it into an abstraction layer. This leaves me with an abstract Renderer class that looks like this.</p>
<pre>class Renderer
{
public:
	typedef unsigned int VertexBufferID;

	enum PrimitiveType	// Mirrors OpenGL ES Values.
	{
		PT_Points		= 0x0000,
		PT_Lines		= 0x0001,
		PT_LineLoop		= 0x0002,
		PT_LineStrip		= 0x0003,
		PT_Triangles		= 0x0004,
		PT_TriangleStrip 	= 0x0005,
		PT_TriangleFan		= 0x0006
	};

	enum MatrixIdentifier
	{
		MAT_ModelView,
		MAT_Projection,
		MAT_Texture
	};

	virtual ~Renderer() {}

	virtual Vector2D GetViewportDimensions() const = 0;
	virtual void SetViewport( const Rectanglei&amp; viewport ) = 0;

	virtual SmartPtr&lt; Texture &gt; CreateTexture(
		const std::string&amp; strFilename,
		Color colorKey = 0,
		bool keepAround = true ) = 0;
		// REQUIRES( strFilename.length() &gt; 0 );
		// PROMISES( result != 0 );

	virtual void ApplyTexture( Texture* pTexture ) = 0;
		// Use null to turn off texturing.

	virtual VertexBufferID CreateVertexBuffer(
		const std::vector&lt; Vector2f &gt;&amp; vecVertices ) = 0;
	virtual VertexBufferID CreateVertexBuffer(
		const Vector2f* arrVertices,
		size_t nElements ) = 0;
		// nElements counts the number of Vector2fs in the array.

	virtual void DeleteVertexBuffer( VertexBufferID&amp; idVertexBuffer ) = 0;
		// Deletes the buffer and sets the ID to 0.

	virtual void BindTextureID( unsigned int idTexture ) = 0;
	virtual void SetGeometryPointer( Vector2f* arrVertices ) = 0;
	virtual void SetGeometryVertexBuffer( VertexBufferID idVertexBuffer ) = 0;
	virtual void DrawGeometry( PrimitiveType primitiveType,
                                          int nVertices,
                                          int offset = 0 ) = 0;
	virtual void SetAlphaBlending( bool alphaBlend ) = 0;

	virtual void BeginVertices( PrimitiveType primitiveType ) = 0;
	virtual void AddVertex( float x, float y, float u = 0, float v = 0 ) = 0;
	virtual void EndVertices() = 0;

	// Matrix functions
	//
	virtual void SetOrthoProjection(Number left,
					Number right,
					Number top,
					Number bottom,
					Number zNear,
					Number zFar ) = 0;

	virtual void SetMatrixToIdentity(
                                   MatrixIdentifier whichMatrix = MAT_ModelView ) = 0;
	virtual void PushMatrix( MatrixIdentifier whichMatrix = MAT_ModelView ) = 0;
	virtual void PopMatrix( MatrixIdentifier whichMatrix = MAT_ModelView ) = 0;

	virtual void Rotate( Number angleDegrees,
			     MatrixIdentifier whichMatrix = MAT_ModelView ) = 0;
	virtual void Translate( const Vector2&lt; Number &gt;&amp; translation,
				MatrixIdentifier whichMatrix = MAT_ModelView ) = 0;
	virtual void Scale( const Vector2&lt; Number &gt;&amp; scale,
			    MatrixIdentifier whichMatrix = MAT_ModelView ) = 0;

	// Material color transform functions
	//
	virtual void PushColor() = 0;
	virtual void PopColor() = 0;
	virtual void SetColor( Color color ) = 0;
	virtual Color GetColor() const = 0;
	virtual void MultiplyColor( Color color ) = 0;

	virtual void ReportErrors() = 0;

	virtual Vector2D DrawText( const std::string&amp; text,
				  Font* pFont,
				  const Vector2D&amp; textULCorner,
				  const Vector2D&amp; fontScale,
				  const Vector2D&amp; spacingScale,
				  Color color = Color::White,
				  bool calculateMetricsOnly = false ) = 0;
		// REQUIRES( pFont != 0 );
		// REQUIRES( pFont-&gt;GetTexture() != 0 );

	FRESH_DECLARE_CLASS_ABSTRACT( Renderer )
};
</pre>
<p>Look at all those &#8220;= 0&#8243;&#8216;s after each method. This is a pure abstract class, merely an interface. It&#8217;s the RendererGLES1 class that inherits from and implements this interface.</p>
<p>What I did next was to create a second renderer implementation called RendererGLES2. This renderer also derives from Renderer and also implements all its functions. But whereas RendererGLES1 calls OpenGL 1 functions in its implementations, RendererGLES2, naturally, uses OpenGL ES 2.</p>
<p><a title="Part 3 in this series" href="http://www.jeffwofford.com/?p=698">Next time</a> I&#8217;ll show you how I implemented the OpenGL ES 2 version of the renderer, stripping out GL 1-specific functions and adding programmable shaders.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=637</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Porting a Fixed-Function Game to a Programmable Pipeline: Part 1</title>
		<link>http://www.jeffwofford.com/?p=635</link>
		<comments>http://www.jeffwofford.com/?p=635#comments</comments>
		<pubDate>Sat, 29 May 2010 19:30:15 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Crush the Castle]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[technology]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=635</guid>
		<description><![CDATA[I&#8217;ve started work on porting Crush the Castle from the iPhone/iPod Touch to the iPad. I thought I&#8217;d share some of the technical issues I&#8217;ve encountered while expanding the Crush the Castle renderer from an OpenGL 1-based system to a system that supports both OpenGL 1 and OpenGL 2. When my daughter wants the iPad [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jeffwofford.com/wp/wp-content/uploads/2009/10/CrushTheCastle-shot01.png"><img class="alignright size-medium wp-image-419" title="Crush the Castle: iPhone" src="http://www.jeffwofford.com/wp/wp-content/uploads/2009/10/CrushTheCastle-shot01-300x156.png" alt="Crush the Castle: iPhone" width="300" height="156" /></a>I&#8217;ve started work on porting <a title="Crush the Castle [iTunes]" href="http://itunes.com/apps/crushthecastle">Crush the Castle</a> from the iPhone/iPod Touch to the iPad. I thought I&#8217;d share some of the technical issues I&#8217;ve encountered while expanding the Crush the Castle renderer from an OpenGL 1-based system to a system that supports both OpenGL 1 and OpenGL 2.</p>
<p>When my daughter wants the iPad she asks for &#8220;the huge iPod.&#8221; That&#8217;s about right. Inside and out, the iPad is basically an exploding iPod.</p>
<p>One difference, though, is the graphics hardware. Older iPhones and iPod Touches used simpler graphics hardware that&#8217;s built on OpenGL ES 1.1. That&#8217;s the platform I built Crush the Castle on. The iPad uses a more modern graphics pipeline that&#8217;s built on OpenGL ES 2.0. From a programmer&#8217;s perspective, the big difference here is <em>programmable shaders</em>.</p>
<p>So my first job in bringing Crush the Castle to the iPad is upgrading the renderer from a fixed function, OpenGL ES 1.1-style system to a programmable, OpenGL ES 2.0-style system. If you&#8217;ve ever been interested in learning graphics programming with shaders, follow along with me and perhaps we can learn together.</p>
<p>In the articles that follow I&#8217;ll talk about iPhone/iPod  Touch/iPad development. But much of what I do would apply to anyone  working with OpenGL on any platform—PC, Mac, PS3, whatever. I&#8217;ll talk about OpenGL &#8220;ES&#8221;—the trimmed down, mobile version of OpenGL. But in  practice, Crush the Castle runs on non-&#8221;ES&#8221; versions of OpenGL, so the  &#8220;ES&#8221; is immaterial. I&#8217;m also working in C++. If you&#8217;re working in a  different language, like Java, C#, or Objective-C, you&#8217;ll have to read  between the lines a bit. But I&#8217;m mostly dealing in terms of design  patterns that aren&#8217;t specific to any particular language, so the leap  shouldn&#8217;t be too far.</p>
<p><span id="more-635"></span></p>
<h2>Creating an Abstraction Layer</h2>
<p>The first step in bringing Crush the Castle into the world of OpenGL 2 was refactoring my fixed-function renderer to use vertex and pixel shaders. In Crush the Castle, all rendering is handled through a class called—naturally enough—<em>Renderer</em>. This class offers functionality for setting up transforms, creating and setting vertex buffers, setting textures, handling render state (like whether alpha blending is turned on, for example), and of course initiating the actual rendering.</p>
<p>In this initial phase I wanted to keep the interface to the Renderer class as unchanged as possible. I wanted client code—the game code that asks for rendering to be done—to remain untouched wherever possible.</p>
<p>Moreover, I wanted to keep the current fixed function renderer completely intact. After all, Crush the Castle isn&#8217;t leaving the iPhone—it&#8217;s just gaining new platforms. So my Renderer class should support both OpenGL 1 and OpenGL 2, When you run the game it will ask the hardware whether GL 2 is available. If it is, it will use it. If it isn&#8217;t, the game will fall back to GL 1.</p>
<p>The first thing I did was to refactor my Renderer into an <em>abstraction layer</em>. An abstraction layer is a design pattern in which a single class &#8220;stands in&#8221; for one or more other classes that do the actual work. The &#8220;stand in&#8221; class is abstract in the technical sense. Although it declares functions, it doesn&#8217;t actually implement them. In Java terms, it&#8217;s an <em>interface</em>. The &#8220;working&#8221; classes derive from the abstract class, so they have the same interface. But they actually implement this interface.</p>
<p>The advantage of this setup is that user code can talk to the abstract interface class without bothering about how it&#8217;s actually being implemented. The implementation class in the background can even change—so there&#8217;s really no telling what it is, from the user&#8217;s perspective.</p>
<p>For Crush the Castle what I&#8217;ve done is to turn my Renderer class into an abstract interface. I then moved the Renderer implementation into a second, &#8220;behind the scenes&#8221; class—RendererGLES1. Just to give you a snippet of how this works, the two classes look something like this.</p>
<p>In Renderer.h:</p>
<pre>class Renderer
{
public:
    // ...
    virtual void Clear() = 0;
    // ...
};
</pre>
<p>In RendererGLES1.h:</p>
<pre>class RendererGLES1 : public Renderer
{
public:
    // ...
    virtual void Clear()
    {
        glClear();
    }
};
</pre>
<p>And now my user code looks something like this.</p>
<pre>void main()
{
    Renderer* pRenderer = new RendererGLES1();
    // ...
    pRenderer-&gt;Clear();
}
</pre>
<p>In practice, the process of converting my existing, concrete, OpenGL 1-based Renderer class into an abstraction layer with a concrete class in the background was a matter of simple refactoring.</p>
<ol>
<li>First, I copied my Renderer&#8217;s implementation files (Renderer.h and Renderer.cpp) to two new files called RendererGLES1.h and RendererGLES1.cpp.</li>
<li>Next, I gutted the original Renderer files. I stripped almost all the function implementations from Renderer.cpp. I got rid of most member variables from the Renderer class declaration. I converted almost all the method declarations into <a title="Pure Virtual [Wikipedia]" href="http://en.wikipedia.org/wiki/Virtual_function#Abstract_classes_and_pure_virtual_functions">pure virtual functions</a>.</li>
<li>With the original renderer gutted, I now made new renderer—RendererGLES1—inherit from Renderer. RendererGLES1 implemented all the functions that Renderer had implemented.</li>
<li>Finally, in the place where I previously had made a <em>new Renderer</em>, I now made a<em> new</em> <em>RendererGLES1</em>. But I kept all the pointers and references to Renderer the same. The game thought it was talking to a Renderer, but through the magic of virtual functions, it was actually talking to a RendererGLES2.</li>
</ol>
<p>At this point I was able to test the game to make sure that the refactoring had broken nothing. So far so good. But what—you may be asking—had I really gained? Hadn&#8217;t I just made more trouble for myself by turning one perfectly good class into an unwieldy and essentially redundant pair?</p>
<p>The benefit of this work came in the next step, which was to implement my OpenGL ES 2.0-based renderer. But I&#8217;m out of time today, so—more on that <a title="Part 2 in this series" href="http://www.jeffwofford.com/?p=637">next time!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=635</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Roll Along, Roll Along</title>
		<link>http://www.jeffwofford.com/?p=628</link>
		<comments>http://www.jeffwofford.com/?p=628#comments</comments>
		<pubDate>Sat, 17 Apr 2010 22:57:44 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[thinking]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=628</guid>
		<description><![CDATA[Coffee doesn&#8217;t taste as good to me as it used to. Once upon a time my morning cappuccino would have me turning up my face and closing my eyes in a prayer of thanksgiving. Now I wait for a rapture that never comes. I stare into the froth of a caramel macchiato wondering where all [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-713" title="Leaf ornament" src="http://www.jeffwofford.com/wp/wp-content/uploads/2010/04/leaf.png" alt="Leaf" width="150" height="150" />Coffee doesn&#8217;t taste as good to me as it used to.</p>
<p>Once upon a time my morning cappuccino would have me turning up my face and closing my eyes in a prayer of thanksgiving. Now I wait for a rapture that never comes. I stare into the froth of a caramel macchiato wondering where all the marvel went. I tweak the recipe—a little less foam, a little more sweet—but nothing ever brings me back to how it used to be.</p>
<p>It&#8217;s not just the coffee. The spring—princess of seasons—has lost the magic it once had. Who can be unmoved by a field of Texas wildflowers? Yet the spiders and mosquitoes and the early rising heat make me wish it was midwinter again.</p>
<p>Yesterday&#8217;s delights fade too soon. Still, today is not without its charms. My son is becoming a man, growing from child into peer and friend. In the evenings my daughters and I tumble into Wonderland (as told by Lewis Carroll—I&#8217;ll have nothing to do with the film). Every day I learn a thousand things both in my studies and through my teaching. I enjoy every day.</p>
<p>So old delights fade as new delights arrive. I&#8217;m sure that&#8217;s how it should be.</p>
<p>In college, my wife and I loved Jeremy Brett&#8217;s <em>Sherlock Holmes</em>. Recently we tried watching the old episodes. They were still fun, but a little tired. I can&#8217;t quite manage to completely forget the solutions to all Sherlock&#8217;s problems.</p>
<p>Although we can&#8217;t resurrect our love of Holmes, we have discovered a new love<em>—Nodame Cantabile</em>, an anime series about musicians in college.</p>
<p>It seems that joys have a way of rolling around.</p>
<p>This realization has led me to a resolution. Don&#8217;t try to regain the pleasures of the past. Enjoy the pleasures of the moment.</p>
<p>Tomorrow they&#8217;ll have faded too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=628</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The Christian Storyteller&#8217;s Dilemma</title>
		<link>http://www.jeffwofford.com/?p=620</link>
		<comments>http://www.jeffwofford.com/?p=620#comments</comments>
		<pubDate>Tue, 23 Feb 2010 04:36:03 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[culture]]></category>
		<category><![CDATA[faith]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=620</guid>
		<description><![CDATA[There&#8217;s no good way to tell a Christian story. The gospel is perennially uncool. Any story that points to the gospel runs the risk of inheriting its uncoolness. A Christian yarn may end up sounding like a sermon. It may come across as moralizing, over-hopeful, or lacking the secular sheen that modern readers demand. A [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-medium wp-image-709" title="Lucy and Tumnus from &quot;The Lion, the Witch, and the Wardrobe&quot;" src="http://www.jeffwofford.com/wp/wp-content/uploads/2010/02/lucy-tumnus-lww-283x300.jpg" alt="Lucy and Tumnus" width="283" height="300" />There&#8217;s no good way to tell a Christian story.</p>
<p>The gospel is perennially uncool. Any story that points to the gospel runs the risk of inheriting its uncoolness. A Christian yarn may end up sounding like a sermon. It may come across as moralizing, over-hopeful, or lacking the secular sheen that modern readers demand. A story designed to draw people to the gospel may end up repelling them instead.</p>
<p>How can a Christian writer craft a story that appeals to the culture while pointing beyond it?</p>
<p><span id="more-620"></span></p>
<h2>The Moral Proverb</h2>
<p>The simplest way for Christians to tell edifying, appealing stories is to talk about how people do and should live. Most successful stories—secular and otherwise—are moral fables.</p>
<p>As Robert McKee explains in his scriptwriting masterpiece <em>Story</em>, all the films we love have an essentially moral message. Great and successful movies—from <em>Casablanca </em>to <em>Star Wars </em>to <em>The Godfather—</em>teach us how to live and how not to.</p>
<p>Pixar&#8217;s most lucrative film to date is <em>Finding Nemo.</em> The moral core of the movie is easy to spot. The question that it asks is &#8220;When is it right to seek control and when to let go?&#8221; The protagonist, Marlin, is terrified of life and seeks to control his son Nemo. His traveling companion Dory has no control—she constantly forgets the past. She embraces her lack of control and approaches every minute as a new, usually delightful, adventure. The story of how Marlin learns to trust Fate and give up control is the driving force behind the story. <!--more-->Since both children and parents struggle with this question, the film appealed to both.</p>
<p>For the Christian writer, the moral proverb offers a good way to tell a story that helps people think through questions of morality and wisdom without violating social norms about how we talk about religion and ethics.</p>
<p>The book of Proverbs provides a model for this kind of story. A proverb like &#8220;The borrower is the lender&#8217;s slave,&#8221; isn&#8217;t a weird religious idea. It&#8217;s good plain common sense. So we can follow the example of Proverbs by telling stories that portray the best way to live.</p>
<h2>Explicit Conversion</h2>
<p>The trouble with Moral Proverbs is that they don&#8217;t go far enough. The essence of the Christian message is that try as we might, human beings simply <em>don&#8217;t</em> do good. Proverbs can help improve behavior. They can steer us away from the most damaging mistakes. They can help us recognize our inability to do good. But they do not make us good. If all the world needed was a little more ethical education, Jesus didn&#8217;t need to die on a cross. The gospel begins with the idea that moral education is not enough—that Jesus himself is the key to living the human life well.</p>
<p>This leads us to the second way that Christian writers can frame their stories. A story that shows a character hitting bottom, recognizing her sinfulness, accepting Christ&#8217;s death and resurrection, and experiencing life transformation portrays the gospel explicitly.</p>
<p>The only place in a modern bookstore where you&#8217;ll find this kind of story in abundance is in the Christian fiction section. That&#8217;s a pity, because the Christians who shop in this section are precisely the people who least benefit from these kinds of stories.</p>
<p>Yet some of the greatest novels of all time are explicit gospels. Dostoyevsky&#8217;s <em>The Brothers Karamazov. </em>Tolstoy&#8217;s <em>Anna Karenina. </em>In each of these tales we watch one of the main characters undergo a conversion. John Bunyan&#8217;s <em>Pilgrim&#8217;s Progress</em> is another familiar example, though here again mainly Christians read it.</p>
<p>Christian writers yearn to portray the gospel explicitly in their stories. The gospel is, after all, the deepest and truest solution to every human life. It is the ultimate resolution to every plot. But secular publishers, reviewers, and readers will tend to see a novel with an explicit gospel as idiosyncratic and sectarian, no matter how superb the rest of the storytelling is. So an explicit gospel is rarely a good option for authors wanting to tell their stories to a broad audience.</p>
<h2>The Metaphorical/Allegorical Gospel</h2>
<p>C. S. Lewis&#8217;s <em>The Lion, the Witch, and the Wardrobe</em> offers an oft-discussed option for portraying the gospel in a socially acceptable way. Throughout the Narnia series, Lewis portrayed Jesus as Aslan the Lion. Although it was easy enough to perceive that Aslan was Jesus, the distinction made the story more oblique, less jarring, and more intriguing.</p>
<p>All the elements of the gospel are present in the series—particularly in its first book. Satan is there as the White Witch. Sinners are represented by Edmund. God the Father is described as &#8220;The Emperor Over the Sea.&#8221; The cross appears as the Stone Table. Lewis tells the gospel, but he tells it allegorically. This has the effect both of veiling it—making it harder to reject outright—and of illuminating it, giving us a fresh perspective on the Christian story.</p>
<p>Although many admire what Lewis did, metaphorical and allegorical retellings of the gospel are uncommon in fiction literature. Perhaps Lewis did his job so well that few others feel the need to retread that ground.</p>
<h2>Tight-Lipped Conversion</h2>
<p>One of the most generally useful ways of portraying the gospel in a secular story is to show the beginning and the end of a conversion without showing the middle. In this kind of story, we see a character hitting bottom. Later we see them transformed and whole. We are not told explicitly what happened between their collapse and their renewal, but we are given hints that they experienced Christian conversion.</p>
<p>Take for example this imaginary novel. One of the secondary characters—we&#8217;ll call him Ryan—is a professional louse. He&#8217;s rude and selfish, a drunk and a womanizer. Through the first half of the novel we watch Ryan deteriorate. Every time we see him he is worse off than before. By the midpoint of the book he is unshaven, unkempt, basically homeless after his last girlfriend booted him out, and constantly drunk. Then, for a few chapters, Ryan disappears. None of the other characters know what happened to him and no one particularly cares.</p>
<p>Suddenly Ryan shows up again, and he&#8217;s different. He&#8217;s still badly shaven but at least somebody washed him. He doesn&#8217;t reek of bourbon. But the big difference lies in his eyes, his face. As we hear him speak it&#8217;s with a different voice—now humble, helpful, not without wit but far more reserved.</p>
<p>The other characters mutter for a chapter or so about the transformed Ryan. Finally someone comes around to asking him what happened. &#8220;I finally found someone who loved me enough to kick me in the seat.&#8221; Then we notice that the gold chains that use to decorate his neck have been replaced with a simple cross.</p>
<p>In one sense, a tight-lipped conversion like Ryan&#8217;s is a reduction of the gospel. It draws back from an explicit portrayal of Christian faith. But this sacrifice of explicitness is offered in exchange for accessibility. Secular readers may not receive the full gospel but they do get a story they can understand and enjoy. Although the gospel itself remains hidden, the pattern of moral destitution and recovery that characterizes the sincere Christian believer is clearly portrayed.</p>
<p>Tight-lipped conversions serve as an invitation to an inspiring—if vague—hope. Ryan&#8217;s cross is a clue that you can ignore or pursue. You may ignore it now, but if you ever find yourself in a dark place like Ryan&#8217;s, maybe you&#8217;ll investigate further.</p>
<h2>Prefiguration Stories</h2>
<p>The gospel is a rich and complex story with many different parts and ideas. We cannot understand what Christ did on the cross without grasping these underlying ideas. Sin, holiness, righteousness, love, covenant, forgiveness, atonement, sacrifice, redemption—all of these elements are fundamental to the gospel story.</p>
<p>The Old Testament does not explain the gospel, but it does prefigure it. The Hebrew Scriptures portrayed each of these fundamental elements so that the gospel would make sense when Christ enacted it.</p>
<p>In the same way, modern writers can prefigure the gospel in the minds of their readers by portraying certain elements in clear, vivid terms. A novel that clearly portrays the horror of sin, for example, paves the way for its readers to grasp why God demands retribution for sin.</p>
<p>A wonderful and perhaps surprising example of a prefiguration story is <em>The Lord of the Rings</em> by Catholic author J. R. R. Tolkien. Tolkien&#8217;s novel prefigures the gospel in many different ways, but one of the most obvious is in his portrayal of the hero Frodo.</p>
<p>What is it that makes Frodo a hero? It&#8217;s not his strength, his prowess with a weapon. It&#8217;s not his wit, his cleverness or charm. It&#8217;s not even, precisely, his courage—though his courage is considerable. What makes Frodo such a remarkable hero is two qualities that are fundamentally Christian.</p>
<p>First, Frodo trusts that Fate as he understands it—the unnamed God who lovingly and sovereignly presides over Middle Earth—will snatch victory from the jaws of defeat. Although Frodo&#8217;s own efforts are feeble and basically foolhardy, he trusts that God will honor his obedience and the prayers of his friends by granting victory over the evil Sauron.</p>
<p>Frodo&#8217;s second heroic quality is his self-sacrifice. Frodo fully recognizes that although his quest may bring peace to Middle Earth, it will probably destroy him. Indeed, Frodo&#8217;s quest <em>does</em> destroy him—he returns as Frodo the Nine-Fingered, wounded and in some sense humiliated. He is haunted by his attachment to the Ring, cannot settle back into life in his old home the Shire, and ultimate abandons Middle Earth to travel to the Uttermost West—a symbol for the afterlife. Frodo accepts the mantle that Fate places upon him despite the terrible cost to himself. This is a Christian view of heroism. It is evocative on Christ&#8217;s own quest.</p>
<p>Christian stories can serve the gospel by vividly showing parts of it. Readers may not understand the gospel through a story like <em>The Lord of the Rings</em>, but they do begin to grasp and to love some of the values and ideas that feed into the grand gospel narrative.</p>
<h2>Other Models?</h2>
<p>Are there are models for how Christians can tell stories that honor the gospel without smacking readers in the face with it? I&#8217;m still searching for solutions to this tension. Please share your ideas!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=620</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>January Blues</title>
		<link>http://www.jeffwofford.com/?p=572</link>
		<comments>http://www.jeffwofford.com/?p=572#comments</comments>
		<pubDate>Sat, 16 Jan 2010 21:03:27 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=572</guid>
		<description><![CDATA[January is the most disappointing of months. The excitement of the holidays is over. We&#8217;re back to work with no end in sight. The weather remains dreary. It&#8217;s like Demember&#8217;s evil twin, with a turtleneck and goatee. I wrote this song years ago to cheer myself up. Maybe it&#8217;ll cheer you up too. I haven&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>January is the most disappointing of months. The excitement of the holidays is over. We&#8217;re back to work with no end in sight. The weather remains dreary. It&#8217;s like Demember&#8217;s evil twin, with a turtleneck and goatee.</p>
<p>I wrote this song years ago to cheer myself up. Maybe it&#8217;ll cheer you up too.</p>
<p><span id="more-572"></span></p>
<div style="padding-left: 0.5in; font-style: italic;">
<p>I haven&#8217;t been looking out the window much lately<br />
I haven&#8217;t watching when the birds come to feed<br />
Don&#8217;t want to feel anything<br />
Can&#8217;t always be on the wing<br />
Life slips on by&#8230;</p>
<p>I haven&#8217;t been looking at the stars much lately<br />
The city&#8217;s too bright and the nights are too cold<br />
There&#8217;ll be plenty of country nights<br />
To look up and count those lights<br />
Life slips on by&#8230;</p>
<p><a href="http://www.jeffwofford.com/wp/wp-content/uploads/2009/12/january.jpg"><img class="alignright size-full wp-image-577" style="border: 3px solid black;" title="January, from Les Tres Riches Heures du Duc de Berry" src="http://www.jeffwofford.com/wp/wp-content/uploads/2009/12/january.jpg" alt="" width="270" height="435" /></a>Christmas is a memory of a memory<br />
I can&#8217;t help losing<br />
Mother when your child is grown<br />
Virgin when your secret&#8217;s known<br />
We fade away</p>
<p>Don&#8217;t you worry yourself now<br />
I&#8217;ll find my way back somehow<br />
Just got those &#8220;new year&#8217;s getting old already&#8221;<br />
January Blues</p>
<p>I haven&#8217;t been looking in your eyes like I used to<br />
I know that you feel it when I don&#8217;t kiss you right<br />
Sometimes you gotta come down<br />
The makeup comes off the clown<br />
Life slips on by&#8230;</p>
<p>If I could erase my mind<br />
Feel it all again for the first time<br />
Singer when the song is done<br />
Runner when the race is won<br />
We fade away</p>
<p>Don&#8217;t you worry yourself now<br />
I&#8217;ll find my way back somehow<br />
Maybe I just need some time</p>
<p>Just got those &#8220;new year&#8217;s getting old already&#8221;<br />
January Blues</p>
<p>I haven&#8217;t been watching when the storms come up lately<br />
Keep watching the T.V. as the lightning flashes ‘round<br />
I&#8217;ve lived a little too much<br />
Just gotta get out of touch<br />
Life slips on by&#8230;</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=572</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://www.jeffwofford.com/music/Jeff%20Wofford%20-%20January%20Blues.mp3" length="3915732" type="audio/mpeg" />
		</item>
		<item>
		<title>Never in a Hundred Million Years Will You Ever Sell Your Game Idea to a Company</title>
		<link>http://www.jeffwofford.com/?p=605</link>
		<comments>http://www.jeffwofford.com/?p=605#comments</comments>
		<pubDate>Fri, 15 Jan 2010 15:46:34 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[games]]></category>

		<guid isPermaLink="false">http://www.jeffwofford.com/?p=605</guid>
		<description><![CDATA[A while back I posted an article on How to Get Your Game Idea Made into a Game. Since that article appeared I&#8217;ve received hundreds of emails telling me about ideas that you&#8217;d like to see made into a game. I appreciate your openness in talking about your ideas with me. I applaud your drive [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-medium wp-image-716" title="PS3 Sonar Patent" src="http://www.jeffwofford.com/wp/wp-content/uploads/2010/01/ps3-sonar-patent-300x265.jpg" alt="PS3 Sonar Patent" width="300" height="265" />A while back I posted an article on <a title="How to Get Your Game Idea Made into a Game" href="http://www.jeffwofford.com/?p=151">How to Get Your Game Idea Made into a Game</a>. Since that article appeared I&#8217;ve received hundreds of emails telling me about ideas that you&#8217;d like to see made into a game.</p>
<p>I appreciate your openness in talking about your ideas with me. I applaud your drive in moving forward and trying to get your ideas made.</p>
<p>But your questions have made me realize that I wasn&#8217;t clear enough in my first post. So let me be clear.</p>
<p style="text-align: center;"><strong>Never in a hundred million years will you ever sell your game idea to a company.</strong></p>
<p style="text-align: left;">Game developers never, ever, ever, ever, ever buy game ideas. Game publishers never, ever, ever, ever, ever buy game ideas.</p>
<p style="text-align: left;"><span id="more-605"></span>They never accept free game ideas. They will not even <em>listen</em> to your ideas.</p>
<p style="text-align: left;">You have <strong>no</strong> chance—<strong>Zero Percent</strong>—of ever selling any game idea to a game company. If you want to get your game idea made into a game, talking to game companies about it is a total waste of time and energy.</p>
<p style="text-align: left;">The brilliance of your idea has nothing to do with your chances of getting a company to make the idea. If your idea is mediocre you have a 0% chance of getting a company to make it. If your idea is the greatest game idea that mankind has ever seen, you still have a 0% chance of getting a company to make it.</p>
<p style="text-align: left;">Game companies do not buy ideas. They do not accept free ideas. You will never get a company to make your idea.</p>
<p style="text-align: left;">Okay, is that clear now?</p>
<p style="text-align: left;">You know, <strong>I don&#8217;t <em>enjoy</em> crushing people&#8217;s hopes.</strong> I know what a powerful, passionate feeling it is to have a game idea that you can see and hear and smell and taste. You know just how it would look and play. You can see the awesome boss monsters, the wrenching camera angles, the astounding visual effects. It seems <em>so</em> real. The vision in your mind feels <em>so close</em> to the games you play on your screen.</p>
<p style="text-align: left;">The only thing standing between you and making your game a reality is $20 million. If you only had eighty or so highly-trained, experienced game programmers, artists, and designers working 60 hours a week for three years, your game could get made and become a hit! If only a game company would fall in love with your idea as you and your friends have, you could see your vision become reality.</p>
<p style="text-align: left;">I know how that hope feels. It feels something like lovesickness. You can&#8217;t stand the thought of your awesome idea wasting away in the obscurity of a few shabby pencil drawings. It deserves better!</p>
<p style="text-align: left;">I know what that feels like. Like I said, I don&#8217;t enjoy crushing your hopes.</p>
<p style="text-align: left;">But false hopes will get you nowhere. And I&#8217;m here to tell you, as someone who has worked in the game industry for 15 years, that you will never, ever get a company to make your idea. That&#8217;s a false hope. Don&#8217;t waste your time on it.</p>
<p style="text-align: left;">But there <em>is</em> a way to get your game idea made into a game. Two ways, in fact.</p>
<ol>
<li>Make it yourself.</li>
<li>Build a career in game development.</li>
</ol>
<p>Making it yourself either means spending a ton of money (millions!) to hire other people to make it. Or it means gathering a group of friends to work on the game on an amateur basis. That will probably mean scaling down the quality and scope of your vision, but you can still make the essence of your idea.</p>
<p>Building a career in game development means spending 10-15 years working on other peoples&#8217; games until you&#8217;ve gained enough power and respect to call the shots. If you can win that kind of respect you might be able to make your own game. But 10-15 years is a long, hard road to walk. And even if you walk it, you may never win the chance to call your own shots. I&#8217;ve made dozens of games since I started in 1995, yet it&#8217;s rare that I get to choose which game to make. The people with the money decide what gets made. That&#8217;s just the reality of the business.</p>
<p>So you <em>can</em> get your idea made. But it&#8217;s not going to be easy. And it&#8217;s not going to happen through talking to a company.</p>
<p>You can read more about your options for getting a game idea made in my <a title="How to Get Your Game Idea Made into a Game" href="http://www.jeffwofford.com/?p=151">previous post</a> on this topic.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffwofford.com/?feed=rss2&amp;p=605</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
