Commits

Jason McKesson committed 94d58f3

Added supplimental images to Tut01. Also some documentation improvements.

Comments (0)

Files changed (4)

Documents/Basics/RasterizerDataFlow.svg

Added
New image
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   stroke-miterlimit="10"
+   id="svg2"
+   inkscape:version="0.48.0 r9654"
+   width="700"
+   height="375"
+   sodipodi:docname="RasterizerDataFlow.svg"
+   style="fill:none;stroke:none">
+  <metadata
+     id="metadata36">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs34" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1232"
+     inkscape:window-height="760"
+     id="namedview32"
+     showgrid="false"
+     inkscape:zoom="1"
+     inkscape:cx="429.99498"
+     inkscape:cy="134.23622"
+     inkscape:window-x="38"
+     inkscape:window-y="149"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer2"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-bbox="false"
+     inkscape:snap-bbox-midpoints="false">
+    <sodipodi:guide
+       orientation="1,0"
+       position="23,290"
+       id="guide3825" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="211,384"
+       id="guide3042" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="45,319"
+       id="guide3048" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="269,140"
+       id="guide3862" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="215.5,248.5"
+       id="guide3868" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="605.28341,225.56706"
+       id="guide3874" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="299.5,291.75"
+       id="guide3878" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="626.14306,207.53584"
+       id="guide3882" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="650.18469,149.55308"
+       id="guide3884" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="574.87781,160.86679"
+       id="guide3886" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="476,365"
+       id="guide3921" />
+  </sodipodi:namedview>
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Background"
+     sodipodi:insensitive="true">
+    <path
+       d="m 23,76.87021 0,0 c 0,-7.98065 6.4696,-14.45026 14.45026,-14.45026 l 170.56406,0 c 3.8324,0 7.50787,1.52243 10.2178,4.23238 2.71,2.70996 4.23245,6.38544 4.23245,10.21788 l 0,52.98923 c 0,7.98068 -6.46961,14.45028 -14.45025,14.45028 l -170.56406,0 C 29.4696,144.30972 23,137.84012 23,129.85944 z"
+       id="path4"
+       inkscape:connector-curvature="0"
+       style="fill:#efecfd;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <path
+       d="m 23,176.50538 0,0 c 0,-7.98066 6.46961,-14.45027 14.45027,-14.45027 l 170.56405,0 c 3.83241,0 7.50787,1.52243 10.21781,4.23238 2.70999,2.70996 4.23245,6.38544 4.23245,10.21789 l 0,52.98922 c 0,7.98069 -6.46961,14.45028 -14.45026,14.45028 l -170.56405,0 C 29.46961,243.94488 23,237.47528 23,229.4946 z"
+       id="path4-4"
+       inkscape:connector-curvature="0"
+       style="fill:#efecfd;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <path
+       d="m 23,272.50538 0,0 c 0,-7.98066 6.46961,-14.45027 14.45027,-14.45027 l 170.56405,0 c 3.83241,0 7.50787,1.52243 10.21781,4.23238 2.70999,2.70996 4.23245,6.38544 4.23245,10.21789 l 0,52.98922 c 0,7.98068 -6.46961,14.45028 -14.45026,14.45028 l -170.56406,0 C 29.46961,339.94488 23,333.47528 23,325.4946 z"
+       id="path4-2"
+       inkscape:connector-curvature="0"
+       style="fill:#efecfd;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <rect
+       style="fill:#d3f3a2;fill-opacity:1;stroke:none"
+       id="rect3858"
+       width="132"
+       height="207"
+       x="277"
+       y="28" />
+    <rect
+       style="fill:#efdefb;fill-opacity:1;stroke:none"
+       id="rect3860"
+       width="105"
+       height="226"
+       x="425"
+       y="9" />
+    <rect
+       style="fill:#d3f7ef;fill-opacity:1;stroke:none"
+       id="rect3864"
+       width="145"
+       height="202"
+       x="544"
+       y="33" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Foreground">
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="119"
+       y="56"
+       id="text4066"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="119"
+         y="56"
+         id="tspan4068"><tspan
+           x="119"
+           y="56"
+           id="tspan4070"
+           style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Serif;-inkscape-font-specification:Serif">Vertex Shaders</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="211"
+       y="125.34438"
+       id="text3036"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="211"
+         y="125.34438"
+         id="tspan3038"><tspan
+           x="211"
+           y="125.34438"
+           id="tspan3040"
+           style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;font-family:Serif;-inkscape-font-specification:Serif">gl_Position</tspan></tspan></text>
+    <use
+       x="0"
+       y="0"
+       xlink:href="#text3036"
+       id="use3044"
+       transform="translate(0,101.5)"
+       width="700"
+       height="375" />
+    <use
+       height="375"
+       width="700"
+       transform="translate(0,198.5)"
+       id="use3046"
+       xlink:href="#text3036"
+       y="0"
+       x="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="341.85938"
+       y="56"
+       id="text3915"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="341.85938"
+         y="56"
+         id="tspan3917"><tspan
+           x="341.85938"
+           y="56"
+           id="tspan3919">Divide by W</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="476"
+       y="30.344383"
+       id="text3909"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="476"
+         y="30.344383"
+         id="tspan3911"><tspan
+           x="476"
+           y="30.344383"
+           id="tspan3913">Viewport</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="476"
+       y="56"
+       id="text3903"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="476"
+         y="56"
+         id="tspan3905"><tspan
+           x="476"
+           y="56"
+           id="tspan3907">Transform</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="619"
+       y="56"
+       id="text3086"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3088"
+         x="619"
+         y="56">Rasterizer</tspan></text>
+    <path
+       style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 215.5,120.5 C 245,113 242,106 250.5,94.5 258.52428,83.643622 265,72 299.5,72 334,72 472,72 472,72 l 84.25,0 c 14.2522,0 58.59552,13.478853 78.51614,49.65218 19.92063,36.17334 15.41855,95.04117 15.41855,103.79474"
+       id="path3866"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cssccsc" />
+    <path
+       style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 215.5,223 c 10.5,0.25 13.5,0.3125 16.4375,-10.625 4.22456,-17.80425 4.14317,-66.99545 17.13483,-84.29657 C 269.33332,101.58329 291.49609,98.25 299.5,98.25 L 556.25,96.5 c 32.5,0 69.89306,57.20507 69.89306,70.96416"
+       id="path3870"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 215.5,320.90633 c 41.07173,0 37.20211,-19.16428 37.20211,-52.2362 0,-33.07192 9.46121,-85.2332 16.37888,-114.57448 6.50047,-27.57172 17.16984,-32.97002 30.41901,-32.97002 13.24917,0 234.58665,0 256.75,0 11.08168,0 30.88796,24.75849 28.23176,46.33853 -2.70966,22.01445 -9.60395,40.30509 -9.60395,46.66905"
+       id="path3880"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="czszssc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:10;stroke-dasharray:none"
+       d="m 626.14306,167.46416 24.04163,57.98276 -75.30688,-11.31371 z"
+       id="path3888"
+       inkscape:connector-curvature="0" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#000000;fill-opacity:1;stroke:none"
+       id="path3897"
+       sodipodi:cx="626.14307"
+       sodipodi:cy="167.46416"
+       sodipodi:rx="6.4782476"
+       sodipodi:ry="6.4782476"
+       d="m 632.62131,167.46416 a 6.4782476,6.4782476 0 1 1 -12.95649,0 6.4782476,6.4782476 0 1 1 12.95649,0 z" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#path3897"
+       id="use3899"
+       transform="translate(-51.25,46.669053)"
+       width="700"
+       height="375" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#use3899"
+       id="use3901"
+       transform="translate(75.3125,11.31371)"
+       width="700"
+       height="375" />
+  </g>
+</svg>

