<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>NSH + Graphics &#38; Photography</title>
	<atom:link href="http://nshgraph.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://nshgraph.wordpress.com</link>
	<description>Graphics, photography and whatever</description>
	<lastBuildDate>Thu, 14 Oct 2010 22:13:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='nshgraph.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>NSH + Graphics &#38; Photography</title>
		<link>http://nshgraph.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://nshgraph.wordpress.com/osd.xml" title="NSH + Graphics &#38; Photography" />
	<atom:link rel='hub' href='http://nshgraph.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Graphics &#8211; MGP &#8211; Melting Glass</title>
		<link>http://nshgraph.wordpress.com/2010/10/15/graphics-mgp-melting-glass/</link>
		<comments>http://nshgraph.wordpress.com/2010/10/15/graphics-mgp-melting-glass/#comments</comments>
		<pubDate>Thu, 14 Oct 2010 22:13:22 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=1049</guid>
		<description><![CDATA[So finally we come to the actual melting of the glass by building on the foundations of the previous post. To recap, in the previous post we setup a process whereby we could render our geometry to an FBO, run a shader over this FBO (where each fragment corresponds to exactly one vertex of the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1049&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>So finally we come to the actual melting of the glass by building on the foundations of the previous post. To recap, in the previous post we setup a process whereby we could render our geometry to an FBO, run a shader over this FBO (where each fragment corresponds to exactly one vertex of the geometry) and then use the resulting information as the new position/normal/colour for each vertex in the geometry.</p>
<p><strong>Why not just do this in a vertex shader? </strong><br />
An interesting thing about this type of feedback is that changing the vertex position in one time step can be carried over to the next, something that can&#8217;t be achieved by just modifying a vertex position in a shader.</p>
<p><strong>Getting Started</strong><br />
Before we can add the melting it is important to state what the most basic shader set is for this type of operation. I was naughty and didn&#8217;t include this in the previous post but should have. Thus the vertex shader that runs when rendering to the FBO is very simple (does nothing):<br />
<pre class="brush: cpp;">
void main()
{
	gl_Position = gl_ProjectionMatrix*gl_Vertex;
	gl_TexCoord[0] = gl_MultiTexCoord0;
}
</pre></p>
<p>The fragment shader has a little more base code because it has to make sure the position, normal and colours are all passed on to the relevant render targets:<br />
<pre class="brush: cpp;">
// references to the incoming textures (really the vertices etc)
uniform sampler2DRect colourTex; 
uniform sampler2DRect vertexTex;
uniform sampler2DRect normalTex;
void main()
{
    //retrieve the specific vertex that this fragment refers to
    vec3 vertex = texture2DRect(vertexTex,gl_TexCoord[0].st).xyz;
    vec4 color  = texture2DRect(colourTex,gl_TexCoord[0].st);
    vec3 normal = texture2DRect(normalTex,gl_TexCoord[0].st).xyz ; 
    // write the information back out to the various render targets
    gl_FragData[0] = vec4(vertex,1.0); 
    gl_FragData[1] = color; 
    gl_FragData[2] = vec4(normal,1.0);
}
</pre></p>
<p>With this in place we should finally have the geometry appearing again!</p>
<h1>Melting</h1>
<p>How the user will be interacting with the melting is through the use of right-clicking and dragging over the surface of the glass to heat areas up. These areas will then &#8216;flow&#8217; in the direction of gravity as they also cool back down to a static state</p>
<p><strong>Translating mouse clicks</strong><br />
This means the first thing we need is to know where the user is clicking, not just in the viewport but also on our geometry. Luckily glu provides us with an easy to use function for just this purpose. By using <em>gluunproject</em> we can turn a provided x and y coordinate into a position within the volume the user can see. The only other things we need to provide are the current modelview, projection, and viewport matrices along with how &#8216;deep&#8217; into the scene we are wanting to reference.</p>
<p>The usage of <em>gluunproject</em> is thus:<br />
<pre class="brush: cpp;">
GLint viewport[4];
GLdouble projection[16];
GLdouble modelview[16];                
GLdouble out_point[3]; 

glGetDoublev(GL_MODELVIEW_MATRIX, (GLdouble*)&amp;modelview);
glGetDoublev(GL_PROJECTION_MATRIX, (GLdouble*)&amp;projection);   
glGetIntegerv( GL_VIEWPORT, viewport );

gluUnProject( x, y, z, modelview, projection, viewport, &amp;out_point[0], &amp;out_point[1], &amp;out_point[2]);
</pre><br />
Which should populate <em>out_point</em>with the position in 3D space. The only missing thing is how to get the &#8216;z&#8217; component of where we want to hit, for which there are two strategies:</p>
<ul>
<li>The first is to use a number between 0 and 1 that matches approximately the plane we want to affect. For me the number 0.8 worked well</li>
<li>The second is to read the exact depth of the first object at the selected point</li>
</ul>
<p>If we want to take the second approach we have to make sure we have not yet cleared the depth buffer from the previous rendering and then read the depth component for the pixel in question:<br />
<pre class="brush: cpp;">
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &amp;z);
</pre></p>
<p><strong>&#8216;Heating up&#8217; the glass</strong><br />
Now that we have the point at which we know the user is clicking we can determine how close each vertex is to this point and apply some function to increase heat in this area. We can then store the amount of &#8216;heat&#8217; that each vertex has in the colour channels so that next iteration we can recall the value and thus retain this information. Handily we humans use colour as an indication of heat so storing this information in the colour channel makes a lot of sense.</p>
<p>To determine the amount of heat we will apply to each vertex we first determine the distance between the vertex and the &#8216;affect point&#8217; that the user is clicking.<br />
<pre class="brush: cpp;">
uniform vec3 affect;
...
 float diff = 0.1 / dot( vertex - affect, vertex - affect ); // or 0.001/d^2
</pre><br />
We can then use this to determine how much heat we want to apply:<br />
<pre class="brush: cpp;">
  float addInt = smoothstep( 0.0, MAX_INTENSITY, diff); // max/d^2
</pre><br />
And determine how much heat will be lost through cooling:<br />
<pre class="brush: cpp;">
  float remInt = (color.r + color.g + color.b) * COOL_PERCENT;
</pre><br />
And the final intensity for this vertex (in the range [0,3]<br />
<pre class="brush: cpp;">
  float intensity = (color.r + color.g + color.b) + (addInt - remInt) * deltaTime;
</pre><br />
To store this intensity for next time we can modify how the colour is stored so that instead of just the previous colour it is now:<br />
<pre class="brush: cpp;">
  gl_FragData[1] = clamp(vec4(intensity,intensity-1.0,intensity-2.0,1.0),0.0,1.0); // colour
</pre><br />
which will mean that red, green, and blue will be &#8216;filled&#8217; in sequence up to a white hot heat.</p>
<p>For the purposes of completeness: I used the values of 1.0 and 0.5 for <em>MAX_INTENSITY</em> and <em>COOL_PERCENT</em> respectively.</p>
<p><strong>I&#8217;m melting&#8230;</strong><br />
After calculating the intensity in the previous step we now have enough information to advect the vertex to a new position. Step one in this process is knowing which way is &#8216;down&#8217;. This can be extracted from the modelview matrix as if we treat the &#8216;y axis&#8217; as being vertical then retrieving the &#8216;y axis&#8217; for the current camera view will be the equivalent of gravity. Thus gravity becomes:<br />
<pre class="brush: cpp;">
float gravity[3];
gravity[0] = modelview[1];
gravity[1] = modelview[5];
gravity[2] = modelview[9]
</pre></p>
<p>And the amount to move the vertex by vertically can be calculated in the shader by:<br />
<pre class="brush: cpp;">
 vec3 transform = -(intensity*gravity*deltaTime*MAX_MELT);

 gl_FragData[0] = vec4(vertex + transform,1.0); // vertex
</pre><br />
where <em>MAX_MELT</em> is just a scale factor of 0.02</p>
<p>With this the glass will start melting when right-clicked!!</p>
<p>The only thing that will be a little strange is that while advecting the vertices we are leaving the normals as they are, which isn&#8217;t exactly correct. However because we don&#8217;t have direct access to the surrounding vertices we can&#8217;t easily reconstruct the exact normal and in my experiments keeping it the same works as an approximation unless large changes in geometry are made&#8230;</p>
<p>So the results:<br />
<div id="attachment_1055" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/10/melting-glass.jpg"><img src="http://nshgraph.files.wordpress.com/2010/10/melting-glass.jpg?w=510&#038;h=375" alt="" title="melting-glass" width="510" height="375" class="size-full wp-image-1055" /></a><p class="wp-caption-text">Melting Glass</p></div></p>
<p>And a short video:<br />
<div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/15834489' width='400' height='300' frameborder='0'></iframe></div></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/1049/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/1049/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/1049/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/1049/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/1049/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/1049/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/1049/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/1049/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/1049/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/1049/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/1049/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/1049/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/1049/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/1049/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1049&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/10/15/graphics-mgp-melting-glass/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/10/melting-glass.jpg" medium="image">
			<media:title type="html">melting-glass</media:title>
		</media:content>
	</item>
		<item>
		<title>Graphics – MGP – Rendering Geometry to an FBO</title>
		<link>http://nshgraph.wordpress.com/2010/10/07/graphics-mgp-rendering-geometry-to-an-fbo/</link>
		<comments>http://nshgraph.wordpress.com/2010/10/07/graphics-mgp-rendering-geometry-to-an-fbo/#comments</comments>
		<pubDate>Thu, 07 Oct 2010 10:13:04 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=1038</guid>
		<description><![CDATA[The title of this post might seem a little strange both in content and intention. Hopefully by the end of it I will have explained what I mean by &#8220;rendering geometry to an FBO&#8221; and why we would want to do it. First the why Now that we have a reasonable approximation of a glass [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1038&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The title of this post might seem a little strange both in content and intention. Hopefully by the end of it I will have explained what I mean by &#8220;rendering geometry to an FBO&#8221; and why we would want to do it.</p>
<p><b>First the why</b><br />
Now that we have a reasonable approximation of a glass the next and final step is to make it melt. This involves simulating the process of heating up glass, letting gravity cause the heated (and now less viscous) glass to flow, and then letting the glass cool over time into its new shape.</p>
<p>This sounds pretty complicated (it isn&#8217;t) but most importantly it requires us to be able to take the position of each vertex in the glass, do something with it, and then store the new position for the next time we want to draw it. The naïve approach would be to keep all the info in main memory, do our thing, and then update the graphics card with the new positions every time. This has a few issues though:</p>
<ol>
<li>Even a fast computer is slow</li>
<li>We end up transferring lots to the graphics card</li>
<li>It isn&#8217;t anywhere near as cool as getting the GPU to do it!</li>
</ol>
<p><b>And now the how&#8230;</b><br />
Back in the <a href="http://nshgraph.wordpress.com/2010/05/23/graphics-mgp-tessellation/">post on tessellation</a> we described how we were uploading the data onto the graphics card so that each time we wanted to draw this we didn&#8217;t have to upload it again.</p>
<p>So the idea behind rendering the geometry to an FBO and reading it back out is that we can use the existing vertex/normal/colours buffers as &#8216;textures&#8217;, run calculations on the graphics card within a shader, and then read the information back out into the same buffers to continue the rendering process as we have previously.</p>
<p>Based on this we can break down what we have to do into 4 steps: create an FBO to render into, interpret the existing buffers as textures, run a shader over them, and copy the result back into the original buffers.</p>
<p><b>1. Create an FBO</b><br />
I&#8217;m not going to post the exact code I use for setting everything up exactly for the FBOs as there is a bit more going on (and this post is going to be long enough) but here are the basics. This code will set up a variable number of colour attachments to take advantage of the multiple render targets that FBOs can have.</p>
<p><pre class="brush: objc;">
// Create a reference to an fbo
glGenFramebuffersEXT(1, (GLuint*)&amp;FBOId);
// bind to the new fbo
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOId);
	
// Create the texture representing the results that will be written to
for( int i=0;i&lt;num_draw_buffers;i++)
{
	glGenTextures(1, (GLuint*)&amp;TexId[i]);
	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, TexId[i]);
	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB_FLOAT32_APPLE,  width, height, 0, GL_RGB, GL_FLOAT, 0x0);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_RECTANGLE_ARB, TexId[i], 0);
}
 
// Check the final status of this frame buffer
int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if( status != GL_FRAMEBUFFER_COMPLETE_EXT ){
	valid = false;
}
else{
	valid = true;
}
// Unbind FBO so we can continue as normal
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
</pre></p>
<p>The other setup we need to do is to allocate texture references that we can eventually associate with the buffers. </p>
<p>But first: a non-obvious issue. Buffers for holding Vertex, Normal and Colour information are one dimensional and reasonably free of space limitations. Textures are different and different graphics cards/drivers have different limitations. Thus we need to break up our 1D buffer into a 2D buffer where the width is no larger than the max texture width supported by the card.</p>
<p><pre class="brush: objc;">
// calculate the width and height of the fbo we need
if( numberVerts &lt; max_width )
{
	renderWidth = numberVerts;
	renderHeight = 1;
	renderOverrun = 0;
}
else {
	renderWidth = max_width;
	renderHeight = numberVerts / max_width + 1;
	renderOverrun = max_width * renderHeight - numberVerts;
}
</pre></p>
<p>And now that we have our dimensions we can allocate the required texture references. As you may notice the <i>data</i> portion of the call is <i>NULL</i> which means we aren&#8217;t actually providing data, just allowing for a reference to a texture of the given size.</p>
<p>We need to use <i>GL_RGB_FLOAT32_APPLE</i> as our internal storage method as we need reasonably high precision that would be otherwise lost. We will also be using <i>GL_TEXTURE_RECTANGLE_ARB</i> instead of the standard 2D because we need the precision when accessing the elements of the texture. </p>
<p><pre class="brush: objc;">
glGenTextures(1, (GLuint*)&amp;vertexTex);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, vertexTex);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB_FLOAT32_APPLE,  renderWidth, renderHeight, 0, GL_RGB, GL_FLOAT, 0x0);
</pre></p>
<p><b>2. Interpret the existing Buffers as Textures</b><br />
This step is one of the simplest and involves only 3 steps for each buffer. One just has to bind the texture, bind the buffer and &#8216;update&#8217; the texture from the buffer. The trick is not to provide data when updating the texture which tells the card to use the bound buffer as the data source instead.</p>
<p><pre class="brush: objc;">
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, vertexTex);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, vertexBufferRef);
glTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB,	0, 0, 0, renderWidth, renderHeight, GL_RGB, GL_FLOAT, NULL );
</pre></p>
<p><b>3. Render the data into the FBO</b><br />
Rendering the data into the FBO involves setting up one quad that covers the entire frame so that each fragment corresponds to one vertex. Thus each time the fragment shader runs it will advect one vertex (and update colours and normals). For this to happen we have to change the frame buffer we are rendering into, bind the textures we updated in Step 2, enable the shader, render our quad, and then disable everything again.</p>
<p><pre class="brush: objc;">
// Step 1: Change the frame buffer and set up the view port to be rendering 
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOId);
	
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer	// OUCH!! Big performance hit
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0,width,0.0,height);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
	
