2012年3月25日日曜日

All about OpenGL ES 2.x 2/3

Open GL の「ESの」詳しいドキュメントがあったので、読みがてらのメモの2ページ目
1ページ目メモ:All about OpenGL ES 2.x 1/3
元ネタ:bd-interactively All about OpenGL ES 2.x – (part 2/3)

原文とあわせてお読みください。和訳の正確性と内容の信憑性については話半分ということで。


著者はこのチュートリアルの1つめが思っていたよりもビッグな話題になり、とてもびっくりしたということを冒頭で述べています。そりゃ、いい文章だもの。


At a glance


コード類はC、もしくは Objective-C で解説する。元ネタサイトからダウンロードできるのはiOS、とくに iPhone アプリのプロジェクトファイル。第1回チュートリアルの pdf もおいてある。

一般に OpenGL のメソッド名には"gl"もしくは"gl."のプレフィックスがつく。また、OpenGL が使用する型も独自に定義されている(GLfloat, GLiknt など)。これはマルチプラットフォーム対応のため。型については OpenGL の元ネタサイトに一覧表がある。

OpenGL ES は64bit のデータ型をサポートしていない。OpenGL ES の独自型を使えば大丈夫。

OpenGL の描画の各ステップについて解説を行う(元ネタサイトにそのイメージ画像あり)。しかしその前に EGL の説明を文章があるのでそちらを読んで欲しい。

> 補足ページヘ


Primitives


Primitives の構成要素の基礎となるのは vertex、つまり頂点情報。x, y, z の3つの数値を持つ。また、軽量化のために数値の羅列で表現される。
GLfloat point3D = {1.0 ,0.0, 0.5};
GLfloat line3D = {0.5, 0.5, 0.5, 1.0, 1.0, 1.0};
GLfloat triangle3D = {0.0, 0.0, 0.0, 0.5, 1.0, 0.0, 1.0, 0.0, 0.0};

線と三角形のデータでは区切りもないが、1つ目の数字はx座標, 次はy、次はz, x, y, z, x, y z,,,というように OpenGL が勝手に処理してくれる。

ちなみに、3Dモデルデータを読み込むような関数は(著者はあると思っていたが)無い。

じゃあ3Dモデルデータを僕らの OpenGL アプリケーションに導入するにはどうするかというと、サードパーティ製のエンジン使うのが一番簡単。もしくは .h ファイルとして書きだす。

で、(元ネタの)著者がシンプルは Objective-C ベースの 3Dエンジンをつくたのでよろしく!モデルデータの形式変更などが行える。
http://nineveh.gl


Meshes and Lines Optimization


ここで、3D空間の立方体について見てみよう。先に触れたようにポリゴン(三角形)の集合である。よって以下のように表現できる。
GLfloat cube3D[] =
{
    0.50,-0.50,-0.50,   // vertex 1
    0.50,-0.50,0.50,    // vertex 2
    -0.50,-0.50,0.50,   // vertex 3
    -0.50,-0.50,-0.50,  // vertex 4
    0.50,0.50,-0.50,    // vertex 5
    -0.50,0.50,-0.50,   // vertex 6
    0.50,0.50,0.50,     // vertex 7
    -0.50,0.50,0.50     // vertex 8
}

数値の精度についてはOpenGLは問題としない。ただ、メモリーの消費を考えると小数点2ケタぐらいを推奨する。

一般にメッシュは頂点・テクスチャ座標・法線の3つの情報を持つ。これらをまとめてもつような配列を考えると以下のようになる。これは Array of Structures と呼ばれる。
GLfloat cube3D[] =
{
    0.50,-0.50,-0.50,   // vertex 1
    0.00,0.33,          // texture coordinate 1
    1.00,0.00,0.00      // normal 1
    0.50,-0.50,0.50,    // vertex 2
    0.33,0.66,          // texture coordinate 2
    0.00,1.00,0.00      // normal 2
    ...
}

この手法でどんな種類の頂点でも書くことができる。単体のデータ型(ここでは GLfloat
 型)の1つの情報としてまとめなければいけないかと聞かれたらそのとおり。後で説明する。


Buffers


BufferObject は僕らの Primitive の配列のための理想的なデータ形式である。前に説明したように2つあって、頂点配列(vertexes buffer object = VBO) とインデックス配列 (Indeces buffer object = IBO)である。

ひとたび、もともとのデータから VBO を作ってしまえば元のデータは破棄することができる。OpenGL がデータをコピーして BO として保持するからである。BO は法線のデータ・テクスチャ座標のデータ・Structure のデータなどどんな種類のデータも保持できる。

IBO のデータ型は GLubyte かもしくは GLushort が一般的。たまに GLuintもあるが、オプションと考えるべきだろう。

さて、これらのバッファーを作っていこう。

FrameBuffer と RenderBuffer の作り方はほぼ同じ。手順としては1つ以上の名前 or ID を作り、それをバッファーオブジェクトにつなげる。それからプロパティを定義してデータをそこに入れる。以下のメソッドを使う。メソッドのリファレンスは省略。

GLvoid glGenBuffers(GLsizei n, GLuint* buffers)
GLvoid glBindBuffer(GLenum target, GLuint buffer)

港のクレーンの話に戻ると、BufferObject が持っているフックは2つある。すなわち、GL_ARRAY_BUFFER と GL_ELEMENT_ARRAY_BUFFER の2つである。設定メソッドは以下の2つ。

GLvoid glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
GLvoid glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)

1つめは BufferObject とその設定の内容をセットする。ここで引数に GL_DYNAMIC_DRAW を選択したのなら、それはバッファーオブジェクトの更新を後回しにして、glBufferSubData メソッドを使うことになる。

このメソッドは以前に定義された BufferObject のサイズの中限定で、一部を書き換えるというもの。でも著者は個人的には GL_DYNAMIC_DRAW は使いたくないらしい。結局シェーダーでできる機能なので(?)。

BufferObject が出来上がったらあとは好きなやつをつなげる(bind)だけ。ただし僕らが bind できるのは一度に一種類の BufferObject だけ。ある BufferObject が bind された状態になったら、すべての描画コマンドはその BufferObject を使うことになる。使い終わったら bind 状態を解除すること。


> 2/3-2 へ

0 件のコメント:

コメントを投稿