win32编程:Win32 OpenGL编程(5)顶点数组详细介绍

  需求

  按照前面已经讲过内容来说简单2D图形绘制已经没有问题了并且很多东西其实已经涉及到3D但是会发现复杂图形绘制时glBegin和 glEnd对中指定顶点会非常多glVertex开销会过大(虽然在C/C开销其实已经比较小)在3D图形绘制时此问题更加严重想想个 4边形4个顶点个 4方体就有8个顶点了但是按照我们目前描述平面方式来描述就是需要指定6 * 4 = 24个顶点这正是OpenGL作为高性能图像接口应该极力避免事情事实上OpenGL当然不会直要求我们用如此低效方式来完成任务我们有新高效工具——顶点事实上在强调高效和尽量减少APIOpenGL ES中甚至根本就没有glBeginglEnd和glVertex*等API

  顶点相对来说是OpenGL中用于提高效率手段不是核心概念(虽然OpenGL ES中完全以顶点绘制图元但是事实上OpenGL 1.1版中才加入了定点)顶点不能使我们绘制出以前以前绘制不了图元但是却实实在在提高了我们绘制图形效率但是事实上对于高性能图像处理来说提高效率是如此重要效率提升从本质上来说没有增加我们绘制更多图形能力(即不用提高效率手段也能绘制出相同图形)但是随着效率提高我们却能在同样机器上绘制更多图元那么意味着我们可以更加丰富和逼真地表现图像这不正是图形绘制所追求目标吗?

  概念

  有东西说简单就简单说复杂就复杂顶点概念如此简单如其名就是将原来由系列glVertex*指定顶点放在(其意思就是顶点数据组成)由顶点处理次性指定事实上不仅如此次性指定不仅仅是还可以是其他系列东西比如表面发现,RGBA 颜色辅助颜色等

  使用方式初步

  使用方式编程手段使用方式最佳讲解手段肯定是我们以个例子来讲解使用方式

  glVertexArray:

   1: //OpenGL化开始
   2: void SceneInit( w, h)
   3: {
   4:     glClearColor(0.0, 0.0, 0.0, 0.0);
   5:     // 启用顶点
   6:     glEnableClientState(GL_VERTEX_ARRAY);
   7:     
   8:     // 顶点数据
   9:      GLfloat fVertices = {    -0.5, -0.5,
  10:                                      0.5, -0.5,
  11:                                      0.5,  0.5,
  12:                                     -0.5,  0.5};
  13:  
  14:     glVertexPoer(2, GL_FLOAT, 0, fVertices);
  15: }
  16:  
  17: //这里进行所有绘图工作
  18: void SceneShow(GLvoid)        
  19: {
  20:     glClear(GL_COLOR_BUFFER_BIT);    // 清空颜色缓冲区
  21:     glColor4f(1.0, 1.0, 1.0, 1.0);
  22:  
  23:     glBegin(GL_QUADS);    
  24:     glArrayElement(0);
  25:     glArrayElement(1);
  26:     glArrayElement(2);
  27:     glArrayElement(3);
  28:     glEnd;
  29:  
  30:     // 上述和下面效果
  31:     //glBegin(GL_QUADS);    
  32:     //glVertex3f(-0.5, -0.5, 0.0);
  33:     //glVertex3f(0.5, -0.5, 0.0);
  34:     //glVertex3f(0.5, 0.5, 0.0);
  35:     //glVertex3f(-0.5, 0.5, 0.0);
  36:     //glEnd;
  37:  
  38:     glFlush;
  39: } 


  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2009-10-18\glVertexArray\ 目录获取方式见文章最后有关获取博客完整源代码介绍说明

  上述例子效果和以前SimpleRectangle效果完全请参考本OpenGL系列文章34(以下简称XO3,XO4^^)截图如以前

  分步骤介绍说明下上述源代码含义:

glEnableClientState(GL_VERTEX_ARRAY);

  用于表示启用顶点还可以搭配其他参数用于指定其他

  OpenGL Reference Manual:

glEnableClientState — enable or disable client-side capability  
void glEnableClientState(    GLenum      cap);  
Parameters:Species the capability to enable.  
                        Symbolic constants  
                        GL_COLOR_ARRAY,  
                        GL_EDGE_FLAG_ARRAY,  
                        GL_FOG_COORD_ARRAY,  
                        GL_INDEX_ARRAY,  
                        GL_NORMAL_ARRAY,  
                        GL_SECONDARY_COLOR_ARRAY,  
                        GL_TEXTURE_COORD_ARRAY, and  
                        GL_VERTEX_ARRAY  
                        are accepted.


  此例中仅仅使用了GL_VERTEX_ARRAY种使用方法

  glVertexPoer也是关键用于指定顶点数据

  OpenGL Reference Manual:

