VA、VAO和VBO API备忘

来源:互联网 发布:毛笔字 知乎 编辑:程序博客网 时间:2024/05/22 15:50

  • 缘起

接触OpenGL有一段时间了,大多数时候都是使用OSG在进行开发,前几天同事问起OpenGL中VBO的相关内容,才发现很多OpenGL的知识生疏了。这两天花了点时间重新复习了一下与VBO相关的内容,记录在此以备忘。文中大部分内容来自网络。

  • 概述

OpenGL从OpenGL 3.0开始将API分成了两种类型:即旧式的OpenGL(Legacy OpenGL)和新式的OpenGL(Core Profile),OpenGL3.3 的官方API文档完整地描述了新式的OpenGL API,旧式的OpenGL API可以在OpenGL 2.1中查看。

对于OpenGL渲染的的第一站:也就是把顶点数据(包括顶点位置、顶点法线、顶点颜色、纹理坐标等)传入到OpenGL,旧式的OpenGL中有以下几种方式实现:

  1. 立即模式(glBegin/glEnd) 这种方式恐怕是学习OpenGL最早接触到的API吧,至少我是这样。不过很遗憾它已经被新式OpenGL抛弃了
  2. 顶点数组(VA:Vertex Array)相比立即模式减少了函数的调用开销。目前也被新式OpenGL抛弃
  3. 缓冲区对象(VBO:Vertex Buffer Object)相比较VA,将数据存储到服务器端(VA存储在客户端)。目前是新式OpenGL支持的唯一数据传入方式
  4. 显示列表(Display List)将若干条OpenGL命令编译好,直接由显卡调用。由于编译好的模块无法修改,丧失了灵活性。也被新式OpenGL抛弃

此外VBO在Legacy OpenGL中和Core Profile OpenGL中的使用也有着不同的方式。

  • VA API

(1) 开启和关闭VA

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //开启和关闭客户端状态  
  2. void glEnableClientState(GLenum cap);  
  3. void glDisableClientState(GLenum cap);  
  4.   
  5. //参数cap取值  
  6. GL_VERTEX_ARRAY                 //顶点位置        
  7. GL_COLOR_ARRAY                  //顶点颜色  
  8. GL_EDGE_FLAG_ARRAY              //顶点边界线标识  
  9. GL_FOG_COORD_ARRAY              //顶点雾坐标  
  10. GL_INDEX_ARRAY                  //顶点索引  
  11. GL_NORMAL_ARRAY                 //顶点法线  
  12. GL_SECONDARY_COLOR_ARRAY            //顶点辅助颜色  
  13. GL_TEXTURE_COORD_ARRAY              //顶点纹理坐标  

(2) 设置数据到顶点

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //////////////////////////////////////////////////////////////////////////  
  2. //以下是一系列设置顶点数据的API  
  3. //参数取值(默认形参代表OpenGL中默认值):  
  4. // size   描述数据的维度(2D\3D)   
  5. // type   描述每个数据的类型   
  6. // stride 描述每个顶点数据的跨度  
  7. //pointer 指向实际数据  
  8.   
  9.   
  10. //设置顶点位置数据  
  11. void glVertexPointer( GLint size=4,  GLenum type=GL_FLOAT,  GLsizei stride=0,  const GLvoid *pointer=0);   
  12. //设置顶点颜色数据  
  13. void glColorPointer( GLint size=4,  GLenum type=GL_FLOAT,  GLsizei stride=0,  const GLvoid *pointer=0);   
  14. //设置顶点边界线标识数据  
  15. void glEdgeFlagPointer( GLsizei stride=0,  const GLvoid *pointer=0);   
  16. //设置顶点雾坐标数据  
  17. void glFogCoordPointer( GLenum type=GL_FLOAT, GLsizei stride=0,  GLvoid *pointer=0);   
  18. //设置顶点索引数据  
  19. void glIndexPointer( GLenum type=GL_FLOAT,  GLsizei stride=0,  const GLvoid *pointer=0);   
  20. //设置顶点法线数据  
  21. void glNormalPointer( GLenum type=GL_FLOAT,  GLsizei stride=0,  const GLvoid *pointer=0);   
  22. //设置顶点辅助颜色数据  
  23. void glSecondaryColorPointer( GLint size=3,  GLenum type=GL_FLOAT,  GLsizei stride=0,  const GLvoid *pointer=0);   
  24. //设置顶点纹理坐标数据  
  25. void glTexCoordPointer( GLint size=4,  GLenum type=GL_FLOAT,  GLsizei stride=0,  const GLvoid *pointer=0);   

