OpenGL3.3教程-----First Triangle

来源:互联网 发布:南充行知小学 编辑:程序博客网 时间:2024/05/18 01:02
Vertex Buffer Object (VBO):顶点缓冲对象

你可能已经早就听过VBO了,它是学习OpenGL最重要的东西之一。VBO是存储在GPU Ram上的任意数据,他们可以快速被访问,故可加速渲染。VBO可以任何东西,关键是告知OpenGL如何解释它们。例如,可以用一个VBO来存储顶点数据(x,y,z)值,可以用VBO来存储顶点颜色值,纹理坐标值,顶点颜色值。如果有多个VBO,可以将它们存入VAO(顶点数组对象),那么就可以在所有对象之间快速切换了。

老版本的OpenGL 使用glBegin() 和 glEnd(),这会导致CPU的瓶颈,它的问题是必须把每个参数传给GPU。但是现在,我们仅是加载我们的对象数据(或者场景数据)到GPU里面,告诉OpenGL 如何解释它们,就可以开始渲染了。本例中,我们渲染一个三角形和一个四边形,不使用颜色。在 initScene中,我们设置顶点数据,然后用他们创建两个VBO.



float fTriangle[9]; // Data to render triangle (3 vertices, each has 3 floats)
float fQuad[12]; // Data to render quad using triangle strips (4 vertices, each has 3 floats)

UINT uiVBO[2]; 

void initScene(LPVOID lpParam) 

   glClearColor(0.0f, 0.5f, 1.0f, 1.0f); 

   // Setup triangle vertices
   fTriangle[0] = -0.4f; fTriangle[1] = 0.1f; fTriangle[2] = 0.0f; 
   fTriangle[3] = 0.4f; fTriangle[4] = 0.1f; fTriangle[5] = 0.0f; 
   fTriangle[6] = 0.0f; fTriangle[7] = 0.7f; fTriangle[8] = 0.0f; 
  
   // Setup quad vertices
  
   fQuad[0] = -0.2f; fQuad[1] = -0.1f; fQuad[2] = 0.0f; 
   fQuad[3] = -0.2f; fQuad[4] = -0.6f; fQuad[5] = 0.0f; 
   fQuad[6] = 0.2f; fQuad[7] = -0.1f; fQuad[8] = 0.0f; 
   fQuad[9] = 0.2f; fQuad[10] = -0.6f; fQuad[11] = 0.0f; 

   // Now we create two VBOs
   glGenBuffers(2, uiVBO); 
  
   glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]); 
   glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), fTriangle, GL_STATIC_DRAW); 

   glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]); 
   glBufferData(GL_ARRAY_BUFFER, 12*sizeof(float), fQuad, GL_STATIC_DRAW); 



glGenBuffers中,第一个参数是VBO的个数,第二参数指向存储数据的地方(本例中就是uiVBO中)。这样在uiVBO中,存储了两个缓冲区域的ID,使用这两个ID就可以读取修改这些缓冲区域。接着告诉OpenGL,调用glBindBuffer来使用第一块缓冲区域,第一个参数指向使用哪种的缓冲区域类型,第二参数缓冲区域 ID,接着调用glBufferData,将数据加载到GPU.第一个参数是缓冲区域类型,第二个是缓冲区域字节大小,第三个参数是客户端内存中源数据,最后一个参数告诉OpenGL缓冲数据的作用。本例中,我们不会改变数据,它们是静态的,所以我们设为GL_STATIC_DRAW,其他类型如GL_DYNAMIC_DRAW,GL_STREAM_DRAW ,OpenGL根据它们做一些性能优化。四边形我们也使用这两个函数,现在有了数据集了,下面看下渲染函数。


void renderScene(LPVOID lpParam) 

   // Typecast lpParam to COpenGLControl pointer
   COpenGLControl* oglControl = (COpenGLControl*)lpParam; 

   // We just clear color
   glClear(GL_COLOR_BUFFER_BIT); 

   glEnableVertexAttribArray(0); 
   // Triangle render
   glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]); 
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
   glDrawArrays(GL_TRIANGLES, 0, 3); 

   // Quad render using triangle strip
   glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]); 
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

   oglControl->swapBuffers(); 


第一个函数glVertexAttribPointer(),用它来设置顶点属性,如之前所讲,顶点有很多属性,如位置、颜色等(shaders中,可以告知OpenGL如何使用这些属性),第一个参数是顶点属性索引,本例中是0既是顶点位置,由于没使用shader,顶点在渲染管道里没有任何改变,进入管道前后的数值是一样的。注意的是我们没告知OpenGL属性索引0表示位置,这是默认的,所以函数的参数的顺序是:属性集的索引,每个顶点属性的元素个数(本例是3,位置包含了x,y,z三个值),数据类型,数据是否要归一化,属性之间的字节偏移(我们把数据紧凑放在内存中,故是0),最后一个参数是个指针,指向第一个元素。

效果图如下:


0 0