Documents/Basics/Tutorial 01.xml

                 step is to allocate some memory that OpenGL <emphasis>can</emphasis> see, and fill
                 that memory with our data. This is done with something called a <glossterm>buffer
                     object.</glossterm></para>
-            <para>A buffer object is a linear array of memory allocated by OpenGL at the behest of
-                the user. The content of this memory is controlled by the user, but the user has
-                only indirect control over it. Think of a buffer object as an array of GPU memory.
-                The GPU can read this memory quickly, so storing data in it has performance
-                advantages.</para>
+            <para>A buffer object is a linear array of memory, managed and allocated by OpenGL at
+                the behest of the user. The content of this memory is controlled by the user, but
+                the user has only indirect control over it. Think of a buffer object as an array of
+                GPU memory. The GPU can read this memory quickly, so storing data in it has
+                performance advantages.</para>
             <para>The buffer object in the tutorial was created during initialization. Here is the
                 code responsible for creating the buffer object:</para>
             <example>
                     <link linkend="OpenGLObjects">Tutorial 0</link>, objects in OpenGL usually have
                 to be bound to the context in order for them to do anything, and buffer objects are
                 no exception.</para>
-            <para>The <function>glBufferData</function> function allocates memory for the buffer
-                currently bound to <literal>GL_ARRAY_BUFFER</literal>, which is the one we just
-                created and bound. We already have some vertex data; the problem is that it is in
-                our memory rather than OpenGL's memory. This function allocates enough GPU memory to
-                store our vertex data. The third parameter is a pointer to the data to initialize
-                the buffer with; we give it our vertex data. The fourth parameter is something we
-                will look at in future tutorials.</para>
+            <para>The <function>glBufferData</function> function performs two operations. It
+                allocates memory for the buffer currently bound to
+                    <literal>GL_ARRAY_BUFFER</literal>, which is the one we just created and bound.
+                We already have some vertex data; the problem is that it is in our memory rather
+                than OpenGL's memory. The <literal>sizeof(vertexPositions)</literal> uses the C++
+                compiler to determine the byte size of the <varname>vertexPositions</varname> array.
+                We then pass this size to <function>glBufferData</function> as the size of memory to
+                allocate for this buffer object. Thus, we allocate enough GPU memory to store our
+                vertex data.</para>
+            <para>The other operation that <function>glBufferData</function> performs is copying
+                data from our memory array into the buffer object. The third parameter controls
+                this. If this value is not NULL, as in this case, <function>glBufferData</function>
+                will copy the data referenced by the pointer into the buffer object. After this
+                function call, the buffer object stores exactly what
+                    <varname>vertexPositions</varname> stores.</para>
+            <para>The fourth parameter is something we will look at in future tutorials.</para>
             <para>The second bind buffer call is simply cleanup. By binding the buffer object 0 to
                     <literal>GL_ARRAY_BUFFER</literal>, we cause the buffer object previously bound
