<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Pixel Perfect</title>
	<atom:link href="http://blog.shayanjaved.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.shayanjaved.com</link>
	<description>Tips/tricks related to Computer Graphics, GPUs and other programming</description>
	<lastBuildDate>Tue, 22 May 2012 00:24:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='blog.shayanjaved.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Pixel Perfect</title>
		<link>http://blog.shayanjaved.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://blog.shayanjaved.com/osd.xml" title="Pixel Perfect" />
	<atom:link rel='hub' href='http://blog.shayanjaved.com/?pushpress=hub'/>
		<item>
		<title>Writing a Software Rasterizer</title>
		<link>http://blog.shayanjaved.com/2012/05/04/writing-a-software-rasterizer/</link>
		<comments>http://blog.shayanjaved.com/2012/05/04/writing-a-software-rasterizer/#comments</comments>
		<pubDate>Sat, 05 May 2012 00:04:27 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[rasterizer]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/2012/05/04/writing-a-software-rasterizer/</guid>
		<description><![CDATA[There is an interesting post on AltDevBlogADay showing how one can write a software rasterizer: http://www.altdevblogaday.com/2012/04/14/software-rasterizer-part-1/   Anyone interested in graphics should have some kind understanding as to how the graphics pipeline works and how the rasterizer works. Knowledge of math (especially linear algebra) helps greatly.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=305&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>There is an interesting post on AltDevBlogADay showing how one can write a software rasterizer:</p>
<p><a href="http://www.altdevblogaday.com/2012/04/14/software-rasterizer-part-1/">http://www.altdevblogaday.com/2012/04/14/software-rasterizer-part-1/</a></p>
<p> </p>
<p>Anyone interested in graphics should have some kind understanding as to how the graphics pipeline works and how the rasterizer works. Knowledge of math (especially linear algebra) helps greatly.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/305/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/305/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/305/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/305/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/305/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/305/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/305/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/305/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/305/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/305/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/305/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/305/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/305/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/305/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=305&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2012/05/04/writing-a-software-rasterizer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>
	</item>
		<item>
		<title>BezierView using WebGL</title>
		<link>http://blog.shayanjaved.com/2012/03/15/bezierview-webgl/</link>
		<comments>http://blog.shayanjaved.com/2012/03/15/bezierview-webgl/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 20:17:56 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Browser]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[WebGL]]></category>
		<category><![CDATA[bezier]]></category>
		<category><![CDATA[bezierview]]></category>
		<category><![CDATA[surfaces]]></category>
		<category><![CDATA[three.js]]></category>
		<category><![CDATA[webgl]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/2012/03/15/bezierview-using-webgl/</guid>
		<description><![CDATA[My lab (SurfLab) manages a program called BezierView which is used for rendering different kinds of Bezier surfaces (triangular, tensor-product, rational, etc.). BezierView has not been updated for a few years, so me and a few other colleagues decided to update the program using WebGL instead. Now instead of downloading BezierView to your own computer [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=288&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>My lab (<a title="SurfLab" href="http://www.cise.ufl.edu/research/SurfLab/">SurfLab</a>) manages a program called <a href="http://www.cise.ufl.edu/research/SurfLab/bview/">BezierView </a>which is used for rendering different kinds of Bezier surfaces (triangular, tensor-product, rational, etc.). BezierView has not been updated for a few years, so me and a few other colleagues decided to update the program using <a href="http://en.wikipedia.org/wiki/WebGL">WebGL </a>instead.</p>
<p>Now instead of downloading BezierView to your own computer and running a .exe file, you can just run it online through a webpage. You can find the still-being-updated version <a href="http://dl.dropbox.com/u/6665854/BezierView/BezierView.html">here</a>. For now you can view tensor-product, triangular and rational patches along with polyhedra. It is being currently updated to include a better interface and to have support for all types.</p>
<p>There are some shortcomings to writing BezierView in WebGL &#8211; the most obvious one is that Javascript is much slower compared to C/C++. And the online version cannot handle huge files which the offline version can. And since WebGL is based on OpenGL ES 2.0, we cannot take advantage of the tessellator engine in modern graphics cards to evaluate parametric patches on the GPU (which results in a significant speedup). So all the evaluation is done on the CPU and the resultant vertices sent to the GPU. I guess we&#8217;ll have to wait for OpenGL ES 4.0 (or WebCL to be finalized &#8211; a Javascript implementation of OpenCL).</p>
<p>BezierView was developed using the excellent <a href="https://github.com/mrdoob/three.js/">Three.js</a> library. I highly recommend using it if you are developing a WebGL application.</p>
<p>The source code is available on <a href="https://github.com/pixelperfect3/BezierView">GitHub</a>.</p>
<p>You can find BezierView <a href="http://dl.dropbox.com/u/6665854/BezierView/BezierView.html">here</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/288/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/288/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/288/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/288/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/288/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/288/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/288/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/288/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=288&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2012/03/15/bezierview-webgl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>
	</item>
		<item>
		<title>Virtual Reality Projects</title>
		<link>http://blog.shayanjaved.com/2012/01/20/virtual-reality-projects/</link>
		<comments>http://blog.shayanjaved.com/2012/01/20/virtual-reality-projects/#comments</comments>
		<pubDate>Fri, 20 Jan 2012 21:20:15 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[Virtual Reality]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[artoolkit]]></category>
		<category><![CDATA[augmented reality]]></category>
		<category><![CDATA[ogre]]></category>
		<category><![CDATA[sketchup]]></category>
		<category><![CDATA[virtual reality]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=267</guid>
		<description><![CDATA[Back in Spring of 2009 (almost 3 years ago!), I took a very interesting Virtual Reality course offered by Dr. Benjamin Lok in my department. The course basically involves creating Virtual Reality projects. I ended up creating 4 which took a lot of work but which in the end were worth the effort. Here are [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=267&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Back in Spring of 2009 (almost 3 years ago!), I took a very interesting Virtual Reality course offered by Dr. Benjamin Lok in my department. The course basically involves creating Virtual Reality projects. I ended up creating 4 which took a lot of work but which in the end were worth the effort. Here are the four projects I worked on (click on the links for more detailed info/video):</p>
<p>&nbsp;</p>
<ol>
<li><a href="http://www.cise.ufl.edu/~sjaved/artoolkit1.html"><em>Using ARToolkit to demonstrate how touch-screens work:</em></a>  
<p>We had to come up with a way to use ARToolkit (Augmented Reality). I thought of attaching some AR markers to a <strong>Nintendo DS</strong> and demonstrating how 3 different kinds of touch-screens work (resistive, capacitive and infrared). Written in <strong>C</strong></li>
<li><a href="http://www.cise.ufl.edu/~sjaved/vr-project2.html"><em>Virtual Reality experience: Rescuing someone from a fire:</em></a>
<p>Now we started getting into the heavy stuff. We had to create a Virtual Reality 3D experience using a Head-Mounted Display, object tracking and small space. At the suggestion of my teammate, colleague and friend we ended up using the <strong>Ogre 3D Engine</strong> for the project. We also used <strong>Google SketchUp</strong> models and wrote the program in <strong>C++</strong>.</li>
<li><a href="http://www.cise.ufl.edu/~sjaved/vr-project3.html"><em>VR experience: Target practice on a military base:</em></a>
<p>This was my favorite project. We (me and my colleague Aritra Nath) created &#8220;virtual&#8221; shooting, where we attached a marker to a <strong>Nintendo Wiimote</strong> (which was in a gun shell, and you pressed the trigger to shoot). We had an actual barrier in the real-world which was nearly pixel-accurate in the virtual world (well, not quite). Used <strong>Ogre</strong>and <strong>Sketchup </strong>again.</li>
<li><a href="http://www.cise.ufl.edu/~sjaved/vr-project4.html"><em>New VR Interface for doing 3D landscaping around a house:</em></a>
<p>The 4th project involved creating a VR experience where the user could &#8220;create&#8221; new content. My team ended up creating a way to do 3D landscaping only using fingers and a wiimote. Used the same tools as before.</li>
</ol>
<p>
I consider myself lucky that I was able to take such a course. Though it was kind of grueling at times (especially since all the teams had to share the virtual reality hardware), it was also fun and rewarding at the end.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/267/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/267/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/267/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=267&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2012/01/20/virtual-reality-projects/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>
	</item>
		<item>
		<title>Binary Search Tree in Python</title>
		<link>http://blog.shayanjaved.com/2012/01/14/binary-search-tree-in-python/</link>
		<comments>http://blog.shayanjaved.com/2012/01/14/binary-search-tree-in-python/#comments</comments>
		<pubDate>Sat, 14 Jan 2012 16:32:52 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[Data Structures]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[binary search tree]]></category>
		<category><![CDATA[binary search trees]]></category>
		<category><![CDATA[bst]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[data structures]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=260</guid>
		<description><![CDATA[It has been a while since I have written a data structure from scratch (had to write B-Trees for an Advanced Data Structures course 2 years ago), so I decided to refresh my memory by quickly writing up Binary Search Trees in Python. Making sure you are familiar with data structures always helps with interviews [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=260&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It has been a while since I have written a data structure from scratch (had to write B-Trees for an Advanced Data Structures course 2 years ago), so I decided to refresh my memory by quickly writing up <a href="http://en.wikipedia.org/wiki/Binary_search_tree" title="Binary Search Tree">Binary Search Trees</a> in Python. Making sure you are familiar with data structures always helps with interviews too. </p>
<p>You can access the file <a href="http://dl.dropbox.com/u/6665854/binarytree.py"><strong>here</strong></a>. I have only tested this for integers, so might need a little bit of work for other data types. The following methods have been implemented:</p>
<ul>
<li><strong>add(data)</strong></li>
<li><strong>remove(data)</strong></li>
<p>Traversals:</p>
<li><strong>preorder()</strong></li>
<li><strong>inorder()</strong></li>
<li><strong>postorder()</strong></li>
<li><strong>bfTraversal()</strong> (Breadth-first traversal)</li>
<p>Helper methods:</p>
<li><strong>isLeaf(node)</strong> &#8211; checks if a node is a leaf</strong></li>
<li><strong>lcAncestor(value1, value2)</strong> &#8211; finds the least common ancestor of two nodes with values value1 and value2 </strong></li>
<li><strong>printAllPaths()</strong> &#8211; prints all the possible paths from the root to the leaves</li>
</ul>
<p>I won&#8217;t go over how a BST works, but hopefully the code is self-explanatory.</p>
<p>If there are any questions let me know &#8211; hope people find it useful.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/260/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/260/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/260/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/260/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/260/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/260/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/260/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/260/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/260/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/260/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/260/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/260/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/260/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/260/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=260&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2012/01/14/binary-search-tree-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>
	</item>
		<item>
		<title>Evaluating Bicubic Bézier Surfaces using (Py)OpenCL</title>
		<link>http://blog.shayanjaved.com/2011/11/13/evaluating-bezier-pyopencl/</link>
		<comments>http://blog.shayanjaved.com/2011/11/13/evaluating-bezier-pyopencl/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 00:11:06 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[GPGPU]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Surfaces]]></category>
		<category><![CDATA[bezier]]></category>
		<category><![CDATA[bicubic]]></category>
		<category><![CDATA[gpgpu]]></category>
		<category><![CDATA[gpu]]></category>
		<category><![CDATA[opencl]]></category>
		<category><![CDATA[pyopencl]]></category>
		<category><![CDATA[surfaces]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=215</guid>
		<description><![CDATA[&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; GitHub Repository here &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; I&#8217;ve been meaning to get into OpenCL for a while, so I thought I would write a simple program which would evaluate Bicubic Bezier patches (surfaces) in parallel. I also wanted to program in Python more, so I decided to use PyOpenCL. You can find more info about the OpenCL [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=215&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
<strong><em>GitHub Repository</em></strong> <a href="https://github.com/pixelperfect3/PyOpenCLBezier" target="_blank">here</a><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>I&#8217;ve been meaning to get into OpenCL for a while, so I thought I would write a simple program which would evaluate Bicubic Bezier patches (surfaces) in parallel.<br />
I also wanted to program in Python more, so I decided to use <a href="http://mathema.tician.de/software/pyopencl" target="_blank">PyOpenCL</a>. You can find more info about the OpenCL implementation in Python from the link.</p>
<p>I am not going to go over what a Bezier patch is and how it can be evaluated. There is a straightforward equation for evaluating one which I will be showing later on, but for more info about Bezier patches you can find other info online.</p>
<p>Let&#8217;s begin.</p>
<p><span id="more-215"></span></p>
<h4><em><strong>Introduction:</strong></em></h4>
<p>If you have a surface made of multiple Bezier patches they can be evaluated in parallel. The new shaders in DirectX 11 (Hull and Domain shaders) make this easier for graphics applications and rendering. There is a straightforward method of evaluating these patches using a simple equation. I am going to demonstrate the simple, straightforward way first (<a href="https://github.com/pixelperfect3/PyOpenCLBezier/blob/master/method2-bb.py" target="_blank">method2-bb.py</a>) and then another way which I thought would work faster (<a href="https://github.com/pixelperfect3/PyOpenCLBezier/blob/master/simple-bb.py" target="_blank">simple-bb.py</a>).</p>
<p><em>What you&#8217;ll need:</em></p>
<ul>
<li><a href="http://python.org/download/" target="_blank">Python</a> (Preferably 2.7)</li>
<li><a href="http://numpy.scipy.org/" target="_blank">NumPy</a></li>
<li><a href="http://mathema.tician.de/software/pyopencl" target="_blank">PyOpenCL</a></li>
<li>A Graphics card which supports OpenCL. Any recent card should work fine (I used an old Nvidia 8800 GT).</li>
</ul>
<h4><em><strong>OpenCL:</strong></em></h4>
<p>This is not intended to be an OpenCL tutorial, but I will be going over what I did in PyOpenCL (getting the context, setting up the input buffers, writing the kernels, getting the output, etc.) For a more detailed look into OpenCL I would suggest <a href="http://developer.download.nvidia.com/compute/cuda/3_2_prod/toolkit/docs/OpenCL_Programming_Guide.pdf" target="_blank">OpenCL tutorials by Nvidia</a>.<br />
I will not be going over in detail what a work-item is, what a work-group is, etc.</p>
<p><strong>Quick note for CUDA users:</strong> For some reason CUDA and OpenCL use different terminology. I will be using OpenCL terminology throughout this post. So here&#8217;s a quick translation for CUDA users:</p>
<ul>
<li>CUDA thread = OpenCL work-item</li>
<li>CUDA block = OpenCL work-group</li>
<li>CUDA shared memory = OpenCL local memory</li>
<li>CUDA local memory = OpenCL private memory</li>
</ul>
<h4><em><strong>Input:</strong></em></h4>
<p>The input to both programs is a <a href="http://www.cise.ufl.edu/research/SurfLab/bview/" target="_blank">BezierView</a> file with the control point coordinates of all the patches. <a href="http://www.cise.ufl.edu/research/SurfLab/bview/" target="_blank">BezierView</a> is a program developed by my graduate research lab (SurfLab) for the purposes of rendering different kinds of surfaces and viewing their properties (like Gaussian curvature, highlight lines, etc.)</p>
<p>Here is a sample file: <a href="https://raw.github.com/pixelperfect3/PyOpenCLBezier/master/cube2.bv" target="_blank">cube2.bv</a>.</p>
<p>The input method is called <strong>readBezierFile</strong> and returns a 1-D list with all the vertices in it (16 vertices per patch).</p>
<h4><em><strong>NumPy:</strong></em></h4>
<p>PyOpenCL requires the use of <a href="http://numpy.scipy.org/" target="_blank">NumPy</a> arrays as input buffers to the OpenCL kernels.</p>
<p>NumPy is a python module used for scientific computing, and it allows better creation of multi-dimensional arrays which are widely used for OpenCL. I won&#8217;t go over in much detail about what NumPy is, but I will show you how I use it.</p>
<p>First, we need to convert the regular Python list with all the vertices in it to a NumPy array:</p>
<p><pre class="brush: plain;">
import numpy

...

# try to read from a file here - returns the array
vertices = readBezierFile(&quot;cube2.bv&quot;)

# create numpy array
npVertices = array( vertices, dtype = float32)
</pre></p>
<p>The function &#8220;array&#8221; converts a Python list to a NumPy array. The &#8220;dtype&#8221; represents the type of values we will be storing in the array (32-bit floating numbers in this case).</p>
<h4><em><strong>Initial Setup:</strong></em></h4>
<p>I read the file with all the OpenCL kernels in it first (<a href="https://github.com/pixelperfect3/PyOpenCLBezier/blob/master/bezier.cl" target="_blank">bezier.cl</a>)</p>
<p>After that I setup the UV-buffer. Evaluating a Bicubic patch requires U and V values. The more UV-value pairs there are the more detailed surface is output (from 0.0 to 1.0). The UV-value generation code is:</p>
<p><pre class="brush: plain;">
# Array of UV values - 36 in total (detail by 0.2)
uvValues = empty( (36, 2)).astype(numpy.float32)

index = 0
for u in range(0, 12, 2): # step = 2
    for v in range(0, 12, 2):
        # conver the ints to floats
        fU = float(u)
        fV = float(v)
        uvValues[index] = [ fU/10.0, fV/10.0]
        index = index + 1
</pre></p>
<p>The &#8220;empty&#8221; function is used for creating a NumPy array with empty values. We are going to be generating an array of size 36 * 2. (UV values spaced by 0.2)</p>
<h4><em><strong>OpenCL Setup:</strong></em></h4>
<p>Before we do computation we have to do some OpenCL setup. This can be a little tedious when writing in C/C++, but PyOpenCL makes it much easier.</p>
<p>First, we have to create an <em>OpenCL Context</em>. This can be done in two ways (I used the second one for my clarification):</p>
<ol>
<li>This simple way will automatically choose a device for you (usually the GPU if it&#8217;s available). Very convenient.<br />
<pre class="brush: plain;">
ctx = cl.create_some_context()
</pre></li>
<li>This way goes through all the platforms/devices and creates a context specifically with that device.<br />
<pre class="brush: plain;">
# Platform test
for found_platform in cl.get_platforms():
    if found_platform.name == 'NVIDIA CUDA':
        my_platform = found_platform
        print &quot;Selected platform:&quot;, my_platform.name

for device in my_platform.get_devices():
  dev_type = cl.device_type.to_string(device.type)
  if dev_type == 'GPU':
        dev = device
        print &quot;Selected device: &quot;, dev_type

# context
ctx = cl.Context([dev])
</pre></li>
</ol>
<p>Next we need to create the <em>Command Queue</em>:</p>
<p><pre class="brush: plain;">
cq = cl.CommandQueue(ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
</pre></p>
<p>You can just pass in the Context to the function, but I want to point out that I passed in the PROFILING_ENABLE flag, which allows us to determine how much time the operation took. This will allow us to compare the different methods.</p>
<p>Now finally we setup the input/output buffers to be sent to the GPU:</p>
<p><pre class="brush: plain;">
# memory flags
mf = cl.mem_flags

# input buffers
# the control point vertices
vertex_buffer = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=npVertices)

# the uv buffer
uv_buffer = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=uvValues)

# final output
output_buffer = cl.Buffer(ctx, mf.WRITE_ONLY, uvValues.nbytes * 2 * numPatches)
</pre></p>
<p>The output buffer is to be written to (WRITE_ONLY), and we specify the size of the output buffer in terms of bytes. the &#8220;nbytes&#8221; property in a NumPy array lets us know the size in terms of bytes of that array.<br />
For each patch we will have 36 * 4 * 4 bytes.<br />
36 = number of UV pairs<br />
4 = number of floating-point values output for each UV-value<br />
4 = number of bytes for a float32 value<br />
Hopefully that is clear.</p>
<p>Now we can start evaluating!</p>
<h4><em><strong>Method #1: The simple, straightforward way:</strong></em></h4>
<p>The first method directly evaluates the patch for 1 UV-pair. The kernel takes in the UV-pair, reads in the control points for the corresponding patch and then outputs it to the output buffer. The Python evaluation code is as follows:</p>
<p><pre class="brush: plain;">
# the global size (number of uv-values * number of patches): 36 * numPatches
numUVs = uvValues.size/2 # 72/2 = 36
globalSize = numUVs * numPatches

localSize = numUVs # 36 work-items per work-group

# evaluate
exec_evt = prg.bezierEval2Multiple(cq, (globalSize,), (localSize,), vertex_buffer, uv_buffer, output_buffer)
exec_evt.wait()
</pre></p>
<p>First we calculate the global memory size (total number of kernels needed), and then the local memory size (# of work-items per work-group). The global memory size is basically the number of UV-value pairs.</p>
<p>We will need this information to send to the evaluation kernel. The kernel name is <strong>&#8220;bezierEval2Multiple&#8221;</strong> (apologies for the incoherent names).<br />
The kernel needs to take in the <em>Command Queue</em>, the <em>global memory size</em> and the <em>local memory size</em> first.</p>
<p>After that we pass in the input and output buffers as parameters. Once the kernel is called we wait for it to finish (exec_evt.wait()).</p>
<p>The kernel is as follows (in <a href="https://github.com/pixelperfect3/PyOpenCLBezier/blob/master/bezier.cl" target="_blank">bezier.cl</a>):</p>
<p><pre class="brush: plain;">
__kernel void bezierEval2Multiple(__global const float4 *controlPoints, __global float2 *uvValues,
                        __global float4 *output) {

   // get the global id and the corresponding patch number
   int gid = get_global_id(0);

   // get the patch number - the patch info we will have to read
   int numPatch = gid/get_local_size(0);

   // get the uv values - local id goes from 0-35
   int lid = get_local_id(0);
   float2 uv = uvValues[lid];

   // evaluate row1
   float4 b00 = evalCubicCurve(controlPoints[numPatch * 16 + 0], controlPoints[numPatch * 16 + 1], controlPoints[numPatch * 16 + 2], controlPoints[numPatch * 16 + 3], uv.x);

   float4 b01 = evalCubicCurve(controlPoints[numPatch * 16 + 4], controlPoints[numPatch * 16 + 5], controlPoints[numPatch * 16 + 6], controlPoints[numPatch * 16 + 7], uv.x);

   float4 b02 = evalCubicCurve(controlPoints[numPatch * 16 + 8], controlPoints[numPatch * 16 + 9], controlPoints[numPatch * 16 + 10], controlPoints[numPatch * 16 + 11], uv.x);

   float4 b03 = evalCubicCurve(controlPoints[numPatch * 16 + 12], controlPoints[numPatch * 16 + 13], controlPoints[numPatch * 16 + 14], controlPoints[numPatch * 16 + 15], uv.x);

  // evaluated point
  output[gid] = evalCubicCurve(b00, b01, b02, b03, uv.y);
}
</pre></p>
<p>For each kernel we need to figure out which Bezier patch we are going to evaluate, what UV-pair we are going to use and where we need to place our output in the output buffer.</p>
<p>The global id let&#8217;s us know where we need to place our output.<br />
To get the patch we just divide our global id by the local memory size.<br />
The UV-pair we want to evaluate is our local id. The local memory size is 36, which is the # of UV-value pairs, so we can easily find out which one we need to use.</p>
<p>Finally we evaluate the Bezier patch and place it in the output buffer. A simple kernel.</p>
<h4><em><strong>Method #2: The complex, trying-to-be-more-parallel way:</strong></em></h4>
<p>The &#8220;problem&#8221; I noticed with the first kernel is how all the work-items in each work-group have to read the same control points from global memory again and again. At this point I was still iffy on the concept of &#8220;local memory&#8221; so I read up on it and found out that reading from local memory is faster than global memory (obviously). So will using local memory allow me to make the whole process faster? I decided to come up with a different way which will use a lot more work-items but where each work-item does &#8220;less&#8221; work (only simple bilinear interpolation across selective control points).</p>
<p>This method did not turn out to be faster. My advisor already told me before I fully implemented this that the first method will be much faster, and he was right. Turns out it was <em>3 times slower.</em> In any case here is the concept:</p>
<p>Bezier Patches can be evaluated using what is known as <a href="http://en.wikipedia.org/wiki/De_Casteljau's_algorithm">De Casteljau&#8217;s Algorithm</a> (The link is for curves but can be easily adapted to surfaces). It basically involves linearly interpolating (bilinearly interpolating for surfaces) the control points and their results until you get the evaluated point. I try to parallelize the interpolation part so it can be done faster.</p>
<p>Here are a few images showing the steps for a UV-pair of (0.5, 0.5):</p>
<p>&nbsp;</p>
<p>First, here are the 16 control points of a patch:</p>
<div id="attachment_248" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/11/cp1.png"><img class="size-full wp-image-248" title="Bicubic Control Points" src="http://pixelp3.files.wordpress.com/2011/11/cp1.png?w=540" alt="Bicubic Control Points"   /></a><p class="wp-caption-text">16 Bicubic Control Points</p></div>
<p>&nbsp;</p>
<p>The next step would be to do a bilinear interpolation across each &#8220;square&#8221; (4) of control points <em>per kernel</em>. The results are the blue points shown below: (since U and V are both 0.5, the point lies in the middle)</p>
<div id="attachment_252" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/11/cp2.png"><img class="size-full wp-image-252" title="First pass" src="http://pixelp3.files.wordpress.com/2011/11/cp2.png?w=540" alt=""   /></a><p class="wp-caption-text">First bilinear interpolation pass (results in biquadratic patch)</p></div>
<p>&nbsp;</p>
<p>We repeat the process for this biquadratic patch: (results are points in red)</p>
<div id="attachment_251" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/11/cp3.png"><img class="size-full wp-image-251" title="Second pass" src="http://pixelp3.files.wordpress.com/2011/11/cp3.png?w=540" alt=""   /></a><p class="wp-caption-text">Second interpolation pass (results in linear patch)</p></div>
<p>&nbsp;</p>
<p>Finally we do one last bilinear interpolation to get the evaluated point (in green):</p>
<div id="attachment_250" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/11/cp4.png"><img class="size-full wp-image-250" title="Evaluated Point" src="http://pixelp3.files.wordpress.com/2011/11/cp4.png?w=540" alt=""   /></a><p class="wp-caption-text">The point at (U,V) = (0.5, 0.5)</p></div>
<p>&nbsp;</p>
<p>You have probably figured it out by now, but the way this method works in parallel is that it generates <em>9 work-items per UV-pair</em>. Each work-item does a bilinear interpolation and stores it&#8217;s result in local memory. This completes the first pass.</p>
<p>After the first pass we need to repeat the process, but this time we only need 4 work-items. This is where I encounter a problem: the other 5 work-items don&#8217;t do anything. Then for the final evaluation I only use 1 work-item, with others not doing work.</p>
<p>The kernel (<strong>bezierEvalMutiple</strong>) shown below:<br />
<pre class="brush: plain;">
__kernel void bezierEvalMultiple(int numPatches, __global const float4 *controlPoints, __global float2 *uvValues,
                     __global float4 *output, __local float4 *local_points, __local float4 *local_points2) {

	// get the global id
	int gid = get_global_id(0)/get_local_size(0); // divide by 9
	
	// get the patch number
	int numPatch = gid/36; //get_local_size(0);
	
	// get the uv values 
	float2 uv = uvValues[gid];//get_global_id(0)];
	
	//output[gid] = (float4)(numPatch, numPatch, 0, 0);
	
	// get the row
	int lid = get_local_id(0);
	int patchNum = numPatch * 16; 	// the patch to deal with
	int row = lid/3;
	int index = row + numPatch + lid;
	
	// get the 4 control points you'll need
	/****************
	  b10--b11
	   |   |
	  b00--b01
	****************/
	
	float4 b00 = controlPoints[index];
	float4 b01 = controlPoints[index+1];
	float4 b10 = controlPoints[index+4];
	float4 b11 = controlPoints[index+5];
	
	// do linear interpolation across u first
	float4 val1 = lerp(b00, b01, uv.x);
	float4 val2 = lerp(b10, b11, uv.x);
	
	// then across v
	float4 newPoint = lerp(val1, val2, uv.y);
	
	// store it in the local memory
	local_points[lid] = newPoint;
	
	// synchronize in work-group
	barrier(CLK_LOCAL_MEM_FENCE);
	
	// only do it for certain work-items (now evaluating quadratic)
	if (lid &lt; 4) {
		row = lid/2; 		// 2 = degree
		float4 b002 = local_points[row + lid];
		float4 b012 = local_points[row + lid+1];
		float4 b102 = local_points[row + lid+3];
		float4 b112 = local_points[row + lid+4];
		
		// do linear interpolation across u first
		float4 val12 = lerp(b002, b012, uv.x);
		float4 val22 = lerp(b102, b112, uv.x);
	
		// then across v
		float4 newPoint2 = lerp(val12, val22, uv.y);
		
		local_points2[lid] = newPoint2;
		barrier(CLK_LOCAL_MEM_FENCE);
		
		// output - only do it for the first work-item
		if (lid == 1) {
			float4 val13 = lerp(local_points2[0], local_points2[1], uv.x);
			float4 val23 = lerp(local_points2[2], local_points2[3], uv.x);
			
			float4 newPoint3 = lerp(val13, val23, uv.y);
			output[gid] = newPoint3;
		}
	}
}
</pre></p>
<p>I won&#8217;t go over much of this (you can probably figure it out), but I just wanted to mention how I synchronize between work-items (in a work-group) at each pass. You have to call <strong>barrier(CLK_LOCAL_MEM_FENCE);</strong> to ensure synchronization at each point.</p>
<p>This method runs 3 times slower &#8211; I would guess mainly because it requires 9 times more work-items and just straightforward multiplication is fast enough. At the very least I learned how to use local memory and synchronize between work-items.</p>
<h4><em><strong>Output:</strong></em></h4>
<p>In the end we want to find out the time elapsed and read back the output. This is how it&#8217;s done in Python:<br />
<pre class="brush: plain;">
elapsed = exec_evt.profile.end - exec_evt.profile.start
print(&quot;Execution time of test: %g &quot; % elapsed)

# read back the result
eval = empty( numUVs * 4 * numPatches).astype(numpy.float32)
cl.enqueue_read_buffer(cq, output_buffer, eval).wait()
</pre></p>
<p>We create an empty NumPy buffer and then call <strong>enqueue_read_buffer</strong> to read from the output buffer into the array.</p>
<h4><em><strong>Conclusion:</strong></em></h4>
<p>I showed a simple example of using (Py)OpenCL for evaluating Bezier patches. The next step would be to render them using PyOpenGL, and perhaps allow user manipulation of the control points. This project helped me get a start on OpenCL and learn some of the basics. I would recommend using PyOpenCL since it allows you to write applications quickly.</p>
<p>If you have any questions, comments or suggestions please feel free to ask.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
<strong><em>GitHub Repository</em></strong> <a href="https://github.com/pixelperfect3/PyOpenCLBezier" target="_blank">here</a><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/215/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=215&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2011/11/13/evaluating-bezier-pyopencl/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/11/cp1.png" medium="image">
			<media:title type="html">Bicubic Control Points</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/11/cp2.png" medium="image">
			<media:title type="html">First pass</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/11/cp3.png" medium="image">
			<media:title type="html">Second pass</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/11/cp4.png" medium="image">
			<media:title type="html">Evaluated Point</media:title>
		</media:content>
	</item>
		<item>
		<title>My Google Chrome extension &#8211; &#8220;Comment Save&#8221;</title>
		<link>http://blog.shayanjaved.com/2011/08/04/my-google-chrome-extension-comment-save/</link>
		<comments>http://blog.shayanjaved.com/2011/08/04/my-google-chrome-extension-comment-save/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 04:03:14 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[Browser]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[comment]]></category>
		<category><![CDATA[comment save]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=204</guid>
		<description><![CDATA[Though I focus mostly on computer graphics, I also have an (amateurish) interest in web-design and web-programming. Late last year a friend of mine brought to my attention a problem he encountered: he wrote a bunch of text in a textbox and when he clicked submit the server responded with an error. He had lost [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=204&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Though I focus mostly on computer graphics, I also have an (amateurish) interest in web-design and web-programming.</p>
<p>Late last year a friend of mine brought to my attention a problem he encountered: he wrote a bunch of text in a textbox and when he clicked submit the server responded with an error. He had lost all he wrote which was frustrating. I thought it would be useful to have an extension which records everything you type in one of those boxes so you can recover it if you lose it.</p>
<p>Another friend suggested it would be nice if the extension kept a history of all your posts (if you are one of those people who comment across many sites a lot). And so I came up with <strong><a title="Comment Save" href="https://chrome.google.com/webstore/detail/ndmcbhmmonjkclhmeidccodfhlifmmco" target="_blank">&#8220;Comment Save&#8221;</a></strong> (which has roughly 500 users as I type this).I&#8217;ll let the description describe it:</p>
<blockquote><p>As featured on Lifehacker!</p>
<p><a href="http://lifehacker.com/5715657/comment-save-keeps-track-of-your-comments-on-the-web" target="_blank">http://lifehacker.com/5715657/comment-save-keeps-track-of-your-comments-on-the-web</a></p>
<p>Ever written a large post or comment on a website, click submit, only to see your comment get lost in the internet wilderness? Or your tab/window closed somehow before you could submit?</p>
<p>Or maybe you just like to keep track of all the posts you made on different websites.</p>
<p>Comment Save (CS) helps you keep track of what you have been writing as you type. Icon beside the address bar brings up a window showing you the last post you wrote alongwith a link to the page. Link in the window allows you to view your post history.</p>
<p>You can also filter websites where you don&#8217;t want any of your posts to be tracked.</p>
<p>Works on sites like:<br />
- Youtube<br />
- Facebook/Google+<br />
- Gawker blogs (Gawker/Gizmodo/Jezebel/Lifehacker/etc.)<br />
- Engadget/Techcrunch/etc. (Sites which use Disqus)<br />
- WordPress/Tumblr<br />
- Forums of all kinds<br />
- Digg/Reddit<br />
- CNN/New York Times/The Guardian/other news websites<br />
- And lots more!</p>
<p>FEATURES:<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
* Records your post as you type so you can recover it if you lose it.<br />
* Keeps a history of all your posts along with a link to the page and the time.<br />
* Allows you to add filters so you can disable tracking on certain websites.<br />
* Simple checkbox in the popup window enables/disable tracking globally</p></blockquote>
<p>The latest version (0.4) added tracking for Google+ posts.</p>
<p>The extension helped me learn Javascript more (and also helped me deal with HTML Web Databases). The source code for the extension is open-source and has been released under the GPL v2 license. The source code can be accessed on Google Code <a href="http://code.google.com/p/androidshaders/">here</a>. Feel free to look through it.</p>
<p>If you have any feature requests for the extension please let me know. Some features I have thought about adding include:</p>
<ul>
<li>Delete all comments after a set time. (User-specified time, for ex. 10 minutes, 1 day, 1 month, etc.) (<strong>UPDATE:</strong> Added in Version 0.5 on 9th August 2011)</li>
<li><em>Search Comments</em>: Within that include searching by website, within a specific timeframe, etc.</li>
<li>Delete Comments by website</li>
</ul>
<p>Any other suggestions would be welcome! </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/204/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/204/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/204/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=204&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2011/08/04/my-google-chrome-extension-comment-save/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>
	</item>
		<item>
		<title>Deferred Shading in DirectX 10 (with Ambient Occlusion)</title>
		<link>http://blog.shayanjaved.com/2011/06/26/deferred-shading-dx10/</link>
		<comments>http://blog.shayanjaved.com/2011/06/26/deferred-shading-dx10/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 03:30:25 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[Deferred Shading]]></category>
		<category><![CDATA[DirectX]]></category>
		<category><![CDATA[ambient occlusion]]></category>
		<category><![CDATA[deferred shading]]></category>
		<category><![CDATA[directx]]></category>
		<category><![CDATA[directx 10]]></category>
		<category><![CDATA[g-buffer]]></category>
		<category><![CDATA[ssao]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=159</guid>
		<description><![CDATA[Deferred Shading is a rendering technique (in comparison to regular forward rendering) which has become popular over the last few years. Games like the upcoming Battlefield 3, Crysis 2 and numerous others use it, so I wanted to give it a try and implement a simple deferred renderer myself in DirectX 10. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- GitHub Repository [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=159&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Deferred Shading</strong> is a rendering technique (in comparison to regular forward rendering) which has become popular over the last few years. Games like the upcoming <a href="http://www.slideshare.net/DICEStudio/directx-11-rendering-in-battlefield-3" target="_blank">Battlefield 3</a>, Crysis 2 and numerous others use it, so I wanted to give it a try and implement a simple deferred renderer myself in DirectX 10.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
GitHub Repository and Visual Studio 2010 files:<br />
<strong><em>GitHub Repository</em></strong> <a href="https://github.com/pixelperfect3/deferredDX" target="_blank">here</a><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Images for all the render targets/textures (Diffuse, Normals, Depth, Ambient Occlusion, Composite with Ambient Occlusion, Composite without AO):</p>
<div id="attachment_181" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/06/diffuse.png"><img class="size-medium wp-image-181 " title="Diffuse Texture" src="http://pixelp3.files.wordpress.com/2011/06/diffuse.png?w=300&h=232" alt="" width="300" height="232" /></a><p class="wp-caption-text">Diffuse Texture</p></div>
<div id="attachment_182" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/06/normals.png"><img class="size-medium wp-image-182 " title="View-space Normals" src="http://pixelp3.files.wordpress.com/2011/06/normals.png?w=300&h=232" alt="" width="300" height="232" /></a><p class="wp-caption-text">View-space Normals</p></div>
<div id="attachment_180" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/06/depth.png?w=300"><img class="size-medium wp-image-180 " title="Depth Texture" src="http://pixelp3.files.wordpress.com/2011/06/depth.png?w=300&h=232" alt="" width="300" height="232" /></a><p class="wp-caption-text">Depth Texture</p></div>
<div id="attachment_177" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/06/ao.png"><img class="size-medium wp-image-177 " title="Ambient Occlusion" src="http://pixelp3.files.wordpress.com/2011/06/ao.png?w=300&h=232" alt="" width="300" height="232" /></a><p class="wp-caption-text">Ambient Occlusion</p></div>
<div id="attachment_178" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/06/composite.png"><img class="size-medium wp-image-178 " title="Composite" src="http://pixelp3.files.wordpress.com/2011/06/composite.png?w=300&h=232" alt="" width="300" height="232" /></a><p class="wp-caption-text">Composite with Ambient Occlusion</p></div>
<div id="attachment_179" class="wp-caption aligncenter" style="width: 310px"><a href="http://pixelp3.files.wordpress.com/2011/06/compositenoao.png"><img class="size-medium wp-image-179 " title="Composite Without AO" src="http://pixelp3.files.wordpress.com/2011/06/compositenoao.png?w=300&h=232" alt="" width="300" height="232" /></a><p class="wp-caption-text">Composite without AO</p></div>
<h4><span style="text-decoration:underline;"><em><strong>What is Deferred Shading?</strong></em></span></h4>
<p>If you are reading this chances are you already know what deferred shading is and how it works, so I won&#8217;t go into too much detail. <a href="http://en.wikipedia.org/wiki/Deferred_shading" target="_blank">Wikipedia </a>has a good overview and there are other places which can describe it better.</p>
<p>Basically deferred shading involves rendering your view-space normals, your depth-buffer, specular/diffuse, ambient occlusion, etc. values into different textures and then using them at a later pass to create a final composite image (by rendering a full-screen quad). There are several advantages and some disadvantages (increased memory bandwidth due to multiple render targets, inability to handle transparency, anti-aliasing, etc.)</p>
<p><span id="more-159"></span></p>
<h4><span style="text-decoration:underline;"><em><strong>Implementation:</strong></em></span></h4>
<p>I started off by modifying an existing DirectX10 project. &#8220;Tutorial10&#8243; from Microsoft&#8217;s DirectX SDK Samples was used as a starting point, which uses the DXUT Library to specify setup and input (think <em>GLUT</em> for <em>OpenGL</em>). So my scene itself is simple (just one character mesh) as I mainly wanted to focus on the rendering part (I might add a more complex scene later). The steps which I&#8217;m going to cover are:</p>
<ol>
<li>Setup the Multiple Render Targets and full-screen quad.</li>
<li>Call simple pass (which uses the geometry shader) to render view-space normals and depth into a texture.</li>
<li>Call pass to generate the AO texture from the previously generated normals and depth.</li>
<li>Gaussian Blur passes to smooth out the noise from the AO texture.</li>
<li>View Texture (either the composite lit one or one of the others)</li>
</ol>
<h4><span style="text-decoration:underline;"><em><strong>1. Setting up Render Targets:</strong></em></span></h4>
<p>I&#8217;ll just show how to setup the multiple render targets for the first pass, and then you can figure out the setup for the AO textures. First we declare all the variables we need:</p>
<p><pre class="brush: plain;">
// The Multiple Render Targets
ID3D10Texture2D*                    _mrtTex;// Environment map
ID3D10RenderTargetView*             _mrtRTV;// Render target view for the mrts
ID3D10ShaderResourceView*           _mrtSRV;// Shader resource view for the mrts
ID3D10EffectShaderResourceVariable* _mrtTextureVariable = NULL; // for sending in the mrts
ID3D10Texture2D*                    _mrtMapDepth;// Depth
ID3D10DepthStencilView*             _mrtDSV;// Depth stencil view
</pre></p>
<p>These are the minimum variables you need. You need the <em>textures (ID3D10Texture2D)</em>, the <em>RenderTargetViews</em>, the <em>ShaderResourceViews</em> and the <em>EffectShaderResourceVariable</em> (to send in the texture to the shader). You also need a <em>DepthStencilView</em> for the depth.</p>
<p>The setup is done in the <strong>SetupMRTs(..)</strong> function:</p>
<p><pre class="brush: plain;">
//----------------------------------------------
// Sets up the Multiple Render Targets
//----------------------------------------------
HRESULT SetupMRTs(ID3D10Device* pd3dDevice) {
    HRESULT hr;

    // Create depth stencil texture.
    D3D10_TEXTURE2D_DESC dstex;
    ZeroMemory( &amp;dstex, sizeof(dstex) );
    dstex.Width = _width * TEXSCALE;
    dstex.Height = _height * TEXSCALE;
    dstex.MipLevels = 1;
    dstex.ArraySize = NUMRTS;
    dstex.SampleDesc.Count = 1;
    dstex.SampleDesc.Quality = 0;
    dstex.Format = DXGI_FORMAT_D32_FLOAT;
    dstex.Usage = D3D10_USAGE_DEFAULT;
    dstex.BindFlags =  D3D10_BIND_DEPTH_STENCIL;
    dstex.CPUAccessFlags = 0;

    _mrtMapDepth = NULL;

    V_RETURN(  pd3dDevice-&gt;CreateTexture2D( &amp;dstex, NULL, &amp;_mrtMapDepth ));

    // Create the depth stencil view for the mrts
    D3D10_DEPTH_STENCIL_VIEW_DESC DescDS;
    DescDS.Format = dstex.Format;
    DescDS.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2DARRAY;
    DescDS.Texture2DArray.FirstArraySlice = 0;
    DescDS.Texture2DArray.ArraySize = NUMRTS;
    DescDS.Texture2DArray.MipSlice = 0;

    _mrtDSV = NULL;
    V_RETURN (  pd3dDevice-&gt;CreateDepthStencilView( _mrtMapDepth, &amp;DescDS, &amp;_mrtDSV ) );

    // Create all the multiple render target textures
    dstex.Format = DXGI_FORMAT_R16G16B16A16_UNORM;
    dstex.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
    _mrtTex = NULL;
    V_RETURN ( pd3dDevice-&gt;CreateTexture2D( &amp;dstex, NULL, &amp;_mrtTex ) );

    // Create the 3 render target view
    D3D10_RENDER_TARGET_VIEW_DESC DescRT;
    DescRT.Format = dstex.Format;
    DescRT.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DARRAY;
    DescRT.Texture2DArray.FirstArraySlice = 0;
    DescRT.Texture2DArray.ArraySize = NUMRTS;
    DescRT.Texture2DArray.MipSlice = 0;
    V_RETURN ( pd3dDevice-&gt;CreateRenderTargetView( _mrtTex, &amp;DescRT, &amp;_mrtRTV ) );

    // Create the shader resource view for the cubic env map
    D3D10_SHADER_RESOURCE_VIEW_DESC SRVDesc;
    ZeroMemory( &amp;SRVDesc, sizeof( SRVDesc ) );
    SRVDesc.Format = dstex.Format;
    SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2DARRAY;
    SRVDesc.Texture2DArray.ArraySize = NUMRTS;
    SRVDesc.Texture2DArray.FirstArraySlice = 0;
    SRVDesc.Texture2DArray.MipLevels = 1;
    SRVDesc.Texture2DArray.MostDetailedMip = 0;
    _mrtSRV = NULL;
    V_RETURN ( pd3dDevice-&gt;CreateShaderResourceView( _mrtTex, &amp;SRVDesc, &amp;_mrtSRV ) );

    return S_OK;
}
</pre></p>
<p>I know the above might look overwhelming at first, but it&#8217;s the standard way of generating a render target in DX10. The first thing we do is generate the Depth texture and the Depth Stencil View, making sure we specify the <strong>ArraySize</strong> (the # of render targets). Also make sure that the <strong>ViewDimension</strong> is specified as <strong>D3D10_RTV_DIMENSION_TEXTURE2DARRAY</strong>, since we have an array of Textures (in HLSL the variable will be declared as <em>Texture2DArray</em>). If we are using just one render target we would use <strong>D3D10_RTV&#8230;_TEXTURE2D</strong> instead (for the Ambient Occlusion Textures).</p>
<p>Next we generate the Textures themselves, the RenderTargetView and the ShaderResourceView. Make sure the <strong>BindFlags </strong>are <strong>D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE</strong>, indicating that the textures will be used as both Render Targets and Shader Resources.</p>
<h4><span style="text-decoration:underline;"><em><strong>2. Rendering View-Space Normals and Depth:</strong></em></span></h4>
<p>In the main draw function (<strong>OND3D10FrameRender</strong>), before we render to texture we first make sure that we save the old viewport and render target:</p>
<p><pre class="brush: plain;">
// Save the old RT and DS buffer views
ID3D10RenderTargetView* apOldRTVs[1] = { NULL };
ID3D10DepthStencilView* pOldDS = NULL;
pd3dDevice-&gt;OMGetRenderTargets( 1, apOldRTVs, &amp;pOldDS );

// Save the old viewport
D3D10_VIEWPORT OldVP;
UINT cRT = 1;
pd3dDevice-&gt;RSGetViewports( &amp;cRT, &amp;OldVP );

/** Start rendering to all the textures **/
RenderTextures(pd3dDevice);
</pre></p>
<p>Next we are going to look at the <strong>RenderTextures(..)</strong> function:</p>
<p><pre class="brush: plain;">
//--------------------------------------------------------------------
// Renders all the textures:
// -Diffuse
// -Normals
// -Position
// -Depth
//--------------------------------------------------------------------
void RenderTextures( ID3D10Device* pd3dDevice) {
  // Set a new viewport for rendering to texture(s)
  D3D10_VIEWPORT SMVP;
  SMVP.Height = _height * TEXSCALE;
  SMVP.Width = _width * TEXSCALE;
  SMVP.MinDepth = 0;
  SMVP.MaxDepth = 1;
  SMVP.TopLeftX = 0;
  SMVP.TopLeftY = 0;
  pd3dDevice-&gt;RSSetViewports( 1, &amp;SMVP );

  float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f };//{ 0.0f, 0.0f, 0.0f, 1.0f };

  // Clear Textures
  pd3dDevice-&gt;ClearRenderTargetView( _mrtRTV, ClearColor );
  pd3dDevice-&gt;ClearDepthStencilView( _mrtDSV, D3D10_CLEAR_DEPTH, 1.0, 0 );

  // set input layout
  pd3dDevice-&gt;IASetInputLayout( g_pVertexLayout );

  // Set all the render targets
  ID3D10RenderTargetView* aRTViews[ 1 ] = { _mrtRTV };
  UINT numRenderTargets = sizeof( aRTViews ) / sizeof( aRTViews[0] );
  pd3dDevice-&gt;OMSetRenderTargets( numRenderTargets, aRTViews, _mrtDSV );

  // Render the objects

  //_aoTextureVariable-&gt;SetResource(  _aoSRV );

  // Get the technique
  D3D10_TECHNIQUE_DESC techDesc;
  g_pTechnique-&gt;GetDesc( &amp;techDesc );

  // send the camera variables
  g_pProjectionVariable-&gt;SetMatrix( ( float* )g_Camera.GetProjMatrix() );
  g_pViewVariable-&gt;SetMatrix( ( float* )g_Camera.GetViewMatrix() );
  g_pWorldVariable-&gt;SetMatrix( ( float* )&amp;g_World );

  /** Render the Mesh ***/
  UINT Strides[1];
  UINT Offsets[1];
  ID3D10Buffer* pVB[1];
  pVB[0] = g_Mesh.GetVB10( 0, 0 );
  Strides[0] = ( UINT )g_Mesh.GetVertexStride( 0, 0 );
  Offsets[0] = 0;
  pd3dDevice-&gt;IASetVertexBuffers( 0, 1, pVB, Strides, Offsets );
  pd3dDevice-&gt;IASetIndexBuffer( g_Mesh.GetIB10( 0 ), g_Mesh.GetIBFormat10( 0 ), 0 );

  //D3D10_TECHNIQUE_DESC techDesc;
  g_pTechnique-&gt;GetDesc( &amp;techDesc );
  SDKMESH_SUBSET* pSubset = NULL;
  ID3D10ShaderResourceView* pDiffuseRV = NULL;
  D3D10_PRIMITIVE_TOPOLOGY PrimType;

  for( UINT subset = 0; subset &lt; g_Mesh.GetNumSubsets( 0 ); ++subset )   {     pSubset = g_Mesh.GetSubset( 0, subset );     PrimType = g_Mesh.GetPrimitiveType10( ( SDKMESH_PRIMITIVE_TYPE )pSubset-&gt;PrimitiveType );
    pd3dDevice-&gt;IASetPrimitiveTopology( PrimType );

    pDiffuseRV = g_Mesh.GetMaterial( pSubset-&gt;MaterialID )-&gt;pDiffuseRV10;
    g_ptxDiffuseVariable-&gt;SetResource( pDiffuseRV );

    g_pTechnique-&gt;GetPassByIndex( 2 )-&gt;Apply( 0 );
    pd3dDevice-&gt;DrawIndexed( ( UINT )pSubset-&gt;IndexCount, 0, ( UINT )pSubset-&gt;VertexStart );
  }
} // End Render Textures
</pre></p>
<p>Next we are going to look at the HLSL shader code for rendering to the multiple targets:</p>
<p><em><strong>NOTE:</strong> Before you start coding in HLSL (in Visual Studio) make sure you setup the debugger for it. It saved me a lot of time and headache. Thanks to Bobby Anguelov for the <a href="http://takinginitiative.net/2011/02/19/debugging-hlsl/" target="_blank">instructions</a>.</em></p>
<p><pre class="brush: plain;">
/******* Multiple Render Target Functions***************/

// Geometry Shader input - vertex shader output
struct GS_IN
{
    float4 Pos	: POSITION;  // WorldViewProj position
    float4 PosWV: TEXCOORD1; // World View Position
    float3 Norm : NORMAL;    // Normal
    float2 Tex	: TEXCOORD0; // Texture coord
};

// Pixel Shader in - Geometry Shader out
struct PS_MRT_INPUT
{
    float4 Pos  : SV_POSITION; 
    float4 PosWV: TEXCOORD1;    // World View Position
    float3 Norm: NORMAL;        //normal
    float2 Tex : TEXCOORD0;
    uint RTIndex : SV_RenderTargetArrayIndex; // which render target to write to (0-2)
};

//---------------------------------------------------------------------
// Simple Vertex Shader for MRT
//---------------------------------------------------------------------
GS_IN VSMRT( VS_INPUT input )
{
    GS_IN output = (GS_IN)0;
    
    input.Pos += input.Norm*Puffiness;
    
    output.PosWV = mul( float4(input.Pos,1), World );
    output.PosWV = mul( output.PosWV, View );
    output.Pos = mul( output.PosWV, Projection );
    output.Norm = mul( input.Norm, World );
    output.Norm = mul( output.Norm, View );
    output.Norm = mul( output.Norm, Projection );
    output.Tex = input.Tex;
    
    return output;
}

//----------------------------------------------------------------------
// Geometry Shader For MRT
//----------------------------------------------------------------------
[maxvertexcount(12)]
void GSMRT( triangle GS_IN input[3], inout TriangleStream&lt;PS_MRT_INPUT&gt; CubeMapStream )
{

    // 0 = diffuse color
    // 1 = normals
    // 3 = depth

    for( int f = 0; f &lt; 4; ++f )
    {
        // Compute screen coordinates
        PS_MRT_INPUT output;
        output.RTIndex = f;
        for( int v = 0; v &lt; 3; v++ )
        {
            output.Pos =  input[v].Pos;	// position
            output.PosWV =  input[v].PosWV;	// position
	    output.Norm = input[v].Norm;	// normal
			
            output.Tex = input[v].Tex;
            CubeMapStream.Append( output );
        }
        CubeMapStream.RestartStrip();
    }

} // end of geometry shader

float4 PSMRT( PS_MRT_INPUT input ) : SV_Target
{
	if (input.RTIndex == 0)	{	 // diffuse
	   return g_txDiffuse.Sample( samLinear, input.Tex  );
	}
	else if (input.RTIndex == 1) { // normal
	   // convert normal to texture space [-1;+1] -&gt; [0;1]
	   float4 normal;
	   normal.xyz = input.Norm * 0.5 + 0.5;
	   normal.w = 1.0;
	   return normal;
	}
	else if (input.RTIndex == 2) // position - not actually used
	   return input.PosWV;
	else {			     // depth
          float normalizedDistance = input.Pos.z / input.Pos.w;
	  
          normalizedDistance = 1.0f - normalizedDistance;
	  return float4(normalizedDistance, normalizedDistance, normalizedDistance, normalizedDistance);
	}
    //return input.Pos;
}
</pre></p>
<p>I am just going to focus on the geometry shader (<strong>GSMRT()</strong>) and pixel shader (<strong>PSMRT()</strong>). The code above renders 4 values: The <em>Diffuse colour</em> (from texture), the <em>view-space normals</em>, the <em>view-space position</em> and the <em>depth</em>. I actually don&#8217;t use the view-space position since I reconstruct the position from depth later on, but I thought I&#8217;d just leave it in there.</p>
<p>The geometry shader is essential for rendering to multiple targets. The <strong>&#8220;RTIndex&#8221;</strong> variable is used for telling the pixel shader to render to which target. Otherwise we just pass through the information (normals, UV-values, position, etc.)</p>
<p>In the pixel shader we read the RTIndex value and then write out the values we want to. Hopefully the code isn&#8217;t too complex and is comprehensible. Now you can go ahead and create the final render (composite texture), or apply other effects. I thought I might give Screen-Space Ambient Occlusion a try.</p>
<h4><span style="text-decoration:underline;"><em><strong>3. Ambient Occlusion &amp; Gaussian Blur:</strong></em></span></h4>
<p>Ambient Occlusion is a popular technique for adding realism to scenes. It takes into account &#8220;attenuation of light due to occlusion&#8221;. <strong><a href="http://en.wikipedia.org/wiki/Screen_Space_Ambient_Occlusion" target="_blank">Screen-Space Ambient Occlusion</a></strong> has been the most-popular and cost-effective way of implementing AO. The videogame Crysis was the first to implement it, and there have been multiple variants since. I implemented the SSAO algorithm<br />
featured on <a href="http://archive.gamedev.net/reference/programming/features/simpleSSAO/" target="_blank">GameDev.net</a>. I won&#8217;t go over the shader code here since GameDev has a pretty good explanation. </p>
<p>To render Ambient Occlusion the function <strong>&#8220;RenderAmbientOcclusion()&#8221;</strong> is called. The first step is to change the render target, and then we render a full-screen quad. The first pass will generate the AO texture, but it has a lot of noise. To &#8220;smooth out&#8221; the noise we apply gaussian blur. The blur shaders were taken from <a href="http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/" target="_blank">here</a> (it&#8217;s basically sampling from around the current pixel and averaging to smooth out &#8211; do it once for horizontal and then once for vertical).</p>
<p>SSAO requires a lot of computation &#8211; my framerate goes from 60 to ~11 when I turn on AO (though it&#8217;s roughly ~23 without gaussian blur). There shouldn&#8217;t be such a huge drop in the framerate; the texture lookup for the random vector is the bottleneck, and I can probably optimize it further.</p>
<p>Finally we can go on to create the final render.</p>
<h4><span style="text-decoration:underline;"><em><strong>4. Viewing Composite Texture:</strong></em></span></h4>
<p>To view the composite rendering we once again render a full-screen quad and pass in all the textures (diffuse, depth, normals, ambient occlusion). NOTE: The light variables are hard-coded into the shader (ideally you&#8217;d want to send them in). </p>
<p>The final shader is simple enough:<br />
<pre class="brush: plain;">
// Pixel Shader for rendering full-screen quad
// 0 = diffuse 
// 1 = normal (put specular in .w?)
// 2 = position
// 3 = depth
// 4 = ambient occlusion
// 5 = composite
float4 PSQuad( PS_INPUT input) : SV_Target 
{
   // get all the values

   // Diffuse
   float4 diffuse = _mrtTextures.Sample( samPoint, float3(input.Tex, 0) );
   if (TexToRender == 0)
   	return diffuse;

    // normals 
    float4 normals = _mrtTextures.Sample( samPoint, float3(input.Tex, 1) );
    normals =  (normals - 0.5) * 2.0;
    if (TexToRender == 1)
 	return normals;

    // depth
    float4 depth	= _mrtTextures.Sample( samPoint, float3(input.Tex, 3) );
    // discard
    if (depth.x == 0.0)
	return float4( 0.0f, 0.125f, 0.3f, 1.0f );
    if (TexToRender == 3)
	return depth;

    // position
    // reconstructed from depth value
    depth = 1.0 - depth;
    float4 H = float4(input.Tex.x * 2.0 - 1.0, 
                     (1.0 - input.Tex.y) * 2.0 - 1.0,  
		     depth.x,
		     1);
    float4 D = mul(H, ProjectionInverse);
    float4 position = D / D.w;
    if (TexToRender == 2)
        return position;
   
    // ambient occlusion
    float4 ao;
    if (UseAO == true) {
    	ao  = _aoTexture.Sample( samLinear, input.Tex );
    	if (TexToRender == 5)
	    return ao;

    // else calculate the light value - phong shading
    
    float3 lightDir = vLightPos - position.xyz;
    float3 eyeVec   = -position.xyz;
    float3 N        = normalize(normals);
    float3 E        = normalize(eyeVec);
    float3 L        = normalize(lightDir);
    float3 reflectV = reflect(-L, normals.xyz);

    // diffuse
    float4 dTerm = diffuse * max(dot(N, L), 0.0);

    // specular
    float4 specular = matSpecular * pow(max(dot(reflectV, E), 0.0), matShininess);

    float4 outputColor = dTerm;// + specular;
    if (UseAO == true) {
    	outputColor = outputColor * ao;
    }

    return outputColor;
}
</pre></p>
<p>First I read in all the different textures. And depending on which texture the user wants to view the value is returned. If the composite texture is to be viewed phong shading is performed. Though I calculate the specular value I don&#8217;t use it in my final rendering since it gives an overly plastic look. And depending on whether ambient occlusion is turned or not further the color is appropriately darkened.</p>
<h4><span style="text-decoration:underline;"><em><strong>Conclusion:</strong></em></span></h4>
<p>I went over how to setup multiple render targets and write to them, rendering a full-screen quad and ambient occlusion, and then creating a composite texture. If there is something in my code you don&#8217;t understand or have suggestions to improve please feel free to ask/let me know. </p>
<p>I will probably try to create a better scene and come up with better images. I might also try implementing shadow mapping since it shouldn&#8217;t be that difficult to include it in a deferred renderer.</p>
<p><strong>NOTE:</strong> When you exit my DirectX program it gives errors &#8211; I realize I don&#8217;t release all the resources but it should be ok.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
GitHub Repository and Visual Studio 2010 files:<br />
<strong><em>GitHub Repository</em></strong> <a href="https://github.com/pixelperfect3/deferredDX" target="_blank">here</a><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p><span style="text-decoration:underline;">Credits:</span></p>
<ol>
<li><a href="http://takinginitiative.net/2011/02/19/debugging-hlsl/">Debugging HLSL</a></li>
<li><a href="http://archive.gamedev.net/reference/programming/features/simpleSSAO/">A Simple and Practical Approach to SSAO</a></li>
<li><a href="http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/">Gaussian Blur Filter Shader</a></li>
</ol>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/159/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/159/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/159/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=159&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2011/06/26/deferred-shading-dx10/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/06/diffuse.png?w=300" medium="image">
			<media:title type="html">Diffuse Texture</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/06/normals.png?w=300" medium="image">
			<media:title type="html">View-space Normals</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/06/depth.png?w=300" medium="image">
			<media:title type="html">Depth Texture</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/06/ao.png?w=300" medium="image">
			<media:title type="html">Ambient Occlusion</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/06/composite.png?w=300" medium="image">
			<media:title type="html">Composite</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/06/compositenoao.png?w=300" medium="image">
			<media:title type="html">Composite Without AO</media:title>
		</media:content>
	</item>
		<item>
		<title>WebGL Anaglyph 3D using Three.js</title>
		<link>http://blog.shayanjaved.com/2011/06/01/webgl-anaglyph-3d-using-three-js/</link>
		<comments>http://blog.shayanjaved.com/2011/06/01/webgl-anaglyph-3d-using-three-js/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 08:27:34 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[WebGL]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[anaglyph]]></category>
		<category><![CDATA[three.js]]></category>
		<category><![CDATA[webgl]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=151</guid>
		<description><![CDATA[I have been meaning to get into WebGL for a while, and a few days ago I discovered this excellent WebGL library called Three.js on Github. Someone requested an Anaglyph WebGL Renderer for it, so I thought I might give it a try. After reading up on the code I came up with an example [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=151&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I have been meaning to get into WebGL for a while, and a few days ago I discovered this excellent WebGL library called <strong><a href="https://github.com/mrdoob/three.js">Three.js</a></strong> on Github.</p>
<p>Someone requested an Anaglyph WebGL Renderer for it, so I thought I might give it a try. After reading up on the code I came up with an example you can find <a href="http://www.cise.ufl.edu/~sjaved/webgl/webgl.html">here</a> (NOTE: Works best on latest version of Chrome and Firefox).</p>
<p>The author of Three.js has already fixed my version and incorporated an actual anaglyph renderer into his code. <a href="http://mrdoob.github.com/three.js/examples/webgl_materials_cars_anaglyph.html">Here</a> is an example.</p>
<p>If you are interested in WebGL development I would recommend checking out Three.js.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/151/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=151&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2011/06/01/webgl-anaglyph-3d-using-three-js/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>
	</item>
		<item>
		<title>Android OpenGL ES 2.0 &#8211; Shadow Mapping</title>
		<link>http://blog.shayanjaved.com/2011/05/20/android-opengl-es-2-0-shadow-mapping/</link>
		<comments>http://blog.shayanjaved.com/2011/05/20/android-opengl-es-2-0-shadow-mapping/#comments</comments>
		<pubDate>Sat, 21 May 2011 01:39:06 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[2.0]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[es]]></category>
		<category><![CDATA[mapping]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[pixel]]></category>
		<category><![CDATA[render to texture]]></category>
		<category><![CDATA[shaders]]></category>
		<category><![CDATA[shadow]]></category>
		<category><![CDATA[shadow mapping]]></category>
		<category><![CDATA[texture mapping]]></category>
		<category><![CDATA[vertex]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=97</guid>
		<description><![CDATA[NOTE: This tutorial builds up on my previous 2 tutorials: how to setup OpenGL ES 2.0 on Android and how to render to texture. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- I&#8217;ll first link to the apk, source code and the repository: apk here. Source code here. Google Code Repository  here. NOTE: Branch is &#8220;shadowMapping&#8221; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; UPDATE: Thanks to Henry&#8217;s comment below I was able to fix most [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=97&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>NOTE: </strong>This tutorial builds up on my previous 2 tutorials: <a href="http://blog.shayanjaved.com/2011/03/13/shaders-android/">how to setup OpenGL ES 2.0 on Android</a> and <a href="http://blog.shayanjaved.com/2011/05/13/android-opengl-es-2-0-render-to-texture/">how to render to texture</a>.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
I&#8217;ll first link to the apk, source code and the repository:<br />
<strong><em>apk</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersShadowMapping.apk">here</a>.</strong><br />
<strong><em>Source code</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersShadowMapping.zip">here.</a></strong><br />
<strong><em>Google Code Repository </em> <a href="http://code.google.com/p/androidshaders/">here.</a><strong> NOTE:</strong> Branch is &#8220;shadowMapping&#8221;</strong><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p><strong>UPDATE: </strong></p>
<p>Thanks to Henry&#8217;s comment below I was able to fix most of the artifacts showing up. Turns out I had dithering enabled, so I had to disable it to remove the dithering effect [ <em>GLES20.glDisable(GLES20.GL_DITHER)</em> ]. Updated images below &#8211; it works but has very slight artifacts when it comes to the mesh&#8217;s self-shadows.</p>
<h4><span style="text-decoration:underline;"><em><strong>Introduction:</strong></em></span></h4>
<p>Shadow Mapping is a popular technique for rendering shadows in games and other real-time applications. Given how GPUs on mobile devices (iPhone/Android/whatever) are getting more and more powerful every day I thought I might try implementing it on my<em> Samsung Captivate (Galaxy S).</em></p>
<p><del> While my implementation &#8220;works&#8221;, it does not good look at all. Shadow-mapping is prone to many artifacts , which I wasn&#8217;t able to properly fix (UPDATE: Main artifacts fixed).I am posting this without the fix in the hopes that somebody can help me out too as to what I am doing wrong.</del></p>
<p><em>Here are the updated images (I changed the color of the plane to get a better contrast):</em></p>
<div id="attachment_140" class="wp-caption aligncenter" style="width: 190px"><a href="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194443.png"><img class="size-medium wp-image-140 " title="Textured Cube" src="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194443.png?w=180&h=300" alt="" width="180" height="300" /></a><p class="wp-caption-text">Textured Cube (with proper shadows)</p></div>
<div id="attachment_141" class="wp-caption aligncenter" style="width: 190px"><a href="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194458.png"><img class="size-medium wp-image-141" title="Dragon Head" src="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194458.png?w=180&h=300" alt="" width="180" height="300" /></a><p class="wp-caption-text">Dragon Head</p></div>
<div id="attachment_142" class="wp-caption aligncenter" style="width: 190px"><a href="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194515.png"><img class="size-medium wp-image-142" title="Octahedron" src="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194515.png?w=180&h=300" alt="" width="180" height="300" /></a><p class="wp-caption-text">Octahedron</p></div>
<p><em><br />
</em></p>
<p><em>Here are the old images:</em></p>
<div id="attachment_108" class="wp-caption aligncenter" style="width: 190px"><a href="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183459.png"><img class="size-medium wp-image-108   " title="Octahedron shadow mapping" src="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183459.png?w=180&h=300" alt="" width="180" height="300" /></a><p class="wp-caption-text">Octahedron Mesh (.OFF) with shadows + artifacts</p></div>
<div id="attachment_109" class="wp-caption aligncenter" style="width: 190px"><a href="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183520.png"><img class="size-medium wp-image-109  " title="Dragon-head shadow mapping" src="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183520.png?w=180&h=300" alt="" width="180" height="300" /></a><p class="wp-caption-text">Dragon-head Mesh (.OFF)</p></div>
<div id="attachment_110" class="wp-caption aligncenter" style="width: 190px"><a href="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183548.png"><img class="size-medium wp-image-110  " title="Textured Cube shadow mapping" src="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183548.png?w=180&h=300" alt="" width="180" height="300" /></a><p class="wp-caption-text">Textured Cube (.OBJ)</p></div>
<p>I would like to credit <a href="http://fabiensanglard.net/shadowmapping/index.php">Fabien Sanglard</a> for his shadow mapping tutorials which I used as a basis for my code. I looked at his DEngine code as an example. In any case let&#8217;s begin.</p>
<h4><span style="text-decoration:underline;"><em><strong>What is Shadow Mapping?</strong></em></span></h4>
<p>If you are reading this chances are that you already know what shadow mapping is and how it works, but let me give a quick overview of the steps involved:</p>
<p><span id="more-97"></span></p>
<ol>
<li><strong>Generating the Shadow Map:</strong>The &#8220;shadow map&#8221; (aka a depth map) is just a texture which stores the depth of the scene from the viewpoint of the (directional) light. Scene is rendered from the light&#8217;s viewpoint into a texture.</li>
<li><strong>Rendering the Scene:</strong>The scene is rendered from the usual camera&#8217;s viewpoint. But along with the usual information the lightviewmatrix and the depth texture are passed in to the shader, and a texture projection is used to compare whether the current pixel being shaded is covered by a shadow or not.And that&#8217;s basically it! Shadow Mapping isn&#8217;t too complex, but it has a habit of producing a lot of nasty artifacts. So we will have to be careful when generating proper shadow maps, the matrices and doing the shading.</li>
</ol>
<h4><span style="text-decoration:underline;"><em><strong>Implementation: </strong></em></span></h4>
<ol>
<li><strong>The Scene:</strong>The scene is just composed of one mesh object (octahedron[.OFF], dragon&#8217;s head[.OFF] or textured cube[.OBJ]) above a plane (.OFF) with a rotating light. You can switch between the meshes and pause/resume the rotation of the light through the menus. I modified the <em>phong shader</em> to produce the shadows &#8211; the gouraud and normal mapping shaders function as before. To look at how all this is done please refer to my previous tutorials.<br />
<em><strong>NOTE:</strong></em> Shadow Mapping requires a &#8220;spotlight&#8221; to function &#8211; my shaders use &#8220;point lights&#8221;. To get shadows from point lights you have to render from multiple views around the light (<em>cube map</em> generation), so I just treat my point light as a spotlight for generating shadows, and render the rest of the non-shadowed scene as if lit by a point light.</li>
<li><strong>Generating the Shadow Map:</strong>To render the shadow map you have to render from the light&#8217;s viewpoint. The size of the depth map texture in my code is 512 X 512. You can view the depth map through the &#8220;View depth map&#8221; option in the menu. The rendering is done in the <em>renderDepthToTexture()</em>function:
<p><pre class="brush: plain;">
// Cull front faces for shadow generation
// Culling front faces is suggested for removing artifacts, but it doesn't seem to
// present a noticeable improvement
GLES20.glCullFace(GLES20.GL_FRONT);// Bind the shadow map texture now...
GLES20.glViewport(0, 0, this.texW, this.texH);// bind the generated framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0])

// specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTex[0], 0);

// attach render buffer as depth buffer
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRb[0]);

// check status
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE)
return false;

/*** DRAW ***/
// Clear color and buffers
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

// depth map shaders
// I used a new shader to generate the depth map.
Shader shader = _shaders[this.DEPTHMAP_SHADER];
int _program = shader.get_program();

// Start using the shader
GLES20.glUseProgram(_program);
checkGlError(&quot;glUseProgram&quot;);

// View from the light's perspective
Matrix.setLookAtM(lMVMatrix, 0, lightPos[0], lightPos[1], lightPos[2],
lightPos[4], lightPos[5], lightPos[6],
lightPos[7], lightPos[8], lightPos[9]);
float ratio2 = (float)texW /texH;
Matrix.frustumM(lProjMatrix, 0, -ratio2, ratio2, -1, 1, 1f, 5000f);

// modelviewprojection matrix
Matrix.multiplyMM(lMVPMatrix,0, lProjMatrix, 0, lMVMatrix, 0);

// send to the shader
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(_program, &quot;uMVPMatrix&quot;), 1, false, lMVPMatrix, 0);

/// DRAW ALL THE OBJECTS
drawAllObjects(_program, false, false);

// render the depth buffer?
if (viewDepthTex) {
renderToQuad();
return true;
}

/**** Else, render with shadow now --
*/
renderWithShadow(lMVPMatrix);
</pre></p>
<p>Hopefully the code above is self-explanatory. After we render the depth to the texture we can either view the depth texture or render the shadows. Next I am going to look at the <strong>depth map pixel shader</strong> which generates the depth map and then the &#8220;renderWithShadow&#8221; function.</p>
<p>The depth map pixel shader is written below. We basically just render the depth into a RGB texture. There might be better ways to do this, but this gave me good results.</p>
<p><pre class="brush: plain;">
// Pixel shader to generate the Depth Map
// Used for shadow mapping - generates depth map from the light's viewpoint precision highp float;

varying vec4 position; 

// taken from Fabien Sangalard's DEngine - this is used to pack the depth into a 32-bit texture (GL_RGBA)
vec4 pack (float depth)
{
	const vec4 bitSh = vec4(256.0 * 256.0 * 256.0,
					   256.0 * 256.0,
					   256.0,
					  1.0);
	const vec4 bitMsk = vec4(0,
					     1.0 / 256.0,
					     1.0 / 256.0,
				             1.0 / 256.0);
	vec4 comp = fract(depth * bitSh);
	comp -= comp.xxyz * bitMsk;
	return comp;
}

void main() {
	// the depth
	float normalizedDistance  = position.z / position.w;
        // scale it from 0-1
	normalizedDistance = (normalizedDistance + 1.0) / 2.0;
	
	// bias (to remove artifacts)
	normalizedDistance += 0.0005;

	// pack value into 32-bit RGBA texture
	gl_FragColor = pack(normalizedDistance);
	
}
</pre>
</li>
<li><strong>Rendering the Scene with Shadows:</strong>Now we have our depth texture. All we need to do is render the scene from the camera&#8217;s viewpoint. The only new variable we are passing in this time into the phong shader is the modelview matrix from the light&#8217;s viewpoint. The rendering is done in the &#8220;renderWithShadow(lMVPMatrix)&#8221; function. It works pretty much the same way as the rendering functions shown in the previous tutorials, so look at those first if you want to get an idea of how this works. The shadow map texture is attached as &#8220;shadowTexture&#8221;.We will modify our<em> phong vertex shader</em> slightly to accommodate the shadow projection matrix:
<p><pre class="brush: plain;">
// Vertex shader Phong Shading
...
// the shadow projection matrix
uniform mat4 shadowProjMatrix;
varying vec4 shadowCoord;
...
attribute vec4 aPosition;
...void main() {
...

shadowCoord = shadowProjMatrix * aPosition;
...
}
</pre></p>
<p>We are going to use these shadow coordinates to perform a texture lookup in our pixel shader and use them for testing whether the pixel is in shadow or not:</p>
<p><pre class="brush: plain;">
...

// This function looks up the shadow texture
// and returns whether the pixel is in shadow or not
float getShadowFactor(vec4 lightZ)
{
	vec4 packedZValue = texture2D(shadowTexture, lightZ.st);

	// unpack the value stored to get the depth. 
	const vec4 bitShifts = vec4(1.0 / (256.0 * 256.0 * 256.0),
						1.0 / (256.0 * 256.0),
						1.0 / 256.0,
						1);
	float shadow = dot(packedZValue , bitShifts);

	return float(shadow &amp;gt; lightZ.z);
}

void main() {
...
...
// ambient, diffuse and specular terms have been calculated

// Shadow
float sValue = 1.0; // for ambient + diffuse
float sValue2 = 1.0; // for specular
if (shadowCoord.w &amp;gt; 0.0) {
// get the shadow coordinates for the texture
vec4 lightZ = shadowCoord / 45.0;

// scale + bias
lightZ = (lightZ + 1.0) /2.0;
lightZ.z += 0.0005;

// get the shadow value
sValue = getShadowFactor(lightZ);

// scale the value from 0.5-1.0 to get a softer shadow
float newMin = 0.5;
float v1 = (1.0)/(1.0 - newMin);
float v2 = sValue/v1;
sValue2 = sValue + newMin;
}

gl_FragColor = ( (ambientTerm + diffuseTerm) * sValue2 + specularTerm * sValue) ;
}
</pre></p>
<p>The scene has been rendered. That&#8217;s pretty much all there is to it &#8211; the next step would be implementing percentage-closer filtering and other techniques to produce better shadows. </p>
<p>Any comments and questions are welcome.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Links to the apk, source code and the repository:<br />
<strong><em>apk</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersShadowMapping.apk">here</a>.</strong><br />
<strong><em>Source code</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersShadowMapping.zip">here.</a></strong><br />
<strong><em>Google Code Repository </em> <a href="http://code.google.com/p/androidshaders/">here.</a><strong> NOTE:</strong> Branch is &#8220;shadowMapping&#8221;</strong><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</li>
</ol>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/97/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/97/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/97/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=97&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2011/05/20/android-opengl-es-2-0-shadow-mapping/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194443.png?w=180" medium="image">
			<media:title type="html">Textured Cube</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194458.png?w=180" medium="image">
			<media:title type="html">Dragon Head</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/05/snap20110524_194515.png?w=180" medium="image">
			<media:title type="html">Octahedron</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183459.png?w=180" medium="image">
			<media:title type="html">Octahedron shadow mapping</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183520.png?w=180" medium="image">
			<media:title type="html">Dragon-head shadow mapping</media:title>
		</media:content>

		<media:content url="http://pixelp3.files.wordpress.com/2011/05/snap20110520_183548.png?w=180" medium="image">
			<media:title type="html">Textured Cube shadow mapping</media:title>
		</media:content>
	</item>
		<item>
		<title>Android OpenGL ES 2.0 &#8211; Render To Texture</title>
		<link>http://blog.shayanjaved.com/2011/05/13/android-opengl-es-2-0-render-to-texture/</link>
		<comments>http://blog.shayanjaved.com/2011/05/13/android-opengl-es-2-0-render-to-texture/#comments</comments>
		<pubDate>Sat, 14 May 2011 00:36:16 +0000</pubDate>
		<dc:creator>sjaay</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[2.0]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[es]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[render to texture]]></category>
		<category><![CDATA[texture mapping]]></category>

		<guid isPermaLink="false">http://blog.shayanjaved.com/?p=63</guid>
		<description><![CDATA[NOTE: This tutorial builds up on my previous tutorial on how to setup OpenGL ES 2.0 on Android. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- I&#8217;ll first link to the apk, source code and the repository: apk here. Source code here. Google Code Repository  here. NOTE: Branch is &#8220;renderToTex&#8221; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; Rendering to a texture is important when it comes to various graphics techniques and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=63&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>NOTE: </strong>This tutorial builds up on my previous <a href="http://blog.shayanjaved.com/2011/03/13/shaders-android/">tutorial</a> on how to setup OpenGL ES 2.0 on Android.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
I&#8217;ll first link to the apk, source code and the repository:<br />
<strong><em>apk</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersRenderToTex.apk">here</a>.</strong><br />
<strong><em>Source code</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersRenderToTex.zip">here.</a></strong><br />
<strong><em>Google Code Repository </em> <a href="http://code.google.com/p/androidshaders/">here.</a><strong> NOTE:</strong> Branch is &#8220;renderToTex&#8221;</strong><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Rendering to a texture is important when it comes to various graphics techniques and algorithms (Shadow Mapping, cube map generation, Deferred Shading, etc.) So this quick tutorial will demonstrate how to setup a texture for rendering (and then how to display that texture on screen).</p>
<p><strong>What is rendered to the texture?</strong><br />
We are going to render the same objects as in the previous tutorial (where you can choose between gouraud/phong/normal mapping shaders). The texture is going to be a <em>simple quad</em> which will then be displayed on the full screen. I have a <em>Samsung Captivate</em>(Samsung Galaxy S) which has a screen resolution of 800 X 480, so I use those values as the height and width of my texture. Adjust accordingly to your phone (I was a tad lazy to read in the values from the system itself). Let&#8217;s begin:</p>
<p><span id="more-63"></span></p>
<ol>
<ol>
<li><strong><em>New Variable declarations:</em></strong></li>
</ol>
</ol>
<p>The variables below are for creating the quad to render the texture onto:</p>
<p><pre class="brush: plain;">
// the full-screen quad buffers
final float x = 10.0f;
final float y = 15.0f;
final float z = 2.0f;
// vertex information - clockwise
                       // x,  y, z, nx, ny, nz, u, v
final float _quadv[] = { -x, -y, z, 0, 0, -1, 0, 0,
			-x,  y, z, 0, 0, -1, 0, 1,
			 x,  y, z, 0, 0, -1, 1, 1,
			 x, -y, z, 0, 0, -1, 1, 0
			};

private FloatBuffer _qvb;
// index
final int _quadi[] = { 0, 1, 2,
		      2, 3, 0 };
private IntBuffer _qib;
</pre></p>
<p>Variables used for rendering to texture are declared below:</p>
<p><pre class="brush: plain;">
// RENDER TO TEXTURE VARIABLES
int[] fb, depthRb, renderTex; // the framebuffer, the renderbuffer and the texture to render
int texW = 480 * 2;           // the texture's width
int texH = 800 * 2;           // the texture's height
IntBuffer texBuffer;          //  Buffer to store the texture
</pre></p>
<ol>
<ol>
<li><strong><em>Setup Render To Texture:</em></strong></li>
</ol>
</ol>
<p>The method setupRenderToTexture() (Hopefully the comments give enough detail):<br />
<pre class="brush: plain;">
// create the ints for the framebuffer, depth render buffer and texture
fb = new int[1];
depthRb = new int[1];
renderTex = new int[1];

// generate
GLES20.glGenFramebuffers(1, fb, 0);
GLES20.glGenRenderbuffers(1, depthRb, 0); // the depth buffer
GLES20.glGenTextures(1, renderTex, 0);

// generate texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[0]);

// parameters - we have to make sure we clamp the textures to the edges
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
		GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
		GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
		GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
		GLES20.GL_LINEAR);

// create it
// create an empty intbuffer first
int[] buf = new int[texW * texH];
texBuffer = ByteBuffer.allocateDirect(buf.length
		* FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asIntBuffer();;

// generate the textures
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texW, texH, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_SHORT_5_6_5, texBuffer);

// create render buffer and bind 16-bit depth buffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, texW, texH);
</pre></p>
<ol>
<ol>
<li><strong><em>Rendering:</em></strong></li>
</ol>
</ol>
<p>The rendering begins in the <em>onDrawFrame()</em> method. First we render to texture:</p>
<p><pre class="brush: plain;">
// viewport should match texture size
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 0.5f, 10);
GLES20.glViewport(0, 0, this.texW, this.texH);

// Bind the framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);

// specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTex[0], 0);

// attach render buffer as depth buffer
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRb[0]);

// check status
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE)
	return false;

// Clear the texture (buffer) and then render as usual...
GLES20.glClearColor(.0f, .0f, .0f, 1.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

....usual rendering continues....
</pre></p>
<p>The final step is to render the quad itself to cover the screen fully (this is done using the gouraud shader):</p>
<p><pre class="brush: plain;">
// Bind the default framebuffer (to render to the screen) - indicated by '0'
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

GLES20.glClearColor(.0f, .0f, .0f, 1.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

...setup all the matrices as usual....

// send the vertex coordinates
_qvb.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(_program, &quot;aPosition&quot;), 3, GLES20.GL_FLOAT, false,
		TRIANGLE_VERTICES_DATA_STRIDE_BYTES, _qvb);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(_program, &quot;aPosition&quot;));

// the normal info (though shouldn't be needed)
_qvb.position(TRIANGLE_VERTICES_DATA_NOR_OFFSET);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(_program, &quot;aNormal&quot;), 3, GLES20.GL_FLOAT, false,
		TRIANGLE_VERTICES_DATA_STRIDE_BYTES, _qvb);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(_program, &quot;aNormal&quot;));

// bind the framebuffer texture - this is what will be attached to the quad
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[0]);
GLES20.glUniform1i(GLES20.glGetUniformLocation(_program, &quot;texture1&quot;), 0);

// enable texturing? [fix - sending float is waste]
GLES20.glUniform1f(GLES20.glGetUniformLocation(_program, &quot;hasTexture&quot;), 1.0f);

// texture coordinates
_qvb.position(TRIANGLE_VERTICES_DATA_TEX_OFFSET);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(_program, &quot;textureCoord&quot;), 2, GLES20.GL_FLOAT, false,
		TRIANGLE_VERTICES_DATA_STRIDE_BYTES, _qvb);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(_program, &quot;textureCoord&quot;));//GLES20.glEnableVertexAttribArray(shader.maTextureHandle);

// Draw with indices
GLES20.glDrawElements(GLES20.GL_TRIANGLES, _quadi.length, GLES20.GL_UNSIGNED_INT, _qib);
</pre></p>
<p>And that&#8217;s it! Hopefully all the comments in the code snippets above explain everything. The quad and texture sizes are something I just fiddled around with, so adjust accordingly to the device you are testing on.</p>
<p>If you have any questions, suggestions or comments please let me know.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Links to the apk, source code and the repository:<br />
<strong><em>apk</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersRenderToTex.apk">here</a>.</strong><br />
<strong><em>Source code</em> <a href="http://dl.dropbox.com/u/6665854/AndroidShadersRenderToTex.zip">here.</a></strong><br />
<strong><em>Google Code Repository </em> <a href="http://code.google.com/p/androidshaders/">here.</a><strong> NOTE:</strong> Branch is &#8220;renderToTex&#8221;</strong><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pixelp3.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pixelp3.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pixelp3.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pixelp3.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pixelp3.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pixelp3.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pixelp3.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pixelp3.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pixelp3.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pixelp3.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pixelp3.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pixelp3.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pixelp3.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pixelp3.wordpress.com/63/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.shayanjaved.com&#038;blog=15417419&#038;post=63&#038;subd=pixelp3&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.shayanjaved.com/2011/05/13/android-opengl-es-2-0-render-to-texture/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1fb49ce77e774c0a5652a6683dc47a09?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sjaay</media:title>
		</media:content>
	</item>
	</channel>
</rss>
