頂点配列による描画とVBOを利用した描画を考察。
固定機能でマルチテクスチャなんかやってられんな・・・というのが1点。
指定が回りくどいにも程があるのとAPIの呼び出し順序がカオス過ぎる。
いづれにしても可変頂点フォーマットを実現するには、頂点要素は分離しておく
必要性がありそうだ。
■頂点配列による描画
頂点配列描画用データ
// 位置 float position[] = { -1.0f, +1.0f, 0.0f, +1.0f, +1.0f, 0.0f, -1.0f, -1.0f, 0.0f, +1.0f, -1.0f, 0.0f }; // 法線 float normal[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }; // テクスチャ座標0 float texcoord0[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; // テクスチャ座標1 float texcoord1[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; // インデクス GLuint indices[] = { 0, 1, 2, 2, 1, 3 }; // 三角形の数 size_t ntri = sizeof(indices) / sizeof(GLuint) / 3; // テクスチャ GLuint texture[2];
頂点配列描画
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // 頂点 glVertexPointer(3, GL_FLOAT, 0, position); // 法線 glNormalPointer(GL_FLOAT, 0, normal); // テクスチャ0 glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, 0, texcoord0); // テクスチャ1 glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[1]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glClientActiveTexture(GL_TEXTURE1); glTexCoordPointer(2, GL_FLOAT, 0, texcoord1); // 描画 glDrawElements(GL_TRIANGLES, ntri * 3, GL_UNSIGNED_INT, indices); // 後始末 glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
■VBOによる描画
頂点配列描画用データにVBOを追加
GLuint buffers[5];
VBOの初期化
glGenBuffers(5, buffers); glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(normal), normal, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, buffers[2]); glBufferData(GL_ARRAY_BUFFER, sizeof(texcoord0), texcoord0, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, buffers[3]); glBufferData(GL_ARRAY_BUFFER, sizeof(texcoord1), texcoord1, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[4]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
VBOで描画
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // 頂点 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); glVertexPointer(3, GL_FLOAT, 0, 0); // 法線 glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); glNormalPointer(GL_FLOAT, 0, 0); // テクスチャ0 glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glClientActiveTexture(GL_TEXTURE0); glBindBuffer(GL_ARRAY_BUFFER, buffers[2]); glTexCoordPointer(2, GL_FLOAT, 0, 0); // テクスチャ1 glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[1]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glClientActiveTexture(GL_TEXTURE1); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[3]); glTexCoordPointer(2, GL_FLOAT, 0, 0); // インデクス glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[4]); // 描画 glDrawElements(GL_TRIANGLES, ntri * 3, GL_UNSIGNED_INT, 0); // 後始末 glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
■GLSL(シェーダ)版
実はGLSLは初めてだったりする。
DirectXではHLSLやHLSLになる前のアセンブリシェーダは使い倒していたのだが
すっかり疎遠になってほぼ忘れかけている(汗
そんな私でもGLSLに限らず細かいことは床井先生のところを見れば万事問題解決!
テクスチャ座標0と1が異なる場合なのは上記と変わらず。
テスト中にglGetUniformLocationから-1(そんなシンボルないよ)と返ってきたが、シェーダの
コンパイル時に最適化が掛かって実質無意味(例えば利用されていない)なものは削除されている
かも知れない。
やっぱり固定機能でなんて書いていられない。
シェーダの利点としてベクトルなんかは内部で4成分のレジスタとして表現してあるから
RGBであるとかRGBAであるとかあまり意識しなくて済むのは非常に楽。
というかOpenGLの固定機能は無駄に神経をすり減らされて疲れる。
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); // 頂点 glVertexPointer(3, GL_FLOAT, 0, position); // 法線 glNormalPointer(GL_FLOAT, 0, normal); // テクスチャ座標0 glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); glClientActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texcoord0); // テクスチャ座標1 glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[1]); glClientActiveTexture(GL_TEXTURE1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texcoord1); // 描画1 glUseProgram(gl2Program); glPushMatrix(); glTranslatef(-1.0f, 1.0f, 0.0f); glDrawElements(GL_TRIANGLES, ntri * 3, GL_UNSIGNED_INT, indices); glPopMatrix(); // 描画2 glUseProgram(gl2Program2); GLint texture0Idx = glGetUniformLocation(gl2Program2, "texture0"); glUniform1i(texture0Idx, 0); GLint texture1Idx = glGetUniformLocation(gl2Program2, "texture1"); glUniform1i(texture1Idx, 1); glPushMatrix(); glTranslatef( 1.0f,-1.0f, 0.0f); glDrawElements(GL_TRIANGLES, ntri * 3, GL_UNSIGNED_INT, indices); glPopMatrix(); // 後始末 glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); glClientActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glUseProgram(0);
マルチテクスチャではないが、シェーダを利用したついでに。
前回利用させて頂いたモデル。
て・・・アレ?
GLSLってJITコンパイルのみ!?
シェーダの手直しが面倒臭過ぎるんだけどどうしたものか。
ログ取れるからコンパイルだけするツールでも作るか・・・。
0 件のコメント :
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。