<?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>Learning WebGL</title>
	<atom:link href="http://learningwebgl.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://learningwebgl.com/blog</link>
	<description>...lessons &#039;n&#039; links...</description>
	<lastBuildDate>Tue, 09 Feb 2010 02:05:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>WebGL around the net, 8 Feb 2010</title>
		<link>http://learningwebgl.com/blog/?p=1703</link>
		<comments>http://learningwebgl.com/blog/?p=1703#comments</comments>
		<pubDate>Mon, 08 Feb 2010 14:45:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1703</guid>
		<description><![CDATA[One big one today, and two smaller ones:

There have been a lot of fantastic games and demos made for WebGL, but that makes it particularly cool to see someone building something different.  iChemLabs have just released a 3D library for modelling molecules using WebGL (click the &#8220;3D&#8221; button at the top to get the [...]]]></description>
			<content:encoded><![CDATA[<p>One big one today, and two smaller ones:</p>
<ul>
<li>There have been a lot of fantastic games and demos made for WebGL, but that makes it particularly cool to see someone building something different.  iChemLabs have just released a <a href="http://web.chemdoodle.com/">3D library for modelling molecules using WebGL</a> (click the &#8220;3D&#8221; button at the top to get the WebGL version).  They have <a href="http://web.chemdoodle.com/overview3D.php">an overview page</a> showing a bunch of different kinds of views of various molecules, and <a href="http://web.chemdoodle.com/molgrabber3d.php">a page demonstrating their MolGrabber3D canvas</a> where you can pick the drug whose molucule you want to see and can change the kind of representation you want to see it in.  There&#8217;s also <a href="http://web.chemdoodle.com/3dcwc.html">a nice 8-minute overview video</a>, so you can see what they&#8217;re up to even if you don&#8217;t have WebGL setup on your machine, and <a href="http://www.macresearch.org/3d-chemdoodle-web-components">a written overview</a> for the MacResearch community site.  So that&#8217;s chemistry done, any astrophysicists or geologists out there working with WebGL?  :-)</li>
<li>Not strictly WebGL, but it&#8217;s using it under the hood: Andor Salga has built <a href="http://matrix.senecac.on.ca/~asalga/DPS911/release0.5/demo/IDE3D/">a web-based mini-IDE</a> for the <a href="http://processingjs.org/">Processing.js</a> port of the <a href="http://processing.org/">Processing</a> 3D language.</li>
<li>A simple demo: drawing <a href="http://www.c3dl.org/wp-content/effects_all_3_browsers/effect_test2/">cartoon animations</a> using C3DL.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1703</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WebGL around the net, 5 Feb 2010</title>
		<link>http://learningwebgl.com/blog/?p=1698</link>
		<comments>http://learningwebgl.com/blog/?p=1698#comments</comments>
		<pubDate>Fri, 05 Feb 2010 14:29:11 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1698</guid>
		<description><![CDATA[Some interesting new projects today!

In the earliest WebGL demos, Vladimir Vukićević used the Sylvester library for vector and matrix maths; it&#8217;s convenient, well-written, well-documented, and open source.  Pretty much everyone else followed suit.  However, its very general-purpose nature means that it can&#8217;t be as fast as a specialised library focusing on the specific [...]]]></description>
			<content:encoded><![CDATA[<p>Some interesting new projects today!</p>
<ul>
<li>In the earliest WebGL demos, Vladimir Vukićević used the <a href="http://sylvester.jcoglan.com/">Sylvester library</a> for vector and matrix maths; it&#8217;s convenient, well-written, well-documented, and open source.  Pretty much everyone else followed suit.  However, its very general-purpose nature means that it can&#8217;t be as fast as a specialised library focusing on the specific kinds of calculations we need for 3D graphics.  <a href="http://blog.vlad1.com/2010/02/05/mjs-simple-vector-and-matrix-math-for-js/">So, he&#8217;s started a new project called mjs</a>, to provide just the really simple vector and matrix maths we need, and to do it really quickly.  He&#8217;s getting pretty encouraging results on his benchmarks, with JITed calculations being more than ten times as quick, and un-JITed at least twice as fast.  [UPDATE I've tried porting the upcoming lesson 14 to it, and it works fine.  No performance figures yet, though.]</li>
<li>Another important part of building 3D scenes is getting models designed in 3D graphics programs into your JavaScript code.  People are working on tools to import existing 3D graphics formats like <a href="http://techblog.floorplanner.com/2010/01/27/introducing-js3ds-a-javascript-parser-for-3ds/">3DS</a>, but an alternative route is to get the 3D modelling tool to output JSON or some other format you can easily read.  Paul Brunt&#8217;s <a href="http://www.glge.org/">GLGE</a> has some support for doing this from Blender, but <a href="http://www.rozengain.com/blog/2010/02/04/blender-to-webgl-javascript-exporter/">Dennis Ippel has just announced a project that makes exporting from Blender to WebGL code its main focus</a>.  So far it exports to SceneJS, but a generic WebGL version is on its way.  It&#8217;s not ready to download yet, but will be soon.</li>
<li>Another 3D library for WebGL, this one with its own editor!  <a href="http://www.ambiera.com/copperlicht/index.html">CopperLicht</a> is definitely worth a look.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1698</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebGL around the net, 4 Feb 2010</title>
		<link>http://learningwebgl.com/blog/?p=1695</link>
		<comments>http://learningwebgl.com/blog/?p=1695#comments</comments>
		<pubDate>Thu, 04 Feb 2010 19:59:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1695</guid>
		<description><![CDATA[For today, one new link and a couple of older things that I managed to miss first time around:

A new interview with a WebGL library creator at 3D test: this time, it&#8217;s Marco Di Benedetto on SpiderGL.  Well worth a read.
GLGE has forums!  It looks like a good place not just for discussing [...]]]></description>
			<content:encoded><![CDATA[<p>For today, one new link and a couple of older things that I managed to miss first time around:</p>
<ul>
<li>A new interview with a WebGL library creator at 3D test: this time, it&#8217;s <a href="http://www.3d-test.com/interviews/webgl_spiderGL_1.htm">Marco Di Benedetto on SpiderGL</a>.  Well worth a read.</li>
<li><a href="http://www.glge.org/forum/">GLGE has forums</a>!  It looks like a good place not just for discussing the library, but also WebGL in general.</li>
<li>Peter Strohm has added more to his <a href="http://peter-strohm.de/webgl/">WebGL lessons in German</a>; there are now tutorials on adding <a href="http://peter-strohm.de/webgl/webgltutorial5.html">interaction</a>, and <a href="http://peter-strohm.de/webgl/webgltutorial6.html">textures</a>.</li>
<li><a href="http://code.google.com/p/gwt-g3d/">gwt-g3d</a>, one of the three independent projects to create a Google Web Toolkit binding for WebGL, now includes ports of my first 12 lessons as part of its demos.  I&#8217;m flattered :-) &mdash; but additionally, that suggests things have moved on quite a bit since it was announced at the end of December.  Its competitors, <a href="http://sourceforge.net/projects/wgt/">WGT</a> and <a href="http://code.google.com/p/gwtgl/">GwtGL</a> seem to be coming along nicely too.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1695</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebGL around the net, 2 Feb 2010</title>
		<link>http://learningwebgl.com/blog/?p=1690</link>
		<comments>http://learningwebgl.com/blog/?p=1690#comments</comments>
		<pubDate>Tue, 02 Feb 2010 14:03:43 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Links]]></category>
		<category><![CDATA[Upcoming lessons]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1690</guid>
		<description><![CDATA[
It looks like WebGL is going to get a bit of a push at the Game Developers&#8217; Conference in San Francisco in March: there are three sessions highlighting it, one from Barthold Lichtenbelt of NVIDIA on OpenGL &#8212; Featuring WebGL, one from Tom Olson of Khronos on Khronos Mobile &#8212; Featuring WebGL, and one from [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>It looks like WebGL is going to get a bit of a push at the Game Developers&#8217; Conference in San Francisco in March: there are three sessions highlighting it, one from Barthold Lichtenbelt of NVIDIA on <a href="https://www.cmpevents.com/GD10/a.asp?option=C&#038;V=11&#038;SessID=10553">OpenGL &mdash; Featuring WebGL</a>, one from Tom Olson of Khronos on <a href="https://www.cmpevents.com/GD10/a.asp?option=C&#038;V=11&#038;SessID=10555">Khronos Mobile &mdash; Featuring WebGL</a>, and one from Mark Barnes of Khronos on <a href="https://www.cmpevents.com/GD10/a.asp?option=C&#038;V=11&#038;SessID=10554">COLLADA &mdash; Featuring WebGL</a>.  Interestingly, there doesn&#8217;t seem to be anything on WebGL on its own.</li>
<li>A new demo, this time from Marko Ivankovic: <a href="http://code.google.com/p/mivankovic-blog/wiki/WebGLTestpage">fractal mountain generation</a>.</li>
</ul>
<p>Finally, some good news about the next tutorial on this blog: <a href="/lessons/lesson14">the page for lesson 14</a> &mdash; which covers specular highlights &mdash; is pretty much done, as is <a href="http://www.youtube.com/watch?v=OSjVRA2BQJU">the video</a> for people who don&#8217;t have WebGL-enabled browsers.  Now it&#8217;s &#8220;just&#8221; a question of writing about it :-S</p>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1690</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebGL around the net, 1 Feb 2010</title>
		<link>http://learningwebgl.com/blog/?p=1680</link>
		<comments>http://learningwebgl.com/blog/?p=1680#comments</comments>
		<pubDate>Mon, 01 Feb 2010 14:28:04 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1680</guid>
		<description><![CDATA[
A game!  From the C3DL team, 3D Asteroids.
Also from the C3DL guys, an update to keep their particle systems working, which leads neatly on to&#8230;
&#8230;this N-body simulation from Mike Bostock.  Look out, though &#8212; it works in Chrome but it crashed last night&#8217;s Minefield for me.
More good news from Paul Brunt: GLGE can [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>A game!  From the C3DL team, <a href="http://www.c3dl.org/index.php/c3dl-dev/asteroids-in-3d-and-a-bit-of-2d/">3D Asteroids</a>.</li>
<li>Also from the C3DL guys, <a href="http://www.c3dl.org/index.php/c3dl-dev/another-demo-updated/">an update to keep their particle systems working</a>, which leads neatly on to&#8230;</li>
<li>&#8230;<a href="http://graphics.stanford.edu/~mbostock/physics-webgl.html">this N-body simulation</a> from Mike Bostock.  Look out, though &mdash; it works in Chrome but it crashed last night&#8217;s Minefield for me.</li>
<li>More good news from Paul Brunt: <a href="http://www.glge.org/glge-text-rendering-demo/">GLGE can now render text</a>!</li>
<li>A new real-world use for WebGL: from Helmut Dersch, <a href="http://webuser.hs-furtwangen.de/~dersch/PTViewerNG/PTViewerNG.html">DIY Streetview in WebGL</a> (and also <a href="http://www.diy-streetview.org/data/development/20100130/webgl/PTViewerNG.htm">here</a>).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1680</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebGL around the net, 28 Jan 2010</title>
		<link>http://learningwebgl.com/blog/?p=1664</link>
		<comments>http://learningwebgl.com/blog/?p=1664#comments</comments>
		<pubDate>Thu, 28 Jan 2010 14:43:44 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1664</guid>
		<description><![CDATA[A lot of new stuff over the last three days:

Over at 3D test, an interview with Paul Brunt of GLGE fame &#8212; well worth reading.
On thing that&#8217;s going to be important for WebGL going forward is the ability to load up objects that have been designed in 3D modeling tools like Blender, Autodesk 3D Studio [...]]]></description>
			<content:encoded><![CDATA[<p>A lot of new stuff over the last three days:</p>
<ul>
<li>Over at 3D test, <a href="http://www.3d-test.com/interviews/webgl_GLGE_1.htm">an interview with Paul Brunt</a> of <a href="http://www.glge.org/">GLGE</a> fame &mdash; well worth reading.</li>
<li>On thing that&#8217;s going to be important for WebGL going forward is the ability to load up objects that have been designed in 3D modeling tools like Blender, Autodesk 3D Studio or Google SketchUp.  There are two ways of doing this &mdash; by converting the tools&#8217; files into a JavaScript-friendly format like JSON, or by writing code to load the files directly in JavaScript.  Tim Knip has started work on the latter kind: <a href="http://techblog.floorplanner.com/2010/01/27/introducing-js3ds-a-javascript-parser-for-3ds/">js3ds, a 3DS import library for JavaScript</a>.</li>
<li>A very neat (Firefox-only) demo from murphy: <a href="http://murfy.de/read/webgl-drawWindow">using a web page as a texture on a WebGL object</a>.</li>
<li>An impressive (new?) X3DOM demo that I&#8217;ve not seen before: <a href="http://x3dom.org/x3dom/example/x3dom_shadows.xhtml">floating objects with shadows</a>.</li>
<li>Some interesting news about the WebGL spec &mdash; <a href="http://blog.vlad1.com/2009/11/06/canvasarraybuffer-and-canvasarray/">a while back</a>,  Vladimir Vukićević suggested that the <code>WebGLArrayBuffer</code> and <code>WebGL*Array</code> types would be useful outside WebGL.  He&#8217;s now started moving their definition into <a href="http://people.mozilla.com/~vladimir/jsvec/TypedArray-spec.html">a specification of their own</a>.  If this goes ahead, and they are broken out of WebGL, then we&#8217;ll probably have to change our pages once again &mdash; after all, if they&#8217;re not WebGL-specific then they won&#8217;t have &#8220;WebGL&#8221; in their names.  One to keep an eye on&#8230;</li>
<li>Finally, Benjamin DeLillo reports that <a href="http://bjartr.blogspot.com/2010/01/webglu-now-on-github.html">he&#8217;s moved WebGLU to github</a> (an excellent idea) and shows that the latest version of his library makes his 50-line demo <a href="http://bjartr.blogspot.com/2010/01/remember-that-50-line-webgl-demo-now.html">an even more impressive 25 lines</a>!</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1664</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebGL around the net, 25 Jan 2010</title>
		<link>http://learningwebgl.com/blog/?p=1651</link>
		<comments>http://learningwebgl.com/blog/?p=1651#comments</comments>
		<pubDate>Mon, 25 Jan 2010 19:46:06 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1651</guid>
		<description><![CDATA[Three framework updates today!

Benjamin DeLillo has been quiet for a while, but he&#8217;s been working hard on WebGLU, adding (among other things) keyframe animation, image and video-based textures, shader loading from external files, and the beginning stages of import capabilities for .obj files (a common format for 3D models).  His blog post gives more [...]]]></description>
			<content:encoded><![CDATA[<p>Three framework updates today!</p>
<ul>
<li>Benjamin DeLillo has been quiet for a while, but he&#8217;s been working hard on WebGLU, adding (among other things) keyframe animation, image and video-based textures, shader loading from external files, and the beginning stages of import capabilities for .obj files (a common format for 3D models).  <a href="http://bjartr.blogspot.com/2010/01/long-delayed-webglu-update-some-360.html">His blog post gives more information</a>, including a very cool example of a 360&deg; video.</li>
<li>Paul Brunt&#8217;s GLGE improves in leaps and bounds; <a href="http://www.glge.org/fog-now-supported/">he&#8217;s now added fog effects</a>.</li>
<li><a href="http://lindsaystanleykay.blogspot.com/2010/01/scenejs-environment-nodes.html">Lindsay Kay&#8217;s SceneJS</a> has now gained the ability to override certain rendering parameters in specific subtrees of the scene graph.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1651</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebGL Lesson 13 – per-fragment lighting and multiple programs</title>
		<link>http://learningwebgl.com/blog/?p=1523</link>
		<comments>http://learningwebgl.com/blog/?p=1523#comments</comments>
		<pubDate>Sun, 24 Jan 2010 01:13:51 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Lessons]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1523</guid>
		<description><![CDATA[&#60;&#60; Lesson 12
Welcome to my number thirteen in my series of WebGL tutorials!  In it, we&#8217;ll cover per-fragment lighting, which is harder work for the graphics card than the per-vertex lighting we&#8217;ve been doing so far, but gives much more realistic results.  We&#8217;ll also look at how you can switch the shaders used [...]]]></description>
			<content:encoded><![CDATA[<p><span style="float: left; padding: 0px 20px 0px 0px;"><a href="http://learningwebgl.com/blog/?p=1359">&lt;&lt; Lesson 12</a></span><br/><br />
Welcome to my number thirteen in my series of WebGL tutorials!  In it, we&#8217;ll cover per-fragment lighting, which is harder work for the graphics card than the per-vertex lighting we&#8217;ve been doing so far, but gives much more realistic results.  We&#8217;ll also look at how you can switch the shaders used by your code by changing which WebGL program object is in use.</p>
<p>Here&#8217;s what the lesson looks like when run on a browser that supports WebGL:</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/IKFLr-7WnEA&#038;hl=en_US&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/IKFLr-7WnEA&#038;hl=en_US&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p><a href="/lessons/lesson13/index.html">Click here and you&#8217;ll see the live WebGL version</a>, if you&#8217;ve got a browser that supports it; <a href="http://learningwebgl.com/blog/?p=11">here&#8217;s how to get one</a> if you don&#8217;t.  You&#8217;ll see a sphere and cube orbiting; both will probably be white for a few moments while the textures load, but once that&#8217;s done you should see that the sphere is the moon and the cube a (not-to-scale) wooden crate; the scene is similar to the one we had for <a href="http://learningwebgl.com/blog/?p=1359">lesson 12</a>, but we&#8217;re closer to the orbiting objects so that you can see more clearly what they look like.  As before, both are illuminated by a point light source that is in between them, and if you want to change the light&#8217;s position, colour, etc., there are fields beneath the WebGL canvas, along with checkboxes to switch lighting on and off, to switch between per-fragment and per-pixel lighting, and to use or not use the textures.</p>
<p>Try toggling the per-fragment lighting on and off.  You should be able to see the difference on the crate pretty easily; the centre is obviously brighter with it switched on.  The difference with the moon is more subtle; the edges where the lighting fades out are smoother and less ragged with per-fragment lighting than they are with per-vertex.  You will probably be able to see this more easily if you switch off the textures.</p>
<p>More on how it all works below&#8230;</p>
<p><span id="more-1523"></span></p>
<p>The usual <a href="http://learningwebgl.com/blog/?page_id=29">warning</a>: these lessons are targeted at people with a reasonable amount of programming knowledge, but no real experience in 3D graphics; the aim is to get you up and running, with a good understanding of what&#8217;s going on in the code, so that you can start producing your own 3D Web pages as quickly as possible.  If you haven&#8217;t read the previous tutorials already, you should probably do so before reading this one &mdash; here I will only explain the new stuff.  The lesson is based on <a href="http://learningwebgl.com/blog/?p=1359">lesson 12</a>, so you should make sure that you understand that one (and please do post a comment on  that post if anything&#8217;s unclear about it!)</p>
<p>There may be bugs and misconceptions in this tutorial.  If you spot anything wrong, let me know in the comments and I&#8217;ll correct it ASAP.</p>
<p>There are two ways you can get the code for this example; just &#8220;View Source&#8221; while you&#8217;re looking at the live version, or if you use GitHub, you can clone it (and the other lessons) from <a href="http://github.com/gpjt/webgl-lessons">the repository there</a>.  </p>
<p>Let&#8217;s kick off by describing exactly why it&#8217;s worth taking up more graphics processor power by coding per-fragment lighting.  <img src="/lessons/lesson07/point.png" style="float:left" />You may remember the diagram to the left from <a href="http://learningwebgl.com/blog/?p=684">lesson 7</a>.  As you know, the brightness of a surface is determined by the angle between its normal and the incoming rays of light from the light source.  Now, so far, our lighting has been calculated in the vertex shader by combining the normals specified for each vertex with the lighting direction from it.  This has provided a light-weighting factor, which we&#8217;ve passed from the vertex shader to the fragment shader in a varying variable, and there used to vary the brightness of the colour of the fragment appropriately.  This light-weighting factor, like all varying variables, will have been linearly interpolated by the WebGL system to provide values for it for the fragments that lie between the vertices; so, in the diagram, B will be quite bright because the light is parallel with the normal there, A will be dimmer because the light is reaching it at more of an angle, and points in between will shade smoothly between bright and dim.  This will look just right.</p>
<p><img src="/lessons/lesson13/point-lighting-in-middle.png" style="float: right" />But now imagine that the light is higher up, as in the diagram to the right.  A and C will be dim, as the light reaches them at an angle.  We are calculating lighting at the vertices only, and so point B will have the average brightness of A and C, so it will also be dim.  This is, of course, wrong &mdash; the light is parallel the surface&#8217;s normal at B, so it should actually be brighter than either of them.  So, in order to calculate the lighting at fragments between vertices, we obviously need to calculate it separately for each fragment.</p>
<p>Calculating the lighting for each fragment means that for each one we need its location (to work out the direction of the light) and its normal; we can get these by passing them from the vertex shader to the fragment shader.  They will both be linearly interpolated, so the positions will lie along a straight line between the vertices, and the normals will vary smoothly.  That straight line is just what we want, and because the normals at A and C are the same, the normals will be the same for all of the fragments, which is perfect too.</p>
<p>So, that all explains why the cube in our web page looks better and more realistic with per-fragment lighting.  But there&#8217;s another benefit, and this is that it gives a great effect to shapes made up of flat planes that are meant to approximate curved surfaces, like our sphere.  If the normals at two vertices are different, then the smoothly-changing normals at the intervening fragments will give the effect of a curving surface.  When considered in this way, per-fragment lighting is a form of what is called Phong shading, and <a href="http://en.wikipedia.org/wiki/File:Phong-shading-sample.jpg">this picture on Wikipedia</a> shows the effect better than I could explain in several thousand words.  You can see this in the demo; if you use per-vertex lighting, you can see that the edge of the shadow (where the point light stops having an effect and the ambient lighting takes over) looks a bit &#8220;ragged&#8221;.  This is because the sphere is made up of many triangles, and you can see their edges.  When you switch on per-fragment lighting, you can see that the edge of this transition is smoother, giving a better effect of roundness. </p>
<p>Right, that&#8217;s the theory out of the way &mdash; let&#8217;s take a look at the code!  The shaders are at the top of the file, so lets take a look at them first.  Because this example uses either per-vertex or per-fragment lighting, depending on the setting of the &#8220;per-vertex&#8221; checkbox, it has vertex and fragment shaders for each kind (it would be possible to write shaders that could do both, but they would be harder to read).  The way that we switch between them is something we&#8217;ll come to later, but for now you should just note that we distinguish between them by using different <code>id</code> tags when defining them as scripts in the web page.  The first to appear are the shaders for per-vertex lighting, and they&#8217;re exactly the same as the ones we&#8217;ve been using since lesson 7, so I will just show their <code>script</code> tags so that you can match them up with what you will see if you&#8217;re following through in the file:</p>
<pre>
&lt;script id="per-vertex-lighting-fs" type="x-shader/x-fragment"&gt;
</pre>
<pre>
&lt;script id="per-vertex-lighting-vs" type="x-shader/x-vertex"&gt;
</pre>
<p>Next comes the fragment shader for per-fragment lighting.</p>
<pre>
&lt;script id="per-fragment-lighting-fs" type="x-shader/x-fragment"&gt;
  varying vec2 vTextureCoord;
  varying vec4 vTransformedNormal;
  varying vec4 vPosition;

  uniform bool uUseLighting;
  uniform bool uUseTextures;

  uniform vec3 uAmbientColor;

  uniform vec3 uPointLightingLocation;
  uniform vec3 uPointLightingColor;

  uniform sampler2D uSampler;

  void main(void) {
    vec3 lightWeighting;
    if (!uUseLighting) {
      lightWeighting = vec3(1.0, 1.0, 1.0);
    } else {
      vec3 lightDirection = normalize(uPointLightingLocation - vPosition.xyz);

      float directionalLightWeighting = max(dot(normalize(vTransformedNormal.xyz), lightDirection), 0.0);
      lightWeighting = uAmbientColor + uPointLightingColor * directionalLightWeighting;
    }

    vec4 fragmentColor;
    if (uUseTextures) {
      fragmentColor = texture2D(uSampler, vec2(vTextureCoord.s, 1.0 - vTextureCoord.t));
    } else {
      fragmentColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
    gl_FragColor = vec4(fragmentColor.rgb * lightWeighting, fragmentColor.a);
  }
&lt;/script&gt;
</pre>
<p>You can see that this is very similar to the vertex shaders that we&#8217;ve been using so far; it does exactly the same calculations to work out the direction of the light and to then combine that with the normal to calculated a light weighting.  The difference is that the inputs to this calculation now come from varying variables rather than per-vertex attributes, and the resulting weighting is immediately combined with the texture colour from the sample rather than passed out for processing later.  It&#8217;s also worth noting that we have to normalise the varying variable that contains the interpolated normal; normalising, you will remember, adjusts a vector so that its length is one unit.  This is because interpolating between two length-one vectors does not necessarily give you a length-one vector, just a vector that points in the right direction.  Normalising them fixes that.  (Thanks to Glut for pointing that out <a href="http://learningwebgl.com/blog/?p=1523&#038;cpage=1#comment-1262">in the comments</a>.)</p>
<p>Because all of the heavy lifting is being done by the fragment shader, the vertex shader for per-fragment lighting is really simple:</p>
<pre>
&lt;script id="per-fragment-lighting-vs" type="x-shader/x-vertex"&gt;
  attribute vec3 aVertexPosition;
  attribute vec3 aVertexNormal;
  attribute vec2 aTextureCoord;

  uniform mat4 uMVMatrix;
  uniform mat4 uPMatrix;
  uniform mat4 uNMatrix;

  varying vec2 vTextureCoord;
  varying vec4 vTransformedNormal;
  varying vec4 vPosition;

  void main(void) {
    vPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
    gl_Position = uPMatrix * vPosition;
    vTextureCoord = aTextureCoord;
    vTransformedNormal = uNMatrix * vec4(aVertexNormal, 1.0);
  }
&lt;/script&gt;
</pre>
<p>We still need to work out the vertex&#8217;s location after the application of the model-view matrix and multiply the normal by the normal matrix, but now we just stash them away in varying variables for later use in the fragment shader. </p>
<p>That&#8217;s it for the shaders!  The rest of the code will be pretty familiar from the previous lessons, with one exception.  So far, we&#8217;ve only used one vertex shader and one fragment shader per WebGL page.  This one uses two pairs, one for per-vertex lighting and one for per-fragment lighting.  Now, you may remember from lesson 1 that the WebGL program object that we use to pass our shader code up to the graphics card can have only one fragment shader and one vertex shader.  What this means is that we need to have two programs, and switch which one we use based on the setting of the &#8220;per-fragment&#8221; checkbox.</p>
<p>The way we do this is simple; our <code>initShaders</code> function is changed to look like this:</p>
<pre>
  var currentProgram;
  var perVertexProgram;
  var perFragmentProgram;
  function initShaders() {
    perVertexProgram = createProgram("per-vertex-lighting-fs", "per-vertex-lighting-vs");
    perFragmentProgram = createProgram("per-fragment-lighting-fs", "per-fragment-lighting-vs");
  }
</pre>
<p>So, we have two programs in separate global variables, one for per-vertex lighting and one for per-fragment, and a separate <code>currentProgram</code> variable to store the one that&#8217;s currently in use.  The <code>createProgram</code> we use to create them is simply a parameterised version of the code we used to have in <code>initShaders</code>, so I won&#8217;t duplicate it here.</p>
<p>We then switch in the appropriate program right at the start of the <code>drawScene</code> function: </p>
<pre>
  function drawScene() {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

    perspective(45, 1.0, 0.1, 100.0);

    var perFragmentLighting = document.getElementById("per-fragment").checked;
    if (perFragmentLighting) {
      currentProgram = perFragmentProgram;
    } else {
      currentProgram = perVertexProgram;
    }
    gl.useProgram(currentProgram);
</pre>
<p>We have to do this before anything else because when we do drawing code (for example setting uniforms or attaching buffers of per-vertex attributes to attributes) we need the current program to be appropriately set up, as otherwise we might use the wrong program:</p>
<pre>
    var lighting = document.getElementById("lighting").checked;
    gl.uniform1i(currentProgram.useLightingUniform, lighting);
</pre>
<p>You can see that this means that for each call to <code>drawScene</code> we use one and only one program; it differs only between calls.  If you&#8217;re wondering whether or not you could use different shader programs at different times within <code>drawScene</code>, so that different parts of the scene were drawn with different ones &mdash; perhaps some of your scene might use per-vertex lighting and some per-pixel &mdash; the answer is yes!  It wasn&#8217;t needed for this example, but is perfectly valid and can be useful.</p>
<p>Anyway &mdash; with that explained, that&#8217;s it for this lesson!  You now know how to use multiple programs to switch shaders, and how to code per-pixel lighting.  Next time we&#8217;ll look at the last bit of lighting that was mentioned in lesson 7: specular highlights.</p>
<p><span style="float: left; padding: 0px 20px 0px 0px;"><a href="http://learningwebgl.com/blog/?p=1359">&lt;&lt; Lesson 12</a></span><br/></p>
<p><em>Acknowledgments: As before, the texture-map for the moon <a href="http://maps.jpl.nasa.gov/">comes from NASA&#8217;s JPL website</a>, and the code to generate a sphere is based on <a href="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/webkit/Earth.html">this demo</a>, which was originally by the WebKit team.  Many thanks to both!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1523</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Retrospective changes: storing attributes and uniforms on the program</title>
		<link>http://learningwebgl.com/blog/?p=1606</link>
		<comments>http://learningwebgl.com/blog/?p=1606#comments</comments>
		<pubDate>Fri, 22 Jan 2010 14:39:00 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Retrospective changes]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1606</guid>
		<description><![CDATA[For lesson 13, I needed to be able to easily switch the WebGL program object (which manages the shaders) so that you can see the effects of per-vertex or per-pixel lighting just by toggling a checkbox.  Obviously, changing which program you&#8217;re using means that the code that draws the scene needs to use the [...]]]></description>
			<content:encoded><![CDATA[<p>For <a href="/lessons/lesson13/">lesson 13</a>, I needed to be able to easily switch the WebGL program object (which manages the shaders) so that you can see the effects of per-vertex or per-pixel lighting just by toggling a checkbox.  Obviously, changing which program you&#8217;re using means that the code that draws the scene needs to use the current program&#8217;s attribute and uniform locations.  One easy way to do this was to keep the attribute and the uniform locations as fields of the program object; this not only made it easier to switch everything across in one go by just changing a <code>currentProgram</code> object, but it also gave me a chance to change things so that we get the uniform locations in one go while initialising, instead of getting them every repaint; as <a href="http://ewgl.wordpress.com/2010/01/11/uniforms/">Easy WebGL pointed out the other day</a>, getting uniforms can be costly in terms of processor power, so it&#8217;s worth avoiding doing it unnecessarily.</p>
<p>Anyhow, this was such a nice change that I decided to push it back into the older lessons.  Here&#8217;s an example of what the new code looks like &mdash; first, the new <code>initShaders</code> from <a href="http://learningwebgl.com/blog/?p=28">lesson 1</a>:</p>
<pre>
  var shaderProgram;
  function initShaders() {
    var fragmentShader = getShader(gl, "shader-fs");
    var vertexShader = getShader(gl, "shader-vs");

    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
      alert("Could not initialise shaders");
    }

    gl.useProgram(shaderProgram);

    <span style="color:red">shaderProgram.</span>vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    gl.enableVertexAttribArray(<span style="color:red">shaderProgram</span>.vertexPositionAttribute);

    <span style="color:red">shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");</span>
  }
</pre>
<p>So, you can see that it stores the attributes and uniforms as fields in the program object.  This means that <code>setMatrixUniforms</code> can be simplified, as it no longer needs to look up uniforms:</p>
<pre>
  function setMatrixUniforms() {
    gl.uniformMatrix4fv(<span style="color:red">shaderProgram.pMatrixUniform</span>, false, new WebGLFloatArray(pMatrix.flatten()));
    gl.uniformMatrix4fv(<span style="color:red">shaderProgram.mvMatrixUniform</span>, false, new WebGLFloatArray(mvMatrix.flatten()));
  }
</pre>
<p>&#8230;and also, the code in <code>drawScene</code> needs a small adjustment to pick up the attribute locations from the program object rather than the no-longer-existent global variables:</p>
<pre>
    gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
    gl.vertexAttribPointer(<span style="color:red">shaderProgram.</span>vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
</pre>
<p>Right, hopefully I can get round to writing up lesson 13 properly now, it&#8217;s been too long coming!</p>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1606</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>WebGL around the net, 21 Jan 2010</title>
		<link>http://learningwebgl.com/blog/?p=1565</link>
		<comments>http://learningwebgl.com/blog/?p=1565#comments</comments>
		<pubDate>Thu, 21 Jan 2010 20:08:49 +0000</pubDate>
		<dc:creator>giles</dc:creator>
				<category><![CDATA[Links]]></category>

		<guid isPermaLink="false">http://learningwebgl.com/blog/?p=1565</guid>
		<description><![CDATA[Lots of YouTube stuff today:

Another very cool graphics-card overloading page from the demo scene guys, who specialise in creating very cool scenes using jaw-droppingly tiny amounts of code, all in the fragment shaders.  This one&#8217;s called Four Dollar Plastic Laminator, it&#8217;s apparently a 1k demo (meaning it&#8217;s all coded in just one kilobyte of [...]]]></description>
			<content:encoded><![CDATA[<p>Lots of YouTube stuff today:</p>
<ul>
<li>Another very cool graphics-card overloading page from the demo scene guys, who specialise in creating very cool scenes using jaw-droppingly tiny amounts of code, all in the fragment shaders.  This one&#8217;s called <a href="http://wakaba.c3.cx/w/four_dollar_plastic_laminator">Four Dollar Plastic Laminator</a>, it&#8217;s apparently a 1k demo (meaning it&#8217;s all coded in just one kilobyte of fragment shader!), and if your GPU&#8217;s not powerful enough to view it, <a href="http://www.youtube.com/watch?v=COluewhIUG4">you can see it on YouTube here</a>.</li>
<li><a href="http://www.youtube.com/watch?v=16P6_e7VUmw">A very cool demo</a> in a different way; this one is unfortunately only on YouTube, but it shows a model taken from World of Warcraft, exported to X3D, and then displayed in a Web browser using <a href="http://www.x3dom.org/">X3DOM</a>, which is built on WebGL.  Very impressive!</li>
<li>Finally, <a href="http://www.youtube.com/watch?v=E07lHZv3Wqk">two</a> <a href="http://www.youtube.com/watch?v=xSGJkSCimro">examples</a> of terrain mapping in WebGL, which both look pretty promising.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://learningwebgl.com/blog/?feed=rss2&amp;p=1565</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
