Jason McKesson avatar Jason McKesson committed cca6d35

Issue #55: Doc updating to match current source code.

Comments (0)

Files changed (16)

Documents/Basics/Tutorial 01.xml

                 into something called <varname>gl_Position</varname>. This is a variable that is
                     <emphasis>not</emphasis> defined in the shader; that is because it is a standard
                 variable defined in every vertex shader. If you see an identifier in a GLSL shader
-                that starts with <quote>gl_</quote>, then it must be a built-in identifier.</para>
+                that starts with <quote>gl_</quote>, then it must be a built-in identifier. You
+                cannot make an identifier that begins with <quote>gl_</quote>; you can only use ones
+                that already exist.</para>
             <para><varname>gl_Position</varname> is defined as:</para>
             <programlisting language="glsl">out vec4 gl_Position;</programlisting>
             <para>Recall that the minimum a vertex shader must do is generate a clip-space position
     shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, strFragmentShader));
     
     theProgram = CreateProgram(shaderList);
+
+    std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
 }</programlisting>
         </example>
         <para>The first statement simply creates a list of the shader objects we intend to link
             together. The next two statements compile our two shader strings. The
-                <function>CreateShader</function> function is a utility function defined by the
-            tutorial that compiles a shader.</para>
+                <function>CreateShader</function> function is a function defined by the tutorial
+            that compiles a shader.</para>
         <para>Compiling a shader into a shader object is a lot like compiling source code. Most
             important of all, it involves error checking. This is the implementation of
                 <function>CreateShader</function>:</para>
                 may call <function>glGetAttribLocation</function> with the program object and a
                 string containing the attribute's name.</para>
         </note>
+        <para>After linking the program, the shader objects in the <type>vector</type> of shaders are
+            deleted using the C++ algorithm <function>std::for_each.</function> This line loops over
+            each of the shaders in the list and calls <function>glDeleteShader</function> on
+            them.</para>
         <formalpara>
             <title>Using Programs</title>
             <para>To tell OpenGL that rendering commands should use a particular program object, the
         <title>Cleanup</title>
         <para>The tutorial allocates a lot of OpenGL resources. It allocates a buffer object, which
             represents memory on the GPU. It creates two shader objects and a program object, all of
-            which stored in memory owned by OpenGL. But it never explicitly deletes any of
-            this.</para>
+            which stored in memory owned by OpenGL. But it only deletes the shader objects; nothing
+            else.</para>
         <para>Part of this is due to the nature of FreeGLUT, which does not provide hooks for a
             cleanup function. But part of it is also due to the nature of OpenGL itself. In a simple
             example such as this, there is no need to delete anything. OpenGL will clean up its own
                     </glossdef>
                 </glossentry>
                 <glossentry>
-                    <glossterm>glCreateShader, glShaderSource, glCompileShader</glossterm>
+                    <glossterm>glCreateShader, glShaderSource, glCompileShader,
+                        glDeleteShader</glossterm>
                     <glossdef>
                         <para>These functions create a working shader object.
                                 <function>glCreateShader</function> simply creates an empty shader
                             sets strings into that object; multiple calls to this function simply
                             overwrite the previously set strings.
                                 <function>glCompileShader</function> causes the shader object to be
-                            compiled with the previously set strings.</para>
+                            compiled with the previously set strings.
+                                <function>glDeleteShader</function> causes the shader object to be
+                            deleted.</para>
                     </glossdef>
                 </glossentry>
                 <glossentry>

Documents/Building the Tutorials.xml

     <section>
         <title>Unofficial OpenGL SDK</title>
         <para>The <link xlink:href="http://glsdk.sourceforge.net/docs/html/index.html">Unofficial
-                OpenGL SDK</link> is a library aggregation, consisting of a number of tools for
+                OpenGL SDK</link> is an aggregation of libraries, unifying a number of tools for
             developing OpenGL applications, all bound together with a unified build system. A
             modified SDK distribution is bundled with these tutorials; this distro does not contain
             the documentation or GLFW that comes with the regular SDK.</para>
             makefile. To build for debug, use <userinput>make config=debug</userinput>; similarly,
             to build for release, use <userinput>make config=release</userinput>.</para>
         <para>Using the generated build files, compile for both debug and release. You should build
-            the entire solution; the tutorials use all of the libraries in the SDK.</para>
+            the entire solution; the tutorials use all of the libraries provided.</para>
         <para>Note that there is no execution of <userinput>make install</userinput> or similar
             constructs. The SDK is designed to be used where it is; it does not install itself to
             any system directories on your machine. Incidentally, neither do these tutorials.</para>
         <para><link xlink:href="http://sourceforge.net/projects/tinyxml/">TinyXML</link> is an XML
             parser. The framework uses an XML file format for loading complex 3D mesh data. This
             library simply makes the loading and parsing of this format easier.</para>
-        <para>Like the SDK, it uses Premake to generate its build files. So perform the steps as
-            above to build it.</para>
+        <para>Like the SDK, it uses Premake to generate its build files. So go to the
+                <filename>tinyxml</filename> directory and perform the steps as above to build
+            it.</para>
     </section>
     <section>
         <title>Tutorial Building</title>

Documents/Getting Started.xml

     <para>Now that you understand at least the beginnings of graphics programming, it would be
         useful to discuss how to get started using OpenGL in your own projects. This discussion will
         assume that you know how to set up a build project in your build system of choice.</para>
