この図では三角形を2枚書いて、IBOを使わない場合、定義しなければいけない頂点数は6となる。
IBOを使うと共通に使用する頂点をまとめて4個にできる。
基本は以下と同じ:
GLSLを試す (1)
注目すべき点は、
・頂点バッファの定義は普通と同じ形式で良い
・IBOを使うからと言って、バーテクスシェーダ、フラグメントシェーダに変更を加える必要は無い
・頂点バッファなどを準備する時に、一緒にGL_ELEMENT_ARRAY_BUFFERでIBOを作成する
・glDrawArraysではなくglDrawElementsを使用する
// バッファとデータ typedef GLfloat points_t[3]; GLuint vertexbuffer;//バッファのIDを格納する変数 GLuint colorbuffer;//バッファのIDを格納する変数 GLuint indexbuffer;//三角形を頂点IDで表現するバッファのIDを格納する変数 //////////////////////////////////////////////////
// データの準備
void prepare_buffers() { points_t position[4]; points_t color[4]; //頂点座標 position[0][0] = 0; position[0][1] = 0.5; position[0][2] = 0; position[1][0] = 0.5; position[1][1] = -0.5; position[1][2] = 0; position[2][0] = -0.5; position[2][1] = -0.5; position[2][2] = 0; position[3][0] = 0; position[3][1] = -1.0; position[3][2] = 0; //色 color[0][0] = 1.0; color[0][1] = 0.0; color[0][2] = 0.0; color[1][0] = 0.0; color[1][1] = 1.0; color[1][2] = 0.0; color[2][0] = 0.0; color[2][1] = 0.0; color[2][2] = 1.0; color[3][0] = 1.0; color[3][1] = 1.0; color[3][2] = 1.0; //頂点座標のバッファ glGenBuffers(1, &vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glBufferData( GL_ARRAY_BUFFER, 4 * 3 * sizeof(GLfloat), position, GL_STATIC_DRAW); //頂点カラーのバッファ glGenBuffers(1, &colorbuffer); glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); glBufferData( GL_ARRAY_BUFFER, 4 * 3 * sizeof(GLfloat), color, GL_STATIC_DRAW);
//頂点Indexで表現した三角形一覧 // △012,△213 の二つを定義 GLuint triangle_elements[] = { 0,1,2 , 2,1,3 }; //三角形の頂点IDのバッファ const size_t triangle_elements_memsize = sizeof(triangle_elements);
glGenBuffers(1, &indexbuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer); glBufferData( GL_ELEMENT_ARRAY_BUFFER, triangle_elements_memsize, // バッファのメモリ上のバイト数を求める triangle_elements, //バッファへのポインタ GL_STATIC_DRAW ); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void display(void) { glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); // シェーダを使う glUseProgram(ProgramID); // 頂点バッファ:頂点 glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glVertexAttribPointer( 0, // シェーダ内のlayoutとあわせる 3, // 1要素の要素数(x,y,z)で3要素 GL_FLOAT, // タイプ GL_FALSE, // 正規化しない(データが整数型の時) 0, // ストライド (void*)0 // 配列バッファオフセット ); // カラーバッファを有効にする glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); glVertexAttribPointer( 1, // シェーダ内のlayoutとあわせる 3, // 1要素の要素数(r,g,b)で3要素 GL_FLOAT, // タイプ GL_FALSE, // 正規化しない(データが整数型の時) 0, // ストライド (void*)0 // 配列バッファオフセット );
// 三角形を描きます! glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer); //int size; //glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); glDrawElements( GL_TRIANGLES, 6, // 頂点数。size / sizeof(GLuint) の式でも頂点数を算出できる。 GL_UNSIGNED_INT, 0 );
glDisableVertexAttribArray(0);//バッファを無効にする glDisableVertexAttribArray(1); glFlush(); }
各シェーダはIBOの使用の有無で書き換える必要は無い。
#version 460 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 incolor; out vec4 vertexColor; void main() { gl_Position = vec4(aPos, 1.0); vertexColor = vec4(incolor, 1.0); }
#version 460 core out vec4 FragColor; in vec4 vertexColor; void main() { FragColor = vertexColor; }