glVertexPoer —  an .gif' /> of vertex data  
C Specication  
void glVertexPoer(    GL      size,  
     GLenum      type,  
     GLsizei      stride,  
     const GLvoid *      poer);  
Parameters
size
                        Species the number of coordinates per vertex. Must be 2, 3, or  
                        4. The initial value is 4.  
type
                        Species the data type of each coordinate in the .gif' />.  
                        Symbolic constants  
                        GL_SHORT,  
                        GL_INT,  
                        GL_FLOAT,  
                        or GL_DOUBLE  
                        are accepted. The initial value is GL_FLOAT.  
stride
                        Species the  off between consecutive  
                        vertices. If stride is 0, the vertices are understood to be tightly packed in  
                        the .gif' />. The initial value  
                        is 0.  
poer
                        Species a poer to the first coordinate of the first vertex in the  
                        .gif' />. The initial value is 0.


  此例中数据以2个位类型都是GL_FLOAT,跨度为0表示数据紧密排列指针自然指向刚才分配顶点数据

  glArrayElement用于指定顶点具体顶点放在glBegin和glEnd的间产生glVertex*效果次指定个顶点

  OpenGL Reference Manual:

glArrayElement — render a vertex using the specied vertex .gif' /> element  
C Specication  
void glArrayElement(    GL      i);  
Parameters
i
                        Species an index o the enabled vertex data .gif' />s.


  上例中分别制定了0123共4个顶点和以前在SimpleRectangle中指定4个顶点注意取数据方式我们上面通过 glVertexPoer制定数据时候介绍说明了是2个数据(如同缩进所示)那么这里指定0123其实分别是从0,2,4,6个数据开始取每次取2个意思就是此处glArrayElement指定并不是顶点数据实际对应C语言索引而是按照 glVertexPoer指定分组分组后分组索引

  附带颜色使用

  上述内容就已经包含了定点核心内容但是我们无法发现使用顶点任何好处甚至发现更加复杂更多了-_-!下面通过个附带颜色例子加深理解顶点使用方式并可以发现此时其初步减少次数作用

   1: //OpenGL化开始
   2: void SceneInit( w, h)
   3: {
   4:     glClearColor(0.0, 0.0, 0.0, 0.0);
   5:     // 启用顶点
   6:     glEnableClientState(GL_VERTEX_ARRAY);
   7:  
   8:     // 颜色也需要启用
   9:     glEnableClientState(GL_COLOR_ARRAY);
  10:     
  11:     // 默认就是此参数可忽略为了明确介绍说明特意指定
  12:     glShadeModel(GL_SHADE_MODEL);
  13:  
  14:     // 顶点数据
  15:      GLfloat fVertices = {    -0.5, -0.5,
  16:                                      0.5, -0.5,
  17:                                      0.5,  0.5,
  18:                                     -0.5,  0.5};
  19:  
  20:     // 颜色
  21:      GLfloat fColor = { 1.0, 0.0, 0.0,
  22:                                 0.0, 1.0, 0.0,
  23:                                 0.0, 0.0, 1.0,
  24:                                 1.0, 1.0, 1.0};
  25:  
  26:     // 指定顶点数据
  27:     glVertexPoer(2, GL_FLOAT, 0, fVertices);
  28:  
  29:     // 制定颜色
  30:     glColorPoer(3, GL_FLOAT, 0, fColor);
  31:  
  32: }
  33:  
  34: //这里进行所有绘图工作
  35: void SceneShow(GLvoid)        
  36: {
  37:     glClear(GL_COLOR_BUFFER_BIT);    // 清空颜色缓冲区
  38:  
  39:     glPushMatrix;
  40:     glTranslatef(-0.5, 0, 0);
  41:     glBegin(GL_QUADS);    
  42:     glArrayElement(0);
  43:     glArrayElement(1);
  44:     glArrayElement(2);
  45:     glArrayElement(3);
  46:     glEnd;
  47:     glPopMatrix;
  48:  
  49:     // 上述和下面效果
  50:     glPushMatrix;
  51:     glTranslatef(0.5, 0.0, 0.0);
  52:     glBegin(GL_QUADS);    
  53:     glColor3f(1.0, 0.0, 0.0);
  54:     glVertex3f(-0.5, -0.5, 0.0);
  55:  
  56:     glColor3f(0.0, 1.0, 0.0);
  57:     glVertex3f(0.5, -0.5, 0.0);
  58:  
  59:     glColor3f(0.0, 0.0, 1.0);
  60:     glVertex3f(0.5, 0.5, 0.0);
  61:  
  62:     glColor3f(1.0, 1.0, 1.0);
  63:     glVertex3f(-0.5, 0.5, 0.0);
  64:     glEnd;
  65:     glPopMatrix;
  66:  
  67:     glFlush;
  68: }  


  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2009-10-18\glVertexArrayWithColor\ 目录获取方式见文章最后有关获取博客完整源代码介绍说明

  注释已经详细介绍说明了大部分新添内容意义此例子为加强对比将用顶点绘制图形移到了屏幕左侧而用glVertex*绘制图形放在了屏幕右侧同样效果在此例中由于glArrayElement同时指定了顶点和颜色已经显示出了节省作用何况顶点还可以同时指定辅助颜色法线向量雾坐标等等东西此举例运行效果如下图所示

  

  此例中首先需要介绍说明glMultiDrawElements是OpenGL 1.4版本引进而Windows仅仅实现了1.1所以在Windows下必须需要进行额外处理才能使用了我使用是glew库详细情况见 XO2其中详细介绍说明了如何获取Windows中缺失OpenGLglMultiDrawElements仅仅通过最后个参数(此例中为 4)表示指定4次glDrawElements其他参数和glDrawElements意义仅仅是第24参数变成形式这是种非常有意思又很容易理解和记忆参数排列方式也是值得

  序列顶点

  还是为了优化考虑在对于排好序顶点序列而言可以通过接口指明这点以允许OpenGL实现进优化OpenGL中对应为 glDrawArrays和glMultiDrawArrays分别于上述glDrawElements和glMultiDrawElements对应使用上由于有顶点按顺序这个优先条件在参数更加简单需在需要额外索引(前面例子中Indice类)只需要指明起点和数量就行

  OpenGL Reference Manual:

