2013年6月24日月曜日

三角形の描画

三角形を描画します。
glBegin,glEnd等を使って、直接描画することができないので、
VAOとVBOを生成して、描画します。

VAO(Vertex Array Object)とは

描画に用いるバッファやバッファの設定の集まりです。
1つのVAOには複数のVBOを含みます。
初期化時にglBindVertexArrayを呼び出して、
VAOの設定をし、描画時にもう一度呼び出すと、設定が全てロードされるので
描画処理を単純化することができます。

VBO(Vertex Buffer Object)とは

描画に用いるバッファ(つまりデータ)です。
VBOには2種類あり、GL_ARRAY_BUFFERGL_ELEMENT_ARRAY_BUFFERがあります。
GL_ARRAY_BUFFERは、頂点データやテクスチャ座標、法線データなど通常のバッファです。
GL_ELEMENT_ARRAY_BUFFERは、描画時の頂点の描画する順番のインデックスを格納します。
また、これらのバッファはglVertexAttribPointerを使って、シェーダへ渡します。

三角形描画クラス

Sample1のソースコードに以下のクラスを追加すると利用できます。
初期化処理などは以前の記事を参考にしてください。
class Triangle {
public:
  typedef std::shared_ptr Ptr;
  Triangle(GLfloat size) {
    GLfloat low = -size/2.0f;
    GLfloat high = size/2.0f;
    GLfloat vertices[3*3] = {
      low, low, low,
      low, high, low,
      high, high, low,
    };
    GLuint indecise[ELEMENT_SIZE] = {
      0, 1, 2
    };
    //VAO(バッファデータ・設定群)の生成
    glGenVertexArrays(1, &vertex_array_object_);
    //現在のVAOに設定
    glBindVertexArray(vertex_array_object_);
    //VBO(バッファ)の生成
    glGenBuffers(1, &vertex_buffer_object_);
    //現在のバッファに設定
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object_);
    //現在のバッファにデータを送信
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    //データ型の設定(float * 3)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
    //シェーダで0番地を使用
    glEnableVertexAttribArray(0);
    //インデックスの設定
    glGenBuffers(1, &index_buffer_object_);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_object_);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indecise), indecise, GL_STATIC_DRAW);
    //VAO設定を終了する
    glBindVertexArray(0);
  }

  ~Triangle() {
    glDeleteBuffers(1, &index_buffer_object_);
    glDeleteBuffers(1, &vertex_buffer_object_);
    glDeleteVertexArrays(1, &vertex_array_object_);
  }
  
  void Draw() {
    //VAOの有効化(VAOに割り当てた設定とバッファが復元される)
    glBindVertexArray(vertex_array_object_);
    //インデックスを用いて描画する
    glDrawElements(GL_TRIANGLES, ELEMENT_SIZE, GL_UNSIGNED_INT, nullptr);
    //VAOの無効化
    glBindVertexArray(0);
  }
private:
  enum { ELEMENT_SIZE = 3};
  GLuint vertex_array_object_;
  GLuint vertex_buffer_object_;
  GLuint index_buffer_object_;
};
VAO生成→VAOのバインド→{VBOの設定}→VAOの無効化がVAO設定の流れになります。
VBOの設定ではVBOの生成→VBOのバインド→データ送信→(シェーダへの設定)となります。
glGenVertexArrays(num, *buffers):num個のVAOを生成します。
glBindVertexArray(buffer):現在のVAOを設定します。
glGenBuffers(num, *buffers):num個のVBOを生成します。
glBindBuffer(target, buffer):現在のVBOを設定します。
targetには、頂点データのバッファGL_ARRAY_BUFFERやインデックスバッファGL_ELEMENT_ARRAY_BUFFERがあります。
glBufferData(target, size, *data, usage):VBOにデータを送信します。
usageはGL_XXXX_YYYYの形式で表されます。
(XXXX)
  • STREAM 読み込みも書き込みも一度のみのバッファ
  • STATIC 書き込みが一度だけで、読み込みは何度も行われるバッファ
  • DYNAMIC 何度も読み書きが行われるバッファ
  • (YYYY)
  • DRAW アプリケーション側から書き込まれ、OpenGLが描画のために読み込むバッファ
  • READ OpenGL側で書き込まれ、アプリケーション側で読み込むバッファ
  • COPY OpenGL側で書き込まれ、描画に用いられるバッファ
  • glVertexAttribPointer(index,size,type,normalied,stride,pointer):頂点データの種類とデータ1つ分の大きさを指定し、シェーダのindex番地へと格納します。
    glEnableVertexAttribArray(index):上で設定したデータを利用することを通知します。

    描画は非常に簡単で、glBindVertexArrayで利用するVAOを有効化し、
    描画関数を呼び出し(ここでは、インデックスを利用するglDrawElements)、
    最後に、VAOが汚されないようにglBindVertexArrayでVAOを無効化しておきます。

    ここで一つ注意してほしいことですが、GL_QUADSがサポートされなくなったため、
    四角形を描画する場合は、GL_TRIANGLE_STRIPを使ってください。

    0 件のコメント:

    コメントを投稿