読者です 読者をやめる 読者になる 読者になる

音ゲーの出来ない雑魚のブログ

LWJGLとかのことをいうブログ

「moreover lwjgl」 4 VAOとVBOで表示(1)

OpenGL 3.0からの機能の、VertexArrayObject(VAO)VertexBufferObject(VBO)を使って、物体を表示させましょう。

(注:ここでは、OpenGL3.0以上に対応していないと、エラーを起こして起動できません)

それでは、ソースコードです。


解説

正直、ソースコードに大まかな解説書いてもいいんですけどね…

その前に、まずVAOとVBOの説明

VertexBufferObjectVertexArrayObjectとは

VertexBufferObjectは、「頂点を(Vertex)一時保管する(Buffer)もの(Object)」で、頂点の情報(座標やら)を一旦保管するものです。一旦保管することで、処理が楽になるのです。
VBOと略されます。

そして、VertexArrayObjectは、「頂点の配列の(Array)もの」で、中には、頂点情報のバッファー(VBOの形で)と、それらを描画するときの設定(VBO側の設定とVAO側の設定)が入っています。
VAOと略されます。

f:id:cakkby:20160314194419p:plain

OpenGL3.0からは、VAOから、設定をふまえて頂点情報を描画することが出来るようになりました。

ソースコードの解説

変更点のみ、GLFW系OpenGLの色で分けてます。


27~29行目 : VBO,VAOのIDと、頂点数を定義しています。VBO,VAOはID制で、

   「生成」→「結びつけ」→「設定」→「描画」→「結びつけ解除」→「消去」

という感じにしていきます。それぞれの処理は後でやります。

54,55行目 : WindowのHintにOpenGLのコアバージョンを指定しています。MAJORが 3 ,MINORが 2 です。

59~64行目 : もしWindowが生成されなかった時に、JOptionWindowでエラーメッセージを表示します。

GLFWのWindowが生成されない時は、上で指定したOpenGLのバージョンに対応していなかった時です。
そして、エラーメッセージを閉じるとシステムを終了します。


ここから、VAOの処理~~~


97~101行目 : 頂点座標の配列を作成します。

102行目 : VBOの中身となる、FloatBufferをメモリ上に容量(capacity)を頂点座標配列の長さ分(つまり、9個)となるように作成します。

103,104行目 : 作成したバッファーに頂点座標配列を入れ、反転します。「反転」はとても分かりづらい表現ですが、実際に行うことは、「今までに入れた値のところだけ読み込めるようにする」という感じです。この辺のバッファーに関することはいつか書きます。いつか。

106行目 : 頂点の数を入れています。これは、後で描画するときに必要になります。

108行目 : 指定したVAOのIDにVertexArraysを作成します。

int glGenVertexArrays()

この時点では、作成されただけで、何も出来ません。

109行目 : 現在のVertexArraysに先ほどのIDを指定(バインド)しています。

void glBindVertexArray(int array)

111行目 : 指定したVBOのIDにバッファーを作成しています。

int glGenBuffers()

112,113行目 :

void glBindBuffer(int target,int buffer)
void glBufferData(int target,IntBuffer data,int usage)

GL_ARRAY_BUFFER(頂点の配列バッファー)に作成したVBOをバインドして、そのバッファーの中身の設定をしています。(さっきの図でいう、VBO側の設定)

GL_ARRAY_BUFFER
このバッファーが頂点配列バッファーであることを意味します。

2引数目に頂点座標の配列を、3引数目にはこのバッファーがどのように振る舞うか(何回も変更するかなど)を指定します。

第3引数にはGL_●●_〇〇というかたちのGL定数が入り、それらは、、、

   GL_STATIC_〇〇 = 1度しか変更せず、何回も呼び出す。
   GL_DYNAMIC_〇〇 = 何度も変更し、何回も呼び出す。
   GL_STREAM_〇〇 = 1度しか変更せず、数回しか呼び出さない。
という形で、また

   GL_●●_DRAW = プログラムで決めた情報を描画するときについて
   GL_●●_READ = GL側の情報を読み込むときについて
   GL_●●_COPY = GL側の情報を描画するときについて
という形になります。

例えば、、、

GL_STATIC_DRAW
このバッファーは、変更なし、何回も読み込み、描画する用であるとしています。

114行目 : 指定した「頂点情報ポインター」(VertexAttributePointer)を現在のVAOに設定します。

void glVertexAttrbPointer( . . . )

図にもある、この「頂点情報ポインター」は、VAO側の処理で、与えられたVBOをそれらの属性に沿って設定できます。

この「属性」と言うのは、頂点の座標や色、法線、テクスチャの座標などを表していて、それらは第1引数で指定できます。この第1引数も設定によって変えることが出来て…

    GL15.glBindAttribLocation(int program,int index,CharSequence name);

でprogramのindex番目の属性をnameの属性に指定できます。
例えば、

    GL15.glBindAttribLocation(GL20.glCreateProgram(), 5, "TestAttribute");

とすれば、5番目の属性名を"TestAttribute"にすることが出来ます。
この辺のことは、シェーダプログラムなどの時に必要になります。

116,117行目 : GL_ARRAY_BUFFERに0をバインド(つまり、初期状態に戻す)し、VAOも0をバインドします。

これで初期設定を終えます。





今回は、一旦ここまでにします。と言っても後ちょっとなのですが、描画する直前のキリがいいところで次に回します。