glDrawArrays — render primitives from .gif' /> data  
C Specication  
void glDrawArrays(    GLenum      mode,  
     GL      first,  
     GLsizei      count);  
Parameters
mode
                        Species what kind of primitives to render.  
                        Symbolic constants  
                        GL_POINTS,  
                        GL_LINE_STRIP,  
                        GL_LINE_LOOP,  
                        GL_LINES,  
                        GL_TRIANGLE_STRIP,  
                        GL_TRIANGLE_FAN,  
                        GL_TRIANGLES,  
                        GL_QUAD_STRIP,  
                        GL_QUADS,  
                        and GL_POLYGON are accepted.  
first
                        Species the starting index in the enabled .gif' />s.  
count
                        Species the number of indices to be rendered.
glMultiDrawArrays — render multiple s of primitives from .gif' /> data  
C Specication  
void glMultiDrawArrays(    GLenum      mode,  
     GL *      first,  
     GLsizei *      count,  
     GLsizei      primcount);  
Parameters
mode
                        Species what kind of primitives to render.  
                        Symbolic constants  
                        GL_POINTS,  
                        GL_LINE_STRIP,  
                        GL_LINE_LOOP,  
                        GL_LINES,  
                        GL_TRIANGLE_STRIP,  
                        GL_TRIANGLE_FAN,  
                        GL_TRIANGLES,  
                        GL_QUAD_STRIP,  
                        GL_QUADS,  
                        and GL_POLYGON are accepted.  
first
                        Pos to an .gif' /> of starting indices in the enabled .gif' />s.  
count
                        Pos to an .gif' /> of the number of indices to be rendered.  
