質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

解決済

opengl freetype ライブラリ 描画される文字と描画されない文字がある理由が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

3回答

0グッド

0クリップ

1064閲覧

投稿2021/10/04 14:03

編集2021/10/07 07:22

提示コードですがコメント部のRenderString()で描画するのですがなぜ表示される文字を化ける文字があるのでしょうか?

確認したこと

フォントは正常に読み込めてます。
face->glyph-> の値を確認フォーマット指定を確認
グリフの値をデバッグ

利用ライブラリ

opengl
glew
glfw
glm
freetype
stb

参考サイト:https://learnopengl.com/In-Practice/Text-Rendering
イメージ説明

$ ./GL face->glyph->bitmap.width 0 face->glyph->bitmap.rows 2 face->glyph->bitmap_left 0 face->glyph->bitmap_top 1 face->glyph->advance.x 0 character H pixelSize 30 全て正常と思われる値が出ているため文字数の関係で割愛
#include "../header/Text.hpp" #include <glm/gtc/matrix_transform.hpp> #include <glm/gtx/transform.hpp> #include <GL/glew.h> #include <glm/glm.hpp> #include <uchar.h> #include <iostream> #include <vector> #include <iostream> #include "../header/Window.hpp" #include "../header/Init.hpp" #include "../header/Shader.hpp" #include "../header/Render.hpp" #include "../header/Camera.hpp" #include "../header/Resource.hpp" // ##################################### コンストラクタ ##################################### FrameWork::Text::Text() : FrameWork::Render_2D() { //シェーダー読み込み shader->Input(FrameWork::LoadShader("Shader/2D/BasicText_2D.vert")->data(),FrameWork::LoadShader("Shader/2D/BasicText_2D.frag")->data()); vertex = FrameWork::Camera_2D::getVertexAttribute(); vertex->resize(6); //頂点 GLint attrib = shader->getAttribLocation("vertexPosition"); glEnableVertexAttribArray(attrib); glBufferData(GL_ARRAY_BUFFER, vertex->size() * sizeof(VertexAttribute), vertex->data(), GL_DYNAMIC_DRAW); glVertexAttribPointer(attrib, 4, GL_FLOAT, GL_FALSE, 11 * sizeof(GLfloat), (GLvoid*)0); shader->setBindAttribLocation("vertexPosition"); //UV attrib = shader->getAttribLocation("vertexUV"); glEnableVertexAttribArray(attrib); glBufferData(GL_ARRAY_BUFFER, vertex->size() * sizeof(VertexAttribute), vertex->data(), GL_DYNAMIC_DRAW); glVertexAttribPointer(attrib, 4, GL_FLOAT, GL_FALSE, 11 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat) * 2)); shader->setBindAttribLocation("vertexUV"); } // ##################################### wchar_t型の文字列を取得 ##################################### std::vector<wchar_t> FrameWork::Text::getWchar_t(const char* str) { std::vector<wchar_t> newText(0); int i, j, f; for (i = 0, j = 0; str[j] != '\0'; i++, j += f) { wchar_t t; f = (int)mbrtowc(&t, &str[j], (size_t)MB_CUR_MAX, nullptr); newText.push_back(t); } newText.push_back(L'\0'); return newText; } // ##################################### 固定長文字列 描画 ##################################### void FrameWork::Text::DrawString(glm::vec2 pos) { RenderString(pos); } void FrameWork::Text::setString( const byte pixelSize, const glm::lowp_u8vec4 color, const char* args,...) { char buf[1024] = { '\0' }; va_list va; va_start(va,args); vsprintf(buf,args,va); va_end(va); std::vector<wchar_t> wc = getWchar_t(buf); //wchar_t型 取得 setTexture(wc,text,color,pixelSize); //テクスチャ 設定 } // ##################################### テクスチャ 設定 ##################################### void FrameWork::Text::setTexture(const std::vector<wchar_t>& wc, std::vector<Character>& text, const glm::lowp_u8vec4 color, const byte pixelSize) { for (std::vector<wchar_t>::const_iterator itr = wc.begin(); itr != wc.end(); itr++) { FT_Face face = LoadFont("Font/SourceHanCodeJP.ttc"); FT_Set_Pixel_Sizes(face, 0, pixelSize); FT_Load_Glyph(face, FT_Get_Char_Index(face, *itr), FT_LOAD_RENDER); printf("face->glyph->bitmap.width %ld\n",face->glyph->bitmap.width); printf("face->glyph->bitmap.rows %ld\n",face->glyph->bitmap.rows); printf("face->glyph->bitmap_left %ld\n",face->glyph->bitmap_left); printf("face->glyph->bitmap_top %ld\n",face->glyph->bitmap_top); printf("face->glyph->advance.x %ld\n",face->glyph->advance.x); printf("character %c\n",*itr); printf("pixelSize %ld\n",pixelSize); printf("\n\n\n"); Character ch = { 0, glm::lowp_u8vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows), glm::lowp_u8vec2(face->glyph->bitmap_left, face->glyph->bitmap_top), (unsigned short)face->glyph->advance.x, *itr, color, pixelSize }; glGenTextures(1, &ch.textureID); glBindTexture(GL_TEXTURE_2D, ch.textureID); glActiveTexture(GL_TEXTURE0); glTexImage2D ( GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width, face->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer ); //テクスチャタイプを設定 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); text.push_back(ch); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ##################################### 文字列を描画 ##################################### void FrameWork::Text::RenderString(glm::vec2 pos) { if (text.size() > 0) { vertex->resize(6); //色をRGBにして位置を反転 int y = pos.y; for (std::vector<Character>::const_iterator itr = text.begin(); itr->character != '\0'; itr++) { pos.y = FrameWork::windowContext->getSize().y - y - itr->pixelSize; #define SCALE 1.0f //文字の大きさ float xpos = pos.x + itr->bearing.x * SCALE; float ypos = pos.y - (itr->size.y - itr->bearing.y) * SCALE; float w = itr->size.x * SCALE; float h = itr->size.y * SCALE; vertex->at(0).position[0] = xpos; vertex->at(0).position[1] = ypos + h; vertex->at(0).uv[0] = 0.0f; vertex->at(0).uv[1] = 0.0f; vertex->at(1).position[0] = xpos; vertex->at(1).position[1] = ypos; vertex->at(1).uv[0] = 0.0f; vertex->at(1).uv[1] = 1.0f; vertex->at(2).position[0] = xpos + w; vertex->at(2).position[1] = ypos; vertex->at(2).uv[0] = 1.0f; vertex->at(2).uv[1] = 1.0f; vertex->at(3).position[0] = xpos; vertex->at(3).position[1] = ypos + h; vertex->at(3).uv[0] = 0.0f; vertex->at(3).uv[1] = 0.0f; vertex->at(4).position[0] = xpos + w; vertex->at(4).position[1] = ypos; vertex->at(4).uv[0] = 1.0f; vertex->at(4).uv[1] = 1.0f; vertex->at(5).position[0] = xpos + w; vertex->at(5).position[1] = ypos + h; vertex->at(5).uv[0] = 1.0f; vertex->at(5).uv[1] = 0.0f; shader->setEnable(); glBufferSubData(GL_ARRAY_BUFFER, 0, vertex->size() * sizeof(VertexAttribute), vertex->data()); shader->setUniform4f("uFragment", GetGlColor((glm::vec4)itr->color)); shader->setUniformMatrix4fv("uViewProjection", glm::ortho(0.0f, FrameWork::windowContext->getSize().x, 0.0f, FrameWork::windowContext->getSize().y)); glBindTexture(GL_TEXTURE_2D, itr->textureID); glDrawArrays(GL_TRIANGLES, 0, vertex->size()); glBindTexture(GL_TEXTURE_2D, 0); shader->setDisable(); pos.x += ((itr->advance >> 6) * SCALE); //次のグリフに進める #undef SCALE } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ##################################### デストラクタ ##################################### FrameWork::Text::~Text() { }
#ifndef ___TEXT_HPP_ #define ___TEXT_HPP_ #include <iostream> #include <stdio.h> #include <vector> #include <stdarg.h> #include <map> #include <glm/glm.hpp> #include <ft2build.h> #include FT_FREETYPE_H #include "Help.hpp" #include "Render.hpp" #include "VertexData.hpp" /*######################################################################### # 文字描画クラス 説明 文字を描画する ###########################################################################*/ namespace FrameWork { class Text : public FrameWork::Render_2D { private: //文字 構造体 typedef struct { GLuint textureID; // グリフのテクスチャID glm::lowp_u8vec2 size; // グリフサイズ glm::lowp_u8vec2 bearing; // グリフのベースライン unsigned short advance; // 次のグリフまでのオフセット wchar_t character; // 文字 glm::lowp_u8vec4 color; // 描画色 byte pixelSize; // ピクセルサイズ }Character; public: Text(); //コンストラクタ ~Text(); //デストラクタ void setString(const byte pixelSize, const glm::lowp_u8vec4 color, const char* args,...); void DrawString(glm::vec2 pos); private: std::vector<wchar_t> getWchar_t(const char* str); void setTexture(const std::vector<wchar_t>& wc, std::vector<Character>& text, const glm::lowp_u8vec4 color, const byte pixelSize); void RenderString(glm::vec2 pos); std::vector<Character> text; }; }; #endif

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

