<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>#AltDevBlogADay &#187; Rolando-Abarca</title>
	<atom:link href="http://www.altdevblogaday.com/author/rolando-abarca/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.altdevblogaday.com</link>
	<description>Each day a little more #gamedev love</description>
	<lastBuildDate>Thu, 17 May 2012 03:06:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Naive fallback to canvas from WebGL</title>
		<link>http://www.altdevblogaday.com/2011/10/29/naive-fallback-to-canvas-from-webgl/</link>
		<comments>http://www.altdevblogaday.com/2011/10/29/naive-fallback-to-canvas-from-webgl/#comments</comments>
		<pubDate>Sat, 29 Oct 2011 15:00:17 +0000</pubDate>
		<dc:creator>Rolando-Abarca</dc:creator>
				<category><![CDATA[#gamedev]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[webgl]]></category>

		<guid isPermaLink="false">http://altdevblogaday.com/?p=19437</guid>
		<description><![CDATA[<h1>Disclaimer</h1>
<p>Falling back to canvas should be used only when your game is really simple and has no fancy shader. It can also be used to provide the player with a subset of the experience of your game, for instance for mobile devices, when there&#8217;s no WebGL support. So what I&#8217;ll descrive here only works for really simple games and perhaps, to just show a limited experience instead of a &#8220;download Chrome to play this game&#8221;</p>
<p><a href="http://www.altdevblogaday.com/2011/10/29/naive-fallback-to-canvas-from-webgl/" class="more-link">Read more on Naive fallback to canvas from WebGL&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<h1>Disclaimer</h1>
<p>Falling back to canvas should be used only when your game is really simple and has no fancy shader. It can also be used to provide the player with a subset of the experience of your game, for instance for mobile devices, when there&#8217;s no WebGL support. So what I&#8217;ll descrive here only works for really simple games and perhaps, to just show a limited experience instead of a &#8220;download Chrome to play this game&#8221;</p>
<h1>The theory and implementation</h1>
<p>When writing <a href="http://github.com/funkaster/ChesterGL">ChesterGL</a> I realized that if I kept the rendering logic isolated enough, I could easily create a thin layer for adding new rendering techniques, like Canvas API or plain DOM. The rationale behind is that all the math is done in a very general way (using the good old matrix transformations), so I just needed to think through it. One thing that makes things easier, is that for every image (sprite) rendered on screen, you don&#8217;t really need to position the image, just set the transform of the current context before drawing and that&#8217;s it. And of course, you can easily get the transform from the current model-view matrix:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">ChesterGL.<span style="color: #660066;">Block</span>.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">render</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ChesterGL.<span style="color: #660066;">webglMode</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// ... the usual WebGL way</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> gl <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">offContext</span><span style="color: #339933;">;</span>
		<span style="color: #006600; font-style: italic;">// canvas drawing api - we only draw textures</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">program</span> <span style="color: #339933;">==</span> ChesterGL.<span style="color: #660066;">Block</span>.<span style="color: #660066;">PROGRAM</span>.<span style="color: #660066;">TEXTURE</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #003366; font-weight: bold;">var</span> m <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> texture <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">getAsset</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'texture'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">texture</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			gl.<span style="color: #660066;">globalAlpha</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">opacity</span><span style="color: #339933;">;</span>
			gl.<span style="color: #660066;">setTransform</span><span style="color: #009900;">&#40;</span>m<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> m<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> m<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> m<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">5</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> m<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">12</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> m<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">13</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> w <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">contentSize</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> h <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">contentSize</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> frame <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">frame</span><span style="color: #339933;">;</span>
			gl.<span style="color: #660066;">drawImage</span><span style="color: #009900;">&#40;</span>texture<span style="color: #339933;">,</span> frame<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> texture.<span style="color: #660066;">height</span> <span style="color: #339933;">-</span> <span style="color: #009900;">&#40;</span>frame<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> h<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> frame<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> frame<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">3</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span>w<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span>h<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> w<span style="color: #339933;">,</span> h<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I added an option to set the opacity of the sprite as well by changing the state of the context before drawing. If you look at the drawImage call, we can even support sprite sheets very easily. So with only a few lines, you can support WebGL sprites as well as pure canvas API sprites. Since we use the same matrix for WebGL and canvas, the whole scene graph is preserved so everything else works the same way.</p>
<p>So where should you start this? I did it in the initialization code, where you create the WebGL context from the canvas, if that fails, then create a 2d context:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * tryies to init the graphics stuff:
 * 1st attempt: webgl
 * fallback: canvas
 */</span>
ChesterGL.<span style="color: #660066;">initGraphics</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">canvas</span> <span style="color: #339933;">=</span> canvas<span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">webglMode</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;experimental-webgl&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;ERROR: &quot;</span> <span style="color: #339933;">+</span> e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// fallback to canvas API (can use an offscreen buffer)</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;2d&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">usesOffscreenBuffer</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offCanvas</span> <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'canvas'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offCanvas</span>.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">width</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offCanvas</span>.<span style="color: #660066;">height</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">height</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offCanvas</span>.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;2d&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span>.<span style="color: #660066;">viewportWidth</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">width</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span>.<span style="color: #660066;">viewportHeight</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">height</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'offContext'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'viewportWidth'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span>.<span style="color: #660066;">viewportWidth</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'viewportHeight'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span>.<span style="color: #660066;">viewportHeight</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">throw</span> <span style="color: #3366CC;">&quot;Error initializing graphic context!&quot;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">webglMode</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'gl'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// get real width and height</span>
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span>.<span style="color: #660066;">viewportWidth</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">width</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span>.<span style="color: #660066;">viewportHeight</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">height</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'viewportWidth'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span>.<span style="color: #660066;">viewportWidth</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'viewportHeight'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span>.<span style="color: #660066;">viewportHeight</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>There are some things that will not work, the most obvious being batched sprites (BlockGroup in ChesterGL) and shaders. But if you want to have a very simple fallback line, this could work.</p>
<p>For clearing the screen, you have two options: either clear the whole rect, or paint it some color. I opted for drawing a black rectangle to simulate the glClear in WebGL:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * main draw function, will call the root block
 */</span>
ChesterGL.<span style="color: #660066;">drawScene</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">webglMode</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// WebGL draw mode here</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #003366; font-weight: bold;">var</span> gl <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offContext</span><span style="color: #339933;">;</span>
		gl.<span style="color: #660066;">setTransform</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		gl.<span style="color: #660066;">fillRect</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">viewportWidth</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">viewportHeight</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// start mayhem</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">rootBlock</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">rootBlock</span>.<span style="color: #660066;">visit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">webglMode</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// copy back the off context (if we use one)</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">usesOffscreenBuffer</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span>.<span style="color: #660066;">fillRect</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">viewportWidth</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">viewportHeight</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span>.<span style="color: #660066;">drawImage</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">offCanvas</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I even let the option there to use an offscreen buffer for drawing (something like double buffering). I did some quick performance test and I couldn&#8217;t find a big difference between using fillRect instead of clear. Also, we need to set the transform to the unit matrix.</p>
<h1>Conclusion</h1>
<p>It can be very trivial to have a simple fallback to canvas API, but you must keep in mind what you will use it for. One concern would be performance: it is definitively not bad, but it&#8217;s not as good as it can be with WebGL, also you will lose all the cool things you would be able to do in WebGL, like adding 3D objects to your 2d game, 3D effects/transitions or fancy shaders.</p>
<p>One way to optimize the canvas API rendering would be to do not draw the whole screen and use just dirty rects to only draw the things that where modified. Another optimization would be to port BlockGroup (batched sprites) and draw those sprites to an offscreen buffer, this would work great for tiled maps or backgrounds.</p>
<p>That&#8217;s it&#8230; easy and simple fallback to canvas API when WebGL is now available for your game. Oh, and it also works on iOS! I got ~26fps with 12 moving sprites on iOS 4.3.5 and ~35fps with 42 moving sprites on iOS 5 &#8211; pretty good for canvas!</p>
<p>If you want to try this technique, you&#8217;re more than welcome to download <a href="http://github.com/funkaster/ChesterGL">ChesterGL</a> or fork it from <a href="http://github.com/funkaster/ChesterGL">github</a> (but please note that ChesterGL is still a work in progress that I maintain on my free time). If you&#8217;re also interested, you can read the <a href="http://altdevblogaday.com/2011/09/29/meet-my-dog-chester/">original article</a> where I introduced ChesterGL.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.altdevblogaday.com/2011/10/29/naive-fallback-to-canvas-from-webgl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Meet my dog Chester</title>
		<link>http://www.altdevblogaday.com/2011/09/29/meet-my-dog-chester/</link>
		<comments>http://www.altdevblogaday.com/2011/09/29/meet-my-dog-chester/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 00:00:56 +0000</pubDate>
		<dc:creator>Rolando-Abarca</dc:creator>
				<category><![CDATA[#gamedev]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[webgl]]></category>

		<guid isPermaLink="false">http://altdevblogaday.com/?p=17500</guid>
		<description><![CDATA[<h1>Meet Chester</h1>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/09/IMG_0027.jpg"><img class="size-full wp-image-17525 alignright" src="http://altdevblogaday.com/wp-content/uploads/2011/09/IMG_0027.jpg" alt="The Coding Dog" width="256" height="276" /></a>Chester is my dog. He&#8217;s sloppy and messy, but most of the time, let&#8217;s say 80% of the time he&#8217;s the best dog in the world PERIOD.</p>
<p>The other that I asked him: &#8220;Hey Chester, would you mind teaching me some WebGL? I understand you&#8217;ve been playing a lot with it, and you even made some cool WebGL demo&#8221;, and since he&#8217;s such a good dog he had no problem in teaching me.</p>
<p><a href="http://www.altdevblogaday.com/2011/09/29/meet-my-dog-chester/" class="more-link">Read more on Meet my dog Chester&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<h1>Meet Chester</h1>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/09/IMG_0027.jpg"><img class="size-full wp-image-17525 alignright" src="http://altdevblogaday.com/wp-content/uploads/2011/09/IMG_0027.jpg" alt="The Coding Dog" width="256" height="276" /></a>Chester is my dog. He&#8217;s sloppy and messy, but most of the time, let&#8217;s say 80% of the time he&#8217;s the best dog in the world PERIOD.</p>
<p>The other that I asked him: &#8220;Hey Chester, would you mind teaching me some WebGL? I understand you&#8217;ve been playing a lot with it, and you even made some cool WebGL demo&#8221;, and since he&#8217;s such a good dog he had no problem in teaching me.</p>
<h2>First, the first</h2>
<p>Chester is a good dog, but he&#8217;s not a good teacher, and he has little patience, so he told me: &#8220;if you want to learn webgl, just go to <a href="http://learningwebgl.com/blog/?page_id=1217">learning webgl</a> and when you finish with the lessons, come back for some really premium extra knwoledge&#8221;.</p>
<p>After reading the lessons, Chester asked me: &#8220;hey, what about we go through the basics? &#8211; and while we&#8217;re on it, let&#8217;s take a look on how we can optimize what you just learned &#8211; but for 2d, and add some other things in the way, like a graceful fallback to canvas when webgl is not enabled.&#8221;</p>
<p>And so we did. These are the basics.</p>
<h3>1) WebGL == OpenGL-ES 2.0</h3>
<p>Don&#8217;t know OpenGL? what about OpenGL-ES 2.0? if not, go <a href="http://goo.gl/DSx7w">read</a> <a href="http://goo.gl/1T6AS">some</a> <a href="http://goo.gl/fKFJs">books</a>. If you&#8217;re not in the mood for those books, the <a href="http://learningwebgl.com/blog/?page_id=1217">webgl lessons</a> are good enough for starters.</p>
<h3>2) Let&#8217;s take you to the matrices</h3>
<p>When it comes down to WebGL, it&#8217;s all about your matrices, you have the projection matrix, the model-view matrix and some other matrices.</p>
<p>But what are the 3d matrices? Here&#8217;s where your linear algebra classes must be remembered. For us they&#8217;re going to be basically transformation matrices. 3D ones. So you use them to store your model transformations: translate, rotate, scale. In order to concatenate two transformations, you would just multiply them and the result is the concatenation.</p>
<p>In order to understand a little bit more about this, Chester brought up the next example: let&#8217;s create a simple <a href="http://en.wikipedia.org/wiki/Scene_graph">scene graph</a>, you know, like the one used in a very well known 2d game engine <a href="http://www.cocos2d-iphone.org">cocos2d</a>.</p>
<p>The scene graph is what holds the objects in your game scene and how you would traverse them. The basic structure we&#8217;re going to use is a block (like a construction block) and every block can contain other blocks. Blocks transformation should be relative to it&#8217;s parent, like so:</p>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/09/1.png"><img class="alignnone size-full wp-image-17529" style="border-width: 1px;border-color: black;border-style: solid" src="http://altdevblogaday.com/wp-content/uploads/2011/09/1.png" alt="" width="300" height="300" /></a></p>
<p>In this example, the big block (a 64px square) is the parent and the small one (a 32px square) is the child. The big block is positionated at the middle of the canvas, and the little one has a relative position of {32,0}. Since 32 is half the width of the parent, the center of the child is exactly on the right side.</p>
<p>Ok, let&#8217;s have some fun, first let&#8217;s move the little one outside the bounds of the block, so if we set its position to {32 + 16, 0}, it should be right outside:</p>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/09/2.png"><img class="alignnone size-full wp-image-17531" style="border-width: 1px;border-color: black;border-style: solid" src="http://altdevblogaday.com/wp-content/uploads/2011/09/2.png" alt="" width="300" height="300" /></a></p>
<p>Cool. Now let&#8217;s rotate the bock 45 degrees:</p>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/09/3.png"><img class="alignnone size-full wp-image-17532" style="border-width: 1px;border-color: black;border-style: solid" src="http://altdevblogaday.com/wp-content/uploads/2011/09/3.png" alt="" width="300" height="300" /></a></p>
<p>Even cooler :) &#8211; What would happen if we rotate the parent in -45 degrees?</p>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/09/4.png"><img class="alignnone size-full wp-image-17533" style="border-width: 1px;border-color: black;border-style: solid" src="http://altdevblogaday.com/wp-content/uploads/2011/09/4.png" alt="" width="300" height="300" /></a></p>
<p>And that&#8217;s how our concatenated transformations should work: the child transformation (so far, rotation -&gt; translation) should be concatenated to the one from the parent. The first 3 examples were just a single translation, but after that, we added the rotation, and since we rotated the parent in -45 degrees, it looks like if our little block is not rotated.</p>
<p>Fun fun. But enough for now said Chester, we need to move on.</p>
<h3>3) It&#8217;s all about 2D</h3>
<p>We&#8217;re going to use WebGL, a 3D engine to do some cool and performant 2D graphics, like 2D sprites and 2D games. So Chester said &#8220;When doing 2D we face a completely different challenge: you will not be filling the screen with thousands of triangles, you will be sending lots of textures to the screen, so your bottleneck will be the fill rate instead of how many triangles you want to draw. The fill rate is how fast you can send the texture &#8212; usually a much higher quality texture than in a 3D game &#8212; and how many of them you can use at the same time in the screen&#8221;. Then, after a small break playing with the ball, Chester continued &#8220;The thing is, to achieve what we want, we will be fixing a coordinate, in this case z = 0, to draw everything in a plane. Thus, our sprites will be represented by two triangles forming a square and that square is the constructing block we talked about earlier.&#8221;</p>
<h2>Show me the code!</h2>
<p>I was getting a little bit bored with too much talking and no coding, so I demanded Chester to show me the code. He said &#8220;ok, but I will just give you the hints, you can build up from there and make sure you refer to the webgl lessons when you feel lost&#8221;.</p>
<p>And so, Chester continued &#8220;The first thing we will do, is to set our projection. The projection we&#8217;re looking for must be a 3D, but must look 1-1 with the pixel size of the canvas we&#8217;re drawing into, right?&#8221;. And then he started typing.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">setupPerspective<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> gl <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span><span style="color: #339933;">;</span>
&nbsp;
	gl.<span style="color: #660066;">clearColor</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0.0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0.0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0.0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1.0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	gl.<span style="color: #660066;">clearDepth</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1.0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> width <span style="color: #339933;">=</span> gl.<span style="color: #660066;">viewportWidth</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> height <span style="color: #339933;">=</span> gl.<span style="color: #660066;">viewportHeight</span><span style="color: #339933;">;</span>
	gl.<span style="color: #660066;">viewport</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> width<span style="color: #339933;">,</span> height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">pMatrix</span> <span style="color: #339933;">=</span> mat4.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">projection</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;2d&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// 2d projection</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;setting up 2d projection (&quot;</span> <span style="color: #339933;">+</span> width <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;,&quot;</span> <span style="color: #339933;">+</span> height <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		mat4.<span style="color: #660066;">ortho</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> width<span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> height<span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1024</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1024</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">pMatrix</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">projection</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;3d&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// 3d projection</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;setting up 3d projection (&quot;</span> <span style="color: #339933;">+</span> width <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;,&quot;</span> <span style="color: #339933;">+</span> height <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> matA   <span style="color: #339933;">=</span> mat4.<span style="color: #660066;">perspective</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">60</span><span style="color: #339933;">,</span> width <span style="color: #339933;">/</span> height<span style="color: #339933;">,</span> <span style="color: #CC0000;">0.5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1500.0</span><span style="color: #339933;">,</span> matA<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> zeye <span style="color: #339933;">=</span> height <span style="color: #339933;">/</span> <span style="color: #CC0000;">1.1566</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> eye    <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>width<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> height<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> zeye<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> center <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>width<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> height<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> up     <span style="color: #339933;">=</span> vec3.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> matB <span style="color: #339933;">=</span> mat4.<span style="color: #660066;">lookAt</span><span style="color: #009900;">&#40;</span>eye<span style="color: #339933;">,</span> center<span style="color: #339933;">,</span> up<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		mat4.<span style="color: #660066;">multiply</span><span style="color: #009900;">&#40;</span>matA<span style="color: #339933;">,</span> matB<span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">pMatrix</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">throw</span> <span style="color: #3366CC;">&quot;Invalid projection: &quot;</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">projection</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></div></div>

<p>NOTE: &#8220;for now, think of <code>this</code> as a magic object that holds some important information. We will be building around it and with time, you will understand&#8221;, Chester said.</p>
<p>The first thing that I asked after reading the code was &#8220;Wait! what&#8217;s that weird hardcoded 1.1566 number!?&#8221;. And Chester told me what it was:</p>
<p>&#8220;It&#8217;s there to gives us a 1-1 relation between opengl points and pixels at the plane z=0. It has to do with the field of view, which we also hardcoded to 60 degrees. Don&#8217;t ask me how I came up with this number &#8211; it&#8217;s being transfered over generations&#8221;. Later I found that Chester just copied the number from cocos2d and that he couldn&#8217;t trace the number. But you will have to believe me that it has to do with the fov.</p>
<p>And then Chester started to discuss the &#8220;3d&#8221; projection.</p>
<p>&#8220;So, you first create a simple projection matrix, with a fov of 60 degrees, with the right aspect ratio, znear of 0.5 and zfar of 1500, and store that in matA. After that, we calculate the parameters for the lookAt, which are the zeye previously discussed, the eye, center and up vectors. We pack all those into matrix B, and concatenate those transformations in the pMatrix, the <em>projection</em> Matrix.&#8221;<a href="#fn1">[1]</a></p>
<p>So, how do I render a sprite? I asked Chester, and so Chester answered.</p>
<p>&#8220;What is a sprite? I already told you a sprite is two triangles, but how are they represented in the webgl world? Let&#8217;s see what we need first.&#8221;</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
* @type {?WebGLBuffer}
*/</span>
glBuffer<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
&nbsp;
<span style="color: #006600; font-style: italic;">/**
* @type {Float32Array}
*/</span>
glBufferData<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span></pre></div></div>

<p>That&#8217;s all? I asked, what about the buffer for color, position and textures? (remembering the lessons in webgl). And Chester told me that we could pack all those in a single array, a technique known as &#8220;interleaved array&#8221;. That sounded cool, so I asked him more about that.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * this is the size of the buffer data (Float32Array)
 * @const
 */</span>
Block.<span style="color: #660066;">QUAD_SIZE</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">36</span><span style="color: #339933;">;</span>
&nbsp;
Block.<span style="color: #660066;">create</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> b <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Block<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		b.<span style="color: #660066;">setFrame</span><span style="color: #009900;">&#40;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #006600; font-style: italic;">// set default color</span>
	b.<span style="color: #660066;">setColor</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> gl <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">gl</span><span style="color: #339933;">;</span>
	<span style="color: #006600; font-style: italic;">// just a single buffer for all data (a &quot;quad&quot;)</span>
	b.<span style="color: #660066;">glBuffer</span> <span style="color: #339933;">=</span> gl.<span style="color: #660066;">createBuffer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	b.<span style="color: #660066;">glBufferData</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Float32Array<span style="color: #009900;">&#40;</span>Block.<span style="color: #660066;">QUAD_SIZE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// always create the mvMatrix</span>
	b.<span style="color: #660066;">mvMatrix</span> <span style="color: #339933;">=</span> mat4.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	mat4.<span style="color: #660066;">identity</span><span style="color: #009900;">&#40;</span>b.<span style="color: #660066;">mvMatrix</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">return</span> b<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Why 36? I know what a &#8220;quad&#8221; is (frame + texture + colors), but why 36?</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #CC0000;">36</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">12</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">8</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">16</span>
<span style="color: #CC0000;">12</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">4</span> <span style="color: #006600; font-style: italic;">// 4 points for the frame, 3 coords each (x, y, z)</span>
<span style="color: #CC0000;">8</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">4</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">2</span> <span style="color: #006600; font-style: italic;">// 4 points for the tex coord, 2 coords each (u,v)</span>
<span style="color: #CC0000;">16</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">4</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">4</span> <span style="color: #006600; font-style: italic;">// 4 colors, one for each point in the frame, 4 coords each (r, g, b, a)</span></pre></div></div>

<p>Ok, that makes sense. But how do we send the data to the GPU?</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">render<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> gl <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">gl</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// select current shader</span>
	<span style="color: #003366; font-weight: bold;">var</span> program <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">selectProgram</span><span style="color: #009900;">&#40;</span>Block.<span style="color: #660066;">PROGRAM_NAME</span><span style="color: #009900;">&#91;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">program</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	gl.<span style="color: #660066;">bindBuffer</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">ARRAY_BUFFER</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">glBuffer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> texOff <span style="color: #339933;">=</span> <span style="color: #CC0000;">12</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">4</span><span style="color: #339933;">,</span>
	    colorOff <span style="color: #339933;">=</span> texOff <span style="color: #339933;">+</span> <span style="color: #CC0000;">8</span> <span style="color: #339933;">*</span> <span style="color: #CC0000;">4</span><span style="color: #339933;">;</span>
&nbsp;
	gl.<span style="color: #660066;">vertexAttribPointer</span><span style="color: #009900;">&#40;</span>program.<span style="color: #660066;">attribs</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'vertexPositionAttribute'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">3</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">FLOAT</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	gl.<span style="color: #660066;">vertexAttribPointer</span><span style="color: #009900;">&#40;</span>program.<span style="color: #660066;">attribs</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'vertexColorAttribute'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">4</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">FLOAT</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> colorOff<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	gl.<span style="color: #660066;">uniform1f</span><span style="color: #009900;">&#40;</span>program.<span style="color: #660066;">opacityUniform</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">opacity</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> texture <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">getAsset</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'texture'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">texture</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// pass the texture attributes</span>
	gl.<span style="color: #660066;">vertexAttribPointer</span><span style="color: #009900;">&#40;</span>program.<span style="color: #660066;">attribs</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'textureCoordAttribute'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">FLOAT</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> texOff<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	gl.<span style="color: #660066;">activeTexture</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">TEXTURE0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	gl.<span style="color: #660066;">bindTexture</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">TEXTURE_2D</span><span style="color: #339933;">,</span> texture.<span style="color: #660066;">tex</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	gl.<span style="color: #660066;">uniform1i</span><span style="color: #009900;">&#40;</span>program.<span style="color: #660066;">samplerUniform</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>				
&nbsp;
	<span style="color: #006600; font-style: italic;">// set the matrix uniform (actually, only the model view matrix)</span>
	gl.<span style="color: #660066;">uniformMatrix4fv</span><span style="color: #009900;">&#40;</span>program.<span style="color: #660066;">mvMatrixUniform</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	gl.<span style="color: #660066;">drawArrays</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">TRIANGLE_STRIP</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>All right! now we&#8217;re talking. I could see that Chester was using the well known vertexAttribPointer, but just one bind and setting the offset of the call to match the position of the array. He&#8217;s also multiplying the offset by 4 because a Float32Array contains 4 bytes. Clever dog! Then I gave him a treat. He was happy.</p>
<p>Chester then showed me the shader and it was nothing out of the ordinary, just a very simple texture shader. So I asked him &#8220;Ok, but how do I fill the bufferData?&#8221;</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">transform<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> gl <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">gl</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> transformDirty <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isTransformDirty</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">parent</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">parent</span>.<span style="color: #660066;">isTransformDirty</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>transformDirty<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		mat4.<span style="color: #660066;">identity</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		mat4.<span style="color: #660066;">translate</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">position</span>.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">position</span>.<span style="color: #660066;">y</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">position</span>.<span style="color: #660066;">z</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		mat4.<span style="color: #660066;">rotate</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">rotation</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		mat4.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">scale</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">scale</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #006600; font-style: italic;">// concat with parent's transform</span>
		<span style="color: #003366; font-weight: bold;">var</span> ptransform <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">parent</span> <span style="color: #339933;">?</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">parent</span>.<span style="color: #660066;">mvMatrix</span> <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ptransform<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			mat4.<span style="color: #660066;">multiply</span><span style="color: #009900;">&#40;</span>ptransform<span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">mvMatrix</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> bufferData <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">glBufferData</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isFrameDirty</span> <span style="color: #339933;">||</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isColorDirty</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		gl.<span style="color: #660066;">bindBuffer</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">ARRAY_BUFFER</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">glBuffer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isFrameDirty</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// NOTE</span>
		<span style="color: #006600; font-style: italic;">// the tex coords and the frame coords need to match. Otherwise you get a distorted image</span>
		<span style="color: #003366; font-weight: bold;">var</span> hw <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">contentSize</span>.<span style="color: #660066;">w</span> <span style="color: #009966; font-style: italic;">/ 2.0, hh = this.contentSize.h /</span> <span style="color: #CC0000;">2.0</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> _idx <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> z <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">position</span>.<span style="color: #660066;">z</span><span style="color: #339933;">;</span>
&nbsp;
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>hw<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>hh<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>hw<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span> <span style="color: #CC0000;">4</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>  hh<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">6</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>  hw<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span> <span style="color: #CC0000;">7</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>hh<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span> <span style="color: #CC0000;">8</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">9</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>  hw<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">10</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>  hh<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">11</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #003366; font-weight: bold;">var</span> tex <span style="color: #339933;">=</span> ChesterGL.<span style="color: #660066;">getAsset</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;texture&quot;</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">texture</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> texW <span style="color: #339933;">=</span> tex.<span style="color: #660066;">width</span><span style="color: #339933;">,</span>
			texH <span style="color: #339933;">=</span> tex.<span style="color: #660066;">height</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> l <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">frame</span>.<span style="color: #660066;">l</span> <span style="color: #339933;">/</span> texW<span style="color: #339933;">,</span>
			t <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">frame</span>.<span style="color: #660066;">t</span> <span style="color: #339933;">/</span> texH<span style="color: #339933;">,</span>
			w <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">frame</span>.<span style="color: #660066;">w</span> <span style="color: #339933;">/</span> texW<span style="color: #339933;">,</span>
			h <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">frame</span>.<span style="color: #660066;">h</span> <span style="color: #339933;">/</span> texH<span style="color: #339933;">;</span>
		_idx <span style="color: #339933;">=</span> <span style="color: #CC0000;">12</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">baseBufferIndex</span> <span style="color: #339933;">*</span> Block.<span style="color: #660066;">QUAD_SIZE</span><span style="color: #339933;">;</span>
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> l  <span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> t<span style="color: #339933;">;</span>
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> l  <span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> t<span style="color: #339933;">+</span>h<span style="color: #339933;">;</span>
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">4</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> l<span style="color: #339933;">+</span>w<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">5</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> t<span style="color: #339933;">;</span>
		bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">6</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> l<span style="color: #339933;">+</span>w<span style="color: #339933;">;</span> bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span><span style="color: #CC0000;">7</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> t<span style="color: #339933;">+</span>h<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isColorDirty</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		_idx <span style="color: #339933;">=</span> <span style="color: #CC0000;">20</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">baseBufferIndex</span> <span style="color: #339933;">*</span> Block.<span style="color: #660066;">QUAD_SIZE</span><span style="color: #339933;">;</span>
		<span style="color: #003366; font-weight: bold;">var</span> color <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">color</span><span style="color: #339933;">;</span>
		<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">4</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span>i<span style="color: #339933;">*</span><span style="color: #CC0000;">4</span>    <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> color.<span style="color: #660066;">r</span><span style="color: #339933;">;</span>
			bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span>i<span style="color: #339933;">*</span><span style="color: #CC0000;">4</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> color.<span style="color: #660066;">g</span><span style="color: #339933;">;</span>
			bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span>i<span style="color: #339933;">*</span><span style="color: #CC0000;">4</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> color.<span style="color: #660066;">b</span><span style="color: #339933;">;</span>
			bufferData<span style="color: #009900;">&#91;</span>_idx<span style="color: #339933;">+</span>i<span style="color: #339933;">*</span><span style="color: #CC0000;">4</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> color.<span style="color: #660066;">a</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isFrameDirty</span> <span style="color: #339933;">||</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isColorDirty</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		gl.<span style="color: #660066;">bufferData</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">ARRAY_BUFFER</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">glBufferData</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">STATIC_DRAW</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></div></div>

<p>In a step by step:</p>
<ol>
<li>If the transform is dirty (that is, if we moved the block, rotated or scaled it), after that we need to recalculate the transform. Also, if our parent&#8217;s transformation is dirty, we also need to recalculate it.</li>
<ol>
<li>To transform, first load the identity, second translate, then rotate, and finally scale. The order is *very* important! Lastly, if we have a parent transformation, we must concatenate it with the one of the current block.</li>
</ol>
<li>When the transform is ready, it&#8217;s time to fill the buffer data:</li>
<ol>
<li>If the frame is dirty, copy the right coordinates on the vertex first to form the two triangles: bottom left, up left, bottom right for the first one, and the last two + top right for the second triangle. The same thing goes for the texture, but without z.</li>
<li>The color is easy: just copy the current color on the four vertices.</li>
</ol>
<li>As a final step, send the buffer data to the webgl buffer.</li>
</ol>
<p>Seems pretty easy. Chester pointed out that having the Float32Array created just once and copying the data only when it has changed makes a huge performance improvement.</p>
<p>I had only one question left: How do you start the whole thing? I mean, how do you start the rendering chain?</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * main draw function, will call the root block
 * (this is in ChesterGL)
 */</span>
drawScene<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> gl <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">gl</span><span style="color: #339933;">;</span>
&nbsp;
	gl.<span style="color: #660066;">clear</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">COLOR_BUFFER_BIT</span> <span style="color: #339933;">|</span> gl.<span style="color: #660066;">DEPTH_BUFFER_BIT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// global blending options</span>
	gl.<span style="color: #660066;">blendFunc</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">SRC_ALPHA</span><span style="color: #339933;">,</span> gl.<span style="color: #660066;">ONE_MINUS_SRC_ALPHA</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	gl.<span style="color: #660066;">enable</span><span style="color: #009900;">&#40;</span>gl.<span style="color: #660066;">BLEND</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// start mayhem</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">rootBlock</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">rootBlock</span>.<span style="color: #660066;">visit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// this is in a Block</span>
visit<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">visible</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">transform</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> children <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">children</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> len <span style="color: #339933;">=</span> children.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> len<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		children<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">visit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// reset our dirty markers</span>
	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isFrameDirty</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isColorDirty</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isTransformDirty</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The magic begins with the drawScene method, that basically creates the chain reaction, first visiting the root block, and in turn the root block will visit all their children. Chester also said that the visit method can be improved and that is in this point where you want to keep an eye on the rendering order: since all your objects are in the plane z=0, the rendering order is what says what is on top of each other.</p>
<p>At this point Chester unveiled the curtain and told me that he had written this simple 2D engine/demo using WebGL, that even falls back to the canvas API when there&#8217;s no webgl, supporting asynchronous loading of assets, sprite sheets (<a href="http://www.texturepacker.com">Texture Packer</a> format) and tile maps (TMX files). He called it &#8220;ChesterGL&#8221; because it was his library.</p>
<p>He passed me the source code, I added a MIT license to the files and placed them in a <a href="http://github.com/funkaster/ChesterGL">github repo</a> for everyone to hack them: we want more HTML5 games!</p>
<p>Cool! Now for the rest of the stuff, I&#8217;ll leave that for another post, like how Chester approached the canvas API fallback. Spoiler: it was easy, canvas provides a setTransform() method!</p>
<p><a name="fn1"></a>1. For more info on this, head over to the opengl docs http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml</p>
]]></content:encoded>
			<wfw:commentRss>http://www.altdevblogaday.com/2011/09/29/meet-my-dog-chester/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