-                to that target to become unbound from it. This was not strictly necessary, as any
-                later binds to this target will simply unbind what is already there. But unless you
-                have very strict control over your rendering, it is usually a good idea to unbind
-                the objects you bind.</para>
+                to that target to become unbound from it. Zero in this cases works a lot like the
+                NULL pointer. This was not strictly necessary, as any later binds to this target
+                will simply unbind what is already there. But unless you have very strict control
+                over your rendering, it is usually a good idea to unbind the objects you
+                bind.</para>
             <para>This is all just to get the vertex data in the GPU's memory. But buffer objects
-                are not formatted; as far as OpenGL is concerned, all we did was fill a buffer
-                object with random binary data. We now need to do something that tells OpenGL that
-                there is vertex data in this buffer object.</para>
+                are not formatted; as far as OpenGL is concerned, all we did was allocate a buffer
+                object and fill it with random binary data. We now need to do something that tells
+                OpenGL that there is vertex data in this buffer object and what form that vertex
+                data takes.</para>
             <para>We do this in the rendering code. That is the purpose of these lines:</para>
             <programlisting language="cpp">glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
 glEnableVertexAttribArray(0);
             <para>The third function is the real key. <function>glVertexAttribPointer</function>,
                 despite having the word <quote>Pointer</quote> in it, does not deal with pointers.
                 Instead, it deals with buffer objects.</para>
-            <para>This function tells OpenGL where a particular piece of vertex data is coming from.
-                The buffer that is bound to <literal>GL_ARRAY_BUFFER</literal> at the time that this
-                function is called is the buffer object that will be associated with this piece of
-                data.</para>
             <para>When rendering, OpenGL pulls vertex data from arrays stored in buffer objects. What
                 we need to tell OpenGL is what format our vertex array data in the buffer object is
                 stored in. That is, we need to tell OpenGL how to interpret the array of data stored
                 in the buffer.</para>
-            <para>In our case, the array of data contains 32-bit floating-point values. Every 4
-                floating-point values represents a position. And each piece of position data is
-                directly adjacent to the next; there are no gaps between positions in the array.
-                Lastly, our data was placed at the very beginning of the buffer object. OpenGL needs
-                to know where in the buffer object the array starts, as you can have data for many
-                objects in a single buffer.</para>
+            <para>In our case, our data is formatted as follows:</para>
+            <itemizedlist>
+                <listitem>
+                    <para>Our position data is stored in 32-bit floating point values using the
+                        C/C++ type <type>float</type>.</para>
+                </listitem>
+                <listitem>
+                    <para>Each position is composed of 4 of these values.</para>
+                </listitem>
+                <listitem>
+                    <para>There is no space between each set of 4 values. The values are tightly
+                        packed in the array.</para>
+                </listitem>
+                <listitem>
+                    <para>The first value in our array of data is at the beginning of the buffer
+                        object.</para>
+                </listitem>
+            </itemizedlist>
             <para>The <function>glVertexAttribPointer</function> function tells OpenGL all of this.
