OpenGL ES 2.0 その03

前回、シェーダプログラムを設定するところまでやりました。

今回でやっと描画です。といっても、トライアングルを出すだけですが。

今回はDirectXで言うところのDrawPrimitiveUP()系の解説になるので注意してください。

DirectXの場合、シェーダプログラムを利用する時にVertexDeclarationを作成する必要がありました。

GLESの場合は作成の必要はありませんが、多分それが内部でやっていることと同じようなことをする必要があります。

すなわち、頂点データとシェーダプログラム内の変数を対応させなければならないわけです。

まず、頂点データを用意します。

前回解説した頂点シェーダの入力は座標のみなので、3次元ベクトル3つを配列で確保します。

GLfloat  pfVertices[] =

{

    -0.4f, -0.4f, 0.0f,

    +0.4f, -0.4f, 0.0f,

      0.0f,  0.4f, 0.0f

};

頂点データと頂点シェーダ入力の対応付けは、シェーダプログラムから入力変数の位置を取得->その属性を有効に->データのポインタを設定、と言う順番で行われます。

// 頂点座標属性の位置を取得

GLuint nAttLoc = glGetAttribLocation( hProgram, "myVertex" );

// 頂点座標属性を有効に

glEnableVertexAttribArray( nAttLoc );

// 頂点座標属性のポインタを設定する

glVertexAttribPointer( nAttLoc, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, pfVertices );

入力変数の位置は glGetAttribLocation() 関数で取得できます。プログラムハンドルと変数名を指定します。

なお、シェーダプログラム内で attribute で宣言されている変数が頂点入力です。

glEnableVertexAttribArray() で有効にしてからポインタを設定します。

glVertexAttribPointer() は頂点データのポインタを指定します。

引数は順番に、変数の位置、頂点1つあたりの要素数、フォーマット、正規化するかどうかのフラグ、ストライド、頂点データのポインタとなります。

素数は頂点1つあたりのもので、3Dベクトルなら3となります。

正規化するかどうかのフラグは主に法線で用います。

ストライドは頂点データの先頭から次の頂点データの先頭までのバイト数です。今回はfloatの3Dベクトルなので、sizeof(float) * 3 となります。

頂点データの他の入力変数を設定する場合、そのデータの配列は別々に作成してもかまいません。

DirectXでは頂点ストリームを複数使う方法もありますが、通常は頂点の各情報を1つの構造体にまとめています。

GLESでも同じような方法は可能ですが、頂点データのポインタは該当データの先頭アドレスを指定しなければなりません。

次にプログラムのグローバル変数を設定します。プログラムの中で uniform で宣言されている変数です。

これも頂点入力と同じ要領ですが、有効・無効の設定は必要ありません。

// 変数の位置を取得する

GLuint nMtxLoc = glGetUniformLocation( hProgram, "myPMVMatrix" );

// 変数を設定する

glUniformMatrix4fv( nMtxLoc, 1, GL_FALSE, pfIdentity );

glUniformMatrix4fv() 関数は名前からもわかるとおり4*4行列を設定する関数です。

引数は、変数の位置、設定する行列の数、転置するかどうかのフラグ、行列です。

当然、他にもベクトルを設定したりする関数もあります。

こうして頂点入力と変数を設定したらいよいよ描画です。といっても、一行だけです。

glDrawArrays( GL_TRIANGLES, 0, 3 );

引数は、プリミティブタイプ、使用する頂点の開始位置、使用する頂点の数となります。

DirectXでは描画するプリミティブの数を引数として渡していました。

つまり、TriangleListで三角形を1つ描画したいなら1を渡す必要がありました。

GLESでは使用する頂点の数です。TriangleListなら3nを指定する必要があるわけです。

上記の例はインデックスを用いない方法ですが、当然使用することは可能です。

glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, pIndices );

インデックスを使用する場合、glDrawElements()を使います。

引数は、プリミティブタイプ、使用する頂点の数、インデックスフォーマット、インデックスデータとなります。

使用する頂点の数は glDrawArrays() と同じです。

これで、前回までのプログラムとあわせて三角形が表示されたはずです。

たったこれだけのことをやるのに3回も使って解説するとは、ちょっと効率悪いですかね。