<p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;"> 随着OpenGL状态和固定管线模式的移除,我们不在用任何glEnable函数调用,而且也不会有glVertex、glColor等函数调用。这就意味着我们需要一种新的方式来将数据传输到图形卡以渲染图形。我们可以采用VBO,或者是在OpenGL3以上版本引入的新的特性,叫做VAO。通过它,我们可以把顶点数据和颜色存储在不同的VBO中,但是在同一个VAO中。对于法线数据或者其他的顶点信息也是一样。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">VAO,是这样一种方式:把对象信息直接存储在图形卡中,而不是在当我们需要的时候传输到图形卡。这就是Direct3D所采用得方式,而在OpenGL中只有OpenGL3.X以上的版本中采用。这就意味着我们的应用程序不用将数据传输到图形卡或者是从图形卡输出,这样也就获得了额外的性能提升。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">使用VAO并不难。我们不需要大量的glVertex调用,而是把顶点数据存储在数组中,然后放进VBO,最后在VAO中存储相关的状态。记住:VAO中并没有存储顶点的相关属性数据。OpenGL会在后台为我们完成其他的功能。</span></p>
一个三角形顶点数据
<span style="font-size:18px;">float position[9]={ -0.8f, -0.8f, 0.0f, 0.8f, -0.8f, 0.0f, 0.0f, 0.8f, 0.0f}; </span>
一、
<span style="font-size:18px;"> /***单独vao绘制***/ glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0,position);/*size:指定每个顶点对应的坐标个数,可取2,3,4 type:指定数组中每个顶点坐标的数据类型:GL_BYTE, GL_SHORT,GL_FIXED,GL_FLOAT; stride:指定连续顶点间的字节排列方式,即<从一个数据的开始到下一个数据的开始, 所相隔的字节数>,为0表示数组中的顶点被认为按照紧凑方式排列,默认为0; pointer:指定了数组中第一个顶点的首地址,默认值为0。*/ glDrawArrays(GL_TRIANGLES, 0, 3); glDisableClientState(GL_VERTEX_ARRAY);</span>
二、
<span style="font-size:18px;"> /***单独vbo绘制***/ GLuint vboNum; glGenBuffers(1,&vboNum); glBindBuffer(GL_ARRAY_BUFFER,vboNum); glBufferData(GL_ARRAY_BUFFER,9*sizeof(float),position,GL_STATIC_DRAW); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, 0); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableClientState(GL_VERTEX_ARRAY); </span>
三、
<span style="font-size:18px;"><span style="margin: 0px; padding: 0px; border: 0px; background: transparent;"> </span>/***使用glVertexPointer()、vbo和vao传递数据***/ /***vbo***/ GLuint vboNum; glGenBuffers(1,&vboNum); glBindBuffer(GL_ARRAY_BUFFER,vboNum); glBufferData(GL_ARRAY_BUFFER,9*sizeof(float),position,GL_STATIC_DRAW); /***vao***/ GLuint vaoNum; glGenVertexArrays(1,&vaoNum); glBindVertexArray(vaoNum); glBindBuffer(GL_ARRAY_BUFFER,vboNum); glVertexPointer(3, GL_FLOAT, 0,(void *)NULL); glEnableClientState(GL_VERTEX_ARRAY); glBindVertexArray(vaoNum); glDrawArrays(GL_TRIANGLES, 0, 3 ); glDisableClientState(GL_VERTEX_ARRAY); </span>
四、
<span style="font-size:18px;"><span style="margin: 0px; padding: 0px; border: 0px; background: transparent;"> </span>/***使用glVertexAttribPointer()、vbo和vao传递数据***/ /***vbo***/ GLuint vboNum; glGenBuffers(1,&vboNum); glBindBuffer(GL_ARRAY_BUFFER,vboNum); glBufferData(GL_ARRAY_BUFFER,9*sizeof(float),position,GL_STATIC_DRAW); /***vao***/ GLuint vaoNum; glGenVertexArrays(1,&vaoNum); glBindVertexArray(vaoNum); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER,vboNum); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void *)NULL); glBindVertexArray(vaoNum); glDrawArrays(GL_TRIANGLES, 0, 3 );</span>
<span style="font-size:18px;"> </span>
<p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"> </p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;"> </span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="color: rgb(255, 0, 0);"><span style="font-size:18px;">使用VAO的步骤:</span></span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">1、产生VAO</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">void glGenVertexArrays(<span style="white-space: pre;"></span>GLsizei n, <span style="white-space: pre;"> </span>GLuint *arrays);</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">n:要产生的VAO对象的数量。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">arrays:存放产生的VAO对象的名称。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">2、绑定VAO</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">void glBindVertexArray(GLuint array);</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">array:要绑定的顶点数组的名字。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">3、产生VBOs</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">void glGenBuffers(<span style="white-space: pre;"></span>GLsizei <span style="white-space: pre;"></span>n, <span style="white-space: pre;"> </span>GLuint * <span style="white-space: pre;"> </span> buffers);</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">产生缓冲区对象的名称。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">参数含义和glGenVertexArrays类似。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">4、绑定VBOs</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">void glBindBuffer(<span style="white-space: pre;"></span>GLenum <span style="white-space: pre;"></span>target, <span style="white-space: pre;"> </span>GLuint <span style="white-space: pre;"> </span> buffer);</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">绑定一个缓冲区对象。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">target可能取值是:GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, or GL_PIXEL_UNPACK_BUFFER.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">当进行绑定之后,以前的绑定就失效了。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">5、给VBO分配数据:</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">void glBufferData( GLenum target,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> GLsizeiptr size,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> const GLvoid * data,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> GLenum usage);</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">target可能取值为:GL_ARRAY_BUFFER(表示顶点数据), GL_ELEMENT_ARRAY_BUFFER(表示索引数据),GL_PIXEL_PACK_BUFFER(表示从OpenGL获取的的像素数据), or GL_PIXEL_UNPACK_BUFFER(表示传递给OpenGL的像素数据).</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">参数含义:</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">size:缓冲区对象字节数</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">data:指针:指向用于拷贝到缓冲区对象的数据。或者是NULL,表示暂时不分配数据。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">6、定义存放顶点属性数据的数组:</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">首先需要启用VAO中对应的顶点属性数组:</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">void glEnableVertexAttribArray( GLuint index);</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">index:指定了需要启用的顶点属性数组的索引</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">注意:它只在OpenGL2.0及其以上版本才有。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">7、给对应的顶点属性数组指定数据:</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">void glVertexAttribPointer( GLuint index,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> GLint size,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> GLenum type,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> GLboolean normalized,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> GLsizei stride,</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;"> const GLvoid * pointer);</span></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">index:要指定数据的顶点属性数组的索引。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">size:每个顶点属性的数据个数。可能的取值是1、2、3或者4.初始值是4.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">type:数组中每个数据的类型。可能的取值是:GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, or GL_DOUBLE。初始值是GL_FLOAT。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">normalized:指定顶点数在被访问的时候是否需要被归一化。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">注意:如果有个非零的缓冲对象绑定到GL_ARRAY_BUFFER,那么pointer就是对应的缓冲区对象的偏移量。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;"> stride:两个连续顶点的属性之间的偏移量。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">pointer:指向数组中的第一个顶点属性的第一个数据。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><strong><span style="font-size:18px;">8、然后在进行渲染的时候,只需要绑定对应的VAO即可,操作起来十分方便。</span></strong></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="color: rgb(0, 153, 0);"><span style="font-size:18px;">glBindVertexArray(vaoHandle);</span></span></p><span style="font-size:18px;"><span style="font-family: Arial; line-height: 26px;"><strong>9、使用完毕之后需要清除绑定。</strong></span><span style="font-family: Arial; line-height: 26px;"></span></span><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;"><span style="color: rgb(0, 153, 0);">glBindVertexArray(0);</span> </span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;"> </span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">VAO参考资料:</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><a target=_blank href="http://www.opengl.org/wiki/Vertex_Array_Object" target="_blank" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="font-size:18px;">VAO wiki</span></a></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><a target=_blank href="http://www.cppblog.com/init/archive/2012/02/21/166098.html" target="_blank" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="font-size:18px;">关于VAO的一篇博客</span></a></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><a target=_blank href="http://www.swiftless.com/tutorials/opengl4/4-opengl-4-vao.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="font-size:18px;">VAO</span></a></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;">事实上,在这个简单的程序中,不用VAO,只用VBO也一样可以实现。只是采用VAO可以进一步提升性能,而且在较新版本的OpenGL中不用VAO的方式会被逐渐废弃。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;"> </span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; font-family: Arial; line-height: 26px;"><span style="font-size:18px;"> </span></p><div class="refsynopsisdiv" style="line-height: 26px; font-family: 'Songti SC';"><div class="funcsynopsis"><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table "><tbody><tr><td><code class="funcdef"><span style="font-size:18px;">void <span class="fsfunc" style="font-weight: bold;">glVertexAttribPointer</span>(</span></code></td><td><span style="font-size:18px;">GLuint <var class="pdparam">index</var>,</span></td></tr><tr><td><span style="font-size:18px;"> </span></td><td><span style="font-size:18px;">GLint <var class="pdparam">size</var>,</span></td></tr><tr><td><span style="font-size:18px;"> </span></td><td><span style="font-size:18px;">GLenum <var class="pdparam">type</var>,</span></td></tr><tr><td><span style="font-size:18px;"> </span></td><td><span style="font-size:18px;">GLboolean <var class="pdparam">normalized</var>,</span></td></tr><tr><td><span style="font-size:18px;"> </span></td><td><span style="font-size:18px;">GLsizei <var class="pdparam">stride</var>,</span></td></tr><tr><td><span style="font-size:18px;"> </span></td><td><span style="font-size:18px;">const GLvoid * <var class="pdparam">pointer</var><code>)</code>;</span></td></tr></tbody></table><div class="funcprototype-spacer"><span style="font-size:18px;"> </span></div></div></div><div class="refsect1" lang="en" style="line-height: 26px; font-family: 'Songti SC';"><span style="font-size:18px;"><a target=_blank target="_blank" id="parameters" style="color: rgb(202, 0, 0);"></a></span><h2 style="margin: 0px; padding: 0px;"><span style="font-size:18px;"><a target=_blank name="t2" style="color: rgb(202, 0, 0);"></a>Parameters</span></h2><div class="variablelist"><dl><dt><span class="term"><span class="parameter" style="font-style: italic;"><code><span style="font-size:18px;">index</span></code></span></span></dt><dd><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">Specifies the index of the generic vertex attribute to be modified.</span></p></dd><dt><span class="term"><span class="parameter" style="font-style: italic;"><code><span style="font-size:18px;">size</span></code></span></span></dt><dd><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, or 4. The initial value is 4.</span></p></dd><dt><span class="term"><span class="parameter" style="font-style: italic;"><code><span style="font-size:18px;">type</span></code></span></span></dt><dd><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">Specifies the data type of each component in the array. Symbolic constants <code class="constant">GL_BYTE</code>, <code class="constant">GL_UNSIGNED_BYTE</code>, <code class="constant">GL_SHORT</code>, <code class="constant">GL_UNSIGNED_SHORT</code>, <code class="constant">GL_FIXED</code>, or<code class="constant">GL_FLOAT</code> are accepted. The initial value is <code class="constant">GL_FLOAT</code>.</span></p></dd><dt><span class="term"><span class="parameter" style="font-style: italic;"><code><span style="font-size:18px;">normalized</span></code></span></span></dt><dd><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">Specifies whether fixed-point data values should be normalized (<code class="constant">GL_TRUE</code>) or converted directly as fixed-point values (<code class="constant">GL_FALSE</code>) when they are accessed.</span></p></dd><dt><span class="term"><span class="parameter" style="font-style: italic;"><code><span style="font-size:18px;">stride</span></code></span></span></dt><dd><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">Specifies the byte offset between consecutive generic vertex attributes. If <span class="parameter" style="font-style: italic;"><code>stride</code></span> is 0, the generic vertex attributes are understood to be tightly packed in the array. The initial value is 0.</span></p></dd><dt><span class="term"><span class="parameter" style="font-style: italic;"><code><span style="font-size:18px;">pointer</span></code></span></span></dt><dd><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">Specifies a pointer to the first component of the first generic vertex attribute in the array. The initial value is 0.</span></p></dd></dl></div></div><div class="refsect1" lang="en" style="line-height: 26px; font-family: 'Songti SC';"><span style="font-size:18px;"><a target=_blank target="_blank" id="description" style="color: rgb(202, 0, 0);"></a></span><h2 style="margin: 0px; padding: 0px;"><span style="font-size:18px;"><a target=_blank name="t3" style="color: rgb(202, 0, 0);"></a>Description</span></h2><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><code class="function">glVertexAttribPointer</code> specifies the location and data format of the array of generic vertex attributes at index <span class="parameter" style="font-style: italic;"><code>index</code></span> to use when rendering. <span class="parameter" style="font-style: italic;"><code>size</code></span> specifies the number of components per attribute and must be 1, 2, 3, or 4. <span class="parameter" style="font-style: italic;"><code>type</code></span> specifies the data type of each component, and <span class="parameter" style="font-style: italic;"><code>stride</code></span> specifies the byte stride from one attribute to the next, allowing vertices and attributes to be packed into a single array or stored in separate arrays. If set to <code class="constant">GL_TRUE</code>, <span class="parameter" style="font-style: italic;"><code>normalized</code></span> indicates that values stored in an integer format are to be mapped to the range [-1,1] (for signed values) or [0,1] (for unsigned values) when they are accessed and converted to floating point. Otherwise, values will be converted to floats directly without normalization.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">If a non-zero named buffer object is bound to the <code class="constant">GL_ARRAY_BUFFER</code> target (see <a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindBuffer.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glBindBuffer</a>) while a generic vertex attribute array is specified, <span class="parameter" style="font-style: italic;"><code>pointer</code></span> is treated as a byte offset into the buffer object's data store. Also, the buffer object binding (<code class="constant">GL_ARRAY_BUFFER_BINDING</code>) is saved as generic vertex attribute array client-side state (<code class="constant">GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING</code>) for index <span class="parameter" style="font-style: italic;"><code>index</code></span>.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">When a generic vertex attribute array is specified, <span class="parameter" style="font-style: italic;"><code>size</code></span>, <span class="parameter" style="font-style: italic;"><code>type</code></span>, <span class="parameter" style="font-style: italic;"><code>normalized</code></span>, <span class="parameter" style="font-style: italic;"><code>stride</code></span>, and <span class="parameter" style="font-style: italic;"><code>pointer</code></span> are saved as client-side state, in addition to the current vertex array buffer object binding.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">To enable and disable a generic vertex attribute array, call <a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glEnableVertexAttribArray</a> and <a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDisableVertexAttribArray.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glDisableVertexAttribArray</a> with <span class="parameter" style="font-style: italic;"><code>index</code></span>. If enabled, the generic vertex attribute array is used when <a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawArrays.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glDrawArrays</a> or <a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glDrawElements</a> is called.</span></p></div><div class="refsect1" lang="en" style="line-height: 26px; font-family: 'Songti SC';"><span style="font-size:18px;"><a target=_blank target="_blank" id="notes" style="color: rgb(202, 0, 0);"></a></span><h2 style="margin: 0px; padding: 0px;"><span style="font-size:18px;"><a target=_blank name="t4" style="color: rgb(202, 0, 0);"></a>Notes</span></h2><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;">Each generic vertex attribute array is initially disabled and isn't accessed when <a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glDrawElements</a> or <a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawArrays.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glDrawArrays</a> is called.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><code class="function">glVertexAttribPointer</code> is typically implemented on the client side.</span></p></div><div class="refsect1" lang="en" style="line-height: 26px; font-family: 'Songti SC';"><span style="font-size:18px;"><a target=_blank target="_blank" id="errors" style="color: rgb(202, 0, 0);"></a></span><h2 style="margin: 0px; padding: 0px;"><span style="font-size:18px;"><a target=_blank name="t5" style="color: rgb(202, 0, 0);"></a>Errors</span></h2><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><code class="constant">GL_INVALID_ENUM</code> is generated if <span class="parameter" style="font-style: italic;"><code>type</code></span> is not an accepted value.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><code class="constant">GL_INVALID_VALUE</code> is generated if <span class="parameter" style="font-style: italic;"><code>index</code></span> is greater than or equal to <code class="constant">GL_MAX_VERTEX_ATTRIBS</code>.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><code class="constant">GL_INVALID_VALUE</code> is generated if <span class="parameter" style="font-style: italic;"><code>size</code></span> is not 1, 2, 3, or 4.</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><code class="constant">GL_INVALID_VALUE</code> is generated if <span class="parameter" style="font-style: italic;"><code>stride</code></span> is negative.</span></p></div><div class="refsect1" lang="en" style="line-height: 26px; font-family: 'Songti SC';"><span style="font-size:18px;"><a target=_blank target="_blank" id="associatedgets" style="color: rgb(202, 0, 0);"></a></span><h2 style="margin: 0px; padding: 0px;"><span style="font-size:18px;"><a target=_blank name="t6" style="color: rgb(202, 0, 0);"></a>Associated Gets</span></h2><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGet</a> with argument <code class="constant">GL_MAX_VERTEX_ATTRIBS</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetVertexAttrib.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGetVertexAttrib</a> with arguments <span class="parameter" style="font-style: italic;"><code>index</code></span> and <code class="constant">GL_VERTEX_ATTRIB_ARRAY_ENABLED</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetVertexAttrib.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGetVertexAttrib</a> with arguments <span class="parameter" style="font-style: italic;"><code>index</code></span> and <code class="constant">GL_VERTEX_ATTRIB_ARRAY_SIZE</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetVertexAttrib.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGetVertexAttrib</a> with arguments <span class="parameter" style="font-style: italic;"><code>index</code></span> and <code class="constant">GL_VERTEX_ATTRIB_ARRAY_TYPE</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetVertexAttrib.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGetVertexAttrib</a> with arguments <span class="parameter" style="font-style: italic;"><code>index</code></span> and <code class="constant">GL_VERTEX_ATTRIB_ARRAY_NORMALIZED</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetVertexAttrib.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGetVertexAttrib</a> with arguments <span class="parameter" style="font-style: italic;"><code>index</code></span> and <code class="constant">GL_VERTEX_ATTRIB_ARRAY_STRIDE</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetVertexAttrib.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGetVertexAttrib</a> with arguments <span class="parameter" style="font-style: italic;"><code>index</code></span> and <code class="constant">GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGet</a> with argument <code class="constant">GL_ARRAY_BUFFER_BINDING</code></span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span style="font-size:18px;"><a target=_blank target="_blank" class="citerefentry" href="http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetVertexAttribPointerv.xml" style="color: rgb(202, 0, 0); text-decoration: none;">glGetVertexAttribPointerv</a> with arguments <span class="parameter" style="font-style: italic;"><code>index</code></span> and <code class="constant">GL_VERTEX_ATTRIB_ARRAY_POINTER</code></span></p></div>
<div class="cnblogs_code" style="margin: 0px; padding: 5px; color: rgb(51, 51, 51); font-family: 微软雅黑, 'Microsoft YaHei', 宋体, 'Segoe UI', Tahoma, Arial; font-size: 13px; line-height: 16.9px; border: 1px solid rgb(204, 204, 204); background-color: rgb(245, 245, 245);"><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 255);">void</span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 0);"> InitializeVertexBuffer() { glGenBuffers(</span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(128, 0, 128);">1</span>, &<span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 0);">vertexBufferObject); glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); glBufferData(GL_ARRAY_BUFFER, </span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 255);">sizeof</span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 0);">(vertexData), vertexData, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, </span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(128, 0, 128);">0</span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 0);">); glGenBuffers(</span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(128, 0, 128);">1</span>, &<span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 0);">indexBufferObject); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject); glBufferData(GL_ELEMENT_ARRAY_BUFFER, </span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 255);">sizeof</span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 0);">(indexData), indexData, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, </span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(128, 0, 128);">0</span><span style="margin: 0px; padding: 0px; line-height: 15.6px; color: rgb(0, 0, 0);">); }</span>
void InitializeVertexArrayObjects() { glGenVertexArrays(1, &vaoObject1); glBindVertexArray(vaoObject1); size_t colorDataOffset = sizeof(float) * 3 * numberOfVertices; glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject); glBindVertexArray(0); glGenVertexArrays(1, &vaoObject2); glBindVertexArray(vaoObject2); size_t posDataOffset = sizeof(float) * 3 * (numberOfVertices/2); colorDataOffset += sizeof(float) * 4 * (numberOfVertices/2); //Use the same buffer object previously bound to GL_ARRAY_BUFFER. glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)posDataOffset); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)colorDataOffset); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject); glBindVertexArray(0); }
Draw:
glBindVertexArray(vaoObject1); glUniform3f(offsetUniform, 0.0f, 0.0f, 0.0f); glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0); glBindVertexArray(vaoObject2); glUniform3f(offsetUniform, 0.0f, 0.0f, -1.0f); glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0); glBindVertexArray(0);
例子:
#include <stdlib.h> #include <stdio.h> /* Ensure we are using opengl's core profile only */ #define GL3_PROTOTYPES 1 #include <GL3/gl3.h> #include <SDL.h> #define PROGRAM_NAME "Tutorial2" /* A simple function that will read a file into an allocated char pointer buffer */ char* filetobuf(char *file) { FILE *fptr; long length; char *buf; fptr = fopen(file, "rb"); /* Open file for reading */ if (!fptr) /* Return NULL on failure */ return NULL; fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */ length = ftell(fptr); /* Find out how many bytes into the file we are */ buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */ fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */ fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */ fclose(fptr); /* Close the file */ buf[length] = 0; /* Null terminator */ return buf; /* Return the buffer */ } /* A simple function that prints a message, the error code returned by SDL, and quits the application */ void sdldie(char *msg) { printf("%s: %s\n", msg, SDL_GetError()); SDL_Quit(); exit(1); } void setupwindow(SDL_WindowID *window, SDL_GLContext *context) { if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */ sdldie("Unable to initialize SDL"); /* Or die on error */ /* Request an opengl 3.2 context. * SDL doesn't have the ability to choose which profile at this time of writing, * but it should default to the core profile */ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); /* Turn on double buffering with a 24bit Z buffer. * You may need to change this to 16 or 32 for your system */ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); /* Create our window centered at 512x512 resolution */ *window = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); if (!*window) /* Die if creation failed */ sdldie("Unable to create window"); /* Create our opengl context and attach it to our window */ *context = SDL_GL_CreateContext(*window); /* This makes our buffer swap syncronized with the monitor's vertical refresh */ SDL_GL_SetSwapInterval(1); } void drawscene(SDL_WindowID window) { int i; /* Simple iterator */ GLuint vao, vbo[2]; /* Create handles for our Vertex Array Object and two Vertex Buffer Objects */ int IsCompiled_VS, IsCompiled_FS; int IsLinked; int maxLength; char *vertexInfoLog; char *fragmentInfoLog; char *shaderProgramInfoLog; /* We're going to create a simple diamond made from lines */ const GLfloat diamond[4][2] = { { 0.0, 1.0 }, /* Top point */ | { 1.0, 0.0 }, /* Right point */ | { 0.0, -1.0 }, /* Bottom point */ { -1.0, 0.0 } }; /* Left point */ const GLfloat colors[4][3] = { { 1.0, 0.0, 0.0 }, /* Red */ { 0.0, 1.0, 0.0 }, /* Green */ { 0.0, 0.0, 1.0 }, /* Blue */ { 1.0, 1.0, 1.0 } }; /* White */ /* These pointers will receive the contents of our shader source code files */ GLchar *vertexsource, *fragmentsource; /* These are handles used to reference the shaders */ GLuint vertexshader, fragmentshader; /* This is a handle to the shader program */ GLuint shaderprogram; /* Allocate and assign a Vertex Array Object to our handle */ glGenVertexArrays(1, &vao); /* Bind our Vertex Array Object as the current used object */ glBindVertexArray(vao); /* Allocate and assign two Vertex Buffer Objects to our handle */ glGenBuffers(2, vbo); /* Bind our first VBO as being the active buffer and storing vertex attributes (coordinates) */ glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); /* Copy the vertex data from diamond to our buffer */ /* 8 * sizeof(GLfloat) is the size of the diamond array, since it contains 8 GLfloat values */ glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW); /* Specify that our coordinate data is going into attribute index 0, and contains two floats per vertex */ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); /* Enable attribute index 0 as being used */ glEnableVertexAttribArray(0); /* Bind our second VBO as being the active buffer and storing vertex attributes (colors) */ glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); /* Copy the color data from colors to our buffer */ /* 12 * sizeof(GLfloat) is the size of the colors array, since it contains 12 GLfloat values */ glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), colors, GL_STATIC_DRAW); /* Specify that our color data is going into attribute index 1, and contains three floats per vertex */ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0); /* Enable attribute index 1 as being used */ glEnableVertexAttribArray(1); /* Read our shaders into the appropriate buffers */ vertexsource = filetobuf("tutorial2.vert"); fragmentsource = filetobuf("tutorial2.frag"); /* Create an empty vertex shader handle */ vertexshader = glCreateShader(GL_VERTEX_SHADER); /* Send the vertex shader source code to GL */ /* Note that the source code is NULL character terminated. */ /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */ glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0); /* Compile the vertex shader */ glCompileShader(vertexshader); glGetShaderiv(vertexshader, GL_COMPILE_STATUS, &IsCompiled_VS); if(IsCompiled_VS == FALSE) { glGetShaderiv(vertexshader, GL_INFO_LOG_LENGTH, &maxLength); /* The maxLength includes the NULL character */ vertexInfoLog = (char *)malloc(maxLength); glGetShaderInfoLog(vertexshader, maxLength, &maxLength, vertexInfoLog); /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */ /* In this simple program, we'll just leave */ free(vertexInfoLog); return; } /* Create an empty fragment shader handle */ fragmentshader = glCreateShader(GL_FRAGMENT_SHADER); /* Send the fragment shader source code to GL */ /* Note that the source code is NULL character terminated. */ /* GL will automatically detect that therefore the length info can be 0 in this case (the last parameter) */ glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0); /* Compile the fragment shader */ glCompileShader(fragmentshader); glGetShaderiv(fragmentshader, GL_COMPILE_STATUS, &IsCompiled_FS); if(IsCompiled_FS == FALSE) { glGetShaderiv(fragmentshader, GL_INFO_LOG_LENGTH, &maxLength); /* The maxLength includes the NULL character */ fragmentInfoLog = (char *)malloc(maxLength); glGetShaderInfoLog(fragmentshader, maxLength, &maxLength, fragmentInfoLog); /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */ /* In this simple program, we'll just leave */ free(fragmentInfoLog); return; } /* If we reached this point it means the vertex and fragment shaders compiled and are syntax error free. */ /* We must link them together to make a GL shader program */ /* GL shader programs are monolithic. It is a single piece made of 1 vertex shader and 1 fragment shader. */ /* Assign our program handle a "name" */ shaderprogram = glCreateProgram(); /* Attach our shaders to our program */ glAttachShader(shaderprogram, vertexshader); glAttachShader(shaderprogram, fragmentshader); /* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */ /* Attribute locations must be setup before calling glLinkProgram. */ glBindAttribLocation(shaderprogram, 0, "in_Position"); glBindAttribLocation(shaderprogram, 1, "in_Color"); /* Link our program */ /* At this stage, the vertex and fragment programs are inspected, optimized and a binary code is generated for the shader. */ /* The binary code is uploaded to the GPU, if there is no error. */ glLinkProgram(shaderprogram); /* Again, we must check and make sure that it linked. If it fails, it would mean either there is a mismatch between the vertex */ /* and fragment shaders. It might be that you have surpassed your GPU's abilities. Perhaps too many ALU operations or */ /* too many texel fetch instructions or too many interpolators or dynamic loops. */ glGetProgramiv(shaderprogram, GL_LINK_STATUS, (int *)&IsLinked); if(IsLinked == FALSE) { /* Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. */ glGetProgramiv(shaderprogram, GL_INFO_LOG_LENGTH, &maxLength); /* The maxLength includes the NULL character */ shaderProgramInfoLog = (char *)malloc(maxLength); /* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */ glGetProgramInfoLog(shaderprogram, maxLength, &maxLength, shaderProgramInfoLog); /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */ /* In this simple program, we'll just leave */ free(shaderProgramInfoLog); return; } /* Load the shader into the rendering pipeline */ glUseProgram(shaderprogram); /* Loop our display increasing the number of shown vertexes each time. * Start with 2 vertexes (a line) and increase to 3 (a triangle) and 4 (a diamond) */ for (i=2; i <= 4; i++) { /* Make our background black */ glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); /* Invoke glDrawArrays telling that our data is a line loop and we want to draw 2-4 vertexes */ glDrawArrays(GL_LINE_LOOP, 0, i); /* Swap our buffers to make our changes visible */ SDL_GL_SwapWindow(window); /* Sleep for 2 seconds */ SDL_Delay(2000); } /* Cleanup all the things we bound and allocated */ glUseProgram(0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDetachShader(shaderprogram, vertexshader); glDetachShader(shaderprogram, fragmentshader); glDeleteProgram(shaderprogram); glDeleteShader(vertexshader); glDeleteShader(fragmentshader); glDeleteBuffers(2, vbo); glDeleteVertexArrays(1, &vao); free(vertexsource); free(fragmentsource); } void destroywindow(SDL_WindowID window, SDL_GLContext context) { SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); } /* Our program's entry point */ int main(int argc, char *argv[]) { SDL_WindowID mainwindow; /* Our window handle */ SDL_GLContext maincontext; /* Our opengl context handle */ /* Create our window, opengl context, etc... */ setupwindow(&mainwindow, &maincontext); /* Call our function that performs opengl operations */ drawscene(mainwindow); /* Delete our opengl context, destroy our window, and shutdown SDL */ destroywindow(mainwindow, maincontext); return 0; }