GLenum dbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};
glDrawBuffers(numTexId, dbuffers);

// Step 2: bind the textures
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glActiveTextureARB( GL_TEXTURE0_ARB );
glBindTexture(GL_TEXTURE_RECTANGLE_ARB,vertexTex);

// Step 3: enable the shader
shader-&gt;enableShader();

// Step 4: render the quad - yes it is immediate mode. yes that is bad
glBegin(GL_QUADS);
glMultiTexCoord2f(GL_TEXTURE0, 0,0); 
glVertex2f(0, 0);
glMultiTexCoord2f(GL_TEXTURE0, renderWidth,0); 
glVertex2f(renderWidth, 0);
glMultiTexCoord2f(GL_TEXTURE0, renderWidth,renderHeight); 
glVertex2f(renderWidth, renderHeight);
glMultiTexCoord2f(GL_TEXTURE0, 0,renderHeight); 
glVertex2f(0, renderHeight);
glEnd();

// Step 5: turn everything back to normal
shader-&gt;disableShader();
glPopAttrib();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
</pre></p>
<p><b>4. Read the FBO render targets back into the Textures</b><br />
This is also an easy step as we are just reversing the process taken in Step 2.  The difference is that we are now binding the render target as our source (instead of the buffer) and we read into the buffer using <i>glReadPixels</i> instead of <i>glTexSubImage2D</i>. Once again using NULL for the &#8216;data&#8217; portion tells it to use the attached read buffer.</p>
<p><pre class="brush: objc;">
// bind to the FBO so we can reference its render targets
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo-&gt;getID());
		
