GLEW、GLM、FreeTypeなどを使って、画面上に日本語を表示させる処理を作っているときに、自分が詰まったことを、記録しておきます。
なお、僕は主に以下のサイトを参考にしながら処理を作成しました。
そもそも英文字が表示されない
"abc"みたいな簡単な英文字が画面に表示されない場合、とりあえず以下のことができているか、チェックしてみてください。
- glTexImage2D 関数でformatとinternalformatを GL_RED にしたか?
- vertex Shaderで、gl_Positionに view projectionもtransfrom matrixなどをかけずに、そのまま頂点座標をわたしたとき、描画されるか?
(描画される場合、view projectionやtransform matrixが間違っている。Uniformを指定する前に、glUseProgram呼び出してる?
描画されない場合、Vertex Arrayなどのほかのところが間違っている。)
2個目のやつで言っていたのは、以下のようなvetex shaderでとりあえず文字列が描画されるか調べてみよ、ということ。
Vertex.vert
#version 330 core
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec2 inTexCoord;
out vec2 fragTexCoord;
void main()
{
vec4 pos = vec4(inPosition, 0.0, 1.0);
gl_Position = pos;
fragTexCoord = inTexCoord;
}
日本語が思ったように表示されない(文字化けする)場合
以下のことを試してみてください。
- true typeのフォントが本当に日本語対応しているか?(SDL TTFで日本語表示できたからと言って、Free Typeでも同じようにやろうと思ったら、日本語が表示できませんでした。なぜかわからない!!)
僕はArial Unicode MSでうまく表示できました。
記事執筆現在では、以下のサイトでダウンロードできます。
- FT_Select_Charmap(mFontFace, ft_encoding_unicode); をコード中に記述してみたか?
- ソースコードのエンコーディングがutf-8か?
- FT_Get_Char_Indexに渡す文字はchar16_tか?
日本語文字列を読み込むイメージとしては以下のような感じです。
struct TexChar {
GLuint texID;
glm::ivec2 Size;
glm::ivec2 Bearing;
unsigned int Advance;
};
std::vector<TexChar> mJapanTexVec;
///////////////////////////////////////////
const char16_t str[] = u"あいうえお"; // 小文字のuを忘れない!!!
for (int i = 0; str[i] != '\0'; i++) {
if (FT_Load_Glyph(mFontFace, FT_Get_Char_Index(mFontFace, str[i]), FT_LOAD_RENDER)) {
std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
exit(-1);
}
GLuint tex;
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE);
glBindTexture(GL_TEXTURE_2D, tex);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// ↓↓↓ GL_REDにする ↓↓↓
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, mFontFace->glyph->bitmap.width, mFontFace->glyph->bitmap.rows,
0, GL_RED, GL_UNSIGNED_BYTE, mFontFace->glyph->bitmap.buffer);
mFontWidth = mFontFace->glyph->bitmap.width;
mFontHeight = mFontFace->glyph->bitmap.rows;
TexChar tc = {
tex,
glm::ivec2(mFontFace->glyph->bitmap.width, mFontFace->glyph->bitmap.rows),
glm::ivec2(mFontFace->glyph->bitmap_left, mFontFace->glyph->bitmap_top),
mFontFace->glyph->advance.x
};
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(tex, 0); // unbind
mJapanTexVec.push_back(tc);
}
文字列を描画する処理は、https://learnopengl.com/In-Practice/Text-Rendering のとおりに作成しました。