2021/10/15 22:11

こちらの質問が複数のユーザーから「過去の低評価」という指摘を受けました。

回答3

1

face->glyph->bitmap.buffer

これがどんなフォーマットのデータになってるのか知りませんが,
テクスチャのピクセルデータのフォーマット設定(提示コードに見当たらないが)と食い違っているのでは?
(e.g. padding とか)


一応,↑のように想像する理由を書いておく.

  • 示された画像で変になってる文字の具合を見るに,各行の先頭のbyte位置が(行ごとに一定量ずつ)ずれているように見える

このような絵面になるバグは,"Padding" の扱いをミスった画像表示コードを書いた場合によくみられるものである.

  • 示された画像で変になってる文字の幅を見てみると,全て4の倍数ではない.

対して,まともに描画できている文字の幅(ってどこからどこまでだよ?っていうのはあるが,とりあえず余白を一切含まない幅)を見てみると,こちらは全て4の倍数になっている.
これも,4byteアライン関係なんじゃねーの? と推測する材料になる.

投稿2021/10/05 06:05

編集2021/10/06 04:52
fana

総合スコア10645

退会済みユーザー👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

退会済みユーザー

退会済みユーザー

2021/10/05 09:18

確認したのですがだめでした。
int32_t

2021/10/05 09:24

