glDrawElementsのみを使う想定
glDrawElementsを使う方が速いので描画関数はこれしか使わない。
頂点の設定の流れ
頂点座標、法線、インデックスの場合
VAO,VBO,VBO,EBO って感じで設定する。
VAO
glGenVertexArrays(1, &vao_); glBindVertexArray(vao_); ... glBindVertexArray(0);
VBO
// VBO --- 位置属性 (location = 0) --- glBindBuffer(GL_ARRAY_BUFFER, vbo_positions_); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer( 0, // シェーダー側の layout(location = 0) に対応する番号。 3, // 1 頂点あたりの要素数。ここでは vec3 なので 3。 GL_FLOAT, // データ型。頂点配列の要素が float 型であることを指定。 GL_FALSE, // 正規化フラグ。整数型を 0〜1 に正規化するかどうかを指定するが、float なので不要。 3 * sizeof(float), // ストライド(1 頂点分のバイト幅)。 (void*)0 // バッファ内のオフセット。ここでは VBO の先頭から読む。 ); glEnableVertexAttribArray(0); // VBO --- 法線属性 (location = 1) --- glBindBuffer(GL_ARRAY_BUFFER, vbo_normals_); glBufferData(GL_ARRAY_BUFFER, sizeof(normals), normals, GL_STATIC_DRAW); glVertexAttribPointer( 1, // layout(location = 1) 3, // vec3 GL_FLOAT, GL_FALSE, 3 * sizeof(float), // ストライド(1 頂点分のバイト幅)。 (void*)0 ); glEnableVertexAttribArray(1); ... glBindBuffer(GL_ARRAY_BUFFER, 0); // 解除してもしなくてもよい
EBO
EBOにはVBOのglVertexAttribPointerに相当するものは無い。
なぜならglDrawElementsでオフセットを指定できるから。
またglBufferDataで解除してはいけない
// EBO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
Shader Programの切り替え
glUseProgramで切り替える
Shaderの行列は列優先

Uniform は location を指定できる
画像の読み込みには stb_image.h を使う
単一ヘッダなのでこちらダウンロードしてプロジェクトに追加するだけ。
#include の前に #define をする必要あり。
#define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" int width, height, channels; unsigned char *data = stbi_load("image.png", &width, &height, &channels, 0); if (data) { // 画像データを利用 stbi_image_free(data); }
glTexImage2D - stb_image.h を使用する例
int width, height, channels; unsigned char* data = stbi_load("image0.png", &width, &height, &channels, 0); if (data) { GLenum format = GL_RGB; if (channels == 1) format = GL_RED; else if (channels == 3) format = GL_RGB; else if (channels == 4) format = GL_RGBA; // 画像データを利用 glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(data); }
glTexImage2D - CImage を使用する例
少しハマったのでメモ
CImage の pitch とパディングを考慮して連続バッファにコピーする
あとBGRにする。
unsigned char* src = (unsigned char*)img.GetBits(); std::vector<unsigned char> buffer(width * height * (bpp / 8)); int pitch = img.GetPitch(); for (int y = 0; y < height; ++y) { memcpy(&buffer[y * width * (bpp / 8)], src + y * pitch, width * (bpp / 8)); } glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, buffer.data()); glGenerateMipmap(GL_TEXTURE_2D);