(3) VA绘制

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  2. //通过设置好的顶点数据进行绘制:可以使用下列API进行绘制  
  3.   
  4. void glDrawArrays( GLenum mode,  GLint first,  GLsizei count);  
  5. //参数描述  
  6. //mode    绘制几何图元类型(GL_POINTS, GL_LINE_STRIP, GL_TRIANGLE等)  
  7. //first      顶点数据的开始索引位置(对应(2)中pointer)  
  8. //count    需要渲染的顶点数据数量  
  9.   
  10. void glDrawElements( GLenum mode,  GLsizei count,  GLenum type,  const GLvoid *indices);   
  11. //参数描述  
  12. //mode     绘制几何图元类型(GL_POINTS, GL_LINE_STRIP, GL_TRIANGLE等)  
  13. //count     第四个参数indices中参与渲染的索引数量  
  14. //type       第四个参数indices的数据类型  
  15. //indices  需要额外传入的一个索引数组指针  
  16.   
  17. void glDrawRangeElements( GLenum mode, GLuint start,  GLuint end,  GLsizei count,  GLenum type,  const GLvoid * indices);  
  18. //参数描述(与glDrawElements一致但多出两个参数)  
  19. //mode     绘制几何图元类型(GL_POINTS, GL_LINE_STRIP, GL_TRIANGLE等)  
  20. //count     第四个参数indices中参与渲染的索引数量  
  21. //type       第四个参数indices的数据类型  
  22. //indices  需要额外传入的一个索引数组指针  
  23. //start       索引数组indices中的最小值索引值  
  24. //end        索引数组indices中的最大值索引值  

以上就是VA所涉及到的基本API,使用过程如下

首先开启客户端VertexArray状态,接着绑定数据到顶点状态,最后进行绘制:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static float vertices[][3] = {  
  2.     1.0f, 0.0f, 0.0f,  
  3.     0.0f, 1.0f, 0.0f,  
  4.     -1.0f, 0.0f, 0.0f  
  5. };  
  6.   
  7. static float colors[][4] = {  
  8.     1.0f, 0.0f, 0.0f, 1.0f,  
  9.     0.0f, 1.0f, 0.0f, 1.0f,  
  10.     0.0f, 0.0f, 1.0f, 1.0f  
  11. };  
  12.   
  13. //绘制函数  
  14. void renderScene()  
  15. {  
  16.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  17.   
  18.     glMatrixMode(GL_MODELVIEW);  
  19.     glLoadIdentity();  
  20.     glTranslatef(0.0f, 0.0f, -5.0f);  
  21.       
  22.     //////////////////////////////////////////////////////////////////////////  
  23.     //开启VA状态  
  24.     glEnableClientState(GL_VERTEX_ARRAY);  
  25.     glEnableClientState(GL_COLOR_ARRAY);  
  26.     //绑定数据  
  27.     glVertexPointer(3, GL_FLOAT, 0, vertices);  
  28.     glColorPointer(4, GL_FLOAT, 0, colors);  
  29.     //绘制  
  30.     glDrawArrays(GL_TRIANGLES, 0, 3);  
  31.     //关闭VA状态  
  32.     glDisableClientState(GL_VERTEX_ARRAY);  
  33.     glDisableClientState(GL_COLOR_ARRAY);  
  34.     //////////////////////////////////////////////////////////////////////////  
  35. }     

  • VBO API

前文描述了VBO在Legacy 和Core Profile中有两种不同的方式:

  • Legacy OpenGL VBO API