何を確認して何を試したのか具体的に書きましょう。
fana

2021/10/05 09:39

話が違うのであれば 「そもそもこれはこうでこうなんだから,そんな話じゃねーんだよ」といった形に,しっかりと論破してください. その暁には「間違っている」という理由で低評価を入れても良いでしょう.
退会済みユーザー

退会済みユーザー

2021/10/05 10:23

文字のフォーマットが食い違っているか確認しましたが問題ありませんでした。またフォントとデータをttfしましたが同じでした。
int32_t

2021/10/05 12:41 編集

> 文字のフォーマットが食い違っているか確認しましたが それじゃあ答えになっていません。 この回答について確認するとしたら、 「FreeTypeのドキュメントの〜のページに書いてあるとおりbufferが指す先は1ピクセルがnバイトで1行がmバイトアラインメントです。OpenGLのドキュメント〜に書いてあるとおり glTexImage2D(..., GL_RED, GL_UNSIGNED_BYTE, ...) の場合に受け付ける形式は1ピクセルがnバイトで1行がmバイトアラインメントです。よって形式は一致しているはずです」というような返答になるはずです。
退会済みユーザー

退会済みユーザー

2021/10/05 12:51

すいませんでした。
fana

2021/10/06 01:21

…というか,ふつーは まずそういうことを調べて →そういう話ならこうすればいけるハズっていう確信をもって →実装する んじゃないかな. (どうすればいけるのか知らんけども,まともに動くコードを書くぜ! ってのは無理すぎる)
退会済みユーザー

退会済みユーザー

2021/10/06 02:44

ちゃんと考えて調べて分からないので質問しているのですがすいませんでした。
fana

2021/10/06 03:00

いや,だから, 調べたり考えたりしたならば,具体的にその内容を 「調査した結果こういうことになってるんだから,これで合ってるはずだと俺は考えるわけだが」とかなんとか示してくれないと いつまでたっても話が止まったままなのだが… …ってだけの話なんだけど.(何故謝る?)
退会済みユーザー

退会済みユーザー

2021/10/06 03:59

何を間違ているのか検討が付かないのです。
fana

2021/10/06 04:14

