OpenGL顶点数组及VBO扩展用法详解

 OpenGL1.0提供了一系列绘制场景的函数,如设置顶点数组,设置颜色,法向量,贴图坐标.这些函数有极大的灵活性,但其缺点也是显而易见的,对于较大场景,需要多次调用这些函数,对效率影响很大.OpenGL后来版本提供了6个用于指定顶点数组的函数.它们是

glVertexPointer();

glNormalPointer();

glColorPointer();

glIndexPointer();

glTexCoordPointer();

glEdgeFlagPointer();

使用前要调用使能函数打开这些状态,使用顶点数组时有一点要注意,打开的数组一定要使用,并且对其指针的设置要正确,不然会导导致程序无法运行

glEnableClientState( enum_value );

enum_value可以是

GL_VERTEX_ARRAY

GL_NORMAL_ARRAY

GL_COLOR_ARRAY

GL_INDEX_ARRAY

GL_TEXTURE_COORD_ARRAY

GL_EDGE_FLAG_ARRAY

 

下面介绍

void glArrayElement();

void glDrawArrays();

void glDrawElements();

的用法及区别:

对于每一个点都可以看作一个绘制单元glArrayElement( i )把第 i 个绘制单元的点放入缓存进行绘制

glBegin( GL_TRANGLES );

for( int i = 0; i<VERTEX_NUM; ++i )

    glArrayElement( i );

glEnd();

 

glDrawArrays( enum mode, int first, sizei count )对从first开始的count个单元分别调用glArrayElement();缺点是不支持顶点索引

 

glDrawElements()支持顶点索引

 

 

下面介绍VBO的用法

VBO是vertex buffer object的缩写,OpenGL支持直接数数据放进显存,从而大大提高渲染速度,但并非所有显卡都支持VBO,故在使用VBO之前必须查询显卡是否支持:

int isGLExtensionSupported(const char *extension)
{
 const GLubyte *extensions = NULL;
 const GLubyte *start;
 GLubyte *where, *terminator;

 /* Extension names should not have spaces. */
 where = (GLubyte *) strchr(extension, ' ');
 if (where || *extension == '/0')
  return 0;

 /* It takes a bit of care to be fool-proof about parsing the
 OpenGL extensions string. Don't be fooled by sub-strings,
 etc. */
 extensions = glGetString(GL_EXTENSIONS);
 start = extensions;
 for (;;)
 {
  where = ( GLubyte* ) strstr( (const char *) start, extension );
  if ( !where ) break;

  terminator = where + strlen(extension);
  if ( (where == start || *(where - 1) == ' ') && (*terminator == ' ' || *terminator == '/0') )
    return 1;
  start = terminator;
 }

 return 0;
}

使用VBO查询字符串为

isVBOSupported = isGLExtensionSupported( "GL_ARB_vertex_buffer_object" )

返回1为支持.

 

下面声明VBO扩展函数

// VBO Extension Function Pointers
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;     // VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;     // VBO Bind Procedure
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;     // VBO Data Loading Procedure
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;   // VBO Deletion Procedure

获取函数地址

if( g_fVBOSupported )
{
  // Get Pointers To The GL Functions
  glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) wglGetProcAddress("glGenBuffersARB");
  glBindBufferARB = (PFNGLBINDBUFFERARBPROC) wglGetProcAddress("glBindBufferARB");
  glBufferDataARB = (PFNGLBUFFERDATAARBPROC) wglGetProcAddress("glBufferDataARB");
  glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) wglGetProcAddress("glDeleteBuffersARB");
}

 

至此,就可以使用VBO函数了,

 

glGenBuffersARB( 1, &m_nVBOVertices );       // Get A Valid Name


 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBOVertices );   // Bind The Buffer


 // Load The Data
 glBufferDataARB( GL_ARRAY_BUFFER_ARB, m_nVertexCount*3*sizeof(float), m_pVertices, GL_STATIC_DRAW_ARB );

 

 // Generate And Bind The Texture Coordinate Buffer
 glGenBuffersARB( 1, &m_nVBOTexCoords );       // Get A Valid Name


 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBOTexCoords );  // Bind The Buffer


 // Load The Data
 glBufferDataARB( GL_ARRAY_BUFFER_ARB, m_nVertexCount*2*sizeof(float), m_pTexCoords, GL_STATIC_DRAW_ARB );

 

 // Our Copy Of The Data Is No Longer Necessary, It Is Safe In The Graphics Card
 delete [] m_pVertices; m_pVertices = NULL;
 delete [] m_pTexCoords; m_pTexCoords = NULL;

 

渲染阶段代码如下:

// Enable Pointers
 glEnableClientState( GL_VERTEX_ARRAY );      // Enable Vertex Arrays
 glEnableClientState( GL_TEXTURE_COORD_ARRAY );    // Enable Texture Coord Arrays

 

 // Set Pointers To Our Data
 if( isVBOSupported )
 {
  glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBOVertices );

    // Set The Vertex Pointer To The Vertex Buffer

    // 这里必须将后面那个指针设为 NULL
  glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL );  


  glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nVBOTexCoords );

    // Set The TexCoord Pointer To The TexCoord Buffer

    // 这里必须将后面那个指针设为 NULL
  glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL );  
 }
 else
 {
  glVertexPointer( 3, GL_FLOAT, 0, g_pMesh->m_pVertices ); // Set The Vertex Pointer To Our Vertex Data
  glTexCoordPointer( 2, GL_FLOAT, 0, g_pMesh->m_pTexCoords ); // Set The Vertex Pointer To Our TexCoord Data
 }

 // Render

 //渲染,如果使用索引,则调用glDrawElements(...);
 glDrawArrays( GL_TRIANGLES, 0, g_pMesh->m_nVertexCount ); // Draw All Of The Triangles At Once

 

 // Disable Pointers
 glDisableClientState( GL_VERTEX_ARRAY );     // Disable Vertex Arrays
 glDisableClientState( GL_TEXTURE_COORD_ARRAY );    // Disable Texture Coord Arrays

 

最后,当场景数据不再需要时,一定要记着释放显存中的数据

unsigned int nBuffers[2] = { m_nVBOVertices, m_nVBOTexCoords };
glDeleteBuffersARB( 2, nBuffers );      // Free The Memory

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值