-                The third parameter tells OpenGL what the type of data is (floats, in this case).
-                The second parameter tells OpenGL how many of them compose a single piece of data;
-                there are 4 values to our position data.</para>
-            <para>The fifth parameter tells OpenGL how much space there is between elements; 0 means
-                that there is no space between array values. And the last parameter is the byte
-                offset from the beginning of the buffer object to the position of the first element
-                in our array of data. In this case, the data is at the beginning of the buffer, so
-                the offset is zero.</para>
+                The third parameter specifies the base type of a value. In this case, it is
+                    <literal>GL_FLOAT</literal>, which corresponds to a 32-bit floating-point value.
+                The second parameter specifies how many of these values represent a single piece of
+                data. In this case, that is 4. The fifth parameter specifies the spacing between
+                each set of values. In our case, there is no space between values, so this value is
+                0. And the sixth parameter specifies the byte offset from the  value in the buffer
+                object is at the front, which is 0 bytes from the beginning of the buffer
+                object.</para>
+            <para>The fourth parameter is something that we will look at in later tutorials. The
+                first parameter is something we will look at in the next section.</para>
+            <para>One thing that appears absent is specifying which buffer object this data comes
+                from. This is an implicit association rather than an explicit one.
+                    <function>glVertexAttribPointer</function> always refers to whatever buffer is
+                bound to <literal>GL_ARRAY_BUFFER</literal> at the time that this function is
+                called. Therefore it does not take a buffer object handle; it simply uses the handle
+                we bound previously.</para>
             <para>This function will be looked at in greater detail in later tutorials.</para>
             <para>Once OpenGL knows where to get its vertex data from, it can now use that vertex
                 data to render.</para>
                 statement:</para>
             <programlisting language="glsl">layout(location = 0) in vec4 position;</programlisting>
             <para>The layout location part assigns the attribute index of 0 to
-                    <varname>position</varname>. Attribute indices must be positive numbers, and
-                there is a hardware-based limit on the number of attribute indices that can be in
-                use at any one time (for virtually all hardware since the beginning of commercial
-                programmable hardware, this has been 16).</para>
+                    <varname>position</varname>. Attribute indices must be greater than or equal to
+                zero, and there is a hardware-based limit on the number of attribute indices that
+                can be in use at any one time<footnote>
+                    <para>For virtually all hardware since the beginning of commercial programmable
+                        hardware, this limit has been exactly 16. No more, no less.</para>
+                </footnote>.</para>
             <para>In code, when referring to attributes, they are <emphasis>always</emphasis>
                 referred to by attribute index. The functions
                     <function>glEnableVertexAttribArray</function>,
                 attribute to 0 in the vertex shader, so the call to
                     <function>glEnableVertexAttribArray(0)</function> enables the attribute index
                 for the <varname>position</varname> attribute.</para>
-            <para>Here is a diagram of the data flow through the vertex shader:</para>
-            <!--TODO: A diagram with the following. Show input attribute from
-glEnableVertexAttrib/glVertexAttribPointer going from the buffer object to the
-attribute. Then show the attribute going to the vertex shader's 'position' input.
-Then show the output gl_Position coming out of the vertex shader.
-Show 3 invocations of the shader.-->
+            <para>Here is a diagram of the data flow to the vertex shader:</para>
+            <figure>
+                <title>Data Flow to Vertex Shader</title>
+                <mediaobject>
+                    <imageobject>
+                        <imagedata fileref="VertexShaderDataFlow.svg" format="SVG"/>
+                    </imageobject>
+                </mediaobject>
+            </figure>
             <para>Without the call to <function>glEnableVertexAttribArray</function>, calling
                     <function>glVertexAttribPointer</function> on that attribute index would not
                 mean much. The enable call does not have to be called before the vertex attribute
                 OpenGL interprets vertex lists is given by the draw command:</para>
             <programlisting>glDrawArrays(GL_TRIANGLES, 0, 3);</programlisting>
             <para>The enum <literal>GL_TRIANGLES</literal> tells OpenGL that every 3 vertices of the
-                list should be taken to be a triangle. Since we passed only 3 vertices, we get 1
+                list should be used to build a triangle. Since we passed only 3 vertices, we get 1
                 triangle.</para>