(1)创建(初始化)VBO对象

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //创建VBO的API  
  2. //////////////////////////////////////////////////////////////////////////  
  3. void glGenBuffers( GLsizei   n, GLuint *   buffers);   
  4. //生成缓冲区ID  
  5. //参数描述  
  6. // n            生成ID数量  
  7. // buffers 存储缓冲区ID的数组  
  8.   
  9. void glBindBuffer( GLenum   target,  GLuint   buffer);   
  10. //设置缓冲区为当前操作的缓冲区,并且设置缓冲区的类型  
  11. //参数描述  
  12. //target            缓冲区类型(包括4种)  
  13. GL_ARRAY_BUFFER  
  14. GL_ELEMENT_ARRAY_BUFFER  
  15. GL_PIXEL_PACK_BUFFER  
  16. GL_PIXEL_UNPACK_BUFFER  
  17. //buffer        使用glGenBuffers生成的缓冲区ID  
  18.   
  19. void glBufferData( GLenum   target,  GLsizeiptr   size,  const GLvoid *   data,  GLenum   usage);   
  20. //为缓冲区设置数据  
  21. //参数描述  
  22. //target            缓冲区类型(包括4种)  
  23. GL_ARRAY_BUFFER  
  24. GL_ELEMENT_ARRAY_BUFFER  
  25. GL_PIXEL_PACK_BUFFER  
  26. GL_PIXEL_UNPACK_BUFFER  
  27. //size             缓冲区大小(多少字节)  
  28. //data         实际指向数组的指针  
  29. //usage        当前缓冲区的使用模式[一种提示用来优化之用](取值如下9种)  
  30. GL_STREAM_DRAW  
  31. GL_STREAM_READ  
  32. GL_STREAM_COPY  
  33. GL_STATIC_DRAW  
  34. GL_STATIC_READ  
  35. GL_STATIC_COPY  
  36. GL_DYNAMIC_DRAW  
  37. GL_DYNAMIC_READ  
  38. GL_DYNAMIC_COPY  
(2)开启/关闭VBO

当创建完VBO之后,我们并不知道VBO中存储的是顶点位置、还是顶点颜色或者是顶点法线,于是使用下面的API来描述某一个VBO中到底是顶点什么方面的数据

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //////////////////////////////////////////////////////////////////////////  
  2. //开启关闭VBO状态  
  3. void glEnableClientState(GLenum cap);  
  4. void glDisableClientState(GLenum cap);  
  5. //参考VA中的描述  
  6.   
  7.   
  8. void glVertexPointer( GLint   size,  GLenum   type,  GLsizei   stride,  const GLvoid *   pointer);   
  9. //参考VA中的描述:  
  10. //但是pointer参数有所区别:  
  11. //当使用了glBindBuffer将GL_ARRAY_BUFFER绑定到一个非0的VBO ID上之后,这时候的pointer  
  12. //代表的是一个VBO ID对象中实际数据(glBufferData中data参数)的偏移值,也就是说这时候pointer  
  13. //并不是一个指针,仅仅是一个偏移值。同时GL_ARRAY_BUFFER_BINDING这个状态会保存在客户端  
  14.   
  15. //综合上面VA中的解释:可以知道这个glVertexPointer中的pointer两种含义:  
  16. //(1)当glBindBuffer绑定到非0的ID时:  
  17. //pointer代表偏移,此时客户端glClientState中会保存GL_ARRAY_BUFFER_BINDING暗示现在在用VBO  
  18. //(2)当glBindBuffer绑定到0的ID时:  
  19. //pointer代表一个指向数组的指针,此时客户端glClientState中不会保存GL_ARRAY_BUFFER_BINDING暗示现在在用VA  
  20.   
  21. //同理,对于VA中用到的一系列函数都有同样的解释,不再赘述:  
  22. glColorPointer  
  23. glEdgeFlagPointer  
  24. glFogCoordPointer  
  25. glIndexPointer  
  26. glNormalPointer  
  27. glSecondaryColorPointer  
  28. glTexCoordPointer  