-    <para>There are two ways to go about it: you can use the framework provided in the download, or
-        you can use whatever tools you wish. I don't advocate using the tutorial framework for any
-        serious application; it was intended to be used for only these tutorials, so it may not
-        serve your needs outside of this particular purpose.</para>
-    <section>
-        <?dbhtml filename="Started Tutorial Framework.html" ?>
-        <title>Tutorial Framework</title>
-        <para>If you intend to use the tutorial framework, the process is relatively simple, though
-            it is somewhat restricted.</para>
-        <para>The framework is intended to only be used in the directory it was downloaded into. So
-            if you want to use it in a project, you will need to make a new directory under the base
-            tutorial directory. Let us call this directory <filename>Project</filename>.</para>
-        <para>In the <filename>Framework</filename> directory, there is the file
-                <filename>empty.cpp</filename>. This file contains all of the functions that the
-            framework expects you to define. Copy this file to your <filename>Project</filename>
-            directory and rename it however you want. For the purpose of this example, let us call
-            it <filename>project.cpp</filename>.</para>
-        <para>In order to build this file, you will need to use Premake; therefore, you will need to
-            use a Premake build script. You will need to create a <filename>premake4.lua</filename>
-            file in the <filename>Project</filename> directory. This is a text file that contains
-            the following:</para>
-        <example>
-            <title>Solution Premake Build Script</title>
-            <programlisting>dofile("../framework/framework.lua")
-
-SetupSolution("Project")
-dofile("tutorials.lua");</programlisting>
-        </example>
-        <para>You can replace the <quote><literal>Project</literal></quote> with whatever name you
-            wish. This will be the name of the solution file (for those build tools that have
-                <quote>solution</quote> files).</para>
-        <para>Next you must make a <filename>tutorials.lua</filename> file, in the
-                <filename>Project</filename> directory. It should contain the following:</para>
-        <example>
-            <title>Tutorial Premake Build Script</title>
-            <programlisting>SetupProject("Project", "project.cpp")</programlisting>
-        </example>
-        <para>You can again replace the <quote><literal>Project</literal></quote> with whatever name
-            you wish. This is the name of the executable, as well as the name of the project build
-            file (again, for build tools that have <quote>project</quote> files). Lua allows for
-            arbitrary numbers of arguments. Following the project name can be any number of files
-            that will be included with the project. Premake even allows wildcards, so
-                    <quote><filename>*.cpp</filename></quote> would include every C++ source file in
-            this directory. You can include non-buildable files like shaders as well, but you have
-            to specify the directory for that.</para>
-        <section>
-            <title>Using the Framework Library</title>
-            <para>At this point, you should be able to build and run the project. The framework
-                includes a number of extra facilities, like shader loading, mesh loading, and so
-                forth.</para>
-            <para>All of the framework library headers should be included <emphasis>after</emphasis>
-                including the GLLoad header.</para>
-            <para>Shaders and mesh files are assumed to come from a subdirectory of the current
-                directory called <filename>data</filename>. When you call
-                    <function>Framework::LoadShader</function>, it will look in the
-                    <filename>data</filename> directory for the file. If it is not there, then it
-                will look in the <filename>data</filename> directory just off the root of the
-                tutorial distribution; this is used for common shaders that are used across multiple
-                tutorials.</para>
-            <para>Here is a quick runthrough of the available tools in the framework library.</para>
-            <formalpara>
-                <title>framework.h</title>
-                <para>Contains functions to load shader files. It also has functions for converting
-                    degrees to radians.</para>
-            </formalpara>
-            <formalpara>
-                <title>Mesh.h</title>
-                <para>Contains the <classname>Framework::Mesh</classname> class. This class loads
-                    meshes in an XML format, and it can be used to render them. The XML format can
-                    define named variations of the mesh, which represent different sets of vertex
-                    attributes. The particular named set can be rendered with the
-                        <function>Mesh::Render</function> function. Note that it will only load
-                    meshes from the <filename>Project/data</filename> directory.</para>
-            </formalpara>
-            <formalpara>
-                <title>MousePole.h</title>
-                <para>Contains the <classname>Framework::MousePole</classname> class. This is used
-                    to allow mouse-based movements to control the camera. This control allows
-                    rotating the view around a point in the world: the look-at point. The
-                    constructor takes a <classname>Framework::RadiusDef</classname> object, which
-                    defines the limits for how the distance from the look-at can change, as well as
-                    the initial distance. They must be given the input from FreeGLUT's mouse and
-                    keyboard callbacks; the tutorials show how to set this up.</para>
-            </formalpara>
-            <formalpara>
-                <title>ObjectPole.h</title>
-                <para>Contains the <classname>Framework::ObjectPole</classname> class. This is used
-                    to allow mouse-based movements to control an object. This control allows
-                    rotating the object in space. Again, many tutorials show how to set this
-                    up.</para>
-            </formalpara>
-            <formalpara>
-                <title>Timer.h</title>
-                <para>Contains the <classname>Framework::Timer</classname> class. The timer is used
-                    to keep accurate time. The <function>Timer::Update</function> function must be
-                    used to advance the time since the last time it was used. You should only do
-                    this once per frame. There are three kinds of timers: looping timers, single
-                    timers, and infinite timers. Looping and single timers have a set duration, and
-                    they return the time as a value on the range [0, 1] from
-                        <function>Timer::GetAlpha()</function>, depending on how far towards the
-                    duration they are. The duration starts the first time the update function is
-                    called. Infinite timers should use <function>Timer::GetDuration()</function>,
-                    which returns the time in seconds since the first update call.</para>
-            </formalpara>
-            <formalpara>
-                <title>MatrixStack.h</title>
-                <para>Contains the <classname>Framework::MatrixStack</classname> class. The use of
-                    this class is well documented in Tutorial 7.</para>
-            </formalpara>
-            <para>All of the other parts of the framework library are probably too advanced,
-                special-case, or cumbersome to use.</para>
-        </section>
-    </section>
+    <para>The easiest way is to just use the <link
+            xlink:href="http://glsdk.sourceforge.net/docs/html/index.html">Unofficial OpenGL
+            SDK</link>. It is a well-documented collection of tools for writing simple OpenGL
+        applications. It has functions for compiling shaders, the mouse-based controls we have used,
+        image loading tools, and various other utilities that are vital to making OpenGL
+        applications. Details for how to use it are found on the SDK's website.</para>
     <section>
         <?dbhtml filename="Started Necessary Tools.html" ?>
