GLFLによるOpenGL入門:第5章 図形の描画
5.1 OpenGL の図形データ
図形データは頂点属性(attributeで表す)
位置、色、法線ベクトル
attributeを転送されるGPUメモリを
頂点バッファという
多分これは誤植で頂点バッファなのでは?
attributeにはいろいろ与えられる
「図形データ」の描画
描画手順
>(1) glGenVertexArrays() で頂点配列オブジェクトを作成する。
構造体を登録する
>(3) glGenBuffers() で頂点バッファオブジェクトを作成する。
>(4) 作成した頂点バッファオブジェクトを glBindBuffer() で結合する
>(5) glBufferData() で頂点バッファオブジェクトにデータ (頂点属性) を転送する
>(6) 頂点バッファオブジェクトを glVertexAttribPointer() で attribute 変数に関連づける
>(7) 頂点配列オブジェクトを結合して描画命令 (ドローコール) を実行する
完成したプログラムを眺めてみると、1-6は図形データObjectのコンストラクタで実装されている
cppglGenVertexArrays(1, &vao); // (1)
glBindVertexArray(vao); // (2)
glGenBuffers( // (3)
1, //作成するVBOの数
&vbo // VBOを格納する配列の先頭アドレス
);
// VBOの内容を描画に使う頂点属性として使うのでGL_ARRAY_BUFFERを指定する
glBindBuffer(GL_ARRAY_BUFFER, vbo); // (4)
// VBOのメモリを確保し、データ(ここではvertex)を転送する
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertexcount, vertex, GL_STATIC_DRAW); //(5)
// 結合されているVBOをvertex shaderのin変数(attribute変数)から参照できるようにする
// attribute変数がデータを取り出すVBOを設定する
glVertexAttribPointer( // (6)
// glBindAttribLocation で指定したattribute変数の場所
// vertex shaderのメンバpositionのindexは0に指定しているのでこっちも0にする
0,
size, GL_FLOAT, GL_FALSE, 0, 0);
(7)は Shape->draw()
で実行される
作成したプログラムのよくわからない点は、(2)がObjectのコンストラクタ以外の他にdraw()の直前に再度指定していること
5.2.4 頂点配列オブジェクトの作成
VBOとattribute変数の紐付け
glVertexAttribPointer
でのindexを glBindAttribLocation
のindexと同じにしなければいけない
まず、これらがvertex shaderとプログラムのオブジェクト(position)が紐づいている
point.vert#version 150 core
in vec4 position;
void main()
{
gl_Position = position;
}
cpp glBindAttribLocation(
program,
0, // index
"position" // point.vertのattribute変数の名前(in vec4 position)
);
Object.hClass Object { // VAO, VBOを定義
public:
Object(GLint size, GLsizei vertexcount, const Vertex *vertex) {
// 略
glVertexAttribPointer(
// glBindAttribLocation で指定したattribute変数の場所
// vertex shaderのメンバpositionのindexは0に指定しているのでこっちも0にする
0, // index
size, GL_FLOAT, GL_FALSE, 0, 0);
このObjectがどうつながるのかわかっていない
>頂点バッファに関する処理がどのような流れで行なわれていくのかを時系列に並べてみると、おおよそ次のような流れになります。
> WebGL のメソッドを使って VBO を生成
> WebGL のメソッドを使い VBO に配列のデータを転送
> 頂点シェーダ内の attribute 変数と VBO を紐付ける
VBOのindex 0と、vertex shaderのin変数 position
が glBindAttribLocation()
でinexを指定してbindされる
glBindAttribLocation()のindexはなんのindexなんだっけ?
objectの使い方
Object::Vertex型の配列 rectangleVertex
を作るときの型の指定に利用
main.cpp// 矩形の頂点の位置
constexpr Object::Vertex rectangleVertex[] = {
{-0.5f, -0.5f},
{0.5f, -0.5f},
{0.5f, 0.5f},
{ -0.5f, 0.5f }
};
図形の描画クラスのコンストラクタ
Shape.h.cpp Shape(GLint size, GLsizei vertexcount, const Object::Vertex *vertex) :
// 初期化する
object(new Object(size, vertexcount, vertex)),
vertexcount(vertexcount) {
}
変数objectをObjectで補完している
図形を描画する時にはあらかじめVAOを結合しておく必要がある
Shapeを作成するときにObjectのコンストラクタで
Shapeをdrawすると glBindVertexArray(vao)
が呼ばれる
これ呼ぶ必要あるの?
ある。別の図形を書く前にbindしなおしておかないと他の図形の頂点情報が混じる可能性がある
vaoとvboがどう紐づいているの?陽に紐づけていないけど
vaoをbindするとそのあとはvaoに頂点情報が登録されるようだ
>バインドが完了すると、ここから先に行うすべての頂点関連処理(主に Attribute 系)を通じて VAO に頂点情報が登録されていきます。先ほど登場した自前の関数の中身で行っていたように、gl.bindBufferやgl.enableVertexAttribArray、gl.vertexAttribPointerなどを適宜呼び出しましょう。これらのメソッドが呼び出されるたびに VAO に情報がひとまとめにされて格納されていきます。
Shape->draw()
でvaoをバインドし直しているのも別の図形を書く前にbindしなおしておかないと他の図形の頂点情報が混じる可能性があるということだろう
この文章は、vaoをbindした後にvboをbindするとvaoの管理下にvboがおかれるという意味
>頂点配列オブジェクトを結合 (glBindVertexArray()) した後、頂点バッファオブジェクトを結合 (glBindBuffer()) することによって、頂点配列オブジェクトに頂点バッファオブジェクトが組み込まれます。
5.2.5 描画の実行
描画する図形データを保持したVAOを基本図形の種類を選んで描画する
やっと図形を出すことができた
ここまで書かないと試せないのは嫌だなぁ