// read the output of each render target back into the buffers provided
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glBindBuffer(GL_PIXEL_PACK_BUFFER,vertexBufferRef);
glReadPixels(0, 0, renderWidth, renderHeight, GL_RGB, GL_FLOAT, 0);
</pre></p>
<p><b>And the final output!</b><br />
If something didn&#8217;t work then the final output will be nothing at all (doh!) but if it did you will be greeted with the impressive sight of&#8230; exactly what we had when we started. But we now are ready to add the melting.</p>
<div id="attachment_1026" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-07-at-11-20-42-pm.png"><img src="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-07-at-11-20-42-pm.png?w=510&#038;h=372" alt="" title="Screen shot 2010-09-07 at 11.20.42 PM" width="510" height="372" class="size-full wp-image-1026" /></a><p class="wp-caption-text">Glass</p></div>
<p><strong>Addendum: Actually, because I haven&#8217;t specified what the shaders are for rendering into the FBO nothing will be passed on till the next rendering step so nothing will be shown&#8230; till the next post</strong></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/1038/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/1038/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/1038/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/1038/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/1038/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/1038/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/1038/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/1038/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/1038/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/1038/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/1038/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/1038/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/1038/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/1038/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1038&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/10/07/graphics-mgp-rendering-geometry-to-an-fbo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-07-at-11-20-42-pm.png" medium="image">
			<media:title type="html">Screen shot 2010-09-07 at 11.20.42 PM</media:title>
		</media:content>
	</item>
		<item>
		<title>Photo Blog 112</title>
		<link>http://nshgraph.wordpress.com/2010/09/26/photoblog112/</link>
		<comments>http://nshgraph.wordpress.com/2010/09/26/photoblog112/#comments</comments>
		<pubDate>Sun, 26 Sep 2010 04:44:51 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[PhotoBlog]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=1031</guid>
		<description><![CDATA[While it is a subject that has been done to death the Golden Gate bridge is pretty spectacular and I don&#8217;t think anyone goes there without taking a photo. We arrived in the early afternoon and there was already the stereotypical fog rolling in off the sea which made it all quite dramatic, if a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1031&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>While it is a subject that has been done to death the Golden Gate bridge is pretty spectacular and I don&#8217;t think anyone goes there without taking a photo. We arrived in the early afternoon and there was already the stereotypical fog rolling in off the sea which made it all quite dramatic, if a little cold.</p>
<p><a href="http://nshgraph.files.wordpress.com/2010/09/112-_mg_1439-the-bridge.jpg"><img src="http://nshgraph.files.wordpress.com/2010/09/112-_mg_1439-the-bridge.jpg?w=510&#038;h=765" alt="The Bridge (f14 45mm 1/100s)" title="112 _MG_1439 - The Bridge" width="510" height="765" class="alignnone size-full wp-image-1032" /></a><br />
All I&#8217;ve done is convert to Black and White using a blue filter (which makes the bridge&#8217;s red closer to black) and I really like the almost antique feel. Maybe I should add some grain or something&#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/1031/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/1031/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/1031/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/1031/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/1031/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/1031/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/1031/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/1031/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/1031/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/1031/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/1031/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/1031/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/1031/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/1031/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1031&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/09/26/photoblog112/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/112-_mg_1439-the-bridge.jpg" medium="image">
			<media:title type="html">112 _MG_1439 - The Bridge</media:title>
		</media:content>
	</item>
		<item>
		<title>Photo Blog 111</title>
		<link>http://nshgraph.wordpress.com/2010/09/12/photo-blog-111/</link>
		<comments>http://nshgraph.wordpress.com/2010/09/12/photo-blog-111/#comments</comments>
		<pubDate>Sun, 12 Sep 2010 03:55:11 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[PhotoBlog]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=1001</guid>
		<description><![CDATA[As mentioned in the last photo blog I&#8217;ve been working on some more product photography. The new setup is a bit simpler than before using just one light and the box set up in a way that is a bit easier to manipulate. I also have the props / background that was needed by my [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1001&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>As mentioned in the last photo blog I&#8217;ve been working on some more product photography. The new setup is a bit simpler than before using just one light and the box set up in a way that is a bit easier to manipulate. I also have the props / background that was needed by my Aunt for her shots which meant that the white backdrop wasn&#8217;t necessary. This made it heaps easier to set up each individual item and cut the time required down substantially.</p>
<p>The setup:<br />
<div id="attachment_1002" class="wp-caption alignnone" style="width: 310px"><a href="http://nshgraph.files.wordpress.com/2010/09/setup.jpg"><img src="http://nshgraph.files.wordpress.com/2010/09/setup.jpg?w=300&#038;h=225" alt="" title="Setup" width="300" height="225" class="size-medium wp-image-1002" /></a><p class="wp-caption-text">The Setup</p></div></p>
<p>The only real issue was making sure that I was using a custom white balance that matched the lighting as otherwise it would have been a pain in post-processing. In the end the only changes needed in post where a bit of cropping and use of the &#8216;heal&#8217; brush in Photoshop to remove some artifacts near the edges.</p>
<p>A couple example images:<br />
<div id="attachment_1003" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/09/mg_1941.jpg"><img src="http://nshgraph.files.wordpress.com/2010/09/mg_1941.jpg?w=510&#038;h=340" alt="" title="_MG_1941" width="510" height="340" class="size-medium wp-image-1003" /></a><p class="wp-caption-text">Example Shot 1 (f16 2.5s 105mm)</p></div></p>
<div id="attachment_1004" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/09/img_0003.jpg"><img src="http://nshgraph.files.wordpress.com/2010/09/img_0003.jpg?w=510&#038;h=340" alt="" title="IMG_0003" width="510" height="340" class="size-full wp-image-1004" /></a><p class="wp-caption-text">Example Shot 2 (f16 2.5s 105mm)</p></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/1001/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/1001/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/1001/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/1001/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/1001/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/1001/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/1001/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/1001/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/1001/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/1001/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/1001/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/1001/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/1001/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/1001/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1001&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/09/12/photo-blog-111/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/setup.jpg?w=300" medium="image">
			<media:title type="html">Setup</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/mg_1941.jpg" medium="image">
			<media:title type="html">_MG_1941</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/img_0003.jpg" medium="image">
			<media:title type="html">IMG_0003</media:title>
		</media:content>
	</item>
		<item>
		<title>Graphics &#8211; MGP &#8211; Glass</title>
		<link>http://nshgraph.wordpress.com/2010/09/08/graphics-mgp-glass/</link>
		<comments>http://nshgraph.wordpress.com/2010/09/08/graphics-mgp-glass/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 11:27:22 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=1020</guid>
		<description><![CDATA[With this installment we will finally make our object look like it is made of glass. Luckily we have already been introduced to shaders in a previous post so all that remains to be done is to describe how we can incorporate our new environment/cube map into our shader and use it to fake reflection [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1020&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>With this installment we will finally make our object look like it is made of glass. Luckily we have already been introduced to shaders in a <a href="http://nshgraph.wordpress.com/2010/06/10/graphics-mgp-intro-to-shaders/">previous post</a> so all that remains to be done is to describe how we can incorporate our new environment/cube map into our shader and use it to fake reflection and refraction.</p>
<p>The first thing we are going to need for our calculations is the normal and position associated for each pixel. These can be calculated in the Vertex shader, as can the usual set of calculations needed for basic operations. As such our Vertex shader is quite simple as shown in Figure 1.</p>
<p><pre class="brush: cpp;">
varying vec3 normal;
varying vec3 view;

void main()
{
    // the basics that have to be done
    gl_FrontColor = gl_Color;
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = ftransform();
	
    // calculate the view vector in eye-space using the ModelView and Projection matrix
    view = (gl_ModelViewProjectionMatrix * gl_Vertex).xyz;
    // calculate the normal vector in eye-space using the ModelView and Projection matrix
    normal = normalize(gl_NormalMatrix * gl_Normal);
}
// Figure 1
</pre></p>
<p>Using the same code as in the previous post the cube map texture should automatically be available to us in the GLSL shader as a texture. The only difference is that the type of the texture is <em>samplerCube</em> instead of <em>sampler2D</em>. Thus we begin our fragment shader like this:</p>
<p><pre class="brush: cpp;">
// our cube map texture
uniform samplerCube tex;
//variables passed in from our vertex shader
varying vec3 view;
varying vec3 normal;

void main()
{	
</pre></p>
<p>When we want to access our cube map we do so through the use of a vector which expresses the direction we wish to sample the &#8216;cube&#8217; that surrounds our object. For example, by calculating the reflection vector of the view around the normal and sampling this we can see what would be &#8216;reflected&#8217; if our object was a perfect mirror.</p>
<p><pre class="brush: cpp;">
    // create the reflection vector 
    vec3 reflect_v = normalize(reflect(view,-normal));
    // sample the cube map to find the reflected color
    vec3 colReflect = textureCube(tex,reflect_v).rgb;
</pre></p>
<p>GLSL provides a very useful function which we use here for performing the reflection of <em>&#8216;view&#8217;</em> around <em>&#8216;-normal&#8217;</em> so we don&#8217;t even have to think about it.</p>
<p>We can do exactly the same thing to find the colour that would come from refracting through the surface. This refraction would of course depend on the refractive indices of the two materials. Because we are trying to model glass this means that we are going from a refractive index of 1.0 (air) to 1.2 (glass).</p>
<p><pre class="brush: cpp;">
    const float eta = 1.00 / 1.20;
    // create the reflection vector 
    vec3 refract_v = normalize(refract(view,-normal,eta));
    // sample the cube map to find the reflected color
    vec3 colReflect = textureCube(tex,refract_v).rgb;
</pre></p>
<p>There is one major limitation to this of course. A real simulation would model the effect of coming out the other side of the glass, and perhaps even entering another material if there are other objects in the scene / concave objects. This is pretty serious but for our purposes it works ok because we limit ourselves to only one object and it kind of looks &#8216;good enough&#8217;.</p>
<p>Finally we composite the reflected and refracted components together, along with a bit of specular lighting from the phong model discussed previously.</p>
<p><pre class="brush: cpp;">
    // calculate the specular lighting
    float light = pow(max(dot(normal, gl_LightSource[0].halfVector.xyz),0.0),1000.0);
    // coefficients for each of the calculated components (reflection, refraction, lighting). These DON'T have to add to 1.0
    const vec3 coeff = vec3( 0.3, 0.6, 0.5 );
    gl_FragColor = vec4(coeff.x * colReflect + coeff.y * colRefract + coeff.z * vec3(light,light,light) + gl_Color.rgb,1.0);
}
</pre></p>
<p>This gives us a final result that looks something like this:<br />
<div id="attachment_1026" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-07-at-11-20-42-pm.png"><img src="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-07-at-11-20-42-pm.png?w=510&#038;h=372" alt="" title="Screen shot 2010-09-07 at 11.20.42 PM" width="510" height="372" class="size-full wp-image-1026" /></a><p class="wp-caption-text">Glass</p></div></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/1020/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/1020/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/1020/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/1020/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/1020/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/1020/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/1020/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/1020/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/1020/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/1020/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/1020/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/1020/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/1020/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/1020/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1020&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/09/08/graphics-mgp-glass/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-07-at-11-20-42-pm.png" medium="image">
			<media:title type="html">Screen shot 2010-09-07 at 11.20.42 PM</media:title>
		</media:content>
	</item>
		<item>
		<title>Photo Blog 110</title>
		<link>http://nshgraph.wordpress.com/2010/09/07/photo-blog-110/</link>
		<comments>http://nshgraph.wordpress.com/2010/09/07/photo-blog-110/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 02:14:33 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[PhotoBlog]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=1007</guid>
		<description><![CDATA[Recently I got to do a bit of road trippen&#8217; between Las Vegas and San Fransisco and we took the route through Death Valley and Yosemite National Park. There is some stunning scenery through there as well as some rather interesting extremes. In 12 hours we went from -200feet to 10000feet and from 46ºC to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1007&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Recently I got to do a bit of road trippen&#8217; between Las Vegas and San Fransisco and we took the route through Death Valley and Yosemite National Park. There is some stunning scenery through there as well as some rather interesting extremes. In 12 hours we went from -200feet to 10000feet and from 46ºC to 3ºC. Luckily I was traveling with a couple of other photographers so there were plenty of opportunities for stopping and taking photos.</p>
<p>Obviously there are lots of photos from there that I&#8217;m proud of but one in particular would have to be a panorama I took while leaving Death Valley. So here it is:</p>
<div id="attachment_1008" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/09/111-_mg_1261-death-valley-panorama.jpg"><img src="http://nshgraph.files.wordpress.com/2010/09/111-_mg_1261-death-valley-panorama.jpg?w=510&#038;h=186" alt="" title="111 _MG_1261 - Death Valley Panorama" width="510" height="186" class="size-full wp-image-1008" /></a><p class="wp-caption-text">Death Valley Panorama</p></div>
<p>I really do suggest you click on it to view it at a higher resolution as seeing it in a small frame like above doesn&#8217;t do it justice.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/1007/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/1007/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/1007/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/1007/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/1007/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/1007/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/1007/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/1007/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/1007/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/1007/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/1007/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/1007/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/1007/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/1007/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=1007&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/09/07/photo-blog-110/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/111-_mg_1261-death-valley-panorama.jpg" medium="image">
			<media:title type="html">111 _MG_1261 - Death Valley Panorama</media:title>
		</media:content>
	</item>
		<item>
		<title>Graphics – MGP – Environment Mapping</title>
		<link>http://nshgraph.wordpress.com/2010/09/06/graphics-mgp-environment-mapping/</link>
		<comments>http://nshgraph.wordpress.com/2010/09/06/graphics-mgp-environment-mapping/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 06:13:25 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=995</guid>
		<description><![CDATA[From the previous step we have a well illuminated cup that looks like it is made of clay, but hardly like a glass. To make this a little more realistic we are going to use environment mapping. How this works is that we define a set of textures representing the six sides of a cube [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=995&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>From the previous step we have a well illuminated cup that looks like it is made of clay, but hardly like a glass. To make this a little more realistic we are going to use environment mapping. How this works is that we define a set of textures representing the six sides of a cube surrounding our scene. This is stored in a cube map which can be accessed like any other texture and so at any point we can ask what colour is in a particular direction and so create pseudo reflection and refraction by asking what from the scene would be reflected or refracted.</p>
<p><strong>Creating the Cube Map</strong><br />
The first step to do this is to acquire a Cube Map. The one I have to use is one I found quite a while ago of the Swedish Royal Palace at night. It has a lot of interesting colours and lighting and while it isn&#8217;t the natural habitat for a wine glass it suits well enough for our purposes. You can often find textures appropriate for this sort of thing around the internet and one good collection in particular is Emil Persson&#8217;s over <a href="http://www.humus.name/index.php?page=Textures">here</a>.</p>
<p>These images then need to be loaded into graphics memory so they can be used This is done by using the same glTexImage2D calls as usual but with the targets in Figure 1 instead.<br />
<pre class="brush: cpp;">
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
GL_TEXTURE_CUBE_MAP_POSITIVE_Z
GL_TEXTURE_CUBE_MAP_NEGATIVE_X
GL_TEXTURE_CUBE_MAP_POSITIVE_X
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
GL_TEXTURE_CUBE_MAP_POSITIVE_Y
// Figure 1
</pre></p>
<p>Once all 6 textures are loaded we can generate the environment map needed for reflections by calling the functions outlined in Figure 2.<br />
<pre class="brush: cpp;">
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
// Figure 2
</pre></p>
<p>And finally, every time we want to employ our new Environment Map all we have to do is turn it on like we would any other texture.<br />
<pre class="brush: cpp;">
// Enable
	glEnable(GL_TEXTURE_CUBE_MAP);
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	glEnable(GL_TEXTURE_GEN_R);

// Draw
DrawObject();

// Disable
	glDisable(GL_TEXTURE_CUBE_MAP);
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);
	glDisable(GL_TEXTURE_GEN_R);
// Figure 3
</pre></p>
<p>The result we now get hardly looks like a lot more like pewter than glass but we can already see the basic effect of environment mapping and how it might allow us to preform refraction as well as reflection.</p>
<div id="attachment_1014" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-06-at-6-04-14-pm.png"><img src="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-06-at-6-04-14-pm.png?w=510&#038;h=372" alt="" title="Screen shot 2010-09-06 at 6.04.14 PM" width="510" height="372" class="size-full wp-image-1014" /></a><p class="wp-caption-text">Environment Mapping</p></div>
<p>This cube/environment map will now be available for us in the shader so we can make more customized requests of it.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/995/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/995/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/995/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/995/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/995/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/995/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/995/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/995/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/995/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/995/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/995/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/995/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/995/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/995/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=995&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/09/06/graphics-mgp-environment-mapping/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/screen-shot-2010-09-06-at-6-04-14-pm.png" medium="image">
			<media:title type="html">Screen shot 2010-09-06 at 6.04.14 PM</media:title>
		</media:content>
	</item>
		<item>
		<title>Photo Blog 109</title>
		<link>http://nshgraph.wordpress.com/2010/09/05/photo-blog-109/</link>
		<comments>http://nshgraph.wordpress.com/2010/09/05/photo-blog-109/#comments</comments>
		<pubDate>Sun, 05 Sep 2010 00:48:25 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[PhotoBlog]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=998</guid>
		<description><![CDATA[While I was playing around with some more product photography (perhaps the next update will explain) Alyona decided to do some painting. I spun the camera around on the tripod and managed to catch this without her seeing. I like her pose and look of utter concentration. That and our random assortment of stuff around [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=998&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>While I was playing around with some more product photography (perhaps the next update will explain) Alyona decided to do some painting. I spun the camera around on the tripod and managed to catch this without her seeing. I like her pose and look of utter concentration. That and our random assortment of stuff around the apartment!</p>
<div id="attachment_999" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/09/109-img_1942-painter.jpg"><img src="http://nshgraph.files.wordpress.com/2010/09/109-img_1942-painter.jpg?w=510&#038;h=339" alt="" title="109 IMG_1942 - Painter" width="510" height="339" class="size-full wp-image-999" /></a><p class="wp-caption-text">Painting (f8.0 1/10s 47mm)</p></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/998/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/998/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/998/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/998/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/998/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/998/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/998/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/998/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/998/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/998/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/998/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/998/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/998/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/998/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=998&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/09/05/photo-blog-109/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/09/109-img_1942-painter.jpg" medium="image">
			<media:title type="html">109 IMG_1942 - Painter</media:title>
		</media:content>
	</item>
		<item>
		<title>Graphics &#8211; MGP &#8211; Lighting</title>
		<link>http://nshgraph.wordpress.com/2010/07/03/graphics-mgp-lighting/</link>
		<comments>http://nshgraph.wordpress.com/2010/07/03/graphics-mgp-lighting/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 00:53:53 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=962</guid>
		<description><![CDATA[Now that our surface has normals we can light it with the afore-mentioned Phong illumination model. This model breaks lighting into 3 components: ambient, diffuse and specular. Ambient light is that light which is everywhere due to light reflecting of other surfaces. If you look at the underside of your chair you will notice that [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=962&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Now that our surface has normals we can light it with the afore-mentioned Phong illumination model. This model breaks lighting into 3 components: ambient, diffuse and specular.</p>
<p><img src="http://nshgraph.files.wordpress.com/2010/06/5_phong1.png?w=274&#038;h=18" alt="" title="5_phong1" width="274" height="18" class="alignnone size-full wp-image-963" /></p>
<p><strong>Ambient</strong> light is that light which is everywhere due to light reflecting of other surfaces. If you look at the underside of your chair you will notice that there is some light, despite there not being a light shining directly on it. Ideally one would use a global illumination method to calculate this properly. Under Phong this is just a constant</p>
<p><img src="http://nshgraph.files.wordpress.com/2010/06/5_phong2.png?w=96&#038;h=20" alt="" title="5_Phong2" width="96" height="20" class="alignnone size-full wp-image-964" /></p>
<p><strong>Diffuse</strong> light is that which results from being in direct illumination from a light source. The defining characteristic of diffuse light is that it is strongest when the light is pointing directly at the surface and less when it is at an angle. Of course when the angle between the 2 hits 90 degrees there is no diffuse light at all (or if it is on the underside of an object). Under phong this is calculated using the angle between the surface normal and the direction to the light source.</p>
<p><img src="http://nshgraph.files.wordpress.com/2010/06/5_phong3.png?w=150&#038;h=20" alt="" title="5_Phong3" width="150" height="20" class="alignnone size-full wp-image-965" /></p>
<p>Here the angle between the direction to the Light (L) and surface is calculated using the dot product between the normal (N) and light direction. This has the property that when they are in the same direction they will be 1 and when they are 90 degrees apart they will be 0.</p>
<p><strong>Specular</strong> light is that which comes from the light source itself reflecting off the surface and into the camera. This allows us to model shiny (although not reflective) surfaces. Under Phong we now add the direction to the camera and compare the angle between this vector and the reflected vector from the light source. If they match up we have a reflection and if they don&#8217;t, neither do we.</p>
<p><img src="http://nshgraph.files.wordpress.com/2010/06/5_phong4.png?w=166&#038;h=23" alt="" title="5_Phong4" width="166" height="23" class="alignnone size-full wp-image-967" /></p>
<p>The alpha in this equation determines how wide the spot of light will be. A small alpha equates to a larger spotlight.</p>
<p>But we can get the same results from a slightly different formula that is a little more efficient.<br />
Instead of having to reflect the light vector to get the vector to compare against the view we can use what is known as the &#8216;Half Vector&#8217;. If we add the Light Vector and View Vector we will get something which should point directly away from the surface if they are reflected exactly around the normal (i.e there should be a specular reflection) and will point elsewhere if it they aren&#8217;t. As such we can compare this half vector with the normal for the same effect. Making the equation to use:</p>
<p><img src="http://nshgraph.files.wordpress.com/2010/06/5_phong5.png?w=170&#038;h=23" alt="" title="5_Phong5" width="170" height="23" class="alignnone size-full wp-image-971" /></p>
<p>The <a href="http://en.wikipedia.org/wiki/Phong_shading">wikipedia article</a> has more if you are interested and is where I got the following demonstrative picture which clearly shows how each of these three components are used to create the final lighting of a strange object:</p>
<div id="attachment_968" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/06/655px-phong_components_version_4.png"><img src="http://nshgraph.files.wordpress.com/2010/06/655px-phong_components_version_4.png?w=510&#038;h=141" alt="" title="655px-Phong_components_version_4" width="510" height="141" class="size-full wp-image-968" /></a><p class="wp-caption-text">Phong Components (from the Wikipedia Article)</p></div>
<p>That is all well and good but we need to convert this into code. We can do this using the GLSL shaders introduced last time. As such the Vertex shader looks like this:<br />
<pre class="brush: cpp;">
varying vec3 normal;
varying vec3 eyeDir;
varying vec3 lightDir;
void main() {
    gl_Position = ftransform();
    normal = normalize(gl_NormalMatrix * gl_Normal);
    vec3 vertex = vec3(gl_ModelViewMatrix * gl_Vertex);
    lightDir = normalize(gl_LightSource[0].position.xyz - vertex);
    eyeDir = normalize(-vertex);
    gl_FrontColor = gl_Color;
} \n\
</pre><br />
Here we calculate all the vectors we need for computing the lighting. These will then be interpolated between each vertex to be correct on the per-pixel level. This is far more efficient than computing them at each pixel. This approach can have problems for very large surfaces where the interpolation may not be done correctly / may be undefined. Our glass is fairly high resolution so this isn&#8217;t an issue here.</p>
<p>The Fragment shader then looks like this:<br />
<pre class="brush: cpp;">
varying vec3 normal;
varying vec3 eyeDir;
varying vec3 lightDir;
void main() {
    vec3 ambient = vec3(0.2,0.2,0.2);
    vec3 diffuse = vec3(0.8,0.8,0.8)*( max(dot(normal,lightDir), 0.0);
    vec3 specular = pow(max(dot(normal,normalize(lightDir+eyeDir)),0.0),30.0));
    vec3 lightCol =  diffuse + specular + ambient;
     gl_FragColor = vec4(gl_Color.rgb * lightCol,1.0);
}
</pre><br />
Here we calculate the 3 components (ambient, diffuse and specular) to create the intensity of the light at that point. This is then multiplied with the colour of the surface to get the final colour of the pixel.</p>
<p>This then gives us this image for our glass:<br />
<div id="attachment_991" class="wp-caption alignnone" style="width: 520px"><a href="http://nshgraph.files.wordpress.com/2010/07/7_lighting.png"><img src="http://nshgraph.files.wordpress.com/2010/07/7_lighting.png?w=510&#038;h=410" alt="" title="7_lighting" width="510" height="410" class="size-full wp-image-991" /></a><p class="wp-caption-text">Phong Illumination</p></div></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/962/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/962/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/962/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/962/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/962/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/962/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/962/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/962/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/962/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/962/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/962/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/962/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/962/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/962/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=962&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/07/03/graphics-mgp-lighting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/5_phong1.png" medium="image">
			<media:title type="html">5_phong1</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/5_phong2.png" medium="image">
			<media:title type="html">5_Phong2</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/5_phong3.png" medium="image">
			<media:title type="html">5_Phong3</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/5_phong4.png" medium="image">
			<media:title type="html">5_Phong4</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/5_phong5.png" medium="image">
			<media:title type="html">5_Phong5</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/655px-phong_components_version_4.png" medium="image">
			<media:title type="html">655px-Phong_components_version_4</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/07/7_lighting.png" medium="image">
			<media:title type="html">7_lighting</media:title>
		</media:content>
	</item>
		<item>
		<title>Graphics &#8211; MGP &#8211; Intro to Shaders</title>
		<link>http://nshgraph.wordpress.com/2010/06/10/graphics-mgp-intro-to-shaders/</link>
		<comments>http://nshgraph.wordpress.com/2010/06/10/graphics-mgp-intro-to-shaders/#comments</comments>
		<pubDate>Thu, 10 Jun 2010 03:00:42 +0000</pubDate>
		<dc:creator>nshgraph</dc:creator>
				<category><![CDATA[Graphics]]></category>

		<guid isPermaLink="false">http://nshgraph.wordpress.com/?p=980</guid>
		<description><![CDATA[Intro Before we can go any further into the project we need to introduce the concept of shaders and the modification of the Fixed Functionality Pipeline. In OpenGL the normal pipeline looks like that in the image below. Vertices, normals and colours go in one end, are transformed into their final location (depending on camera, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=980&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Intro</strong><br />
Before we can go any further into the project we need to introduce the concept of shaders and the modification of the Fixed Functionality Pipeline. </p>
<p>In OpenGL the normal pipeline looks like that in the image below. Vertices, normals and colours go in one end, are transformed into their final location (depending on camera, matrix transformations etc) and then the colour of each pixel is determined before being put on the screen.</p>
<div id="attachment_982" class="wp-caption alignnone" style="width: 502px"><a href="http://nshgraph.files.wordpress.com/2010/06/6_pipeline_flat.png"><img src="http://nshgraph.files.wordpress.com/2010/06/6_pipeline_flat.png?w=492&#038;h=312" alt="" title="6_pipeline_flat" width="492" height="312" class="size-full wp-image-982" /></a><p class="wp-caption-text">OpenGL Pipeline Simplified</p></div>
<p>In our use of shaders we are changing two stages of this pipeline by replacing the fixed functionality with little programs of our own. The two areas that we can replace are marked in green in the diagram.</p>
<p><strong>Replacing the FFP</strong><br />
We are going to use GLSL shaders which means they are written in the GLSL language and supplied to the graphics driver as code at runtime. The graphics driver then compiles them into a shader and returns a reference for us to use.</p>
<p>To create the reference we need to follow the steps below:</p>
<ol>
<li>Create handles for our shaders</li>
<li>Send the source code for each to the graphics driver</li>
<li>Compile the shaders</li>
<li>Check for compilation problems</li>
<li>Tell our shader about the Fragment and Vertex shaders</li>
<li>Link shader</li>
<li>Validate shader</li>
<li>Check for linker errors</li>
</ol>
<p>The code to do this is as follows:<br />
<pre class="brush: cpp;">
// references we will need
GLuint shaderHandle, vsHandle, fsHandle;
GLint result;
const GLChar* vsSource = &quot;…&quot;;
const GLChar* fsSource = &quot;…&quot;;

// compile the vertex shader part
vsHandle = glCreateShader (GL_VERTEX_SHADER_ARB); // Step 1
glShaderSource (vsHandle, 1, &amp;vsSource, NULL); // Step 2
glCompileShader (vsHandle); // Step 3
glGetShaderiv (vsHandle, GL_COMPILE_STATUS, &amp;result); // Step 4
if( result == GL_FALSE )
    ; // ohoh - need to handle the fail case (print what is wrong etc)

// compile the fragment shader part
fsHandle = glCreateShader (GL_FRAGMENT_SHADER_ARB); // Step 1
glShaderSource (fsHandle, 1, &amp;fsSource, NULL); // Step 2
glCompileShader (fsHandle); // Step 3
glGetShaderiv (fsHandle, GL_COMPILE_STATUS, &amp;result); // Step 4
if( result == GL_FALSE )
    ; // ohoh - need to handle the fail case (print what is wrong etc)

// link them together
shaderHandle = glCreateProgram (); // Step 1
glAttachShader (shaderHandle, vsHandle); // Step 5
glAttachShader (shaderHandle, fsHandle); // Step 5
glLinkProgram (shaderHandle); // Step 6
glValidateProgram (shaderHandle);	// Step 7
glGetShaderiv (shaderHandle, GL_LINK_STATUS, &amp;result); // Step 8
if( result == GL_FALSE )
    ; // ohoh - need to handle the fail case (print what is wrong etc)
</pre></p>
<p>And that is pretty much it. There is a whole bunch of extra error checking you can do and you can even get and print the compilation errors if you want but the above is the simplest case.</p>
<p>Now that you have a proper shader you need to be able to turn it on and off. How this works is that you can enable a particular shader much like you would lighting and then each draw command submitted until the shader is turned off will use the new functionality.</p>
<p>As such the proper way to use it would be something like:<br />
<pre class="brush: cpp;">
glUseProgram (shaderHandle); // Turn it on
// Do some drawing
glUseProgram(0); // Turn it off
</pre></p>
<p><strong>Writing a (really) simple shader</strong><br />
The above code explains how to create a new shader and how to use to draw but assumes you have some code to submit to the graphics driver. Here we will describe the simplest possible shader and a small variation that lets you use the normal at each point as the colour (for visualization much like the image in the previous graphics post).</p>
<p>If all you want is to replicate the fixed funtionality the following fragment and vertex shaders will do the trick<br />
<pre class="brush: cpp;">
// Vertex shader
void main ()
{
	gl_Normal = gl_NormalMatrix * normalize(gl_Normal);
	gl_Position = ftransform();
}
</pre></p>
<p><pre class="brush: cpp;">
// Fragment shader
void main ()
{
	gl_FragColor = gl_FrontColor;
}
</pre></p>
<p>This is pretty boring though (and does even less than the normal pipeline) so lets change the fragment shader a bit to use the normal instead of the color.</p>
<p><pre class="brush: cpp;">
// Fragment shader
void main ()
{
	gl_FragColor = vec4( gl_Normal.xyz, 1.0);
}
</pre><br />
This will use the x, y and z components as the red, green and blue components respectively.</p>
<p>And here is that image again to show where we are at:<br />
<div id="attachment_956" class="wp-caption alignnone" style="width: 455px"><a href="http://nshgraph.files.wordpress.com/2010/06/4_normals.png"><img src="http://nshgraph.files.wordpress.com/2010/06/4_normals.png?w=445&#038;h=291" alt="" title="4_Normals" width="445" height="291" class="size-full wp-image-956" /></a><p class="wp-caption-text">Normals</p></div></p>
<p>For further reading into what functionality is available when creating these shaders the GLSL spec is the place to go: <a href="http://www.opengl.org/documentation/glsl/">OpenGL.org</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nshgraph.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nshgraph.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nshgraph.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nshgraph.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nshgraph.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nshgraph.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nshgraph.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nshgraph.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nshgraph.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nshgraph.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nshgraph.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nshgraph.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nshgraph.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nshgraph.wordpress.com/980/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nshgraph.wordpress.com&amp;blog=4878648&amp;post=980&amp;subd=nshgraph&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nshgraph.wordpress.com/2010/06/10/graphics-mgp-intro-to-shaders/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/9d2a302c69fbdb0d7fc34b6ecf3f1a40?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">nshgraph</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/6_pipeline_flat.png" medium="image">
			<media:title type="html">6_pipeline_flat</media:title>
		</media:content>

		<media:content url="http://nshgraph.files.wordpress.com/2010/06/4_normals.png" medium="image">
			<media:title type="html">4_Normals</media:title>
		</media:content>
	</item>
	</channel>
</rss>