primcount
                        Species the size of the first and count


  下面是个例子

   1: //OpenGL化开始
   2: void SceneInit( w, h)
   3: {
   4:     GLenum err = glewInit;
   5:     (err != GLEW_OK)
   6:     {
   7:         MessageBox(NULL, _T("Error"), _T("Glew init failed."), MB_OK);
   8:         exit(-1);
   9:     }
  10:  
  11:     glClearColor(0.0, 0.0, 0.0, 0.0);
  12:     // 启用顶点
  13:     glEnableClientState(GL_VERTEX_ARRAY);
  14:  
  15:     // 颜色也需要启用
  16:     glEnableClientState(GL_COLOR_ARRAY);
  17:     
  18:     // 默认就是此参数可忽略为了明确介绍说明特意指定
  19:     glShadeModel(GL_SHADE_MODEL);
  20:  
  21:     // 顶点数据
  22:      GLfloat fVertices = {    -0.5, -0.5,
  23:                                      0.5, -0.5,
  24:                                      0.5,  0.5,
  25:                                     -0.5,  0.5,
  26:                                      0.0,  0.0,     // 添加原点
  27:                                     -0.5, -0.5}; // 添加个点
  28:  
  29:     // 颜色
  30:      GLfloat fColor = { 1.0, 0.0, 0.0,
  31:                                 0.0, 1.0, 0.0,
  32:                                 0.0, 0.0, 1.0,
  33:                                 0.0, 0.0, 0.0,
  34:                                 1.0, 1.0, 1.0,    // 原点颜色为白色
  35:                                 1.0, 0.0, 0.0};    // 回归添加第个点为红色
  36:  
  37:     // 指定顶点数据
  38:     glVertexPoer(2, GL_FLOAT, 0, fVertices);
  39:  
  40:     // 制定颜色
  41:     glColorPoer(3, GL_FLOAT, 0, fColor);
  42:  
  43: }
  44:  
  45: //这里进行所有绘图工作
  46: void SceneShow(GLvoid)        
  47: {
  48:     glClear(GL_COLOR_BUFFER_BIT);    // 清空颜色缓冲区
  49:  
  50:      GLu byTopIndices = { 2, 3, 4};
  51:      GLu byLeftIndices = { 3, 0, 4};
  52:      GLu byBottomIndices = { 0, 1, 4};
  53:      GLu byRightIndices = { 1, 2, 4};
  54:  
  55:      GLsizei iCounts = { 3, 3, 3, 3};
  56:      GLvoid *indices = { byTopIndices, byLeftIndices, byBottomIndices, byRightIndices};
  57:  
  58:      GL iFirsts = { 0, 2, 3};
  59:  
  60:     // 左上角图形展示了glDrawArrays效果glDrawArray连续绘制0到4索引指定顶点图形
  61:     glPushMatrix;
  62:     glTranslatef(-0.5, 0.0, 0.0);
  63:     glDrawArrays(GL_QUADS, 0, 4);
  64:     glPopMatrix;
  65:  
  66:     // 左下角图展示了glMultiDrawArrays效果
  67:  
  68:     glPushMatrix;
  69:     glTranslatef(0.5, 0.0, 0.0);
  70:     glMultiDrawArrays(GL_TRIANGLES, iFirsts, iCounts, 3);
  71:     glPopMatrix;
  72:  
  73:     glFlush;
  74: }  


  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2009-10-18\glRectWithArrayDraw 目录获取方式见文章最后有关获取博客完整源代码介绍说明

  按上面例子中顶点排序我们没有办法再组织处个完整矩形了这里我通过{0,1,2},{2,3,4}绘制出了3/4,然后补上了个第个点坐标通过绘制{3,4,5},完成完整矩形记住.gif' />按顺序特点就很好理解了运行效果如下图注意实现区别导致和前面例子中效果差异

  

  为了方便顶点排列顺序理解和上例中参数含义我特意画了张草图:

  

  此例中首先需要介绍说明glMultiDrawElements是OpenGL 1.4版本引进而Windows仅仅实现了1.1所以在Windows下必须需要进行额外处理才能使用了我使用是glew库详细情况见 XO2其中详细介绍说明了如何获取Windows中缺失OpenGLglMultiDrawElements仅仅通过最后个参数(此例中为 4)表示指定4次glDrawElements其他参数和glDrawElements意义仅仅是第24参数变成形式这是种非常有意思又很容易理解和记忆参数排列方式也是值得

  序列顶点

  还是为了优化考虑在对于排好序顶点序列而言可以通过接口指明这点以允许OpenGL实现进优化OpenGL中对应为 glDrawArrays和glMultiDrawArrays分别于上述glDrawElements和glMultiDrawElements对应使用上由于有顶点按顺序这个优先条件在参数更加简单需在需要额外索引(前面例子中Indice类)只需要指明起点和数量就行

  OpenGL Reference Manual:

glDrawArrays — render primitives from .gif' /> data  
C Specication  
void glDrawArrays(    GLenum      mode,  
     GL      first,  
     GLsizei      count);  
Parameters
mode
                        Species what kind of primitives to render.  
                        Symbolic constants  
                        GL_POINTS,  
                        GL_LINE_STRIP,  
                        GL_LINE_LOOP,  
                        GL_LINES,  
                        GL_TRIANGLE_STRIP,  
                        GL_TRIANGLE_FAN,  
                        GL_TRIANGLES,  
                        GL_QUAD_STRIP,  
                        GL_QUADS,  
                        and GL_POLYGON are accepted.  
first
                        Species the starting index in the enabled .gif' />s.  
count
                        Species the number of indices to be rendered.
glMultiDrawArrays — render multiple s of primitives from .gif' /> data  
C Specication  
void glMultiDrawArrays(    GLenum      mode,  
     GL *      first,  
     GLsizei *      count,  
     GLsizei      primcount);  
Parameters
mode
                        Species what kind of primitives to render.  
                        Symbolic constants  
                        GL_POINTS,  
                        GL_LINE_STRIP,  
                        GL_LINE_LOOP,  
                        GL_LINES,  
                        GL_TRIANGLE_STRIP,  
                        GL_TRIANGLE_FAN,  
                        GL_TRIANGLES,  
                        GL_QUAD_STRIP,  
                        GL_QUADS,  
                        and GL_POLYGON are accepted.  
first
                        Pos to an .gif' /> of starting indices in the enabled .gif' />s.  
count
                        Pos to an .gif' /> of the number of indices to be rendered.  
primcount
                        Species the size of the first and count


Tags:  win32编程

延伸阅读

最新评论

发表评论