<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
	<title>OpenGL - Articles</title>
	<link>http://www.gamedev.net/page/resources/_/technical/opengl/</link>
	<pubDate>Sat, 25 Feb 2012 22:01:09 +0000</pubDate>
	<ttl>43200</ttl>
	<description>Resources for the OpenGL API</description>
	<item>
		<title>GLSL 4.0: Discarding Fragments to Create a Perf...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/glsl-40-discarding-fragments-to-create-a-perf-r2873</link>
		<description><![CDATA[Fragment shaders can make use of the <em class='bbc'>discard</em> keyword to "throw away" fragments. Use of this keyword causes the fragment shader to stop execution, without writing anything (including depth) to the output buffer. This provides a way to create holes in polygons without using blending. In fact, since fragments are completely discarded, there is no dependence on the order in which objects are drawn, saving us the trouble of doing any depth sorting that might have been necessary if blending was used. In this recipe by <strong class='bbc'>David Wolff</strong>, author of <a href='http://www.packtpub.com/opengl-4-0-shading-language-cookbook/book/rk/opengl4-abr6/0811?utm_source=rk_opengl4_abr6_0811&utm_medium=content&utm_campaign=ramsai' class='bbc_url' title='External link' rel='nofollow external'>OpenGL 4.0 Shading Language Cookbook</a>, we'll draw a teapot, and use the discard keyword to remove fragments selectively based on texture coordinates.<br />
<br />
The result will look like the following image:<br />
 <br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_18.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Getting ready</strong></span><br />
The vertex position, normal, and texture coordinates must be provided to the vertex shader from the OpenGL application. The position should be provided at location 0, the normal at location 1, and the texture coordinates at location 2. As in <a href='http://www.packtpub.com/article/opengl-glsl-4-shaders-basics' class='bbc_url' title='External link' rel='nofollow external'>previous examples</a>, the lighting parameters must be set from the OpenGL application via the appropriate uniform variables.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How to do it...</strong></span><br />
To create a shader program that discards fragments based on a square lattice (as in the preceding image), use the following code:<br />
<br />
Use the following code for the vertex shader:<br />
<pre class='prettyprint'>#version 400<br /><br />layout (location = 0) in vec3 VertexPosition;<br />layout (location = 1) in vec3 VertexNormal;<br />layout (location = 2) in vec2 VertexTexCoord;<br /><br />out vec3 FrontColor;<br />out vec3 BackColor;<br />out vec2 TexCoord;<br /><br />struct LightInfo {<br />  vec4 Position; // Light position in eye coords.<br />  vec3 La; // Ambient light intensity<br />  vec3 Ld; // Diffuse light intensity<br />  vec3 Ls; // Specular light intensity<br />};<br />uniform LightInfo Light;<br /><br />struct MaterialInfo {<br />  vec3 Ka; // Ambient reflectivity<br />  vec3 Kd; // Diffuse reflectivity<br />  vec3 Ks; // Specular reflectivity<br />  float Shininess; // Specular shininess factor<br />};<br />uniform MaterialInfo Material;<br /><br />uniform mat4 ModelViewMatrix;<br />uniform mat3 NormalMatrix;<br />uniform mat4 ProjectionMatrix;<br />uniform mat4 MVP;<br /><br />void getEyeSpace( out vec3 norm, out vec4 position )<br />{<br />  norm = normalize( NormalMatrix * VertexNormal);<br />  position = ModelViewMatrix * vec4(VertexPosition,1.0);<br />}<br /><br />vec3 phongModel( vec4 position, vec3 norm )<br />{<br />  // The ADS shading calculations go here (see: "Using<br />  // functions in shaders," and "Implementing<br />  // per-vertex ambient, diffuse and specular (ADS) shading")<br />  ...<br />}<br /><br />void main()<br />{<br />  vec3 eyeNorm;<br />  vec4 eyePosition;<br /><br />  TexCoord = VertexTexCoord;<br /><br />  // Get the position and normal in eye space<br />  getEyeSpace(eyeNorm, eyePosition);<br /><br />  FrontColor = phongModel( eyePosition, eyeNorm );<br />  BackColor = phongModel( eyePosition, -eyeNorm );<br /><br />  gl_Position = MVP * vec4(VertexPosition,1.0);<br />}</pre><br />
<br />
Use the following code for the fragment shader:<br />
<pre class='prettyprint'>#version 400<br /><br />in vec3 FrontColor;<br />in vec3 BackColor;<br />in vec2 TexCoord;<br /><br />layout( location = 0 ) out vec4 FragColor;<br /><br />void main() {<br />  const float scale = 15.0;<br />  bvec2 toDiscard = greaterThan( fract(TexCoord * scale),<br />								 vec2(0.2,0.2) );<br /><br />if( all(toDiscard) )<br />	discard;<br /><br />if( gl_FrontFacing )<br />	FragColor = vec4(FrontColor, 1.0);<br />else<br />	FragColor = vec4(BackColor, 1.0);<br />}</pre><br />
<br />
Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How it works...</strong></span><br />
Since we will be discarding some parts of the teapot, we will be able to see through the teapot to the other side. This will cause the back sides of some polygons to become visible. Therefore, we need to compute the lighting equation appropriately for both sides of each face. We'll use the same technique presented earlier in the two-sided shading recipe.<br />
<br />
The vertex shader is essentially the same as in the two-sided shading recipe, with the main difference being the addition of the texture coordinate. The differences are highlighted in the above listing. To manage the texture coordinate, we have an additional input variable, <em class='bbc'>VertexTexCoord</em>, that corresponds to attribute location 2. The value of this input variable is passed directly on to the fragment shader unchanged via the output variable <em class='bbc'>TexCoord</em>. The ADS shading model is calculated twice, once using the given normal vector, storing the result in <em class='bbc'>FrontColor</em>, and again using the reversed normal, storing that result in <em class='bbc'>BackColor</em>.<br />
<br />
In the fragment shader, we calculate whether or not the fragment should be discarded based on a simple technique designed to produce the lattice-like pattern shown in the preceding image. We first scale the texture coordinate by the arbitrary scaling factor <em class='bbc'>scale</em>. This corresponds to the number of lattice rectangles per unit (scaled) texture coordinate. We then compute the fractional part of each component of the scaled texture coordinate using the built-in function <em class='bbc'>fract</em>. Each component is compared to 0.2 using the built-in function <em class='bbc'>greaterThan</em>, and the result is stored in the <em class='bbc'>bool</em> vector <em class='bbc'>toDiscard</em>. The <em class='bbc'>greaterThan</em> function compares the two vectors component-wise, and stores the Boolean results in the corresponding components of the return value.<br />
<br />
If both components of the vector <em class='bbc'>toDiscard</em> are true, then the fragment lies within the inside of each lattice frame, and therefore we wish to discard this fragment. We can use the built-in function <em class='bbc'>all</em> to help with this check. The function <em class='bbc'>all</em> will return true if all of the components of the parameter vector are true. If the function returns true, we execute the <em class='bbc'>discard</em> statement to reject the fragment.<br />
<br />
In the else branch, we color the fragment based on the orientation of the polygon, as in the two-sided shading recipe presented earlier.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
This recipe showed us how to use the <em class='bbc'>discard</em> keyword to "throw away" fragments and create a perforated look.]]></description>
		<pubDate>Tue, 07 Feb 2012 02:41:41 +0000</pubDate>
		<guid isPermaLink="false">08b90c2ebcce5d7f46176eb7c05af0ea</guid>
	</item>
	<item>
		<title>GLSL 4.0: Using Subroutines to Select Shader Fu...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/glsl-40-using-subroutines-to-select-shader-fu-r2872</link>
		<description><![CDATA[In GLSL, a subroutine is a mechanism for binding a function call to one of a set of possible function definitions based on the value of a variable. Subroutines therefore provide a way to select alternate implementations at runtime without swapping shader programs and/or recompiling, or using <em class='bbc'>if</em> statements along with a uniform variable.<br />
<br />
In this article by <strong class='bbc'>David Wolff</strong>, author of <a href='http://www.packtpub.com/opengl-4-0-shading-language-cookbook/book/rk/opengl4-abr5/0811?utm_source=rk_opengl4_abr5_0811&utm_medium=content&utm_campaign=ramsai' class='bbc_url' title='External link' rel='nofollow external'>OpenGL 4.0 Shading Language Cookbook</a>, we'll demonstrate the use of subroutines by rendering a teapot twice. The first teapot will be rendered with the <a href='http://www.packtpub.com/article/opengl-glsl-4-shaders-basics' class='bbc_url' title='External link' rel='nofollow external'>full ADS shading model</a> described earlier. The second teapot will be rendered with diffuse shading only. A subroutine uniform will be used to choose between the two shading techniques.<br />
<br />
In many ways it is similar to function pointers in C. A uniform variable serves as the pointer and is used to invoke the function. The value of this variable can be set from the OpenGL side, thereby binding it to one of a few possible definitions. The subroutine's function definitions need not have the same name, but must have the same number and type of parameters and the same return type.<br />
<br />
A single shader could be written to provide several shading algorithms intended for use on different objects within the scene. When rendering the scene, rather than swapping shader programs (or using a conditional statement), we can simply change the subroutine's uniform variable to choose the appropriate shading algorithm as each object is rendered.<br />
 <br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'>Since performance is crucial in shader programs, avoiding a conditional statement or a shader swap can be very valuable. With subroutines, we can implement the functionality of a conditional statement or shader swap without the computational overhead.</em></p><br />
In the following image, we see an example of a rendering that was created using subroutines. The teapot on the left is rendered with the full ADS shading model, and the teapot on the right is rendered with diffuse shading only. A subroutine is used to switch between shader functionality.<br />
 <br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_17.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Getting ready</strong></span><br />
As with <a href='http://www.packtpub.com/article/opengl-glsl-4-shaders-basics' class='bbc_url' title='External link' rel='nofollow external'>previous recipes</a>, provide the vertex position at attribute location 0 and the vertex normal at attribute location 1. Uniform variables for all of the ADS coefficients should be set from the OpenGL side, as well as the light position and the standard matrices.<br />
<br />
We'll assume that, in the OpenGL application, the variable <em class='bbc'>programHandle</em> contains the handle to the shader program object.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How to do it...</strong></span><br />
To create a shader program that uses a subroutine to switch between pure-diffuse and ADS shading, use the following code:<br />
<br />
Use the following code for the vertex shader:<br />
<pre class='prettyprint'>#version 400<br /><br />subroutine vec3 shadeModelType( vec4 position, vec3 normal);<br /><br />subroutine uniform shadeModelType shadeModel;<br /><br />layout (location = 0) in vec3 VertexPosition;<br />layout (location = 1) in vec3 VertexNormal;<br /><br />out vec3 LightIntensity;<br /><br />struct LightInfo {<br />  vec4 Position; // Light position in eye coords.<br />  vec3 La; // Ambient light intensity<br />  vec3 Ld; // Diffuse light intensity<br />  vec3 Ls; // Specular light intensity<br />};<br />uniform LightInfo Light;<br /><br />struct MaterialInfo {<br />  vec3 Ka; // Ambient reflectivity<br />  vec3 Kd; // Diffuse reflectivity<br />  vec3 Ks; // Specular reflectivity<br />  float Shininess; // Specular shininess factor<br />};<br />uniform MaterialInfo Material;<br /><br />uniform mat4 ModelViewMatrix;<br />uniform mat3 NormalMatrix;<br />uniform mat4 ProjectionMatrix;<br />uniform mat4 MVP;<br /><br />void getEyeSpace( out vec3 norm, out vec4 position )<br />{<br />  norm = normalize( NormalMatrix * VertexNormal);<br />  position = ModelViewMatrix * vec4(VertexPosition,1.0);<br />}<br /><br />subroutine( shadeModelType )<br /><br />vec3 phongModel( vec4 position, vec3 norm )<br />{<br />  // The ADS shading calculations go here (see: "Using<br />  // functions in shaders," and "Implementing<br />  // per-vertex ambient, diffuse and specular (ADS) shading")<br />  ...<br />}<br /><br />subroutine( shadeModelType )<br /><br />vec3 diffuseOnly( vec4 position, vec3 norm )<br />{<br />  vec3 s = normalize( vec3(Light.Position - position) );<br />  return<br />	  Light.Ld * Material.Kd * max( dot(s, norm), 0.0 );<br />}<br /><br />void main()<br />{<br />  vec3 eyeNorm;<br />  vec4 eyePosition;<br /><br />  // Get the position and normal in eye space<br /><br />  getEyeSpace(eyeNorm, eyePosition);<br /><br />  // Evaluate the shading equation. This will call one of<br />  // the functions: diffuseOnly or phongModel.<br />  LightIntensity = shadeModel( eyePosition, eyeNorm );<br /><br />  gl_Position = MVP * vec4(VertexPosition,1.0);<br />}</pre><br />
<br />
Use the following code for the fragment shader:<br />
<pre class='prettyprint'>#version 400<br /><br />in vec3 LightIntensity;<br /><br />layout( location = 0 ) out vec4 FragColor;<br /><br />void main() {<br />FragColor = vec4(LightIntensity, 1.0);<br />}</pre><br />
<br />
In the OpenGL application, compile and link the above shaders into a shader program, and install the program into the OpenGL pipeline.<br />
<br />
Within the render function of the OpenGL application, use the following code:<br />
<pre class='prettyprint'>GLuint adsIndex =<br />glGetSubroutineIndex( programHandle,<br />					 GL_VERTEX_SHADER,"phongModel" );<br />GLuint diffuseIndex =<br />  glGetSubroutineIndex(programHandle,<br />					   GL_VERTEX_SHADER, "diffuseOnly");<br /><br />glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &adsIndex);<br />... // Render the left teapot<br /><br />glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &diffuseIndex);<br />... // Render the right teapot</pre><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How it works...</strong></span><br />
In this example, the subroutine is defined within the vertex shader. The first step involves declaring the subroutine type.<br />
<br />
<pre class='prettyprint'>subroutine vec3 shadeModelType( vec4 position,<br />					 vec3 normal);</pre><br />
<br />
This defines a new subroutine type with the name <em class='bbc'>shadeModelType</em>. The syntax is very similar to a function prototype, in that it defines a name, a parameter list, and a return type. As with function prototypes, the parameter names are optional.<br />
<br />
After creating the new subroutine type, we declare a uniform variable of that type named <em class='bbc'>shadeModel</em>.<br />
<br />
<pre class='prettyprint'>subroutine uniform shadeModelType shadeModel;</pre><br />
<br />
This variable serves as our function pointer and will be assigned to one of the two possible functions in the OpenGL application.<br />
<br />
We declare two functions to be part of the subroutine by prefixing their definition with the subroutine qualifier:<br />
<br />
<pre class='prettyprint'>subroutine ( shadeModelType )</pre><br />
<br />
This indicates that the function matches the subroutine type, and therefore its header must match the one in the subroutine type definition. We use this prefix for the definition of the functions <em class='bbc'>phongModel</em> and <em class='bbc'>diffuseOnly</em>. The <em class='bbc'>diffuseOnly</em> function computes the diffuse shading equation, and the <em class='bbc'>phongModel</em> function computes the complete ADS shading equation.<br />
<br />
We call one of the two subroutine functions by utilizing the subroutine uniform <em class='bbc'>shadeModel</em> within the main function.<br />
<br />
<pre class='prettyprint'>LightIntensity = shadeModel( eyePosition, eyeNorm );</pre><br />
<br />
Again, this call will be bound to one of the two functions depending on the value of the subroutine uniform <em class='bbc'>shadeModel</em>, which we will set within the OpenGL application.<br />
<br />
Within the render function of the OpenGL application, we assign a value to the subroutine uniform with the following steps. First, we query for the index of each subroutine function using <em class='bbc'>glGetSubroutineIndex</em>. The first argument is the program handle. The second is the shader stage. In this case, the subroutine is defined within the vertex shader, so we use <em class='bbc'>GL_VERTEX_SHADER</em> here. The third argument is the name of the subroutine. We query for each function individually and store the indexes in the variables <em class='bbc'>adsIndex</em> and <em class='bbc'>diffuseIndex</em>.<br />
<br />
To select the appropriate subroutine function, we need to set the value of the subroutine uniform <em class='bbc'>shadeModel</em>. To do so, we call <em class='bbc'>glUniformSubroutinesuiv</em>. This function is designed for setting multiple subroutine uniforms at once. In our case, of course, we are setting only a single uniform. The first argument is the shader stage (<em class='bbc'>GL_VERTEX_SHADER</em>), the second is the number of uniforms being set, and the third is a pointer to an array of subroutine function indexes. Since we are setting a single uniform, we simply provide the address of the <em class='bbc'>GLuint</em> variable containing the index, rather than a true array of values. Of course, we would use an array if multiple uniforms were being set. In general, the array of values provided as the third argument is assigned to subroutine uniform variables in the following way. The ith element of the array is assigned to the subroutine uniform variable with index <em class='bbc'>i</em>. Since we have provided only a single value, we are setting the subroutine uniform at index zero.<br />
<br />
You may be wondering, "How do we know that our subroutine uniform is located at index zero? We didn't query for the index before calling <em class='bbc'>glUniformSubroutinesuiv</em>!" The reason that this code works is that we are relying on the fact that OpenGL will always number the indexes of the subroutines consecutively starting at zero. If we had multiple subroutine uniforms, we could (and should) query for their indexes using <em class='bbc'>glGetSubroutineUniformLocation</em>, and then order our array appropriately.<br />
<br />
Finally, we select the <em class='bbc'>phongModel</em> function by setting the uniform to <em class='bbc'>adsIndex</em> and then render the left teapot. We then select the <em class='bbc'>diffuseOnly</em> function by setting the uniform to <em class='bbc'>diffuseIndex</em> and render the right teapot.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>There's more...</strong></span><br />
A subroutine function defined in a shader can match multiple subroutine types. In that case, the subroutine qualifier can contain a comma-separated list of subroutine types. For example, if a subroutine matched the types <em class='bbc'>type1</em> and <em class='bbc'>type2</em>, we could use the following qualifier:<br />
<br />
<pre class='prettyprint'>subroutine( type1, type2 )</pre><br />
<br />
This would allow us to use subroutine uniforms of differing types to refer to the same subroutine function.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
With subroutines we can implement the functionality of a conditional statement or shader swap without the computational overhead.]]></description>
		<pubDate>Fri, 03 Feb 2012 02:41:38 +0000</pubDate>
		<guid isPermaLink="false">83b7e1c6a22424f5b4c47bb30798b770</guid>
	</item>
	<item>
		<title>The Basics of GLSL 4.0 Shaders</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/the-basics-of-glsl-40-shaders-r2861</link>
		<description><![CDATA[Shaders give us the power to implement alternative rendering algorithms and a greater degree of flexibility in the implementation of those techniques. With shaders, we can run custom code directly on the GPU, providing us with the opportunity to leverage the high degree of parallelism available with modern GPUs.<br />
<br />
This article by <strong class='bbc'>David Wolff</strong>, author of <a href='http://www.packtpub.com/opengl-4-0-shading-language-cookbook/book/rk/opengl4-abr4/0811?utm_source=rk_opengl4_abr4_0811&utm_medium=content&utm_campaign=ramsai' class='bbc_url' title='External link' rel='nofollow external'>OpenGL 4.0 Shading Language Cookbook</a>, provides examples of basic shading techniques such as diffuse shading, two-sided shading, and flat shading. Specifically, we will cover:<br />
<ul class='bbc'><br /><li>Implementing diffuse, per-vertex shading with a single point light source<br /></li><li>Implementing per-vertex ambient, diffuse, and, specular (ADS) shading<br /></li><li>Using functions in shaders<br /></li><li>Implementing two sided shading<br /></li><li>Implementing flat shading<br /></li></ul><br />
<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Introduction</strong></span><br />
Shaders were first introduced into OpenGL in version 2.0, introducing programmability into the formerly fixed-function OpenGL pipeline. Shaders are implemented using the OpenGL Shading Language (GLSL). The GLSL is syntactically similar to C, which should make it easier for experienced OpenGL programmers to learn. Due to the nature of this text, I won't present a thorough introduction to GLSL here. Instead, if you're new to GLSL, reading through these recipes should help you to learn the language by example. If you are already comfortable with GLSL, but don't have experience with version 4.0, you'll see how to implement these techniques utilizing the newer API. However, before we jump into GLSL programming, let's take a quick look at how vertex and fragment shaders fit within the OpenGL pipeline.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Vertex and fragment shaders</strong></span><br />
In OpenGL version 4.0, there are five shader stages: vertex, geometry, tessellation control, tessellation evaluation, and fragment. In this article we'll focus only on the vertex and fragment stages.<br />
<br />
Shaders replace parts of the OpenGL pipeline. More specifically, they make those parts of the pipeline programmable. The following block diagram shows a simplified view of the OpenGL pipeline with only the vertex and fragment shaders installed.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_01.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
Vertex data is sent down the pipeline and arrives at the vertex shader via shader input variables. The vertex shader's input variables correspond to vertex attributes (see <a href='http://www.packtpub.com/article/tips-tricks-getting-started-with-opengl-glsl-4' class='bbc_url' title='External link' rel='nofollow external'>Sending data to a shader using per-vertex attributes and vertex buffer objects</a>). In general, a shader receives its input via programmer-defined input variables, and the data for those variables comes either from the main OpenGL application or previous pipeline stages (other shaders). For example, a fragment shader's input variables might be fed from the output variables of the vertex shader. Data can also be provided to any shader stage using uniform variables (see <a href='http://www.packtpub.com/article/opengl-glsl-4-using-uniform-blocks-buffer-objects' class='bbc_url' title='External link' rel='nofollow external'>Sending data to a shader using uniform variables</a>). These are used for information that changes less often than vertex attributes (for example, matrices, light position, and other settings). The following figure shows a simplified view of the relationships between input and output variables when there are two shaders active (vertex and fragment).<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_02.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The vertex shader is executed once for each vertex, possibly in parallel. The data corresponding to vertex position must be transformed into clip coordinates and assigned to the output variable <em class='bbc'>gl_Position</em> before the vertex shader finishes execution. The vertex shader can send other information down the pipeline using shader output variables. For example, the vertex shader might also compute the color associated with the vertex. That color would be passed to later stages via an appropriate output variable.<br />
<br />
Between the vertex and fragment shader, the vertices are assembled into primitives, clipping takes place, and the viewport transformation is applied (among other operations). The rasterization process then takes place and the polygon is filled (if necessary). The fragment shader is executed once for each fragment (pixel) of the polygon being rendered (typically in parallel). Data provided from the vertex shader is (by default) interpolated in a perspective correct manner, and provided to the fragment shader via shader input variables. The fragment shader determines the appropriate color for the pixel and sends it to the frame buffer using output variables. The depth information is handled automatically.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Replicating the old fixed functionality</strong></span><br />
Programmable shaders give us tremendous power and flexibility. However, in some cases we might just want to re-implement the basic shading techniques that were used in the default fixed-function pipeline, or perhaps use them as a basis for other shading techniques. Studying the basic shading algorithm of the old fixed-function pipeline can also be a good way to get started when learning about shader programming.<br />
<br />
In this article, we'll look at the basic techniques for implementing shading similar to that of the old fixed-function pipeline. We'll cover the standard ambient, diffuse, and specular (ADS) shading algorithm, the implementation of two-sided rendering, and flat shading. in the next article, we'll also see some examples of other GLSL features such as <a href='http://www.packtpub.com/article/opengl-glsl-4-using-subroutines-select-shader-functionality' class='bbc_url' title='External link' rel='nofollow external'>functions, subroutines</a>, and the <a href='http://www.packtpub.com/article/opengl-glsl-4-discarding-fragments-create-perforated-look' class='bbc_url' title='External link' rel='nofollow external'>discard</a> keyword.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Implementing diffuse, per-vertex shading with a single point light source</strong></span><br />
One of the simplest shading techniques is to assume that the surface exhibits purely diffuse reflection. That is to say that the surface is one that appears to scatter light in all directions equally, regardless of direction. Incoming light strikes the surface and penetrates slightly before being re-radiated in all directions. Of course, the incoming light interacts with the surface before it is scattered, causing some wavelengths to be fully or partially absorbed and others to be scattered. A typical example of a diffuse surface is a surface that has been painted with a matte paint. The surface has a dull look with no shine at all.<br />
<br />
The following image shows a torus rendered with diffuse shading.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_03.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The mathematical model for diffuse reflection involves two vectors: the direction from the surface point to the light source (<strong class='bbc'>s</strong>), and the normal vector at the surface point (<strong class='bbc'>n</strong>). The vectors are represented in the following diagram.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_04.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The amount of incoming light (or radiance) that reaches the surface is partially dependent on the orientation of the surface with respect to the light source. The physics of the situation tells us that the amount of radiation that reaches a point on a surface is maximal when the light arrives along the direction of the normal vector, and zero when the light is perpendicular to the normal. In between, it is proportional to the cosine of the angle between the direction towards the light source and the normal vector. So, since the dot product is proportional to the cosine of the angle between two vectors, we can express the amount of radiation striking the surface as the product of the light intensity and the dot product of <strong class='bbc'>s</strong> and <strong class='bbc'>n</strong>.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_05.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
Where L<sub class='bbc'>d</sub> is the intensity of the light source, and the vectors <strong class='bbc'>s</strong> and <strong class='bbc'>n</strong> are assumed to be normalized. You may recall that the dot product of two unit vectors is equal to the cosine of the angle between them.<br />
<br />
As stated previously, some of the incoming light is absorbed before it is re-emitted. We can model this interaction by using a reflection coefficient (K<sub class='bbc'>d</sub>), which represents the fraction of the incoming light that is scattered. This is sometimes referred to as the <strong class='bbc'>diffuse reflectivity</strong>, or the diffuse reflection coefficient. The diffuse reflectivity becomes a scaling factor for the incoming radiation, so the intensity of the outgoing light can be expressed as follows:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_06.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
Because this model depends only on the direction towards the light source and the normal to the surface, not on the direction towards the viewer, we have a model that represents uniform (omnidirectional) scattering.<br />
<br />
In this recipe, we'll evaluate this equation at each vertex in the vertex shader and interpolate the resulting color across the face.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'>In this and the following recipes, light intensities and material reflectivity coefficients are represented by 3-component (RGB) vectors. Therefore, the equations should be treated as component-wise operations, applied to each of the three components separately. Luckily, the GLSL will make this nearly transparent because the needed operators will operate component-wise on vector variables.</em></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Getting ready</strong></span><br />
Start with an OpenGL application that provides the vertex position in attribute location 0, and the vertex normal in attribute location 1 (see <a href='http://www.packtpub.com/article/tips-tricks-getting-started-with-opengl-glsl-4' class='bbc_url' title='External link' rel='nofollow external'>Sending data to a shader using per-vertex attributes and vertex buffer objects</a>). The OpenGL application also should provide the standard transformation matrices (projection, modelview, and normal) via uniform variables.<br />
<br />
The light position (in eye coordinates), <em class='bbc'>Kd</em>, and <em class='bbc'>Ld</em> should also be provided by the OpenGL application via uniform variables. Note that <em class='bbc'>Kd</em> and <em class='bbc'>Ld</em> are type vec3. We can use a <em class='bbc'>vec3</em> to store an RGB color as well as a vector or point.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How to do it...</strong></span><br />
To create a shader pair that implements diffuse shading, use the following code:<br />
<ul class='bbcol decimal'><br /><li>Use the following code for the vertex shader.<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	layout (location = 0) in vec3 VertexPosition;<br />	layout (location = 1) in vec3 VertexNormal;<br />	<br />	out vec3 LightIntensity;<br />	<br />	uniform vec4 LightPosition; // Light position in eye coords.<br />	uniform vec3 Kd; // Diffuse reflectivity<br />	uniform vec3 Ld; // Light source intensity<br />	<br />	uniform mat4 ModelViewMatrix;<br />	uniform mat3 NormalMatrix;<br />	uniform mat4 ProjectionMatrix;<br />	uniform mat4 MVP; // Projection * ModelView<br />	<br />	void main()<br />	{<br />	  // Convert normal and position to eye coords<br />	  vec3 tnorm = normalize( NormalMatrix * VertexNormal);<br />	  vec4 eyeCoords = ModelViewMatrix *<br />					   vec4(VertexPosition,1.0));<br />	  vec3 s = normalize(vec3(LightPosition - eyeCoords));<br />	<br />	  // The diffuse shading equation<br />	  LightIntensity = Ld * Kd * max( dot( s, tnorm ), 0.0 );<br />	<br />	  // Convert position to clip coordinates and pass along<br />	  gl_Position = MVP * vec4(VertexPosition,1.0);<br />	}	<br />	</pre><br /></li><li>Use the following code for the fragment shader.<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	in vec3 LightIntensity;<br />	<br />	layout( location = 0 ) out vec4 FragColor;<br />	<br />	void main() {<br />		FragColor = vec4(LightIntensity, 1.0);<br />	}	<br />	</pre><br /></li><li>Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering. See <a href='http://www.packtpub.com/article/tips-tricks-getting-started-with-opengl-glsl-4' class='bbc_url' title='External link' rel='nofollow external'>Tips and Tricks for Getting Started with OpenGL and GLSL 4.0</a> for details about compiling, linking, and installing shaders.<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>How it works...</strong></span><br />
The vertex shader does all of the work in this example. The diffuse reflection is computed in eye coordinates by first transforming the normal vector using the normal matrix, normalizing, and storing the result in <em class='bbc'>tnorm</em>. Note that the normalization here may not be necessary if your normal vectors are already normalized and the normal matrix does not do any scaling.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'>The normal matrix is typically the inverse transpose of the upper-left 3x3 portion of the model-view matrix. We use the inverse transpose because normal vectors transform differently than the vertex position. For a more thorough discussion of the normal matrix, and the reasons why, see any introductory computer graphics textbook. (A good choice would be Computer Graphics with OpenGL by Hearn and Baker.) If your model-view matrix does not include any non-uniform scalings, then one can use the upper-left 3x3 of the model-view matrix in place of the normal matrix to transform your normal vectors. However, if your model-view matrix does include (uniform) scalings, you'll still need to (re)normalize your normal vectors after transforming them.</em></p><br />
<br />
The next step converts the vertex position to eye (camera) coordinates by transforming it via the model-view matrix. Then we compute the direction towards the light source by subtracting the vertex position from the light position and storing the result in s.<br />
<br />
Next, we compute the scattered light intensity using the equation described above and store the result in the output variable <em class='bbc'>LightIntensity</em>. Note the use of the <em class='bbc'>max</em> function here. If the dot product is less than zero, then the angle between the normal vector and the light direction is greater than 90 degrees. This means that the incoming light is coming from inside the surface. Since such a situation is not physically possible (for a closed mesh), we use a value of 0.0. However, you may decide that you want to properly light both sides of your surface, in which case the normal vector needs to be reversed for those situations where the light is striking the back side of the surface (see <em class='bbc'>Implementing two-sided shading</em>).<br />
<br />
Finally, we convert the vertex position to clip coordinates by multiplying with the model-view projection matrix, (which is: <em class='bbc'>projection * view * model</em>) and store the result in the built-in output variable <em class='bbc'>gl_Position</em>.<br />
<br />
<pre class='prettyprint'><br />gl_Position = MVP * vec4(VertexPosition,1.0);<br /><br /></pre><br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'>The subsequent stage of the OpenGL pipeline expects that the vertex position will be provided in clip coordinates in the output variable gl_Position. This variable does not directly correspond to any input variable in the fragment shader, but is used by the OpenGL pipeline in the primitive assembly, clipping, and rasterization stages that follow the vertex shader. It is important that we always provide a valid value for this variable.</em></p><br />
<br />
Since <em class='bbc'>LightIntensity</em> is an output variable from the vertex shader, its value is interpolated across the face and passed into the fragment shader. The fragment shader then simply assigns the value to the output fragment.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>There's more...</strong></span><br />
Diffuse shading is a technique that models only a very limited range of surfaces. It is best used for surfaces that have a "matte" appearance. Additionally, with the technique used above, the dark areas may look a bit too dark. In fact, those areas that are not directly illuminated are completely black. In real scenes, there is typically some light that has been reflected about the room that brightens these surfaces. In the following recipes, we'll look at ways to model more surface types, as well as provide some light for those dark parts of the surface.<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Implementing per-vertex ambient, diffuse, and specular (ADS) shading</strong></span><br />
The OpenGL fixed function pipeline implemented a default shading technique which is very similar to the one presented here. It models the light-surface interaction as a combination of three components: ambient, diffuse, and specular. The <strong class='bbc'>ambient</strong> component is intended to model light that has been reflected so many times that it appears to be emanating uniformly from all directions. The <strong class='bbc'>diffuse</strong> component was discussed in the previous recipe, and represents omnidirectional reflection. The <strong class='bbc'>specular</strong> component models the shininess of the surface and represents reflection around a preferred direction. Combining these three components together can model a nice (but limited) variety of surface types. This shading model is also sometimes called the <strong class='bbc'>Phong reflection model</strong> (or <strong class='bbc'>Phong shading model</strong>), after Bui Tuong Phong.<br />
<br />
An example of a torus rendered with the ADS shading model is shown in the following screenshot:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_07.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The ADS model is implemented as the sum of the three components: ambient, diffuse, and specular. The ambient component represents light that illuminates all surfaces equally and reflects equally in all directions. It is often used to help brighten some of the darker areas within a scene. Since it does not depend on the incoming or outgoing directions of the light, it can be modeled simply by multiplying the light source intensity (L<sub class='bbc'>a</sub>) by the surface reflectivity (K<sub class='bbc'>a</sub>).<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_08.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The diffuse component models a rough surface that scatters light in all directions (see <em class='bbc'>Implementing diffuse per-vertex shading with a single point light source</em> above). The intensity of the outgoing light depends on the angle between the surface normal and the vector towards the light source.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_09.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The specular component is used for modeling the shininess of a surface. When a surface has a glossy shine to it, the light is reflected off of the surface in a mirror-like fashion. The reflected light is strongest in the direction of perfect (mirror-like) reflection. The physics of the situation tells us that for perfect reflection, the angle of incidence is the same as the angle of reflection and that the vectors are coplanar with the surface normal, as shown in the following diagram:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_10.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In the preceding diagram, r represents the vector of pure-reflection corresponding to the incoming light vector (<strong class='bbc'>-s</strong>), and n is the surface normal. We can compute <strong class='bbc'>r</strong> by using the following equation:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_11.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
To model specular reflection, we need to compute the following (normalized) vectors: the direction towards the light source (<strong class='bbc'>s</strong>), the vector of perfect reflection (<strong class='bbc'>r</strong>), the vector towards the viewer (<strong class='bbc'>v</strong>), and the surface normal (<strong class='bbc'>n</strong>). These vectors are represented in the following image:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_12.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
We would like the reflection to be maximal when the viewer is aligned with the vector <strong class='bbc'>r</strong>, and to fall off quickly as the viewer moves further away from alignment with <strong class='bbc'>r</strong>. This can be modeled using the cosine of the angle between <strong class='bbc'>v</strong> and <strong class='bbc'>r</strong> raised to some power (f).<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_13.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
(Recall that the dot product is proportional to the cosine of the angle between the vectors involved.) The larger the power, the faster the value drops towards zero as the angle between <strong class='bbc'>v</strong> and <strong class='bbc'>r</strong> increases. Again, similar to the other components, we also introduce a specular light intensity term (L<sub class='bbc'>s</sub>) and reflectivity term (K<sub class='bbc'>s</sub>).<br />
<br />
The specular component creates <strong class='bbc'>specular highlights</strong> (bright spots) that are typical of glossy surfaces. The larger the power of f in the equation, the smaller the specular highlight and the shinier the surface appears. The value for f is typically chosen to be somewhere between 1 and 200.<br />
<br />
Putting all of this together, we have the following shading equation:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_14.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In the following code, we'll evaluate this equation in the vertex shader, and interpolate the color across the polygon.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Getting ready</strong></span><br />
In the OpenGL application, provide the vertex position in location 0 and the vertex normal in location 1. The light position and the other configurable terms for our lighting equation are uniform variables in the vertex shader and their values must be set from the OpenGL application.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How to do it...</strong></span><br />
To create a shader pair that implements ADS shading, use the following code:<br />
<ul class='bbcol decimal'><br /><li>Use the following code for the vertex shader:<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	layout (location = 0) in vec3 VertexPosition;<br />	layout (location = 1) in vec3 VertexNormal;<br />	<br />	out vec3 LightIntensity;<br />	<br />	struct LightInfo {<br />	  vec4 Position; // Light position in eye coords.<br />	  vec3 La; // Ambient light intensity<br />	  vec3 Ld; // Diffuse light intensity<br />	  vec3 Ls; // Specular light intensity<br />	};<br />	uniform LightInfo Light;<br />	<br />	struct MaterialInfo {<br />	  vec3 Ka; // Ambient reflectivity<br />	  vec3 Kd; // Diffuse reflectivity<br />	  vec3 Ks; // Specular reflectivity<br />	  float Shininess; // Specular shininess factor<br />	};<br />	uniform MaterialInfo Material;<br />	<br />	uniform mat4 ModelViewMatrix;<br />	uniform mat3 NormalMatrix;<br />	uniform mat4 ProjectionMatrix;<br />	uniform mat4 MVP;<br />	<br />	void main()<br />	{<br />	  vec3 tnorm = normalize( NormalMatrix * VertexNormal);<br />	  vec4 eyeCoords = ModelViewMatrix *<br />					   vec4(VertexPosition,1.0);<br />	  vec3 s = normalize(vec3(Light.Position - eyeCoords));<br />	  vec3 v = normalize(-eyeCoords.xyz);<br />	  vec3 r = reflect( -s, tnorm );<br />	  vec3 ambient = Light.La * Material.Ka;<br />	  float sDotN = max( dot(s,tnorm), 0.0 );<br />	  vec3 diffuse = Light.Ld * Material.Kd * sDotN;<br />	  vec3 spec = vec3(0.0);<br />	  if( sDotN &gt; 0.0 )<br />		spec = Light.Ls * Material.Ks *<br />			   pow( max( dot(r,v), 0.0 ), Material.Shininess );<br />	<br />	  LightIntensity = ambient + diffuse + spec;<br />	  gl_Position = MVP * vec4(VertexPosition,1.0);<br />	}	<br />	</pre><br /></li><li>Use the following code for the fragment shader:<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	in vec3 LightIntensity;<br />	<br />	layout( location = 0 ) out vec4 FragColor;<br />	<br />	void main() {<br />		FragColor = vec4(LightIntensity, 1.0);<br />	}	<br />	</pre><br /></li><li>Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering.<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>How it works...</strong></span><br />
The vertex shader computes the shading equation in eye coordinates. It begins by transforming the vertex normal into eye coordinates and normalizing, then storing the result in <em class='bbc'>tnorm</em>. The vertex position is then transformed into eye coordinates and stored in <em class='bbc'>eyeCoords</em>.<br />
<br />
Next, we compute the normalized direction towards the light source (s). This is done by subtracting the vertex position in eye coordinates from the light position and normalizing the result.<br />
<br />
The direction towards the viewer (<em class='bbc'>v</em>) is the negation of the position (normalized) because in eye coordinates the viewer is at the origin.<br />
<br />
We compute the direction of pure reflection by calling the GLSL built-in function <em class='bbc'>reflect</em>, which reflects the first argument about the second. We don't need to normalize the result because the two vectors involved are already normalized.<br />
<br />
The ambient component is computed and stored in the variable <em class='bbc'>ambient</em>. The dot product of <em class='bbc'>s</em> and <em class='bbc'>n</em> is computed next. As in the preceding recipe, we use the built-in function max to limit the range of values to between one and zero. The result is stored in the variable named <em class='bbc'>sDotN</em>, and is used to compute the diffuse component. The resulting value for the diffuse component is stored in the variable <em class='bbc'>diffuse</em>. Before computing the specular component, we check the value of <em class='bbc'>sDotN</em>. If <em class='bbc'>sDotN</em> is zero, then there is no light reaching the surface, so there is no point in computing the specular component, as its value must be zero. Otherwise, if <em class='bbc'>sDotN</em> is greater than zero, we compute the specular component using the equation presented earlier. Again, we use the built-in function <em class='bbc'>max</em> to limit the range of values of the dot product to between one and zero, and the function <em class='bbc'>pow</em> raises the dot product to the power of the <em class='bbc'>Shininess</em> exponent (corresponding to f in our lighting equation).<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'>If we did not check sDotN before computing the specular component, it is possible that some specular highlights could appear on faces that are facing away from the light source. This is clearly a non-realistic and undesirable result. Some people solve this problem by multiplying the specular component by the diffuse component, which would decrease the specular component substantially and alter its color. The solution presented here avoids this, at the cost of a branch statement (the if statement).</em></p><br />
<br />
The sum of the three components is then stored in the output variable <em class='bbc'>LightIntensity</em>. This value will be associated with the vertex and passed down the pipeline. Before reaching the fragment shader, its value will be interpolated in a perspective correct manner across the face of the polygon.<br />
<br />
Finally, the vertex shader transforms the position into clip coordinates, and assigns the result to the built-in output variable <em class='bbc'>gl_Position</em> (see <em class='bbc'>Implementing diffuse, per-vertex shading with a single point light source</em>).<br />
<br />
The fragment shader simply applies the interpolated value of <em class='bbc'>LightIntensity</em> to the output fragment by storing it in the shader output variable <em class='bbc'>FragColor</em>.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>There's more...</strong></span><br />
This version of the ADS (Ambient, Diffuse, and Specular) reflection model is by no means optimal. There are several improvements that could be made. For example, the computation of the vector of pure reflection can be avoided via the use of the so-called "halfway vector".<br />
<br />
<strong class='bbc'>	Using a non-local viewer</strong><br />
<br />
We can avoid the extra normalization needed to compute the vector towards the viewer (v), by using a so-called <strong class='bbc'>non-local viewer</strong>. Instead of computing the direction towards the origin, we simply use the constant vector (0, 0, 1) for all vertices. This is similar to assuming that the viewer is located infinitely far away in the z direction. Of course, it is not accurate, but in practice the visual results are very similar, often visually indistinguishable, saving us normalization.<br />
<br />
In the old fixed-function pipeline, the non-local viewer was the default, and could be adjusted (turned on or off) using the function <em class='bbc'>glLightModel</em>.<br />
<br />
<strong class='bbc'>	Per-vertex vs. Per-fragment</strong><br />
<br />
Since the shading equation is computed within the vertex shader, we refer to this as <strong class='bbc'>per-vertex lighting</strong>. One of the disadvantages of per-vertex lighting is that specular highlights can be warped or lost, due to the fact that the shading equation is not evaluated at each point across the face. For example, a specular highlight that should appear in the middle of a polygon might not appear at all when per-vertex lighting is used, because of the fact that the shading equation is only computed at the vertices where the specular component is near zero.<br />
<br />
<strong class='bbc'>	Directional lights</strong><br />
<br />
We can also avoid the need to compute a light direction (s), for each vertex if we assume a directional light. A <strong class='bbc'>directional light source</strong> is one that can be thought of as located infinitely far away in a given direction. Instead of computing the direction towards the source for each vertex, a constant vector is used, which represents the direction towards the remote light source.<br />
<br />
<strong class='bbc'>	Light attenuation with distance</strong><br />
<br />
You might think that this shading model is missing one important component. It doesn't take into account the effect of the distance to the light source. In fact, it is known that the intensity of radiation from a source falls off in proportion to the inverse square of the distance from the source. So why not include this in our model?<br />
<br />
It would be fairly simple to do so, however, the visual results are often less than appealing. It tends to exaggerate the distance effects and create unrealistic looking images. Remember, our equation is just an approximation of the physics involved and is not a truly realistic model, so it is not surprising that adding a term based on a strict physical law produces unrealistic results.<br />
<br />
In the OpenGL fixed-function pipeline, it was possible to turn on distance attenuation using the <em class='bbc'>glLight</em> function. If desired, it would be straightforward to add a few uniform variables to our shader to produce the same effect.<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Using functions in shaders</strong></span><br />
The GLSL supports functions that are syntactically similar to C functions. However, the calling conventions are somewhat different. In this example, we'll revisit the ADS shader using functions to help provide abstractions for the major steps.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Getting ready</strong></span><br />
As with previous recipes, provide the vertex position at attribute location 0 and the vertex normal at attribute location 1. Uniform variables for all of the ADS coefficients should be set from the OpenGL side, as well as the light position and the standard matrices.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How to do it...</strong></span><br />
To implement ADS shading using functions, use the following code:<br />
<ul class='bbcol decimal'><br /><li>Use the following vertex shader:<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	layout (location = 0) in vec3 VertexPosition;<br />	layout (location = 1) in vec3 VertexNormal;<br />	<br />	out vec3 LightIntensity;<br />	<br />	struct LightInfo {<br />	  vec4 Position; // Light position in eye coords.<br />	  vec3 La; // Ambient light intensity<br />	  vec3 Ld; // Diffuse light intensity<br />	  vec3 Ls; // Specular light intensity<br />	};<br />	uniform LightInfo Light;<br />	<br />	struct MaterialInfo {<br />	  vec3 Ka; // Ambient reflectivity<br />	  vec3 Kd; // Diffuse reflectivity<br />	  vec3 Ks; // Specular reflectivity<br />	  float Shininess; // Specular shininess factor<br />	};<br />	uniform MaterialInfo Material;<br />	<br />	uniform mat4 ModelViewMatrix;<br />	uniform mat3 NormalMatrix;<br />	uniform mat4 ProjectionMatrix;<br />	uniform mat4 MVP;<br />	<br />	void getEyeSpace( out vec3 norm, out vec4 position )<br />	{<br />	  norm = normalize( NormalMatrix * VertexNormal);<br />	  position = ModelViewMatrix * vec4(VertexPosition,1.0);<br />	}<br />	<br />	vec3 phongModel( vec4 position, vec3 norm )<br />	{<br />	  vec3 s = normalize(vec3(Light.Position - position));<br />	  vec3 v = normalize(-position.xyz);<br />	  vec3 r = reflect( -s, norm );<br />	  vec3 ambient = Light.La * Material.Ka;<br />	  float sDotN = max( dot(s,norm), 0.0 );<br />	  vec3 diffuse = Light.Ld * Material.Kd * sDotN;<br />	  vec3 spec = vec3(0.0);<br />	  if( sDotN &gt; 0.0 )<br />		  spec = Light.Ls * Material.Ks *<br />				 pow( max( dot(r,v), 0.0 ), Material.Shininess );<br />	  return ambient + diffuse + spec;<br />	}<br />	<br />	void main()<br />	{<br />	  vec3 eyeNorm;<br />	  vec4 eyePosition;<br />	  // Get the position and normal in eye space<br />	  getEyeSpace(eyeNorm, eyePosition);<br />	  // Evaluate the lighting equation.<br />	  LightIntensity = phongModel( eyePosition, eyeNorm );<br />	  gl_Position = MVP * vec4(VertexPosition,1.0);<br />	}	<br />	</pre><br /></li><li>Use the following fragment shader:<br />	<pre class='prettyprint'>	<br />#version 400<br />	in vec3 LightIntensity;<br />	layout( location = 0 ) out vec4 FragColor;<br />	void main() {<br />		FragColor = vec4(LightIntensity, 1.0);<br />	}	<br />	</pre><br /></li><li>Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering.<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>How it works...</strong></span><br />
In GLSL functions, the evaluation strategy is "call by value-return" (also called "call by copyrestore" or "call by value-result"). Parameter variables can be qualified with <em class='bbc'>in</em>, <em class='bbc'>out</em>, or <em class='bbc'>inout</em>. Arguments corresponding to input parameters (those qualified with in or inout) are copied into the parameter variable at call time, and output parameters (those qualified with <em class='bbc'>out</em> or <em class='bbc'>inout</em>) are copied back to the corresponding argument before the function returns. If a parameter variable does not have any of the three qualifiers, the default qualifier is <em class='bbc'>in</em>.<br />
<br />
We've created two functions in the vertex shader. The first, named <em class='bbc'>getEyeSpace</em>, transforms the vertex position and vertex normal into eye space, and returns them via output parameters. In the <em class='bbc'>main</em> function, we create two uninitialized variables (<em class='bbc'>eyeNorm</em> and <em class='bbc'>eyePosition</em>) to store the results, and then call the function with the variables as the function's arguments. The function stores the results into the parameter variables (<em class='bbc'>norm</em> and <em class='bbc'>position</em>) which are copied into the arguments before the function returns.<br />
<br />
The second function, <em class='bbc'>phongModel</em>, uses only input parameters. The function receives the eye-space position and normal, and computes the result of the ADS shading equation. The result is returned by the function and stored in the shader output variable <em class='bbc'>LightIntensity</em>.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>There's more...</strong></span><br />
Since it makes no sense to read from an output parameter variable, output parameters should only be written to within the function. Their value is undefined.<br />
<br />
Within a function, writing to an input only parameter (qualified with <em class='bbc'>in</em>) is allowed. The function's copy of the argument is modified, and changes are not reflected in the argument.<br />
<br />
<strong class='bbc'>	The const qualifier</strong><br />
<br />
The additional qualifier <em class='bbc'>const</em> can be used with input-only parameters (not with <em class='bbc'>out</em> or <em class='bbc'>inout</em>). This qualifier makes the input parameter read-only, so it cannot be written to within the function.<br />
<br />
<strong class='bbc'>	Function overloading</strong><br />
<br />
Functions can be overloaded by creating multiple functions with the same name, but with different number and/or type of parameters. As with many languages, two overloaded functions may not differ in return type only.<br />
<br />
<strong class='bbc'>	Passing arrays or structures to a function</strong><br />
<br />
It should be noted that when passing arrays or structures to functions, they are passed by value. If a large array or structure is passed, it can incur a large copy operation which may not be desired. It would be a better choice to declare these variables in the global scope.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Implementing two-sided shading</strong></span><br />
When rendering a mesh that is completely closed, the back faces of polygons are hidden. However, if a mesh contains holes, it might be the case that the back faces would become visible. In this case, the polygons may be shaded incorrectly due to the fact that the normal vector is pointing in the wrong direction. To properly shade those back faces, one needs to invert the normal vector and compute the lighting equations based on the inverted normal.<br />
<br />
The following image shows a teapot with the lid removed. On the left, the ADS lighting model is used. On the right, the ADS model is augmented with the two-sided rendering technique discussed in this recipe.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_15.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In this recipe, we'll look at an example that uses the ADS model discussed in the previous recipes, augmented with the ability to correctly shade back faces.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Getting ready</strong></span><br />
The vertex position should be provided in attribute location 0 and the vertex normal in attribute location 1. As in previous examples, the lighting parameters must be provided to the shader via uniform variables.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How to do it...</strong></span><br />
To implement a shader pair that uses the ADS shading model with two-sided lighting, use the following code:<br />
<ul class='bbcol decimal'><br /><li>Use the following code for the vertex shader:<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	layout (location = 0) in vec3 VertexPosition;<br />	layout (location = 1) in vec3 VertexNormal;<br />	<br />	out vec3 FrontColor;<br />	out vec3 BackColor;<br />	<br />	struct LightInfo {<br />	  vec4 Position; // Light position in eye coords.<br />	  vec3 La; // Ambient light intensity<br />	  vec3 Ld; // Diffuse light intensity<br />	  vec3 Ls; // Specular light intensity<br />	};<br />	uniform LightInfo Light;<br />	<br />	struct MaterialInfo {<br />	  vec3 Ka; // Ambient reflectivity<br />	  vec3 Kd; // Diffuse reflectivity<br />	  vec3 Ks; // Specular reflectivity<br />	  float Shininess; // Specular shininess factor<br />	};<br />	uniform MaterialInfo Material;<br />	<br />	uniform mat4 ModelViewMatrix;<br />	uniform mat3 NormalMatrix;<br />	uniform mat4 ProjectionMatrix;<br />	uniform mat4 MVP;<br />	<br />	vec3 phongModel( vec4 position, vec3 normal ) {<br />	  // The ADS shading calculations go here (see: "Using<br />	  // functions in shaders," and "Implementing<br />	  // per-vertex ambient, diffuse and specular (ADS) shading")<br />	  ...<br />	}<br />	<br />	void main()<br />	{<br />	  vec3 tnorm = normalize( NormalMatrix * VertexNormal);<br />	  vec4 eyeCoords = ModelViewMatrix *<br />					   vec4(VertexPosition,1.0);<br />	<br />	  FrontColor = phongModel( eyeCoords, tnorm );<br />	<br />	  BackColor = phongModel( eyeCoords, -tnorm );<br />	<br />	  gl_Position = MVP * vec4(VertexPosition,1.0);<br />	}	<br />	</pre><br /></li><li>Use the following for the fragment shader:<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	in vec3 FrontColor;<br />	in vec3 BackColor;<br />	<br />	layout( location = 0 ) out vec4 FragColor;<br />	<br />	void main() {<br />	<br />	  if( gl_FrontFacing ) {<br />		  FragColor = vec4(FrontColor, 1.0);<br />	  } else {<br />		  FragColor = vec4(BackColor, 1.0);<br />	  }<br />	}	<br />	</pre><br /></li><li>Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering.<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>How it works...</strong></span><br />
In the vertex shader, we compute the lighting equation using both the vertex normal and the inverted version, and pass each resultant color to the fragment shader. The fragment shader chooses and applies the appropriate color depending on the orientation of the face.<br />
<br />
The vertex shader is a slightly modified version of the vertex shader presented in the recipe <em class='bbc'>Implementing per-vertex ambient, diffuse, and specular (ADS) shading</em>. The evaluation of the shading model is placed within a function named <em class='bbc'>phongModel</em>. The function is called twice, first using the normal vector (transformed into eye coordinates), and second using the inverted normal vector. The combined results are stored in <em class='bbc'>FrontColor</em> and <em class='bbc'>BackColor</em>, respectively.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'>Note that there are a few aspects of the shading model that are independent of the orientation of the normal vector (such as the ambient component). One could optimize this code by rewriting it so that the redundant calculations are only done once. However, in this recipe we compute the entire shading model twice in the interest of making things clear and readable.</em></p><br />
<br />
In the fragment shader, we determine which color to apply based on the value of the built-in variable <em class='bbc'>gl_FrontFacing</em>. This is a Boolean value that indicates whether the fragment is part of a front or back facing polygon. Note that this determination is based on the <strong class='bbc'>winding</strong> of the polygon, and not the normal vector. (A polygon is said to have counter-clockwise winding if the vertices are specified in counter-clockwise order as viewed from the front side of the polygon.) By default when rendering, if the order of the vertices appear on the screen in a counter-clockwise order, it indicates a front facing polygon, however, we can change this by calling <em class='bbc'>glFrontFace</em> from the OpenGL program.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>There's more...</strong></span><br />
In the vertex shader we determine the front side of the polygon by the direction of the normal vector, and in the fragment shader, the determination is based on the polygon's winding. For this to work properly, the normal vector must be defined appropriately for the face determined by the setting of <em class='bbc'>glFrontFace</em>.<br />
<br />
<strong class='bbc'>	Using two-sided rendering for debugging</strong><br />
<br />
It can sometimes be useful to visually determine which faces are front facing and which are back facing. For example, when working with arbitrary meshes, polygons may not be specified using the appropriate winding. As another example, when developing a mesh procedurally, it can sometimes be helpful to determine which faces are oriented in the proper direction in order to help with debugging. We can easily tweak our fragment shader to help us solve these kinds of problems by mixing a solid color with all back (or front) faces. For example, we could change the <em class='bbc'>else</em> clause within our fragment shader to the following:<br />
<br />
<pre class='prettyprint'><br />FragColor = mix( vec4(BackColor,1.0),<br />				vec4(1.0,0.0,0.0,1.0), 0.7 );<br /><br /></pre><br />
This would mix a solid red color with all back faces, helping them to stand out, as shown in the following image. In the image, back faces are mixed with 70% red as shown in the preceding code.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Implementing flat shading</strong></span><br />
Per-vertex shading involves computation of the shading model at each vertex and associating the result (a color) with that vertex. The colors are then interpolated across the face of the polygon to produce a smooth shading effect. This is also referred to as <strong class='bbc'>Gouraud shading</strong>. In earlier versions of OpenGL, this per-vertex shading with color interpolation was the default shading technique.<br />
<br />
It is sometimes desirable to use a single color for each polygon so that there is no variation of color across the face of the polygon, causing each polygon to have a flat appearance. This can be useful in situations where the shape of the object warrants such a technique, perhaps because the faces really are intended to look flat, or to help visualize the locations of the polygons in a complex mesh. Using a single color for each polygon is commonly called <strong class='bbc'>flat shading</strong>.<br />
<br />
The images below show a mesh rendered with the ADS shading model. On the left, Gouraud shading is used. On the right, flat shading is used.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_02_16.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In earlier versions of OpenGL, flat shading was enabled by calling the function <em class='bbc'>glShadeModel</em> with the argument <em class='bbc'>GL_FLAT</em>. In which case, the computed color of the last vertex of each polygon was used across the entire face.<br />
<br />
In OpenGL 4.0, flat shading is facilitated by the interpolation qualifiers available for shader input/output variables.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>How to do it...</strong></span><br />
To modify the ADS shading model to implement flat shading, use the following steps:<br />
<ul class='bbcol decimal'><br /><li>Use the same vertex shader as in the ADS example provided earlier. Change the output variable <em class='bbc'>LightIntensity</em> as follows:<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	layout (location = 0) in vec3 VertexPosition;<br />	layout (location = 1) in vec3 VertexNormal;<br />	<br />	flat out vec3 LightIntensity;<br />	<br />	// the rest is identical to the ADS shader...	<br />	</pre><br /></li><li>Use the following code for the fragment shader:<br />	<pre class='prettyprint'>	<br />#version 400<br />	<br />	flat in vec3 LightIntensity;<br />	<br />	layout( location = 0 ) out vec4 FragColor;<br />	<br />	void main() {<br />		FragColor = vec4(LightIntensity, 1.0);<br />	}	<br />	</pre><br /></li><li>Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering.<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>How it works...</strong></span><br />
Flat shading is enabled by qualifying the vertex output variable (and its corresponding fragment input variable) with the <em class='bbc'>flat</em> qualifier. This qualifier indicates that no interpolation of the value is to be done before it reaches the fragment shader. The value presented to the fragment shader will be the one corresponding to the result of the invocation of the vertex shader for either the first or last vertex of the polygon. This vertex is called the <strong class='bbc'>provoking vertex</strong>, and can be configured using the OpenGL function <em class='bbc'>glProvokingVertex</em>. For example, the call:<br />
<br />
<pre class='prettyprint'><br />glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);<br /><br /></pre><br />
This indicates that the first vertex should be used as the value for the flat shaded variable. The argument <em class='bbc'>GL_LAST_VERTEX_CONVENTION</em> indicates that the last vertex should be used.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
This article provided examples of basic shading techniques such as diffuse shading, two-sided shading, and flat shading.]]></description>
		<pubDate>Fri, 27 Jan 2012 04:46:14 +0000</pubDate>
		<guid isPermaLink="false">75a84b531abe6e9fe5de743f134186ab</guid>
	</item>
	<item>
		<title>OpenGL 4.0: Using Uniform Blocks and Uniform Bu...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/opengl-40-using-uniform-blocks-and-uniform-bu-r2860</link>
		<description><![CDATA[If your OpenGL/GLSL program involves multiple shader programs that use the same uniform variables, one has to manage the variables separately for each program. Uniform blocks were designed to ease the sharing of uniform data between programs. In this article by <strong class='bbc'>David Wolff</strong>, author of <a href='http://www.packtpub.com/opengl-4-0-shading-language-cookbook/book/rk/opengl4-abr2/0811?utm_source=rk_opengl4_abr2_0811&utm_medium=content&utm_campaign=ramsai' class='bbc_url' title='External link' rel='nofollow external'>OpenGL 4.0 Shading Language Cookbook</a>, we will create a buffer object for storing the values of all the uniform variables, and bind the buffer to the uniform block. Then when changing programs, the same buffer object need only be re-bound to the corresponding block in the new program.<br />
<br />
Uniform locations are generated when a program is linked, so the locations of the uniforms may change from one program to the next. The data for those uniforms may have to be re-generated and applied to the new locations.<br />
<br />
A uniform block is simply a group of uniform variables defined within a syntactical structure known as a uniform block. For example, in this recipe, we'll use the following uniform block:<br />
<br />
<pre class='prettyprint'><br />uniform BlobSettings {<br />  vec4 InnerColor;<br />  vec4 OuterColor;<br />  float RadiusInner;<br />  float RadiusOuter;<br />};<br /><br /></pre><br />
This defines a block with the name <em class='bbc'>BlobSettings</em> that contains four uniform variables. With this type of block definition, the variables within the block are still part of the global scope and do not need to be qualified with the block name.<br />
<br />
The buffer object used to store the data for the uniforms is often referred to as a <strong class='bbc'>uniform buffer object</strong>. We'll see that a uniform buffer object is simply just a buffer object that is bound to a certain location.<br />
<br />
For this recipe, we'll use a simple example to demonstrate the use of uniform buffer objects and uniform blocks. We'll draw a quad (two triangles) with texture coordinates, and use our fragment shader to fill the quad with a fuzzy circle. The circle is a solid color in the center, but at its edge, it gradually fades to the background color, as shown in the following image.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/4767OS_01_06.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Getting ready</strong></span><br />
Start with an OpenGL program that draws two triangles to form a quad. Provide the position at vertex attribute location 0, and the texture coordinate (0 to 1 in each direction) at vertex attribute location 1 (see: <a href='http://www.packtpub.com/article/tips-tricks-getting-started-with-opengl-glsl-4' class='bbc_url' title='External link' rel='nofollow external'>Sending data to a shader using per-vertex attributes and vertex buffer objects</a>).<br />
<br />
We'll use the following vertex shader:<br />
<br />
<pre class='prettyprint'><br />#version 400<br /><br />layout (location = 0) in vec3 VertexPosition;<br />layout (location = 1) in vec3 VertexTexCoord;<br /><br />out vec3 TexCoord;<br /><br />void main()<br />{<br />	TexCoord = VertexTexCoord;<br />	gl_Position = vec4(VertexPosition,1.0);<br />}<br /><br /></pre><br />
The fragment shader contains the uniform block, and is responsible for drawing our fuzzy circle:<br />
<br />
<pre class='prettyprint'><br />#version 400<br />in vec3 TexCoord;<br />layout (location = 0) out vec4 FragColor;<br /><br />uniform BlobSettings {<br />  vec4 InnerColor;<br />  vec4 OuterColor;<br />  float RadiusInner;<br />  float RadiusOuter;<br />};<br /><br />void main() {<br />	float dx = TexCoord.x - 0.5;<br />	float dy = TexCoord.y - 0.5;<br />	float dist = sqrt(dx * dx + dy * dy);<br />	FragColor =<br />	   mix( InnerColor, OuterColor,<br />			 smoothstep( RadiusInner, RadiusOuter, dist )<br />	   );<br />}<br /><br /></pre><br />
The uniform block is named <em class='bbc'>BlobSettings</em>. The variables within this block define the parameters of our fuzzy circle. The variable <em class='bbc'>OuterColor</em> defines the color outside of the circle. <em class='bbc'>InnerColor</em> is the color inside of the circle. <em class='bbc'>RadiusInner</em> is the radius defining the part of the circle that is a solid color (inside the fuzzy edge), and the distance from the center of the circle to the inner edge of the fuzzy boundary. <em class='bbc'>RadiusOuter</em> is the outer edge of the fuzzy boundary of the circle (when the color is equal to <em class='bbc'>OuterColor</em>).<br />
<br />
The code within the main function computes the distance of the texture coordinate to the center of the quad located at (0.5, 0.5). It then uses that distance to compute the color by using the <em class='bbc'>smoothstep</em> function. This function provides a value that smoothly varies between 0.0 and 1.0 when the value of the third argument is between the values of the first two arguments. Otherwise it returns 0.0 or 1.0 depending on whether it is less than the first or greater than the second, respectively. The <em class='bbc'>mix</em> function is then used to linearly interpolate between <em class='bbc'>InnerColor</em> and <em class='bbc'>OuterColor</em> based on the value returned by the <em class='bbc'>smoothstep</em> function.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>How to do it...</strong></span><br />
In the OpenGL program, after linking the shader program, use the following steps to send data to the uniform block in the fragment shader:<br />
<ul class='bbcol decimal'><br /><li>Get the index of the uniform block using <em class='bbc'>glGetUniformBlockIndex</em>.<br />	<pre class='prettyprint'>	<br />GLuint blockIndex = glGetUniformBlockIndex(programHandle,<br />											  "BlobSettings");	<br />	</pre><br /></li><li>Allocate space for the buffer to contain the data for the uniform block. We get the size of the block using <em class='bbc'>glGetActiveUniformBlockiv</em>.<br />	<pre class='prettyprint'>	<br />GLint blockSize;<br />	<br />	glGetActiveUniformBlockiv(programHandle, blockIndex,<br />						  GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);<br />	<br />	GLubyte * blockBuffer= (GLubyte *) malloc(blockSize);	<br />	</pre><br /></li><li>Query for the offset of each variable within the block. To do so, we first find the index of each variable within the block.<br />	<pre class='prettyprint'>	<br />// Query for the offsets of each block variable<br />	const GLchar *names&#91;&#93; = { "InnerColor", "OuterColor",<br />							  "RadiusInner", "RadiusOuter" };<br />	<br />	GLuint indices&#91;4&#93;;<br />	glGetUniformIndices(programHandle, 4, names, indices);<br />	<br />	GLint offset&#91;4&#93;;<br />	glGetActiveUniformsiv(programHandle, 4, indices,<br />						  GL_UNIFORM_OFFSET, offset);	<br />	</pre><br /></li><li>Place the data into the buffer at the appropriate offsets.<br />	<pre class='prettyprint'>	<br />GLfloat outerColor&#91;&#93; = {0.0f, 0.0f, 0.0f, 0.0f};<br />	GLfloat innerColor&#91;&#93; = {1.0f, 1.0f, 0.75f, 1.0f};<br />	GLfloat innerRadius = 0.25f, outerRadius = 0.45f;<br />	<br />	memcpy(blockBuffer + offset&#91;0&#93;, innerColor,<br />									4 * sizeof(GLfloat));<br />	memcpy(blockBuffer + offset&#91;1&#93;, outerColor,<br />									4 * sizeof(GLfloat));<br />	memcpy(blockBuffer + offset&#91;2&#93;, &innerRadius,<br />									sizeof(GLfloat));<br />	memcpy(blockBuffer + offset&#91;3&#93;, &outerRadius,<br />									sizeof(GLfloat));	<br />	</pre><br /></li><li>Create the OpenGL buffer object and copy the data into it.<br />	<pre class='prettyprint'>	<br />GLuint uboHandle;<br />	glGenBuffers( 1, &uboHandle );<br />	glBindBuffer( GL_UNIFORM_BUFFER, uboHandle );<br />	glBufferData( GL_UNIFORM_BUFFER, blockSize, blockBuffer,<br />				  GL_DYNAMIC_DRAW );	<br />	</pre><br /></li><li>Bind the buffer object to the uniform block.<br />	<pre class='prettyprint'>	<br />glBindBufferBase( GL_UNIFORM_BUFFER, blockIndex, uboHandle );	<br />	</pre><br /></li></ul><br />
<span style='font-size: 18px;'><strong class='bbc'>How it works...</strong></span><br />
Phew! This seems like a lot of work! However, the real advantage comes when using multiple programs where the same buffer object can be used for each program. Let's take a look at each step individually.<br />
<br />
First, we get the index of the uniform block by calling <em class='bbc'>glGetUniformBlockIndex</em>, then we query for the size of the block by calling <em class='bbc'>glGetActiveUniformBlockiv</em>. After getting the size, we allocate a temporary buffer named <em class='bbc'>blockBuffer</em> to hold the data for our block.<br />
<br />
The layout of data within a uniform block is implementation dependent, and implementations may use different padding and/or byte alignment. So, in order to accurately layout our data, we need to query for the offset of each variable within the block. This is done in two steps. First, we query for the index of each variable within the block by calling <em class='bbc'>glGetUniformIndices</em>. This accepts an array of variable names (third argument) and returns the indices of the variables in the array <em class='bbc'>indices</em> (fourth argument). Then we use the indices to query for the offsets by calling <em class='bbc'>glGetActiveUniformsiv</em>. When the fourth argument is <em class='bbc'>GL_UNIFORM_OFFSET</em>, this returns the offset of each variable in the array pointed to by the fifth argument. This function can also be used to query for the size and type; however, in this case we choose not to do so, to keep the code simple (albeit less general).<br />
<br />
The next step involves filling our temporary buffer <em class='bbc'>blockBuffer</em> with the data for the uniforms at the appropriate offsets. Here we use the standard library function <em class='bbc'>memcpy</em> to accomplish this.<br />
<br />
Now that the temporary buffer is populated with the data with the appropriate layout, we can create our buffer object and copy the data into the buffer object. We call <em class='bbc'>glGenBuffers</em> to generate a buffer handle, and then bind that buffer to the <em class='bbc'>GL_UNIFORM_BUFFER</em> binding point by calling <em class='bbc'>glBindBuffer</em>. The space is allocated within the buffer object and the data is copied when <em class='bbc'>glBufferData</em> is called. We use <em class='bbc'>GL_DYNAMIC_DRAW</em> as the usage hint here, because uniform data may be changed somewhat often during rendering. Of course, this is entirely dependent on the situation.<br />
<br />
Finally, we associate the buffer object with the uniform block by calling <em class='bbc'>glBindBufferBase</em>. This function binds to an index within a buffer binding point. Certain binding points are also so-called "indexed buffer targets". This means that the target is actually an array of targets, and <em class='bbc'>glBindBufferBase</em> allows us to bind to one index within the array.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>There's more...</strong></span><br />
If the data for a uniform block needs to be changed at some later time, one can call <em class='bbc'>glBufferSubData</em> to replace all or part of the data within the buffer. If you do so, don't forget to first bind the buffer to the generic binding point <em class='bbc'>GL_UNIFORM_BUFFER</em>.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Using an instance name with a uniform block</strong></span><br />
A uniform block can have an optional instance name. For example, with our <em class='bbc'>BlobSettings</em> block, we could have used the instance name <em class='bbc'>Blob</em>, as shown here:<br />
<br />
<pre class='prettyprint'><br />uniform BlobSettings {<br />  vec4 InnerColor;<br />  vec4 OuterColor;<br />  float RadiusInner;<br />  float RadiusOuter;<br />} Blob;<br /><br /></pre><br />
In this case, the variables within the block are placed within a namespace qualified by the instance name. Therefore our shader code needs to refer to them prefixed with the instance name. For example:<br />
<br />
<pre class='prettyprint'><br />FragColor =<br />   mix( Blob.InnerColor, Blob.OuterColor,<br />	   smoothstep( Blob.RadiusInner, Blob.RadiusOuter, dist )<br />   );<br /><br /></pre><br />
Additionally, we need to qualify the variable names within the OpenGL code when querying for variable indices. The OpenGL specification says that they must be qualified with the block name (<em class='bbc'>BlobSettings</em>). However, my tests using the ATI Catalyst (10.8) drivers required me to use the instance name (<em class='bbc'>Blob</em>).<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Using layout qualifiers with uniform blocks</strong></span><br />
Since the layout of the data within a uniform buffer object is implementation dependent, it required us to query for the variable offsets. However, one can avoid this by asking OpenGL to use the standard layout <em class='bbc'>std140</em>. This is accomplished by using a layout qualifier when declaring the uniform block. For example:<br />
<br />
<pre class='prettyprint'><br />layout( std140 ) uniform BlobSettings {<br />   ...<br />};<br /><br /></pre><br />
The <em class='bbc'>std140</em> layout is described in detail within the OpenGL specification document (available at <a href='http://www.opengl.org/' class='bbc_url' title='External link' rel='nofollow external'>http://www.opengl.org</a>).<br />
<br />
Other options for the layout qualifier that apply to uniform block layouts include <em class='bbc'>packed</em> and <em class='bbc'>shared</em>. The <em class='bbc'>packed</em> qualifier simply states that the implementation is free to optimize memory in whatever way it finds necessary (based on variable usage or other criteria). With the <em class='bbc'>packed</em> qualifier, we still need to query for the offsets of each variable. The <em class='bbc'>shared</em> qualifier guarantees that the layout will be consistent between multiple programs and program stages provided that the uniform block declaration does not change. If you are planning to use the same buffer object between multiple programs and/or program stages, it is a good idea to use the <em class='bbc'>shared</em> option.<br />
<br />
There are two other layout qualifiers that are worth mentioning: <em class='bbc'>row_major</em> and <em class='bbc'>column_major</em>. These define the ordering of data within the matrix type variables within the uniform block.<br />
<br />
One can use multiple qualifiers for a block. For example, to define a block with both the <em class='bbc'>row_major</em> and <em class='bbc'>shared</em> qualifiers, we would use the following syntax:<br />
<br />
<pre class='prettyprint'><br />layout( row_major, shared ) uniform BlobSettings {<br />   ...<br />};<br /><br /></pre><br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
This article covered the topic of <em class='bbc'>Using Uniform Blocks and Uniform Buffer Objects</em>.]]></description>
		<pubDate>Fri, 27 Jan 2012 04:42:12 +0000</pubDate>
		<guid isPermaLink="false">314954362f31609663dc4765ab4c7030</guid>
	</item>
	<item>
		<title>OpenGL Type Traits</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/opengl-type-traits-r2566</link>
		<description><![CDATA[Anyone working with OpenGL knows that its API is *ekhm* not perfect. Its imperfection is especially visible to C++ programmers that (as I do) love typesafety that can't often be assured with C language when flexibility is at stakes. This is why we often see code such as:<br />
<br />
  void someFunctionTakingArbitraryData(int dataTypeIdentifier, int count, void* dataPointer);  Because this function is meant to be used with different data types it takes void* as buffer data type which forces client code to drop precious type info. What does it mean? It means lots of errors at runtime, which is the worst possible outcome. Why? Here is an example:  vector buffer; someFunctionTakingArbitraryData(TYPE_FLOAT, buffer.size(), &buffer[0]);  everything is fine – for now. Buffer is declared only one line above function call so error is not likely to happen. But this is not real life. More likely buffer is just passed in from a completely different context and we have to remember how it was declared. Time passes, decision is made that buffer should be filled with ints instead or even worse – doubles which most of the time behave the same as floats. Change is made to a buffer declaration. Click. Compilation runs smoothly thanks to STL. Run. Bam! Nothing looks like it should, but why? Because your application will most probably not crash, only unexpected program behavior will tell us that something is wrong. Tracking such bugs is the worst part of coding since they are trivial to fix but hard to find.<br />
<br />
 But fear no more. The cure is there. Has always been. It's called C++.<br />
<br />
 OpenGL API is build around functions like this one above. For example:<br />
<br />
  void glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);  and a call to it using a buffer declared before would be:  glVertexPointer(1, GL_FLOAT, 0, &buffer[0]);  wouldn't be nice to just write:  vertexPointer(1, 0, buffer);  and rely on compiler to do the rest for us? He knows best what type buffer really stores. It can be done and takes only a few lines of code to make this work forever. I called the technique OpenGL Type Traits. Type traits is a common C++ technique used to bind compile time information with another compilation constant (more on that later). It is used widely in STL, BOOST and basically template based libraries. Check the references to learn more.<br />
<br />
 Typically this "compilation constant” is a type but it doesn't have to be. It can also be a constant number (surprising huh?). So where does this all lead us to? What we need is a way to bind together OpenGL constants and types that we use in a buffer passed in. This is where traits are needed. Lets take a look:<br />
<br />
  template  struct opengl_traits {    }; template<> struct opengl_traits {   enum {GL_TYPE = GL_UNSIGNED_INT}; };  what you see here is a static binding of an unsigned int type with GL_UNSIGNED_INT constant number. But there is more:  template  void vertexPointer(GLint size, GLsizei stride, const T* pointer) {   glVertexPointer(size, opengl_traits::GL_TYPE, stride, pointer); };  Here we have a glVertexPointer wrapped by a template function. Lets say we would write the following code:  vector buffer; vertexPointer(3, 0, &buffer[0]);  A compiler will deduce T parameter as "unsigned int”, look inside the opengl_traits specialization for a nested GL_TYPE constant and he will find the GL_UNSIGNED_INT value. What will happen if buffer declaration is changed to say int? A compiler error. Nice. To fix an error another specialization is needed and so on. This way whenever we decide to change a buffer content we automatically have a valid type parameter passed. But there is one more thing left to cover: buffer objects. Since OpenGL API says that glVertexPointer and others take a NULL-pointer (which is implicitly of type int) when using VBOs, presented code would not compile. Because buffer content cannot be deduced form the passed in parameter, the compiler has to be instructed to figure this out some other way. For this purpose we need to create a template buffer object class. Additionally it has to contain a nested typedef member with value type definition, for example:<br />
<br />
  template  class BufferObject { public:     	typedef T value_type;     	... etc }  We use such a VBO in this way:  typedef BufferObject VBO; VBO vbo(numElements); ... vbo.use(); //do some setup and binding vertexPointer(3, 0, 0);  Again, a change in VBO definition will automagically result in vertexPointer() code modification. In fact, std::vector also contains a nested typedef “value_type” (as does any other std container) and can be used in the exact same way. Typically vertexPointer() would be placed inside some kind of renderer class like so:  class OpenGlRenderer { 	... 	template  	void vertexPointer() 	template  	void normalPointer() 	... etc }  This technique is not limited to OpenGL of course, but I came up with it while looking for a rendering bug so it is presented in this way. Also even here is a place to improvements. For example in my code I also have a GL_SIZE member in opengl_traits specializations to remove the first glVertexPointer parameter (why this is useful is a readers exercise, just think of vector for example ;) ) Even if this is not something you would use I still hope you liked it. Feel free to contact me at szymon-dot-gatner-at-gmail-dot-com.<br />
<br />
 References:<br />
<br />
 <a href='http://www.generic-programming.org/languages/cpp/techniques.php#traits' class='bbc_url' title='External link' rel='nofollow external'>http://www.generic-p...ques.php#traits</a><br />
<br />
]]></description>
		<pubDate>Tue, 30 Sep 2008 04:42:28 +0000</pubDate>
		<guid isPermaLink="false">f6e8de88807006538cd9be5fd3ba51c1</guid>
	</item>
	<item>
		<title>Excerpt from OpenGL® SuperBible: Comprehensive...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/excerpt-from-opengl%c2%ae-superbible-comprehensive-r2505</link>
		<description><![CDATA[What you'll learn in this chapter:<br />
<br />
        <strong class='bbc'>How To</strong><br />
<br />
   <strong class='bbc'>Functions You'll Use</strong><br />
<br />
     Add specular highlights to textured objects<br />
<br />
   glLightModel/glSecondaryColor<br />
<br />
     Use anisotropic texture filtering<br />
<br />
   glTexParameterf<br />
<br />
     Load and use compressed textures<br />
<br />
   glCompressedTexImage/glCompressedTexSubImage<br />
<br />
     Use points as textured quads<br />
<br />
   glPointParameter<br />
<br />
     Texture mapping is perhaps one of the most exciting features of OpenGL (well, close behind shaders anyway!) and is heavily relied on in the games and simulation industry. In Chapter 8, "Texture Mapping: The Basics," you learned the basics of loading and applying texture maps to geometry. In this chapter, we'll expand on this knowledge and cover some of the finer points of texture mapping in OpenGL.<br />
<br />
  <br />
<strong class='bbc'>Secondary Color</strong><br />
 Applying texture to geometry, in regard to how lighting works, causes a hidden and often undesirable side effect. In general, you set the texture environment to GL_MODULATE, causing lit geometry to be combined with the texture map in such a way that the textured geometry also appears lit. Normally, OpenGL performs lighting calculations and calculates the color of individual fragments according to the standard light model. These fragment colors are then multiplied by the filtered texel colors being applied to the geometry. However, this process has the side effect of suppressing the visibility of specular highlights on the geometry. Basically, any texture color multiplied by ones (the white spot) is the same texture color. You cannot, by multiplication of any number less than or equal to one, make a color brighter than it already is!<br />
<br />
 For example, Figure 9.1 shows the original lit SPHEREWORLD sample from Chapter 5, "Color, Materials, and Lighting: The Basics." In this figure, you can see clearly the specular highlights reflecting off the surface of the torus. In contrast, Figure 9.2 shows the SPHEREWORLD sample from Chapter 8. In this figure, you can see the effects of having the texture applied after the lighting has been added.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig01.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 9.1</strong><br />
The original SPHEREWORLD torus with specular highlights.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig02.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 9.2</strong><br />
The textured torus with muted highlights.<br />
<br />
 The solution to this problem is to apply (by adding instead of multiplication) the specular highlights after texturing. This technique, called the <em class='bbc'>secondary specular color,</em> can be manually applied or automatically calculated by the lighting model. Usually, you do this using the normal OpenGL lighting model and simply turn it on using glLightModeli, as shown here:<br />
<br />
  glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);  You can switch back to the normal lighting model by specifying GL_SINGLE_COLOR for the light model parameter:<br />
<br />
  glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_COLOR_SINGLE);  Figure 9.3 shows the output from this chapter's version of SPHEREWORLD with the restored specular highlights on the torus. We do not provide a listing for this sample because it simply contains the addition of the preceding single line of code.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig03.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig03.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.3</strong><br />
Highlights restored to the textured torus.<br />
<br />
 You can also directly specify a secondary color after texturing when you are not using lighting (lighting is disabled) using the glSecondaryColor function. This function comes in many variations just as glColor does and is fully documented in the reference section. You should also note that if you specify a secondary color, you must also explicitly enable the use of the secondary color by enabling the GL_COLOR_SUM flag:<br />
<br />
  glEnable(GL_COLOR_SUM);  Manually setting the secondary color only works when lighting is disabled.<br />
<br />
 </a> <br />
<strong class='bbc'>Anisotropic Filtering</strong><br />
 Anisotropic texture filtering is not a part of the core OpenGL specification, but it is a widely supported extension that can dramatically improve the quality of texture filtering operations. Texture filtering is covered in the preceding chapter, where you learned about the two basic texture filters: nearest neighbor (GL_NEAREST) and linear (GL_LINEAR). When a texture map is filtered, OpenGL uses the texture coordinates to figure out where in the texture map a particular fragment of geometry falls. The texels immediately around that position are then sampled using either the GL_NEAREST or the GL_LINEAR filtering operations.<br />
<br />
 This process works perfectly when the geometry being textured is viewed directly perpendicular to the viewpoint, as shown on the left in Figure 9.4. However, when the geometry is viewed from an angle more oblique to the point of view, a regular sampling of the surrounding texels results in the loss of some information in the texture (it looks blurry!). A more realistic and accurate sample would be elongated along the direction of the plane containing the texture. This result is shown on the right in Figure 9.4. Taking this viewing angle into account for texture filtering is called <em class='bbc'>anisotropic filtering.</em><br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig04.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 9.4</strong><br />
Normal texture sampling versus anisotropic sampling.<br />
<br />
 You can apply anisotropic filtering to any of the basic or mipmapped texture filtering modes; applying it requires three steps. First, you must determine whether the extension is supported. You can do this by querying for the extension string GL_EXT_texture_filter_anisotropic. You can use the glTools function named gltIsExtSupported for this task:<br />
<br />
  if(gltIsExtSupported("GL_EXT_texture_filter_anisotropic"))   // Set Flag that extension is supported  After you determine that this extension is supported, you can find the maximum amount of <em class='bbc'>anisotropy</em> supported. You can query for it using glGetFloatv and the parameter GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:<br />
<br />
  GLfloat fLargest; . . . . . . glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);  The larger the amount of anisotropy applied, the more texels are sampled along the direction of greatest change (along the strongest point of view). A value of 1.0 represents normal texture filtering (called <em class='bbc'>isotropic</em> filtering). Bear in mind that anisotropic filtering is not free. The extra amount of work, including other texels, can sometimes result in substantial performance penalties. On modern hardware, this feature is getting quite fast and is becoming a standard feature of popular games, animation, and simulation programs.<br />
<br />
 Finally, you set the amount of anisotropy you want applied using glTexParameter and the constant GL_TEXTURE_MAX_ANISOTROPY_EXT. For example, using the preceding code, if you want the maximum amount of anisotropy applied, you would call glTexParameterf as shown here:<br />
<br />
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);  This modifier is applied per texture object just like the standard filtering parameters.<br />
<br />
 The sample program ANISOTROPIC provides a striking example of anisotropic texture filtering in action. This program displays a tunnel with walls, a floor, and ceiling geometry. The arrow keys move your point of view (or the tunnel) back and forth along the tunnel interior. A right mouse click brings up a menu that allows you to select from the various texture filters, and turn on and off anisotropic filtering. Figure 9.5 shows the tunnel using trilinear filtered mipmapping. Notice how blurred the patterns become in the distance, particularly with the bricks.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig05.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 9.5</strong><br />
ANISOTROPIC tunnel sample with trilinear filtering.<br />
<br />
 Now compare Figure 9.5 with Figure 9.6, in which anisotropic filtering has been enabled. The mortar between the bricks is now clearly visible all the way to the end of the tunnel. In fact, anisotropic filtering can also greatly reduce the visible mipmap transition patterns for the GL_LINEAR_MIPMAP_NEAREST and GL_NEAREST_MIPMAP_NEAREST mipmapped filters.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig06.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig06.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.6</strong><br />
ANISOTROPIC tunnel sample with anisotropic filtering.<br />
<br />
 <br />
<strong class='bbc'>Texture Compression</strong><br />
 Texture mapping can add incredible realism to any 3D rendered scene, with a minimal cost in vertex processing. One drawback to using textures, however, is that they require a lot of memory to store and process. Early attempts at texture compression were crudely storing textures as JPG files and decompressing the textures when loaded before calling glTexImage. These attempts saved disk space or reduced the amount of time required to transmit the image over the network (such as the Internet), but did nothing to alleviate the storage requirements of texture images loaded into graphics hardware memory.<br />
<br />
 Native support for texture compression was added to OpenGL with version 1.3. Earlier versions of OpenGL may also support texture compression via extension functions of the same name. You can test for this extension by using the GL_ARB_texture_compression string.<br />
<br />
 Texture compression support in OpenGL hardware can go beyond simply allowing you to load a compressed texture; in most implementations, the texture data stays compressed even in the graphics hardware memory. This allows you to load more texture into less memory and can significantly improve texturing performance due to fewer texture swaps (moving textures around) and fewer memory accesses during texture filtering.<br />
<br />
 </a> <br />
<strong class='bbc'>Compressing Textures</strong><br />
 Texture data does not have to be initially compressed to take advantage of OpenGL support for compressed textures. You can request that OpenGL compress a texture image when loaded by using one of the values in Table 9.1 for the <em class='bbc'>internalFormat</em> parameter of any of the glTexImage functions.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Table 9.1 Compressed Texture Formats</strong></strong><br />
        <strong class='bbc'>Compressed Format</strong><br />
<br />
   <strong class='bbc'>Base Internal Format</strong><br />
<br />
     GL_COMPRESSED_ALPHA<br />
<br />
   GL_ALPHA<br />
<br />
     GL_COMPRESSED_LUMINANCE<br />
<br />
   GL_LUMINANCE<br />
<br />
     GL_COMPRESSED_LUMINANCE_ALPHA<br />
<br />
   GL_LUMINANCE_ALPHA<br />
<br />
     GL_COMPRESSED_INTENSITY<br />
<br />
   GL_INTENSITY<br />
<br />
     GL_COMPRESSED_RGB<br />
<br />
   GL_RGB<br />
<br />
     GL_COMPRESSED_RGBA<br />
<br />
   GL_RGBA<br />
<br />
     Compressing images this way adds a bit of overhead to texture loads but can increase texture performance due to the more efficient usage of texture memory. If, for some reason, the texture cannot be compressed, OpenGL uses the base internal format listed instead and loads the texture uncompressed.<br />
<br />
 When you attempt to load and compress a texture in this way, you can find out whether the texture was successfully compressed by using glGetTexLevelParameteriv with GL_TEXTURE_COMPRESSED as the parameter name:<br />
<br />
  GLint compFlag; . . . glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &compFlag);  The glGetTexLevelParameteriv function accepts a number of new parameter names pertaining to compressed textures. These parameters are listed in Table 9.2.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Table 9.2 Compressed Texture Parameters Retrieved with glGetTexLevelParameter</strong></strong><br />
        <strong class='bbc'>Parameter</strong><br />
<br />
   <strong class='bbc'>Returns</strong><br />
<br />
     GL_TEXTURE_COMPRESSED<br />
<br />
   The value 1 if the texture is compressed, 0 if not<br />
<br />
     GL_TEXTURE_COMPRESSED_IMAGE_SIZE<br />
<br />
   The size in bytes of the compressed texture<br />
<br />
     GL_TEXTURE_INTERNAL_FORMAT<br />
<br />
   The compression format used<br />
<br />
     GL_NUM_COMPRESSED_TEXTURE_FORMATS<br />
<br />
   The number of supported compressed texture formats<br />
<br />
     GL_COMPRESSED_TEXTURE_FORMATS<br />
<br />
   An array of constant values corresponding to each supported compressed texture format<br />
<br />
     GL_TEXTURE_COMPRESSION_HINT<br />
<br />
   The value of the texture compression hint (GL_NICEST/GL_FASTEST)<br />
<br />
     When textures are compressed using the values listed in Table 9.1, OpenGL chooses the most appropriate texture compression format. You can use glHint to specify whether you want OpenGL to choose based on the fastest or highest quality algorithm:<br />
<br />
  glHint(GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST); glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); glHint(GL_TEXTURE_COMPRESSION_HINT, GL_DONT_CARE);  The exact compression format varies from implementation to implementation. You can obtain a count of compression formats and a list of the values by using GL_NUM_ COMPRESSED_TEXTURE_FORMATS and GL_COMPRESSED_TEXTURE_FORMATS. To check for support for a specific set of compressed texture formats, you need to check for a specific extension for those formats. For example, nearly all implementations support the GL_EXT_texture_compression_s3tc texture compression format. If this extension is supported, the compressed texture formats listed in Table 9.3 are all supported, but only for two-dimensional textures.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Table 9.3 Compression Formats for GL_EXT_texture_compression_s3tc</strong></strong><br />
        <strong class='bbc'>Format</strong><br />
<br />
   <strong class='bbc'>Description</strong><br />
<br />
     GL_COMPRESSED_RGB_S3TC_DXT1<br />
<br />
   RGB data is compressed; alpha is always 1.0.<br />
<br />
     GL_COMPRESSED_RGBA_S3TC_DXT1<br />
<br />
   RGB data is compressed; alpha is either 1.0 or 0.0.<br />
<br />
     GL_COMPRESSED_RGBA_S3TC_DXT3<br />
<br />
   RGB data is compressed; alpha is stored as 4 bits.<br />
<br />
     GL_COMPRESSED_RGBA_S3TC_DXT5<br />
<br />
   RGB data is compressed; alpha is a weighted average of 8-bit values.<br />
<br />
      <br />
<strong class='bbc'>Loading Compressed Textures</strong><br />
 Using the functions in the preceding section, you can have OpenGL compress textures in a natively supported format, retrieve the compressed data with the glGetCompressedTexImage function (identical to the glGetTexImage function for uncompressed textures), and save it to disk. On subsequent loads, the raw compressed data can be used, resulting in substantially faster texture loads. Be advised, however, that some vendors may cheat a little when it comes to texture loading in order to optimize texture storage or filtering operations. This technique will work only on fully conformant hardware implementations.<br />
<br />
 To load precompressed texture data, use one of the following functions:<br />
<br />
  void glCompressedTexImage1D(GLenum <em class='bbc'>target</em>, GLint <em class='bbc'>level</em>, GLenum <em class='bbc'>internalFormat</em>,         	GLsizei <em class='bbc'>width</em>,         	GLint <em class='bbc'>border</em>, GLsizei <em class='bbc'>imageSize</em>, void *<em class='bbc'>data</em>); void glCompressedTexImage2D(GLenum <em class='bbc'>target</em>, GLint <em class='bbc'>level</em>, GLenum <em class='bbc'>internalFormat</em>,         	GLsizei <em class='bbc'>width</em>, GLsizei <em class='bbc'>height</em>,         	GLint <em class='bbc'>border</em>, GLsizei <em class='bbc'>imageSize</em>, void *<em class='bbc'>data</em>); void glCompressedTexImage3D(GLenum <em class='bbc'>target</em>, GLint <em class='bbc'>level</em>, GLenum <em class='bbc'>internalFormat</em>,         	GLsizei <em class='bbc'>width</em>, GLsizei <em class='bbc'>height</em>, GLsizei <em class='bbc'>depth</em>,         	GLint <em class='bbc'>border</em>, Glsizei <em class='bbc'>imageSize</em>, GLvoid *<em class='bbc'>data</em>);  These functions are virtually identical to the glTexImage functions from the preceding chapter. The only difference is that the <em class='bbc'>internalFormat</em> parameter must specify a supported compressed texture image. If the implementation supports the GL_EXT_texture_compression_s3tc extension, this would be one of the values from Table 9.3. There is also a corresponding set of glCompressedTexSubImage functions for updating a portion or all of an already-loaded texture that mirrors the glTexSubImage functionality from the preceding chapter.<br />
<br />
 Texture compression is a very popular texture feature. Smaller textures take up less storage, transmit faster over networks, load faster off disk, copy faster to graphics memory, allow for substantially more texture to be loaded onto hardware, and generally texture slightly faster to boot! Don't forget, though, as with so many things in life, there is no such thing as a free lunch. Something may be lost in the compression. The GL_EXT_texture_compression_s3tc method, for example, works by stripping color data out of each texel. For some textures, this results in substantial image quality loss (particularly for textures that contain smooth color gradients). Other times, textures with a great deal of detail are visually nearly identical to the original uncompressed version. The choice of texture compression method (or indeed no compression) can vary greatly depending on the nature of the underlying image.<br />
<br />
  <br />
<strong class='bbc'>Texture Coordinate Generation</strong><br />
 In Chapter 8, you learned that textures are mapped to geometry using texture coordinates. Often, when you are loading models (see Chapter 11, "It's All About the Pipeline: Faster Geometry Throughput"), texture coordinates are provided for you. If necessary, you can easily map texture coordinates manually to some surfaces such as spheres or flat planes. Sometimes, however, you may have a complex surface for which it is not so easy to manually derive the coordinates. OpenGL can automatically generate texture coordinates for you within certain limitations.<br />
<br />
 Texture coordinate generation is enabled on the S, T, R, and Q texture coordinates using glEnable:<br />
<br />
  glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_TEXTURE_GEN_Q);  When texture coordinate generation is enabled, any calls to glTexCoord are ignored, and OpenGL calculates the texture coordinates for each vertex for you. In the same manner that texture coordinate generation is turned on, you turn it off by using glDisable:<br />
<br />
  glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); glDisable(GL_TEXTURE_GEN_Q);  You set the function or method used to generate texture coordinates with the following functions:<br />
<br />
  void glTexGenf(GLenum <em class='bbc'>coord</em>, GLenum <em class='bbc'>pname</em>, GLfloat <em class='bbc'>param</em>); void glTexGenfv(GLenum <em class='bbc'>coord</em>, GLenum <em class='bbc'>pname</em>, GLfloat *<em class='bbc'>param</em>);  The first parameter, <em class='bbc'>coord</em>, specifies which texture coordinate this function sets. It must be GL_S, GL_T, GL_R, or GL_Q. The second parameter, <em class='bbc'>pname</em>, must be GL_TEXTURE_GEN_MODE, GL_OBJECT_PLANE, or GL_EYE_PLANE. The last parameter sets the values of the texture generation function or mode. Note that integer (GLint) and double (GLdouble) versions of these functions are also used.<br />
<br />
 The pertinent portions of the sample program TEXGEN are presented in Listing 9.1. This program displays a torus that can be manipulated (rotated around) using the arrow keys. A right-click brings up a context menu that allows you to select from the first three texture generation modes we will discuss: Object Linear, Eye Linear, and Sphere Mapping.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Listing 9.1</strong> Source Code for the TEXGEN Sample Program</strong><br />
  #include "&#46;&#46;/&#46;&#46;/shared/gltools.h"  // gltools library // Rotation amounts static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; GLuint toTextures[2];    // Two texture objects int iRenderMode = 3;    // Sphere Mapped is default /////////////////////////////////////////////////////////////////////////////// // Reset flags as appropriate in response to menu selections void ProcessMenu(int value)   {   // Projection plane   GLfloat zPlane[] = { 0.0f, 0.0f, 1.0f, 0.0f };   // Store render mode   iRenderMode = value;   // Set up textgen based on menu selection   switch(value) 	{ 	case 1:   	// Object Linear   	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);   	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);   	glTexGenfv(GL_S, GL_OBJECT_PLANE, zPlane);   	glTexGenfv(GL_T, GL_OBJECT_PLANE, zPlane);   	break; 	case 2:   	// Eye Linear   	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);   	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);   	glTexGenfv(GL_S, GL_EYE_PLANE, zPlane);   	glTexGenfv(GL_T, GL_EYE_PLANE, zPlane);   	break; 	case 3: 	default:   	// Sphere Map   	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);   	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);   	break; 	}   glutPostRedisplay();  // Redisplay   } /////////////////////////////////////////////////////////////////////////////// // Called to draw scene void RenderScene(void)   {   // Clear the window with current clearing color   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // Switch to orthographic view for background drawing   glMatrixMode(GL_PROJECTION);   glPushMatrix();   glLoadIdentity();   gluOrtho2D(0.0f, 1.0f, 0.0f, 1.0f);   glMatrixMode(GL_MODELVIEW);   glBindTexture(GL_TEXTURE_2D, toTextures[1]);  // Background texture   // We will specify texture coordinates   glDisable(GL_TEXTURE_GEN_S);   glDisable(GL_TEXTURE_GEN_T);   // No depth buffer writes for background   glDepthMask(GL_FALSE);   // Background image   glBegin(GL_QUADS); 	glTexCoord2f(0.0f, 0.0f); 	glVertex2f(0.0f, 0.0f); 	glTexCoord2f(1.0f, 0.0f); 	glVertex2f(1.0f, 0.0f); 	glTexCoord2f(1.0f, 1.0f); 	glVertex2f(1.0f, 1.0f); 	glTexCoord2f(0.0f, 1.0f); 	glVertex2f(0.0f, 1.0f);   glEnd();   // Back to 3D land   glMatrixMode(GL_PROJECTION);   glPopMatrix();   glMatrixMode(GL_MODELVIEW);   // Turn texgen and depth writing back on   glEnable(GL_TEXTURE_GEN_S);   glEnable(GL_TEXTURE_GEN_T);   glDepthMask(GL_TRUE);   // May need to switch to stripe texture   if(iRenderMode != 3) 	glBindTexture(GL_TEXTURE_2D, toTextures[0]);   // Save the matrix state and do the rotations   glPushMatrix();   glTranslatef(0.0f, 0.0f, -2.0f);   glRotatef(xRot, 1.0f, 0.0f, 0.0f);   glRotatef(yRot, 0.0f, 1.0f, 0.0f);   // Draw the torus   gltDrawTorus(0.35, 0.15, 61, 37);   // Restore the matrix state   glPopMatrix();   // Display the results   glutSwapBuffers();   }  <br />
<strong class='bbc'>Object Linear Mapping</strong><br />
 When the texture generation mode is set to GL_OBJECT_LINEAR, texture coordinates are generated using the following function:<br />
<br />
  coord = P1*X + P2*Y + P3*Z + P4*W  The X, Y, Z, and W values are the vertex coordinates from the object being textured, and the P1–P4 values are the coefficients for a plane equation. The texture coordinates are then projected onto the geometry from the perspective of this plane. For example, to project texture coordinates for S and T from the plane Z = 0, we would use the following code from the TEXGEN sample program:<br />
<br />
  // Projection plane GLfloat zPlane[] = { 0.0f, 0.0f, 1.0f, 0.0f }; . . . . . . // Object Linear glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, zPlane); glTexGenfv(GL_T, GL_OBJECT_PLANE, zPlane);  Note that the texture coordinate generation function can be based on a different plane equation for each coordinate. Here, we simply use the same one for both the S and the T coordinates.<br />
<br />
 This technique maps the texture to the object in object coordinates, regardless of any modelview transformation in effect. Figure 9.7 shows the output for TEXGEN when the Object Linear mode is selected. No matter how you reorient the torus, the mapping remains fixed to the geometry.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig07.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig07.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.7</strong><br />
Torus mapped with object linear coordinates.<br />
<br />
 </a> <br />
<strong class='bbc'>Eye Linear Mapping</strong><br />
 When the texture generation mode is set to GL_EYE_LINEAR, texture coordinates are generated in a similar manner to GL_OBJECT_LINEAR. The coordinate generation looks the same, except that now the X, Y, Z, and W coordinates indicate the location of the point of view (where the camera or eye is located). The plane equation coefficients are also inverted before being applied to the equation to account for the fact that now everything is in eye coordinates.<br />
<br />
 The texture, therefore, is basically projected from the plane onto the geometry. As the geometry is transformed by the modelview matrix, the texture will appear to slide across the surface. We set up this capability with the following code from the TEXGEN sample program:<br />
<br />
  // Projection plane GLfloat zPlane[] = { 0.0f, 0.0f, 1.0f, 0.0f }; . . . . . . // Eye Linear glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_S, GL_EYE_PLANE, zPlane); glTexGenfv(GL_T, GL_EYE_PLANE, zPlane);  The output of the TEXGEN program when the Eye Linear menu option is selected is shown in Figure 9.8. As you move the torus around with the arrow keys, note how the projected texture slides about on the geometry.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig08.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig08.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.8</strong><br />
An example of eye linear texture mapping.<br />
<br />
 </a> <br />
<strong class='bbc'>Sphere Mapping</strong><br />
 When the texture generation mode is set to GL_SPHERE_MAP, OpenGL calculates texture coordinates in such a way that the object appears to be reflecting the current texture map. This is the easiest mode to set up, with just these two lines from the TEXGEN sample program:<br />
<br />
  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);  You usually can make a well-constructed texture by taking a photograph through a fish-eye lens. This texture then lends a convincing reflective quality to the geometry. For more realistic results, sphere mapping has largely been replaced by cube mapping (discussed next). However, sphere mapping still has some uses because it has significantly less overhead.<br />
<br />
 In particular, sphere mapping requires only a single texture instead of six, and if true reflectivity is not required, you can obtain adequate results from sphere mapping. Even without a well-formed texture taken through a fish-eye lens, you can also use sphere mapping for an approximate environment map. Many surfaces are shiny and reflect the light from their surroundings, but are not mirror-like in their reflective qualities. In the TEXGEN sample program, we use a suitable environment map for the background (all modes show this background), as well as the source for the sphere map. Figure 9.9 shows the environment-mapped torus against a similarly colored background. Moving the torus around with the arrow keys produces a reasonable approximation of a reflective surface.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig09.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig09.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.9</strong><br />
An environment map using a sphere map.<br />
<br />
 </a> <br />
<strong class='bbc'>Cube Mapping</strong><br />
 The last two texture generation modes, GL_REFLECTION_MAP and GL_NORMAL_MAP, require the use of a new type of texture target: the cube map. A cube map is treated as a single texture, but is made up of six square (yes, they must be square!) 2D images that make up the six sides of a cube. Figure 9.10 shows the layout of six square textures composing a cube map for the CUBEMAP sample program.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig10.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig10.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.10</strong><br />
The layout of six cube faces in the CUBEMAP sample program.<br />
<br />
 These six 2D tiles represent the view of the world from six different directions (negative and positive X, Y, and Z). Using the texture generation mode GL_REFLECTION_MAP, you can then create a realistically reflective surface.<br />
<br />
 </a> <br />
<strong class='bbc'>Loading Cube Maps</strong><br />
 Cube maps add six new values that can be passed into glTexImage2D: GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, and GL_TEXTURE_CUBE_MAP_NEGATIVE_Z. These constants represent the direction in world coordinates of the cube face surrounding the object being mapped. For example, to load the map for the positive X direction, you might use a function that looks like this:<br />
<br />
  glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, iWidth, iHeight,                 	0, GL_RGBA, GL_UNSIGNED_BYTE, pImage);  To take this example further, look at the following code segment from the CUBEMAP sample program. Here, we store the name and identifiers of the six cube maps in arrays and then use a loop to load all six images into a single texture object:<br />
<br />
  const char *szCubeFaces[6] = { "pos_x.tga", "neg_x.tga", "pos_y.tga",         	"neg_y.tga","pos_z.tga", "neg_z.tga" }; GLenum cube[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X,            GL_TEXTURE_CUBE_MAP_NEGATIVE_X,            GL_TEXTURE_CUBE_MAP_POSITIVE_Y,            GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,            GL_TEXTURE_CUBE_MAP_POSITIVE_Z,            GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; . . . . . .   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,                       	GL_LINEAR_MIPMAP_LINEAR);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);   GLbyte *pBytes;   GLint iWidth, iHeight, iComponents;   GLenum eFormat;   // Load Cube Map images   for(i = 0; i < 6; i++) 	{ 	// Load this texture map 	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); 	pBytes = gltLoadTGA(szCubeFaces<em class='bbc'>, &iWidth, &iHeight,                            &iComponents, &eFormat); 	glTexImage2D(cube<em class='bbc'>, 0, iComponents, iWidth, iHeight, 0, eFormat,                       	GL_UNSIGNED_BYTE, pBytes); 	free(pBytes); 	}  To enable the application of the cube map, we now call glEnable with GL_TEXTURE_CUBE_MAP instead of GL_TEXTURE_2D (we also use the same value in glBindTexture when using texture objects):<br />
<br />
  glEnable(GL_TEXTURE_CUBE_MAP);  If both GL_TEXTURE_CUBE_MAP and GL_TEXTURE_2D are enabled, GL_TEXTURE_CUBE_MAP has precedence. Also, notice that the texture parameter values (set with glTexParameter) affect all six images in a single cube texture.<br />
<br />
 Texture coordinates for cube maps seem a little odd at first glance. Unlike a true 3D texture, the S, T, and R texture coordinates represent a signed vector from the center of the texture map. This vector intersects one of the six sides of the cube map. The texels around this intersection point are then sampled to create the filtered color value from the texture.<br />
<br />
  <br />
<strong class='bbc'>Using Cube Maps</strong><br />
 The most common use of cube maps is to create an object that reflects its surroundings. The six images used for the CUBEMAP sample program were provided courtesy of The Game Creators, Ltd. (<a href='http://www.thegamecreators.com' class='bbc_url' title='External link' rel='nofollow external'>http://www.thegamecreators.com</a>). This cube map is applied to a sphere, creating the appearance of a mirrored surface. This same cube map is also applied to the skybox, which creates the background being reflected.<br />
<br />
 A skybox is nothing more than a big box with a picture of the sky on it. Another way of looking at it is as a picture of the sky on a big box! Simple enough. An effective skybox contains six images that contain views from the center of your scene along the six directional axes. If this sounds just like a cube map, congratulations, you're paying attention! For our CUBEMAP sample program a large box is drawn around the scene, and the CUBEMAP texture is applied to the six faces of the cube. The skybox is drawn as a single batch of six GL_QUADS. Each face is then manually textured using glTexCoord3f. For each vertex, a vector is specified that points to that corner of the sky box. The first side (in the negative X direction) is shown here:<br />
<br />
  glBegin(GL_QUADS); 	////////////////////////////////////////////// 	// Negative X 	glTexCoord3f(-1.0f, -1.0f, 1.0f); 	glVertex3f(-fExtent, -fExtent, fExtent);          glTexCoord3f(-1.0f, -1.0f, -1.0f); 	glVertex3f(-fExtent, -fExtent, -fExtent);          glTexCoord3f(-1.0f, 1.0f, -1.0f); 	glVertex3f(-fExtent, fExtent, -fExtent);          glTexCoord3f(-1.0f, 1.0f, 1.0f); 	glVertex3f(-fExtent, fExtent, fExtent); . . . . . .  It is important to remember that in order for the manual selection of texture coordinates via glTexCoord3f to work, you must disable the texture coordinate generation:<br />
<br />
  // Sky Box is manually textured glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); 	DrawSkyBox();  To draw the reflective sphere, the CUBEMAP sample sets the texture generation mode to GL_REFLECTION_MAP for all three texture coordinates:<br />
<br />
  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);  We must also make sure that texture coordinate generation is enabled:<br />
<br />
  // Use texgen to apply cube map glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R);  To provide a true reflection, we also take the orientation of the camera into account. The camera's rotation matrix is extracted from the camera class, and inverted. This is then applied to the texture matrix before the cube map is applied. Without this rotation of the texture coordinates, the cube map will not correctly reflect the surrounding skybox. Since the gltDrawSphere function makes no modelview matrix mode changes, we can also leave the matrix mode as GL_TEXTURE until we are through drawing and have restored the texture matrix to its original state (usually this will be the identity matrix):<br />
<br />
  glMatrixMode(GL_TEXTURE);   glPushMatrix();          // Invert camera matrix (rotation only) and apply to   // texture coordinates   M3DMatrix44f m, invert;   frameCamera.GetCameraOrientation(m);   m3dInvertMatrix44(invert, m);   glMultMatrixf(invert);       	gltDrawSphere(0.75f, 41, 41);       	glPopMatrix(); glMatrixMode(GL_MODELVIEW);  Figure 9.11 shows the output of the CUBEMAP sample program. Notice how the sky and surrounding terrain are reflected correctly off the surface of the sphere. Moving the camera around the sphere (by using the arrow keys) reveals the correct background and sky view reflected accurately off the sphere as well.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig11.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 9.11</strong><br />
Output from the CUBEMAP sample program. (This figure also appears in the Color insert.)<br />
<br />
 <br />
<strong class='bbc'>Multitexture</strong><br />
 Modern OpenGL hardware implementations support the capability to apply two or more textures to geometry simultaneously. If an implementation supports more than one texture unit, you can query with GL_MAX_TEXTURE_UNITS to see how many texture units are available:<br />
<br />
  GLint iUnits; glGetIntegerv(GL_MAX_TEXTURE_UNITS, &iUnits);  Textures are applied from the base texture unit (GL_TEXTURE0), up to the maximum number of texture units in use (GL_TEXTURE<em class='bbc'>n</em>, where <em class='bbc'>n</em> is the number of texture units in use). Each texture unit has its own texture environment that determines how fragments are combined with the previous texture unit. Figure 9.12 shows three textures being applied to geometry, each with its own texture environment.<br />
<br />
 In addition to its own texture environment, each texture unit has its own texture matrix and set of texture coordinates. Each texture unit has its own texture bound to it with different filter modes and edge clamping parameters. You can even use different texture coordinate generation modes for each texture.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig12.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig12.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.12</strong><br />
Multitexture order of operations.<br />
<br />
 By default, the first texture unit is the active texture unit. All texture commands, with the exception of glTexCoord, affect the currently active texture unit. You can change the current texture unit by calling glActiveTexture with the texture unit identifier as the argument. For example, to switch to the second texture unit and enable 2D texturing on that unit, you would call the following:<br />
<br />
  glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D);  To disable texturing on the second texture unit and switch back to the first (base) texture unit, you would make these calls:<br />
<br />
  glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0);  All calls to texture functions such as glTexParameter, glTexEnv, glTexGen, glTexImage, and glBindTexture are bound only to the current texture unit. When geometry is rendered, texture is applied from all enabled texture units using the texture environment and parameters previously specified.<br />
<br />
 </a> <br />
<strong class='bbc'>Multiple Texture Coordinates</strong><br />
 Occasionally, you might apply all active textures using the same texture coordinates for each texture, but this is rarely the case. When using multiple textures, you can still specify texture coordinates with glTexCoord; however, these texture coordinates are used only for the first texture unit (GL_TEXTURE0). To specify texture coordinates separately for each texture unit, you need one of the new texture coordinate functions:<br />
<br />
  GlMultiTexCoord1f(GLenum <em class='bbc'>texUnit</em>, GLfloat <em class='bbc'>s</em>); glMultiTexCoord2f(GLenum <em class='bbc'>texUnit</em>, GLfloat <em class='bbc'>s</em>, GLfloat <em class='bbc'>t</em>); glMultiTexCoord3f(GLenum <em class='bbc'>texUnit</em>, GLfloat <em class='bbc'>s</em>, GLfloat <em class='bbc'>t, </em>Glfloat<em class='bbc'> r</em>);  The <em class='bbc'>texUnit</em> parameter is GL_TEXTURE0, GL_TEXTURE1, and so on up to the maximum number of supported texturing units. In these functions, you specify the <em class='bbc'>s</em>, <em class='bbc'>t</em>, and <em class='bbc'>r</em> coordinates of a one-, two-, or three-dimensional texture (including cube maps). You can also use texture coordinate generation on one or more texture units.<br />
<br />
 <a name="Heading16" id="Heading16"> <br />
<strong class='bbc'>A Multitextured Example</strong><br />
 Listing 9.2 presents some of the code for the sample program MULTITEXTURE. This program is similar to the CUBEMAP program, and only the important changes are listed here. In this example, we place the CUBEMAP texture on the second texture unit, and on the first texture unit we use a "tarnish" looking texture. When the tarnish texture is multiplied by the cube map texture, we get the same reflective surface as before, but now there are fixed darker spots that appear as blemishes on the mirrored surface. Make note of the fact that each texture unit has its own texture matrix. Therefore, we must take care to apply the inverse of the camera matrix, only to the texture unit containing the reflected cube map. <a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig13.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.13</a> shows the output from the MULTITEXTURE program.<br />
<br />
 <a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig13.jpg' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig13.jpg' alt='Posted Image' class='bbc_img' /></a> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig13.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.13</a></strong><br />
Output from the MULTITEXTURE sample program.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Listing 9.2</strong> Source Code for the MULTITEXTURE Sample Program</strong><br />
  #include "&#46;&#46;/&#46;&#46;/shared/gltools.h"  // OpenGL toolkit #include "&#46;&#46;/&#46;&#46;/shared/glframe.h"  // Camera class #include  . . . . . . // Storage for two texture objects GLuint   textureObjects[2]; #define CUBE_MAP  0 #define COLOR_MAP  1 . . . . . . ////////////////////////////////////////////////////////////////// // This function does any needed initialization on the rendering // context.  void SetupRC()   {   GLbyte *pBytes;   GLint iWidth, iHeight, iComponents;   GLenum eFormat;   int i;        // Cull backs of polygons   glCullFace(GL_BACK);   glFrontFace(GL_CCW);   glEnable(GL_CULL_FACE);   glEnable(GL_DEPTH_TEST);        glGenTextures(2, textureObjects);        // Set up texture maps        // Cube Map   glBindTexture(GL_TEXTURE_CUBE_MAP, textureObjects[CUBE_MAP]);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,                       	GL_LINEAR_MIPMAP_LINEAR);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 	// Load Cube Map images   for(i = 0; i < 6; i++) 	{     	// Load this texture map 	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); 	pBytes = gltLoadTGA(szCubeFaces<em class='bbc'>, &iWidth, &iHeight,                       	&iComponents, &eFormat); 	glTexImage2D(cube<em class='bbc'>, 0, iComponents, iWidth, iHeight,                 	0, eFormat, GL_UNSIGNED_BYTE, pBytes); 	free(pBytes); 	}        // Color map   glBindTexture(GL_TEXTURE_2D, textureObjects[COLOR_MAP]);   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,                        GL_LINEAR_MIPMAP_LINEAR);   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);   pBytes = gltLoadTGA("tarnish.tga", &iWidth, &iHeight,                       	&iComponents, &eFormat);   glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight,                    0, eFormat, GL_UNSIGNED_BYTE, pBytes);   free(pBytes);      /////////////////////////////////////////////////////////////////////   // Set up the texture units   // First texture unit contains the color map   glActiveTexture(GL_TEXTURE0);   glEnable(GL_TEXTURE_2D);   glBindTexture(GL_TEXTURE_2D, textureObjects[COLOR_MAP]);   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);  // Decal tarnish      // Second texture unit contains the cube map   glActiveTexture(GL_TEXTURE1);   glBindTexture(GL_TEXTURE_CUBE_MAP, textureObjects[CUBE_MAP]);   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);   glEnable(GL_TEXTURE_CUBE_MAP);      // Multiply this texture by the one underneath   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);   } /////////////////////////////////////////////////////////// // Draw the skybox. This is just six quads, with texture // coordinates set to the corners of the cube map void DrawSkyBox(void)   {   GLfloat fExtent = 15.0f;      glBegin(GL_QUADS); 	////////////////////////////////////////////// 	// Negative X 	// Note, we must now use the multitexture version of glTexCoord 	glMultiTexCoord3f(GL_TEXTURE1, -1.0f, -1.0f, 1.0f); 	glVertex3f(-fExtent, -fExtent, fExtent);          glMultiTexCoord3f(GL_TEXTURE1, -1.0f, -1.0f, -1.0f); 	glVertex3f(-fExtent, -fExtent, -fExtent);          glMultiTexCoord3f(GL_TEXTURE1, -1.0f, 1.0f, -1.0f); 	glVertex3f(-fExtent, fExtent, -fExtent);          glMultiTexCoord3f(GL_TEXTURE1, -1.0f, 1.0f, 1.0f); 	glVertex3f(-fExtent, fExtent, fExtent);    . . .    . . .   glEnd();   }      // Called to draw scene void RenderScene(void)   {   // Clear the window   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        glPushMatrix();      frameCamera.ApplyCameraTransform(); // Move the camera about 	// Sky Box is manually textured 	glActiveTexture(GL_TEXTURE0); 	glDisable(GL_TEXTURE_2D); 	glActiveTexture(GL_TEXTURE1); 	glEnable(GL_TEXTURE_CUBE_MAP); 	glDisable(GL_TEXTURE_GEN_S); 	glDisable(GL_TEXTURE_GEN_T); 	glDisable(GL_TEXTURE_GEN_R);        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 	DrawSkyBox();   	// Use texgen to apply cube map 	glEnable(GL_TEXTURE_GEN_S); 	glEnable(GL_TEXTURE_GEN_T); 	glEnable(GL_TEXTURE_GEN_R); 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);          glActiveTexture(GL_TEXTURE0); 	glEnable(GL_TEXTURE_2D); 	glPushMatrix();   	glTranslatef(0.0f, 0.0f, -3.0f);       	glActiveTexture(GL_TEXTURE1);   	glMatrixMode(GL_TEXTURE);   	glPushMatrix();              // Invert camera matrix (rotation only) and apply to        // texture coordinates   	M3DMatrix44f m, invert;   	frameCamera.GetCameraOrientation(m);   	m3dInvertMatrix44(invert, m);   	glMultMatrixf(invert);          glColor3f(1.0f, 1.0f, 1.0f);   	gltDrawSphere(0.75f, 41, 41);     	glPopMatrix();   	glMatrixMode(GL_MODELVIEW); 	glPopMatrix();   glPopMatrix();        // Do the buffer Swap   glutSwapBuffers();   }  <br />
<strong class='bbc'>Texture Combiners</strong><br />
 In Chapter 6, "More on Colors and Materials," you learned how to use the blending equation to control the way color fragments were blended together when multiple layers of geometry were drawn in the color buffer (typically back to front). OpenGL's texture combiners allow the same sort of control (only better) for the way multiple texture fragments are combined. By default, you can simply choose one of the texture environment modes (GL_DECAL, GL_REPLACE, GL_MODULATE, or GL_ADD) for each texture unit, and the results of each texture application are then added to the next texture unit. These texture environments were covered in Chapter 8.<br />
<br />
 Texture combiners add a new texture environment, GL_COMBINE, that allows you to explicitly set the way texture fragments from each texture unit are combined. To use texture combiners, you call glTexEnv in the following manner:<br />
<br />
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);  Texture combiners are controlled entirely through the glTexEnv function. Next, you need to select which texture combiner function you want to use. The combiner function selector, which can be either GL_COMBINE_RGB or GL_COMBINE_ALPHA, becomes the second argument to the glTexEnv function. The third argument becomes the texture environment function that you want to employ (for either RGB or alpha values). These functions are listed in Table 9.4. For example, to select the GL_REPLACE combiner for RGB values, you would call the following function:<br />
<br />
  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);  This combiner does little more than duplicate the normal GL_REPLACE texture environment.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Table 9.4 Texture Combiner Functions</strong></strong><br />
        <strong class='bbc'>Constant</strong><br />
<br />
   <strong class='bbc'>Function</strong><br />
<br />
     GL_REPLACE<br />
<br />
   Arg0<br />
<br />
     GL_MODULATE<br />
<br />
   Arg0 * Arg1<br />
<br />
     GL_ADD<br />
<br />
   Arg0 + Arg1<br />
<br />
     GL_ADD_SIGNED<br />
<br />
   Arg0 + Arg1 – 0.5<br />
<br />
     GL_INTERPOLATE<br />
<br />
   (Arg0 * Arg2) + (Arg1 * (1 – Arg2))<br />
<br />
     GL_SUBTRACT<br />
<br />
   Arg0 – Arg1<br />
<br />
     GL_DOT3_RGB/GL_DOT3_RGBA<br />
<br />
   4*((Arg0r – 0.5) * (Arg1r – 0.5) + (Arg0g – 0.5) * (Arg1g – 0.5) + (Arg0b – 0.5) * (Arg1b – 0.5))<br />
<br />
     The values of Arg0 – Arg2 are from source and operand values set with more calls to glTexEnv. The values GL_SOURCE<em class='bbc'>x</em>_RGB and GL_SOURCE<em class='bbc'>x</em>_ALPHA are used to specify the RGB or alpha combiner function arguments, where <em class='bbc'>x</em> is 0, 1, or 2. The values for these sources are given in Table 9.5.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Table 9.5 Texture Combiner Sources</strong></strong><br />
        <strong class='bbc'>Constant</strong><br />
<br />
   <strong class='bbc'>Description</strong><br />
<br />
     GL_TEXTURE<br />
<br />
   The texture bound to the current active texture unit<br />
<br />
     GL_TEXTURE<em class='bbc'>x</em><br />
<br />
   The texture bound to texture unit <em class='bbc'>x</em><br />
<br />
     GL_CONSTANT<br />
<br />
   The color (or alpha) value set by the texture environment variable GL_TEXTURE_ENV_COLOR<br />
<br />
     GL_PRIMARY_COLOR<br />
<br />
   The color (or alpha) value coming from the original geometry fragment<br />
<br />
     GL_PREVIOUS<br />
<br />
   The color (or alpha) value resulting from the previous texture unit's texture environment<br />
<br />
     For example, to select the texture from texture unit 0 for Arg0, you would make the following function call:<br />
<br />
  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);  You also have some additional control over what values are used from a given source for each argument. To set these operands, you use the constant GL_OPERAND<em class='bbc'>x</em>_RGB or GL_OPERAND[i]x</em>_ALPHA, where [i]x</em> is 0, 1, or 2. The valid operands and their meanings are given in Table 9.6.<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Table 9.6 Texture Combiner Operands</strong></strong><br />
        <strong class='bbc'>Constant</strong><br />
<br />
   <strong class='bbc'>Meaning</strong><br />
<br />
     GL_SRC_COLOR<br />
<br />
   The color values from the source. This may not be used with GL_OPERAND[i]x</em>_ALPHA.<br />
<br />
     GL_ONE_MINUS_SRC_COLOR<br />
<br />
   One's complement (1-value) of the color values from the source. This may not be used with GL_OPERAND[i]x</em>_ALPHA.<br />
<br />
     GL_SRC_ALPHA<br />
<br />
   The alpha values of the source.<br />
<br />
     GL_ONE_MINUS_SRC_ALPHA<br />
<br />
   One's complement (1-value) of the alpha values from the source.<br />
<br />
     For example, if you have two textures loaded on the first two texture units, and you want to multiply the color values from both textures during the texture application, you would set it up as shown here:<br />
<br />
  // Tell OpenGL you want to use texture combiners glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); // Tell OpenGL which combiner you want to use (GL_MODULATE for RGB values) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); // Tell OpenGL to use texture unit 0's color values for Arg0 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); // Tell OpenGL to use texture unit 1's color values for Arg1 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE1); glTexenvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);  Finally, with texture combiners, you can also specify a constant RGB or alpha scaling factor. The default parameters for these are as shown here:<br />
<br />
  glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.0f); glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f);  Texture combiners add a lot of flexibility to legacy OpenGL implementations. For ultimate control over how texture layers can be combined, we will later turn to shaders.<br />
<br />
 <br />
<strong class='bbc'>Point Sprites</strong><br />
 Point sprites are an exciting feature supported by OpenGL version 1.5 and later. Although OpenGL has always supported texture mapped points, prior to version 1.5 this meant a single texture coordinate applied to an entire point. Large textured points were simply large versions of a single filtered texel. With point sprites you can place a 2D textured image anywhere onscreen by drawing a single 3D point.<br />
<br />
 Probably the most common application of point sprites is for particle systems. A large number of particles moving onscreen can be represented as points to produce a number of visual effects. However, representing these points as small overlapped 2D images can produce dramatic streaming animated filaments. For example, <a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig14.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.14</a> shows a well-known screensaver on the Macintosh powered by just such a particle effect.<br />
<br />
 <a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig14.jpg' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/oglch9excerpt/th09fig14.jpg' alt='Posted Image' class='bbc_img' /></a> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch9excerpt/09fig14.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 9.14</a></strong><br />
A particle effect in the flurry screen saver.<br />
<br />
 Before point sprites, achieving this type of effect was a matter of drawing a large number of textured quads onscreen. This could be accomplished either by performing a costly rotation to each individual quad to make sure that it faced the camera, or by drawing all particles in a 2D orthographic projection. Point sprites allow you to render a perfectly aligned textured 2D square by sending down a single 3D vertex. At one-quarter the bandwidth of sending down four vertices for a quad, and no client-side matrix monkey business to keep the 3D quad aligned with the camera, point sprites are a potent and efficient feature of OpenGL.<br />
<br />
  <br />
<strong class='bbc'>Using Points</strong><br />
 Point sprites are very easy to use. Simply bind to a 2D texture, enable GL_POINT_SPRITE, set the texture environment target GL_POINT_SPRITE's GL_COORD_REPLACE parameter to true, and send down 3D points:<br />
<br />
  glBindTexture(GL_TEXTURE_2D, objectID); glEnable(GL_POINT_SPR]]></description>
		<pubDate>Mon, 28 Apr 2008 12:42:51 +0000</pubDate>
		<guid isPermaLink="false">e39505ef839c38f61139ae78da3f7615</guid>
	</item>
	<item>
		<title>Excerpt from OpenGL® Programming Guide 6th Ed.</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/excerpt-from-opengl%c2%ae-programming-guide-6th-ed-r2490</link>
		<description><![CDATA[<strong class='bbc'>Ed Note:</strong> The links in this document will not work properly. Please use the <a href='http://www.gamedev.net/reference/programming/features/oglch3excerpt/default.asp' class='bbc_url' title=''>Featured version</a> for web browsing.   <a href='http://www.gamedev.net/columns/books/bookdetails.asp?productid=697' class='bbc_url' title=''>http://www.informit.com/ShowCover.asp?isbn=0321481003&type=c</a>  Excerpt from <em class='bbc'>OpenGL® Programming Guide: The Official Guide to Learning OpenGL®, Version 2.1, 6th Edition</em>.    By Dave Shreiner, Mason Woo, Jackie Neider, and Tom Davis<br />
Published by Addison Wesley Professional<br />
ISBN-10: 0-321-48100-3<br />
ISBN-13: 978-0-321-48100-9   <br />
<strong class='bbc'>Chapter Objectives</strong><br />
 After reading this chapter, you'll be able to do the following:<br />
<br />
 <ul class='bbc'><li>View a <em class='bbc'>geometric model</em> in any orientation by transforming it in three-dimensional space </li><li>Control the location in three-dimensional space from which the model is viewed </li><li>Clip undesired portions of the model out of the scene that's to be viewed </li><li>Manipulate the appropriate matrix stacks that control model transformation for viewing, and project the model onto the screen </li><li>Combine multiple transformations to mimic sophisticated systems in motion, such as a solar system or an articulated robot arm </li><li>Reverse or mimic the operations of the geometric processing pipeline</li></ul> Chapter 2 explained how to instruct OpenGL to draw the geometric models you want displayed in your scene. Now you must decide how you want to position the models in the scene, and you must choose a vantage point from which to view the scene. You can use the default positioning and vantage point, but most likely you want to specify them.<br />
<br />
 Look at the image on the cover of this book. The program that produced that image contained a single geometric description of a building block. Each block was carefully positioned in the scene: some blocks were scattered on the floor, some were stacked on top of each other on the table, and some were assembled to make the globe. Also, a particular viewpoint had to be chosen. Obviously, we wanted to look at the corner of the room containing the globe. But how far away from the scene—and where exactly—should the viewer be? We wanted to make sure that the final image of the scene contained a good view out the window, that a portion of the floor was visible, and that all the objects in the scene were not only visible but presented in an interesting arrangement. This chapter explains how to use OpenGL to accomplish these tasks: how to position and orient models in three-dimensional space and how to establish the location—also in three-dimensional space—of the viewpoint. All of these factors help determine exactly what image appears on the screen.<br />
<br />
 You want to remember that the point of computer graphics is to create a two-dimensional image of three-dimensional objects (it has to be two-dimensional because it's drawn on a flat screen), but you need to think in three-dimensional coordinates while making many of the decisions that determine what is drawn on the screen. A common mistake people make when creating three-dimensional graphics is to start thinking too soon that the final image appears on a flat, two-dimensional screen. Avoid thinking about which pixels need to be drawn, and instead try to visualize three-dimensional space. Create your models in some three-dimensional universe that lies deep inside your computer, and let the computer do its job of calculating which pixels to color.<br />
<br />
 A series of three computer operations converts an object's three-dimensional coordinates to pixel positions on the screen:<br />
<br />
 <ul class='bbc'><li>Transformations, which are represented by matrix multiplication, include modeling, viewing, and projection operations. Such operations include rotation, translation, scaling, reflecting, orthographic projection, and perspective projection. Generally, you use a combination of several transformations to draw a scene. </li><li>Since the scene is rendered on a rectangular window, objects (or parts of objects) that lie outside the window must be clipped. In three-dimensional computer graphics, clipping occurs by throwing out objects on one side of a clipping plane. </li><li>Finally, a correspondence must be established between the transformed coordinates and screen pixels. This is known as a <em class='bbc'>viewport</em> transformation.</li></ul> This chapter describes all of these operations, and how to control them, in the following major sections:<br />
<br />
 <ul class='bbc'><li>"Overview: The Camera Analogy" gives an overview of the transformation process by describing the analogy of taking a photograph with a camera, presents a simple example program that transforms an object, and briefly describes the basic OpenGL transformation commands. </li><li>"Viewing and Modeling Transformations" explains in detail how to specify and imagine the effect of viewing and modeling transformations. These transformations orient the model and the camera relative to each other to obtain the desired final image. </li><li>"Projection Transformations" describes how to specify the shape and orientation of the <em class='bbc'>viewing volume</em>. The viewing volume determines how a scene is projected onto the screen (with a perspective or orthographic projection) and which objects or parts of objects are clipped out of the scene. </li><li>"Viewport Transformation" explains how to control the conversion of three-dimensional model coordinates to screen coordinates. </li><li>"Troubleshooting Transformations" presents some tips for discovering why you might not be getting the desired effect from your modeling, viewing, projection, and viewport transformations. </li><li>"Manipulating the Matrix Stacks" discusses how to save and restore certain transformations. This is particularly useful when you're drawing complicated objects that are built from simpler ones. </li><li>"Additional Clipping Planes" describes how to specify additional clipping planes beyond those defined by the viewing volume. </li><li>"Examples of Composing Several Transformations" walks you through a couple of more complicated uses for transformations. </li><li>"Reversing or Mimicking Transformations" shows you how to take a transformed point in window coordinates and reverse the transformation to obtain its original object coordinates. The transformation itself (without reversal) can also be emulated.</li></ul> In Version 1.3, new OpenGL functions were added to directly support row-major (in OpenGL terms, transposed) matrices.<br />
<br />
 <br />
<strong class='bbc'>Overview: The Camera Analogy</strong><br />
 The transformation process used to produce the desired scene for viewing is analogous to taking a photograph with a camera. As shown in <a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig01.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-1</a>, the steps with a camera (or a computer) might be the following:<br />
<br />
 <ul class='bbcol decimal'><li> Set up your tripod and point the camera at the scene (viewing transformation). </li><li> Arrange the scene to be photographed into the desired composition (modeling transformation). </li><li> Choose a camera lens or adjust the zoom (projection transformation). </li><li> Determine how large you want the final photograph to be—for example, you might want it enlarged (viewport transformation).</li></ul> After these steps have been performed, the picture can be snapped or the scene can be drawn.<br />
<br />
 <a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig01.jpg' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig01.jpg' alt='Posted Image' class='bbc_img' /></a> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig01.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-1</a></strong><br />
The Camera Analogy<br />
<br />
 Note that these steps correspond to the order in which you specify the desired transformations in your program, not necessarily the order in which the relevant mathematical operations are performed on an object's vertices. The viewing transformations must precede the modeling transformations in your code, but you can specify the projection and viewport transformations at any point before drawing occurs. <a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig02.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-2</a> shows the order in which these operations occur on your computer.<br />
<br />
 <a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig02.jpg' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig02.jpg' alt='Posted Image' class='bbc_img' /></a> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig02.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-2</a></strong><br />
Stages of Vertex Transformation<br />
<br />
 To specify viewing, modeling, and projection transformations, you construct a 4 x 4 matrix <strong class='bbc'>M</strong>, which is then multiplied by the coordinates of each vertex <em class='bbc'>v</em> in the scene to accomplish the transformation:<br />
<br />
 <em class='bbc'>v<strong class='bbc'>' = Mv</strong></em><br />
<br />
 (Remember that vertices always have four coordinates (<em class='bbc'>x, y, z, w</em>), although in most cases <em class='bbc'>w</em> is 1, and for two-dimensional data, <em class='bbc'>z</em> is 0.) Note that viewing and modeling transformations are automatically applied to surface normal vectors, in addition to vertices. (Normal vectors are used only in <em class='bbc'>eye coordinates</em>.) This ensures that the normal vector's relationship to the vertex data is properly preserved.<br />
<br />
 The viewing and modeling transformations you specify are combined to form the modelview matrix, which is applied to the incoming <em class='bbc'>object coordinates</em> to yield eye coordinates. Next, if you've specified additional clipping planes to remove certain objects from the scene or to provide cutaway views of objects, these clipping planes are applied.<br />
<br />
 After that, OpenGL applies the projection matrix to yield <em class='bbc'>clip coordinates</em>. This transformation defines a viewing volume; objects outside this volume are clipped so that they're not drawn in the final scene. After this point, the <em class='bbc'>perspective division</em> is performed by dividing coordinate values by <em class='bbc'>w</em>, to produce <em class='bbc'>normalized device coordinates</em>. (See Appendix F for more information about the meaning of the <em class='bbc'>w</em>-coordinate and how it affects matrix transformations.) Finally, the transformed coordinates are converted to <em class='bbc'>window coordinates</em> by applying the viewport transformation. You can manipulate the dimensions of the viewport to cause the final image to be enlarged, shrunk, or stretched.<br />
<br />
 You might correctly suppose that the <em class='bbc'>x-</em> and <em class='bbc'>y</em>-coordinates are sufficient to determine which pixels need to be drawn on the screen. However, all the transformations are performed on the <em class='bbc'>z</em>-coordinates as well. This way, at the end of this transformation process, the <em class='bbc'>z</em>-values correctly reflect the depth of a given vertex (measured in distance away from the screen). One use for this depth value is to eliminate unnecessary drawing. For example, suppose two vertices have the same <em class='bbc'>x-</em> and <em class='bbc'>y</em>-values but different <em class='bbc'>z</em>-values. OpenGL can use this information to determine which surfaces are obscured by other surfaces and can then avoid drawing the hidden surfaces. (See Chapter 5 and Chapter 10 for more information about this technique, which is called <em class='bbc'>hidden-surface removal</em>.)<br />
<br />
 As you've probably guessed by now, you need to know a few things about matrix mathematics to get the most out of this chapter. If you want to brush up on your knowledge in this area, you might consult a textbook on linear algebra.<br />
<br />
  <br />
<strong class='bbc'>A Simple Example: Drawing a Cube</strong><br />
 Example 3-1 draws a cube that's scaled by a modeling transformation (see Figure 3-3). The viewing transformation, <strong class='bbc'>gluLookAt()</strong>, positions and aims the camera toward where the cube is drawn. A projection transformation and a viewport transformation are also specified. The rest of this section walks you through Example 3-1 and briefly explains the transformation commands it uses. The succeeding sections contain a complete, detailed discussion of all OpenGL transformation commands.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig03.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig03.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-3</strong><br />
Transformed Cube<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Example 3-1</strong> Transformed Cube: cube.c</strong><br />
  void init(void)  {   glClearColor(0.0, 0.0, 0.0, 0.0);   glShadeModel(GL_FLAT); } void display(void) {   glClear(GL_COLOR_BUFFER_BIT);   glColor3f(1.0, 1.0, 1.0);   glLoadIdentity();   	/* clear the matrix */   	/* viewing transformation */   gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);   glScalef(1.0, 2.0, 1.0);   /* modeling transformation */    glutWireCube(1.0);   glFlush(); } void reshape(int w, int h) {   glViewport(0, 0, (GLsizei) w, (GLsizei) h);    glMatrixMode(GL_PROJECTION);   glLoadIdentity();   glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);   glMatrixMode(GL_MODELVIEW); } int main(int argc, char** argv) {   glutInit(&argc, argv);   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);   glutInitWindowSize(500, 500);    glutInitWindowPosition(100, 100);   glutCreateWindow(argv[0]);   init();   glutDisplayFunc(display);    glutReshapeFunc(reshape);   glutMainLoop();   return 0; }  </a> <br />
<strong class='bbc'>The Viewing Transformation</strong><br />
 Recall that the viewing transformation is analogous to positioning and aiming a camera. In this code example, before the viewing transformation can be specified, the <em class='bbc'>current matrix</em> is set to the identity matrix with <strong class='bbc'>glLoadIdentity()</strong>. This step is necessary since most of the transformation commands multiply the current matrix by the specified matrix and then set the result to be the current matrix. If you don't clear the current matrix by loading it with the identity matrix, you continue to combine previous transformation matrices with the new one you supply. In some cases, you do want to perform such combinations, but you also need to clear the matrix sometimes.<br />
<br />
 In Example 3-1, after the matrix is initialized, the viewing transformation is specified with <strong class='bbc'>gluLookAt()</strong>. The arguments for this command indicate where the camera (or eye position) is placed, where it is aimed, and which way is up. The arguments used here place the camera at (0, 0, 5), aim the camera lens toward (0, 0, 0), and specify the <em class='bbc'>up-vector</em> as (0, 1, 0). The up-vector defines a unique orientation for the camera.<br />
<br />
 If <strong class='bbc'>gluLookAt()</strong> was not called, the camera has a default position and orientation. By default, the camera is situated at the origin, points down the negative <em class='bbc'>z</em>-axis, and has an up-vector of (0, 1, 0). Therefore, in Example 3-1, the overall effect is that <strong class='bbc'>gluLookAt()</strong> moves the camera five units along the <em class='bbc'>z</em>-axis. (See "Viewing and Modeling Transformations" for more information about viewing transformations.)<br />
<br />
  <br />
<strong class='bbc'>The Modeling Transformation</strong><br />
 You use the modeling transformation to position and orient the model. For example, you can rotate, translate, or scale the model—or perform some combination of these operations. In Example 3-1, <strong class='bbc'>glScalef()</strong> is the modeling transformation that is used. The arguments for this command specify how scaling should occur along the three axes. If all the arguments are 1.0, this command has no effect. In Example 3-1, the cube is drawn twice as large in the <em class='bbc'>y</em>-direction. Thus, if one corner of the cube had originally been at (3.0, 3.0, 3.0), that corner would wind up being drawn at (3.0, 6.0, 3.0). The effect of this modeling transformation is to transform the cube so that it isn't a cube but a rectangular box.<br />
<br />
 <strong class='bbc'>Try This</strong><br />
<br />
 Change the <strong class='bbc'>gluLookAt()</strong> call in Example 3-1 to the modeling transformation <strong class='bbc'>glTranslatef()</strong> with parameters (0.0, 0.0, –5.0). The result should look exactly the same as when you used <strong class='bbc'>gluLookAt()</strong>. Why are the effects of these two commands similar?<br />
<br />
 Note that instead of moving the camera (with a viewing transformation) so that the cube could be viewed, you could have moved the cube away from the camera (with a modeling transformation). This duality in the nature of viewing and modeling transformations is why you need to think about the effects of both types of transformations simultaneously. It doesn't make sense to try to separate the effects, but sometimes it's easier to think about them in one way more than in the other. This is also why modeling and viewing transformations are combined into the <em class='bbc'>modelview matrix</em> before the transformations are applied. (See "Viewing and Modeling Transformations" for more information about on how to think about modeling and viewing transformations and how to specify them to get the results you want.)<br />
<br />
 Also note that the modeling and viewing transformations are included in the <strong class='bbc'>display()</strong> routine, along with the call that's used to draw the cube, <strong class='bbc'>glutWireCube()</strong>. In this way, <strong class='bbc'>display()</strong> can be used repeatedly to draw the contents of the window if, for example, the window is moved or uncovered, and you've ensured that the cube is drawn in the desired way each time, with the appropriate transformations. The potential repeated use of <strong class='bbc'>display()</strong> underscores the need to load the identity matrix before performing the viewing and modeling transformations, especially when other transformations might be performed between calls to <strong class='bbc'>display()</strong>.<br />
<br />
  <br />
<strong class='bbc'>The Projection Transformation</strong><br />
 Specifying the projection transformation is like choosing a lens for a camera. You can think of this transformation as determining what the field of view or viewing volume is and therefore what objects are inside it and to some extent how they look. This is equivalent to choosing among wide-angle, normal, and telephoto lenses, for example. With a wide-angle lens, you can include a wider scene in the final photograph than you can with a telephoto lens, but a telephoto lens allows you to photograph objects as though they're closer to you than they actually are. In computer graphics, you don't have to pay $10,000 for a 2,000-millimeter telephoto lens; once you've bought your graphics workstation, all you need to do is use a smaller number for your field of view.<br />
<br />
 In addition to the field-of-view considerations, the projection transformation determines how objects are <em class='bbc'>projected</em> onto the screen, as the term suggests. Two basic types of projections are provided for you by OpenGL, along with several corresponding commands for describing the relevant parameters in different ways. One type is the <em class='bbc'>perspective</em> projection, which matches how you see things in daily life. Perspective makes objects that are farther away appear smaller; for example, it makes railroad tracks appear to converge in the distance. If you're trying to make realistic pictures, you'll want to choose perspective projection, which is specified with the <strong class='bbc'>glFrustum()</strong> command in Example 3-1.<br />
<br />
 The other type of projection is <em class='bbc'>orthographic</em>, which maps objects directly onto the screen without affecting their relative sizes. Orthographic projection is used in architectural and computer-aided design applications where the final image needs to reflect the measurements of objects, rather than how they might look. Architects create perspective drawings to show how particular buildings or interior spaces look when viewed from various vantage points; the need for orthographic projection arises when blueprint plans or elevations, which are used in the construction of buildings, are generated. (See "Projection Transformations" for a discussion of ways to specify both kinds of projection transformations.)<br />
<br />
 Before <strong class='bbc'>glFrustum()</strong> can be called to set the projection transformation, some preparation is needed. As shown in the <strong class='bbc'>reshape()</strong> routine in Example 3-1, the command called <strong class='bbc'>glMatrixMode()</strong> is used first, with the argument GL_PROJECTION. This indicates that the current matrix specifies the projection transformation and that subsequent transformation calls affect the <em class='bbc'>projection matrix</em>. As you can see, a few lines later, <strong class='bbc'>glMatrixMode()</strong> is called again, this time with GL_MODELVIEW as the argument. This indicates that succeeding transformations now affect the modelview matrix instead of the projection matrix. (See "Manipulating the Matrix Stacks" for more information about how to control the projection and modelview matrices.)<br />
<br />
 Note that <strong class='bbc'>glLoadIdentity()</strong> is used to initialize the current projection matrix so that only the specified projection transformation has an effect. Now <strong class='bbc'>glFrustum()</strong> can be called, with arguments that define the parameters of the projection transformation. In this example, both the projection transformation and the viewport transformation are contained in the <strong class='bbc'>reshape()</strong> routine, which is called when the window is first created and whenever the window is moved or reshaped. This makes sense, because both projecting (the width-to-height aspect ratio of the projection viewing volume) and applying the viewport relate directly to the screen, and specifically to the size or aspect ratio of the window on the screen.<br />
<br />
 <strong class='bbc'>Try This</strong><br />
<br />
 Change the <strong class='bbc'>glFrustum()</strong> call in Example 3-1 to the more commonly used Utility Library routine <strong class='bbc'>gluPerspective()</strong>, with parameters (60.0, 1.0, 1.5, 20.0). Then experiment with different values, especially for <em class='bbc'>fovy</em> and <em class='bbc'>aspect</em>.<br />
<br />
  <br />
<strong class='bbc'>The Viewport Transformation</strong><br />
 Together, the projection transformation and the viewport transformation determine how a scene is mapped onto the computer screen. The projection transformation specifies the mechanics of how the mapping should occur, and the viewport indicates the shape of the available screen area into which the scene is mapped. Since the viewport specifies the region the image occupies on the computer screen, you can think of the viewport transformation as defining the size and location of the final processed photograph—for example, whether the photograph should be enlarged or shrunk.<br />
<br />
 The arguments for <strong class='bbc'>glViewport()</strong> describe the origin of the available screen space within the window—(0, 0) in this example—and the width and height of the available screen area, all measured in pixels on the screen. This is why this command needs to be called within <strong class='bbc'>reshape()</strong>: if the window changes size, the viewport needs to change accordingly. Note that the width and height are specified using the actual width and height of the window; often, you want to specify the viewport in this way, rather than give an absolute size. (See "Viewport Transformation" for more information about how to define the viewport.)<br />
<br />
  <br />
<strong class='bbc'>Drawing the Scene</strong><br />
 Once all the necessary transformations have been specified, you can draw the scene (that is, take the photograph). As the scene is drawn, OpenGL transforms each vertex of every object in the scene by the modeling and viewing transformations. Each vertex is then transformed as specified by the projection transformation and clipped if it lies outside the viewing volume described by the projection transformation. Finally, the remaining transformed vertices are divided by <em class='bbc'>w</em> and mapped onto the viewport.<br />
<br />
  <br />
<strong class='bbc'>General-Purpose Transformation Commands</strong><br />
 This section discusses some OpenGL commands that you might find useful as you specify desired transformations. You've already seen two of these commands: <strong class='bbc'>glMatrixMode()</strong> and <strong class='bbc'>glLoadIdentity()</strong>. Four commands described here—<strong class='bbc'>glLoadMatrix*()</strong>, <strong class='bbc'>glLoadTransposeMatrix*()</strong>, <strong class='bbc'>glMultMatrix*()</strong>, and <strong class='bbc'>glMultTransposeMatrix*()</strong>—allow you to specify any transformation matrix directly or to multiply the current matrix by that specified matrix. More specific transformation commands—such as <strong class='bbc'>gluLookAt()</strong> and <strong class='bbc'>glScale*()</strong>—are described in later sections.<br />
<br />
 As described in the preceding section, you need to state whether you want to modify the modelview or projection matrix before supplying a transformation command. You choose the matrix with <strong class='bbc'>glMatrixMode()</strong>. When you use nested sets of OpenGL commands that might be called repeatedly, remember to reset the matrix mode correctly. (The <strong class='bbc'>glMatrixMode()</strong> command can also be used to indicate the <em class='bbc'>texture matrix</em>; texturing is discussed in detail in "The Texture Matrix Stack" in Chapter 9.)<br />
<br />
       void <strong class='bbc'>glMatrixMode</strong>(GLenum <em class='bbc'>mode</em>);<br />
<br />
     Specifies whether the modelview, projection, or texture matrix will be modified, using the argument GL_MODELVIEW, GL_PROJECTION, or GL_TEXTURE for <em class='bbc'>mode</em>. Subsequent transformation commands affect the specified matrix. Note that only one matrix can be modified at a time. By default, the modelview matrix is the one that's modifiable, and all three matrices contain the identity matrix.<br />
<br />
     You use the <strong class='bbc'>glLoadIdentity()</strong> command to clear the currently modifiable matrix for future transformation commands, as these commands modify the current matrix. Typically, you always call this command before specifying projection or viewing transformations, but you might also call it before specifying a modeling transformation.<br />
<br />
       void <strong class='bbc'>glLoadIdentity</strong>(void);<br />
<br />
     Sets the currently modifiable matrix to the 4 x 4 identity matrix.<br />
<br />
     If you want to specify explicitly a particular matrix to be loaded as the current matrix, use <strong class='bbc'>glLoadMatrix*()</strong> or <strong class='bbc'>glLoadTransposeMatrix*()</strong>. Similarly, use <strong class='bbc'>glMultMatrix*()</strong> or <strong class='bbc'>glMultTransposeMatrix*()</strong> to multiply the current matrix by the matrix passed in as an argument.<br />
<br />
       void <strong class='bbc'>glLoadMatrix</strong>{fd}(const <em class='bbc'>TYPE</em> *<em class='bbc'>m</em>);<br />
<br />
     Sets the 16 values of the current matrix to those specified by <em class='bbc'>m</em>.<br />
<br />
           void <strong class='bbc'>glMultMatrix</strong>{fd}(const <em class='bbc'>TYPE</em> *<em class='bbc'>m</em>);<br />
<br />
     Multiplies the matrix specified by the 16 values pointed to by <em class='bbc'>m</em> by the current matrix and stores the result as the current matrix.<br />
<br />
     All matrix multiplication with OpenGL occurs as follows. Suppose the current matrix is <strong class='bbc'>C</strong> and the matrix specified with <strong class='bbc'>glMultMatrix*()</strong> or any of the transformation commands is <strong class='bbc'>M</strong>. After multiplication, the final matrix is always <strong class='bbc'>CM</strong>. Since matrix multiplication isn't generally commutative, the order makes a difference.<br />
<br />
 The argument for <strong class='bbc'>glLoadMatrix*()</strong> and <strong class='bbc'>glMultMatrix*()</strong> is a vector of 16 values (<em class='bbc'>m</em><sub class='bbc'>1</sub>, <em class='bbc'>m</em><sub class='bbc'>2</sub>, ... , <em class='bbc'>m</em><sub class='bbc'>16</sub>) that specifies a matrix <strong class='bbc'>M</strong> stored in column-major order as follows:<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/eq301.gif' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 If you're programming in C and you declare a matrix as <em class='bbc'>m</em>[4][4], then the element <em class='bbc'>m<em class='bbc'>[j]</em> is in the <em class='bbc'>i</em>th column and <em class='bbc'>j</em>th row of the common OpenGL transformation matrix. This is the reverse of the standard C convention in which <em class='bbc'>m<em class='bbc'>[j]</em> is in row <em class='bbc'>i</em> and column <em class='bbc'>j</em>. One way to avoid confusion between the column and row is to declare your matrices as <em class='bbc'>m</em>[16].<br />
<br />
 Another way to avoid possible confusion is to call the OpenGL routines <strong class='bbc'>glLoadTransposeMatrix*()</strong> and <strong class='bbc'>glMultTransposeMatrix*()</strong>, which use row-major (the standard C convention) matrices as arguments.<br />
<br />
       void <strong class='bbc'>glLoadTransposeMatrix</strong>{fd}(const <em class='bbc'>TYPE</em> *<em class='bbc'>m</em>);<br />
<br />
     Sets the 16 values of the current matrix to those specified by <em class='bbc'>m</em>, whose values are stored in row-major order. <strong class='bbc'>glLoadTransposeMatrix*(<em class='bbc'>m)</em></strong> has the same effect as <strong class='bbc'>glLoadMatrix*(<em class='bbc'>m<sup class='bbc'>T)</sup></em></strong>.<br />
<br />
           void <strong class='bbc'>glMultTransposeMatrix</strong>{fd}(const <em class='bbc'>TYPE</em> *<em class='bbc'>m</em>);<br />
<br />
     Multiplies the matrix specified by the 16 values pointed to by <em class='bbc'>m</em> by the current matrix and stores the result as the current matrix. <strong class='bbc'>glMultTransposeMatrix*(<em class='bbc'>m)</em></strong> has the same effect as <strong class='bbc'>glMultMatrix*(<em class='bbc'>m<sup class='bbc'>T)</sup></em></strong>.<br />
<br />
     You might be able to maximize efficiency by using display lists to store frequently used matrices (and their inverses), rather than recomputing them. (See "Display List Design Philosophy" in Chapter 7.) OpenGL implementations often must compute the inverse of the modelview matrix so that normals and clipping planes can be correctly transformed to eye coordinates.<br />
<br />
 <br />
<strong class='bbc'>Viewing and Modeling Transformations</strong><br />
 Viewing and modeling transformations are inextricably related in OpenGL and are in fact combined into a single modelview matrix. (See "A Simple Example: Drawing a Cube.") One of the toughest problems newcomers to computer graphics face is understanding the effects of combined three-dimensional transformations. As you've already seen, there are alternative ways to think about transformations—do you want to move the camera in one direction or move the object in the opposite direction? Each way of thinking about transformations has advantages and disadvantages, but in some cases one way more naturally matches the effect of the intended transformation. If you can find a natural approach for your particular application, it's easier to visualize the necessary transformations and then write the corresponding code to specify the matrix manipulations. The first part of this section discusses how to think about transformations; later, specific commands are presented. For now, we use only the matrix-manipulation commands you've already seen. Finally, keep in mind that you must call <strong class='bbc'>glMatrixMode()</strong> with GL_MODELVIEW as its argument prior to performing modeling or viewing transformations.<br />
<br />
 <br />
<strong class='bbc'>Thinking about Transformations</strong><br />
 Let's start with a simple case of two transformations: a 45-degree counterclockwise rotation about the origin around the <em class='bbc'>z</em>-axis and a translation down the <em class='bbc'>x</em>-axis. Suppose that the object you're drawing is small compared with the translation (so that you can see the effect of the translation) and that it's originally located at the origin. If you rotate the object first and then translate it, the rotated object appears on the <em class='bbc'>x</em>-axis. If you translate it down the <em class='bbc'>x</em>-axis first, however, and then rotate about the origin, the object is on the line <em class='bbc'>y = x</em>, as shown in Figure 3-4. In general, the order of transformations is critical. If you do transformation A and then transformation B, you almost always get something different than if you do them in the opposite order.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig04.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig04.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure3-4</strong><br />
Rotating First or Translating First<br />
<br />
 Now let's talk about the order in which you specify a series of transformations. All viewing and modeling transformations are represented as 4 x 4 matrices. Each successive <strong class='bbc'>glMultMatrix*()</strong> or transformation command multiplies a new 4 x 4 matrix <strong class='bbc'>M</strong> by the current modelview matrix <strong class='bbc'>C</strong> to yield <strong class='bbc'>CM</strong>. Finally, vertices <em class='bbc'>v</em> are multiplied by the current modelview matrix. This process means that the last transformation command called in your program is actually the first one applied to the vertices: <strong class='bbc'>CMv</strong>. Thus, one way of looking at it is to say that you have to specify the matrices in the reverse order. Like many other things, however, once you've gotten used to thinking about this correctly, backward will seem like forward.<br />
<br />
 Consider the following code sequence, which draws a single point using three transformations:<br />
<br />
  glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(N);        /* apply transformation N */ glMultMatrixf(M);        /* apply transformation M */ glMultMatrixf(L);        /* apply transformation L */ glBegin(GL_POINTS); glVertex3f(v);          /* draw transformed vertex v */ glEnd();  With this code, the modelview matrix successively contains <strong class='bbc'>I</strong>, <strong class='bbc'>N</strong>, <strong class='bbc'>NM</strong>, and finally <strong class='bbc'>NML</strong>, where <strong class='bbc'>I</strong> represents the identity matrix. The transformed vertex is <strong class='bbc'>NMLv</strong>. Thus, the vertex transformation is <strong class='bbc'>N(M(Lv))</strong>—that is, <strong class='bbc'>v</strong> is multiplied first by <strong class='bbc'>L</strong>, the resulting <strong class='bbc'>Lv</strong> is multiplied by <strong class='bbc'>M</strong>, and the resulting <strong class='bbc'>MLv</strong> is multiplied by <strong class='bbc'>N</strong>. Notice that the transformations to vertex <strong class='bbc'>v</strong> effectively occur in the opposite order than they were specified. (Actually, only a single multiplication of a vertex by the modelview matrix occurs; in this example, the <strong class='bbc'>N</strong>, <strong class='bbc'>M</strong>, and <strong class='bbc'>L</strong> matrices are already multiplied into a single matrix before it's applied to <strong class='bbc'>v</strong>.)<br />
<br />
 </a> <br />
<strong class='bbc'>Grand, Fixed Coordinate System</strong><br />
 Thus, if you like to think in terms of a grand, fixed coordinate system—in which matrix multiplications affect the position, orientation, and scaling of your model—you have to think of the multiplications as occurring in the opposite order from how they appear in the code. Using the simple example shown on the left side of <a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig04.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-4 (a rotation about the origin and a translation along the <em class='bbc'>x</em>-axis), if you want the object to appear on the axis after the operations, the rotation must occur first, followed by the translation. To do this, you'll need to reverse the order of operations, so the code looks something like this (where <strong class='bbc'>R</strong> is the rotation matrix and <strong class='bbc'>T</strong> is the translation matrix):<br />
<br />
  glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(T);        /* translation */ glMultMatrixf®;        /* rotation */ draw_the_object();  </a> <br />
<strong class='bbc'>Moving a Local Coordinate System</strong><br />
 Another way to view matrix multiplications is to forget about a grand, fixed coordinate system in which your model is transformed and instead imagine that a local coordinate system is tied to the object you're drawing. All operations occur relative to this changing coordinate system. With this approach, the matrix multiplications now appear in the natural order in the code. (Regardless of which analogy you're using, the code is the same, but how you think about it differs.) To see this in the translation-rotation example, begin by visualizing the object with a coordinate system tied to it. The translation operation moves the object and its coordinate system down the <em class='bbc'>x</em>-axis. Then, the rotation occurs about the (now-translated) origin, so the object rotates in place in its position on the axis.<br />
<br />
 This approach is what you should use for applications such as articulated robot arms, where there are joints at the shoulder, elbow, and wrist, and on each of the fingers. To figure out where the tips of the fingers go relative to the body, you'd like to start at the shoulder, go down to the wrist, and so on, applying the appropriate rotations and translations at each joint. Thinking about it in reverse would be far more confusing.<br />
<br />
 This second approach can be problematic, however, in cases where scaling occurs, and especially so when the scaling is nonuniform (scaling different amounts along the different axes). After uniform scaling, translations move a vertex by a multiple of what they did before, as the coordinate system is stretched. Non-uniform scaling mixed with rotations may make the axes of the local coordinate system nonperpendicular.<br />
<br />
 As mentioned earlier, you normally issue viewing transformation commands in your program before any modeling transformations. In this way, a vertex in a model is first transformed into the desired orientation and then transformed by the viewing operation. Since the matrix multiplications must be specified in reverse order, the viewing commands need to come first. Note, however, that you don't need to specify either viewing or modeling transformations if you're satisfied with the default conditions. If there's no viewing transformation, the "camera" is left in the default position at the origin, pointing toward the negative <em class='bbc'>z</em>-axis; if there's no modeling transformation, the model isn't moved, and it retains its specified position, orientation, and size.<br />
<br />
 Since the commands for performing modeling transformations can be used to perform viewing transformations, modeling transformations are <em class='bbc'>discussed</em> first, even if viewing transformations are actually <em class='bbc'>issued</em> first. This order for discussion also matches the way many programmers think when planning their code. Often, they write all the code necessary to compose the scene, which involves transformations to position and orient objects correctly relative to each other. Next, they decide where they want the viewpoint to be relative to the scene they've composed, and then they write the viewing transformations accordingly.<br />
<br />
  <br />
<strong class='bbc'>Modeling Transformations</strong><br />
 The three OpenGL routines for modeling transformations are <strong class='bbc'>glTranslate*()</strong>, <strong class='bbc'>glRotate*()</strong>, and <strong class='bbc'>glScale*()</strong>. As you might suspect, these routines transform an object (or coordinate system, if you're thinking of it in that way) by moving, rotating, stretching, shrinking, or reflecting it. All three commands are equivalent to producing an appropriate translation, rotation, or scaling matrix, and then calling <strong class='bbc'>glMultMatrix*()</strong> with that matrix as the argument. However, using these three routines might be faster than using <strong class='bbc'>glMultMatrix*()</strong>. OpenGL automatically computes the matrices for you. (See Appendix F if you're interested in the details.)<br />
<br />
 In the command summaries that follow, each matrix multiplication is described in terms of what it does to the vertices of a geometric object using the fixed coordinate system approach, and in terms of what it does to the local coordinate system that's attached to an object.<br />
<br />
  <br />
<strong class='bbc'>Translate</strong><br />
       void <strong class='bbc'>glTranslate</strong>{fd}(<em class='bbc'>TYPE</em> <em class='bbc'>x</em>, <em class='bbc'>TYPE y</em>, <em class='bbc'>TYPE</em> <em class='bbc'>z</em>);<br />
<br />
     Multiplies the current matrix by a matrix that moves (translates) an object by the given <em class='bbc'>x-</em>, <em class='bbc'>y</em>-, and <em class='bbc'>z</em>-values (or moves the local coordinate system by the same amounts).<br />
<br />
     Figure 3-5 shows the effect of <strong class='bbc'>glTranslate*()</strong>.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig05.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig05.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-5</strong><br />
Translating an Object<br />
<br />
 Note that using (0.0, 0.0, 0.0) as the argument for <strong class='bbc'>glTranslate*()</strong> is the identity operation—that is, it has no effect on an object or its local coordinate system.<br />
<br />
 </a> <br />
<strong class='bbc'>Rotate</strong><br />
       void <strong class='bbc'>glRotate</strong>{fd}(TYPE <em class='bbc'>angle</em>, TYPE <em class='bbc'>x</em>, TYPE <em class='bbc'>y</em>, TYPE <em class='bbc'>z</em>);<br />
<br />
     Multiplies the current matrix by a matrix that rotates an object (or the local coordinate system) in a counterclockwise direction about the ray from the origin through the point (<em class='bbc'>x, y, z</em>). The <em class='bbc'>angle</em> parameter specifies the angle of rotation in degrees.<br />
<br />
     The effect of <strong class='bbc'>glRotatef(</strong>45.0, 0.0, 0.0, 1.0<strong class='bbc'>)</strong>, which is a rotation of 45 degrees about the <em class='bbc'>z</em>-axis, is shown in Figure 3-6.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig06.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig06.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-6</strong><br />
Rotating an Object<br />
<br />
 Note that an object that lies farther from the axis of rotation is more dramatically rotated (has a larger orbit) than an object drawn near the axis. Also, if the <em class='bbc'>angle</em> argument is zero, the <strong class='bbc'>glRotate*()</strong> command has no effect.<br />
<br />
 </a> <br />
<strong class='bbc'>Scale</strong><br />
       void <strong class='bbc'>glScale</strong>{fd}(<em class='bbc'>TYPE</em> <em class='bbc'>x</em>, <em class='bbc'>TYPE y</em>, <em class='bbc'>TYPE</em> <em class='bbc'>z</em>);<br />
<br />
     Multiplies the current matrix by a matrix that stretches, shrinks, or reflects an object along the axes. Each <em class='bbc'>x-</em>, <em class='bbc'>y-</em>, and <em class='bbc'>z</em>-coordinate of every point in the object is multiplied by the corresponding argument <em class='bbc'>x</em>, <em class='bbc'>y</em>, or <em class='bbc'>z</em>. With the local coordinate system approach, the local coordinate axes are stretched, shrunk, or reflected by the <em class='bbc'>x-</em>, <em class='bbc'>y-</em>, and <em class='bbc'>z</em>-factors, and the associated object is transformed with them.<br />
<br />
     Figure 3-7 shows the effect of <strong class='bbc'>glScalef(</strong>2.0, –0.5, 1.0<strong class='bbc'>)</strong>.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig07.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig07.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-7</strong><br />
Scaling and Reflecting an Object<br />
<br />
 <strong class='bbc'>glScale*()</strong> is the only one of the three modeling transformations that changes the apparent size of an object: scaling with values greater than 1.0 stretches an object, and using values less than 1.0 shrinks it. Scaling with a -1.0 value reflects an object across an axis. The identity values for scaling are (1.0, 1.0, 1.0). In general, you should limit your use of <strong class='bbc'>glScale*()</strong> to those cases where it is necessary. Using <strong class='bbc'>glScale*()</strong> decreases the performance of lighting calculations, because the normal vectors have to be renormalized after transformation.<br />
<br />
 [indent]  <strong class='bbc'>Note -</strong> A scale value of zero collapses all object coordinates along that axis to zero. It's usually not a good idea to do this, because such an operation cannot be undone. Mathematically speaking, the matrix cannot be inverted, and inverse matrices are required for certain lighting operations (see Chapter 5). Sometimes collapsing coordinates does make sense; the calculation of shadows on a planar surface is one such application (see "Shadows" in Chapter 14). In general, if a coordinate system is to be collapsed, the projection matrix should be used, rather than the modelview matrix.<br />
<br />
 [/indent] </a> <br />
<strong class='bbc'>A Modeling Transformation Code Example</strong><br />
 Example 3-2 is a portion of a program that renders a triangle four times, as shown in Figure 3-8. These are the four transformed triangles:<br />
<br />
 <ul class='bbc'><li> A solid wireframe triangle is drawn with no modeling transformation. </li><li> The same triangle is drawn again, but with a dashed line stipple, and translated (to the left—along the negative <em class='bbc'>x</em>-axis). </li><li> A triangle is drawn with a long dashed line stipple, with its height (<em class='bbc'>y</em>-axis) halved and its width (<em class='bbc'>x</em>-axis) increased by 50 percent. </li><li> A rotated triangle, made of dotted lines, is drawn.</li></ul> <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig08.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 3-8</strong><br />
Modeling Transformation Example<br />
<br />
 <br />
<strong class='bbc'><strong class='bbc'>Example 3-2</strong> Using Modeling Transformations: model.c</strong><br />
  glLoadIdentity(); glColor3f(1.0, 1.0, 1.0); draw_triangle();           	/* solid lines */ glEnable(GL_LINE_STIPPLE); 	/* dashed lines */ glLineStipple(1, 0xF0F0);  glLoadIdentity(); glTranslatef(-20.0, 0.0, 0.0); draw_triangle(); glLineStipple(1, 0xF00F); 	/*long dashed lines */ glLoadIdentity(); glScalef(1.5, 0.5, 1.0); draw_triangle(); glLineStipple(1, 0x8888); 	/* dotted lines */ glLoadIdentity(); glRotatef(90.0, 0.0, 0.0, 1.0); draw_triangle(); glDisable(GL_LINE_STIPPLE);  Note the use of <strong class='bbc'>glLoadIdentity()</strong> to isolate the effects of modeling transformations; initializing the matrix values prevents successive transformations from having a cumulative effect. Even though using <strong class='bbc'>glLoadIdentity()</strong> repeatedly has the desired effect, it may be inefficient, because you may have to respecify viewing or modeling transformations. (See "Manipulating the Matrix Stacks" for a better way to isolate transformations.)<br />
<br />
 [indent]  <strong class='bbc'>Note -</strong> Sometimes, programmers who want a continuously rotating object attempt to achieve this by repeatedly applying a rotation matrix that has small values. The problem with this technique is that because of round-off errors, the product of thousands of tiny rotations gradually drifts away from the value you really want (it might even become something that isn't a rotation). Instead of using this technique, increment the angle and issue a new rotation command with the new angle at each update step.<br />
<br />
 [/indent]  <br />
<strong class='bbc'>Nate Robins' Transformation Tutorial</strong><br />
 If you have downloaded Nate Robins' suite of tutorial programs, this is an opportune time to run the <strong class='bbc'>transformation</strong> tutorial. (For information on how and where to download these programs, see "Nate Robins' OpenGL Tutors.") With this tutorial, you can experiment with the effects of rotation, translation, and scaling.<br />
<br />
  <br />
<strong class='bbc'>Viewing Transformations</strong><br />
 A viewing transformation changes the position and orientation of the viewpoint. If you recall the camera analogy, the viewing transformation positions the camera tripod, pointing the camera toward the model. Just as you move the camera to some position and rotate it until it points in the desired direction, viewing transformations are generally composed of translations and rotations. Also remember that to achieve a certain scene composition in the final image or photograph, you can either move the camera or move all the objects in the opposite direction. Thus, a modeling transformation that rotates an object counterclockwise is equivalent to a viewing transformation that rotates the camera clockwise, for example. Finally, keep in mind that the viewing transformation commands must be called before any modeling transformations are performed, so that the modeling transformations take effect on the objects first.<br />
<br />
 You can manufacture a viewing transformation in any of several ways, as described next. You can also choose to use the default location and orientation of the viewpoint, which is at the origin, looking down the negative <em class='bbc'>z</em>-axis.<br />
<br />
 <ul class='bbc'><li> Use one or more modeling transformation commands (that is, <strong class='bbc'>glTranslate*()</strong> and <strong class='bbc'>glRotate*()</strong>). You can think of the effect of these transformations as moving the camera position or as moving all the objects in the world, relative to a stationary camera. </li><li> Use the Utility Library routine <strong class='bbc'>gluLookAt()</strong> to define a line of sight. This routine encapsulates a series of rotation and translation commands. </li><li> Create your own utility routine to encapsulate rotations and translations. Some applications might require custom routines that allow you to specify the viewing transformation in a convenient way. For example, you might want to specify the roll, pitch, and heading rotation angles of a plane in flight, or you might want to specify a transformation in terms of polar coordinates for a camera that's orbiting around an object.</li></ul>  <br />
<strong class='bbc'>Using glTranslate*() and glRotate*()</strong><br />
 When you use modeling transformation commands to emulate viewing transformations, you're trying to move the viewpoint in a desired way while keeping the objects in the world stationary. Since the viewpoint is initially located at the origin and since objects are often most easily constructed there as well (see Figure 3-9), you generally have to perform some transformation so that the objects can be viewed. Note that, as shown in the figure, the camera initially points down the negative <em class='bbc'>z</em>-axis. (You're seeing the back of the camera.)<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig09.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 3-9</strong><br />
Object and Viewpoint at the Origin<br />
<br />
 In the simplest case, you can move the viewpoint backward, away from the objects; this has the same effect as moving the objects forward, or away from the viewpoint. Remember that, by default, forward is down the negative <em class='bbc'>z</em>-axis; if you rotate the viewpoint, forward has a different meaning. Therefore, to put five units of distance between the viewpoint and the objects by moving the viewpoint, as shown in Figure 3-10, use<br />
<br />
  glTranslatef(0.0, 0.0, -5.0);  <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig10.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig10.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-10</strong><br />
Separating the Viewpoint and the Object<br />
<br />
 This routine moves the objects in the scene –5 units along the <em class='bbc'>z</em>-axis. This is also equivalent to moving the camera +5 units along the <em class='bbc'>z</em>-axis.<br />
<br />
 Now suppose you want to view the objects from the side. Should you issue a rotate command before or after the translate command? If you're thinking in terms of a grand, fixed coordinate system, first imagine both the object and the camera at the origin. You could rotate the object first and then move it away from the camera so that the desired side is visible. You know that with the fixed coordinate system approach, commands have to be issued in the opposite order in which they should take effect, so you know that you need to write the translate command in your code first and follow it with the rotate command.<br />
<br />
 Now let's use the local coordinate system approach. In this case, think about moving the object and its local coordinate system away from the origin; then, the rotate command is carried out using the now-translated coordinate system. With this approach, commands are issued in the order in which they're applied, so once again the translate command comes first. Thus, the sequence of transformation commands to produce the desired result is<br />
<br />
  glTranslatef(0.0, 0.0, -5.0); glRotatef(90.0, 0.0, 1.0, 0.0);  If you're having trouble keeping track of the effect of successive matrix multiplications, try using both the fixed and local coordinate system approaches and see whether one makes more sense to you. Note that with the fixed coordinate system, rotations always occur about the grand origin, whereas with the local coordinate system, rotations occur about the origin of the local system. You might also try using the <strong class='bbc'>gluLookAt()</strong> utility routine described next.<br />
<br />
 </a> <br />
<strong class='bbc'>Using the gluLookAt() Utility Routine</strong><br />
 Often, programmers construct a scene around the origin or some other convenient location and then want to look at it from an arbitrary point to get a good view of it. As its name suggests, the <strong class='bbc'>gluLookAt()</strong> utility routine is designed for just this purpose. It takes three sets of arguments, which specify the location of the viewpoint, define a reference point toward which the camera is aimed, and indicate which direction is up. Choose the viewpoint to yield the desired view of the scene. The reference point is typically somewhere in the middle of the scene. (If you've built your scene at the origin, the reference point is probably the origin.) It might be a little trickier to specify the correct up-vector. Again, if you've built some real-world scene at or around the origin and if you've been taking the positive <em class='bbc'>y</em>-axis to point upward, then that's your up-vector for <strong class='bbc'>gluLookAt()</strong>. However, if you're designing a flight simulator, up is the direction perpendicular to the plane's wings, from the plane toward the sky when the plane is right-side-up on the ground.<br />
<br />
 The <strong class='bbc'>gluLookAt()</strong> routine is particularly useful when you want to pan across a landscape, for instance. With a viewing volume that's symmetric in both <em class='bbc'>x</em> and <em class='bbc'>y</em>, the (<em class='bbc'>eyex, eyey, eyez</em>) point specified is always in the center of the image on the screen, so you can use a series of commands to move this point slightly, thereby panning across the scene.<br />
<br />
       void <strong class='bbc'>gluLookAt</strong>(GLdouble <em class='bbc'>eyex</em>, GLdouble <em class='bbc'>eyey</em>, GLdouble <em class='bbc'>eyez</em>, GLdouble <em class='bbc'>centerx</em>, GLdouble <em class='bbc'>centery</em>, GLdouble <em class='bbc'>centerz</em>, GLdouble <em class='bbc'>upx</em>, GLdouble <em class='bbc'>upy</em>, GLdouble <em class='bbc'>upz</em>);<br />
<br />
     Defines a viewing matrix and multiplies it to the right of the current matrix. The desired viewpoint is specified by <em class='bbc'>eyex</em>, <em class='bbc'>eyey</em>, and <em class='bbc'>eyez</em>. The <em class='bbc'>centerx</em>, <em class='bbc'>centery</em>, and <em class='bbc'>centerz</em> arguments specify any point along the desired line of sight, but typically they specify some point in the center of the scene being looked at. The <em class='bbc'>upx</em>, <em class='bbc'>upy</em>, and <em class='bbc'>upz</em> arguments indicate which direction is up (that is, the direction from the bottom to the top of the viewing volume).<br />
<br />
     In the default position, the camera is at the origin, is looking down the negative <em class='bbc'>z</em>-axis, and has the positive <em class='bbc'>y</em>-axis as straight up. This is the same as calling<br />
<br />
  gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);  The <em class='bbc'>z</em>-value of the reference point is –100.0, but could be any negative <em class='bbc'>z</em>, because the line of sight will remain the same. In this case, you don't actually want to call <strong class='bbc'>gluLookAt()</strong>, because this is the default (see Figure 3-11) and you are already there. (The lines extending from the camera represent the viewing volume, which indicates its field of view.)<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig11.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'>Figure 3-11</strong><br />
Default Camera Position<br />
<br />
 Figure 3-12 shows the effect of a typical <strong class='bbc'>gluLookAt()</strong> routine. The camera position (<em class='bbc'>eyex, eyey, eyez</em>) is at (4, 2, 1). In this case, the camera is looking right at the model, so the reference point is at (2, 4, –3). An orientation vector of (2, 2, –1) is chosen to rotate the viewpoint to this 45-degree angle.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/oglch3excerpt/th03fig12.jpg' alt='Posted Image' class='bbc_img' /></span> <strong class='bbc'><a href='http://images.gamedev.net/features/programming/oglch3excerpt/03fig12.jpg' class='bbc_url' title='External link' rel='nofollow external'>Figure 3-12</strong><br />
Using gluLookAt()<br />
<br />
 Therefore, to achieve this effect, call<br />
<br />
  gluLookAt(4.0, 2.0, 1.0, 2.0, 4.0, -3.0, 2.0, 2.0, -1.0);  Note that <strong class='bbc'>gluLookAt()</strong> is part of the Utility Library, rather than the basic OpenGL library. This isn't because it's not useful, but because it encapsulates several basic OpenGL commands—specifically, <strong class='bbc'>glTranslate*()</strong> and <strong class='bbc'>glRotate*()</strong>. To see this, imagine a camera located at an arbitrary viewpoint and oriented according to a line of sight, both as specified with <strong class='bbc'>gluLookAt()</strong> and a scene located at the origin. To "undo" what <strong class='bbc'>gluLookAt()</strong> does, you need to transform the camera so that it sits at the origin and points down the negative <em class='bbc'>z</em>-axis, the default position. A simple translate moves the camera to the origin. You can easily imagine a series of rotations about each of the three axes of a fixed coordinate system that would orient the camera so that it pointed toward negative <em class='bbc'>z</em>-values. Since OpenGL allows rotation about an arbitrary axis, you can accomplish any desired rotation of the camera with a single <strong class='bbc'>glRotate*()</strong> command.<br />
<br />
 [indent]  <strong class='bbc'>Note -</strong> You can have only one active viewing transformation. You cannot try to combine the effects of two viewing transformations, any more than a camera can have two tripods. If you want to change the position of the camera, make sure you call <strong class='bbc'>glLoadIdentity()</strong> to erase the effects of any current viewing transformation.<br />
<br />
 [/indent] </a> <br />
<strong class='bbc'>Nate Robins' Projection Tutorial</strong><br />
 If you have Nate Robins' suite of tutorial programs, run the <strong class='bbc'>projection</strong> tutorial. With this tutorial, you can see the effects of changes to the parameters of <strong class='bbc'>gluLookAt()</strong>.<br />
<br />
 <strong class='bbc'>Advanced</strong><br />
<br />
 To transform any arbitrary vector so that it's coincident with another arbitrary vector (for instance, the negative <em class='bbc'>z</em>-axis), you need to do a little mathematics. The axis about which you want to rotate is given by the cross product of the two normalized vectors. To find the angle of rotation, normalize the initial two vectors. The cosine of the desired angle between the vectors is equal to the dot product of the normalized vectors. The angle of rotation around the axis given by the cross product is always between 0 and 180 degrees. (See Appendix E for definitions of cross and dot products.)<br />
<br />
 Note that computing the angle between two normalized vectors by taking the inverse cosine of their dot product is not very accurate, especially for small angles, but it should work well enough to get you started.<br />
<br />
 <a name="Heading24" id="Heading24"> <br />
<strong class='bbc'>Creating a Custom Utility Routine</strong><br />
 <strong class='bbc'>Advanced</strong><br />
<br />
 For some specialized applications, you might want to define your own transformation routine. Since this is rarely done and is a fairly advanced topic, it's left mostly as an exercise for the reader. The following exercises suggest two custom viewing transformations that might be useful.<br />
<br />
 <strong class='bbc'>Try This</strong><br />
<br />
 <ul class='bbc'><li> Suppose you're writing a flight simulator and you'd like to display the world from the point of view of the pilot of a plane. The world is described in a coordinate system with the origin on the runway and the plane at coordinates (<em class='bbc'>x, y, z</em>). Suppose further that the plane has some <em class='bbc'>roll</em>, [i]pitch</em>, and [i]heading</em> (these are rotation angles of the plane relative to its center of gravity). </li><li> Show that the following routine could serve as the viewing transformation:<br /><br />  void pilotView{GLdouble planex, GLdouble planey,     	GLdouble planez, GLdouble ro</li></ul>]]></description>
		<pubDate>Fri, 04 Apr 2008 17:23:56 +0000</pubDate>
		<guid isPermaLink="false">e5fb88b398b042f6cccce46bf3fa53e8</guid>
	</item>
	<item>
		<title>Rendering efficient 2D sprites in OpenGL using...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/rendering-efficient-2d-sprites-in-opengl-using-r2429</link>
		<description><![CDATA[

<p>Ever wondered how to make a 2D game using OpenGL? Ever wanted to write an efficient and easy to use sprite engine via OpenGL and have the entire functionality of Direct3D's ID3DXSprite interface?
Hopefully my article can give you a hand with your questions and endeavors. I've read and heard many requests on how to write 2D games using the OpenGL API and I too hesitated to start writing 2D
games with OpenGL. Then, I thought of a great implementation as to how to do it fast, efficiently and with the same functionality Microsoft's Direct3D would give you using texture rectangles. Before
I begin, I want to explain some of the benefits that come along with using this technique:</p>
<ul>
<li>No need to use glDrawPixels, glCopyPixels, etc. - Better image quality than those.</li>
<li>Textures do not need to be square or power of 2 - Using a non power of 2 texture using GL_TEXTURE_2D can impact performance on many video cards. Of course you could always use gluBuild2DMipmaps
to solve this problem, but it uses up more video memory than what is really needed.</li>
<li>Actual bitmap dimensions can be used. - It's much easier to use the actual bitmap dimensions then to calculate them from the (s,t) coordinates and saves you time by eliminating the need to do
such calculations.</li>
</ul>
I'm assuming that the reader has a good understanding on how OpenGL works because I'm not going to get detailed on things that do not pertain to the subject here to keep this article as simplified as
possible so that anyone can learn. So if you're ready, let's dive into the code :) The first thing we want to do is setup our viewports and projections for 2D rendering. The code I used is a modified
version of its original written by Dwarf with Axe here on GameDev.net:
<pre class="code">
//-----------------------------------------------------------------------------
// Name: glEnable2D
// Desc: Enabled 2D primitive rendering by setting up the appropriate orthographic
//               perspectives and matrices.
//-----------------------------------------------------------------------------
void glEnable2D( void )
{
        GLint iViewport[4];

        // Get a copy of the viewport
        glGetIntegerv( GL_VIEWPORT, iViewport );

        // Save a copy of the projection matrix so that we can restore it 
        // when it's time to do 3D rendering again.
        glMatrixMode( GL_PROJECTION );
        glPushMatrix();
        glLoadIdentity();

        // Set up the orthographic projection
        glOrtho( iViewport[0], iViewport[0]+iViewport[2],
                         iViewport[1]+iViewport[3], iViewport[1], -1, 1 );
        glMatrixMode( GL_MODELVIEW );
        glPushMatrix();
        glLoadIdentity();

        // Make sure depth testing and lighting are disabled for 2D rendering until
        // we are finished rendering in 2D
        glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT );
        glDisable( GL_DEPTH_TEST );
        glDisable( GL_LIGHTING );
}


//-----------------------------------------------------------------------------
// Name: glDisable2D
// Desc: Disables 2D rendering and restores the previous matrix and render states
//               before they were modified.
//-----------------------------------------------------------------------------
void glDisable2D( void )
{
        glPopAttrib();
        glMatrixMode( GL_PROJECTION );
        glPopMatrix();
        glMatrixMode( GL_MODELVIEW );
        glPopMatrix();
}
</pre>
To use these functions, simply call glEnable2D() before you start rendering 2D and after you do any 3D rendering (if any). Then when you are done with your 2D rendering, simply call glDisable2D()
before you render the final scene or frame. Now that we have our 2D rendering code set up, we need to check to see if texture rectangles are supported. I personally use GL_NV_texture_rectangle, but
you can use GL_EXT_texture_rectangle if your video card doesn't support the NVIDIA extension. I use the NVIDIA extension because at the time of writing, I'm running an NVIDIA GeForce 6600 (256MB,
PCI-E), but either extension should work fine. Also, make sure you have the latest version of glext.h if you need it. Code? Okay...
<pre class="code">
//-----------------------------------------------------------------------------
// Name: InitScene
// Desc: Initializes extensions, textures, render states, etc. before rendering
//-----------------------------------------------------------------------------
int InitScene( void )
{
        // Is the extension supported on this driver/card?
        if( !glh_extension_supported( "GL_NV_texture_rectangle" ) )
        {
                printf( "ERROR: Texture rectangles not supported on this video card!" );
                Sleep(2000);
                exit(-1);
        }

        // NOTE: If your comp doesn't support GL_NV_texture_rectangle, you can try
        // using GL_EXT_texture_rectangle if you want, it should work fine.

        // Disable lighting
        glDisable( GL_LIGHTING );

        // Disable dithering
        glDisable( GL_DITHER );

        // Disable blending (for now)
        glDisable( GL_BLEND );

        // Disable depth testing
        glDisable( GL_DEPTH_TEST );

        return LoadSpriteTexture();
}
</pre>
The function glh_extension_supported() is coming from the NVIDIA SDK v9.5 (see glh_extensions.h). I was too lazy to write my own, plus I'm assuming you all should know how to check extensions anyway
:) Moving on, now that we have determined that this video card and driver supports hardware accelerated texture rectangles, we can continue on by loading our texture(s). Be sure to enable the
token(s) GL_TEXTURE_RECTANGLE_NV or GL_TEXTURE_RECTANGLE_EXT, from whichever extension you are using or else the texture will not show. From then on, simply replace GL_TEXTURE_2D with the token
matching the extension you're using.
<pre class="code">
// Enable the texture rectangle extension
glEnable( GL_TEXTURE_RECTANGLE_NV );

// Generate one texture ID
glGenTextures( 1, &g_uTextureID );
// Bind the texture using GL_TEXTURE_RECTANGLE_NV
glBindTexture( GL_TEXTURE_RECTANGLE_NV, g_uTextureID );
// Enable bilinear filtering on this texture
glTexParameteri( GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

// Write the 32-bit RGBA texture buffer to video memory
glTexImage2D( GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, pTexture_RGB->sizeX, pTexture_RGB->sizeY,
                          0, GL_RGBA, GL_UNSIGNED_BYTE, pTexture_RGBA );

// Save a copy of the texture's dimensions for later use
g_iTextureWidth = pTexture_RGB->sizeX;
g_iTextureHeight = pTexture_RGB->sizeY;
</pre>
Now that we have loaded the texture, we can render it to a primitive such as a quad. This is the easiest part, but be careful not to blit your texture upside down, because even though you're using
the bitmap dimensions, you're still using the (s,t) format so you're starting from the bottom left-hand corner.
<pre class="code">
// Enable 2D rendering
glEnable2D();
        
// Make the sprite 2 times bigger (optional)
glScalef( 2.0f, 2.0f, 0.0f );

// Blend the color key into oblivion! (optional)
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

// Set the primitive color to white
glColor3f( 1.0f, 1.0f, 1.0f );
// Bind the texture to the polygons
glBindTexture( GL_TEXTURE_RECTANGLE_NV, g_uTextureID );

// Render a quad
// Instead of the using (s,t) coordinates, with the  GL_NV_texture_rectangle
// extension, you need to use the actual dimensions of the texture.
// This makes using 2D sprites for games and emulators much easier now
// that you won't have to convert :)
glBegin( GL_QUADS );
 glTexCoord2i( 0, g_iTextureHeight );                           
 glVertex2i( 0, 0 );
 glTexCoord2i( g_iTextureWidth, g_iTextureHeight );     
 glVertex2i( g_iTextureWidth, 0 );
 glTexCoord2i( g_iTextureWidth, 0 );    
 glVertex2i( g_iTextureWidth, g_iTextureHeight );
 glTexCoord2i( 0, 0 );          
 glVertex2i( 0, g_iTextureHeight );
glEnd();

// Disable 2D rendering
glDisable2D();
</pre>
Now give this code a spin and you'll get something like this:
<div class="c1">
<p><img src="http://images.gamedev.net/features/programming/2dogl/fig1.png"></p>
</div>
<p>And there you have it! You can now render 2D sprites as efficiently as you would in Direct3D! Sure it's a little more code, but in the end it works! Of course, you could always make your own C++
wrapper classes or stuctures, but I wanted to keep things simplified for educational purposes. I'm also sure that there are many ways this code can be improved, but you can implement improvements as
you see fit to your own code. If you have any questions or suggestions about this, please e-mail me at <a href="mailto:blueshogun96@gmail.com.">blueshogun96@gmail.com</a>. Happy coding!</p>
<h2>References:</h2>
<p><a href="http://www.gamedev.net/community/forums/topic.asp?topic_id=104791&PageSize=25&WhichPage=2">Last Post about 2D in OpenGL</a><br>
<a href="http://developer.nvidia.com/object/sdk-9.html">NVIDIA SDK</a></p>

]]></description>
		<pubDate>Fri, 02 Nov 2007 09:14:33 +0000</pubDate>
		<guid isPermaLink="false">5c9b5c47258cf1499c2dc64b7072e735</guid>
	</item>
	<item>
		<title>Creating a GLSL Library</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/creating-a-glsl-library-r2428</link>
		<description><![CDATA[

<h1>Introduction</h1>
<p>There are plenty of examples of GLSL shaders available in print or on the web. In this article, rather than showing an a la carte example, we will go through the creation of a shader library.
Since the two most likely requirements in and OpenGL program are texturing and lighting the scene, those will be the two things we'll be doing. Specifically we'll be covering Texturing, and as an
extension Multi-Texturing, and Per-pixel Lighting for Directional, Point, and Spot Lights.</p>
<p>There a couple assumptions that are made in this article. First, it is assumed that you already know how to properly compile, link and use a shader in OpenGL. Second, it is assumed that you do not
need an explanation on the Phong Lighting Model. The references for this article cover those things so look to those if you want a thorough explanation of either of those things.</p>
<p>First thing we're going to do is create the Texturing library. This library is fairly simple, and admittedly overkill, but it provides a basis for going to the more complex Lighting library.</p>
<h1>A Texturing Example</h1>
<p>The vertex shader used in this example isn't very exciting so lets just get it out of the way.</p>
<pre class="code">
/**
 * \file Texturing.vert
 */
void main()
{
    gl_TexCoord[0] = gl_MultiTexCoord0;
   
    gl_Position = ftransform();
}
</pre>
All the vertex shader does is copy the multi-texture coordinate over for the fragment shader to use. The attribute array gl_MultiTexCoord0 is not available in the fragment shader so we need to
populate the gl_TexCoord[0] value with it. Then the vertex position gets transformed according to the current model view matrix.
<p>Now its time to write our Texturing library function.</p>
<p>There are six options for how to texture a geometry in OpenGL</p>
<ul>
<li>GL_REPLACE</li>
<li>GL_MODULATE</li>
<li>GL_DECAL</li>
<li>GL_BLEND</li>
<li>GL_ADD</li>
<li>GL_COMBINE</li>
</ul>
Each of these options has a different calculation for texturing that can be replicated in GLSL. So lets create a function that does just that.
<pre class="code">
/**
 * \file Texturing.frag
 */
const int REPLACE  = 0;
const int MODULATE = 1;
const int DECAL    = 2;
const int BLEND    = 3;
const int ADD      = 4;
const int COMBINE  = 5;

void applyTexture2D(in sampler2D texUnit, in int type, in int index, inout vec4 color)
{
    // Read from the texture
    vec4 texture = texture2D(texUnit, gl_TexCoord[index].st);
   
    if (type == REPLACE)
    {
        color = texture;
    }
    else if (type == MODULATE)
    {
        color *= texture;
    }
    else if (type == DECAL)
    {
        vec3 temp = mix(color.rgb, texture.rgb, texture.a);
       
        color = vec4(temp, color.a);
    }
    else if (type == BLEND)
    {
        vec3 temp = mix(color.rgb, gl_TextureEnvColor[index].rgb, texture.rgb);
       
        color = vec4(temp, color.a * texture.a);
    }
    else if (type == ADD)
    {
        color.rgb += texture.rgb;
        color.a   *= texture.a;
       
        color = clamp(color, 0.0, 1.0);
    }
    else
    {
        color = clamp(texture * color, 0.0, 1.0);
    }
}
</pre>
At the top of the code we create a set of constant integers to denote what type of texturing we want to apply to the geometry. The function itself takes four arguments. The first is a sampler2D which
is the texture unit holding the texture we want to apply. Second is the type which is one of the constant integers we defined. Third is the index of the texture coordinates we wish to use. And
finally color is the current color of the texel which will be modified and returned from the function. The code itself is taken from the Orange Book and can also be created using 3Dlabs ShaderGen
tool.
<p>So now we have a function that will replicate OpenGL's texturing facility. Now we just need to create the other fragment shader that uses this function.</p>
<pre class="code">
/**
 * SingleTexture.frag
 */

void applyTexture2D(in sampler2D texUnit, in int type, in int index, inout vec4 color);

uniform sampler2D TexUnit0;
uniform int TexturingType;

void main()
{
    vec4 color = gl_Color;
   
    applyTexture2D(TexUnit0, TexturingType, 0, color);
   
    gl_FragColor = color;
}
</pre>
The most important thing to remember when creating a shader library is to use forward declarations. The applyTexture2D function is in a different file so when this file is compiled the compiler needs
to have knowledge that there is a function called applyTexture2D and what its parameters are. When the shaders are linked together the linker will figure out the rest.
<p>Other than that the shader is fairly straightforward. There are two uniforms, the sampler2D which just points to the texture unit we wish to use, and the integer TexturingType which denotes what
OpenGL texturing to emulate. The main function just takes the color of the vertex and passes that along with TexUnit0, TexturingType and the index of the texture coordinates to the function. The
result of which is used as the fragment color.</p>
<p>Its worth noting that OpenGL does not provide a mechanism to query what the environment of the texture is (minus the texture environment color, gl_TextureEnvColor[]). So if you send via glTexEnv
that you want to use GL_ADD, there is no way inside the shader to determine that is being requested by the program.</p>
<h1>A Multi-Texturing Example</h1>
<p>Next up is Multi-Texturing. There is no longer a need to use any OpenGL extensions to do multi-texturing, all of it can be done within a fragment shader. You can blend together as many textures as
your video card supports (call glGetIntegerv with GL_MAX_TEXTURE_UNITS to determine that information), but in our case we'll only be doing two. No changes are required to our Texturing library or the
vertex shader we we're using, and we'll need to add three lines of code to our fragment shader to get two textures blended together.</p>
<pre class="code">
/**
 * \file MultiTexture.frag
 */
uniform sampler2D TexUnit0;
uniform int TexturingType0;
uniform sampler2D TexUnit1;
uniform int TexturingType1;

void main()
{
    vec4 color = gl_Color;
   
    applyTexture2D(TexUnit0, TexturingType0, 0, color);
    applyTexture2D(TexUnit1, TexturingType1, 0, color);
   
    gl_FragColor = color;
}
</pre>
So all that needed to be added was another sampler2D and another integer specifying what texturing to use. So hopefully you can see how creating a library can make your shaders a lot more concise,
and a lot more powerful. Now we can move onto creating a Lighting library for per-pixel lighting.
<h1>A One-Sided Per-Pixel Lighting Example</h1>
<p>This example is fairly complicated so the discussion is broken up into parts. The first part will be the vertex shader. Since we're doing everything in the pixel shader, the vertex shader is
fairly simple.</p>
<pre class="code">
/**
 * \file Lighting.vert
 */
varying vec3 normal;
varying vec3 vertex;

void main()
{
    // Calculate the normal
    normal = normalize(gl_NormalMatrix * gl_Normal);
   
    // Transform the vertex position to eye space
    vertex = vec3(gl_ModelViewMatrix * gl_Vertex);
       
    gl_Position = ftransform();
}
</pre>
All thats happening in the vertex shader is passing along the normal and the position of the vertex to the fragment shader. These values are needed for the lighting calculations coming in the
fragment shader.
<pre class="code">
/**
 * \file OneSidedLighting.frag
 */
void calculateLighting(in int numLights, in vec3 N, in vec3 V, in float shininess,
                       inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);

varying vec3 normal;
varying vec3 vertex;

void main()
{
    // Normalize the normal. A varying variable CANNOT
    // be modified by a fragment shader. So a new variable
    // needs to be created.
    vec3 n = normalize(normal);
   
    vec4 ambient  = vec4(0.0);
    vec4 diffuse  = vec4(0.0);
    vec4 specular = vec4(0.0);

    // In this case the built in uniform gl_MaxLights is used
    // to denote the number of lights. A better option may be passing
    // in the number of lights as a uniform or replacing the current
    // value with a smaller value.
    calculateLighting(gl_MaxLights, n, vertex, gl_FrontMaterial.shininess,
                      ambient, diffuse, specular);
   
    vec4 color = gl_FrontLightModelProduct.sceneColor  +
                 (ambient  * gl_FrontMaterial.ambient) +
                 (diffuse  * gl_FrontMaterial.diffuse) +
                 (specular * gl_FrontMaterial.specular);
                
    color = clamp(color, 0.0, 1.0);
   
    gl_FragColor = color;
}
</pre>
Now if this were some shader library we were integrating into our own shaders the only thing we'd need to know is the interface for the function. From there we'd assume that it was doing the proper
calculations and just leave it at that. But since this is a library that we're creating lets go over the functions of the Lighting library.
<h1>The Phong Lighting Shader</h1>
<p>This library is A LOT more complicated than our texturing library. There are a couple of auxillary functions used by this library to simplify the code. The first of which determines whether a
light is enabled.</p>
<pre class="code">
/**
 * \file PhongLighting.frag
 */
const vec4 AMBIENT_BLACK = vec4(0.0, 0.0, 0.0, 1.0);
const vec4 DEFAULT_BLACK = vec4(0.0, 0.0, 0.0, 0.0);

bool isLightEnabled(in int i)
{
    // A separate variable is used to get
    // rid of a linker error.
    bool enabled = true;
   
    // If all the colors of the Light are set
    // to BLACK then we know we don't need to bother
    // doing a lighting calculation on it.
    if ((gl_LightSource[i].ambient  == AMBIENT_BLACK) &&
        (gl_LightSource[i].diffuse  == DEFAULT_BLACK) &&
        (gl_LightSource[i].specular == DEFAULT_BLACK))
        enabled = false;
       
    return(enabled);
}
</pre>
A good chunk of the state information that is passed via an OpenGL program is available within a shader. Unfortunately there is no flag for whether or not a light is enabled. We can determine whether
a light is enabled by viewing its ambient, diffuse and specular contributions. OpenGL defines the default value of the ambient color of a light to be {0.0, 0.0, 0.0, 1.0} and the default value for
the diffuse and specular colors to be {0.0, 0.0, 0.0, 0.0} so if a light has those values we can be sure that it has no contribution to the scene. Otherwise its contribution needs to be calculated.
This information is used in the calculateLighting function to decrease the number of lights that need to be passed over.
<pre class="code">
/**
 * \file PhongLighting.frag
 */
void calculateLighting(in int numLights, in vec3 N, in vec3 V, in float shininess,
                       inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
{
    // Just loop through each light, and if its enabled add
    // its contributions to the color of the pixel.
    for (int i = 0; i < numLights; i++)
    {
        if (isLightEnabled(i))
        {
            if (gl_LightSource[i].position.w == 0.0)
                directionalLight(i, N, shininess, ambient, diffuse, specular);
            else if (gl_LightSource[i].spotCutoff == 180.0)
                pointLight(i, N, V, shininess, ambient, diffuse, specular);
            else
                 spotLight(i, N, V, shininess, ambient, diffuse, specular);
        }
    }
}
</pre>
OpenGL uses some cues to determine what type of light is being passed to it. Directional lights are assumed to have a position where the w value corresponds to 0.0. A Point Light has a w value of 1.0
in its position and a value of 180.0 for their spotCutoff value. And finally a Spot Light has a value in its spotCutoff of something other than 180.0. So if the light is enabled we use these cues to
determine what type of light we're encountering. Finally lets take a look at the actual lighting calculations for each type of light. The actual Phong Lighting equations are not gone over as they are
covered in much greater detail in the references.
<pre class="code">
/**
 * \file PhongLighting.frag
 */
float calculateAttenuation(in int i, in float dist)
{
    return(1.0 / (gl_LightSource[i].constantAttenuation +
                  gl_LightSource[i].linearAttenuation * dist +
                  gl_LightSource[i].quadraticAttenuation * dist * dist));
}

void directionalLight(in int i, in vec3 N, in float shininess,
                      inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
{
    vec3 L = normalize(gl_LightSource[i].position.xyz);
   
    float nDotL = dot(N, L);
   
    if (nDotL > 0.0)
    {   
        vec3 H = gl_LightSource[i].halfVector.xyz;
       
        float pf = pow(max(dot(N,H), 0.0), shininess);

        diffuse  += gl_LightSource[i].diffuse  * nDotL;
        specular += gl_LightSource[i].specular * pf;
    }
   
    ambient  += gl_LightSource[i].ambient;
}

void pointLight(in int i, in vec3 N, in vec3 V, in float shininess,
                inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
{
    vec3 D = gl_LightSource[i].position.xyz - V;
    vec3 L = normalize(D);

    float dist = length(D);
    float attenuation = calculateAttenuation(i, dist);

    float nDotL = dot(N,L);

    if (nDotL > 0.0)
    {   
        vec3 E = normalize(-V);
        vec3 R = reflect(-L, N);
       
        float pf = pow(max(dot(R,E), 0.0), shininess);

        diffuse  += gl_LightSource[i].diffuse  * attenuation * nDotL;
        specular += gl_LightSource[i].specular * attenuation * pf;
    }
   
    ambient  += gl_LightSource[i].ambient * attenuation;
}

void spotLight(in int i, in vec3 N, in vec3 V, in float shininess,
               inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
{
    vec3 D = gl_LightSource[i].position.xyz - V;
    vec3 L = normalize(D);

    float dist = length(D);
    float attenuation = calculateAttenuation(i, dist);

    float nDotL = dot(N,L);

    if (nDotL > 0.0)
    {   
        float spotEffect = dot(normalize(gl_LightSource[i].spotDirection), -L);
       
        if (spotEffect > gl_LightSource[i].spotCosCutoff)
        {
            attenuation *=  pow(spotEffect, gl_LightSource[i].spotExponent);

            vec3 E = normalize(-V);
            vec3 R = reflect(-L, N);
       
            float pf = pow(max(dot(R,E), 0.0), shininess);

            diffuse  += gl_LightSource[i].diffuse  * attenuation * nDotL;
            specular += gl_LightSource[i].specular * attenuation * pf;
        }
    }
   
    ambient  += gl_LightSource[i].ambient * attenuation;
}
</pre>
The attenuation factor of the light is calculated in a different function since it is used when calculating the contribution of both the Point and Spot lights.
<p>Now we have a library that handles per-pixel Phong Lighting. So lets take it a step further.</p>
<h1>A Two-Sided Per-Pixel Lighting Example</h1>
<p>OpenGL by default does two sided lighting. This means that lighting is calculated for the front and back faces of a polygon. This is really useful for something that is lit from the back, an
everyday example of this is a lamp shade.</p>
<p>The only thing that needs to be modified to achieve this is to modify our fragment shader's main function.</p>
<pre class="code">
/**
 * TwoSidedLighting.frag
 */
void main()
{
    // Normalize the normal. A varying variable CANNOT
    // be modified by a fragment shader. So a new variable
    // needs to be created.
    vec3 n = normalize(normal);
   
    vec4 ambient, diffuse, specular, color;

    // Initialize the contributions.
    ambient  = vec4(0.0);
    diffuse  = vec4(0.0);
    specular = vec4(0.0);
   
    // In this case the built in uniform gl_MaxLights is used
    // to denote the number of lights. A better option may be passing
    // in the number of lights as a uniform or replacing the current
    // value with a smaller value.
    calculateLighting(gl_MaxLights, n, vertex, gl_FrontMaterial.shininess,
                      ambient, diffuse, specular);
   
    color  = gl_FrontLightModelProduct.sceneColor  +
             (ambient  * gl_FrontMaterial.ambient) +
             (diffuse  * gl_FrontMaterial.diffuse) +
             (specular * gl_FrontMaterial.specular);

    // Re-initialize the contributions for the back
    // pass over the lights
    ambient  = vec4(0.0);
    diffuse  = vec4(0.0);
    specular = vec4(0.0);
          
    // Now caculate the back contribution. All that needs to be
    // done is to flip the normal.
    calculateLighting(gl_MaxLights, -n, vertex, gl_BackMaterial.shininess,
                      ambient, diffuse, specular);

    color += gl_BackLightModelProduct.sceneColor  +
             (ambient  * gl_BackMaterial.ambient) +
             (diffuse  * gl_BackMaterial.diffuse) +
             (specular * gl_BackMaterial.specular);

    color = clamp(color, 0.0, 1.0);
   
    gl_FragColor = color;
}
</pre>
The only thing that we needed to do was change reset the ambient, diffuse and specular values, flip the normal, and use the back material values. Now we have an even more accurate lighting
calculation available in our programs.
<h1>Conclusion</h1>
<p>Hopefully this article will give you an idea of how to write shader libraries. With the enclosed libraries you could combine Lighting and Texturing into a single pass. You could change the
lighting model from Phong to something else, such as Toon Shading. The possibilities with GLSL are enormous.</p>
<p>Just remember if you come up with something really cool to share with the rest of us. Thanks for reading.</p>
<h2>References</h2>
<p><a href="http://www.lighthouse3d.com/opengl/glsl/">GLSL Tutorial</a> - Lighthouse3D August 2007<br>
<a href="http://www.ozone3d.net/tutorials/glsl_lighting_phong.php">Lighting with GLSL : Phong Model</a> - oZone3D.net August 2007<br>
<a href="http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php">Per Fragment Lighting</a> - ClockworkCoders August 2007<br>
Rost, Randi J. <a href="http://www.amazon.com/OpenGL-R-Shading-Language-2nd/dp/0321334892/ref=pd_bbs_sr_1/104-6482565-4389548?ie=UTF8&s=books&qid=1193709537&sr=8-1">OpenGL Shading
Language</a> 1st ed. Boston : Addison-Wesley, 2004</p>
<h2>Useful Links</h2>
<p><a href="http://developer.3dlabs.com/downloads/shadergen/">ShaderGen</a> - Fixed Functionality Shader Generation Tool (used to emulate OpenGL texturing)<br>
<a href="http://www.opengl.org/sdk/tools/ShaderDesigner/">ShaderDesigner</a> - A GLSL IDE available in the OpenGL SDK (used for development of the enclosed shaders)</p>

]]></description>
		<pubDate>Mon, 29 Oct 2007 21:11:58 +0000</pubDate>
		<guid isPermaLink="false">ca0525bfe5cab4c577d169d3343a5452</guid>
	</item>
	<item>
		<title>OpenGL Frame Buffer Object 201</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/opengl-frame-buffer-object-201-r2333</link>
		<description><![CDATA[<span style='font-size: 18px;'><strong class='bbc'>	Introduction</strong></span><br />
<br />
In the last OpenGL Framebuffer object article we covered the basic usage of an FBO for rendering to a single texture and then applying that texture some where else. However this isn’t allthe FBO extension can do; indeed one of the integrated features of this extension which was touched upon briefly in the last article was that of attachment points.<br />
<br />
In this article we’ll go a little more in-depth into this aspect of the extension, first of all showing how you can use a single FBO to cycle through a number of textures to render to andfinish off with using the OpenGL Shading Language to render to multiple textures at the same time via the Draw Buffers extension.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	One FBO and Many Textures</strong></span><br />
<br />
In the last article we covered how to attach a texture to an FBO as a colour render target using the following function call:<br />
<br />
<pre class='prettyprint'>glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);</pre><br />
As you might recall, the function attaches the texture indicated by the value held in <em class='bbc'>img</em> to the currently bound FBO. In this article the point of interest is the second parameter:<em class='bbc'>GL_COLOR_ATTACHMENT0_EXT</em>.<br />
<br />
This parameter tells OpenGL to attach the texture to attachment point 0, however FBOs have many more colour attachment points which can be bound. The current specification allows for 16 attachmentpoints (<em class='bbc'>GL_COLOR_ATTACHMENT0_EXT</em> to <em class='bbc'>GL_COLOR_ATTACHMENT15_EXT</em>) each of which can point to a separate texture attached to it. However, the number you can render to depends on whetheryou are running on hardware and drivers; this can be queried using the following code:<br />
<br />
<pre class='prettyprint'>GLuint maxbuffers;<br />glGetIntergeri(GL_MAX_COLOR_ATTACHMENTS, &maxbuffers);</pre><br />
At this point <em class='bbc'>maxbuffers</em> holds the total number of colour attachments you can attach. On current hardware available at the time of writing the value returned will be a max of 4buffers.<br />
<br />
So, if we wanted to attach the texture indicated by <em class='bbc'>img</em> to the 2<sup class='bbc'>nd</sup> colour attachment point the above function call would become:<br />
<br />
<pre class='prettyprint'>glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, img, 0);</pre><br />
As you can see it is pretty easy to add textures, but how do we tell OpenGL where to render to?<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	Selecting The Destination</strong></span><br />
<br />
Well, in this case we go back to a function which has been around since the start of OpenGL; <em class='bbc'>glDrawBuffer()</em><br />
<br />
This function, and its relative <em class='bbc'>glReadBuffer()</em>, tells OpenGL where it should write data to and where it should read data from. By default both the draw and read buffers are set asGL_FRONT for single buffered contexts and GL_BACK for double buffered ones. With the advent of the FBO extension this function has been modified to allow you to select<em class='bbc'>GL_COLOR_ATTACHMENTx_EXT</em> for rendering to and reading from (where ‘x’ is the attachment point number).<br />
<br />
When you bind an FBO, the buffers are changed behind your back to <em class='bbc'>GL_COLOR_ATTACHMENT0_EXT</em>. So if you are only rendering to the default colour attachment point you don’t have tomake any changes, however when it comes to other buffers we have to tell OpenGL ourselves where we want it to render to.<br />
<br />
Thus if we want to render to <em class='bbc'>GL_COLOR_ATTACHMENT1_EXT</em> we would have to bind the FBO and set the write buffer to the correct attachment point. Assuming we have attached a texture to colourattachment point 1 for the FBO held in <em class='bbc'>fbo</em>, then rendering would look as follows:<br />
<br />
<pre class='prettyprint'>glBindFrameBuffer(GL_FRAMEBUFFER_EXT, fbo);<br />glPushAttrib(GL_VIEWPORT_BIT &#124; GL_COLOR_BUFFER_BIT);<br />glViewport(0,0,width, height);<br /><br />// Set the render target<br />glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);<br /><br />// Render as normal here<br />// output goes to the FBO and it’s attached buffers<br /><br />glPopAttrib();<br />glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);</pre><br />
Note the use of <em class='bbc'>glPushAttrib()</em> to save both the viewport and colour buffer configuration before we make the changes and the use of <em class='bbc'>glPopAttrib()</em> to restore them once we are done.This is because these changes affect both the FBO and main rendering context and we don’t want them active once we have completed rendering to the texture.<br />
<br />
An important point when attaching multiple textures to an FBO is that they all have to be of the same dimension and colour depth. So, you can’t attach a 512*512 32bit texture and a 256*25616bit texture to the same FBO. However if you can stay within these limits then it is possible to use one FBO to render to multiple textures, which is faster than switching between FBOs. While thisisn’t an overly slow operation, avoiding unneeded operations is often good practise.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	The first example</strong></span><br />
<br />
The first example program gives an example of rendering to 2 textures, one after each other, and then applying those textures to another cube. The code is based on the same example as used in thefirst article; there are some minor changes however.<br />
<br />
Firstly, in the FBO setup code in the init function we create and bind a second texture to the FBO we created. Notice how we bind it to different attachment point to the first texture by using<em class='bbc'>GL_COLOR_ATTACHMENT1_EXT</em> as the bind point.<br />
<br />
The rendering for the scene is basically the same as well, however instead of drawing the cube with its colours on once we draw it twice, the second time with the colours at half theintensity.<br />
<br />
You should notice in the example program that when we render to the FBO we explicitly tell OpenGL to render to <em class='bbc'>GL_COLOR_ATTACHMENT0_EXT</em> and then <em class='bbc'>GL_COLOR_ATTACHMENT1_EXT</em>; this isbecause the FBO remembers the last buffer you told it to draw to, so when the drawing loop runs for the second time the first texture isn’t updated as the drawing goes to the destination givenin the last <em class='bbc'>glDrawBuffer()</em> call, which in this case is <em class='bbc'>GL_COLOR_ATTACHMENT1_EXT</em>. To see this effect comment out line 133, which has the <em class='bbc'>glDrawBuffer()</em> call in it, and youwill notice the texture on the left hand cube is never updated.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	Multiple Render Targets</strong></span><br />
<br />
Now we know how to attach multiple textures to an FBO, however we are still only drawing to one texture at a time by switching the draw target and, as helpful as that might be, at the start of thearticle it was mentioned that we would be covering how to render to multiple textures at the same time.<br />
<br />
Well, it turns out that once you understand how to attach multiple textures at once the rest is pretty simple and all you need comes from the Draw Buffers extension and the OpenGL Shading Language(GLSL), both of which are core features of OpenGL 2.0.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	The Draw Buffers Extension</strong></span><br />
<br />
The first extension, Draw Buffers, builds upon the functionality provided by <em class='bbc'>glDrawBuffer()</em>. As you recall this function allows us to specify which colour buffer we are going to write to,the Draw Buffers extension expands upon this to allow us to specify multiple colour buffers to write to. The number of buffers you can render to at once can be queried as follows:<br />
<br />
<pre class='prettyprint'>GLuint maxbuffers;<br />glGetIntergeri(GL_MAX_DRAW_BUFFERS, &maxbuffers);</pre><br />
After which the variable <em class='bbc'>maxbuffers</em> holds the number of buffers we can render to at once (at the time of writing this value is typically 4, however the GeForce 8x00 series allows for upto 8 buffers to be drawn to).<br />
<br />
The function used to indicated which buffers to draw to takes the same values as the <em class='bbc'>glDrawBuffer()</em> for the targets, which means we can supply it with <em class='bbc'>GL_COLOR_ATTACHMENTx_EXT</em>values in order to write to multiple attached textures at the same time.<br />
<br />
Thus if we had textures attached to points 0 and 1, and wanted to render to both of them then we would do the following:<br />
<br />
<pre class='prettyprint'>GLenum buffers&#91;&#93; = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };<br />glDrawBuffers(2, buffers);</pre><br />
After this function is executed OpenGL is setup to render to both colour buffers, which brings us on to how this is done.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	MRT with FBO and GLSL</strong></span><br />
<br />
At this point if we were to render it using the standard Fixed Function Pipeline (as the examples have used thus far) then both textures would get the same data in them, however using GLSL we canwrite a fragment shader which allows us to send different data to the textures.<br />
<br />
Normally when you write a GLSL fragment shader you would output the colour value to <em class='bbc'>gl_FragColor</em>, which would then be written to the frame buffer as normal. However there is a second wayto write out colour information via the <em class='bbc'>gl_FragData[]</em> array.<br />
<br />
This special variable allows us to direct where the data is going and maps directly to the values given to <em class='bbc'>glDrawBuffers()</em>. So, in the case of the <em class='bbc'>glDrawBuffers()</em> call above thebuffers would map as follows:										<br />
<br />
<table border="1" style="width:50%"> <tbody><tr> <td width="50%"><center><strong>glDrawBuffers value</strong></center></td> <td width="50%"><center><strong>FragData syntax</strong></center></td> </tr> <tr> <td width="50%"><center>GL_COLOR_ATTACHMENT0_EXT</center></td> <td width="50%"><center>gl_FragData[0]</center></td> </tr> <tr> <td width="50%"><center>GL_COLOR_ATTACHMENT1_EXT</center></td> <td width="50%"><center>gl_FragData[1]</center></td> </tr> </tbody></table><br />
				    If we were to change the above function call however the mappings would change:<br />
<br />
<pre class='prettyprint'>GLenum buffers&#91;&#93; = { GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT0_EXT };<br />glDrawBuffers(2, buffers);</pre><br />
<table border="1"> <tbody><tr> <td width="50%"><center><strong>glDrawBuffers value</strong></center></td> <td width="50%"><center><strong>FragData syntax</strong></center></td> </tr> <tr> <td width="50%"><center>GL_COLOR_ATTACHMENT1_EXT</center></td> <td width="50%"><center>gl_FragData[0]</center></td> </tr> <tr> <td width="50%"><center>GL_COLOR_ATTACHMENT0_EXT</center></td> <td width="50%"><center>gl_FragData[1]</center></td> </tr> </tbody></table>	<br />
This is highlighted because it is the order the values are supplied to the <em class='bbc'>glDrawBuffers()</em> function, which dictates how they map to the <em class='bbc'>gl_FragData[]</em> array, not their values.<br />
<br />
Lets say that for some reason we wanted to write green to one render target and blue to the other, then the GLSL code would look as follows:<br />
<br />
<pre class="brush: cpp;">
<br />
#version 110<br />
<br />
void main()<br />
{<br />
	gl_FragData[0] = vec4(0.0, 1.0, 0.0);<br />
	gl_FragData[1] = vec4(0.0, 0.0, 1.0);<br />
}
</pre><br />
The first line says we need at least version 1.10 (OGL2.0) of the GLSL and the function body just writes green to the first buffer and blue to the second buffer.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	The Second Example</strong></span><br />
<br />
The second example is a hybrid of the first example and the example from the first article. It performs the same output as the first example from this article but only draws the cube to the FBOonce like the original article does; we achieve this by using a shader to control the output.<br />
<br />
As with before, the major difference is in the initialisation code. Leaving aside the loading of a GLSL program, which is beyond the scope of this article, the part which is required to make MRTrendering work with an FBO is the following two lines:<br />
<br />
<pre class='prettyprint'>GLenum mrt&#91;&#93; = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }<br />glDrawBuffers(2, mrt);</pre><br />
These two lines tell OpenGL that we wish to render to two buffers and what those two buffers are. Remember that an FBO remembers the last render target it was told to use, as such by doing thiswhile the FBO is bound we can set this at startup and not have to worry about doing so during the main rendering loop.<br />
<br />
The rendering loop should look familiar; the rendering to the FBO is the same as the original code, the only change being the call to bind and unbind the GLSL program which controls the colouroutput. The lower section is the same as the first example from this article, with the two cubes being rendered one with each texture on it.<br />
<br />
The two GLSL shaders themselves require a quick mention as they are somewhat central to how MRT works in this manner.<br />
<br />
The vertex shader, which is executed for each vertex you send to the graphics card, simply passes the colour value passed via <em class='bbc'>glColor()</em> to the fragment shader and transforms the vertex soit will be in the right place to draw the cube.<br />
<br />
The fragment shader used is as follows:<br />
<br />
<pre class='prettyprint'>#version 110<br /><br />void main(void)<br />{<br />	gl_FragData&#91;0&#93; = vec4(gl_Color.r, gl_Color.g,gl_Color.b,1.0);<br />	gl_FragData&#91;1&#93; = vec4(gl_Color.r/2.0, gl_Color.g/2.0,gl_Color.b/2.0,1.0);<br />}</pre><br />
The key lines are the two gl_FragData lines, these indicate which buffer we are writing to. In this case <em class='bbc'>gl_FragData[0]</em> is the first texture and it gets a copy of the unmodified colourpassed down from the vertex. On the other hand <em class='bbc'>gl_FragData[1]</em> is the second texture and gets the value of the colour passed from the vertex shader but halfed, thus giving the same output asthe first example.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	Final Thoughts</strong></span><br />
<br />
This article was designed to give you a quick overview and example of two more uses of the FBO extension.<br />
<br />
The first example allows you to use the same FBO to render to multiple textures without switching FBOs, this is a useful thing to know because while FBOs are light to change when compared topbuffers it is still much quicker to switch render targets than to switch between FBOs. As such if you can group your textures which need to be rendered to one at a time in such a way you can savesome time.<br />
<br />
The second example was to give you a feel for MRT rendering. While the example here is somewhat trivial, MRT does form a major part of various render-to-vertex buffer and post-processingtechniques, as such the ability to output to multiple colour buffers is a useful one to know.<br />
<br />
As before more details can be found in the <a href='http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt' class='bbc_url' title='External link' rel='nofollow external'>Framebuffer Object</a> spec and the <a href='http://www.opengl.org/registry/specs/ARB/draw_buffers.txt' class='bbc_url' title='External link' rel='nofollow external'>Draw Buffers</a> spec. <a href='http://www.gamedev.net/columns/books/bookdetails.asp?productid=570&CategoryID=15' class='bbc_url' title=''>More OpenGL GameProgramming</a> also has a chapter on FBOs and a chapter on GLSL, written by myself, which touches on using FBOs and MRT with GLSL some more.<br />
<br />
<strong class='bbc'>Notes on the example program</strong><br />
<br />
The example program* requires some form of GLUT to be compiled and run (I used <a href='http://freeglut.sourceforge.net/' class='bbc_url' title='External link' rel='nofollow external'>FreeGLUT</a>)<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>	References</strong></span><br />
<br />
<a href='http://www.gamedev.net/columns/books/bookdetails.asp?productid=570&CategoryID=15' class='bbc_url' title=''>More OpenGL Game Programming</a><br />
<a href='http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt' class='bbc_url' title='External link' rel='nofollow external'>Framebuffer Object Spec</a><br />
<a href='http://download.nvidia.com/developer/presentations/2005/GDC/OpenGL_Day/OpenGL_FrameBuffer_Object.pdf' class='bbc_url' title='External link' rel='nofollow external'>GDC 2005 Framebuffer Object pdf</a><br />
<br />
<span style='font-size: 10px;'><strong class='bbc'>*(Editors Note: </strong>The example program appears to have not been included with this article. Please contact the author if you are interested in obtaining these files)</span>]]></description>
		<pubDate>Thu, 14 Dec 2006 00:07:20 +0000</pubDate>
		<guid isPermaLink="false">a8ae104615cb4e966ddb435f3e575a02</guid>
	</item>
	<item>
		<title>OpenGL Frame Buffer Object 101</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/opengl-frame-buffer-object-101-r2331</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 The Frame Buffer Object (FBO) extension was introduced to make Render to Texture objects much more efficient and much easier to perform when compared with the copying or pbuffer alternatives.<br />
<br />
 In this little article I’m going to give you a quick over view of how to use this extension and some things to keep in mind when using it so you can add faster Render to Texture functionality to your OpenGL programs.<br />
<br />
 <br />
<strong class='bbc'>Setting Up</strong><br />
 As with the other objects in OpenGL (texture object, pixel buffer objects and vertex buffer object) before you can use a FBO you have to create a valid handle to it:<br />
<br />
  GLuint fbo; glGenFramebuffersEXT(1, &fbo);  To perform any operations on a FBO you need to bind it, much like you would a VBO or texture, so that the operations can be performed on it, this is done via the following code<br />
<br />
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);  The first parameter is the ‘target’ you wish to bind the framebuffer to, right now the only target you can use is the one indicated above however it is possible future extensions might allow you to bind it somewhere else. The <em class='bbc'>fbo</em> variable holds the handle to the FBO we requested earlier. To perform any FBO related operations you need to have a FBO bound or the calls will fail.<br />
<br />
 <br />
<strong class='bbc'>Adding a Depth Buffer</strong><br />
 A FBO on its own isn’t of much use, for it to be usable you have to attach some renderable objects to it; these can be textures or the newly introduced <strong class='bbc'>renderbuffers</strong>.<br />
<br />
 A <strong class='bbc'>renderbuffer</strong> are just objects which are used to support offscreen rendering, often for sections of the framebuffer which don’t have a texture format associated with them such as the stencil or depth buffer.<br />
<br />
 In this case we are going to use a <strong class='bbc'>renderbuffer</strong> to give our FBO a depth buffer to use while rendering.<br />
<br />
 Like the FBO we first of all have to get a handle to a valid <strong class='bbc'>renderbuffer</strong>:<br />
<br />
  GLuint depthbuffer; glGenRenderbuffersEXT(1, &depthbuffer);  Having successfully done this we need to bind the <strong class='bbc'>renderbuffer</strong> so that it is the current <strong class='bbc'>renderbuffer</strong> for the following operations:<br />
<br />
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);  As with a FBO bind the first parameter is the ‘target’ you wish to bind to, which right now can only be the indicated target. The <em class='bbc'>depthbuffer</em> variable holds the handle to the <strong class='bbc'>renderbuffer</strong> we’ll be working with after this.<br />
<br />
 At this point the <strong class='bbc'>renderbuffer</strong> doesn’t have any storage space associated with it, so we need to tell OpenGL how we want to use it and what size we’d like. In this case we are asking for a depth buffer of a certain size:<br />
<br />
  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);  Upon successful completion of the above code OpenGL will have allocated space for the <strong class='bbc'>renderbuffer</strong> to be used as a depth buffer with a given <em class='bbc'>width</em> and <em class='bbc'>height</em>. Note that <strong class='bbc'>renderbuffers</strong> can be used for normal RGB/RGBA storage and could be used to store stencil information.<br />
<br />
 Having reserved the space for the depth buffer the next job is to attach it to the FBO we created earlier.<br />
<br />
  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthbuffer);  While it might look a bit imposing the function is pretty easy to understand; all it is doing is attaching the <em class='bbc'>depthbuffer</em> we created earlier to the currently bound FBO to its depth buffer attachment point.<br />
<br />
 <br />
<strong class='bbc'>Adding a Texture To Render To</strong><br />
 At this point we still don’t have a way of writing colour information to the FBO, so that is what we are going to add now. There are two ways of going about it:<br />
<br />
 <ul class='bbcol decimal'><li>Attach a colour Renderbuffer to the FBO </li><li>Attach a texture to the FBO</li></ul> The former does have some uses; however it is the latter we will be covering here.<br />
<br />
 Before you can attach a texture you need to create one, this hasn’t changed from the normal way of using textures as you’ll see:<br />
<br />
  GLuint img; glGenTextures(1, &img); glBindTexture(GL_TEXTURE_2D, img); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);  In this instance we are creating a normal RGBA image of the <strong class='bbc'>same width and height</strong> as the <strong class='bbc'>renderbuffer</strong> we created earlier; this is important as <strong class='bbc'>ALL</strong> attachments to a FBO have to be the same width and height. Note that we don’t upload any data, the space is just reserved by OpenGL so we can use it later.<br />
<br />
 Having created our texture the next job is to attach it to the FBO so we can render to it:<br />
<br />
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);  Again this might look imposing but it isn’t that bad, the GL_COLOR_ATTACHMENT0_EXT tells OpenGL to attach it to the relevent attachment point (FBOs can have more than one colour buffer attached at any given time, each one to a different point), the GL_TEXTURE_2D tells OpenGL the format of the texture we are going to be attaching, <em class='bbc'>img</em> is the texture we’ll be attaching and the ‘0’ refers to the mipmap level of the texture you want to attach to, which you will generally want to leave as 0.<br />
<br />
 The final job to do in setup is to check that the FBO is ‘complete’. Completeness refers to the state of the FBO being one which, given the current OpenGL state and its attachments, all is correct for you to render to it.<br />
<br />
 This test is done via a single function which returns the status of the currently bound FBO<br />
<br />
  GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);  If all has gone well then status will equal <em class='bbc'>GL_FRAMEBUFFER_COMPLETE_EXT</em> and your FBO is ready to be rendered to. Other error codes, as found in the spec, indicate other problems which might well have occurred when you tried to setup the FBO.<br />
<br />
 <br />
<strong class='bbc'>Rendering to Texture</strong><br />
 With all the hard work setting things up done the usage of the FBO from here on out is in fact pretty simple and relies on just one function call: glBindFramebufferEXT().<br />
<br />
 To render to a FBO you bind it and to stop rendering to it you call the above again with ‘0’ as the final parameter:<br />
<br />
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0,0,width, height); // Render as normal here // output goes to the FBO and it’s attached buffers glPopAttrib(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  Three lines which probably jumped out at you right away are the glPushAttrib/glPopAttrib pair and the glViewport call. The glViewport call is needed so that we don’t try to render into an area bigger than, or even smaller than, the FBO is setup for. The glPushAtrrib and glPopAttrib are used as a quick way to save the old viewport information, this is needed because the FBO shares all of its states with the main context and as such any changes made affect both the FBO and the main context you would be normally rendering to.<br />
<br />
 An important point to make here is that you’ll notice that we only bound and then unbound the FBO to draw to it, we didn’t reattach any textures or renderbuffers, this because they stay attached until you detach them yourself or the FBO is destroyed.<br />
<br />
 <br />
<strong class='bbc'>Using The Rendered To Texture</strong><br />
 At this point our scene has been rendered to the texture and is now ready for us to use it and this operation itself is easy; we just bind the attached texture like any other texture.<br />
<br />
  glBindTexture(GL_TEXTURE_2D, img);  Having carried that out the texture is now ready to read from as normal.<br />
<br />
 Depending on the texture’s filtering setup you might also want to generate mipmap information for it. Many people are used to using the gluBuild2DMipmaps() function to build mipmap information at load time and some of you might also be aware of the automatic mipmap generation extension; the FBO extension adds a third way with the GenerateMipmapEXT() function.<br />
<br />
 This function lets OpenGL build the mipmap information for you, the way it’s done depends on the hardware you are running on, and is the correct way to do so for textures you have rendered to (you shouldn’t use the automatic mipmap generation on a texture you are going to render to for various reasons which are covered in the spec).<br />
<br />
 To use the function all you have to do is bind a texture as above and then call:<br />
<br />
  glGenerateMipmapEXT(GL_TEXTURE_2D);  OpenGL will then generate all the required mipmap data for you so that your texture is ready to be used.<br />
<br />
 It’s important to note that if you intend on using any of the mipmap filters (GL_LINEAR_MIPMAP_LINEAR for example) then you must call glGenerateMipmapEXT() before checking the framebuffer is complete or attempting to render to it.<br />
<br />
 At setup time you can just do it as follows:<br />
<br />
  glGenTextures(1, &img); glBindTexture(GL_TEXTURE_2D, img); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glGenerateMipmapEXT(GL_TEXTURE_2D);  At this point your texture is complete and can be rendered to like normal.<br />
<br />
 <br />
<strong class='bbc'>Cleaning Up</strong><br />
 Finally, when you are done with your FBO you need to clean things up and delete it. This, like textures, is done via a single function:<br />
<br />
  glDeleteFramebuffersEXT(1, &fbo);  You also have to clean up any <strong class='bbc'>renderbuffers</strong> you might have allocated, in this case the <em class='bbc'>depthbuffer</em> <strong class='bbc'>renderbuffer</strong> needs to deleted, which again works the same way as cleaning up a texture:<br />
<br />
  glDeleteRenderbuffersEXT(1, &depthbuffer);  At this point both the FBO and the <strong class='bbc'>renderbuffer</strong> have been freed and your clean up is completed.<br />
<br />
 <br />
<strong class='bbc'>Final Thoughts</strong><br />
 Hopefully this quick tour of the FBO extension will be enough to get you up and running with it. For a more detailed over view you'll want to check out the <a href='http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt' class='bbc_url' title='External link' rel='nofollow external'>FBO spec</a> or the section on the extension in the book <a href='http://www.gamedev.net/columns/books/bookdetails.asp?productid=570&CategoryID=15%20' class='bbc_url' title=''><em class='bbc'>More OpenGL Game Programming</em></a><br />
<br />
 In way of closing, before you go and check out the example program which shows a basic usage of the FBO extension I’d like to leave you with the following tips and notes on FBO usage.<br />
<br />
 <ul class='bbcol decimal'><li>Currently you can’t have a stencil attachment. There is an extension in the works to allow for a texture format which would allow depth-stencil textures and thus render to stencil, however as of yet there is a lack of support for it. </li><li>Don’t constantly make the destroy FBOs, instead generate what you need at load/setup time and reuse them during the program as required. </li><li>Avoid modifying the texture you have rendered to via any glTexImage and related calls. Doing so can and most probably will hurt your performance.</li></ul> <br />
<strong class='bbc'>Notes on the example program</strong><br />
 While this article talks about adding a depth renderbuffer and then a texture to the FBO in that order it was discovered that currently ATI’s drivers appear to have a bug whereby adding the depth renderbuffer and then a texture causes the application to crash. This should be kept in mind when doing any FBO related work and tested for as it is possible it could be fixed in a future driver revision thus rendering the problem non-existent.<br />
<br />
 I’d also like to put out a big thanks to <a href='http://www.gamedev.net/community/forums/profile.asp?mode=display&id=35639' class='bbc_url' title=''>Rick Appleton</a> for helping me test out and debug the code on NVIDA hardware, couldn’t have done it without you mate <img src='http://public.gamedev.net/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' /><br />
<br />
 The example program requires some form of GLUT to be compiled and run (I used <a href='http://freeglut.sourceforge.net/' class='bbc_url' title='External link' rel='nofollow external'>FreeGLUT</a>)<br />
<br />
 <br />
<strong class='bbc'>References</strong><br />
 <a href='http://www.gamedev.net/columns/books/bookdetails.asp?productid=570&CategoryID=15%20' class='bbc_url' title=''>More OpenGL Game Programming</a><br />
<a href='http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt' class='bbc_url' title='External link' rel='nofollow external'>Framebuffer Object Spec</a><br />
<a href='http://download.nvidia.com/developer/presentations/2005/GDC/OpenGL_Day/OpenGL_FrameBuffer_Object.pdf' class='bbc_url' title='External link' rel='nofollow external'>GDC 2005 Framebuffer Object pdf</a><br />
<br />
]]></description>
		<pubDate>Wed, 22 Nov 2006 19:24:15 +0000</pubDate>
		<guid isPermaLink="false">e4c4e24edd254bb81fc6e3fe7a1a5dd4</guid>
	</item>
	<item>
		<title>Object Abstraction in OpenGL</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/object-abstraction-in-opengl-r2103</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 We are beginning to see more and more use of the notion of an object in OpenGL. An object is simply represented by an unsigned integer that is used as the parameter to various state setting functions. In many cases when working with objects in OpenGL you will be performing the same common tasks with these objects: Creation, Binding and Destruction. I realised this when I was implementing the sub-classes Texture1D, Texture2D, Texture3D etc.. and found I was simply writing the same code over and over, but with just a different constant (in this case, although we see that this can be generalised to different entry points) and decided that an abstraction was needed.<br />
<br />
 My immediate thought was to move this into the base class GLTexture, however I realised I would come across this problem again when implementing vertex and fragment programs(ARB, EXT, NV), vertex buffers(VBO, VAR, VAO). Also note that mechanisms such as ARB_occlusion_query uses a similar notion of an object. The problem with providing a common abstraction is that each of these extensions uses different entry points and/or parameters. The solution to this problem is to use templates and to move the entry point calls into a helper class. So my initial implementation of the Object interface was:<br />
<br />
  template class Object { public:   Object() : ID(ObjectOps::GenerateID())   {}   ~Object()   { 	ObjectOps::Destroy(ID);   }   void Bind() const   { 	ObjectOps::Bind(ID);   } protected:   GLuint ID; };  Notice how simple this class is. The work is done in the ObjectOps classes. I've opted to use all static member functions for the ObjectOps interface, but you could make it into a class and use the Pimpl idiom, allocating an instance as a private variable, but I choose to avoid the overhead of the allocation of the object, any data needed can be stored as private static variables.<br />
<br />
 A sample implementation of an ObjectOps class(for ARB_vertex_program):<br />
<br />
  class ARBVertexProgramOps { public:   static GLuint GenerateID()   { 	GLuint ID; 	glGenProgramsARB(1, &ID); 	return ID;   }   static void Destroy(GLuint ID)   { 	glDeleteProgramsARB(1, &ID);   }   static void Bind(GLuint ID)   { 	if(ID != currentID) 	{   	glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ID);   	currentID = ID; 	}   } private:   static GLuint currentID; };  Still implementing individual Ops classes for each of the texture types is still going to be tedious so we can take advantage of templates again to change the constant for us:<br />
<br />
  template class TexOps { public:   static GLuint GenerateID()   { 	GLuint ID; 	glGenTextures(1, &ID); 	return ID;   }   static void Bind(GLuint ID)   { 	glBindTexture(target, ID);   }   static void Destroy(GLuint ID)   { 	glDeleteTextures(1, &ID);   } };  I've omitted the currently bound state memory in this case since a little more work is needed remembering the state for each texture unit if multitexture is used. I'll leave that as an exercise for the reader. You can also do a similar thing with the ARBVertexProgramOps class to support ARB_fragment_program:<br />
<br />
  template class ARBProgramOps { public:   static GLuint GenerateID()   { 	GLuint ID; 	glGenProgramsARB(1, &ID); 	return ID;   }   static void Destroy(GLuint ID)   { 	glDeleteProgramsARB(1, &ID);   }   static void Bind(GLuint ID)   { 	if(ID != currentID) 	{   	glBindProgramARB(target, ID);   	currentID = ID; 	}   } private:   static GLuint currentID; };  <br />
<strong class='bbc'>Taking a step in the API independence direction</strong><br />
 You'll notice that in the above code, the usage to say create a 2D texture class would be:<br />
<br />
  class Texture2D : public Object< TexOps > { public:   /* 2D Texture specific functions */ };  Now this is ok if you know that the texture you are dealing with is a 2D texture, but it is useful to be able to have a base class GLTexture, that you can refer to all textures by. Now this causes us a problem: we would like the base texture class to have a method void Bind() const. However, this method is defined in Object<> so simply using the seemingly obvious solution of multiple inheritance won't work.<br />
<br />
 The solution comes in the form of a diamond inheritance hierarchy. This formation is normally used as an argument against multiple inheritance, but in this case we can use a handy trick called delegation to a sister class[1] to enable us to achieve our aim. As an indirect side effect of this we also achieve the ability to have an API independent base class for our textures!<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/globjabs/image001.gif' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 This is what our hierarchy will look like. To avoid having two copies of the base texture object we need to make the inheritance of Texture in GLObject<> and GLTexture virtual. Now this poses us a new problem, we've just made GLObject<> dependent upon Texture! Again templates come to the rescue, making the interface now:<br />
<br />
  class Texture { public:   virtual ~Texture() { }   virtual void Bind() const = 0;   /* Other abstract Texture functions */ }; template class Object: public virtual ObjectBase { public:   Object() : ID(ObjectOps::GenerateID())   {}   ~Object()   { 	ObjectOps::Destroy(ID);       	}      void Bind() const   {         	ObjectOps::Bind(ID);   } protected:   GLuint ID; }; class GLTexture : public virtual Texture  // Notice the virtual keyword - very important! { public:   /*GL specific functions and implementations of pure 	virtual functions from Texture */ }; class Texture2D : public GLTexture, private GLObject]]></description>
		<pubDate>Sat, 29 May 2004 14:41:10 +0000</pubDate>
		<guid isPermaLink="false">751f879c2408105e969d31617d31fbf5</guid>
	</item>
	<item>
		<title>Moving Beyond OpenGL 1.1 for Windows</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/moving-beyond-opengl-11-for-windows-r1929</link>
		<description><![CDATA[<strong class='bbc'>(Editor's Note - this article requires additional formatting work and is incomplete)<br />
<br />
</strong><em class='bbc'>Author's note: Keep in mind that although this article is being published on GameDev.net in April 2003, it was written in April 2002, and some things have changed in the past year, notably the release of the OpenGL 1.4 specification, and the standardization of pixel and vertex shaders. I've chosen not to update the article to reflect these changes because I wanted to keep the text consistent with what was published in the book, and because they really make no difference as far as the the purpose of the article is concerned.</em><br />
<br />
 This article originally appeared in the book Game Programming Tricks of the Trade,  2002, Premier Press. Many members of the GameDev.net community,  including several GDNet staff members, contributed to the book, so  you're encouraged to check it out.   <br />
<br />
 <br />
<strong class='bbc'><span style='font-size: 18px;'>Trick #10 from </span><span style='font-size: 18px;'>Game Programming Tricks of the Trade</span></strong><strong class='bbc'><span style='font-size: 18px;'>, Premier Press</span></strong><br />
<br />
 Once you've been programming with OpenGL for Windows for a while, you'll probably notice something: the headers and libraries you're using are old. Dig around in the gl.h header, and you'll see this:<br />
<br />
 [indent]<pre class='prettyprint'>#define GL_VERSION_1_1                    1</pre>[/indent]This means that you're using OpenGL  1.1, which was released in 1996. In the world of graphics, that's  ancient! If you've been paying attention, you know that the current  OpenGL specification is at 1.3 (at least at the time of this writing).  OpenGL 1.4 should be released later this year, with 2.0 following soon  after. Obviously, you need to update your OpenGL headers and libraries  to something more recent. <br />
<br />
As it turns out, the most recent headers and  libraries for Windows correspond to … OpenGL 1.1. That's right, the  files you already have are the most recent ones available.<br />
<br />
This, of course, presents a problem. Although you can do some impressive things with OpenGL 1.1, to take full advantage of modern consumer graphics hardware, you're going to need functionality available through more recent versions, as well as features available through extensions (but we'll get to that in a bit). The question, then, is how to access newer features, when your headers and libraries are stuck at OpenGL 1.1. The purpose of this article is to answer that question.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>What You Will Learn</strong></span><br />
<br />
In this article, I will:<br />
 <ul class='bbc'><li>Explain in greater detail why you need to take some extra steps to use anything beyond OpenGL 1.1.</li><li>Explain OpenGL's extension mechanism, and how it can be used to access OpenGL 1.2 and 1.3 functionality.</li><li>Give you an overview of the new options available in OpenGL 1.2 and 1.3, as well as a look at some of the most useful extensions.</li><li>Give you some tips for using extensions while ensuring that your game will run well on a wide range of systems.</li><li>Provide a demo showing you how to use the techniques described.</li></ul> <br />
<span style='font-size: 18px;'><strong class='bbc'>The Problem</strong></span><br />
<br />
If you're new to OpenGL or have only ever needed the functionality offered in OpenGL 1.1, you may be confused about what the problem is, so let's clarify.<br />
<br />
 To develop for a given version of OpenGL on Windows, you need three things. First, you need a set of libraries (i.e. opengl32.lib and possibly others such as glu32.lib) and headers (i.e. gl.h, and so on) corresponding to the version you'd like to use. These headers and libraries contain the OpenGL functions, constants, and other things you need to be able to compile and link an OpenGL application. Second, the system you intend to run the application on needs to have an OpenGL dynamic link library (OpenGL32.dll), or OpenGL runtime library. The runtime needs to be for either the same or a more recent version of OpenGL as the headers and libraries you're using. Ideally, you will also have a third component, called an Installable Client Driver (IDC). An IDC is provided by the video card drivers to allow for hardware acceleration of OpenGL features, as well as possible enhancements provided by the graphics vendor.<br />
<br />
 So, let's look at these three things and see why you have to jump through a few hoops to use anything newer than OpenGL 1.1:<br />
 <ul class='bbc'><li><strong class='bbc'>Headers and libraries.</strong> As I mentioned in the introduction, the latest version of the OpenGL headers and libraries available from Microsoft correspond to version 1.1. If you look around on the Internet, you may come across another OpenGL implementation for Windows created by Silicon Graphics. SGI's implementation also corresponds to OpenGL 1.1. Unfortunately, this implementation is no longer supported by SGI. In addition, the Microsoft implementation is based upon it, so you really gain nothing by using it. Where does that leave us? <br /><br />Well, there is reason to hope that someone will release up to date libraries. Although, to my knowledge, no one has committed to doing so, several parties have discussed it. Microsoft is the obvious candidate, and despite years of promising and not delivering, it appears that they have taken an interest in the recently proposed OpenGL 2.0. Whether or not that interest will lead to action remains to be seen, but given the large number of graphics workstations running Windows NT and Windows 2000, it's not beyond the realm of possibility.<br /><br /> Besides Microsoft, there has apparently been discussion among the members of OpenGL's Architectural Review Board (ARB) to provide their own implementation of the headers and libraries. At present, though, this is still in the discussion stage, so it may be a while before we see anything come of it.</li><li><strong class='bbc'>The runtime.</strong> Most versions of Windows (the first release of Windows 95 being the exception) come with a 1.1 runtime. Fortunately, this isn't really as important as the other elements. All that the runtime does is guarantee a baseline level of functionality, and allow you to interface with the ICD.</li><li><strong class='bbc'>The ICD.</strong> This is the one area where you're okay. Most hardware vendors (including NVIDIA and ATI) have been keeping up with the latest OpenGL standard. For them to be able to advertise that their drivers are compliant with the OpenGL 1.3 standard, they have to support everything included in the 1.3 specification (though not necessarily in hardware). The cool thing about this is that the ICD contains the code to do everything in newer versions of OpenGL, and we can take advantage of that.</li></ul> The thing that's important to note here is that although the headers and libraries available don't directly allow you to access newer OpenGL features, the features do exist in the video card drivers. You just need to find a way to access those features in our code. We do that by using OpenGL's extension mechanism.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>OpenGL Extensions</strong></span><br />
<br />
As you're aware, the graphics industry has been moving at an alarmingly rapid pace for many years now. Today, consumer-level video cards include features that were only available on professional video cards (costing thousands of dollars) a few years ago. Any viable graphics API has to take these advances into account, and provide some means to keep up with them. OpenGL does this through extensions.<br />
<br />
 If a graphics vendor adds a new hardware feature that they want OpenGL programmers to be able to take advantage of, they simply need to add support for it in their ICD, and then provide developers with documentation about how to use the extension. This is oversimplifying a bit, but it's close enough for our purposes. As an OpenGL programmer, you can then access the extension through a common interface shared by all extensions. You'll learn how to do that in the "Using Extensions" section, but for now, let's look at how extensions are identified, and what they consist of.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Extension Names</strong></span><br />
<br />
Every OpenGL extension has a name by which it can be precisely and uniquely identified. This is important, because hardware vendors will frequently introduce extensions with similar functionality but very different semantics and usage. You need to be able to distinguish between them. For example, both NVIDIA and ATI provide extensions for programmable vertex and pixel shaders, but they bear little resemblance to each other. So, if you wanted to use pixel shaders in your program, it wouldn't be enough to find out if the hardware supported pixel shaders. You'd have to be able to specifically ask whether NVIDIA's or ATI's version is supported, and handle each appropriately.<br />
<br />
 All OpenGL extensions use the following naming convention:<br />
<br />
 [indent]<pre class='prettyprint'>PREFIX_extension_name</pre>[/indent] The "PREFIX" is there to help avoid naming conflicts. It also helps identify the developer of the extension or, as in the case of EXT and ARB, its level of promotion. Table 1 lists most of the prefixes currently in use. The "extension_name" identifies the extension. Note that the name cannot contain any spaces. Some example extension names are <span style='font-family: Courier New'><span style='color: #000080'>ARB_multitexture</span></span>, <span style='font-family: Courier New'><span style='color: #000080'>EXT_bgra</span></span>, <span style='font-family: Courier New'><span style='color: #000080'>NV_vertex_program</span></span>, and <span style='font-family: Courier New'><span style='color: #000080'>ATI_fragment_shader</span></span>.<br />
<br />
                          <strong class='bbc'>Table 1 - OpenGL Extension Prefixes</strong>  <strong class='bbc'>Prefix</strong>    <strong class='bbc'><strong class='bbc'>Meaning/Vendor</strong></strong>   ARBExtension approved by OpenGL's Architectural Review Board (first introduced with OpenGL 1.2)   EXT Extension agreed upon by more than one OpenGL vendor  3DFX 3dfx Interactive   APPLE Apple Computer  ATI ATI Technologies   ATIX ATI Technologies (experimental)  HP Hewlett-Packard   INTELIntel Corporation   IBM International Business Machines  KTX Kinetix   NV NVIDIA Corporation  MESA <a href='http://www.mesa3d.org' class='bbc_url' title='External link' rel='nofollow external'>http://www.mesa3d.org</a>   OML OpenML  SGI Silicon Graphics   SGISSilicon Graphics (specialized)   SGIX Silicon Graphics (experimental)  SUN Sun Microsystems   SUNX Sun Microsystems (experimental)  WIN Microsoft  [indent]<blockquote><em class='bbc'>Caution: Some extensions share a name, but have a different prefix. These extensions are generally not interchangeable, as they may use entirely different semantics. For example, <span style='font-family: Courier New'><span style='color: #000080'>ARB_texture_env_combine</span></span> is not the same thing as <span style='font-family: Courier New'><span style='color: #000080'>EXT_texture_env_combine</span></span>. Rather than making assumptions, be sure to consult the extension specifications when you're unsure.</em></blockquote>[/indent] <span style='font-size: 12px;'><strong class='bbc'>What an Extension Includes</strong></span><br />
<br />
You now know what an extension is, and how extensions are named. Next, let's turn our attention to the relevant components of an extension. There are four parts of an extension that you need to deal with.<br />
<br />
 <strong class='bbc'>Name Strings</strong><br />
Each extension defines a name string, which you can use to determine whether or not the OpenGL implementation supports it. By passing <span style='font-family: Courier New'><span style='color: #000080'>GL_EXTENSIONS</span></span> to the <span style='font-family: Courier New'><span style='color: #000080'>glGetString()</span></span> method, you can get a space-delimited buffer containing all the extension name strings supported by the implementation.<br />
<br />
 Name strings are generally the name of the extension preceded by another prefix. For core OpenGL name strings, this is always GL_ (e.g. GL_EXT_texture_compression). When the name string is tied to a particular windows system, the prefix will reflect which system that is (e.g. Win32 uses WGL_).<br />
 [indent]<blockquote><em class='bbc'>Some extensions may define more than one name string. This would be the case if the extension provided both core OpenGL functionality and functionality specific to the windows system.</em></blockquote>[/indent] <strong class='bbc'>Functions</strong><br />
Many (but not all) extensions introduce one or more new functions to OpenGL. To use these functions, you'll have to obtain their entry point, which requires that you know the name of the function. This process is described in detail in the "Using Extensions" section.<br />
<br />
 The functions defined by the extension follow the naming convention used by the rest of OpenGL, namely <span style='font-family: Courier New'><span style='color: #000080'>glFunctionName()</span></span>, with the addition of a suffix using the same letters as the extension name's prefix. For example, the <span style='font-family: Courier New'><span style='color: #000080'>NV_fence</span></span> extension includes the functions <span style='font-family: Courier New'><span style='color: #000080'>glGetFencesNV()</span></span>, <span style='font-family: Courier New'><span style='color: #000080'>glSetFenceNV()</span></span>, <span style='font-family: Courier New'><span style='color: #000080'>glTestFenceNV()</span></span>, and so on.<br />
<br />
 <strong class='bbc'>Enumerants</strong><br />
An extension may define one or more enumerants. In some extensions, these enumerants are intended for use in the new functions defined by the extension (which may be able to use existing enumerants as well). In other cases, they are intended for use in standard OpenGL functions, thereby adding new options to them. For example, the <span style='font-family: Courier New'><span style='color: #000080'>ARB_texture_env_add</span></span> extension defines a new enumerant, <span style='font-family: Courier New'><span style='color: #000080'>GL_ADD</span></span>. This enumerant can be passed as the <span style='font-family: Courier New'><span style='color: #000080'>params</span></span> parameter of the various <span style='font-family: Courier New'><span style='color: #000080'>glTexEnv()</span></span> functions when the pname parameter is <span style='font-family: Courier New'><span style='color: #000080'>GL_TEXTURE_ENV_MODE</span></span>.<br />
<br />
 The new enumerants follow the normal OpenGL naming convention (i.e. <span style='font-family: Courier New'><span style='color: #000080'>GL_WHATEVER</span></span>), except that they are suffixed by the letters used in the extension name's prefix, such as <span style='font-family: Courier New'><span style='color: #000080'>GL_VERTEX_SOURCE_ATI</span></span>.<br />
<br />
 Using new enumerants is much simpler than using new functions. Usually, you will just need to include a header defining the enumerant, which you can get from your hardware vendor or from SGI. Alternately, you can define the enumerant yourself if you know the integer value it uses. This value can be obtained from the extension's documentation.<br />
 [indent]<blockquote><em class='bbc'>Extensions don't need to define both functions and enumerants (though many do), but they usually include at least one of the two. The few cases where that's not true is when existing functions or enumerants are combined in new ways</em>.</blockquote>[/indent] <strong class='bbc'>Dependencies</strong><br />
Very few extensions stand completely alone. Some require the presence of other extensions, while others take this a step further and modify or extend the usage of other extensions. When you begin using a new extension, you need to be sure to read the specification and understand the extension's dependencies.<br />
<br />
 Speaking of documentation, you're probably wondering where you can get it, so let's talk about that next.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Extension Documentation</strong></span><br />
<br />
Although vendors may (and usually do) provide documentation for their extensions in many forms, there is one piece of documentation that is absolutely essential-- the specification. These are generally written as plain text files, and include a broad range of information about the extension, such as its name, version, number, dependencies, new functions and enumerants, issues, and modifications/additions to the OpenGL specification.<br />
<br />
 The specifications are intended for use by developers of OpenGL hardware or ICDs, and as such, are of limited use to game developers. They'll tell you what the extension does, but not why you'd want to use it, or how to use it. For that reason, I'm not going to go over the details of the specification format. If you're interested, Mark Kilgard has written an excellent article about it which you can read at OpenGL.org. [<a href='#ref'>1</a>]<br />
<br />
 As new extensions are released, their specifications are listed in the OpenGL Extension Registry, which you can find at the following URL:<br />
<br />
 <a href='http://oss.sgi.com/projects/ogl-sample/registry/' class='bbc_url' title='External link' rel='nofollow external'>http://oss.sgi.com/p...ample/registry/</a><br />
<br />
 This registry is updated regularly, so it's a great way to keep up with the newest additions to OpenGL.<br />
<br />
 For more detailed descriptions of new extensions, your best bet is the websites of the leading hardware vendors. In particular, NVIDIA [<a href='#ref'>2</a>] and ATI [<a href='#ref'>3</a>] both provide a wealth of information, including white papers, Power Point presentations, and demos.<br />
 [indent]<blockquote><em class='bbc'>Extensions that are promoted to be a part of the core OpenGL specification may be removed from the extension registry. To obtain information about these, you'll have to refer to the latest OpenGL specification. [<a href='#ref'>4</a>]</em></blockquote>[/indent] <br />
<span style='font-size: 18px;'><strong class='bbc'>Using Extensions</strong></span><br />
<br />
Finally, it's time to learn what you need to do to use an extension. In general, there are only a couple of steps you need to take:<br />
 <ul class='bbc'><li>determine whether or not the extension is supported</li><li>obtain the entry point for the any of the extension's functions that you want to use</li><li>define any enumerants you're going to use.</li></ul> Let's look at each of these steps in greater detail.<br />
 [indent]<blockquote><em class='bbc'>Caution: Before checking for extension availability and obtaining pointers to functions, you MUST have a current rendering context. In addition, the entry points are specific to each rendering context, so if you're using more than one, you'll have to obtain a separate entry point for each.</em></blockquote>[/indent] <span style='font-size: 12px;'><strong class='bbc'>Querying the Name String</strong></span><br />
<br />
In order to find out whether or not a specific extension is available, first get the list of all the name strings supported by the OpenGL implementation. To do this, you just need to call <span style='font-family: Courier New'><span style='color: #000080'>glGetString()</span></span> using <span style='font-family: Courier New'><span style='color: #000080'>GL_EXTENSIONS</span></span>, like so:<br />
<br />
 [indent]<pre class='prettyprint'>char* extensionsList = (char*) glGetString(GL_EXTENSIONS);</pre>[/indent] After this executes, <span style='font-family: Courier New'><span style='color: #000080'>extensionsList</span></span> points to a null-terminated buffer containing the name strings of all the extensions available to you. These name strings are separated by spaces, including a space after the last name string.<br />
 [indent]<blockquote><em class='bbc'>I'm casting the value returned by <span style='font-family: Courier New'><span style='color: #000080'>glGetString()</span></span> because the function actually returns an array of unsigned chars. Since most of the string manipulation functions I'll be using require signed chars, I do the cast once now instead of doing it many times later.</em></blockquote>[/indent] To find out whether or not the extension you're looking for is supported, you'll need to search this buffer to see if it includes the extension's name string. I'm not going to go into great detail about how to parse the buffer, since there are many ways to do so, and it's something that at this stage in your programming career, you should be able to do without much effort. One thing you need to watch out for, though, is accidentally matching a substring. For example, if you're trying to use the <span style='font-family: Courier New'><span style='color: #000080'>EXT_texture_env</span></span> extension, and the implementation doesn't support it, but it does support <span style='font-family: Courier New'><span style='color: #000080'>EXT_texture_env_dot3</span></span>, then calling something like:<br />
<br />
 [indent]<pre class='prettyprint'>strstr("GL_EXT_texture_env", extensionsList);</pre>[/indent] is going to give you positive results, making you think that the <span style='font-family: Courier New'><span style='color: #000080'>EXT_texture_env</span></span> extension is supported, when it's really not. The <span style='font-family: Courier New'><span style='color: #000080'>CheckExtension()</span></span> function in the demo program included with this article shows one way to avoid this problem.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Obtaining the Function's Entry Point</strong></span><br />
<br />
Because of the way Microsoft handles its OpenGL implementation, calling a new function provided by an extension requires that you request a function pointer to the entry point from the ICD. This isn't as bad as it sounds.<br />
<br />
 First of all, you need to declare a function pointer. If you've worked with function pointers before, you know that they can be pretty ugly. If not, here's an example:<br />
<br />
 [indent]<pre class='prettyprint'>void (APIENTRY * pglCopyTexSubImage3DEXT) (GLenum, GLint, GLint,<br />    GLint, GLint, GLint, GLint, GLsizei, GLsizei) = NULL;</pre>[/indent] [indent]<blockquote><em class='bbc'>Update 4/24/03: For the book, and initially here, I used the function name (i.e. glCopyTexSubImage3DEXT) as the pointer name. A reader pointed out to me that on a number of operating systems (e.g. Linux) this can cause serious problems, so it should be avoided. Thanks, Ian!</em></blockquote>[/indent] Now that we have the function pointer, we can attempt to assign an entry point to it. This is done using the function <span style='font-family: Courier New'><span style='color: #000080'>wglGetProcAddress()</span></span>:<br />
<br />
 [indent]<pre class='prettyprint'>PROC wglGetProcAddress( LPCSTR  lpszProcName );</pre>[/indent] The only parameter is the name of the function you want to get the address of. The return value is the entry point of the function if it exists, or <span style='font-family: Courier New'><span style='color: #000080'>NULL</span></span> otherwise. Since the value returned is essentially a generic pointer, you need to cast it to the appropriate function pointer type.<br />
<br />
 Let's look at an example, using the function pointer we declared above:<br />
<br />
 [indent]<pre class='prettyprint'>pglCopyTexSubImage3DEXT  =<br />    (void (APIENTRY *) (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))<br />    wglGetProcAddress("glCopyTexSubImage3DEXT");</pre>[/indent] And you thought the function pointer declaration was ugly.<br />
<br />
 You can make life easier on yourself by using <span style='font-family: Courier New'><span style='color: #000080'>typedefs</span></span>. In fact, you can obtain a header called "glext.h" which contains <span style='font-family: Courier New'><span style='color: #000080'>typedefs</span></span> for most of the extensions out there. This header can usually be obtained from your favorite hardware vendor (for example, NVIDIA includes it in their OpenGL SDK), or from SGI at the following URL:<br />
<br />
 <a href='http://oss.sgi.com/projects/ogl-sample/ABI/glext.h' class='bbc_url' title='External link' rel='nofollow external'>http://oss.sgi.com/p...ple/ABI/glext.h</a><br />
<br />
 Using this header, the code above becomes:<br />
<br />
 [indent]<pre class='prettyprint'>PFNGLCOPYTEXSUBIMAGE3DEXTPROC pglCopyTexSubImage3DEXT = NULL;<br />pglCopyTexSubImage3DEXT = (PFNGLCOPYTEXSUBIMAGE3DEXTPROC) wglGetProcAddress("glCopyTexSubImage3DEXT");</pre>[/indent] Isn't that a lot better?<br />
<br />
 As long as <span style='font-family: Courier New'><span style='color: #000080'>wglGetProcAddress()</span></span> doesn't return NULL, you can then freely use the function pointer as if it were a normal OpenGL function.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Declaring Enumerants</strong></span><br />
<br />
To use new enumerants defined by an extension, all you have to do is define the enumerant to be the appropriate integer value. You can find this value in the extension specification. For example, the specification for the <span style='font-family: Courier New'><span style='color: #000080'>EXT_texture_lod_bias</span></span> says that <span style='font-family: Courier New'><span style='color: #000080'>GL_TEXTURE_LOD_BIAS_EXT</span></span> should have a value of 0x8501, so somewhere, probably in a header (or possibly even in gl.h), you'd have the following:<br />
<br />
 [indent]<span style='font-family: Courier New'><pre class='prettyprint'>#define GL_TEXTURE_LOD_BIAS_EXT    0x8501</pre></span>[/indent] Rather than defining all these values yourself, you can use the glext.h header, mentioned in the last section, since it contains all of them for you. Most OpenGL programmers I know use this header, so don't hesitate to use it yourself and save some typing time.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Win32 Specifics</strong></span><br />
<br />
In addition to the standard extensions that have been covered so far, there are some extensions that are specific to the Windows system. These extensions provide additions that are very specific to the windowing system and the way it interacts with OpenGL, such as additional options related to pixel formats. These extensions are easily identified by their use of "WGL" instead of "GL" in their names. The name strings for these extensions normally aren't included in the buffer returned by <span style='font-family: Courier New'><span style='color: #000080'>glGetString(GL_EXTENSIONS)</span></span>, although a few are. To get all of the Windows-specific extensions, you'll have to use another function, <span style='font-family: Courier New'><span style='color: #000080'>wglGetExtensionsStringARB()</span></span>. As the ARB suffix indicates, it's an extension itself (<span style='font-family: Courier New'><span style='color: #000080'>ARB_extensions_string</span></span>), so you'll have to get the address of it yourself using <span style='font-family: Courier New'><span style='color: #000080'>wglGetProcAddress()</span></span>. Note that for some reason, some ICDs identify this as <span style='font-family: Courier New'><span style='color: #000080'>wglGetExtensionsStringEXT()</span></span> instead, so if you fail to get a pointer to one, try the other. The format of this function is as follows:<br />
<br />
 [indent]<pre class='prettyprint'>const char* wglGetExtensionsStringARB(HDC hdc);</pre>[/indent] [indent]<blockquote><em class='bbc'>Caution: Normally, it's good practice to check for an extension by examining the buffer returned by glGetString() before trying to obtain function entry points. However, it's not strictly necessary to do so. If you try to get the entry point for a non-existant function, <span style='font-family: Courier New'><span style='color: #000080'>wglGetProcAddress()</span></span> will return NULL, and you can simply test for that. The reason I'm mentioning this is because to use <span style='font-family: Courier New'><span style='color: #000080'>wglGetExtensionsStringARB()</span></span>, that's exactly what you have to do. It appears that with most ICDs, the name string for this extension, <span style='font-family: Courier New'><span style='color: #000080'>WGL_ARB_extensions_string</span></span>, doesn't appear in the buffer returned by <span style='font-family: Courier New'><span style='color: #000080'>glGetString()</span></span>. Instead, it is included in the buffer returned by <span style='font-family: Courier New'><span style='color: #000080'>wglGetExtensionsStringARB()</span></span>! Go figure.</em></blockquote>[/indent] Its sole parameter is the handle to your rendering context. The function returns a buffer similar to that returned by <span style='font-family: Courier New'><span style='color: #000080'>glGetString(GL_EXTENSIONS)</span></span>, with the only difference being that it only contains the names of WGL extensions.<br />
 [indent]<blockquote><em class='bbc'>Some WGL extension string names included in the buffer returned by <span style='font-family: Courier New'><span style='color: #000080'>wglGetExtensionsStringARB()</span></span> may also appear in the buffer returned by <span style='font-family: Courier New'><span style='color: #000080'>glGetString()</span></span>. This is due to the fact that those extensions existed before the creation of the <span style='font-family: Courier New'><span style='color: #000080'>ARB_extensions_string</span></span> extension, and so their name strings appear in both places to avoid breaking existing software.</em></blockquote>[/indent] Just as there is a glext.h header for core OpenGL extensions, so is there a wglext.h for WGL extensions. You can find it at the following link:<br />
<br />
 <a href='http://oss.sgi.com/projects/ogl-sample/ABI/wglext.h' class='bbc_url' title='External link' rel='nofollow external'>http://oss.sgi.com/p...le/ABI/wglext.h</a><br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Extensions and OpenGL 1.2 and 1.3, and the Future</strong></span><br />
<br />
Back at the beginning of this article, I said that OpenGL 1.2 and 1.3 features can be accessed using the extensions mechanism, which I've spent the last several pages explaining. The question, then, is how you go about doing that. The answer, as you may have guessed, is to treat 1.2 and 1.3 features as extensions. When it comes right down to it, that's really what they are, since nearly every feature that has been added to OpenGL originated as an extension. The only real difference between 1.2 and 1.3 features and "normal" extensions is that the former tend to be more widely supported in hardware, because, after all, they are part of the standard.<br />
 [indent]<blockquote><em class='bbc'> Sometimes, an extension that has been added to the OpenGL 1.2 or 1.3 core specification will undergo slight changes, causing the semantics and/or behavior to be somewhat different from what is documented in the extension's specification. You should check the latest OpenGL specification to find out about these changes.</em></blockquote><br />
 [/indent] The next update to OpenGL will probably be 1.4. It will most likely continue the trend of promoting successful extensions to become part of the standard, and you should be able to continue to use the extension mechanism to access those features. After that, OpenGL 2.0 will hopefully make its appearance, introducing some radical changes to the standard. Once 2.0 is released, new headers and libraries may be released as well, possibly provided by the ARB members. These will make it easier to use new features.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>What You Get</strong></span><br />
<br />
As you can see, using OpenGL 1.2 and 1.3, and extensions in general, isn't a terribly difficult process, but it does take some extra effort. You may be wondering what you can gain by using them, so lets take a closer look at them. The following sections list the features added by OpenGL 1.2 and 1.3, as well as some of the more useful extensions currently available. With each feature, I've included the extension you can use to access it.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>OpenGL 1.2</strong></span><br />
 <strong class='bbc'><br />
3D Textures</strong> allow you to do some really cool volumetric effects. Unfortunately, they require a significant amount of memory. To give you an idea, a single 256x256x256 16 bit texture will use 32 MB! For this reason, hardware support for them is relatively limited, and because they are also slower than 2D textures, they may not always provide the best solution. They can, however, be useful if used judiciously. 3D textures correspond to the <span style='font-family: Courier New'><span style='color: #000080'>EXT_texture3D</span></span> extension.<br />
<br />
 <strong class='bbc'>BGRA Pixel Formats</strong> make it easier to work with file formats which use blue-green-red color component ordering rather than red-green-blue. Bitmaps and Targas are two examples that fall in this category. BGRA pixel formats correspond to the <span style='font-family: Courier New'><span style='color: #000080'>EXT_bgra</span></span> extension.<br />
<br />
 <strong class='bbc'>Packed Pixel Formats</strong> provide support for packed pixels in host memory, allowing you to completely represent a pixel using a single unsigned byte, short, or int. Packet pixel formats correspond to the <span style='font-family: Courier New'><span style='color: #000080'>EXT_packed_pixels</span></span> extension, with some additions for reversed component order.<br />
<br />
 Normally, since texture mapping happens after lighting, modulating a texture with a lit surface will "wash out" specular highlights. To help avoid this affect, the <strong class='bbc'>Separate Specular Color</strong> feature has been added. This causes OpenGL to track the specular color separately and apply it after texture mapping. Separate specular color corresponds to the <span style='font-family: Courier New'><span style='color: #000080'>EXT_separate_specular_color</span></span> extension.<br />
<br />
 <strong class='bbc'>Texture Coordinate Edge Clamping</strong> addresses a problem with filtering at the edges of textures. When you select <span style='font-family: Courier New'><span style='color: #000080'>GL_CLAMP</span></span> as your texture wrap mode and use a linear filtering mode, the border will get sampled along with edge texels. Texture coordinate edge clamping causes only the texels which are actually part of the texture to be sampled. This corresponds to the <span style='font-family: Courier New'><span style='color: #000080'>SGIS_texture_edge_clamp</span></span> extension (which normally shows up as <span style='font-family: Courier New'><span style='color: #000080'>EXT_texture_edge_clamp</span></span> in the <span style='font-family: Courier New'><span style='color: #000080'>GL_EXTENSIONS</span></span> string).<br />
<br />
 <strong class='bbc'>Normal Rescaling</strong> allows you to automatically scale normals by a value you specify, which can be faster than renormalization in some cases, although it requires uniform scaling to be useful. This corresponds to the <span style='font-family: Courier New'><span style='color: #000080'>EXT_rescale_normal</span></span> extension.<br />
<br />
 <strong class='bbc'>Texture LOD Control</strong> allows you to specify certain parameters related to the texture level of detail used in mipmapping to avoid popping in certain situations. It can also be used to increase texture transfer performance, since the extension can be used to upload only the mipmap levels visible in the current frame, instead of uploading the entire mipmap hierarchy. This matches the <span style='font-family: Courier New'><span style='color: #000080'>SGIS_texture_lod</span></span> extension.<br />
<br />
 The <strong class='bbc'>Draw Element Range</strong> feature adds a new function to be used with vertex arrays. <span style='font-family: Courier New'><span style='color: #000080'>glDrawRangeElements()</span></span> is similar to <span style='font-family: Courier New'><span style='color: #000080'>glDrawElements()</span></span>, but it lets you indicate the range of indicies within the arrays that you are using, allowing the hardware to process the data more efficiently. This corresponds to the <span style='font-family: Courier New'><span style='color: #000080'>EXT_draw_range_elements</span></span> extension.<br />
<br />
 The <strong class='bbc'>Imaging Subset</strong> is not fully present in all OpenGL implementations, since it's primarily intended for image processing applications. It's actually a collection of several extensions. The following are the ones that may be of interest to game developers.<br />
 <ul class='bbc'><li><span style='font-family: Courier New'><span style='color: #000080'>EXT_blend_color</span></span> allows you to specify a constant color which is used to define blend weighting factors.</li><li><span style='font-family: Courier New'><span style='color: #000080'>SGI_color_matrix</span></span> introduces a new matrix stack to the pixel pipeline, causing the RGBA components of each pixel to be multiplied by a 4x4 matrix.</li><li><span style='font-family: Courier New'><span style='color: #000080'>EXT_blend_subtract</span></span> gives you two ways to use the difference between two blended surfaces (rather than the sum).</li><li><span style='font-family: Courier New'><span style='color: #000080'>EXT_blend_minmax</span></span> lets you keep either the minimum or maximum color components of the source and destination colors.</li></ul> <span style='font-size: 12px;'><strong class='bbc'>OpenGL 1.3</strong></span><br />
<br />
The <strong class='bbc'>Multitexturing</strong> extension was promoted to ARB status with OpenGL 1.2.1 (the only real change in that release), and in 1.3, it was made part of the standard. Multitexturing allows you to apply more than one texture to a surface in a single pass, which is useful in many things, such as lightmapping and detail texturing. It was promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_multitexture</span></span> extension.<br />
<br />
 <strong class='bbc'>Texture Compression</strong> allows you to either provide OpenGL with precompressed data for your textures, or to have the driver compress the data for you. The advantage in doing so is that you save both texture memory and bandwidth, thereby improving performance. Compressed textures were promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_compressed_textures</span></span> extension.<br />
<br />
 <strong class='bbc'>Cube Map Textures</strong> provide a new type of texture consisting of six two-dimensional textures in the shape of a cube. Texture coordinates act like a vector from the center of the cube, indicating which face and which texels to use. Cube mapping is useful in environment mapping and texture-based diffuse lighting. It is also important for pixel-perfect dot3 bumpmapping, as a normalization lookup for interpolated fragment normals. It was promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_texture_cube_map</span></span> extension.<br />
<br />
 <strong class='bbc'>Multisampling</strong> allows for automatic antialiasing by sampling all geometry several times for each pixel. When it's supported, and extra buffer is created which contains color, depth, and stencil values. Multisampling is, of course, expensive, and you need to be sure to request a rendering context that supports it. It was promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_multisampling</span></span> extension.<br />
<br />
 The <strong class='bbc'>Texture Add Environment Mode</strong> adds a new enumerant which can be passed to <span style='font-family: Courier New'><span style='color: #000080'>glTexEnv()</span></span>. It causes the texture to be additively combined with the incoming fragment. This was promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_texture_env_add</span></span> extension.<br />
<br />
 <strong class='bbc'>Texture Combine Environment Modes</strong> add a lot of new options for the way textures are combined. In addition to the texture color and the incoming fragment, you can also include a constant texture color and the results of the previous texture environment stage as parameters. These parameters can be combined using passthrough, multiplication, addition, biased addition, subtraction, and linear interpolation. You can select combiner operations for the RGB and alpha components separately. You can also scale the final result. As you can see, this addition gives you a great deal of flexibility. Texture combine environment modes were promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_texture_env_combine</span></span> extension.<br />
<br />
 The <strong class='bbc'>Texture Dot3 Environment Mode</strong> adds a new enumerant to the texture combine environment modes. The dot3 environment mode allows you to take the dot product of two specified components and place the results in the RGB or RGBA components of the output color. This can be used for per-pixel lighting or bump mapping. The dot3 environment mode was promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_texture_env_dot3</span></span> extension.<br />
<br />
 <strong class='bbc'>Texture Border Clamp</strong> is similar to texture edge clamp, except that it causes texture coordinates that straddle the edge to sample from border texels only, rather than from edge texels. This was promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_texture_border_clamp</span></span> extension.<br />
<br />
 <strong class='bbc'>Transpose Matrices</strong> allow you to pass row major matrices to OpenGL, which normally uses column major matrices. This is useful not only because it is how C stores two dimensional arrays, but because it is how Direct3D stores matricies, which saves conversion work when you're writing a rendering engine that uses both APIs. This addition only adds to the interface; it does not change the way OpenGL works internally. Transpose matrices were promoted from the <span style='font-family: Courier New'><span style='color: #000080'>ARB_transpose_matrix</span></span> extension.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Useful Extensions</strong></span><br />
<br />
At the time of writing, there are 269 extensions listed in the Extension Registry. Even if I focused on the ones actually being used, I couldn't hope to cover them all, even briefly. Instead, I'll focus on a few that seem to be the most important for use in games.<br />
<br />
 <strong class='bbc'>Programmable Vertex and Pixel Shaders</strong><br />
It's generally agreed that shaders are the future of graphics, so let's start with them. First of all, the terms "vertex shader" and "pixel shader" are in common usage because of the attention they received with the launch of DirectX 8. However, the OpenGL extensions that you use for them have different names. On NVIDIA cards, vertex shaders are called vertex programs, which are available through the <span style='font-family: Courier New'><span style='color: #000080'>NV_vertex_program</span></span> extension. Pixel shaders are called register combiners, and are available through the <span style='font-family: Courier New'><span style='color: #000080'>NV_register_combiners</span></span> and <span style='font-family: Courier New'><span style='color: #000080'>NV_texture_shader</span></span> extensions. On ATI cards, vertex shaders are still called vertex shaders, and are available through the <span style='font-family: Courier New'><span style='color: #000080'>EXT_vertex_shader</span></span> extension. Pixel shaders are called fragment shaders, and are available through the <span style='font-family: Courier New'><span style='color: #000080'>ATI_fragment_shader</span></span> extension.<br />
<br />
 If you're unfamiliar with shaders, then a quick overview is in order. Vertex shaders allow you to customize the geometry transformation pipeline. Pixel shaders work later in the pipeline, and allow you to control how the final pixel color is determined. Together, the two provide incredible functionality. I recommend that you download NVIDIA's Effects Browser to see examples of the things you can do with shaders.<br />
<br />
 Using shaders can be somewhat problematic right now due to the fact that NVIDIA and ATI both handle them very differently. If you want your game to take advantage of shaders, you'll have to write a lot of special case code to use each vendor's method. At the ARB's last several meetings, this has been a major discussion point. There is a great deal of pressure to create a common shader interface. In fact, it is at the core of 3D Labs' OpenGL 2.0 proposal. Hopefully, the 1.4 specification will address this issue, but the ARB seems to be split as to whether a common shader interface should be a necessary component of 1.4.<br />
<br />
 <strong class='bbc'>Compiled Vertex Arrays</strong><br />
The <span style='font-family: Courier New'><span style='color: #000080'>EXT_compiled_vertex_arrays</span></span> extension adds two functions which allow you to lock and unlock your vertex arrays. When the vertex arrays are locked, OpenGL assumes that their contents will not be changed. This allows OpenGL to make certain optimizations, such as caching the results of vertex transformation. This is especially useful if your data contains large numbers of shared vertices, or if you are using multipass rendering. When a vertex needs to be transformed, the cache is checked to see if the results of the transformation are already available. If they are, the cached results are used instead of recalculating the transformation.<br />
<br />
 The benefits gained by using CVAs depend on the data set, the video card, and the drivers. Although you generally won't see a decrease in performance when using CVAs, it's quite possible that you won't see much of an increase either. In any case, the fact that they are fairly widely supported makes them worth looking into.<br />
<br />
 <strong class='bbc'>WGL Extensions</strong><br />
There are a number of extensions available that add to the way Windows interfaces with OpenGL. Here are some of the main ones.<br />
 <ul class='bbc'><li><span style='font-family: Courier New'><span style='color: #000080'>ARB_pixel_format</span></span> augments the standard pixel format functions (i.e. <span style='font-family: Courier New'><span style='color: #000080'>DescribePixelFormat</span></span>, <span style='font-family: Courier New'><span style='color: #000080'>ChoosePixelFormat</span></span>, <span style='font-family: Courier New'><span style='color: #000080'>SetPixelFormat</span></span>, and <span style='font-family: Courier New'><span style='color: #000080'>GetPixelFormat</span></span>), giving you more control over which pixel format is used. The functions allow you to query individual pixel format attributes, and allow for the addition of new attributes that are not included in the pixel format descriptor structure. Many other WGL extensions are dependent on this extension.</li><li><span style='font-family: Courier New'><span style='color: #000080'>ARB_pbuffer</span></span> adds pixel buffers, which are off-screen (non-visible) rendering buffers. On most cards, these buffers are in video memory, and the operation is hardware accelerated. They are often useful for creating dynamic textures, especially when used with the render texture extension.</li><li><span style='font-family: Courier New'><span style='color: #000080'>ARB_render_texture</span></span> depends on the pbuffer extension. It is specifically designed to provide buffers that can be rendered to and be used as texture data. These buffers are the perfect solution for dynamic texturing.</li><li><span style='font-family: Courier New'><span style='color: #000080'>ARB_buffer_region</span></span> allows you to save portions of the color, depth, or stencil buffers to either system or video memory. This region can then be quickly restored to the OpenGL wind&#111;w.</li></ul> <strong class='bbc'>Fences and Ranges</strong><br />
NVIDIA has created two extensions, <span style='font-family: Courier New'><span style='color: #000080'>NV_fence</span></span> and <span style='font-family: Courier New'><span style='color: #000080'>NV_vertex_array_range</span></span>, that can make video cards based on NVIDIA chipsets use vertex data much more efficiently than they normally would.<br />
<br />
 On NVIDIA hardware, the vertex array range extension is currently the fastest way to transfer data from the application to the GPU. Its speed comes from the fact that it allows the developer to allocate and access memory that normally can only be accessed by the GPU.<br />
<br />
 Although not directly related to the vertex array range extension, the fence extension can help make it even more efficient. When a fence is added to the OpenGL command stream, it can then be queried at any time. Usually, it is queried to determine whether or not it has been completed yet. In addition, you can force the application to wait for the fence to be completed. Fences can be used with vertex array range when there is not enough memory to hold all of your vertex data at once. In this situation, you can fill up available memory, insert a fence, and when the fence has completed, repeat the process.<br />
<br />
 <strong class='bbc'>Shadows</strong><br />
There are two extensions, <span style='font-family: Courier New'><span style='color: #000080'>SGIX_shadow</span></span> and <span style='font-family: Courier New'><span style='color: #000080'>SGIX_depth_texture</span></span>, which work together to allow for hardware-accelerated shadow mapping techniques. The main reason I mention these is that there are currently proposals in place to promote these extensions to ARB status. In addition, NVIDIA is recommending that they be included in the OpenGL 1.4 core specification. Because they may change somewhat if they are promoted, I won't go into detail about how these extensions work. They may prove to be a very attractive alternative to the stencil shadow techniques presently in use.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Writing Well-Behaved Programs Using Extensions</strong></span><br />
<br />
Something you need to be very aware of when using any extension is that it is highly likely that someone will run your program on a system that does not support that extension. It's your responsibility to make sure that when this happens, your program behaves intelligently, rather than crashing or rendering garbage to the screen. In this section, you'll learn several methods to help ensure that your program gets the best possible results on all systems. The focus is on two areas: how to select which extensions to use, and how to respond when an extension you're using isn't supported.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Choosing Extensions</strong></span><br />
<br />
The most important thing you can do to insure that your program runs on as many systems as possible is to choose your extensions wisely. The following are some factors you should consider.<br />
<br />
 <strong class='bbc'>Do you really need the extension?</strong><br />
A quick look at the Extension Registry will reveal that there are a lot of different extensions available, and new ones are being introduced on a regular basis. It's tempting to try many of them out just to see what they do. If you're coding a demo, there's nothing wrong with this, but if you're creating a game that will be distributed to a lot of people, you need to ask yourself whether or not the extension is really needed. Does it make your game run faster? Does it make your game use less video memory? Does it improve the visual quality of your game? Will using it reduce your development time? If the answer to any of these is yes, then the extension is probably a good candidate for inclusion in your product. On the other hand, if it offers no significant benefit, you may want to avoid it altogether.<br />
<br />
 <strong class='bbc'>What level of promotion is the extension at?</strong><br />
Extensions with higher promotion levels tend to be more widely supported. Any former extension that has been made part of the core 1.2 or 1.3 specification will be supported in compliant implementations, so they are the safest to use (1.2 more so than 1.3 since it's been around for longer). ARB-approved extensions (the ones that use the <span style='font-family: Courier New'><span style='color: #000080'>ARB</span></span> prefix) aren't required to be supported in compliant implementations, but they are expected to be widely supported, so they're the next safest. Extensions using the <span style='font-family: Courier New'><span style='color: #000080'>EXT</span></span> prefix are supported by two or more hardware vendors, and are thus moderately safe to use. Finally, vendor specific extensions are the most dangerous. Using them generally requires that you write a lot of special case code. However, they often offer significant benefits, so they should not be ignored. You just have to be especially careful when using them.<br />
 [indent]<blockquote><em class='bbc'>There are times when a vendor-specific extension can be completely replaced by an EXT or ARB extension. In this case, the latter should always be favored.</em></blockquote>[/indent] <strong class='bbc'>Who is your target audience?</strong><br />
If your target audience is hardcore gamers, you can expect that they are going to have newer hardware that will support many, if not all, of the latest extensions, so you can feel safer using them. Moreover, they will probably expect you to use the latest extensions; they want your game to take advantage of all those features they paid so much money for!<br />
<br />
 If, on the other hand, you're targeting casual game players, you'll probably want to use very few extensions, if any.<br />
<br />
 <strong class='bbc'>When will your game be done?</strong><br />
As mentioned earlier, the graphics industry moves at an extremely quick pace. An extension that is only supported on cutting-edge cards today may enjoy widespread support in two years. Then again, it may become entirely obsolete, either because it is something that consumers don't want, or because it gets replaced by another extension. If your ship date is far enough in the future, you may be able to risk using brand new extensions to enhance your game's graphics. On the other hand, if your game is close to shipping, or if you don't want to risk possible rewrites later on, you're better off sticking with extensions that are already well-supported.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>What To Do When an Extension Isn't Supported</strong></span><br />
<br />
First of all, let's make one thing very clear. Before you use any extension, you need to check to see if it is supported on the user's system. If it's not, you need to do something about it. What that "something" is depends on a number of things, as we'll discuss here, but you really need to have some kind of contingency plan. I've seen OpenGL code that just assumes that the needed extensions will be there. This can lead to blank screens, unexpected rendering effects, and even crashes. Here are some of the possible methods you can use when you find that an extension isn't supported.<br />
<br />
 <strong class='bbc'>Don't Use the Extension</strong><br />
If the extension is non-critical, or if there is simply no alternate way to accomplish the same thing, you may be able to get away with just not using it at all. For example compiled vertex arrays (<span style='font-family: Courier New'><span style='color: #000080'>EXT_compiled_vertex_array</span></span>) offer potential speed enhancements when using vertex arrays. The speed gains usually aren't big enough to make or break your program, though, so if they aren't supported, you can use a flag or other means to tell your program to not attempt to use them.<br />
<br />
 <strong class='bbc'>Try Similar Extensions</strong><br />
Because of the way that extensions evolve, it's possible that the extension you're trying to use is present under an older name (for example, most ARB extensions used to be EXT extensions, and vendor specific extensions before that). Or, if you're using a vendor-specific extension, there may be extensions from other vendors that do close to the same thing. The biggest drawback to this solution is that it requires a lot of special case code.<br />
<br />
 <strong class='bbc'>Find an Alternate Way</strong><br />
Many extensions were introduced as more efficient ways to do things which could already be done using only core OpenGL features. If you're willing to put in the effort, you can deal with the absence of these extensions by doing things the "old way". For instance, most things that can be done with multitexturing can be done using multipass rendering and alpha blending. Besides the additional code you have to add to handle this, your game will run slower because it has to make multiple passes through the geometry. That's better than not being able to run the game at all, and arguably better than simply dumping multitexturing and sacrificing visual quality.<br />
<br />
 <strong class='bbc'>Exit Gracefully</strong><br />
In some cases, you may decide that an extension is essential to your program, possibly because there is no other way to do the things you want to do, or because providing a backup plan would require more time and effort than you're willing to invest. When this happens, you should cause your program to exit normally, with a message telling the user what they need to be able to play your game. Note that if you choose to go this route, you should make sure that the hardware requirements listed on the product clearly state what is needed, or your customers will hate you.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>The Demo</strong></span><br />
<br />
I've created a <strong class='bbc'>simple demo</strong> (see attached resource file) to show you some extensions in action. As you can see from Figure 1, the demo itself is fairly simple, nothing more than a light moving above a textured surface, casting a light on it using a lightmap. The demo isn't interactive at all. I kept it simple because I wanted to be able to focus on the extension mechanism.<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[907584fcfad941fbba737f98d2544c8a]' id='ipb-attach-url-4672-0-57922100-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4672" title="fig1.jpg - Size: 47.46K, Downloads: 116"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-21700200-1312298031_thumb.jpg" id='ipb-attach-img-4672-0-57922100-1330207271' style='width:250;height:194' class='attach' width="250" height="194" alt="Attached Image: fig1.jpg" /></a><br />
<strong class='bbc'>Figure 1: Basic lightmapping (click to enlarge)</strong><br />
</p><br />
 The demo uses seven different extensions. Some of them aren't strictly necessary, but I wanted to include enough to get the point across. Table 2 lists all of the extensions in use, and how they are used.<br />
<br />
            <strong class='bbc'>Table 2 - Extensions used in the demo</strong>   <strong class='bbc'>Extension</strong>    <strong class='bbc'>Usage</strong>  ARB_multitexture The floor in this demo is a single quad with two textures applied to it: one for the bricks, and the other for the lightmap, which is updated with the light's position. The textures are combined using modulation.   EXT_point_parametetersWhen used, this extension causes point primitives to change size depending on their distance from the eye. You can set attenuation factors to determine how much the size changes, as well as define maximum and minimum sizes, and even specify that the points become partially transparent if they go below a certain threshold. The yellow light in the demo takes advantage of this extension. The effect is subtle, but you should be able to notice it changing size.   EXT_swap_control Most OpenGL drivers allow the user to specify whether or not screen redraws should wait for the monitor's vertical refresh, or vertical sync. If this is enabled, your game's framerate will be limited to whatever the monitor refresh rate is set to. This extension allows you to programmatically disable vsync to get to avoid this limitation.  EXT_bgra Since the demo uses Targas for textures, using this extension allows it to use their data directly without having to swap the red and blue components before creating the textures.   ARB_texture_compression    Since the demo only uses two textures, it won't gain much by using texture compression, but since it's easy, so I used it anyway. I allow the drivers to compress the data for me, rather than doing so myself beforehand.  EXT_texture_edge_clamp Again, this extension wasn't strictly necessary, but the demo shows how easy it is to use.   SGIS_generate_mipmap GLU provides a function, gluBuild2DMipMaps, that allows you to specify just the base level of a mipmap chain and automatically generates the other levels for you. This extension performs essentially the same function, with a couple of exceptions. One, it is a little more efficient. Two, it will cause all of the mipmap levels to be regenerated automatically whenever you change the base level. This can be useful when using dynamic textures. The full source code to the demo is included on the CD, but there are a couple of functions that I want to look at.<br />
<br />
 The first is <span style='font-family: Courier New'><span style='color: #000080'>InitializeExtensions()</span></span>. This function is called at startup, right after the rendering context is created. It verifies that the extensions used are supported, and gets the function entry points that are needed.<br />
<br />
 [indent]<pre class='prettyprint'>bool InitializeExtensions()<br />{<br />  if (CheckExtension("GL_ARB_multitexture"))<br />  {<br />    glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FARBPROC)<br />        wglGetProcAddress("glMultiTexCoord2fARB");<br />    glActiveTexture = (PFNGLCLIENTACTIVETEXTUREARBPROC)<br />        wglGetProcAddress("glActiveTextureARB");<br />    glClientActiveTexture = (PFNGLACTIVETEXTUREARBPROC)<br />        wglGetProcAddress("glClientActiveTextureARB");<br />  }<br />  else<br />  {<br />    MessageBox(g_hwnd, "This program requires multitexturing, which "<br />      "is not supported by your hardware", "ERROR", MB_OK);<br />    return false;<br />  }<br /><br />  if (CheckExtension("GL_EXT_point_parameters"))<br />  {<br />    glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)<br />        wglGetProcAddress("glPointParameterfvEXT");<br />  }<br /><br />  if (CheckExtension("WGL_EXT_swap_control"))<br />  {<br />    wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)<br />        wglGetProcAddress("wglSwapIntervalEXT");<br />  }<br /><br />  if (!CheckExtension("GL_EXT_bgra"))<br />  {<br />    MessageBox(g_hwnd, "This program requires the BGRA pixel storage"<br />      "format which is not supported by your hardware", "ERROR", MB_OK);<br />    return false;<br />  }<br /><br />  g_useTextureCompression =<br />      CheckExtension("GL_ARB_texture_compression");<br />  g_useEdgeClamp = CheckExtension("GL_EXT_texture_edge_clamp");<br />  g_useSGISMipmapGeneration =<br />      CheckExtension("GL_SGIS_generate_mipmap");<br /><br />  return true;<br />}</pre>[/indent] As you can see, there are two extensions that the demo requires: multitexturing and BGRA pixel formats. Although I could have provided alternate ways to do both of these things, doing so would have unnecessarily complicated the program.]]></description>
		<pubDate>Mon, 21 Apr 2003 23:37:37 +0000</pubDate>
		<guid isPermaLink="false">43c5b26b6738782b9e45719d8a45db1b</guid>
	</item>
	<item>
		<title>Compiling OpenGL Code with MFC</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/compiling-opengl-code-with-mfc-r1802</link>
		<description><![CDATA[<span style='font-size: 18px;'><strong class='bbc'>Using MFC</strong></span><br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>MainFrame Class</strong></span><br />
 <strong class='bbc'><br />
Step 1:</strong> In the Mainframe Class override the initial dimensions of the default wind&#111;w. Using the CREATESTRUCT we change the dimensions of the window to 400 x 400<br />
<br />
 [indent]<pre class='prettyprint'>BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)<br />{<br />  // TODO: Modify the Window class or styles here by modifying<br />  //  the CREATESTRUCT cs<br /><br />  cs.cx=400;<br />  cs.cy=400;<br /><br />  return CFrameWnd::PreCreateWindow(cs);<br />}<br /><br />BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)<br />{<br />  // TODO: Modify the Window class or styles here by modifying<br />  //  the CREATESTRUCT cs<br /><br />  cs.cx=400;<br />  cs.cy=400;<br /><br />  return CFrameWnd::PreCreateWindow(cs);<br />}<br />BOOL CMainFrame::OnQueryNewPalette() <br />{<br />  // TODO: Add your message handler code here and/or call default<br />  CView *pView=GetActiveView();<br />  pView-&gt;Invalidate(FALSE);<br />  return CFrameWnd::OnQueryNewPalette();<br />}<br />BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)<br />{<br />  // TODO: Modify the Window class or styles here by modifying<br />  // the CREATESTRUCT cs<br />  <br />  cs.cx=400;<br />  cs.cy=400;<br /><br />  return CFrameWnd::PreCreateWindow(cs);<br />}</pre>[/indent] <span style='font-size: 12px;'><strong class='bbc'>View Class</strong></span><br />
 <strong class='bbc'><br />
Step 1:</strong> Step up the pixel format and create a rendering context<br />
<br />
 [indent]<pre class='prettyprint'>int CMfc_cubeView::OnCreate(LPCREATESTRUCT lpCreateStruct) <br />{<br />  if (CView::OnCreate(lpCreateStruct) == -1)<br />    return -1;<br />  <br />  // TODO: Add your specialized creation code here<br />  PIXELFORMATDESCRIPTOR pfd=<br />  {<br />    sizeof(PIXELFORMATDESCRIPTOR),<br />      1,<br />      PFD_DRAW_TO_WINDOW&#124;<br />      PFD_SUPPORT_OPENGL&#124;<br />      PFD_DOUBLEBUFFER,<br />      PFD_TYPE_RGBA,<br />      24,          //24-bit color<br />      0,0,0,0,0,0,<br />      0,0,0,0,0,0,0,<br />      32,          //32 bit depth buffer<br />      0,0,<br />      PFD_MAIN_PLANE,    //Main layer type<br />      0,<br />      0,0,0<br />  };<br />  CClientDC clientDC(this);<br />  /*<br />  ChoosePixelFormat<br />  Requests a pixel-format index for a pixel format that most closely<br />  matches the format requested.   This function's two arguments are a<br />  handle to the DC for which to select the pixel format and the<br />  address of the PIXELFORMATDESCRIPTOR structure that holds the attributes<br />  of the requested pixel format<br />  */<br />  int pixelFormat =ChoosePixelFormat(clientDC.m_hDC,&pfd);<br />  BOOL success =   SetPixelFormat(clientDC.m_hDC,pixelFormat,&pfd);<br />  /*<br />  DescribePixelFormat<br />  Fills a PIXELFORMATDESCRIPTOR  structure with information about the given<br />  pixel format.  This function's four arguments are a handle to the DC, the <br />  pixel index to examine, and the size and address of PIXELFORMATDESCRIPTOR structure.<br />  */<br />  DescribePixelFormat(clientDC.m_hDC,pixelFormat, sizeof(pfd),&pfd);<br /><br />  if (pfd.dwFlags & PFD_NEED_PALETTE)<br />      SetupLogicalPalette();<br /><br />  /*<br />  wglCreateContext<br />  Creates a rendering context compatible with the given DC.<br />  */<br />  m_hRC=wglCreateContext(clientDC.m_hDC);<br />  /*<br />  wglMakeCurrent<br />  Makes a rendering context current, which binds the rendering<br />  context to the given DC.  This function's two arguments<br />  are a handle to a DC and the handle to the rendering context.<br />  */<br />  wglMakeCurrent(clientDC.m_hDC,m_hRC);<br /><br />  //Texture Mapping<br />  //Once you have your DIB loaded and its color tables created, you can<br />  // actually start thinking about your texture mapping<br />  //GL_TEXTURE_2D equates to a two-dimensional texture<br />  //GL_CLAMP for a single image<br />  //GL_REPEAT for a repeating pattern<br />  //GL_TEXTURE_MAG_FILTER determines how a texture is magnified when<br />  // the destination is larger than the texture.<br />  //GL_TEXTURE_MIN_FILTER determines how a texture is reduced<br />  //glTexEnvi set the texturing environment<br /><br />  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);<br />  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);<br />  <br />  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);<br />  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);<br />  glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);<br /><br />  glEnable(GL_DEPTH);<br />  glEnable(GL_TEXTURE_2D);<br /><br />  glClearColor(1.0f,1.0f,1.0f,1.0f);<br /><br />  wglMakeCurrent(clientDC.m_hDC,NULL);<br /><br />  /* CDib is a class used to read Device Independant Bitmaps */<br />  m_pDib = new CDib("snake.BMP");<br />  CreateColorTables(m_pDib);<br />  SetupColorTables();<br />  /* The timer determines the rendering refresh rate in milliseconds*/<br />  SetTimer(1,1,0);<br />  return 0;<br />}</pre>[/indent] <strong class='bbc'>Step 2:</strong> Cleanup resources: Bitmaps, Timers, and device contexts<br />
<br />
 [indent]<pre class='prettyprint'>void CMfc_cubeView::OnDestroy() <br />{<br />  CView::OnDestroy();<br />  <br />  // TODO: Add your message handler code here<br />  KillTimer(1);<br />  delete m_pDib;<br />  /*Frees the Rendering Context.  Cleanup of resources*/<br />  wglDeleteContext(m_hRC);<br />  if (m_hPalette)<br /> 	DeleteObject(m_hPalette);<br /><br />}</pre>[/indent] <strong class='bbc'>Step 3:</strong> Modify the Class style<br />
<br />
 [indent]<pre class='prettyprint'>BOOL CMfc_cubeView::PreCreateWindow(CREATESTRUCT& cs)<br />{<br />  // TODO: Modify the Window class or styles here by modifying<br />  // the CREATESTRUCT cs<br />  cs.style &#124;= WS_CLIPCHILDREN &#124; WS_CLIPSIBLINGS;<br /><br />  return CView::PreCreateWindow(cs);<br />}</pre>[/indent] <strong class='bbc'>Step 4:</strong> When Invalidate(TRUE) is invoked the OnDraw event is fired. The OnDraw method contains the rendering code portion.<br />
<br />
 [indent]<pre class='prettyprint'>void CMfc_cubeView::OnDraw(CDC* pDC)<br />{<br />  CMfc_cubeDoc* pDoc = GetDocument();<br />  ASSERT_VALID(pDoc);<br /><br />  // TODO: add draw code for native data here<br />  if (m_hPalette)<br />  {<br />    SelectPalette(pDC-&gt;m_hDC,m_hPalette, FALSE);<br />    RealizePalette(pDC-&gt;m_hDC);<br />  }<br />  wglMakeCurrent(pDC-&gt;m_hDC,m_hRC);<br />  DrawWithOpenGL();<br />  SwapBuffers(pDC-&gt;m_hDC);<br />  wglMakeCurrent(pDC-&gt;m_hDC,NULL);<br />}</pre>[/indent] <strong class='bbc'>Step 5:</strong> The OnSize method defines the current viewport, defines the PROJECTION Model and Object Model, and light sources.<br />
<br />
 [indent]<pre class='prettyprint'>void CMfc_cubeView::OnSize(UINT nType, int cx, int cy) <br />{<br />  CView::OnSize(nType, cx, cy);<br />  <br />  // TODO: Add your message handler code here<br />  CClientDC clientDC(this);<br />  wglMakeCurrent(clientDC.m_hDC,m_hRC);<br />  glViewport(0,0,cx,cy);<br />  glMatrixMode(GL_PROJECTION);<br />  glLoadIdentity();<br />  glFrustum(-1.0,1.0,-1.0,1.0,2.0,9.0);<br />  glMatrixMode(GL_MODELVIEW);<br />  glLoadIdentity();<br /><br />  GLfloat light0Ambient&#91;&#93;={0.0f,0.0f,0.0f,1.0f};<br />  GLfloat light0Diffuse&#91;&#93;={1.0f,1.0f,1.0f,1.0f};<br />  GLfloat light0Position&#91;&#93;={0.0f,0.0f,0.0f,1.0f};<br /><br />  glLightfv(GL_LIGHT0,GL_AMBIENT,light0Ambient);<br />  glLightfv(GL_LIGHT0,GL_DIFFUSE, light0Diffuse);<br />  glLightfv(GL_LIGHT0,GL_POSITION,light0Position);<br /><br />  glEnable(GL_LIGHTING);<br />  glEnable(GL_LIGHT0);<br /><br />  glTranslatef(0.0f,0.0f,-6.0f);<br />  wglMakeCurrent(NULL,NULL);<br />}</pre>[/indent] <strong class='bbc'>Step 6:</strong> On Timer event is invoke every X predefine milliseconds<br />
<br />
 [indent]<pre class='prettyprint'>void CMfc_cubeView::OnTimer(UINT nIDEvent) <br />{<br />  // TODO: Add your message handler code here and/or call default<br /><br />  if (m_cube_animate==1 )<br />  {<br />    m_cube_spin+=2;<br />  }<br />  if (m_icosa_animate==1)<br />  {<br />    m_icosa_spin+=2;<br />  }<br />  Invalidate(FALSE);<br /><br />  CView::OnTimer(nIDEvent);<br />}</pre>[/indent] <strong class='bbc'>Step 7:</strong> Your Rendering Code<br />
<br />
 [indent]<pre class='prettyprint'>void CMfc_cubeView::DrawWithOpenGL()<br />{<br />  glShadeModel(GL_SMOOTH);<br />  glEnable(GL_DEPTH_TEST);<br />  glClearColor(0.0f,0.0f,0.0f,1.0f);<br />  glClear(GL_COLOR_BUFFER_BIT &#124; GL_DEPTH_BUFFER_BIT);<br /><br />  AnimateCube();<br />}</pre>[/indent] <strong class='bbc'>Step 8:</strong> The Animated Cube Example<br />
<br />
 [indent]<pre class='prettyprint'>void CMfc_cubeView::AnimateCube()<br />{<br />  GLfloat glfMaterialColor&#91;&#93;={0.2f,0.8f,0.5f,1.0f};<br />  GLvoid* pTextureBits = (GLvoid*) m_pDib-&gt;GetDibBitsPtr();<br />  GLint width = m_pDib-&gt;GetDibWidth();<br />  GLint height = m_pDib-&gt;GetDibHeight();<br /><br />  glPushMatrix();<br />  glTexImage2D(GL_TEXTURE_2D,0,3,width,height,0,GL_COLOR_INDEX,<br />           	GL_UNSIGNED_BYTE,pTextureBits);<br />  glClear(GL_COLOR_INDEX&#124;GL_DEPTH_BUFFER_BIT);<br /><br />  glRotatef(m_cube_spin,1.0,1.0,1.0);<br />  glScalef (0.5,0.5,0.5);   /* modeling transformation */<br />    <br />  //glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,glfMaterialColor);<br /><br />  glBegin(GL_POLYGON);<br />  //glNormal3f(0.0f,0.0f,1.0f);<br />  //vertice 1<br />  glTexCoord2f(0.0f,1.0f);<br />  glVertex3f(1.0f,1.0f,1.0f);<br />  //vertice 2<br />  glTexCoord2f(0.0f,0.0f);<br />  glVertex3f(-1.0f,1.0f,1.0f);<br />  //vertice 3<br />  glTexCoord2f(1.0f,0.0f);<br />  glVertex3f(-1.0f,-1.0f,1.0f);<br />  //vertice 4<br />  glTexCoord2f(1.0f,1.0f);<br />  glVertex3f(1.0f,-1.0f,1.0f);<br />  glEnd();<br />    <br />  glBegin(GL_POLYGON);<br />  //glNormal3f(0.0f,0.0f,-1.0f);<br />  //vertice 1<br />  glTexCoord2f(0.0f,1.0f);<br />  glVertex3f(1.0f,1.0f,-1.0f);<br />  //vertice 2<br />  glTexCoord2f(0.0f,0.0f);<br />  glVertex3f(1.0f,-1.0f,-1.0f);<br />  //vertice 3<br />  glTexCoord2f(1.0f,0.0f);<br />  glVertex3f(-1.0f,-1.0f,-1.0f);<br />  //vertice 4<br />  glTexCoord2f(0.0f,0.0f);<br />  glVertex3f(-1.0f,1.0f,-1.0f);<br />  glEnd();<br /><br />  glBegin(GL_POLYGON);<br />  //glNormal3f(-1.0f,0.0f,0.0f);<br />  //vertice 1<br />  glTexCoord2f(0.0f,1.0f);<br />  glVertex3f(-1.0f,1.0f,1.0f);<br />  //vertice 2<br />  glTexCoord2f(0.0f,0.0f);<br />  glVertex3f(-1.0f,1.0f,-1.0f);<br />  //vertice 3<br />  glTexCoord2f(1.0f,0.0f);<br />  glVertex3f(-1.0f,-1.0f,-1.0f);<br />  //vertice 4<br />  glTexCoord2f(1.0f,1.0f);<br />  glVertex3f(-1.0f,-1.0f,1.0f);<br />  glEnd();<br /><br />  glBegin(GL_POLYGON);<br />  //glNormal3f(1.0f,0.0f,0.0f);<br />  //vertice 1<br />  glTexCoord2f(0.0f,1.0f);<br />  glVertex3f(1.0f,1.0f,1.0f);<br />  //vertice 2<br />  glTexCoord2f(0.0f,0.0f);<br />  glVertex3f(1.0f,-1.0f,1.0f);<br />  //vertice 3<br />  glTexCoord2f(1.0f,0.0f);<br />  glVertex3f(1.0f,-1.0f,-1.0f);<br />  //vertice 4<br />  glTexCoord2f(1.0f,1.0f);<br />  glVertex3f(1.0f,1.0f,-1.0f);<br />  glEnd();<br /><br />  glBegin(GL_POLYGON);<br />  //glNormal3f(0.0f,1.0f,0.0f);<br />  //vertice 1<br />  glTexCoord2f(0.0f,1.0f);<br />  glVertex3f(-1.0f,1.0f,-1.0f);<br />  //vertice 2<br />  glTexCoord2f(0.0f,0.0f);<br />  glVertex3f(-1.0f,1.0f,1.0f);<br />  //vertice 3<br />  glTexCoord2f(1.0f,0.0f);<br />  glVertex3f(1.0f,1.0f,1.0f);<br />  //vertice 4<br />  glTexCoord2f(1.0f,1.0f);<br />  glVertex3f(1.0f,1.0f,-1.0f);<br />  glEnd();<br /><br />  glBegin(GL_POLYGON);<br />  //glNormal3f(0.0f,-1.0f,0.0f);<br />  //vertice 1<br />  glTexCoord2f(0.0f,1.0f);<br />  glVertex3f(-1.0f,-1.0f,-1.0f);<br />  //vertice 2<br />  glTexCoord2f(0.0f,0.0f);<br />  glVertex3f(1.0f,-1.0f,-1.0f);<br />  //vertice 3<br />  glTexCoord2f(1.0f,0.0f);<br />  glVertex3f(1.0f,-1.0f,1.0f);<br />  //vertice 4<br />  glTexCoord2f(1.0f,1.0f);<br />  glVertex3f(-1.0f,-1.0f,1.0f);<br />  glEnd();<br /><br />  glPopMatrix();<br />}<br /><br />void CMfc_cubeView::CreateColorTables(CDib *pDib)<br />{<br />  LPRGBQUAD pColorTable = pDib-&gt;GetDibRGBTablePtr();<br />  for(UINT i=0; i&lt;256; ++i)<br />  {<br />    m_red&#91;i&#93;=(GLfloat) pColorTable&#91;i&#93;.rgbRed/255;<br />    m_green&#91;i&#93;=(GLfloat) pColorTable&#91;i&#93;.rgbGreen/255;<br />    m_blue&#91;i&#93;=(GLfloat) pColorTable&#91;i&#93;.rgbBlue/255;<br />  }<br />}<br /><br />void CMfc_cubeView::SetupColorTables()<br />{<br />  CClientDC clientDC(this);<br />  wglMakeCurrent(clientDC.m_hDC,m_hRC);<br />  glPixelMapfv(GL_PIXEL_MAP_I_TO_R,256,m_red);<br />  glPixelMapfv(GL_PIXEL_MAP_I_TO_G,256,m_green);<br />  glPixelMapfv(GL_PIXEL_MAP_I_TO_B,256,m_blue);<br />  glPixelTransferi(GL_MAP_COLOR,TRUE);<br />  wglMakeCurrent(clientDC.m_hDC,m_hRC);<br />}<br /><br />void CMfc_cubeView::SetupLogicalPalette()<br />{<br />  struct<br />  {<br />    WORD Version;<br />    WORD NumberOfEntries;<br />    PALETTEENTRY aEntries&#91;256&#93;;<br />  }logicalPalette={0x300,256};<br /><br />  BYTE reds&#91;&#93;={0,36,72,109,145,182,218,255};<br />  BYTE greens&#91;&#93;={0,36,72,109,145,182,218,255};<br />  BYTE blues&#91;&#93;={0,85,170,255};<br /><br />  for(int colorNum=0; colorNum&lt;256; ++colorNum)<br />  {<br />    logicalPalette.aEntries&#91;colorNum&#93;.peRed=reds&#91;colorNum&0x07&#93;;<br />    logicalPalette.aEntries&#91;colorNum&#93;.peGreen=greens&#91;(colorNum&gt;&gt;0x03)&0x07&#93;;<br />    logicalPalette.aEntries&#91;colorNum&#93;.peBlue=blues&#91;(colorNum&gt;&gt;0x06)&0x03&#93;;<br />    logicalPalette.aEntries&#91;colorNum&#93;.peFlags=0;<br />  }<br />  m_hPalette=CreatePalette ((LOGPALETTE*)&logicalPalette);<br />}</pre>[/indent]]]></description>
		<pubDate>Tue, 16 Apr 2002 14:16:02 +0000</pubDate>
		<guid isPermaLink="false">153e7487e891837a34233c390e64c710</guid>
	</item>
	<item>
		<title>Smooth Normal Generation with Preservation of E...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/smooth-normal-generation-with-preservation-of-e-r1763</link>
		<description><![CDATA[<span style='font-size: 18px;'><strong class='bbc'>Overview</strong></span><br />
<br />
	Normals are an important piece of geometry for rendering smooth surfaces. Generation of proper normals is very straightforward for continuous surfaces. To calculate a smooth normal for a vertex, average the facet normals of all the polygons that the vertex is in. However, this does not work when there are edges that are to be preserved in the model. This method will smooth out all edges. Therefore, it is desirable to selectively average normals according to a threshold for edge preservation.<br />
<br />
 A good example is a model of a cube. It is desirable for the cube to have flat faces. However, if all the facet normals around a vertex are averaged, and the resulting average normal is used, the cube takes on a spherical look (<a href='#fig1'>see figure 1</a>), which is probably not the desired effect.<br />
<br />
 Another gotcha when creating smooth normals is duplicate vertices. These can be eliminated by 'welding' vertices that are closer than a tolerance to each other. Then the normals are recalculated. See <a href='#fig2'>figure 2</a> for an example of this.<br />
<br />
 Different models require different edge tolerance angles. Sometimes the angle across some edges is the same as the angle between some geometry that should be smooth. This is a problem with my current algorithm. It could be dealt with by localizing the averaging according to user defined areas. See <a href='#fig3'>figure 3</a> for an example of problems of this kind (the base of the pawn is faceted, when it shouldn't be, but the tolerance must be 76° for the edge in the middle to appear).<br />
<br />
    <br />
<span style='font-size: 18px;'><strong class='bbc'>Implementation</strong></span><br />
<br />
<pre class='prettyprint'>/* glmVertexNormals: Generates smooth vertex normals for a model.<br /> * First builds a list of all the triangles each vertex is in.  Then<br /> * loops through each vertex in the the list averaging all the facet<br /> * normals of the triangles each vertex is in.  Finally, sets the<br /> * normal index in the triangle for the vertex to the generated smooth<br /> * normal.  If the dot product of a facet normal and the facet normal<br /> * associated with the first triangle in the list of triangles the<br /> * current vertex is in is greater than the cosine of the angle<br /> * parameter to the function, that facet normal is not added into the<br /> * average normal calculation and the corresponding vertex is given<br /> * the facet normal.  This tends to preserve hard edges.  The angle to<br /> * use depends on the model, but 90 degrees is usually a good start.<br /> *<br /> * model - initialized GLMmodel structure<br /> * angle - maximum angle (in degrees) to smooth across<br /> */</pre>See attached resource file with source code + tons of models + x86 executable (2,723,239 bytes).<br />
<br />
<a name='fig1'></a><table border="0" cellpadding="6" width="480"><tbody><tr><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3980-0-62968400-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3980" title="cubesmooth.jpg - Size: 10.05K, Downloads: 59"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-21612800-1309455107_thumb.jpg" id='ipb-attach-img-3980-0-62968400-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: cubesmooth.jpg" /></a></td><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3981-0-62977800-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3981" title="cubeflat.jpg - Size: 9.18K, Downloads: 56"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-10908200-1309455121_thumb.jpg" id='ipb-attach-img-3981-0-62977800-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: cubeflat.jpg" /></a></td></tr><tr><td>Smooth normals for a cube generated with a 91° edge tolerance (smooth across the edges).  Eight normals generated (one per vertex).</td><td>Smooth normals for a cube generated with an 89° edge tolerance (not smooth across the edges). Thirty-two normals generated.</td></tr><tr><td colspan="2" class="maintext-2" align="center"><b>Figure 1</b></td></tr></tbody></table><br />
<a name='fig2'></a><table border="0" cellpadding="6" width="480"><tbody><tr><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3982-0-62987800-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3982" title="teapotflat.jpg - Size: 18.63K, Downloads: 53"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-90715300-1309455140_thumb.jpg" id='ipb-attach-img-3982-0-62987800-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: teapotflat.jpg" /></a></td><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3983-0-62997800-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3983" title="teapotsmooth.jpg - Size: 15.87K, Downloads: 56"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-02886300-1309455163_thumb.jpg" id='ipb-attach-img-3983-0-62997800-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: teapotsmooth.jpg" /></a></td></tr><tr valign="top"><td>Flat shaded teapot (one normal per face).</td><td>Smooth normals generated (with a 90° edge tolerance).  The lines are where the bezier patches overlap.  There are duplicate vertices along the lines.</td></tr><tr><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3984-0-63009900-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3984" title="teapotweld.jpg - Size: 15.45K, Downloads: 49"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-73672000-1309455189_thumb.jpg" id='ipb-attach-img-3984-0-63009900-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: teapotweld.jpg" /></a></td><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3985-0-63020100-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3985" title="teapotwire.jpg - Size: 35.27K, Downloads: 55"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-66415800-1309455207_thumb.jpg" id='ipb-attach-img-3985-0-63020100-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: teapotwire.jpg" /></a></td></tr><tr valign="top"><td>Optimized teapot model (duplicate vertices removed).</td><td>Wireframe teapot to illustrate structure. </td></tr><tr><td colspan="2" class="maintext-2" align="center"><b>Figure 2</b></td></tr></tbody></table><br />
<a name='fig3'></a><table border="0" cellpadding="6" width="480"><tbody><tr><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3986-0-63030100-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3986" title="pawnflat.jpg - Size: 13.69K, Downloads: 49"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-39126400-1309455227_thumb.jpg" id='ipb-attach-img-3986-0-63030100-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: pawnflat.jpg" /></a></td><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3987-0-63041200-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3987" title="pawnsmooth.jpg - Size: 11.06K, Downloads: 51"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-97359400-1309455243_thumb.jpg" id='ipb-attach-img-3987-0-63041200-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: pawnsmooth.jpg" /></a></td></tr><tr valign="top"><td>Flat shaded pawn.</td><td>Smooth normals generated (with a 90° edge tolerance). Notice the sharp edges in the model. </td></tr><tr><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3988-0-63051300-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3988" title="pawntoler.jpg - Size: 11.93K, Downloads: 55"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-71796800-1309455262_thumb.jpg" id='ipb-attach-img-3988-0-63051300-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: pawntoler.jpg" /></a></td><td>The third pawn image with the good specular highlight has normals that were created with an edge tolerance of 76°.  These edge tolerance angles are very model specific.</td></tr><tr valign="top"><td>Smooth shaded pawn.</td><td>&nbsp;</td></tr><tr><td colspan="2" class="maintext-2" align="center"><b>Figure 3</b></td></tr></tbody></table><br />
<table border="0" cellpadding="6" width="480"><tbody><tr><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3989-0-63061400-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3989" title="headflat.jpg - Size: 25.45K, Downloads: 55"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-80261300-1309455282_thumb.jpg" id='ipb-attach-img-3989-0-63061400-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: headflat.jpg" /></a></td><td><a class='resized_img' rel='lightbox[049424e13ca440a08d67df9a5bec534a]' id='ipb-attach-url-3990-0-63071600-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3990" title="headsmooth.jpg - Size: 20.46K, Downloads: 60"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-96179900-1309455294_thumb.jpg" id='ipb-attach-img-3990-0-63071600-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: headsmooth.jpg" /></a></td></tr><tr valign="top"><td>Flat shaded head.</td><td>Smooth normals generated (with a 90° edge tolerance). Notice the sharp edges (especially around the eyes) in the model.</td></tr><tr><td colspan="2" class="maintext-2" align="center"><b>Figure 4</b></td></tr></tbody></table><br />
]]></description>
		<pubDate>Sun, 17 Feb 2002 13:11:01 +0000</pubDate>
		<guid isPermaLink="false">d63036cfba56a5c3cb75ab14b33fe677</guid>
	</item>
	<item>
		<title>Lighting and Normals</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/lighting-and-normals-r1682</link>
		<description><![CDATA[<p class='bbc_center'><a class='resized_img' rel='lightbox[c4a5feae7dc040fcba4096a4235e9559]' id='ipb-attach-url-3957-0-66214500-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3957" title="screenshot3.jpg - Size: 16.42K, Downloads: 49"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-42719200-1309435107_thumb.jpg" id='ipb-attach-img-3957-0-66214500-1330207271' style='width:188;height:200' class='attach' width="188" height="200" alt="Attached Image: screenshot3.jpg" /></a><br />
</p>  <br />
Extending on the previous tutorial's spinning cube code, this tutorial will explain how to calculate your cube's face normals and add OpenGL lighting to your program.<br />
<br />
 When you've completed this tutorial, you should have a good enough understanding of the of OpenGL lighting to be able to use it in your own code.<br />
<br />
 We'll be using the same code as we used in the previous tutorial, so load it up and we'll begin.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>The Code</strong></span><br />
 <br />
The first thing we'll do is add normals to our cube quad struct. Normals are vectors of length 1 which indicate the angle of facing of a polygon. The cube struct should now look like this:<br />
<br />
 [indent]<pre class='prettyprint'>struct <br />{<br />  struct<br />  {<br />    float pos&#91;3&#93;;<br />    float col&#91;3&#93;;<br />  }ver&#91;8&#93;;<br /><br />  struct<br />  {<br />    unsigned int ver&#91;6&#93;;<br />    float norm&#91;3&#93;;<br />  }quad&#91;6&#93;;<br />}cube;</pre>[/indent] As we're going to be doing lighting, we'll need a way to store on our lights. Because we might want to have more than one light, it makes sense to use a typedef struct.<br />
<br />
 [indent]<pre class='prettyprint'>typedef struct<br />{<br />  float pos&#91;4&#93;;<br />  float diffuse&#91;4&#93;;<br />  float specular&#91;4&#93;;<br />  float ambient&#91;4&#93;;<br />}light_t;</pre>[/indent] We'll then create an instance of light_t and fill it like this, to create a plain white positional light, positioned at (6,10,15).<br />
<br />
 [indent]<pre class='prettyprint'>light_t light={<br />      {6,10,15,1},  //position (the final 1 means the light is positional)<br />      {1,1,1,1},    //diffuse<br />      {0,0,0,1},    //specular<br />      {0,0,0,1} 	//ambient<br />    };</pre>[/indent] Next we need to add a few lines to our initialization in order to set up the lighting in our program. glEnable(GL_LIGHTING) is fairly self explanatory, I hope. glEnable(GL_LIGHT0) enables light 0 (there are 8 to choose from). glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, 0) specifies that we only want OpenGL to calculate lighting on front faces, ignoring the invisible back ones.<br />
<br />
 [indent]<pre class='prettyprint'>glEnable(GL_LIGHTING);                 	//enables lighting<br />glEnable(GL_LIGHT0);                   	//enables a light<br />glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0);  //sets lighting to one-sided</pre>[/indent] When GL_LIGHTING is enabled, vertices' colours are specified by their material (which holds specular, diffuse and ambient lighting properties) rather than the current colour, however, if we call glEnable(GL_COLOR_MATERIAL) it will cause the current material to "track" the current colour, meaning our calls to glColor3f() will still work.<br />
<br />
 [indent]<pre class='prettyprint'>glEnable(GL_COLOR_MATERIAL);</pre>[/indent] If we left it at that, the ambient and diffuse properties of the material would track the current colour. We don't want that, however, because the ambient colour would cause our cube to glow like something out of Chernobyl, so we'll call glColorMaterial(GL_FRONT,GL_DIFFUSE), which will cause only the diffuse property to track the current colour, resulting in a much healthier looking cube.<br />
<br />
 [indent]<pre class='prettyprint'>glColorMaterial(GL_FRONT,GL_DIFFUSE);</pre>[/indent] Finally, we'll need to make sure that the current material's ambient and specular properties are set to black, as we don't want (or at least I don't want) the cube to be self-illuminating or reflective.<br />
<br />
 [indent]<pre class='prettyprint'>float black&#91;4&#93;={0,0,0,0};<br />glMaterialfv(GL_FRONT,GL_AMBIENT,black);<br />glMaterialfv(GL_FRONT,GL_SPECULAR,black);</pre>[/indent] Next we're going to need to calculate the normals. While we could calculate them by hand very easily (top is (0,1,0) etc) in the case of our cube, it would be useful to be able to calculate them for any given polygon, so we'll need to create some new functions. Add the following declarations in the global scope:<br />
<br />
 [indent]<pre class='prettyprint'>void crossProduct(float *c,float a&#91;3&#93;, float b&#91;3&#93;);<br />void normalize(float *vect);<br />void getFaceNormal(float *norm,float pointa&#91;3&#93;,float pointb&#91;3&#93;,float pointc&#91;3&#93;);</pre>[/indent] The function getFaceNormal() will calculate the normal for any face given three points in clockwise order. When it's done it'll store the normal in a place pointed to by <em class='bbc'>norm</em>.<br />
<br />
 The first thing it'll do is copy the points <em class='bbc'>pointa, pointb</em> and <em class='bbc'>pointc</em> into a 2-dimensional array, <em class='bbc'>point[ ] [ ]</em>.<br />
<br />
 [indent]<pre class='prettyprint'>void <br />getFaceNormal(float *norm,float pointa&#91;3&#93;,float pointb&#91;3&#93;,float pointc&#91;3&#93;)<br />{<br />  float vect&#91;2&#93;&#91;3&#93;;<br />  int a,b;<br />  float point&#91;3&#93;&#91;3&#93;;<br /><br />  for (a=0;a&lt;3;++a)<br />  {<br />    point&#91;0&#93;&#91;a&#93;=pointa&#91;a&#93;;    //copies points into point&#91;&#93;&#91;&#93;<br />    point&#91;1&#93;&#91;a&#93;=pointb&#91;a&#93;; <br />    point&#91;2&#93;&#91;a&#93;=pointc&#91;a&#93;;<br />  }</pre>[/indent] Next, we need to calculate two vectors; one going from point[0] to point[1] and the other going from point[0] to point[2]. We can find them by subtracting point[0] from point[1] and then point[0] from point[2]. I'm not sure why I decided code it like this; I'm sure there's an easier way:<br />
<br />
 [indent]<pre class='prettyprint'>  for (a=0;a&lt;2;++a)        //calculates vectors from point&#91;0&#93; to point&#91;1&#93;<br />  {                        //and point&#91;0&#93; to point&#91;2&#93;<br />    for (b=0;b&lt;3;++b)<br />    {<br />      vect&#91;a&#93;&#91;b&#93;=point&#91;2-a&#93;&#91;b&#93;-point&#91;0&#93;&#91;b&#93;;      <br />    }<br />  }</pre>[/indent] Finally, we need to find the cross product of the 2 vectors to find the vector at 90º to them, and then normalise the result (make it of length 1). These functions aren't written yet, but I'll get there.<br />
<br />
 [indent]<pre class='prettyprint'>  crossProduct(norm,vect&#91;0&#93;,vect&#91;1&#93;);           	//calculates vector at 90° to to 2 vectors<br />  normalize(norm);                                  //makes the vector length 1<br />}</pre>[/indent] The crossProduct() function calculates the cross product of the 2 vectors and sends the result to <em class='bbc'>c.</em><br />
<br />
 [indent]<pre class='prettyprint'>void crossProduct(float *c,float a&#91;3&#93;, float b&#91;3&#93;)  //finds the cross product of two vectors<br />{  <br />  c&#91;0&#93;=a&#91;1&#93;*b&#91;2&#93; - b&#91;1&#93;*a&#91;2&#93;;<br />  c&#91;1&#93;=a&#91;2&#93;*b&#91;0&#93; - b&#91;2&#93;*a&#91;0&#93;;<br />  c&#91;2&#93;=a&#91;0&#93;*b&#91;1&#93; - b&#91;0&#93;*a&#91;1&#93;;<br />}</pre>[/indent] The normalise() function finds the <em class='bbc'>length</em> of the vector pointed to by the pointer <em class='bbc'>vect</em> using Pythagoras' Theorem extended slightly: A² + B² + C² = D², where A, B and C are the vector's dimensions in X, Y and Z, and D is the length of the vector. Use of sqrt() requires we include math.h in our code, so we'll need to add it to the header includes.<br />
<br />
 [indent]<pre class='prettyprint'>length=sqrt(        //A^2 + B^2 + C^2 = length^2<br />  pow(vect&#91;0&#93;,2)+  <br />  pow(vect&#91;1&#93;,2)+<br />  pow(vect&#91;2&#93;,2)<br />  );</pre>[/indent] The function then divides the vector by <em class='bbc'>length</em> to normalise it. Whilst we could at this point check if length equals 0 to prevent divides by zero, its probably not necessary as we shouldn't be sending this function vectors with no length anyway.<br />
<br />
 [indent]<pre class='prettyprint'>for (a=0;a&lt;3;++a)        <br />{<br />  vect&#91;a&#93;/=length;<br />}</pre>[/indent] Next we'll add normal calculation to our initCube() function. At the bottom of the function, just before the closing brace, we'll add the following code, which calculates the normals for every quad and stores the result in cube.quad[ ].norm.<br />
<br />
 [indent]<pre class='prettyprint'>for (a=0;a&lt;6;++a)<br />{<br />  getFaceNormal(cube.quad&#91;a&#93;.norm,  cube.ver&#91; cube.quad&#91;a&#93;.ver&#91;2&#93; &#93;.pos,<br />            cube.ver&#91; cube.quad&#91;a&#93;.ver&#91;1&#93; &#93;.pos,<br />            cube.ver&#91; cube.quad&#91;a&#93;.ver&#91;0&#93; &#93;.pos);<br />}</pre>[/indent] Now, in our redraw function, we need to position the lights. Although we could just do this in our initialise function, we may want to update the position or colour of the light at some time in the main loop of the program, so we need it here. Because we're specifying the position of the light before we translate the modelview matrix for drawing the cube, the position will change relative to the cube as the cube rotates. We'll add the code just after the call to glClear().<br />
<br />
 [indent]<pre class='prettyprint'>glClear(GL_COLOR_BUFFER_BIT &#124; GL_DEPTH_BUFFER_BIT);<br /><br />glLightfv(GL_LIGHT0,GL_POSITION,light.pos);   	//updates the light's position<br />glLightfv(GL_LIGHT0,GL_DIFFUSE,light.diffuse);    //updates the light's diffuse colour<br />glLightfv(GL_LIGHT0,GL_SPECULAR,light.specular);  //updates the light's specular colour<br />glLightfv(GL_LIGHT0,GL_AMBIENT,light.ambient);    //updates the light's ambient colour<br /><br />glPushMatrix();</pre>[/indent] All we need now is to draw our cube with its normals. In our redraw function at the beginning of the quad loop (just after the line that says "for (a=0;a&lt;6;++a)"), we'll add the glNormal command which will specify the normals for each quad.<br />
<br />
 [indent]<pre class='prettyprint'>for (a=0;a&lt;6;++a)<br />{<br />  glNormal3fv(cube.quad&#91; a &#93;.norm);           	//sets the current normal to this quad's normal<br />  for (b=0;b&lt;4;++b)<br />  {<br />    currentVer=cube.quad&#91;a&#93;.ver&#91;b&#93;;</pre>[/indent] And we're done. Run the code and see for yourself. OpenGL can simulate a lot of different effects and materials with its lighting engine, so its worth experimenting with different lighting settings and material properties to see the different effects you can get. If you want to offer some feedback on this article, or if you have any questions or requests for future tutorials, please <a href='mailto:ben@elf-stone.com' title='E-mail Link' class='bbc_email'>email me</a>.<br />
<br />
<p class='bbc_center'> This tutorial is Copyright © 2001 Ben Woodhouse<br />
 </p>]]></description>
		<pubDate>Tue, 29 Jan 2002 22:59:52 +0000</pubDate>
		<guid isPermaLink="false">9518dfaa68111174c238799ce9116e74</guid>
	</item>
	<item>
		<title>Spinning Cube</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/spinning-cube-r1681</link>
		<description><![CDATA[<p class='bbc_center'><a class='resized_img' rel='lightbox[20ad12f5eee94c03b61c0568345eed4a]' id='ipb-attach-url-3954-0-69493400-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3954" title="screenshot2.jpg - Size: 12.52K, Downloads: 65"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-71815600-1309434471_thumb.jpg" id='ipb-attach-img-3954-0-69493400-1330207271' style='width:188;height:200' class='attach' width="188" height="200" alt="Attached Image: screenshot2.jpg" /></a>  <br />
<br />
</p>In this tutorial I'll expand on the previous tutorial's code to show you the basics of animation and models using OpenGL and GLUT. By the end you should know how to create a spinning cube.<br />
<br />
 While we could use the GLUT function glutSolidCube() to create our cube, that wouldn't teach much about storing and drawing 3D objects (and it wouldn't leave much for me to write) so we're going to do it the hard way using glBegin() and glEnd().<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>A Note On Coordinates</strong></span><br />
<br />
As we're going to be dealing a lot with coordinates in this tutorial, I feel it would be a good idea to explain a bit about them. As you probably know, a point in 3D space is specified by an X, Y and Z value, each value showing how far the point is along a particular axis. If you're new to 3D programming, you may not be familiar with the direction of the axes. Well, in the right-handed coordinate system OpenGL uses, the X axis points right, the Y axis up, and the Z axis points <strong class='bbc'>backwards</strong>.<br />
<br />
<p class='bbc_center'> <a class='resized_img' rel='lightbox[20ad12f5eee94c03b61c0568345eed4a]' id='ipb-attach-url-3955-0-69508100-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3955" title="coords.jpg - Size: 2.66K, Downloads: 65"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-55671700-1309434494_thumb.jpg" id='ipb-attach-img-3955-0-69508100-1330207271' style='width:132;height:110' class='attach' width="132" height="110" alt="Attached Image: coords.jpg" /></a><br />
</p><br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>The Code</strong></span><br />
<br />
We're going to build on the code for the previous tutorial, so load it up. The main function should look like this:<br />
<br />
 [indent]<pre class='prettyprint'>int main(int argc, char **argv)<br />{<br />  glutInit(&argc,argv);<br />  glutInitDisplayMode(GLUT_RGB &#124; GLUT_DOUBLE &#124; GLUT_DEPTH);<br />  glutCreateWindow("My first GLUT program");<br />  <br />  glutDisplayFunc(redraw); <br />  <br />  glMatrixMode(GL_PROJECTION); //hello<br />  gluPerspective(45, //view angle<br />             	1.0, //aspect ratio<br />             	10.0, //near clip<br />             	200.0);//far clip<br />  glMatrixMode(GL_MODELVIEW);<br />  <br />  glutMainLoop();<br />  <br />  return 0; <br />}</pre>[/indent] The first thing we're going to do is change our title, so we'll change the glutCreateWindow call to this:<br />
<br />
 [indent]<pre class='prettyprint'>glutCreateWindow("Spinning cube");</pre>[/indent] Next we want to enable backface culling so that only the outside faces of our cube will be drawn (there's not much point in drawing the inside faces, as we won't see them). Backface culling works by drawing polygons whose vertices are ordered anti-clockwise on the screen, ignoring those whose vertices are ordered clockwise, meaning a polygon is only visible from one side, and effectively meaning that OpenGL need only draw (on average) half the number of polygons.<br />
<br />
 Because we're using backface culling we have to be careful about the order of the vertices when we draw our polygons, but we'll come to that later. For now, we'll just add following line just above the call to glutMainLoop().<br />
<br />
 [indent]<pre class='prettyprint'>glEnable(GL_CULL_FACE);</pre>[/indent] We're going to need to store the data for the cube somewhere, so we'll create a global struct, called, imaginatively enough, "cube". Inside this cube struct we'll need an array of 8 ver structs, each containing position and colour data for a vertex. We'll also need data for each face of the cube. To keep things simple we're going to be using quads instead of triangles, which means we only need specify 6 of them. An array of quad structs will hold their data. Within the quad struct, the ver[ ] array will hold the vertex numbers for each of the quad's vertices.<br />
<br />
 [indent]<pre class='prettyprint'>struct<br />{<br />  struct<br />  {<br />    float pos&#91;3&#93;;<br />    float col&#91;3&#93;;<br />  }ver&#91;8&#93;;<br /><br />  struct<br />  {<br />    unsigned int ver&#91;4&#93;;<br />  } quad&#91;6&#93;;<br />}cube;</pre>[/indent] The next thing we need to do is actually set up the vertex and quad data for the cube so we can draw it, so we need to write a function to do that. We'll insert the following call under our call to glEnable(GL_CULL_FACE) in the main() function:<br />
<br />
 [indent]<pre class='prettyprint'>initCube();</pre>[/indent] We'll add the following declaration in the global scope:<br />
<br />
 [indent]<pre class='prettyprint'>void initCube(void);</pre>[/indent] Then we'll need to start writing initCube(). The arrangement of the vertices is not particularly important, as long we don't decide to change them later, but I've decided to arrange them like this. Note the positions in X, Y and Z for each of the points.<br />
<br />
<p class='bbc_center'> <a class='resized_img' rel='lightbox[20ad12f5eee94c03b61c0568345eed4a]' id='ipb-attach-url-3956-0-69520000-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3956" title="cubediagram.jpg - Size: 6.64K, Downloads: 52"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-88674400-1309434610_thumb.jpg" id='ipb-attach-img-3956-0-69520000-1330207271' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: cubediagram.jpg" /></a><br />
</p><br />
 The first thing we'll to do is lay out the positions of all our vertices of our cube in the local array vertexPosDat[ <em class='bbc'>vertex</em> ][ <em class='bbc'>dimension (x/y/z)</em> ].<br />
<br />
 [indent]<pre class='prettyprint'>void initCube(void)<br />{<br />  //defines the position of each vertex<br />  float  vertexPosDat&#91;8&#93;&#91;3&#93;=<br />  {<br />    {-10, 10, 10},  //left,top,front<br />    {10, 10, 10},   //right,top,front<br />    {10, 10,-10},   //right,top,back<br />    {-10, 10,-10},  //left, top,back<br />    {-10,-10, 10},  //left,bottom,front<br />    {10, -10, 10},  //right,bottom,front<br />    {10, -10,-10},  //right,bottom,back<br />    {-10,-10,-10}   //left,bottom,back<br />  };</pre>[/indent] Next, we'll define the colours for each of the vertices with vertexColDat[ <em class='bbc'>vertex</em> ][ <em class='bbc'>colour element (r/g/b)</em> ]. Feel free to be creative at this point. I decided to do them like this:<br />
<br />
 [indent]<pre class='prettyprint'>  //defines the colour of each vertex<br />  float   vertexColDat&#91;8&#93;&#91;3&#93;=<br />  {<br />    {0.5, 0 ,0},   //dark red<br />    {1, 1, 0.3},   //yellow<br />    {1, 0, 0}, 	//red<br />    {0.5, 1, 0.2}, //dull yellow??<br />    {1, 1, 0}, 	//yellow<br />    {0.9, 0.5, 0}, //orange<br />    {1, 0.9, 0.1}, //yellow<br />    {1, 0, 0}, 	//red<br />  };</pre>[/indent] All that's left to define now is the vertex numbers of the 4 points of each of the 6 quads on our cube. We'll use the array quadVerDat[<em class='bbc'>quad number</em>][<em class='bbc'>point</em>] to hold them.<br />
<br />
 [indent]<pre class='prettyprint'>  //defines the vertexes of each quad in anti-clockwise order<br />  unsigned int quadVerDat&#91;6&#93;&#91;4&#93;=<br />  {<br />    {0,1,2,3},  //top<br />    {0,3,7,4},  //left<br />    {3,2,6,7},  //back<br />    {2,1,5,6},  //right<br />    {0,4,5,1},  //front<br />    {4,7,6,5},  //bottom<br />  };</pre>[/indent] Now we just have to put the above data into our cube struct and we're done in cubeInit(). The code below simply loops through every vertex and sets the colours and position to the values we specified above, then loops through every quad and sets the vertex numbers.<br />
<br />
 [indent]<pre class='prettyprint'>  int a,b;<br /><br />  //put the vertex data into the cube.ver&#91;&#93; struct<br />  for (a=0;a&lt;8;++a)<br />  {<br />    for (b=0;b&lt;3;++b)<br />    {<br />      cube.ver&#91;a&#93;.pos&#91;b&#93;=vertexPosDat&#91;a&#93;&#91;b&#93;;<br />      cube.ver&#91;a&#93;.col&#91;b&#93;=vertexColDat&#91;a&#93;&#91;b&#93;;<br />    }<br />  }<br /><br />  //put the quad data into the cube.quad&#91;&#93; struct<br />  for (a=0;a&lt;6;++a)<br />  {<br />    for (b=0;b&lt;4;++b)<br />    {<br />      cube.quad&#91;a&#93;.ver&#91;b&#93;=quadVerDat&#91;a&#93;&#91;b&#93;;<br />    }<br />  }<br />} //end of cubeInit()</pre>[/indent] Now we need to rewrite our redraw() function to draw and rotate our cube. We'll use a static float, rotateBy, which will control the angle of rotation of our cube. Every frame we'll increment rotateBy by 0.1 to make the cube rotate. We'll need an int, currentVer, to hold the current point we're rendering for when we draw the cube.<br />
<br />
 [indent]<pre class='prettyprint'>static void redraw(void)<br />{<br />  static float rotateBy=0;<br />  int a,b;<br />  unsigned int currentVer;<br />  <br />  rotateBy+=0.1;<br />  glClear(GL_COLOR_BUFFER_BIT &#124; GL_DEPTH_BUFFER_BIT);</pre>[/indent] Once we've cleared the depth and colour buffers we're ready to start drawing. The first thing we do is save the current modelview matrix by copying it onto the top of the stack with glPushMatrix(). We can then start translating and rotating the matrix, which has the effect of translating or rotating anything we draw subsequently. So we'll translate by (0,0,-50), moving our or our cube forwards (or our camera back) by 50.<br />
<br />
 [indent]<pre class='prettyprint'>  glPushMatrix();<br />  glTranslatef(0,0,-50);</pre>[/indent] Next we'll rotate the matrix about the vector (1,1,0) by the angle rotateBy using glRotate(). This will cause the cube to rotate (or the camera to orbit the cube).<br />
<br />
 [indent]<pre class='prettyprint'>  glRotatef(rotateBy,1,1,0);  //rotate by rotateBy degrees about the vector (1,1,0)</pre>[/indent] Next we draw the actual cube. We're going to be using quads, so we'll call glBegin(GL_QUADS). The program then loops through the 6 quads in our cube, and for each point of each quad it gets the current vertex from cube.quad[a].ver&#91;b&#93; which holds the vertex number for that particular point of that quad. Then, armed with the number of the current vertex, it changes the current colour to the colour of the current vertex using glColor3fv() and draws a vertex at the position of the current vertex using glVertex3fv().<br />
<br />
 [indent]<pre class='prettyprint'>  glBegin(GL_QUADS); <br />  for (a=0;a&lt;6;++a)                       	//quads loop<br />  {<br />    for (b=0;b&lt;4;++b)                     	//points loop<br />    {<br />      currentVer=cube.quad&#91;a&#93;.ver&#91;b&#93;;            //sets the current vertex to this point's vertex<br /><br />      glColor3fv(cube.ver&#91; currentVer &#93;.col);    //changes the colour to the current vertex's colour<br />      glVertex3fv(cube.ver&#91; currentVer &#93;.pos);   //draws a vertex at the current vertex's position<br />    }<br />  }</pre>[/indent]<strong class='bbc'>Note:</strong> The 'v' on the end of glColor3fv() and glVertex3fv() means we can pass an array to them, which is more efficient than specifying each parameter seperately. The '3' means there are 3 parameters (or array elements in this case) and the 'f' means the data should be of type float.<br />
<br />
 Finally we call glEnd(), restore the old modelview matrix with glPopMatrix(), swap the buffers and call glutPostRedisplay() to tell GLUT to redraw the frame during the next cycle of the GLUT framework (not doing this would result in the frame only being redrawn when the window is opened or resized).<br />
<br />
 [indent]<pre class='prettyprint'>  glEnd();<br />  glPopMatrix();<br /><br />  glutSwapBuffers();<br />  glutPostRedisplay();<br />}</pre>[/indent] And there you have it. A rotating cube. Hopefully you've learned something from this tutorial. If you have any questions or would like to offer feedback, please <a href='mailto:ben@elf-stone.com' title='E-mail Link' class='bbc_email'>email me</a>.<br />
<br />
<p class='bbc_center'> This tutorial is Copyright © 2001 Ben Woodhouse<br />
</p>]]></description>
		<pubDate>Tue, 29 Jan 2002 22:58:32 +0000</pubDate>
		<guid isPermaLink="false">7a6bda9ad6ffdac035c752743b7e9d0e</guid>
	</item>
	<item>
		<title>Basics of GLUT</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/basics-of-glut-r1680</link>
		<description><![CDATA[<p class='bbc_center'><a class='resized_img' rel='lightbox[9d7ab79d2ccf4ac892c3ea0a507bb0c8]' id='ipb-attach-url-3953-0-72413900-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3953" title="screenshot.jpg - Size: 10.46K, Downloads: 66"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-02725700-1309433418_thumb.jpg" id='ipb-attach-img-3953-0-72413900-1330207271' style='width:188;height:200' class='attach' width="188" height="200" alt="Attached Image: screenshot.jpg" /></a>  <br />
</p><br />
In this tutorial I'll cover the basics of setting up and using OpenGL and GLUT with VC++. I'll take you through initializing your GLUT display, opening a window and displaying a triangle in it. The program you'll learn how to create is a foundation for more complex GLUT projects you might want to undertake in the future.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>What is GLUT?</strong></span><br />
<br />
GLUT stands for OpenGL Utility Toolkit. It's an API for OpenGL written by Mark Kilgard. GLUT is very easy to set up and use compared to traditional Win32 OpenGL, making it great for beginners. Because GLUT handles input and window setup, GLUT code is not platform specific, meaning any application you write will run on just about any platform (until you start adding DirectSound code, that is...).<br />
<br />
 Some preliminary links:<br />
 [indent] <blockquote><a href='http://www.opengl.org/developers/documentation/glut/index.html' class='bbc_url' title='External link' rel='nofollow external'>Mark Kilgard's GLUT page</a><br />
<a href='http://www.opengl.org/developers/faqs/technical/glut.htm' class='bbc_url' title='External link' rel='nofollow external'>The GLUT FAQ</a><br />
<a href='http://www.opengl.org/developers/documentation/glut/spec3.html' class='bbc_url' title='External link' rel='nofollow external'>The online GLUT 3 specification</a></blockquote><br />
 [/indent] <span style='font-size: 18px;'><strong class='bbc'>Getting the GLUT files</strong></span><br />
<br />
You can download the latest version of glut from <a href='http://www.xmission.com/%7Enate/glut.html' class='bbc_url' title='External link' rel='nofollow external'>here</a>.<br />
<br />
 Once you've downloaded and unzipped the file, copy glut32.dll to your windows&#092;system directory, glut32.lib to your compiler's lib directory and glut.h to your compiler's include&#092;gl directory. Now you're ready to roll.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Creating your GLUT project</strong></span><br />
<br />
Start up VC++, then create an empty console application.<br />
<br />
 Link to glut32.lib, glu32.lib and opengl32.lib in project > settings<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>The Program</strong></span><br />
<br />
This code includes headers for the libraries we'll be using and declares our functions.<br />
<br />
 [indent]<pre class='prettyprint'>#include &lt;windows.h&gt;           	//header file for windows<br />#include &lt;gl&#092;gl.h&gt;             	//header file for openGL<br />#include &lt;gl&#092;glu.h&gt;                //header file for the openGL utility library<br />#include &lt;gl&#092;glut.h&gt;           	//header file for GLUT<br /><br />static void redraw(void);          //declarations<br />int main(int argc, char **argv);</pre>[/indent] The argc variable contains the number of arguments passed to our program, while argv is a pointer to the arguments. We don't need to worry about them particularly, except to pass them to glutInit() so it can process any command line parameters sent to GLUT. The glutInit() function initializes the GLUT framework.<br />
<br />
 The glutInitDisplayMode function is used to set up the display mode. We'll call it with the following flags:<br />
 <ul class='bbc'><li><strong class='bbc'>GLUT_RGB</strong> specifies we want an RGB colour buffer in our window</li><li><strong class='bbc'>GLUT_DOUBLE</strong> specifies we want a double buffer. Double buffering enables us to finish drawing before our image is sent to the screen, preventing flicker.</li><li><strong class='bbc'>GLUT_DEPTH</strong> specifies we want a depth buffer. The depth buffer ensures that objects near the camera will always be on top of those further away. The output tends to be a bit messy otherwise. While this isn't necessary when we're only drawing a single triangle, it's good practice, so we'll include it anyway.</li></ul> The glutCreateWindow() function creates the window we're going to be drawing in. glutDisplayFunc() specifies the function we'll use to draw the display, which we'll have to write later. GLUT will call this function whenever the display needs updating.<br />
<br />
 [indent]<pre class='prettyprint'>int main(int argc, char **argv)<br />{<br />  glutInit(&argc,argv);                                   	//initializes the GLUT framework<br />  glutInitDisplayMode(GLUT_RGB &#124; GLUT_DOUBLE &#124; GLUT_DEPTH);   //sets up the display mode<br />  glutCreateWindow("My first GLUT program");                  //creates a window<br />  glutDisplayFunc(redraw);                                    //specifies our redraw function</pre>[/indent] Next we need to set up the projection matrix. The projection matrix is a 4x4 matrix which is used to translate points from their positions relative to the camera to their positions on the screen. We use it to specify how our scene will be projected. In order to change it we need to call glMatrixMode() with GL_PROJECTION. The gluPerspective() function creates a projection matrix with a perspective transform for us. All we need do is specify the view angle, aspect ratio and the positions of the near and far clipping planes.<br />
<br />
 [indent]<pre class='prettyprint'>  glMatrixMode(GL_PROJECTION);   //changes the current matrix to the projection matrix<br /><br />  //sets up the projection matrix for a perspective transform<br />  gluPerspective(45, 	//view angle<br />             	1.0,    //aspect ratio<br />             	10.0,   //near clip<br />             	200.0); //far clip</pre>[/indent] When we're done we switch the current matrix to the modelview matrix. The modelview matrix is a 4x4 matrix used to transform points from their actual positions (in world space) into their positions relative to the camera. It's the matrix we use to specify our camera position and the position of anything we draw. The glutMainLoop() function is the main loop of the GLUT framework and we need to call it next.<br />
<br />
 [indent]<pre class='prettyprint'>  glMatrixMode(GL_MODELVIEW);   //changes the current matrix to the modelview matrix<br /><br />  glutMainLoop();           	//the main loop of the GLUT framework<br /><br />  return 0;<br />}</pre>[/indent] Next we need to create our redraw() function which will draw our triangle. glClear() called with GL_COLOR_BUFFER_BIT and GL_DEPTH_BUFFER_BIT will clear the colour and depth buffers in our wind&#111;w. We need to do this before we start drawing on it.<br />
<br />
 [indent]<pre class='prettyprint'>static void redraw(void)                           	//all drawing code goes here<br />{<br />  glClear(GL_COLOR_BUFFER_BIT &#124; GL_DEPTH_BUFFER_BIT);  //clears the colour and depth buffers</pre>[/indent] Now we're almost ready to start drawing. First though we need to store our camera's position ((0,0,0) on the x, y and z axes - the center of our world) with glPushMatrix() and then move it 100 on the Z axis, effectively moving the camera backwards, enabling us to see what we're drawing. Because the modelview matrix specifies where we are drawing relative to the camera, to move the camera we need to translate the matrix by the reverse of the translation we want from the camera, so to move the camera (0,0,100) we translate the modelview matrix (0,0,-100). This has the same effect as moving our triangle (0,0,-100).<br />
<br />
 [indent]<pre class='prettyprint'>  glPushMatrix();     	//saves the current matrix on the top of the matrix stack<br />  glTranslatef(0,0,-100); //translates the current matrix 0 in x, 0 in y and -100 in z</pre>[/indent] Now we're going to draw the triangle. In order to do this, we need to call glBegin(GL_TRIANGLES), which tells OpenGL we're going to begin drawing triangles. OpenGL will then treat every group of three vertices as a triangle, and when glEnd() is called it will render the triangle(s) to our wind&#111;w.<br />
<br />
 Between the glBegin() and glEnd() we need to specify 3 vertices with glVertex3f. The three values specified in the each glVertex3f() call are the vertex's X, Y and Z coordinates in world space. We can also specify a colour for each of the vertices by using glColor3f() before each call to glVertex3f. The parameters we call glColor3f() with are the red, green and blue elements (from 0 to 1), which make up the colour. OpenGL will then blend the colours across the triangle.<br />
<br />
 [indent]<pre class='prettyprint'>  glBegin(GL_TRIANGLES);  //tells OpenGL that we're going to start drawing triangles<br />  glColor3f(1,0,0);   	//sets the current colour to red<br />  glVertex3f(-30,-30,0);  //specifies the first vertex of our triangle<br />  <br />  glColor3f(0,1,0);   	//sets the current colour to green<br />  glVertex3f(30,-30,0);   //specifies the second vertex of our triangle<br />  <br />  glColor3f(0,0,1);   	//sets the current colour to blue<br />  glVertex3f(-30,30,0);   //specifies the third vertex of our triangle<br />  glEnd();                //tells OpenGL that we've finished drawing</pre>[/indent] Next we retrieve our saved matrix from the top of the matrix stack with glPopMatrix(), setting the camera's position back to (0,0,0), ready for the next frame. Because we're using double buffering, all drawing has been done on the back buffer (the invisible buffer). Now the frame is completed we call glutSwapBuffers() to swap the front buffer (the visible buffer) and back buffer over, making what we have drawn visible.<br />
<br />
 [indent]<pre class='prettyprint'>  glPopMatrix();          //retrieves our saved matrix from the top of the matrix stack<br />  glutSwapBuffers();      //swaps the front and back buffers<br />}                     	//The end of our program!</pre>[/indent] That's it! The end of our program and this tutorial. Build the program and try it out.<br />
<br />
 Hopefully with the help of this tutorial you should now be able to build and initialize a GLUT program and draw triangles. If you want to give some feedback on this tutorial or have any questions, please <a href='mailto:ben@elf-stone.com' title='E-mail Link' class='bbc_email'>email me</a>.<br />
<br />
<p class='bbc_center'>This tutorial is Copyright © 2001 Ben Woodhouse<br />
 </p>]]></description>
		<pubDate>Tue, 29 Jan 2002 22:57:08 +0000</pubDate>
		<guid isPermaLink="false">1c6e02b62a98d8d9341a81521edd3426</guid>
	</item>
	<item>
		<title>A Singleton Texture Manager for OpenGL</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/a-singleton-texture-manager-for-opengl-r1439</link>
		<description><![CDATA[<span style='font-size: 18px;'><strong class='bbc'>Abstract</strong></span><br />
<br />
This article will discuss the need for, and creation of, a Singleton Texture Manager in OpenGL. By using a Singleton, we ensure that the Texture Manager class has only one instance, which we can use to handle all texture loading/deleting operations. If implemented properly, this tool could be a great benefit to game programmers, as it gives a viable and simple means for managing a large number of textures at once. For some beginning programmers, this may be their first glimpse of the Singleton pattern.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Introduction</strong></span><br />
<br />
The graphics of today's games have often defined the difference between success and failure. Developers are often questioning themselves how much, how fast, how detailed their graphics should be. Oftentimes, the textures of a game can determine how realistic the game looks and feels. Luckily, programmers have access to API's like DirectX and OpenGL that aid in optimizing texture rendering in complex scenes. The problem that we run into, however, is that we need a way to keep track of all of the textures in the game scenes. In a simple game with a wall, a floor, and a player skin, you shouldn't have many problems, but when changing levels, loading a WAD file, or applying skins to every new model that enters the scene, you need some way to keep track of the textures that are being used or you run into problems. In this article, we will discuss how we can combat these problems through a Singleton Texture Manager with the OpenGL API.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>OpenGL and Textures Overview</strong></span><br />
<br />
Every texture in OpenGL is referenced through a unique ID through the <strong class='bbc'>glBindTexture()</strong> function. Now, you can either specify this unique ID by yourself and have the responsibility of handling all new texture ID's, or you can let OpenGL find a currently unassigned ID with a call to the <strong class='bbc'>glGenTextures()</strong> function. With the latter approach, you only need to keep track of every ID the function returns.<br />
<br />
 Whichever method of texture ID generation you choose, you're still left with a seemingly random list of numbers coming and going as quickly as you can say 'jibs'. Even worse, when you're finished using a texture with a given map/object/effect, you need to find the texture's ID again and call the <strong class='bbc'>glDeleteTextures()</strong> function, which will recover the video memory that was allocated by the texture for re-use.<br />
<br />
 Although keeping track of a list of numbers may not seem like a real problem, if you have ever had code like this:<br />
<br />
 [indent]<pre class='prettyprint'>glDeleteTextures (1, &m_Player-&gt;GetProjectiles ().rocket &#91;nDeadRocket&#93;.GetTexture ().nID);</pre>[/indent] then you might change your mind about how to handle a list of numbers.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>A Statement</strong></span><br />
<br />
What we need is a class or object, which will sit in memory and manage every texture going in or out of our program. It will keep a list of all texture ID's, provide the functionality to delete textures, and also the functionality to give us a list of the number of textures loaded and their unique ID's. If the application sticks to a strict texture ID naming convention, such as:<br />
<br />
 Map/World Textures > 256<br />
Skin Textures < 256<br />
Effect Textures < 64<br />
<br />
 then we could easily look up and delete every texture of a specific type automatically.<br />
<br />
 This seems simple enough, but what if we load a texture in some remote function in the nether-regions of our code? We simply cannot create an instance of this class as a member variable for one of the main systems of our game and hope we put it in a place where it will have the most effectiveness. Even worse would be a series of texture managers keeping their own list of texture ID's.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>A Possible Solution</strong></span><br />
<br />
Enter the Singleton. A Singleton is an object that has at most one instance of itself in memory at any given time. Voodoo witchcraft?! Arcane magic's!? Not really. In code, a Singleton looks like this:<br />
<br />
 [indent]<pre class='prettyprint'>// In the header file<br />class CSingleton <br />{<br />  static class CSingleton *m_Singleton;<br />  static Csingleton *GetSingleton (void);<br />};<br /><br />// In the implementation file<br />CSingleton *CSingleton::m_Singleton = 0;<br /><br />CSingleton *CSingleton::GetSingleton (void) <br />{<br />  if (m_Singleton == 0)<br />	m_Singleton = new CSingleton;<br />  return m_Singleton;<br />}</pre>[/indent] By keeping a pointer itself as a static variable, the Singleton object isn't 're-created' with every instance of the class. So with the first call to GetSingleton, a Csingleton object pointer is allocated in memory, or the static variable m_Singleton. Does that make any sense? If not, don't worry, these links might help explain things a little better...<br />
<br />
 <a href='http://www.codeproject.com/tips/singleton.asp' class='bbc_url' title='External link' rel='nofollow external'>http://www.codeproje...s/singleton.asp</a><br />
<a href='http://www.inquiry.com/techtips/cpp_pro/10min/10min0200.asp' class='bbc_url' title='External link' rel='nofollow external'>http://www.inquiry.c...n/10min0200.asp</a><br />
<br />
 Well now that you are a complete expert on the concept of a Singleton, let's start working on our OpenGL texture manager, shall we?<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>The Code</strong></span><br />
<br />
 [indent]<pre class='prettyprint'>class CTextureManager {<br />public :<br />  CTextureManager (void);<br />  ~CTextureManager (void);<br />  static CTextureManager &GetSingleton (void);<br /><br />private :    // This is called automaticaly! Don't do it yourself!<br />  static void Initialize (void);<br />public :<br />  static void Destroy (void);<br /><br />public :    // Usage / Implumentation<br />  int LoadTexture (const char *szFilename, int nTextureID = -1);<br />  int LoadTextureFromMemory (UBYTE *pData, int nWidth, int nHeight, int nBPP, int nTextureID = -1);<br /><br />  void FreeTexture (int nID);<br />  void FreeAll (void);<br /><br />public :    // Debug / Utilitarian<br />  char *GetErrorMessage (void);<br />    <br />  int    GetNumTextures (void);<br />  int GetAvailableSpace (void);<br />  int GetTexID (int nIndex);<br /><br />private :<br />  static CTextureManager *m_Singleton;<br /><br />  UBYTE *LoadBitmapFile (const char *filename, int &nWidth, int &nHeight, int &nBPP);<br />  UBYTE *LoadTargaFile (const char *filename, int &nWidth, int &nHeight, int &nBPP);<br /><br />  int GetNewTextureID (int nPossibleTextureID);  // get a new one if one isn't provided<br />  bool CheckSize (int nDimension);<br /><br />private :<br />  char szErrorMessage &#91;80&#93;;  // they arn't bugs, their features!<br />  int nNumTextures;<br />  int nAvailable;        	// available space in the nTexID array<br />  int *nTexIDs;<br />};</pre>[/indent] Get the full class header and implementation in the attached resource file.<br />
<br />
 As you can see, the code itself is very self-explanatory. In fact, the only crucial functions are <strong class='bbc'>LoadTexture(), LoadTextureFromMemory(), FreeTexture()</strong>, and <strong class='bbc'>FreeAll()</strong>. The first two (as you would guess) load and register new textures into OpenGL, while the last two free textures from memory.<br />
<br />
 Within those four methods lies the code to handle the variables <strong class='bbc'>nNumTextures, nAvailable</strong> and <strong class='bbc'>nTexIDs</strong>. These variables respectively hold the number of loaded textures, amount of available slots in the texture ID list, and the lift itself.<br />
<br />
 The class itself has the functionality to load Targa (TGA) files and 24-bit color Bitmaps (BMP), however, it can be easily expanded to incorporate other file types via new methods for loading the graphics files internally or via the <strong class='bbc'>LoadTextureFromMemory()</strong> function. Either way, this Singleton class will all but "hold your hand" when dealing with textures in OpenGL.<br />
<br />
 The most crucial part of the code is that <em class='bbc'>all of the 'real' data is in the CTextureManager::m_Singleton object. In other words, if you want to access nNumTextures, you actually want m_Singleton->nNumTextures!</em> This is all because the class is still a Singleton, and to be such, all of the data must be stored in one place: the Singleton pointer.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>In Conclusion</strong></span><br />
<br />
The topics covered in this article may seem overwhelming at first, but keep in mind that having a Singleton texture manager is a good idea in the long run. As the number of graphics and textures used in your game begins to grow exponentially, a solid ID convention and an object to oversee texture operations will save MANY hours of bug tracking.<br />
<br />
 Questions? Comments? Flames?<br />
<a href='mailto:Christopher.Smith@Trinity.edu' title='E-mail Link' class='bbc_email'>Christopher.Smith@Trinity.edu</a><br />
<a href='http://www.cs.trinity.edu/%7Ecsmith8' class='bbc_url' title='External link' rel='nofollow external'>www.cs.trinity.edu/~csmith8</a><br />
Chris Smith]]></description>
		<pubDate>Wed, 18 Jul 2001 01:45:22 +0000</pubDate>
		<guid isPermaLink="false">981fda867ad3a7693c11ec00d2835b86</guid>
	</item>
	<item>
		<title>OpenGL Object Hierarchy</title>
		<link>http://www.gamedev.net/page/resources/_/technical/opengl/opengl-object-hierarchy-r1267</link>
		<description><![CDATA[<p class='bbc_center'><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3297-0-77543000-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3297" title="shot1.jpg - Size: 4.63K, Downloads: 62"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-90664500-1308256171_thumb.jpg" id='ipb-attach-img-3297-0-77543000-1330207271' style='width:170;height:200' class='attach' width="170" height="200" alt="Attached Image: shot1.jpg" /></a> </p><br />
This is a simple example of object hierarchy. We can think of object hierarchy as a mode of representing a complex object composed of more simple ones related to each other. In this tutorial we'll learn two new GL commands: <span style='font-family: Courier New'><span style='color: #000080'>glPushMatrix()</span></span> and <span style='font-family: Courier New'><span style='color: #000080'>glPopMatrix()</span></span> to accomplish our goal, which is modeling a simple robot.<br clear="all"><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>The robot structure</strong></span><br />
<br />
<table width="75%" border="1" cellpadding="0" cellspacing="0"><tbody><tr><td align="center"><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3298-0-77555800-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3298" title="struct_.gif - Size: 3.11K, Downloads: 70"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-10815500-1308256255_thumb.gif" id='ipb-attach-img-3298-0-77555800-1330207271' style='width:162;height:200' class='attach' width="162" height="200" alt="Attached Image: struct_.gif" /></a></td><td align="center"><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3299-0-77566600-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3299" title="struct0.jpg - Size: 7.15K, Downloads: 69"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-27206500-1308256278_thumb.jpg" id='ipb-attach-img-3299-0-77566600-1330207271' style='width:112;height:200' class='attach' width="112" height="200" alt="Attached Image: struct0.jpg" /></a></td><td align="center"><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3300-0-77577100-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3300" title="struct.jpg - Size: 6.23K, Downloads: 61"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-26609500-1308256296_thumb.jpg" id='ipb-attach-img-3300-0-77577100-1330207271' style='width:109;height:200' class='attach' width="109" height="200" alt="Attached Image: struct.jpg" /></a></td></tr><tr><td class="maintext-1" align="center">Fig. 1a - Object Hierarchy</td><td class="maintext-1" align="center">1b - GL model</td><td class="maintext-1" align="center">1c - GL light model</td></tr></tbody></table>Note the relationships between objects: Leg is pelvis child and pelvis is bust's child, forearm is arm's child and arm is shoulder's child, shoulder is bust's child too, and so on. So, if we move bust for example, legs and arms move too. This is an object hierarchy.<br />
<br />
 Every piece of the robot is modeled into a function and stored in a display list so we'll have:<br />
<br />
 [indent]<pre class='prettyprint'>void struct_part_name(void)<br />{<br />  glNewList(part_name,GL_COMPILE);<br />  .&#46;&#46;/* GL Commands to model */<br />  glEndList();<br />}</pre>[/indent] So, for example here is the code for left arm:<br />
<br />
 [indent]<pre class='prettyprint'>void struct_left_arm(void)<br />{<br />  glNewList(left_arm,GL_COMPILE); <br /><br />	// Shoulder<br />	glTranslatef(1.1,0.25,0.0);<br />	glScalef(0.5,0.5,0.5);<br />	glColor3ub(128,128,128);<br />	glutSolidSphere(0.5,20,20);<br />  <br />	// Arm<br />	glTranslatef(0.0,-1.10,0.0);<br />	glScalef(0.5,1.5,0.5);<br />	glColor3ub(255,255,255);<br />	glutSolidCube(1.0);<br /><br />  glEndList();<br />}</pre>[/indent] Note that in this example I'll use some GLUT commands to draw Spheres and Cubes so remember to link gl/glut.h in the headers section as indicated below<br />
<br />
 [indent]<pre class='prettyprint'>...<br />#include &lt;gl/glut.h&gt;<br />...</pre><br />
[/indent] The most important function is DrawRobot() that draws all the parts of the robot and which uses the OpenGL commands glPushMatrix() and glPopMatrix() to estabilish the relationships between objects.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Pseudocode</strong></span><br />
<br />
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre class='prettyprint'>void DrawRobot()<br />{<br />  glPushMatrix();   /* all objects are bust's son<br />                  	that is if we move bust all other parts move too */  <br />  	<br />	/*-------------------- DRAW HEAD AND BUST -----------------------*/ <br />	glPushMatrix();<br />   	/* Draw head */<br />  	/* Draw bust */ <br /><br />	glPopMatrix();</pre></td><td align="center"><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3301-0-77587500-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3301" title="head&bust.jpg - Size: 2.16K, Downloads: 56"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-49879800-1308256562_thumb.jpg" id='ipb-attach-img-3301-0-77587500-1330207271' style='width:101;height:112' class='attach' width="101" height="112" alt="Attached Image: head&bust.jpg" /></a></td></tr><tr><td><pre class='prettyprint'> 	/*---------------- DRAW RIGHT ARM AND FOREARM --------------*/ <br />	glPushMatrix();<br />  	glPushMatrix();<br />     	/* Draw Right arm */ <br /><br />  	glPopMatrix();<br /><br />  	glPushMatrix();   /* forearm is arm's child */<br />    	/* Draw Forearm */ <br />  	glPopMatrix();<br />	glPopMatrix();</pre></td><td align="center"><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3302-0-77598000-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3302" title="arm&forearm.jpg - Size: 1.44K, Downloads: 50"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-49638800-1308256607_thumb.jpg" id='ipb-attach-img-3302-0-77598000-1330207271' style='width:23;height:178' class='attach' width="23" height="178" alt="Attached Image: arm&forearm.jpg" /></a></td></tr><tr><td><pre class='prettyprint'> 	/*-------------- DRAW LEFT ARM AND FOREARM -----------------*/ <br /><br />	glPushMatrix();<br />  	glPushMatrix();<br />     	/* Draw Left arm */ <br />  	glPopMatrix();<br /><br />  	glPushMatrix();   /* forearm is arm's child */<br />    	/* Draw Forearm */ <br />  	glPopMatrix();<br />	glPopMatrix();</pre></td><td align="center"><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3303-0-77610700-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3303" title="arm&forearml.jpg - Size: 1.38K, Downloads: 43"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-88861900-1308256648_thumb.jpg" id='ipb-attach-img-3303-0-77610700-1330207271' style='width:22;height:181' class='attach' width="22" height="181" alt="Attached Image: arm&forearml.jpg" /></a></td></tr><tr><td><pre class='prettyprint'> 	/*------------------ DRAW PELVIS AND LEGS ----------------*/ <br />	glPushMatrix();   /* another glPushMatrix because<br />                    	if we move pelvis the legs move too...<br />                    	(legs are pelvis' son) */ <br />  	glPushMatrix();<br />     	/* Draw pelvis */ <br />  	glPopMatrix();<br />    	<br />  	glPushMatrix();<br />    	glPushMatrix();<br />       	/* Draw Right thigh */ <br />    	glPopMatrix();<br />  	<br />    	glPushMatrix();   /* leg is thigh's child */<br />      	/* Draw Leg */ <br /><br />    	glPopMatrix();<br />  	glPopMatrix();<br />	<br />  	glPushMatrix();<br />    	glPushMatrix();<br />       	/* Draw Left thigh */ <br />    	glPopMatrix();<br />  	<br />    	glPushMatrix();   /* leg is thigh's child */<br />      	/* Draw Leg */ <br />    	glPopMatrix();<br />  	glPopMatrix();<br /><br />	glPopMatrix();<br /><br />  glPopMatrix();<br />}</pre></td><td align="center"><a class='resized_img' rel='lightbox[02c4e645a9dd49a4a309040a5675081f]' id='ipb-attach-url-3304-0-77621500-1330207271' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3304" title="pelvis&legs.jpg - Size: 3.06K, Downloads: 41"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-09258600-1308256691_thumb.jpg" id='ipb-attach-img-3304-0-77621500-1330207271' style='width:85;height:177' class='attach' width="85" height="177" alt="Attached Image: pelvis&legs.jpg" /></a></td></tr></tbody></table><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>The Code</strong></span><br />
<br />
 [indent]<pre class='prettyprint'>void DrawRobot(void)<br />{<br />  /*-------------BUST AND HEAD--------------*/<br />  glPushMatrix();<br />	glRotatef(bust_angle_y,0,1,0);<br />	glRotatef(bust_angle_x,1,0,0);<br />	glPushMatrix();<br />  	glCallList(bust);<br />  	glCallList(head);<br />	glPopMatrix();<br /><br />	/*--------RIGHT ARM AND FOREARM---------*/<br />	glPushMatrix();<br />  	glTranslatef(0,0.25,0);<br />  	glRotatef(right_arm_angle,1,0,0);<br />  	glTranslatef(0,-0.25,0);<br />  	glPushMatrix();<br />    	glCallList(right_arm);<br />  	glPopMatrix();<br /> 	 <br />  	glPushMatrix();<br />    	glTranslatef(1.25,-0.7,0);<br />    	glRotatef(right_forearm_angle,1,0,0);<br />    	glTranslatef(-1.25,0.7,0);<br />    	glCallList(right_forearm);<br />  	glPopMatrix();<br />	glPopMatrix();<br />    <br />	/*---------LEFT ARM AND FOREARM---------*/<br />	glPushMatrix();<br />  	glTranslatef(0,0.25,0);<br />  	glRotatef(left_arm_angle,1,0,0);<br />  	glTranslatef(0,-0.25,0);<br />  	glPushMatrix();<br />    	glCallList(left_arm);<br />  	glPopMatrix();<br /><br />  	glPushMatrix();<br />    	glTranslatef(1.25,-0.7,0);<br />    	glRotatef(left_forearm_angle,1,0,0);<br />    	glTranslatef(-1.25,0.7,0);<br />    	glCallList(left_forearm);<br />  	glPopMatrix();<br />	glPopMatrix();</pre>[/indent] and so on...<br />
<br />
 In the main function I added some keys to control the robot. They are:<br />
<br />
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td>'<b>1</b>' & '<b>Q</b>'<br>'<b>2</b>' & '<b>W</b>'<br>'<b>3</b>' & '<b>E</b>'<br>'<b>4</b>' & '<b>R</b>'<br>'<b>5</b>' & '<b>T</b>'<br>'<b>6</b>' & '<b>Y</b>'<br>'<b>7</b>' & '<b>U</b>'<br>'<b>8</b>' & '<b>I</b>'<br><b>KEY ARROWS</b><br><b>PGUP</b> & <b>PGDOWN</b>&nbsp;&nbsp;&nbsp;&nbsp;<br>'<b>V</b>' '<b>B</b>' '<b>N</b>' '<b>M</b>'</td><td>right arm control<br>right forearm control<br>left arm control<br>left forearm control<br>left thigh control<br>left leg control<br>right thigh control<br>right thigh control<br>rotate model<br>light control<br>camera control<br></td></tr></tbody></table>And finally the bin & source are attached to this article.<br />
<br />
 Happy coding...<br />
<br />
 Arturo "IRIX" Montieri : <a href='mailto:montieri@hotmail.com' title='E-mail Link' class='bbc_email'>montieri@hotmail.com</a>]]></description>
		<pubDate>Thu, 28 Dec 2000 09:51:10 +0000</pubDate>
		<guid isPermaLink="false">151d21647527d1079781ba6ae6571ffd</guid>
	</item>
</channel>
</rss>