-        <title>Necessary Tools</title>
-        <para>In order to use OpenGL without the framework, you will need to do two things. You must
-            create a window and attach an OpenGL context to it, and you must load the OpenGL
-            functions for that context. There are a number of other tools you may want (vector math,
-            model loading, image loading, etc), but these tools are ones you need if you aren't
-            going to do them manually.</para>
+        <title>Manual Usage</title>
+        <para>If you choose not to use the SDK, then you will have to build a set of useful tools
+            yourself.</para>
+        <para>In order to use OpenGL, you will need to do two things. You must create a window and
+            attach an OpenGL context to it, and you must load the OpenGL functions for that context.
+            There are a number of other tools you may want (vector math, model loading, image
+            loading, etc), but these tools are ones you need if you aren't going to do them
+            manually.</para>
         <section>
             <title>Window and OpenGL Creation</title>
             <para>Windows, displayable surfaces in GUI operating environments, are very
                 attached to these windows using the WGL API.</para>
             <para>Because window creation and OpenGL attachment are platform-specific, there are a
                 number of cross-platform tools that make it possible to write platform-neutral
-                OpenGL code. FreeGLUT is the tool that these tutorials use, and it is included in
-                the source distribution. There are a number of other tools available. We will
-                discuss many of the options here.</para>
+                OpenGL code. FreeGLUT is the tool that these tutorials use, and it is included as
+                part of the SDK in the source distribution. There are a number of other tools
+                available. We will discuss many of the options here.</para>
             <formalpara>
                 <title>FreeGLUT</title>
                 <para>FreeGLUT is based on the original GLUT, the OpenGL Utility Toolkit. You should
                 MacOSX), possibly also supporting BSD or various other shades of UNIX. Unlike
                 DirectX, the multimedia libraries did not create their own 3D rendering system; they
                 instead simply provide a way to use OpenGL.</para>
-            <para>The two biggest multimedia libraries are SDL (Simple Directmedia Layer) and SFML
-                (Simple and Fast Multimedia Library). SDL is the older, but it is still receiving
-                updates. It is a C library, so if you are allergic to C-isms, you may wish to avoid
-                it. Work is being done on SDL 1.3, which will apparently have support for mobile
-                platforms. SDL uses the zLib license.</para>
+            <para>The two biggest multimedia libraries are <link xlink:href="http://www.libsdl.org/"
+                    >SDL (Simple Directmedia Layer)</link> and <link
+                    xlink:href="http://www.sfml-dev.org/">SFML (Simple and Fast Multimedia
+                    Library)</link>. SDL is the older, but it is still receiving updates. It is a C
+                library, so if you are allergic to C-isms, you may wish to avoid it. Work is being
+                done on SDL 1.3, which will apparently have support for mobile platforms. SDL uses
+                the zLib license.</para>
             <para>SFML is a newer library, which has a C++ API. While SDL is one big library (and
                 requires dependencies like DirectX on Windows), SFML is more of a choose-your-own
                 package. The base package contains just input and the ability to create a window,
                 integrate SFML windows with other GUI toolkits (see below); this makes it easier to
                 build non-gaming applications that use actual GUI tools. SFML uses the zLib
                 license.</para>
-            <para>Allegro is a game-centric multimedia library. Version 5 has native support for
-                OpenGL in its graphics subsystem. It uses a C interface. It also has a number of
-                advanced 2D rendering functions. Allegro uses the <quote>giftware license,</quote>
-                which is rather like the MIT license.</para>
+            <para><link xlink:href="http://alleg.sourceforge.net/">Allegro</link> is a game-centric
+                multimedia library. Version 5 has native support for OpenGL in its graphics
+                subsystem. It uses a C interface. It also has a number of advanced 2D rendering
+                functions. Allegro uses the <quote>giftware license,</quote> which is rather like
+                the MIT license.</para>
             <formalpara>
                 <title>GUI Toolkits</title>
                 <para>There are a number of cross-platform GUI libraries that deal with detailed
                 context creation tools is that there will be some series of commands to supply
                 parameters to the underlying system for context creation. And then a function is
                 called to use those parameters to create the context. It is only
-                    <emphasis>after</emphasis> this process is complete that one should call
-                whatever initialization function the OpenGL function loading system uses. Your
-                tools' documentation should explain this.</para>
+                    <emphasis>after</emphasis> this process has successfully completed that one
+                should call whatever initialization function the OpenGL function loading system
+                uses. Your tools' documentation should explain this.</para>
             <para>After doing both of these, you should be able to make OpenGL calls. The specifics
                 on how to swap framebuffers (which is not part of the OpenGL API) is again left up
                 to the window management tool.</para>

Documents/Illumination/Tutorial 09.xml

                 <para>The object can be spun by right-clicking while holding <keycap>Alt</keycap>.
                     As with the other object movements, the spin is relative to the current
                     direction of the camera.</para>
-                <para>The code for these are contained in the framework objects
-                        <type>MousePole</type> and <type>ObjectPole</type>. The source code in them
-                    is, outside of how FreeGLUT handles mouse input, nothing that has not been seen
-                    previously.</para>
+                <para>The code for these are contained in the Unofficial SDK's GL Util library.
+                    Specifically, the objects <type>glutil::ViewPole</type> and
+                        <type>glutil::ObjectPole</type>. The source code in them is, outside of how
+                    FreeGLUT handles mouse input, nothing that has not been seen previously.</para>
             </sidebar>
             <para>Pressing the <keycap>Spacebar</keycap> will switch between a cylinder that has a
                 varying diffuse color and one that is pure white. This demonstrates the effect of
                 stack will have the camera matrix at the very bottom.</para>
             <example>
                 <title>Display Camera Code</title>
