zoukankan      html  css  js  c++  java
  • OpenGL之再向虎山行[2]:超越glBegin/glEnd

    想当年学习OpenGL的时候,就是从glBegin/glEnd开始的,呵呵。

    但是glBegin/glEnd并不适合大场景绘制,在OpenGL ES中甚至被踢出局,所以再玩OpenGL,必然要超越它。

    Data:

    // cube ///////////////////////////////////////////////////////////////////////
    // v6----- v5
    // /| /|
    // v1------v0|
    // | | | |
    // | |v7---|-|v4
    // |/ |/
    // v2------v3

    // vertex coords array
    GLfloat vertices[] = {1,1,1, -1,1,1, -1,-1,1, 1,-1,1, // v0-v1-v2-v3
    1,1,1, 1,-1,1, 1,-1,-1, 1,1,-1, // v0-v3-v4-v5
    1,1,1, 1,1,-1, -1,1,-1, -1,1,1, // v0-v5-v6-v1
    -1,1,1, -1,1,-1, -1,-1,-1, -1,-1,1, // v1-v6-v7-v2
    -1,-1,-1, 1,-1,-1, 1,-1,1, -1,-1,1, // v7-v4-v3-v2
    1,-1,-1, -1,-1,-1, -1,1,-1, 1,1,-1}; // v4-v7-v6-v5

    // normal array
    GLfloat normals[] = {0,0,1, 0,0,1, 0,0,1, 0,0,1, // v0-v1-v2-v3
    1,0,0, 1,0,0, 1,0,0, 1,0,0, // v0-v3-v4-v5
    0,1,0, 0,1,0, 0,1,0, 0,1,0, // v0-v5-v6-v1
    -1,0,0, -1,0,0, -1,0,0, -1,0,0, // v1-v6-v7-v2
    0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0, // v7-v4-v3-v2
    0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1}; // v4-v7-v6-v5

    // color array
    GLfloat colors[] = {1,1,1, 1,1,0, 1,0,0, 1,0,1, // v0-v1-v2-v3
    1,1,1, 1,0,1, 0,0,1, 0,1,1, // v0-v3-v4-v5
    1,1,1, 0,1,1, 0,1,0, 1,1,0, // v0-v5-v6-v1
    1,1,0, 0,1,0, 0,0,0, 1,0,0, // v1-v6-v7-v2
    0,0,0, 0,0,1, 1,0,1, 1,0,0, // v7-v4-v3-v2
    0,0,1, 0,0,0, 0,1,0, 0,1,1}; // v4-v7-v6-v5

    // index array of vertex array for glDrawElements()
    // Notice the indices are listed straight from beginning to end as exactly
    // same order of vertex array without hopping, because of different normals at
    // a shared vertex. For this case, glDrawArrays() and glDrawElements() have no
    // difference.
    GLubyte indices[] = {0,1,2,3,
    4,5,6,7,
    8,9,10,11,
    12,13,14,15,
    16,17,18,19,
    20,21,22,23};


    补充一个原来做的小例子:

    void drawTorus(int numMajor, int numMinor, float majorRadius, float minorRadius)
    {
    static double PI = 3.1415926535897932384626433832795;

    double majorStep = 2.0 * PI / numMajor;
    double minorStep = 2.0 * PI / numMinor;

    GLint shine = 128;
    GLfloat opacity = 255;

    GLfloat ambiMat[4] = { 0.2f, 0.5f, 0.7f, opacity };
    GLfloat diffMat[4] = { 0.7f, 0.7f, 0.7f, opacity };
    GLfloat specMat[4] = { 1.0f, 1.0f, 1.0f, opacity };
    GLfloat specRef[4] = { 1.0f, 1.0f, 1.0f, 1.0f };

    // Enable Material
    glEnable(GL_COLOR_MATERIAL);

    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);

    glDepthFunc(GL_LESS);

    //Setup Material
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambiMat);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffMat);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specMat);


    // All materials hereafter have full specular reflectivity
    // with a high shine
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specRef);
    glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, shine);

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    for (int i = 0; i < numMajor; ++i)
    {
    double a0 = i * majorStep;
    double a1 = a0 + majorStep;
    GLdouble x0 = cos(a0);
    GLdouble y0 = sin(a0);
    GLdouble x1 = cos(a1);
    GLdouble y1 = sin(a1);

    glBegin(GL_TRIANGLE_STRIP);

    for (int j = 0; j <= numMinor; ++j)
    {
    double b = j * minorStep;
    GLdouble c = cos(b);
    GLdouble r = minorRadius * c + majorRadius;
    GLdouble z = minorRadius * sin(b);

    glNormal3d(x0 * c, y0 * c, z / minorRadius);
    glTexCoord2d(i / (GLdouble) numMajor, j / (GLdouble) numMinor);
    glVertex3d(x0 * r, y0 * r, z);

    glNormal3d(x1 * c, y1 * c, z / minorRadius);
    glTexCoord2d((i + 1) / (GLdouble) numMajor, j / (GLdouble) numMinor);
    glVertex3d(x1 * r, y1 * r, z);
    }

    glEnd();
    }
    }



    老办法:glBegin/glEnd (Immediate Mode)

    ///////////////////////////////////////////////////////////////////////////////
    // draw 1, immediate mode
    // 54 calls = 24 glVertex*() calls + 24 glColor*() calls + 6 glNormal*() calls
    ///////////////////////////////////////////////////////////////////////////////
    void draw1()
    {
    glPushMatrix();
    glTranslatef(
    -2, 2, 0); // move to upper left corner
    glBegin(GL_QUADS);

      
    // face v0-v1-v2-v3
      glNormal3f(0,0,1);
      glColor3f(
    1,1,1);
      glVertex3f(
    1,1,1);
      glColor3f(
    1,1,0);
      glVertex3f(
    -1,1,1);
      glColor3f(
    1,0,0);
      glVertex3f(
    -1,-1,1);
      glColor3f(
    1,0,1);
      glVertex3f(
    1,-1,1);

      
    // face v0-v3-v4-v6
      glNormal3f(1,0,0);
      glColor3f(
    1,1,1);
      glVertex3f(
    1,1,1);
      glColor3f(
    1,0,1);
      glVertex3f(
    1,-1,1);
      glColor3f(
    0,0,1);
      glVertex3f(
    1,-1,-1);
      glColor3f(
    0,1,1);
      glVertex3f(
    1,1,-1);

    // face v0-v5-v6-v1
      glNormal3f(0,1,0);
      glColor3f(
    1,1,1);
      glVertex3f(
    1,1,1);
      glColor3f(
    0,1,1);
      glVertex3f(
    1,1,-1);
      glColor3f(
    0,1,0);
      glVertex3f(
    -1,1,-1);
      glColor3f(
    1,1,0);
      glVertex3f(
    -1,1,1);

      // face v1-v6-v7-v2
      glNormal3f(-1,0,0);
      glColor3f(
    1,1,0);
      glVertex3f(
    -1,1,1);
      glColor3f(
    0,1,0);
      glVertex3f(
    -1,1,-1);
      glColor3f(
    0,0,0);
      glVertex3f(
    -1,-1,-1);
      glColor3f(
    1,0,0);
      glVertex3f(
    -1,-1,1);

      // face v7-v4-v3-v2
      glNormal3f(0,-1,0);
      glColor3f(
    0,0,0);
      glVertex3f(
    -1,-1,-1);
      glColor3f(
    0,0,1);
      glVertex3f(
    1,-1,-1);
      glColor3f(
    1,0,1);
      glVertex3f(
    1,-1,1);
      glColor3f(
    1,0,0);
      glVertex3f(
    -1,-1,1);

      // face v4-v7-v6-v5
      glNormal3f(0,0,-1);
      glColor3f(
    0,0,1);
      glVertex3f(
    1,-1,-1);
      glColor3f(
    0,0,0);
      glVertex3f(
    -1,-1,-1);
      glColor3f(
    0,1,0);
      glVertex3f(
    -1,1,-1);
      glColor3f(
    0,1,1);
      glVertex3f(
    1,1,-1);
    glEnd();

    glPopMatrix();
    }


    glDrawArray

    明显清爽了很多啊,效率高也是必然啦。

    ///////////////////////////////////////////////////////////////////////////////
    // draw cube at upper-right corner with glDrawArrays
    ///////////////////////////////////////////////////////////////////////////////
    void draw2()
    {
    // enble and specify pointers to vertex arrays
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glNormalPointer(GL_FLOAT,
    0, normals);
    glColorPointer(
    3, GL_FLOAT, 0, colors);
    glVertexPointer(
    3, GL_FLOAT, 0, vertices);

    glPushMatrix();
    glTranslatef(
    2, 2, 0); // move to upper-right

    glDrawArrays(GL_QUADS,
    0, 24);

    glPopMatrix();

    glDisableClientState(GL_VERTEX_ARRAY);
    // disable vertex arrays
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    }

    glDrawElements

    ///////////////////////////////////////////////////////////////////////////////
    // draw cube at bottom-left corner with glDrawElements
    // In this example, glDrawElements() has no advantage over glDrawArrays(),
    // because the shared vertices cannot share normals, so they must be duplicated
    // once per face. Look at the index array defined earlier in this file. The
    // indices are marching straight from 0 to 23 without hopping.
    ///////////////////////////////////////////////////////////////////////////////
    void draw3()
    {
    // enable and specify pointers to vertex arrays
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glNormalPointer(GL_FLOAT,
    0, normals);
    glColorPointer(
    3, GL_FLOAT, 0, colors);
    glVertexPointer(
    3, GL_FLOAT, 0, vertices);

    glPushMatrix();
    glTranslatef(
    -2, -2, 0); // move to bottom-left

    glDrawElements(GL_QUADS,
    24, GL_UNSIGNED_BYTE, indices);

    glPopMatrix();

    glDisableClientState(GL_VERTEX_ARRAY);
    // disable vertex arrays
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    }

    glDrawRangeElements

    ///////////////////////////////////////////////////////////////////////////////
    // draw cube at bottom-right corner with glDrawRangeElements()
    // glDrawRangeElements() has two more parameters compared with glDrawElements(),
    // start and end index. The values in index array must lie in between start and
    // end. Note that not all vertices in range (start, end) must be referenced.
    // But, if you specify a sparsely used range, it causes unnecessary process for
    // many unused vertices in that range.
    ///////////////////////////////////////////////////////////////////////////////
    void draw4()
    {
    // enable and specify pointers to vertex arrays
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glNormalPointer(GL_FLOAT,
    0, normals);
    glColorPointer(
    3, GL_FLOAT, 0, colors);
    glVertexPointer(
    3, GL_FLOAT, 0, vertices);

    glPushMatrix();
    glTranslatef(
    2, -2, 0); // move to bottom-right

    // draw first half (12 elements) {0,1,2,3, 4,5,6,7, 8,9,10,11}
    // tell the driver we use vertices from index 0 to index 11, which means 11-0+1 = 12 vertices
    // So, the driver can prefetch an amount of 12 vertex data prior to rendering
    glDrawRangeElements(GL_QUADS, 0, 11, 12, GL_UNSIGNED_BYTE, indices);

    // draw last half (12 elements) {12,13,14,15, 16,17,18,19, 20,21,22,23}
    // tell the driver we use vertices from index 12 to index 23, which means 23-12+1 = 12 vertices
    // So, the driver can prefetch an amount of 12 vertex data prior to rendering
    glDrawRangeElements(GL_QUADS, 12, 23, 12, GL_UNSIGNED_BYTE, indices + 12);

    glPopMatrix();

    glDisableClientState(GL_VERTEX_ARRAY);
    // disable vertex arrays
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    }



    Reference:

    http://www.songho.ca/opengl/index.html

    本文的例子,就是这位仁兄写的,我这叫阉割后的转贴,很不好意思。
    在我自己的实验里面,连文本和glDrawRangeElements都没有了,汗!!

  • 相关阅读:
    自定义predicate来对List进行去重
    ParameterizedType
    万级TPS亿级流水-中台账户系统架构设计
    【Linux】【压测】基于python Locust库实现自动化压测实践
    家里宽带ADSL是城域网IP以及公网IP的具体区别和联系
    fiddler如何使用Xposed+JustTrustMe来突破SSL Pinning
    幽门螺旋杆菌检查方法那么多,到底选择哪个?
    apache (httpd)不支持中文路径问题
    皮肤瘙痒症、干燥瘙痒、荨麻疹和丘疹性荨麻疹区别和联系
    Redmi K30和Redmi K30 5G和Redmi K30 5G极速版和Redmi K30i 5G
  • 原文地址:https://www.cnblogs.com/piaoger/p/2183037.html
Copyright © 2011-2022 走看看