2012年4月11日水曜日

All about OpenGL ES 2.x 2/3 -5

2/3 -4 の続き

2/3 の最後です。超特急風味。


Using the Buffer Objects


バッファーオブジェクトの使用はとっても簡単!GL_ARRAY_BUFFERGL_ELEMENT_ARRAY_BUFFERの2つのバッファーを同時にバインドし、 glDraw* のメソッドを呼んで開始インデックスを指定する。

では、(ついに最後だ!)次はどうやって EGL API を使ってレンダリングを完成するかを見てみよう。

Rendering


ここまでは基本的なデバイススクリーンへの描画について見てきた。しかしフレームバッファのようなオフスクリーンやテクスチャに描画することもできるし、それをファイルに保存したり、デバイススクリーンの中で画像を作ることもできる。

Pre-Render

レンダリングを2つのステップとして捉えよう。1段階目は pre-render。このステップにおいては僕らは古いゴミを掃除する必要がある。覚えているかな、フレームバッファーとはレンダーバッファの画像の集合体。描画処理を完了したら、スクリーンへの描画が終わってもレンダーバッファにはデータが残っている。というわけでこの pre-render 段階ではレンダーバッファを綺麗にしてあげる。もし前段階のイメージを使いたいのなら話は別だが。

レンダーバッファの掃除のためには以下のメソッドを使う。

GLvoid glClear(GLbitfield mask)

ここまででわかっていると思うが、港のクレーンのフックの一つへの指令というのは最後にバインドしたオブジェクトに対して行われる。よって、このメソッドを使うときには使いたい frame buffer をバインドしておく必要がある。引数には OR "|" ででもって複数の掃除をすることができる。

掃除が出来ればあとはレンダリング glDraw* を呼び出す段階だ。

Drawing

実はここまでよく出てきているが、以下の2つの関数でもって描画が行われる。

GLvoid glDrawArrays(GLenum mode, GLint first, GLsizei count)
GLvoid glDrawElements(GLenum mode, GLsizei count, GLenum type,
                      const GLvoid* indices)

はじめに、どのようにこれらの関数が動くのかを説明しよう。まず programable pipeline において重要なのは VSH が実行される回数が定義されるということ。この回数は引数の count で決まる。もちろん GPU は最適化を行うが、一般には VSH は僕らが定義した attributes と uniforms にその回数だけ処理されることになる。なぜこんなことを言うかというと、例えば200の頂点があって、でもあるときそのうちの3つだけを使いたいということがあるかもしれない。そういうときに役立つのはインデックス配列を使うことだ。立方体なら頂点は8つであるが、描画に必要な数を数えると24になる。

glDrawArrays を使うとき、"first" の引数は頂点ごとの attributes の開始点オフセットを決める。2を指定すれば、glVertexAttribPointer で指定したデータのうち、第2番の要素から開始することになる。

glDrawElements を使うとき、"first" はインデックスの開始点オフセット指定となり、頂点ごとのオフセットとはならない。"type" はデータ型。でもってここにちょっとヒント。もし要素が255以下ならば GL_UNSIGNED_BYTE を使おう
(補足:glDrawElements には first という引数は無い。書き間違い?)

次は "mode" 。メッシュといってもいろいろ書き方がある。次の画像を見てくれ。

(>元ネタサイトへ)

この画像で、すべての頂点データは{v0,v1,v2,v3,v4,v5}のようになっている(それぞれはx, y, z の要素をもった頂点)。一番融通が利くのは GL_LINES 。これを使っておこう。ただし特定の条件では他の2つは最適化されたものとして利用価値はある。お次は三角形の図。

(>元ネタサイトへ)

この画像で、すべての頂点データは{v0,v1,v2,v3,v4,v5}のようになっている(それぞれはx, y, z の要素をもった頂点)。線の時と同じように、GL_TRIANGLE が最も使える。他は特定の使用においては最適な形。

繰り返すが、 GL_LINES と GL_TRIANGLEを使うべし。他の STRIP, LOOP などに関しては OpenGL の他の部分んの最適化で達成できる部分であり、メッシュのポリゴンを減らしたり、シェーダーのプロセスを最適化することによって出来る。

Render

最後は(例え鋭角にフレームバッファを使っていなかったとしても)ただフレームバッファの結果をスクリーンに映すだけである。これは EGL の説明の時に書いたこと。

ここではそれを繰り返しはしないが、EAGL API を使っているなら presentRenderbuffer:GL_RENDERBUFFER を呼び出す前にカラーレンダーバッファとフレームバッファを必ずバインドしなければならない。なぜなら レンダーバッファはフレームバッファの「内部に」置かれているから。

- (void) makeRender
{
    glBindFramebuffer(_framebuffer);
    glBindRenderbuffer(_colorRenderbuffer);
    [_context presentRenderbuffer:GL_RENDERBUFFER];
}

EGL API を使っているなら、これで内部のバッファーが反転する処理が行われる

以上!これがレンダリングの基本。OpenGL はマルチサンプルと呼ばれるなんとやらも提供しているが、これはアンチアライアスなイメージを作るための特別な処理。ここでは取り上げない。次の項で取り上げよう。

全く長くなってしまった。

※Couclusion 省略


以上。


結構省略してしまいましたが、愛嬌ということでお許し下さい。(特に後半にかけて)直訳だけで終わってしまった感があって少し残念ですが、もう自分の頭の中で少し噛み砕いてから他の形でまとめれればいいなと考えています。

3/3 は書きません。発展的なテクニックであり、OpenGL の基礎的な部分から外れるので、個人的にはまだいいやという感じなので。です。

0 件のコメント:

コメントを投稿