-                <programlisting language="cpp">const glm::vec3 &amp;camPos = ResolveCamPosition();
-
-Framework::MatrixStack modelMatrix;
-modelMatrix.SetMatrix(g_mousePole.CalcMatrix());
+                <programlisting language="cpp">glutil::MatrixStack modelMatrix;
+modelMatrix.SetMatrix(g_viewPole.CalcMatrix());
 
 glm::vec4 lightDirCameraSpace = modelMatrix.Top() * g_lightDirection;
 
             <para>To render the ground plane, we run this code:</para>
             <example>
                 <title>Ground Plane Lighting</title>
-                <programlisting language="cpp">Framework::MatrixStackPusher push(modelMatrix);
+                <programlisting language="cpp">glutil::PushStack push(modelMatrix);
 
 glUseProgram(g_WhiteDiffuseColor.theProgram);
 glUniformMatrix4fv(g_WhiteDiffuseColor.modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
             <para>To render the cylinder, we run this code:</para>
             <example>
                 <title>Cylinder Lighting</title>
-                <programlisting language="cpp">Framework::MatrixStackPusher push(modelMatrix);
+                <programlisting language="cpp">glutil::PushStack push(modelMatrix);
 
-modelMatrix.ApplyMatrix(g_objectPole.CalcMatrix());
+modelMatrix.ApplyMatrix(g_objtPole.CalcMatrix());
 
 if(g_bDrawColoredCyl)
 {
             the inverse transpose. The rendering code for the cylinder is as follows:</para>
         <example>
             <title>Lighting with Proper Normal Transform</title>
-            <programlisting language="cpp">Framework::MatrixStackPusher push(modelMatrix);
+            <programlisting language="cpp">glutil::PushStack push(modelMatrix);
 
-modelMatrix.ApplyMatrix(g_objectPole.CalcMatrix());
+modelMatrix.ApplyMatrix(g_objtPole.CalcMatrix());
 
 if(g_bScaleCyl)
 {

Documents/Illumination/Tutorial 10.xml

             of the rendering function.</para>
         <example>
             <title>Per-Vertex Point Light Rendering</title>
-            <programlisting language="cpp">Framework::MatrixStack modelMatrix;
-modelMatrix.SetMatrix(g_mousePole.CalcMatrix());
+            <programlisting language="cpp">glutil::MatrixStack modelMatrix;
+modelMatrix.SetMatrix(g_viewPole.CalcMatrix());
 
 const glm::vec4 &amp;worldLightPos = CalcLightPosition();
 
 glm::vec4 lightPosCameraSpace = modelMatrix.Top() * worldLightPos;
 
-glUseProgram(g_WhiteAmbDiffuseColor.theProgram);
-glUniform3fv(g_WhiteAmbDiffuseColor.lightPosUnif, 1, glm::value_ptr(lightPosCameraSpace));
-glUseProgram(g_VertexAmbDiffuseColor.theProgram);
-glUniform3fv(g_VertexAmbDiffuseColor.lightPosUnif, 1, glm::value_ptr(lightPosCameraSpace));</programlisting>
+glUseProgram(g_WhiteDiffuseColor.theProgram);
+glUniform3fv(g_WhiteDiffuseColor.lightPosUnif, 1, glm::value_ptr(lightPosCameraSpace));
+glUseProgram(g_VertexDiffuseColor.theProgram);
+glUniform3fv(g_VertexDiffuseColor.lightPosUnif, 1, glm::value_ptr(lightPosCameraSpace));</programlisting>
         </example>
         <para>The light is computed initially in world space, then transformed into camera space.
             The camera-space light position is given to both of the shaders. Rendering proceeds
             lighting instead of camera space. The start of the rendering looks as follows:</para>
         <example>
             <title>Initial Per-Fragment Rendering</title>
-            <programlisting language="cpp">Framework::MatrixStack modelMatrix;
-modelMatrix.SetMatrix(g_mousePole.CalcMatrix());
+            <programlisting language="cpp">glutil::MatrixStack modelMatrix;
+modelMatrix.SetMatrix(g_viewPole.CalcMatrix());
 
 const glm::vec4 &amp;worldLightPos = CalcLightPosition();
 
         <para>The ground plane is rendered with this code:</para>
         <example>
             <title>Ground Plane Per-Fragment Rendering</title>
-            <programlisting language="cpp">glUseProgram(pWhiteProgram->theProgram);
+            <programlisting language="cpp">glutil::PushStack push(modelMatrix);
+
+glUseProgram(pWhiteProgram->theProgram);
 glUniformMatrix4fv(pWhiteProgram->modelToCameraMatrixUnif, 1, GL_FALSE,
-    glm::value_ptr(modelMatrix.Top()));
+glm::value_ptr(modelMatrix.Top()));
 
 glm::mat4 invTransform = glm::inverse(modelMatrix.Top());
 glm::vec4 lightPosModelSpace = invTransform * lightPosCameraSpace;

Documents/Illumination/Tutorial 11.xml

         <example>
             <title>Blinn-Phong Lighting Shader</title>
             <programlisting language="glsl">vec3 lightDir = vec3(0.0);
-    float atten = CalcAttenuation(cameraSpacePosition, lightDir);
-    vec4 attenIntensity = atten * lightIntensity;
-    
-    vec3 surfaceNormal = normalize(vertexNormal);
-    float cosAngIncidence = dot(surfaceNormal, lightDir);
-    cosAngIncidence = clamp(cosAngIncidence, 0, 1);
-    
-    vec3 viewDirection = normalize(-cameraSpacePosition);
-    
-    vec3 halfAngle = normalize(lightDir + viewDirection);
-    float blinnTerm = dot(surfaceNormal, halfAngle);
-    blinnTerm = clamp(blinnTerm, 0, 1);
-    blinnTerm = cosAngIncidence != 0.0 ? blinnTerm : 0.0;
-    blinnTerm = pow(blinnTerm, shininessFactor);
-    
-    outputColor = (diffuseColor * attenIntensity * cosAngIncidence) +
-        (specularColor * attenIntensity * blinnTerm) +
-        (diffuseColor * ambientIntensity);</programlisting>
+float atten = CalcAttenuation(cameraSpacePosition, lightDir);
+vec4 attenIntensity = atten * lightIntensity;
+	
+vec3 surfaceNormal = normalize(vertexNormal);
+float cosAngIncidence = dot(surfaceNormal, lightDir);
+cosAngIncidence = clamp(cosAngIncidence, 0, 1);
+	
+vec3 viewDirection = normalize(-cameraSpacePosition);
+	
+vec3 halfAngle = normalize(lightDir + viewDirection);
+float blinnTerm = dot(surfaceNormal, halfAngle);
+blinnTerm = clamp(blinnTerm, 0, 1);
+blinnTerm = cosAngIncidence != 0.0 ? blinnTerm : 0.0;
+blinnTerm = pow(blinnTerm, shininessFactor);
+
+outputColor = (diffuseColor * attenIntensity * cosAngIncidence) +
+    (specularColor * attenIntensity * blinnTerm) +
+    (diffuseColor * ambientIntensity);</programlisting>
         </example>
         <para>The half-angle vector is computed by normalizing the sum of the light direction and
             view direction vectors. As before, we take the dot product between that and the surface

Documents/Illumination/Tutorial 13.xml

                 not work; we must have a dummy attribute enabled and a dummy buffer object to pull
                 data from. We do this in the initialization function of this tutorial.</para>
             <note>
-                <para>The OpenGL 3.3 core specification says that it should be possible to render
-                    with no enabled attributes. Sadly, certain implementations of OpenGL
-                    (*cough*AMD*cough*) incorrectly forbid it.</para>
+                <para>The OpenGL 3.3 core specification is quite clear that it should be possible to
+                    render with no enabled attributes. Sadly, certain implementations of OpenGL
+                    (*cough*AMD*cough*) incorrectly forbid it, so our tutorial has to work around
+                    them.</para>
             </note>
         </section>
         <section>
                     executing. This is not necessarily the case.</para>
                 <para>Due to the way that shaders tend to work, multiple executions of the same
                     shader are often operating at the same time. All of them are running in
-                    lock-step with one another; they all execute instructions at the same time. If
-                    one of them does a discard, it still has to keep doing what it was doing,
-                    because the other three may not have discarded, since the discard was based on
-                    data that may be different between each shader. This is also why branches in
-                    shaders will often execute both sides rather than actually branching; it keeps
-                    the shader logic simpler.</para>
+                    lock-step with one another; they all execute instructions at the same time, just
+                    on different datasets. If one of them does a discard, it still has to keep doing
+                    what it was doing, because the other three may not have discarded, since the
+                    discard was based on data that may be different between each shader. This is
+                    also why branches in shaders will often execute both sides rather than actually
+                    branching; it keeps the shader logic simpler.</para>
                 <para>However, that does not mean <literal>discard</literal> is without use for
                     stopping unwanted processing. If all of the shaders that are running together
                     hit a <literal>discard</literal>, then they can all be aborted with no problems.
-                    And hardware often does this where possible.</para>
+                    And hardware often does this where possible. So if there is a great deal of
+                    spatial coherency with discard, this is useful.</para>
             </sidebar>
             <para>The computation of the normal is based on simple trigonometry. The normal of a
                 sphere does not change based on the sphere's radius. Therefore, we can compute the

Documents/Positioning/Tutorial 03.xml

                 <function>glUniform2f</function> to set the uniform's value. The buffer object's
             data is never changed; the shader simply does the hard work. Which is why those shader
             stages exist in the first place.</para>
+        <sidebar>
+            <title>Standard OpenGL Nomenclature</title>
+            <para>The function <function>glUniform2f</function> uses a special bit of OpenGL
+                nomenclature. Specifically, the <quote>2f</quote> part.</para>
+            <para>Uniforms can have different types. And because OpenGL is defined in terms of C
+                rather than C++, there is no concept of function overloading. So functions that do
+                the same thing which take different types must have different names. OpenGL has
+                standardized its naming convention for these.</para>
+            <para>Functions like <function>glUniform</function> have a suffix. The first part of the
+                suffix is the number of values it takes. In the above case,
+                    <function>glUniform2f</function> takes 2 values, in addition to the regular
+                parameters. The basic <function>glUniform</function> parameters are just the uniform
+                location, so <function>glUniform2f</function> takes a uniform location and two
+                values.</para>
+            <para>The type of values it takes is defined by the second part. The possible type names
+                and their associated types are:</para>
+            <informaltable frame="all">
+                <tgroup cols="4">
+                    <colspec colname="c1" colnum="1" colwidth="1.0*"/>
+                    <colspec colname="c2" colnum="2" colwidth="1.0*"/>
+                    <colspec colname="c3" colnum="3" colwidth="1.0*"/>
+                    <colspec colname="c4" colnum="4" colwidth="1.0*"/>
+                    <thead>
+                        <row>
+                            <entry/>
+                            <entry/>
+                            <entry/>
+                            <entry/>
+                        </row>
+                    </thead>
+                    <tbody>
+                        <row>
+                            <entry>
+                                <para>b</para>
+                            </entry>
+                            <entry>
+                                <para>signed byte</para>
+                            </entry>
+                            <entry>
+                                <para>ub</para>
+                            </entry>
+                            <entry>
+                                <para>unsigned byte</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para>s</para>
+                            </entry>
+                            <entry>
+                                <para>signed short</para>
+                            </entry>
+                            <entry>
+                                <para>us</para>
+                            </entry>
+                            <entry>
+                                <para>unsigned short</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para>i</para>
+                            </entry>
+                            <entry>
+                                <para>signed int</para>
+                            </entry>
+                            <entry>
+                                <para>ui</para>
+                            </entry>
+                            <entry>
+                                <para>unisgned int</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para>f</para>
+                            </entry>
+                            <entry>
+                                <para>float</para>
+                            </entry>
+                            <entry>
+                                <para>d</para>
+                            </entry>
+                            <entry>
+                                <para>double</para>
+                            </entry>
+                        </row>
+                    </tbody>
+                </tgroup>
+            </informaltable>
+            <para>Note that OpenGL has special typedefs for all of these types. <type>GLfloat</type>
+                is a typedef for <type>float</type>, for example. This is not particularly useful
+                for simple types, but for integer types, they can be very useful.</para>
+            <para>Not all functions that take multiple types take all possible types. For example,
+                    <function>glUniform</function> only comes in <literal>i</literal>,
+                    <literal>ui</literal>, and <literal>f</literal> variations (OpenGL 4.0
+                introduces <literal>d</literal> variants).</para>
+            <para>There are also vector forms, defined by adding a <quote>v</quote> after the type.
+                These take an array of values, with a parameter saying how many elements are in the
+                array. So the function <function>glUniform2fv</function> takes a uniform location, a
+                number of entries, and an array of that many entries. Each entry is <emphasis>two
+                    floats</emphasis> in size; the number of entries is not the number of floats or
+                other types. It is the number of values divided by the number of values per entry.
+                Since <quote>2f</quote> represents two floats, that is how many values are in each
+                entry.</para>
+            <para>Some OpenGL functions just take a type without a number. These functions take a
+                fixed number of parameters of that type, usually just one.</para>
+        </sidebar>
         <formalpara>
             <title>Vector Math</title>
             <para>You may be curious about how these lines work:</para>

Documents/Positioning/Tutorial 04.xml

             <title>Reshape with Aspect Ratio</title>
             <programlisting language="cpp"><![CDATA[void reshape (int w, int h)
 {
-    perspectiveMatrix[0] = fFrustumScale * (h / (float)w);
+    perspectiveMatrix[0] = fFrustumScale / (w / (float)h);
     perspectiveMatrix[5] = fFrustumScale;
     
     glUseProgram(theProgram);
         <para>The matrix, now a global variable called <varname>perspectiveMatrix</varname>, gets
             its other fields from the program initialization function just as before. The aspect
             ratio code is only interested in the XY scale values.</para>
-        <para>Here, we change the X scaling based on the ratio of height to width. The Y scaling is
-            left alone.</para>
+        <para>Here, we change the X scaling based on the ratio of the width to the height. The Y
+            scaling is left alone.</para>
         <para>Also, the offset used for positioning the prism was changed from (0.5, 0.5) to (1.5,
             0.5). This means that part of the object is off the side of the viewport until you
             resize the window. Changing the width shows more of the area; only by changing the

Documents/Positioning/Tutorial 05.xml

                     <literal>GL_ARRAY_BUFFER</literal> binding once, but the
                     <literal>GL_ELEMENT_ARRAY_BUFFER</literal> is set for each VAO.</para>
             <note>
-                <para>If you look at the vertex position attribute and the shader, you will notice
-                    that we now use a 3-component position vector rather than a 4-component one.
-                    This saves on data, yet our matrix math should not work, since you cannot
-                    multiply a 4x4 matrix with a 3-component vector.</para>
-                <para>This is a subtle feature of OpenGL. If you attempt to transform a matrix by a
-                    vector that is one size smaller than the matrix, it will assume that the last
-                    coordinate missing from the vector will be 1.0. This means that we do not have
-                    to spend precious buffer object memory on a value we know to be 1.0.</para>
+                <para>If you look at the vertex position attribute in our array, we have a
+                    3-component position vector. But the shader still uses a <type>vec4</type>. This
+                    works because OpenGL will fill in any missing vertex attribute components that
+                    the shader looks for but the attribute array doesn't provide. It fills them in
+                    with zeros, except for the fourth component, which is filled in with a
+                    1.0.</para>
             </note>
             <para>Though the initialization code has been expanded, the rendering code is quite
                 simple:</para>

Documents/Positioning/Tutorial 07.xml

             <para>This world is more complicated than anything we've seen up until now. There are a
                 lot of objects being rendered, and most of them are composed out of multiple
                 objects.</para>
-            <para>This tutorial is the first to incorporate a number of the tutorial framework's
-                features. The <classname>Framework::MatrixStack</classname> class implements a
-                matrix stack very much like we saw in the last tutorial. The main difference is that
-                the stack class does not have public push/pop functions. To push a matrix onto the
-                stack, we use a stack object, <classname>Framework::MatrixStackPusher</classname>.
-                The constructor pushes the matrix and the destructor automatically pops. This way,
-                we can never stack overflow or underflow.<footnote>
+            <para>This tutorial is the first to incorporate some of the features of the Unofficial
+                OpenGL SDK. Specifically, it uses the GL Util library's
+                    <classname>glutil::MatrixStack</classname> class, which implements a matrix
+                stack very much like we saw in the last tutorial. The main difference is that we do
+                not use explicit push/pop functions. To push a matrix onto the stack, we instead use
+                a stack object, <classname>glutil::PushStack</classname>. The constructor pushes the
+                matrix and the destructor automatically pops it. This way, we can never stack
+                overflow or underflow.<footnote>
                     <para>This technique, using constructors and destructors to do this kind of
                         scope-bounded work, is called Resource Acquisition Is Initialization
                             (<acronym>RAII</acronym>). It is a common C++ resource management
                             xlink:href="http://www.hackcraft.net/raii/">online</link>. If you are
                         unfamiliar with it, I suggest you become familiar with it.</para>
                 </footnote></para>
-            <para>The <classname>Framework::Mesh</classname> class is much more complicated. It
-                implements mesh loading from an XML-based file format. We will discuss some of the
-                functioning of this class in detail in the next section. For now, let us say that
-                this class's <function>Mesh::Render</function> function is equivalent to binding a
-                vertex array object, rendering with one or more <function>glDraw*</function> calls,
-                and then unbinding the VAO. It expects a suitable program object to be bound to the
+            <para>The tutorial also is the first to use the Framework's mesh class:
+                    <classname>Framework::Mesh</classname>. It implements mesh loading from an
+                XML-based file format. We will discuss some of the functioning of this class in
+                detail in the next section. For now, let us say that this class's
+                    <function>Mesh::Render</function> function is equivalent to binding a vertex
+                array object, rendering with one or more <function>glDraw*</function> calls, and
+                then unbinding the VAO. It expects a suitable program object to be bound to the
                 context.</para>
         </section>
         <section>
                 <title>Window Resizing</title>
                 <programlisting language="cpp">void reshape (int w, int h)
 {
-    Framework::MatrixStack persMatrix;
-    persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
+    glutil::MatrixStack persMatrix;
+    persMatrix.Perspective(45.0f, (w / (float)h), g_fzNear, g_fzFar);
     
     glUseProgram(UniformColor.theProgram);
-    glUniformMatrix4fv(UniformColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-        glm::value_ptr(persMatrix.Top()));
+    glUniformMatrix4fv(UniformColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
     glUseProgram(ObjectColor.theProgram);
-    glUniformMatrix4fv(ObjectColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-        glm::value_ptr(persMatrix.Top()));
+    glUniformMatrix4fv(ObjectColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
     glUseProgram(UniformColorTint.theProgram);
-    glUniformMatrix4fv(UniformColorTint.cameraToClipMatrixUnif, 1, GL_FALSE,
-        glm::value_ptr(persMatrix.Top()));
+    glUniformMatrix4fv(UniformColorTint.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
     glUseProgram(0);
     
     glViewport(0, 0, (GLsizei) w, (GLsizei) h);
                 <title>Upload World to Camera Matrix</title>
                 <programlisting language="cpp">const glm::vec3 &amp;camPos = ResolveCamPosition();
 
-Framework::MatrixStack camMatrix;
-camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget,
-    glm::vec3(0.0f, 1.0f, 0.0f)));
+glutil::MatrixStack camMatrix;
+camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));
 
 glUseProgram(UniformColor.theProgram);
-glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif,
-    1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
 glUseProgram(ObjectColor.theProgram);
-glUniformMatrix4fv(ObjectColor.worldToCameraMatrixUnif,
-    1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+glUniformMatrix4fv(ObjectColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
 glUseProgram(UniformColorTint.theProgram);
-glUniformMatrix4fv(UniformColorTint.worldToCameraMatrixUnif,
-    1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+glUniformMatrix4fv(UniformColorTint.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
 glUseProgram(0);</programlisting>
             </example>
             <para>The function <function>ResolveCamPosition</function> computes the camera position,
                 <title>Spherical to Euclidean Transform</title>
                 <programlisting language="cpp">glm::vec3 ResolveCamPosition()
 {
-    Framework::MatrixStack tempMat;
+    glutil::MatrixStack tempMat;
     
-    float rho = Framework::DegToRad(g_sphereCamRelPos.x);
+    float phi = Framework::DegToRad(g_sphereCamRelPos.x);
     float theta = Framework::DegToRad(g_sphereCamRelPos.y + 90.0f);
     
     float fSinTheta = sinf(theta);
     float fCosTheta = cosf(theta);
-    float fCosRho = cosf(rho);
-    float fSinRho = sinf(rho);
+    float fCosPhi = cosf(phi);
+    float fSinPhi = sinf(phi);
     
-    glm::vec3 dirToCamera(fSinTheta * fCosRho, fCosTheta, fSinTheta * fSinRho);
+    glm::vec3 dirToCamera(fSinTheta * fCosPhi, fCosTheta, fSinTheta * fSinPhi);
     return (dirToCamera * g_sphereCamRelPos.z) + g_camTarget;
 }</programlisting>
             </example>
                 being unit length. This is rendered by the following code:</para>
             <example>
                 <title>Draw the Ground</title>
-                <programlisting language="cpp">Framework::MatrixStackPusher push(modelMatrix);
+                <programlisting language="cpp">glutil::PushStack push(modelMatrix);
 
 modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));
 
 glUseProgram(UniformColor.theProgram);
-glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE,
-    glm::value_ptr(modelMatrix.Top()));
+glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
 glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
 g_pPlaneMesh->Render();
 glUseProgram(0);</programlisting>
                 function.</para>
             <example>
                 <title>DrawForest Function</title>
-                <programlisting language="cpp">void DrawForest(Framework::MatrixStack &amp;modelMatrix)
+                <programlisting language="cpp">void DrawForest(glutil::MatrixStack &amp;modelMatrix)
 {
     for(int iTree = 0; iTree &lt; ARRAY_COUNT(g_forest); iTree++)
     {
         const TreeData &amp;currTree = g_forest[iTree];
         
-        Framework::MatrixStackPusher push(modelMatrix);
+        glutil::PushStack push(modelMatrix);
         modelMatrix.Translate(glm::vec3(currTree.fXPos, 0.0f, currTree.fZPos));
         DrawTree(modelMatrix, currTree.fTrunkHeight, currTree.fConeHeight);
     }
                 translation matrix to the stack.</para>
             <example>
                 <title>Call to DrawParthenon</title>
-                <programlisting language="cpp">Framework::MatrixStackPusher push(modelMatrix);
+                <programlisting language="cpp">glutil::PushStack push(modelMatrix);
 modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));
 
 DrawParthenon(modelMatrix);</programlisting>
                 <programlisting language="cpp">glDisable(GL_DEPTH_TEST);
 glm::mat4 idenity(1.0f);
 
-Framework::MatrixStackPusher push(modelMatrix);
+glutil::PushStack push(modelMatrix);
 
 glm::vec3 cameraAimVec = g_camTarget - camPos;
 modelMatrix.Translate(0.0f, 0.0, -glm::length(cameraAimVec));
                 and hierarchy. Model space to world space to camera space to clip space. But the
                 important thing to remember is that this framework is only useful to you if it does
                 what you want. If you need to position an object directly in front of the camera,
-                then simply remove world space from the equation entirely.</para>
+                then simply remove world space from the equation entirely and deal directly with
+                camera space.</para>
             <para>We could even turn the depth test back on, and the camera target would interact
                 correctly with the rest of the world. It is a part of the world, even though it
                 seems like it goes through a different transform pipe.</para>
                 <title>UBO-based Perspective Matrix</title>
                 <programlisting language="cpp">void reshape (int w, int h)
 {
-    Framework::MatrixStack persMatrix;
-    persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
+    glutil::MatrixStack persMatrix;
+    persMatrix.Perspective(45.0f, (w / (float)h), g_fzNear, g_fzFar);
     
     glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
-    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4),
-        glm::value_ptr(persMatrix.Top()));
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(persMatrix.Top()));
     glBindBuffer(GL_UNIFORM_BUFFER, 0);
     
     glViewport(0, 0, (GLsizei) w, (GLsizei) h);
                 <title>UBO-based Camera Matrix</title>
                 <programlisting language="cpp">const glm::vec3 &amp;camPos = ResolveCamPosition();
 
-Framework::MatrixStack camMatrix;
+glutil::MatrixStack camMatrix;
 camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));
 
 glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
-glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4),
-    glm::value_ptr(camMatrix.Top()));
+glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(camMatrix.Top()));
 glBindBuffer(GL_UNIFORM_BUFFER, 0);</programlisting>
             </example>
             <para>The world-to-camera matrix is the second matrix, so we start the upload at the end
                 <title>Viewing Point with UBO</title>
                 <programlisting language="cpp">glDisable(GL_DEPTH_TEST);
 