(3)VBO绘制
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //////////////////////////////////////////////////////////////////////////  
  2. //绘制VBO  
  3.   
  4. void glDrawArrays( GLenum mode,  GLint first,  GLsizei count);  
  5. //参考VA中描述  
  6. //所不同的是数据现在在缓冲区之中,而不是VA所指向的pointer数组中了  
  7.   
  8. void glDrawElements( GLenum mode,  GLsizei count,  GLenum type,  const GLvoid *indices);  
  9. //参考VA中描述  
  10. //所不同的是indices设置为NULL  
  11. //因为缓冲区类型有一种是GL_ELEMENT_ARRAY_BUFFER(查看glGenBuffers中类型描述)  
  12. //我们会把indices索引值存储在GL_ELEMENT_ARRAY_BUFFER类型的Buffer中,不需要额外的数组了  
  13. //直接用两个缓冲区即可  
以上便是旧式OpenGL中实现VBO的API,使用过程如下:

首先创建缓冲区并设置缓冲区类型和填满缓冲区,接着指定缓冲里面是什么(到底存的是位置还是颜色或者是法线),最后绘制

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static float vertices[][3] = {  
  2.     1.0f, 0.0f, 0.0f,  
  3.     0.0f, 1.0f, 0.0f,  
  4.     -1.0f, 0.0f, 0.0f  
  5. };  
  6.   
  7. static float colors[][4] = {  
  8.     1.0f, 0.0f, 0.0f, 1.0f,  
  9.     0.0f, 1.0f, 0.0f, 1.0f,  
  10.     0.0f, 0.0f, 1.0f, 1.0f  
  11. };  
  12.   
  13. void renderScene()  
  14. {  
  15.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  16.   
  17.     glMatrixMode(GL_MODELVIEW);  
  18.     glLoadIdentity();  
  19.     glTranslatef(0.0f, 0.0f, -5.0f);  
  20.       
  21.     //////////////////////////////////////////////////////////////////////////  
  22.     //创建VBO(一般放在初始化函数中)  
  23.     GLuint vertexBufferID, colorBufferID;  
  24.     glGenBuffers(1, &vertexBufferID);  
  25.     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);  
  26.     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  
  27.     glGenBuffers(1, &colorBufferID);  
  28.     glBindBuffer(GL_ARRAY_BUFFER, colorBufferID);  
  29.     glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);  
  30.   
  31.     //开启VBO模式并设置VBO该怎么解析  
  32.     glEnableClientState(GL_VERTEX_ARRAY);  
  33.     glEnableClientState(GL_COLOR_ARRAY);  
  34.     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);  
  35.     glVertexPointer(3, GL_FLOAT, 0, 0);  
  36.     glBindBuffer(GL_ARRAY_BUFFER, colorBufferID);  
  37.     glColorPointer(4, GL_FLOAT, 0, 0);  
  38.   
  39.     //绘制  
  40.     glDrawArrays(GL_TRIANGLES, 0, 3);  
  41.   
  42.     //绘制完成之后关闭VBO状态  
  43.     //将glBindBuffer设置为0,使得后续glVertexPointer类似函数起到VA的作用  
  44.     glDisableClientState(GL_VERTEX_ARRAY);  
  45.     glDisableClientState(GL_COLOR_ARRAY);  
  46.     glBindBuffer(GL_ARRAY_BUFFER, 0);  
  47.     //////////////////////////////////////////////////////////////////////////  
  48. }     

  • Core Profile VBO

(1)创建VBO

参考Legacy VBO中内容,二者是一样的

