<?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>Encelo's Blog &#187; snippets</title>
	<atom:link href="http://encelo.netsons.org/blog/tag/snippets/feed/" rel="self" type="application/rss+xml" />
	<link>http://encelo.netsons.org/blog</link>
	<description>When I grow up I want to be a game developer</description>
	<lastBuildDate>Mon, 02 Nov 2009 23:49:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>High Dynamic Range galore</title>
		<link>http://encelo.netsons.org/blog/2009/10/14/high-dynamic-range-galore/</link>
		<comments>http://encelo.netsons.org/blog/2009/10/14/high-dynamic-range-galore/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 19:42:50 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Real-time Graphics]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[GLSL]]></category>
		<category><![CDATA[HDR]]></category>
		<category><![CDATA[High Dynamic Range]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[post-processing]]></category>
		<category><![CDATA[shaders]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=378</guid>
		<description><![CDATA[In January, during my internship activity, I was researching in the field of HDR imaging, today I had the time, at last, to polish a bit and release the two demos I made at the time.
They both load an RGBE image (the two you see here are courtesy of the Paul Devebec&#8217;s Light Probe Image [...]]]></description>
			<content:encoded><![CDATA[<p>In January, during my internship activity, I was researching in the field of HDR imaging, today I had the time, at last, to polish a bit and release the two demos I made at the time.</p>
<p>They both load an <a href="http://en.wikipedia.org/wiki/RGBE_image_format">RGBE</a> image (the two you see here are courtesy of the Paul Devebec&#8217;s <a href="http://www.debevec.org/probes/">Light Probe Image Gallery</a>) through the <a href="http://www.graphics.cornell.edu/online/formats/rgbe/">library</a> of Bruce Walter.</p>
<div id="attachment_382" class="wp-caption aligncenter" style="width: 310px"><a href="http://encelo.netsons.org/blog/wp-content/uploads/2009/10/hdr_strip1.png"><img src="http://encelo.netsons.org/blog/wp-content/uploads/2009/10/hdr_strip1-300x100.png" alt="Light probe at different exposure levels (hdr_load1)" title="hdr_strip1" width="300" height="100" class="size-medium wp-image-382" /></a><p class="wp-caption-text">Light probe at different exposure levels (hdr_load1)</p></div>
<p>The first demo implements the technique described in the article <a href="http://www.gamedev.net/columns/hardcore/hdrrendering/">High Dynamic Range Rendering</a> published on GameDev.net and is based on five passes and four FBOs:</p>
<ol>
<li>Rendering of the floating-point texture in an FBO</li>
<li>Down-sampling in a 1/4 FBO and high-pass filter</li>
<li>Gaussian filter along the X axis</li>
<li>Gaussian filter along the Y axis</li>
<li>Tone-mapping and composition</li>
</ol>
<p>The algorithm is very simple, it first renders the original scene then it extracts bright parts at the second pass, which merely discards fragments which are below a specified threshold:</p>
<pre class="brush: cpp;">
// excrpt from hipass.frag
if (colorMap.r &gt; 1.0 || colorMap.g &gt; 1.0 || colorMap.b &gt; 1.0)
	gl_FragColor = colorMap;
else
	gl_FragColor = vec4(0.0);
</pre>
<p>While the third and fourth passes blurs the bright mask, the last one mixes it with the first FBO and sets exposure and gamma to achieve a bloom effect.</p>
<pre class="brush: cpp;">
// excerpt from tonemap.frag
gl_FragColor = colorMap + Factor * (bloomMap - colorMap);
gl_FragColor *= Exposure;
gl_FragColor = pow(gl_FragColor, vec4(Gamma));
</pre>
<div id="attachment_382" class="wp-caption aligncenter" style="width: 310px"><a href="http://encelo.netsons.org/blog/wp-content/uploads/2009/10/hdr_strip2.png"><img src="http://encelo.netsons.org/blog/wp-content/uploads/2009/10/hdr_strip2-300x100.png" alt="Light probe at different exposure levels (hdr_load2)" title="hdr_strip2" width="300" height="100" class="size-medium wp-image-382" /></a><p class="wp-caption-text">Light probe at different exposure levels (hdr_load2)</p></div>
<p>The second demo implements the technique described in the article <a href="http://www.ziggyware.com/readarticle.php?article_id=226">High Dynamic Range Rendering in XNA</a> published on Ziggyware and is based on seven passed and more than five FBOs:</p>
<ol>
<li>Rendering of the floating-point texture in an FBO</li>
<li>Calculating maximum and mean luminance for the entire scene</li>
<li>Bright-pass filter</li>
<li>Gaussian filter along the X axis</li>
<li>Gaussian filter along the Y axis</li>
<li>Tone-mapping</li>
<li>Bloom layer addition</li>
</ol>
<p>This approach is far more complex than the previous one and is based on converting the scene to its <a href="http://en.wikipedia.org/wiki/Luma_%28video%29">luminance</a> (defined as <em>Y = 0.299*R + 0.587*G + 0.114*B</em>) version, the mean and maximum value can be calculated using a particular downsampling shader and working in more passes, at each one rendering on an FBO with a smaller resolution than the previous until the last pass, when you render the luminance of the entire scene on a 1&#215;1 FBO.</p>
<p>As usual you can have a look at YouTube (<a href="http://www.youtube.com/watch?v=D93glosIbbo">GLSL_hdrload1</a>, <a href="http://www.youtube.com/watch?v=BRdkseJs7t0">GLSL_hdrload2</a>) or Vimeo (<a href="http://vimeo.com/7067100">GLSL_hdrload1</a>, <a href="http://vimeo.com/7067374">GLSL_hdrload2</a>) videos and download the <a href="http://encelo.netsons.org/_download/glsl_hdrload.tar.gz">sources</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2009/10/14/high-dynamic-range-galore/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A flexible PLY loader for Evolution War r71</title>
		<link>http://encelo.netsons.org/blog/2009/09/16/a-flexible-ply-loader-for-evolution-war-r71/</link>
		<comments>http://encelo.netsons.org/blog/2009/09/16/a-flexible-ply-loader-for-evolution-war-r71/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 01:28:33 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[Evolution War]]></category>
		<category><![CDATA[GameDev]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=290</guid>
		<description><![CDATA[I&#8217;ve cited Evolution War for the first time on this blog in my previous post, today I want to celebrate my return to SVN committing after a very long time.  

Revision 71 adds the support for a real Stanford PLY parser and loader, while the one I coded for my graphic class library is [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve cited <a href="http://www.evolution-war.com">Evolution War</a> for the first time on this blog in my <a href="/blog/2009/08/28/summer-summary/">previous post</a>, today I want to celebrate my return to SVN committing after a very long time. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p><img src="http://encelo.netsons.org/blog/wp-content/uploads/2009/09/ply_export.png" alt="PLY Export" title="PLY Export" width="400" height="175" class="aligncenter size-full wp-image-295" /></p>
<p>Revision 71 adds the support for a real <a href="http://en.wikipedia.org/wiki/PLY_%28file_format%29">Stanford PLY</a> parser and loader, while the one I coded for my graphic class library is very primitive, expecting a hard-coded order for data, this one shouldn&#8217;t have any kind of problem with every well-formed PLY file.</p>
<p>For example, while the hard-coded loader can only accept a file like this:</p>
<pre class="brush: plain;">
ply
format ascii 1.0
comment Created by Blender3D 249 - www.blender.org
element vertex 4
property float x
property float y
property float z
property float nx
property float ny
property float nz
element face 3
property list uchar uint vertex_indices
end_header
1.000000 2.000000 3.000000 -4.000000 -5.000000 6.000000
-1.000000 -2.000000 -3.000000 4.000000 5.000000 6.000000
1.000000 2.000000 3.000000 -4.000000 -5.000000 6.000000
-1.000000 -2.000000 -3.000000 4.000000 5.000000 6.000000
3 0 1 2
3 1 3 2
3 4 2 1
</pre>
<p>the parser loader can load even something like this:</p>
<pre class="brush: plain;">
ply
format ascii 1.0
comment Created and shuffled by hand
element face 3
property list uchar uint vertex_indices
element skipme 3
property float skipfirst
property float skipsecond
element vertex 4
property float z
property float nz
property float y
property float ny
property float nx
property float x
end_header
3 0 1 2
3 1 3 2
3 4 2 1
0.0 0.0
0.0 0.0
0.0 0.0
3.000000 -6.000000 2.000000 -5.000000 -4.000000 1.000000
-3.000000 6.000000 -2.000000 5.000000 4.000000 -1.000000
3.000000 -6.000000 2.000000 -5.000000 -4.000000 1.000000
-3.000000 6.000000 -2.000000 5.000000 4.000000 -1.000000
</pre>
<p>But one of its most important feature resides in the ability to correctly load <em>binary</em> PLY files! <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Related to it there&#8217;s a bug I would like to share with you together with the fix:</p>
<pre class="brush: cpp;">
istream&amp; istream::read (char* s, streamsize n);
[...]
ifstream ifs;
unsigned int *uIndices;
[...]
ifs.read((char *) uIndices+(j*3), sizeof(unsigned int) * 3);
</pre>
<p>The <tt>read()</tt> method only accepts <tt>char</tt> pointers, so <tt>uIndices</tt> is casted, but the precedence goes to casting and not to native <tt>unsigned int</tt> pointer arithmetics, leading to catastrophic effects! <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> </p>
<p>The fix was as simple as the bug was subtle:</p>
<pre class="brush: diff;">
-ifs.read((char *) uIndices+(j*3), sizeof(unsigned int) * 3);
+ifs.read((char *) (uIndices+(j*3)), sizeof(unsigned int) * 3)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2009/09/16/a-flexible-ply-loader-for-evolution-war-r71/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Converting weights to vertex colors</title>
		<link>http://encelo.netsons.org/blog/2009/04/19/converting-weights-to-vertex-colors/</link>
		<comments>http://encelo.netsons.org/blog/2009/04/19/converting-weights-to-vertex-colors/#comments</comments>
		<pubDate>Sun, 19 Apr 2009 12:34:39 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[3d Graphics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Blender]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=206</guid>
		<description><![CDATA[If you have read my LinkedIn profile lately you should already know that, by now, some months have passed since I started my pre-graduation internship activity at Raylight (and since I signed my first NDA   ).
The real-time graphic R&#038;D work that I&#8217;m doing there for my thesis is enjoying and stimulating, but this [...]]]></description>
			<content:encoded><![CDATA[<p>If you have read my <a href="http://www.linkedin.com/in/encelo">LinkedIn profile</a> lately you should already know that, by now, some months have passed since I started my pre-graduation internship activity at <a href="http://www.raylightgames.com/">Raylight</a> (and since I signed my first <a href="http://en.wikipedia.org/wiki/Non-disclosure_agreement">NDA</a> <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).<br />
The real-time graphic R&#038;D work that I&#8217;m doing there for my thesis is enjoying and stimulating, but this is not the topic of the post&#8230;</p>
<p><a href="http://www.raylightgames.com"><img src="http://encelo.netsons.org/blog/wp-content/uploads/2009/04/raylight_logo.jpg" alt="Raylight logo" title="Raylight logo" width="640" height="160" class="alignnone size-full wp-image-210" /></a></p>
<p>Some days ago a 3d artist of the team, <a href="http://www.aardolino.com/">Alessandro</a>, asked me a script that would have helped him using Blender for one more task along the company asset creation pipeline, weight painting.<br />
He  needed a simple script to actually convert vertex weights to per-bone vertex colors layers, in order to bake them to per-bone UV maps and later import them inside 3d Studio Max.</p>
<table align="center">
<tr>
<td>
<div id="attachment_213" class="wp-caption alignnone" style="width: 160px"><a href="http://encelo.netsons.org/blog/wp-content/uploads/2009/04/weight.png"><img src="http://encelo.netsons.org/blog/wp-content/uploads/2009/04/weight-150x150.png" alt="Weight painting" title="Weight painting" width="150" height="150" class="size-thumbnail wp-image-213" /></a><p class="wp-caption-text">Weight painting</p></div>
</td>
<td>
<div id="attachment_214" class="wp-caption alignnone" style="width: 160px"><a href="http://encelo.netsons.org/blog/wp-content/uploads/2009/04/vcol.png"><img src="http://encelo.netsons.org/blog/wp-content/uploads/2009/04/vcol-150x150.png" alt="Vertex painting" title="Vertex painting" width="150" height="150" class="size-thumbnail wp-image-214" /></a><p class="wp-caption-text">Vertex painting</p></div>
</td>
</tr>
</table>
<p>At first I didn&#8217;t even know where to start, how to extract and match per-vertex weight data with per-face vertex color one, but my second try with it went as smoothly as honey.<br />
The core algorithm is, indeed, very simple:</p>
<pre class="brush: python;">
for f in faces:
  for i,v in enumerate(f):
      infs = me.getVertexInfluences(v.index)
      for vgroup, w in infs:
        me.activeColorLayer = vgroup
        col = f.col[i]
        col.r = col.g = col.b = int(255*w)
</pre>
<p>Well, he has not yet taken advantage of it nor I know if he will ever use it, nevertheless the script is working and I have <a href="/_download/weight_to_vcol.py.gz">shared it</a> on my site, as usual. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2009/04/19/converting-weights-to-vertex-colors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Habemus OpenGL 3.0!</title>
		<link>http://encelo.netsons.org/blog/2009/01/16/habemus-opengl-30/</link>
		<comments>http://encelo.netsons.org/blog/2009/01/16/habemus-opengl-30/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 18:47:30 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Real-time Graphics]]></category>
		<category><![CDATA[GLX]]></category>
		<category><![CDATA[Nvidia]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[OpenGL3]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=164</guid>
		<description><![CDATA[We have been waiting OpenGL 3.0 for ages, we were all very excited about the wonderful features ARB was promising, then, on the 11th of August 2008, the specs were released&#8230;
I, like everyone else, was really disappointed, the Architecture Review Board was not only really late on schedule but it didn&#8217;t keep its word about [...]]]></description>
			<content:encoded><![CDATA[<p>We have been waiting OpenGL 3.0 for ages, we were all very excited about the wonderful features ARB was promising, then, on the 11th of August 2008, the <a href="http://opengl.org/documentation/specs/">specs</a> were released&#8230;<br />
I, like everyone else, was really disappointed, the <a href="http://www.opengl.org/about/arb/">Architecture Review Board</a> was not only really late on schedule but it didn&#8217;t keep its word about many key features that should have been introduced with this release.<br />
Nevertheless I&#8217;m still confident in the future, when older API functions will be <em>removed</em> and not simply, as in the current version, tagged as deprecated.</p>
<p><img src="http://encelo.netsons.org/blog/wp-content/uploads/2009/01/opengl-3-logo.jpg" alt="OpenGL3 Logo" title="OpenGL3 Logo" width="400" height="118" class="alignnone size-full wp-image-172" /></p>
<p>Now, after the long but needed introduction, let&#8217;s talk about things that matter: today the <a href="http://www.archlinux.org">ArchLinux</a> team moved the new stable 180.22 driver release from the <tt>[testing]</tt> to the <tt>[extra]</tt> repository.<br />
Well, apart from the equally important <a href="http://en.wikipedia.org/wiki/CUDA">CUDA 2.1</a> and <a href="http://en.wikipedia.org/wiki/VDPAU">VDPAU</a> support, this release has been bundled with OpenGL 3 and GLSL 1.30 support, so have a look at how to create an OpenGL 3.0 context.</p>
<p>First of all, it seems like there&#8217;s no other way to open the new context without getting your hands dirty, that is talking directly with GLX.<br />
What follows is a snippet to create an OpenGL 3.0 context integrated in SDL 1.2, which still doesn&#8217;t support it natively.</p>
<p>First of all you need some new defines.</p>
<pre class="brush: cpp;">
#define GLX_CONTEXT_DEBUG_BIT_ARB                         0x00000001
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB   0x00000002
#define GLX_CONTEXT_MAJOR_VERSION_ARB                  0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB                   0x2092
#define GLX_CONTEXT_FLAGS_ARB                                0x2094
</pre>
<p>You need also to retrieve the address of the following new GLX function.</p>
<pre class="brush: cpp;">
typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC)
	(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB =
	(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)&quot;glXCreateContextAttribsARB&quot;);
</pre>
<p>Then you have to define a bunch of GLX related variables.</p>
<pre class="brush: cpp;">
Display *dpy;
GLXDrawable draw, read;
GLXContext ctx, ctx3;
GLXFBConfig *cfg;
int nelements;
int attribs[]= {
	GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
	GLX_CONTEXT_MINOR_VERSION_ARB, 0,
	GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
	0
};
</pre>
<p>At last, after having called <tt>SDL_SetVideoMode()</tt>, create a new context, make it current and destroy the old one.</p>
<pre class="brush: cpp;">
ctx = glXGetCurrentContext();
dpy = glXGetCurrentDisplay();
draw = glXGetCurrentDrawable();
read = glXGetCurrentReadDrawable();
cfg = glXGetFBConfigs(dpy, 0, &amp;nelements);
ctx3 = glXCreateContextAttribsARB(dpy, *cfg, 0, 1, attribs);
glXMakeContextCurrent(dpy, draw, read, ctx3);
glXDestroyContext(dpy, ctx);
</pre>
<p>Don&#8217;t forget to put some querying code, just to be sure the whole process worked. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<pre class="brush: cpp;">
const GLubyte* string;

string = glGetString(GL_VENDOR);
printf(&quot;Vendor: %s\n&quot;, string);
string = glGetString(GL_RENDERER);
printf(&quot;Renderer: %s\n&quot;, string);
string = glGetString(GL_VERSION);
printf(&quot;OpenGL Version: %s\n&quot;, string);
string = glGetString(GL_SHADING_LANGUAGE_VERSION);
printf(&quot;GLSL Version: %s\n\n&quot;, string);
</pre>
<p>On my workstation I get this:<br />
<tt>Vendor: NVIDIA Corporation<br />
Renderer: GeForce 8600 GT/PCI/SSE2<br />
OpenGL Version: 3.0 NVIDIA 180.22<br />
GLSL Version: 1.30 NVIDIA via Cg compiler</tt></p>
<p>If you want to retrieve also the extension list, a new function can help you simplify the process.</p>
<pre class="brush: cpp;">
typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC)glXGetProcAddress((GLubyte*)&quot;glGetStringi&quot;);
</pre>
<p>You can then use it like this:</p>
<pre class="brush: cpp;">
GLint numExtensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &amp;numExtensions);

printf(&quot;Extension list: \n&quot;);
for (int i = 0; i &lt; numExtensions; ++i)
{
	printf(&quot;%s &quot;, glGetStringi(GL_EXTENSIONS, i));
}
printf(&quot;\n&quot;);
</pre>
<p>This new OpenGL version seems to perform just like the old one at the moment, drivers do not honour the <tt>GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB</tt> attribute, this means everything is still in place, backward compatible and unoptimized. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2009/01/16/habemus-opengl-30/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Depth of field reloaded</title>
		<link>http://encelo.netsons.org/blog/2008/04/15/depth-of-field-reloaded/</link>
		<comments>http://encelo.netsons.org/blog/2008/04/15/depth-of-field-reloaded/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 16:28:09 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Real-time Graphics]]></category>
		<category><![CDATA[GLSL]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[post-processing]]></category>
		<category><![CDATA[shaders]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=60</guid>
		<description><![CDATA[Lately I&#8217;ve been really disappointed by the poor performances of my first depth of field implementation, thus I decided to do something about it&#8230;

The most natural step to do was to give a look to the second Direct3D example from the same paper I used for the first one, as I was sure it would [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been really disappointed by the poor performances of my <a href="/blog/2008/03/23/i-love-depth-of-field/">first depth of field implementation</a>, thus I decided to do something about it&#8230;</p>
<p><img src="/blog/wp-content/uploads/2008/04/glsl_dof2.png" alt="glsl_dof2" /></p>
<p>The most natural step to do was to give a look to the second Direct3D example from the <a href="http://ati.amd.com/developer/shaderx/ShaderX2_Real-TimeDepthOfFieldSimulation.pdf">same paper</a> I used for the first one, as I was sure it would have led to more satisfactory results.<br />
I spent the two last nights converting, correcting and fine tuning it, but I was rewarded by the fact that I was right: even if it is a five passes algorithm which is using four different <a href="http://en.wikipedia.org/wiki/Framebuffer_Object">Frame Buffer Objects</a>, it is about 2.5 times faster than my previous implementation!</p>
<p>I think the speed boost depends on the two following:</p>
<ol>
<li>image blurring is achieved by a gaussian filter which is calculated separating the X from the Y axis, it is an approximation of a standard 2D kernel but it also means that the convolution matrix calculation complexity decreases from a quadratic to a linear factor.</li>
<li>this filter operates only on a downsampled (1/4th of the screen resolution actually) FBO</li>
</ol>
<p>Another nice note about this new implementation is that there are only two focal parameters, <em>focus depth</em> and <em>focus range</em>, which really help to setup a correct scene.</p>
<p>Now let&#8217;s review the five passes in detail:</p>
<ol>
<li>Render the scene normally while calculating a blur amount per-vertex, then store the interpolated value per-pixel inside the alpha component of the fragment.<br />
The calculation at the vertex shader is just:</p>
<pre class="brush: cpp;">
Blur = clamp(abs(-PosWV.z - focalDistance) / focalRange, 0.0, 1.0);
</pre>
</li>
<li>Downsample the scene rendered at the previous pass storing it in a smaller FBO</li>
<li>Apply the gaussian filter along the X axis on the downsampled scene and store it in a new FBO</li>
<li>Apply the gaussian filter along the Y axis on the already X blurred scene and store it in a new FBO</li>
<li>Calculate a linear interpolation between the first full resolution FBO and the XY downsampled blurred one<br />
This is performed in the fragment shader as:</p>
<pre class="brush: cpp;">
gl_FragColor = Fullres + Fullres.a * (Blurred - Fullres);
</pre>
</li>
</ol>
<p>Again, you can view it in action on my <a href="http://www.youtube.com/encelo">YouTube Channel</a>, or in a high definition <a href="http://www.vimeo.com/899935">720p version</a> hosted on my <a href="http://www.vimeo.com/encelo">Vimeo page</a>. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2008/04/15/depth-of-field-reloaded/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Image post-processing with shaders</title>
		<link>http://encelo.netsons.org/blog/2008/03/13/image-post-processing-with-shaders/</link>
		<comments>http://encelo.netsons.org/blog/2008/03/13/image-post-processing-with-shaders/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 01:00:04 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Real-time Graphics]]></category>
		<category><![CDATA[GLSL]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[post-processing]]></category>
		<category><![CDATA[shaders]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/2008/03/13/image-post-processing-with-shaders/</guid>
		<description><![CDATA[I&#8217;m back to work after many months, university exams take really a lot of time&#8230;
For I am a bit rusty on GLSL programming, but willing to learn new things anyway, I have decided to begin with a simple yet interesting topic, image processing.

The whole thing, actually, needs two rendering passes and relies heavily on Frame [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m back to work after many months, university exams take really a lot of time&#8230;<br />
For I am a bit rusty on GLSL programming, but willing to learn new things anyway, I have decided to begin with a simple yet interesting topic, image processing.</p>
<p><img src='/blog/wp-content/uploads/2008/03/glsl_imgpro.png' alt='GLSL_imgpro' /></p>
<p>The whole thing, actually, needs two rendering passes and relies heavily on <a href=""http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt>Frame Buffer Objects</a> because:</p>
<ol>
<li>You render the scene to an off-screen texture.</li>
<li>You render a quad covering the entire screen and binded to the previously written texture.</li>
<li>You make a shader process the fragments resulted from rendering this textured quad, i.e. post-processing the original scene.</li>
</ol>
<p>In this program post-processing is demanded to convolution matrices calculated with these kernels:</p>
<pre class="brush: cpp;">
GLfloat kernels[7][9] = {
    { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* Identity */
    { 0.0f,-1.0f, 0.0f,-1.0f, 5.0f,-1.0f, 0.0f,-1.0f, 0.0f}, /* Sharpen */
    { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}, /* Blur */
    { 1.0f, 2.0f, 1.0f, 2.0f, 4.0f, 2.0f, 1.0f, 2.0f, 1.0f}, /* Gaussian blur */
    { 0.0f, 0.0f, 0.0f,-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, /* Edge enhance */
    { 1.0f, 1.0f, 1.0f, 1.0f, 8.0f, 1.0f, 1.0f, 1.0f, 1.0f}, /* Edge detect */
    { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,-1.0f}  /* Emboss */
};
</pre>
<p>The final fragment color is calculated by a simple shader which, at the core, just performs the following:</p>
<pre class="brush: cpp;">
for(i = -1; i &lt;= 1; i++)
    for(j = -1; j &lt;= 1; j++) {
        coord = gl_TexCoord[0].st + vec2(float(i) * (1.0/float(Width)) * float(Dist), float(j) * (1.0/float(Height)) * float(Dist));
        sum += Kernel[i+1][j+1] * texture2D(Tex0, coord.xy);
        contrib += Kernel[i+1][j+1];
    }

    gl_FragColor = sum/contrib;
</pre>
<p>When the user chooses a filter, the application updates the kernel currently in use with a call to:</p>
<pre class="brush: cpp;">
loc = glGetUniformLocation(sh.p2, &quot;Dist&quot;);
glUniform1i(loc, dist);
loc = glGetUniformLocation(sh.p2, &quot;Kernel&quot;);
glUniformMatrix3fv(loc, 1, GL_FALSE, &amp;kernels[curker]);
</pre>
<p>Dist is a user defined parameter (you can change it using arrows) that defines the distance in pixels from the center to the contributing sample.</p>
<p>Since a month I have created a <a href="http://www.youtube.com/encelo">YouTube Channel</a>, now you can have an idea of how this demo works without downloading and compiling <a href="/_download/glsl_imgpro.tar.gz">the source code</a>: have a look at <a href="http://www.youtube.com/watch?v=lmTS9qSwCLg">this link</a>! <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2008/03/13/image-post-processing-with-shaders/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A slighty smarter setup.py for PySoy r64</title>
		<link>http://encelo.netsons.org/blog/2007/06/01/a-slighty-smarter-setuppy-for-pysoy-r64/</link>
		<comments>http://encelo.netsons.org/blog/2007/06/01/a-slighty-smarter-setuppy-for-pysoy-r64/#comments</comments>
		<pubDate>Fri, 01 Jun 2007 01:11:09 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[GameDev]]></category>
		<category><![CDATA[PySoy]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=43</guid>
		<description><![CDATA[While working on PySoy I was really disappointed by the policy adopted by the setup.py script, anytime I launched it the result was a recompilation of *all* the sources, this was really annoying and slow.

What came after was just that I decided to hack it a bit and make it behave more like a standard [...]]]></description>
			<content:encoded><![CDATA[<p>While working on PySoy I was really disappointed by the policy adopted by the setup.py script, anytime I launched it the result was a recompilation of *all* the sources, this was really annoying and slow.</p>
<p><img src='/blog/wp-content/uploads/2007/05/python.png' alt='Python transparent logo' /></p>
<p>What came after was just that I decided to hack it a bit and make it behave more like a standard build tool, that is to control the modification time of a source file in order to choose whether it is updated or need a fresh compilation.</p>
<p>The new policy for the script is very simple, but useful enough to save plenty of time.<br />
It is aware of the following cases (thank you Arc for tips on how to deal with the last one):</p>
<ul>
<li>a .c file is missing, pyrex should compile the .pyx file</li>
<li>a .pyx file is newer than the corresponding .c file, an update is needed</li>
<li>a .pxd file is newer than any .pyx file, a global recompile is needed</li>
</ul>
<p>The last point is not optimal, of course, but it&#8217;s a lot simpler than specifying all the .pxd dependecies for any .pyx file, and, anyway, quite close to being optimal, because of the thick web of cross dependencies which actually exists in PySoy.</p>
<p>Here is the piece of code which performs the magic:</p>
<pre class="brush: python;">
# Convert Pyrex sources to C if using Trunk
if version == 'Trunk' :
  import os
  from stat import *
  from Pyrex.Compiler import Main

  options = Main.CompilationOptions(defaults=Main.default_options, include_path=include_path)

  newestpxd = 0
  for dir in include_path:
    for pxdsource in os.listdir(dir):
      pxdsource_path = (os.path.join(dir, pxdsource))

      if os.path.isfile(pxdsource_path) and pxdsource.rsplit('.', 1)[1] == 'pxd':
        if os.stat(pxdsource_path)[ST_MTIME] &gt; newestpxd:
          newestpxd = os.stat(pxdsource_path)[ST_MTIME]

  for pyxsource in pyrex_sources:
    compilation_needed = False

    if os.path.isfile(pyxsource.rsplit('.', 1)[0] + '.c'):
      ctime = os.stat(pyxsource.rsplit('.', 1)[0] + '.c')[ST_MTIME]
    else:
      ctime = 0

    if newestpxd &gt; ctime:
      compilation_needed = True
    elif os.stat(pyxsource)[ST_MTIME] &gt; ctime:
      compilation_needed = True

    if compilation_needed:
      Main.compile(pyxsource, options)
</pre>
<p>Well, actually Arc commited <a href="http://www.pysoy.org/changeset?old_path=trunk&#038;old=65&#038;new_path=trunk&#038;new=64">r65</a> too, simplifying the conditionals of the script even more, but this is another story. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Anyway, I hope to have made another little step into making the life of our team a bit simpler. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2007/06/01/a-slighty-smarter-setuppy-for-pysoy-r64/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>My Summer of Code begins with PySoy r44</title>
		<link>http://encelo.netsons.org/blog/2007/05/29/summer-of-code-begins-with-pysoy-r44/</link>
		<comments>http://encelo.netsons.org/blog/2007/05/29/summer-of-code-begins-with-pysoy-r44/#comments</comments>
		<pubDate>Tue, 29 May 2007 00:11:42 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[GameDev]]></category>
		<category><![CDATA[PySoy]]></category>
		<category><![CDATA[GSoC]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=42</guid>
		<description><![CDATA[Summer of Code has started just today (even if currently it is only a &#8220;Spring of Code&#8221;   ) but a little contribution of mine has already made his way inside the SVN repository of PySoy.

But let&#8217;s start from the beginning&#8230;
After having shown to Arc an early draft of an UML class diagram for [...]]]></description>
			<content:encoded><![CDATA[<p>Summer of Code has started just today (even if currently it is only a &#8220;Spring of Code&#8221; <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  ) but a little contribution of mine has already made his way inside the SVN repository of PySoy.</p>
<p><img src='/blog/wp-content/uploads/2007/05/code-obfuscation.jpg' alt='Code Obfuscation' /></p>
<p>But let&#8217;s start from the beginning&#8230;<br />
After having shown to Arc an early draft of an UML class diagram for the current code I decided to come back to work on some test code I had written in the afternoon.<br />
It was just a classical spinning cube demo to actually compare PyOpenGL versus Pyrex speed, I don&#8217;t report the results here because they are quite identical, if I haven&#8217;t done any mistake it should be the absolute minimum complexity of the code which actually determined this result.<br />
Anyway, even without this proof I firmly believe in the power and speed of Pyrex. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Going back to my commit, my changes affected a small yet important area of the code, I think we will remember it in the future. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>BEFORE<br />
In <em>src/windows-glx/soy.windows.pyx</em>:</p>
<pre class="brush: python;">
gl.glClear(0x4100)
</pre>
<p>AFTER<br />
In <em>include/gl.pxd</em>:</p>
<pre class="brush: python;">
[...]
# Constants
  ctypedef enum:
    [...]
    # glPush/PopAttrib bits
    GL_DEPTH_BUFFER_BIT
    GL_COLOR_BUFFER_BIT
[...]
</pre>
<p>In <em>src/windows-glx/soy.windows.pyx</em>:</p>
<pre class="brush: python;">
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
</pre>
<p>Was it better before or now? <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2007/05/29/summer-of-code-begins-with-pysoy-r44/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Python 2.5 support in globs r46</title>
		<link>http://encelo.netsons.org/blog/2007/05/23/python-25-support-in-globs-r46/</link>
		<comments>http://encelo.netsons.org/blog/2007/05/23/python-25-support-in-globs-r46/#comments</comments>
		<pubDate>Wed, 23 May 2007 21:50:07 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[G.L.O.B.S.]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=39</guid>
		<description><![CDATA[Yes, I should have written about it when I actually committed the revision, but I forgot completely. 
About two months after Python 2.5 has been moved to the current repository of Arch I begun to think that maybe it was time to support the new release of our beloved language/interpreter.

I don&#8217;t know if it can [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, I should have written about it when I actually committed the <a href="http://globs.svn.sourceforge.net/viewvc/globs?view=rev&#038;revision=46">revision</a>, but I forgot completely. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /><br />
<a href="http://www.archlinux.org/news/299/">About two months</a> after <a href="http://www.python.org/download/releases/2.5/">Python 2.5</a> has been moved to the <em>current</em> repository of Arch I begun to think that maybe it was time to support the new release of our beloved language/interpreter.</p>
<p><img src='/blolg/wp-content/uploads/2007/05/python.png' alt='Python transparent logo' /></p>
<p>I don&#8217;t know if it can be called &#8220;support&#8221;, but at least GL O.B.S. is now aware of it. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
The changes are very simple yet of some importance.<br />
First of all, pysqlite is not needed anymore if you have the integrated <a href=http://docs.python.org/whatsnew/modules.html#SECTION0001440000000000000000>sqlite3 module</a>:</p>
<pre class="brush: python;">
if sys.version_info[:2] &gt;= (2, 5):
  from sqlite3 import dbapi2 as sqlite
else:
  from pysqlite2 import dbapi2 as sqlite
</pre>
<p>Moreover I make use of the updated API of the <a href="http://docs.python.org/lib/module-webbrowser.html">webbrowser module</a>:</p>
<pre class="brush: python;">
if sys.version_info[:2] &gt;= (2, 5):
  webbrowser.open_new_tab(Globs.BROWSE_URL)
else:
  webbrowser.Netscape('firefox').open(Globs.BROWSE_URL)
</pre>
<p>Another addition, not related with the support of Python 2.5, is the <em>check_ver</em> function, which checks if a particular version of OpenGL is available on the machine running GL O.B.S., this have opened the possibility to add an OpenGL 2 only test like GLSL_Parallax into <a href="http://globs.svn.sourceforge.net/viewvc/globs?view=rev&#038;revision=47">benchmarks r47</a>.</p>
<p>Python and GL O.B.S. are getting better and better. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2007/05/23/python-25-support-in-globs-r46/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parallax mapping for the masses</title>
		<link>http://encelo.netsons.org/blog/2007/05/01/parallax-mapping-for-the-masses/</link>
		<comments>http://encelo.netsons.org/blog/2007/05/01/parallax-mapping-for-the-masses/#comments</comments>
		<pubDate>Tue, 01 May 2007 01:11:41 +0000</pubDate>
		<dc:creator>encelo</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Real-time Graphics]]></category>
		<category><![CDATA[GLSL]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[shaders]]></category>
		<category><![CDATA[snippets]]></category>

		<guid isPermaLink="false">http://encelo.netsons.org/blog/?p=38</guid>
		<description><![CDATA[I have spent the last ten days studying hard, reading the first half of the Orange Book (it&#8217;s the last book in the list, of course   ), a plethora of papers, many demos code, tons of tutorials and guides, but at last I achieved what I would have never imagined just two weeks [...]]]></description>
			<content:encoded><![CDATA[<p>I have spent the last ten days studying hard, reading the first half of the <a href="http://en.wikipedia.org/wiki/Orange_Book">Orange Book</a> (it&#8217;s the last book in the list, of course <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  ), a plethora of papers, many demos code, tons of tutorials and guides, but at last I achieved what I would have never imagined just two weeks ago. <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<table>
<tr>
<td>
<a href='/blog/wp-content/uploads/2007/05/fixed.png'><img src='/blog/wp-content/uploads/2007/05/fixed_zoom.png' alt='Fixed Pipeline' /></a>
</td>
<td>
<a href='/blog/wp-content/uploads/2007/05/light.png'><img src='/blog/wp-content/uploads/2007/05/light_zoom.png' alt='Per-pixel Lighting' /></a>
</td>
<td>
<a href='/blog/wp-content/uploads/2007/05/normal.png'><img src='/blog/wp-content/uploads/2007/05/normal_zoom.png' alt='Normal Mapping' /></a>
</td>
<td>
<a href='/blog/wp-content/uploads/2007/05/parallax.png'><img src='/blog/wp-content/uploads/2007/05/parallax_zoom.png' alt='Parallax Mapping' /></a></p>
<td>
</tr>
</table>
<p>The <a href="http://autistici.org/encelo/download/glsl_parallax.tar.gz">GLSL_parallax</a> demo shows per pixel <a href="http://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model">Blinn-Phong shading</a>, specular mapping and tangent space <a href="http://en.wikipedia.org/wiki/Parallax_mapping">parallax mapping</a> with offset limiting! <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Actually I&#8217;m not really sure about the correctness of my implementation (especially regarding tangent space lighting) but screenshots demonstrate that I&#8217;m close to it.<br />
In the first one the usual and boring OpenGL fixed functionality per-vertex lighting (ambient, diffuse and specular components of a point light with attenuation), in the second  one shaders are enabled, but only to calculate lighting on a per-pixel basis. At last, the third and the fourth image show normal and parallax mapping.</p>
<p>Talking in more detail, the code is written for OpenGL 2 only, it makes use of <a href="http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_buffer_object.txt">Vertex Buffer Objects</a> and <a href="http://en.wikipedia.org/wiki/GLSL">GLSL</a> shaders using core functions.</p>
<p>Here is the magic:</p>
<pre class="brush: cpp;">
[...]
if (withParallax == true) { // alpha channel encodes the height map
  height = scale * texture2D(Tex1, gl_TexCoord[1].st).a - bias;
  TexCoord = gl_TexCoord[0].st + height * ecPos.xy;
}
[...]
if (withNormal == true)
  nor = 2.0 * normalMap.rgb - 1.0; // decoding normal map
[...]
</pre>
<p>Some statistics:</p>
<ul>
<li>6 varying variables</il>
<li>7 uniform variables (texture samples and enable/disable booleans)</il>
<li>3 texture fetches every fragment processed</il>
<li>(24&#215;3)x3 + 24&#215;2 = 432 floats (1728 bytes) stored in VBOs</il>
</ul>
<p>Enjoy the shaders! <img src='http://encelo.netsons.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://encelo.netsons.org/blog/2007/05/01/parallax-mapping-for-the-masses/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
