Vertex array

OpenGLでポリゴンなどを描画するときは,

  1
  2
  3
  4
  5
  6
  7
  8
double v0[3] = {0, 0, 0};
double v1[3] = {1, 0, 0};
double v2[3] = {0, 1, 0};
glBegin(GL_TRIANGLES);
glVertex3dv(v0);
glVertex3dv(v1);
glVertex3dv(v2);
glBegin(GL_TRIANGLES);

などのようにglVertexで一つ一つ指定します. しかし,大量の頂点データがある場合,毎回glVertex関数を呼び出すのはパフォーマンス上あまり良くありません. そこで,Vertex arrayを用います.

  1
  2
  3
  4
  5
  6
  7
    GLdouble vertices[] = { 0, 0, 0,  1, 0, 0,  1, 1, 0 };
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_DOUBLE, 0, vertices);
 
    int num_of_vertices = sizeof(vertices)/sizeof(GLdouble);
    glDrawArrays(GL_TRIANGLES, 0, num_of_vertices);
 
    glDisableClientState(GL_VERTEX_ARRAY);

配列に格納した頂点データをOpenGLに転送,描画します. それぞれの関数は,

  • glEnableClientState : arrayをactivateする.引数には,GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_SECONDARY_COLOR_ARRAY, GL_INDEX_ARRAY, GL_NORMAL_ARRAY, GL_FOG_COORDINATE_ARRAY, GL_TEXTURE_COORD_ARRAY, GL_EDGE_FLAG_ARRAYのどれかを指定.
  • glVertexPointer(size, type, stride, pointer) : arrayの元データ(ポインタ)を指定.引数には, size (2,3 or 4), type (GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE), stride, pointer を指定. glVertexPointerは頂点データの場合だが,その他に同様の関数がいくつかある.
    命令名sizetype
    glVertexPointer(size, type, stride, pointer)2,3,4GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE
    glColorPointer(size, type, stride, pointer)3,4GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_DOUBLE
    glSecondaryColorPointer(size, type, stride, pointer)3同上
    glIndexPointer(type, stride, pointer)1GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE
    glNormalPointer(type, stride, pointer)3GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE
    glFogCoordPointer(type, stride, pointer)1GL_FLOAT, GL_DOUBLE
    glTexCoordPointer(size, type, stride, pointer)1,2,3,4GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE
    glEdgeFlagPointer(stride, pointer)1-
  • glDrawArrays(mode, first, count) : arrayのfirstからfirst+count-1までを描画する.描画の最初の引数でプリミティブの種類(glBegin()で用いるものとおなじ)を指定. ちなみにarray内の1要素のみを描画したい場合はglArrayElement()を用いる.
      1
      2
      3
      4
      5
    
    glBegin(GL_POINTS);
    for(int i = 0; i < n; ++i){
        glArrayElement(first+i);
    }
    glEnd();
  • glDisableClientState : arrayをdeactivate.

glDrawElements

ポリゴンデータの表現には通常,頂点列とその幾何構造を用います. そのようなデータの描画時にはglDrawElements()を用います.

  1
  2
  3
  4
  5
  6
  7
  8
  9
    GLdouble vertices[] = { 0, 0, 0,  1, 0, 0,  1, 1, 0,  0, 1, 0 };
    GLuint indices[] = { 0, 1, 2,  0, 2, 3 };
 
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_DOUBLE, 0, vertices);
 
    int num_of_indices = sizeof(indices)/sizeof(GLuint);
    glDrawElements(GL_TRIANGLES, num_of_indices, GL_UNSIGNED_INT, indices);
 
    glDisableClientState(GL_VERTEX_ARRAY);

indicesのある範囲だけ使いたい場合は,glDrawRangeElement(mode, start, end, count, type, indices)を用います. また,複数のindicesをまとめて指定したい場合は,glMultiDrawElementsがあります.

Interleaved array

1つのarrayに複数の種類のデータ(e.g. ColorとVertex)を含めたい場合は, glInterleavedArraysが使えます.例えば,頂点の色と座標の場合,

  1
  2
  3
  4
  5
    GLfloat col_and_vert[] = { 1.0, 0.0, 0.0,  0.0, 0.0, 0.0, 
                               0.0, 1.0, 0.0,  5.0, 0.0, 0.0, 
                               0.0, 0.0, 1.0,  5.0, 5.0, 0.0 };
    glInterleavedArrays(GL_C3F_V3F, 0, col_and_vert);
    glDrawArrays(GL_TRIANGLES, 0, 3);

col_and_vertには{頂点1の色,頂点1の座標,頂点2の色,頂点2の座標,... }の順番にデータが格納されています. glInterleavedArraysの第一引数は配列の型と並びを指定します.GL_C3F_V3FはglColorPointerに対応する3要素のfloatと glVertexPointerに対応する3要素のfloatが並んでいることを示しています. このほかにも,GL_V2F, GL_V3F, GL_C4UB_V2F, GL_C4UB_V3F, GL_C3F_V3F, GL_N3F_V3F, GL_C4F_N3F_V3F, GL_T2F_V3F, GL_T4F_V4F, GL_T2F_C4UB_V3F, GL_T2F_C3F_V3F, GL_T2F_N3F_V3F, GL_T2F_C4F_N3F_V3F, GL_T4F_C4F_N3F_V4F が指定できます.UBはGL_UNSIGNED_BYTE,Tはテクスチャ座標に対応します.

また,構造体を用いると,

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
    struct Vertex
    {
        GLfloat color[4];
        GLfloat normal[3];
        GLfloat vertex[3];
    };
 
    vector<Vertex> inter_array;
    inter_array.resize(N);
    
    ...
 
    glInterleavedArrays(GL_C4F_N3F_V3F, 0, &inter_array[0]);
    glDrawArrays(GL_TRIANGLES, 0, N);

値の格納にはCの配列ではなくSTLのvectorを用いました. vectorは&inter_array[0]を渡すことで配列と互換性を持っています.


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2022-11-30 (水) 13:48:08