C++入門者がOpenGLでハマったポイント〜Hello Triangle辺り
開発環境を構築できたら後はチュートリアルサイトや動画の指示に従えば躓くことは無いはず。ただ理解不足で適当なことをやるとどこが悪いのかわからなくなってハマる。
1. 三角形が表示されなかった
VAOとVBOに対する理解不足でGLuint VAO, VBO;
こう一括で宣言してやるのが気に入らずこんな書き方をしてしまった。VAOは頂点データでも入っているんだろうという認識だった。だったらVBOにはUV用のデータでもいれてやれと。
// Create Vertex Array Object GLuint VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5* sizeof(float), (void*)0); glEnableVertexAttribArray(0); // Create Vertex Buffer Object -- TexCoords GLuint VBO; glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(3*sizeof(float))); glEnableVertexAttribArray(1);
正しくはその時点でバインドされているVAOに対して生成したVBOに格納したデータを指すポインタglVertexAttribPointer
を渡すのでこうなる。VAOは様々な頂点データ(座標・カラー・テクスチャ座標)に対する属性を取りまとめる役割があるようだ。
// Create Vertex Array Object GLuint VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); // Create Vertex Buffer Object: Pos - TexCoords GLuint VBO; glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5* sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(3*sizeof(float))); glEnableVertexAttribArray(1);
2. テクスチャが表示されなかった
頂点シェーダープログラムのタイプミス
TexCoordのタイプをvec3
と無意識にやってしまっていた。VSCode拡張でShader languages support for VS Codeを入れるきっかけになる。がこの手のタイプミスは防げなさそう。
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; // vec3にしていたら当然動かなかった
コピペミス
エラーは出ていないのにtexture1,2がビルド直後は表示されても次のlaunchでは表示されない
imageloaderの不具合を疑ってfilepathを相対から絶対アドレスに変更したりしても徒労に終わった
GDBを使おうと思ってCMakeLists.txtへtarget_compile_optionsを追加-Wall -g -O0
でビルドすると警告してくれた
warning: ‘texture2’ may be used uninitialized in this function [-Wmaybe-uninitialized]
該当する箇所は2枚目のテクスチャを生成する手前
GLuint texture2; glGenTextures(2, &texture1); <-------------ここに警告 glBindTexture(GL_TEXTURE_2D, texture2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
見たまんまtexture2
の参照用intを使用せずにtexture1を使ってしまっていた。ただのタイプミスというかコピペミス。
3. まとめ
入門用のコードなら-Wall
付けなくてもいいかと面倒くさがっていた。というかCMakeListsでコンパイラオプションを設定するのを後回しにしていた。-Wall
がついていれば一瞬で解決するミスを数日掛けて追いかけていた。悲しい。