(2)开启/关闭VBO

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //////////////////////////////////////////////////////////////////////////  
  2. void glEnableVertexAttribArray( GLuint   index);   
  3. void glDisableVertexAttribArray( GLuint   index);   
  4. //开启和关闭一个通用的缓冲区对象  
  5. //参数描述  
  6. //index 缓冲区对象索引值  
  7.   
  8. void glVertexAttribPointer( GLuint   index,    
  9.                                               GLint            size,    
  10.                                               GLenum           type,    
  11.                                               GLboolean        normalized,    
  12.                                               GLsizei          stride,    
  13.                                               const GLvoid *   pointer  
  14.                                               );   
  15. //设置如何解析缓冲区中的数据  
  16. //参数描述  
  17. //index             当前操作的缓冲区对象索引值  
  18. //size              数据的维度是2D/3D/4D  
  19. //type              数据类型 GL_INT /GL_FLOAT  
  20. //normalized    是否已经单位化  
  21. //stride                数据间距  
  22. //pointer           参考Legacy VBO中解释(在glBindBuffer未开启时是指针开启后是索引值)  

(3)绘制

参考Legacy VBO中内容,二者是一样的

以上便是Core Profile 下的VBO,使用方式如下:

首先创建VBO对象,接着开启VBO并且用来说明VBO中数据是什么样组织的(但是并没有说明数据是顶点位置、顶点颜色还是法线),这一点与Legacy VBO不同,因为它的说明部分(哪个VBO存储着位置、哪个VBO存储着颜色、哪个VBO存储着法线等)是在着色语言Shader中指明的,最后还是使用同样的API绘制:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //////////////////////////////////////////////////////////////////////////  
  2. GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f,  
  3. 0.5f, 0.0f, 0.0f,  
  4. 0.0f, 0.5f, 0.0f };  
  5.   
  6. GLfloat vColors [] = { 1.0f, 0.0f, 0.0f, 1.0f,  
  7. 0.0f, 1.0f, 0.0f, 1.0f,  
  8. 0.0f, 0.0f, 1.0f, 1.0f };  
  9. //////////////////////////////////////////////////////////////////////////  
  10.   
  11. void RenderWidget::paintGL()  
  12. {  
  13.     //////////////////////////////////////////////////////////////////////////  
  14.     //生成VBO  
  15.     glGenBuffers(1, &_vertexBuffer);  
  16.     glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);  
  17.     glBufferData(GL_ARRAY_BUFFER, sizeof(vVerts), vVerts, GL_STATIC_DRAW);  
  18.   
  19.     glGenBuffers(1, &_colorBuffer);  
  20.     glBindBuffer(GL_ARRAY_BUFFER, _colorBuffer);  
  21.     glBufferData(GL_ARRAY_BUFFER, sizeof(vColors), vColors, GL_STATIC_DRAW);  
  22.   
  23.     setShaders();  
  24.   
  25.     //开启VBO并设置VBO里面存储的数据模式  
  26.     glEnableVertexAttribArray(0);  
  27.     glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);  
  28.     glVertexAttribPointer(  
  29.         0,  
  30.         3,  
  31.         GL_FLOAT,  
  32.         GL_FALSE,   
  33.         0,  
  34.         (void*)0  
  35.         );  
  36.     glEnableVertexAttribArray(1);  
  37.     glBindBuffer(GL_ARRAY_BUFFER, _colorBuffer);  
  38.     glVertexAttribPointer(  
  39.         1,  
  40.         4,  
  41.         GL_FLOAT,  
  42.         GL_FALSE,  
  43.         0,  
  44.         (void*)0  
  45.         );  
  46.   
  47.     //绘制VBO  
  48.     glDrawArrays(GL_TRIANGLES, 0, 3);  
  49.   
  50.     //关闭VBO  
  51.     glDisableVertexAttribArray(1);  
  52.     glDisableVertexAttribArray(0);  
  53.     glBindBuffer(GL_ARRAY_BUFFER, 0);  
  54. }  
Shader部分

顶点Shader

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #version 330  
  2. layout(location = 0) in vec4 vertex;  
  3. layout(location = 1) in vec4 color;  
  4. out vec4 inFragColor;  
  5.   
  6. void main( void )  
  7. {  
  8.     gl_Position = vertex;  
  9.     inFragColor = color;  
  10. }  
片元Shader

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #version 330  
  2. in vec4 inFragColor;  
  3. out vec4 outFragColor;  
  4.   
  5. void main( void )  
  6. {  
  7.     outFragColor = inFragColor;  
  8. }  