-Framework::MatrixStackPusher push(modelMatrix);
+glutil::PushStack push(modelMatrix);
 
 modelMatrix.Translate(g_camTarget);
 modelMatrix.Scale(1.0f, 1.0f, 1.0f);

Documents/Positioning/Tutorial 08.xml

     glClearDepth(1.0f);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
-    Framework::MatrixStack currMatrix;
+    glutil::MatrixStack currMatrix;
     currMatrix.Translate(glm::vec3(0.0f, 0.0f, -200.0f));
     currMatrix.RotateX(g_angles.fAngleX);
     DrawGimbal(currMatrix, GIMBAL_X_AXIS, glm::vec4(0.4f, 0.4f, 1.0f, 1.0f));
     glClearDepth(1.0f);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
-    Framework::MatrixStack currMatrix;
+    glutil::MatrixStack currMatrix;
     currMatrix.Translate(glm::vec3(0.0f, 0.0f, -200.0f));
     currMatrix.ApplyMatrix(glm::mat4_cast(g_orientation));
     

Documents/Texturing/Tutorial 14.xml

             rare, far more rare than <literal>flat</literal>. The important thing to understand from
             this section is that interpolation style matters. And <literal>smooth</literal> will be
             our default interpolation; fortunately, it is OpenGL's default too.</para>