あなたが何を間違えているか? そんなことはどうでもよい. (今そんな話はしていない) 私が「こういう話はないですか?」という回答を書いた. で,それに対して,あなたが > 文字のフォーマットが食い違っているか確認しましたが問題ありませんでした。またフォントとデータをttfしましたが同じでした。 と述べた. つまり,あなたは 何かを確認して,その結果から,この回答の内容はプログラムの現動作の原因ではなさそうだ と判断したのでしょう? そのことはそれで良い. 今ここで問題にしているのは,この記述だと内容が具体的ではないっていう,その一点だけ.
int32_t

2021/10/06 04:29

> 何を間違ているのか検討が付かないのです。 何を間違えているのかわからないから、調査して事実を積み重ねて間違えている箇所を見つけるのです。何を調査したらいいかは私や fana さんの回答が取っ掛かりとなると思います。 回答の意味がわからなかったら、適当なこと言ってごまかすのではなくて、「わからない」と言っていいんですよ。
fana

2021/10/06 04:57 編集

回答の内容を想像するに至った経緯を追記した. GL側が4byteアラインを要求としている状況に対して,そこに与えているデータ側にはpaddingが無い ような場合 に起きる典型的な現象「に見える」のだ.
fana

2021/10/06 05:05

"padding" がどうの…という話が何のことを言ってるのかわからない場合には 「bitmap padding」とかでググるとよいでしょう.
fana

2021/10/06 05:18

なんだろう,単に, 「ここのドキュメントを見たら〇〇と書いてあった.それは▲▲という意味だと読めるので,■■なハズ」 みたいな現時点の考えを言ってくれれば, 「確かにそうですね.であれば原因はこの回答の内容とは違うところにあるのでしょう」と完結するなり 「いや,そこは▲▲という意味なのではなくて,△△だと書かれているのですよ.だから……」とか何かしら話が進むなりし得るんだけど? ……って言ってるだけなんだけども,何故ここで話を止めるのか? 「もう話を進めたくない」っていうならそれで構わないので,そのように意思表示してくれればそれでOKだし.
退会済みユーザー

退会済みユーザー

2021/10/06 06:21

(そういう地道な調査とデバッグ出来る人間なら何百回も質問しないと思う)
SaitoAtsushi

2021/10/07 07:25

この質問者は頻繁にアカウントを取り直して評価をわからなくするという悪質行為を繰り返していて、低評価を付けられないように態度を改めるということをしません。 指摘するだけ徒労です。 ただ、 Teratail は「価値のあるコンテンツを世の中に残し届ける事」をコンセプトとするということを提示しており、これは質問者に返答するというだけではなく質問のやり取りが後に読む人の役に立つものになることを目指すという意味だと思われますので、コンテンツとして有用となりうる返答が出来ると思ったら (たとえ質問者自身には身につかなくても) こたえる甲斐はあるんじゃないでしょうか。

1

デバッグを丸投げしないで、自分で調べられることは調べましょう。

画像を見る限り、画像の横幅の処理がなにかおかしいのだと推測できます。うまく描画できる文字とできない文字でface->glyph->bitmap.width がどう違うかパターンを見つけるのが調査の第一歩でしょう。

投稿2021/10/05 00:17

int32_t

総合スコア17111

退会済みユーザー👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

ベストアンサー

下記の関数を用いることによって解決しました。
テクスチャがすべて4バイトの配置である必要があります。たとえば、サイズは常に4バイトの倍数です。通常、ほとんどのテクスチャの幅は4の倍数であるか、ピクセルあたり4バイトを使用するため、これは問題にはなりませんが、ピクセルあたり1バイトしか使用しないため、テクスチャは任意の幅を持つことができます。アンパックアライメントをに設定1することで、アライメントの問題(セグメンテーション違反の原因となる可能性があります)がなくなります。

glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

投稿2021/10/07 07:56

退会済みユーザー

退会済みユーザー

総合スコア0

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

2021/12/19 17:34

こちらの回答が複数のユーザーから「過去の低評価」という指摘を受けました。

回答へのコメント

int32_t

2021/10/07 08:01 編集

直ってよかったですね。 回答の文章は参考ページの翻訳ですね。 何が問題で、どうしてこれで直るのか本当に理解できましたか? 理解してないと、同じようなトラブルに何度でもひっかかりますよ。
fana

2021/10/07 09:54

結局私の回答が正解だったんじゃん?
退会済みユーザー

退会済みユーザー

2021/10/07 10:23

そうですね。アライメントという概念を知りませんでした。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。