通过顶点Shader可以知道索引值为0的VBO解释为顶点位置,它传给gl_Position,索引值为1的VBO解释为顶点的颜色

  • VAO API

VAO的介绍可以参考 <<AB是一家?VAO与VBO>> 

(1)初始化

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //////////////////////////////////////////////////////////////////////////  
  2. //初始化VAO  
  3.   
  4. void glGenVertexArrays(GLsizei n,  GLuint *arrays);  
  5. //创建VAO ID  
  6. //参数描述  
  7. //n                 产生VAO ID的数量  
  8. //arrays                    保存VAO ID的数组  
  9.   
  10. void glBindVertexArray(GLuint array);  
  11. //设置当前操作的VAO对象  
  12. //参数描述  
  13. //array              VAO的ID  

(2)开启/关闭VAO

VAO的开启当使用glBindVertexArray时自动开启,使用glBindVertexArray(0),传入一个0值可以视为将VAO关闭

设置VAO的过程就是调用VBO中(2)的过程

(3) 绘制

同VBO中绘制(绘制之前先启用VAO)

以上就是VAO涉及到的API,使用过程如下:

首先创建VAO,接着设置VAO(在调用VBO的数据设置过程中VAO自动完成了设置),最后开启VAO并绘制:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //////////////////////////////////////////////////////////////////////////  
  2. GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f,  
  3. 0.5f, 0.0f, 0.0f,  
  4. 0.0f, 0.5f, 0.0f };  
  5.   
  6. GLfloat vColors [] = { 1.0f, 0.0f, 0.0f, 1.0f,  
  7. 0.0f, 1.0f, 0.0f, 1.0f,  
  8. 0.0f, 0.0f, 1.0f, 1.0f };  
  9. //////////////////////////////////////////////////////////////////////////  
  10.   
  11. void RenderWidget::paintGL()  
  12. {  
  13.     //////////////////////////////////////////////////////////////////////////  
  14.     //生成VBO  
  15.     glGenBuffers(1, &_vertexBuffer);  
  16.     glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);  
  17.     glBufferData(GL_ARRAY_BUFFER, sizeof(vVerts), vVerts, GL_STATIC_DRAW);  
  18.   
  19.     glGenBuffers(1, &_colorBuffer);  
  20.     glBindBuffer(GL_ARRAY_BUFFER, _colorBuffer);  
  21.     glBufferData(GL_ARRAY_BUFFER, sizeof(vColors), vColors, GL_STATIC_DRAW);  
  22.   
  23.     setShaders();  
  24.   
  25.       
  26.     //初始化VAO  
  27.     GLuint vaoBuffer;  
  28.     glGenVertexArrays(1, &vaoBuffer);  
  29.     glBindVertexArray(vaoBuffer);  
  30.   
  31.     //通过设置VBO里面存储的数据模式完成VAO设置  
  32.     glEnableVertexAttribArray(0);  
  33.     glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);  
  34.     glVertexAttribPointer(  
  35.         0,  
  36.         3,  
  37.         GL_FLOAT,  
  38.         GL_FALSE,   
  39.         0,  
  40.         (void*)0  
  41.         );  
  42.     glEnableVertexAttribArray(1);  
  43.     glBindBuffer(GL_ARRAY_BUFFER, _colorBuffer);  
  44.     glVertexAttribPointer(  
  45.         1,  
  46.         4,  
  47.         GL_FLOAT,  
  48.         GL_FALSE,  
  49.         0,  
  50.         (void*)0  
  51.         );  
  52.     glBindVertexArray(0);  
  53.     glBindBuffer(GL_ARRAY_BUFFER, 0);  
  54.   
  55.     //////////////////////////////////////////////////////////////////////////  
  56.     //上述所有的代码在初始化函数中调用  
  57.     //只有绘制代码在渲染函数中调用  
  58.     //使用VAO绘制  
  59.     glBindVertexArray(vaoBuffer);  
  60.     glDrawArrays(GL_TRIANGLES, 0, 3);  
  61.     glBindVertexArray(0);  
  62. }  


0 0
原创粉丝点击