+        <note>
+            <para>If you are interested in how the </para>
+        </note>
     </section>
     <section>
         <?dbhtml filename="Tut14 Texture Mapping.html" ?>

Documents/Texturing/Tutorial 16.xml

                 projection matrix functions. The computation is actually quite simple.</para>
             <example>
                 <title>Window to Clip Matrix Computation</title>
-                <programlisting language="cpp">Framework::MatrixStack persMatrix;
+                <programlisting language="cpp">glutil::MatrixStack persMatrix;
 persMatrix.Translate(-1.0f, 1.0f, 0.0f);
 persMatrix.Scale(2.0f / w, -2.0f / h, 1.0f);</programlisting>
             </example>

Tut 02 Playing with Colors/VertexColors.cpp

 	shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, "VertexColors.frag"));
 
 	theProgram = Framework::CreateProgram(shaderList);
-
 }
 
 const float vertexData[] = {

Tut 04 Objects at Rest/AspectRatio.cpp

 //This is an opportunity to call glViewport or glScissor to keep up with the change in size.
 void reshape (int w, int h)
 {
-	perspectiveMatrix[0] = fFrustumScale * (h / (float)w);
+	perspectiveMatrix[0] = fFrustumScale / (w / (float)h);
 	perspectiveMatrix[5] = fFrustumScale;
 
 	glUseProgram(theProgram);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.