-            <!--TODO: Expand on the above diagram, showing the 3 vertex shader invocations and that the output
-data are composed into a single triangle, one triangle for every 3 vertices.-->
+            <figure>
+                <title>Data Flow to Rasterizer</title>
+                <mediaobject>
+                    <imageobject>
+                        <imagedata fileref="RasterizerDataFlow.svg"/>
+                    </imageobject>
+                </mediaobject>
+            </figure>
             <para>If we rendered 6 vertices, then we would get 2 triangles.</para>
         </section>
         <section>

Documents/Basics/Tutorial 02.xml

             </example>
             <para>Since we have two pieces of data, we have two vertex attributes. For each
                 attribute, we must call <function>glEnableVertexAttribArray</function> to enable
-                that particular attribute. The parameter is the attribute location we query from the
-                shader program (we'll get to that in the next section) that refers to that
-                particular attribute.</para>
+                that particular attribute. The parameter is the attribute location set by the
+                    <literal>layout(location)</literal> field for that attribute in the vertex
+                shader.</para>
             <para>Then, we call <function>glVertexAttribPointer</function> for each of the attribute
                 arrays we want to use. The only difference in the two calls are which attribute
                 location to attach this to and the last parameter. The last parameter, if you
                 <para>If you're wondering why it is <literal>(void*)48</literal> and not just 48,
                     that is because of some legacy API cruft. The reason why the function name is
                         glVertexAttrib<quote>Pointer</quote> is because the last parameter is
-                    technically a pointer to client memory. Or at least, it could be in the
-                    past.</para>
+                    technically a pointer to client memory. Or at least, it could be in the past. So
+                    we must explicitly cast the integer value 48 to a pointer type.</para>
             </note>
             <para>After this, we use <function>glDrawArrays</function> to render, then disable the
                 arrays with <function>glDisableVertexAttribArray.</function></para>

Documents/Basics/VertexShaderDataFlow.svg

Added
New image
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   stroke-miterlimit="10"
+   id="svg2"
+   inkscape:version="0.48.0 r9654"
+   width="700"
+   height="375"
+   sodipodi:docname="VertexShaderDataFlow.svg"
+   style="fill:none;stroke:none">
+  <metadata
+     id="metadata36">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs34" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1138"
+     id="namedview32"
+     showgrid="false"
+     inkscape:zoom="1"
+     inkscape:cx="530.00943"
+     inkscape:cy="121.49248"
+     inkscape:window-x="-4"
+     inkscape:window-y="-4"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1"
+     showguides="true"
+     inkscape:guide-bbox="true">
+    <sodipodi:guide
+       orientation="0,1"
+       position="59,336"
+       id="guide3773" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="23,290"
+       id="guide3825" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="247,493"
+       id="guide3865" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="538,268"
+       id="guide4002" />
+  </sodipodi:namedview>
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Background">
+    <path
+       d="m 247,60.87021 0,0 c 0,-7.98065 6.4696,-14.45026 14.45026,-14.45026 l 170.56406,0 c 3.8324,0 7.50787,1.52243 10.2178,4.23238 2.71,2.70996 4.23245,6.38544 4.23245,10.21788 l 0,52.98923 c 0,7.98068 -6.46961,14.45028 -14.45025,14.45028 l -170.56406,0 C 253.4696,128.30972 247,121.84012 247,113.85944 z"
+       id="path4"
+       inkscape:connector-curvature="0"
+       style="fill:#efecfd;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <path
+       d="m 247,160.50538 0,0 c 0,-7.98066 6.46961,-14.45027 14.45027,-14.45027 l 170.56405,0 c 3.83241,0 7.50787,1.52243 10.21781,4.23238 2.70999,2.70996 4.23245,6.38544 4.23245,10.21789 l 0,52.98922 c 0,7.98069 -6.46961,14.45028 -14.45026,14.45028 l -170.56405,0 C 253.46961,227.94488 247,221.47528 247,213.4946 z"
+       id="path4-4"
+       inkscape:connector-curvature="0"
+       style="fill:#efecfd;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <path
+       d="m 247,256.50538 0,0 c 0,-7.98066 6.46961,-14.45027 14.45027,-14.45027 l 170.56405,0 c 3.83241,0 7.50787,1.52243 10.21781,4.23238 2.70999,2.70996 4.23245,6.38544 4.23245,10.21789 l 0,52.98922 c 0,7.98068 -6.46961,14.45028 -14.45026,14.45028 l -170.56406,0 C 253.46961,323.94488 247,317.47528 247,309.4946 z"
+       id="path4-2"
+       inkscape:connector-curvature="0"
+       style="fill:#efecfd;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <path
+       d="m 23,49.204746 83.40157,0 0,35.795254 L 23,85 z"
+       id="path16"
+       inkscape:connector-curvature="0"
+       style="fill:#d2fff1;fill-opacity:1;stroke:#000000;stroke-width:0.73229474;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <path
+       d="m 23,85 83.40158,0 0,35.79526 -83.40158,0 z"
+       id="path16-0"
+       inkscape:connector-curvature="0"
+       style="fill:#d2fff1;fill-opacity:1;stroke:#000000;stroke-width:0.73229474;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+    <path
+       d="m 23,121.10237 83.40158,0 0,35.79526 -83.40158,0 z"
+       id="path16-0-1"
+       inkscape:connector-curvature="0"
+       style="fill:#d2fff1;fill-opacity:1;stroke:#000000;stroke-width:0.73229474;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Foreground">
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="13"
+       y="39"
+       id="text4042"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="13"
+         y="39"
+         id="tspan4044"><tspan
+           x="13"
+           y="39"
+           id="tspan4046">Buffer Object</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="284"
+       y="39.000004"
+       id="text4066"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="284"
+         y="39.000004"
+         id="tspan4068"><tspan
+           x="284"
+           y="39.000004"
+           id="tspan4070">Vertex Shaders</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="35.826771"
+       y="73.420509"
+       id="text4036"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="35.826771"
+         y="73.420509"
+         id="tspan4038"><tspan
+           x="35.826771"
+           y="73.420509"
+           id="tspan4040">Index 0</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="35.826771"
+       y="109.21577"
+       id="text4030"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="35.826771"
+         y="109.21577"
+         id="tspan4032"><tspan
+           x="35.826771"
+           y="109.21577"
+           id="tspan4034">Index 1</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="35.826771"
+       y="145.31813"
+       id="text4024"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="35.826771"
+         y="145.31813"
+         id="tspan4026"><tspan
+           x="35.826771"
+           y="145.31813"
+           id="tspan4028">Index 2</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="260.72702"
+       y="70.344383"
+       id="text4060"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="260.72702"
+         y="70.344383"
+         id="tspan4062"><tspan
+           x="260.72702"
+           y="70.344383"
+           id="tspan4064">in vec3 position</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="260.72702"
+       y="169.97955"
+       id="text4054"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="260.72702"
+         y="169.97955"
+         id="tspan4056"><tspan
+           x="260.72702"
+           y="169.97955"
+           id="tspan4058">in vec3 position</tspan></tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="260.72702"
+       y="265.97955"
+       id="text4048"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="260.72702"
+         y="265.97955"
+         id="tspan4050"><tspan
+           x="260.72702"
+           y="265.97955"
+           id="tspan4052">in vec3 position</tspan></tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 106,68 c 20.53861,0 28.07937,-13.597416 41.30057,-13.597416 18.59259,0.516592 46.78578,7.078799 65.43463,7.362217 C 231.83848,62.055125 239.29894,65 258,65"
+       id="path3912"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccsc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 106.5,102.5 c 29.39782,0 58.60756,14.24592 77.6668,30.75 34.14983,29.57157 30.02055,31.10355 73.8332,30.75"
+       id="path3914"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 106.06602,138.47278 c 38.18376,-1.06066 49.49747,12.72792 64.34672,51.97235 14.84924,39.24442 40.9774,70.71068 85.91347,70.71068"
+       id="path3916"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 538,107 c -92.52273,0 -92.16917,0 -92.16917,0"
+       id="path4006"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 538,209.18346 c -92.52273,0 -92.16917,0 -92.16917,0"
+       id="path4008"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 538,302.168 -92.16917,0"
+       id="path4010"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+       x="541"
+       y="215"
+       id="text4072"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="541"
+         y="215"
+         id="tspan4074"><tspan
+           x="541"
+           y="215"
+           id="tspan4076">gl_Position</tspan></tspan></text>
+    <use
+       x="0"
+       y="0"
+       xlink:href="#text4072"
+       id="use4086"
+       transform="translate(0,92)"
+       width="700"
+       height="375" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#text4072"
+       id="use4088"
+       transform="translate(0,-104)"
+       width="700"
+       height="375" />
+  </g>
+</svg>