Я пытался принять TrueType Учебник OpenGL в мой движок. Когда я компилирую и запускаю их пример, все работает правильно, но когда я пытался переписать код в свой движок, я продолжаю получать ошибку сегментации. Затем я попытался скопировать их код в мой заголовочный файл Utils, но это не сработало. Я провел небольшую отладку с помощью cout, и похоже, что ошибка происходит в моем методе рендеринга. Сначала я опубликую метод рендеринга, а затем все остальные связанные с TrueType функции. Если тебе нужно что-то спросить, не стесняйся.
Метод рендеринга:
void Util::Font::render(const char *text, Atlas *a, float x, float y, float sx, float sy)
{
glUseProgram(shaderID);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const uint8_t *p;
/* Use the texture containing the atlas */
glBindTexture(GL_TEXTURE_2D, a->tex);
glUniform1i(samplerID, 0);
/* Set up the VBO for our vertex data */
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
point coords[6 * strlen(text)];
int c = 0;
/* Loop through all characters */
for (p = (const uint8_t *)text; *p; p++) {
/* Calculate the vertex and texture coordinates */
float x2 = x + a->c[*p].bl * sx;
float y2 = -y - a->c[*p].bt * sy;
float w = a->c[*p].bw * sx;
float h = a->c[*p].bh * sy;
/* Advance the cursor to the start of the next character */
x += a->c[*p].ax * sx;
y += a->c[*p].ay * sy;
/* Skip glyphs that have no pixels */
if (!w || !h)
continue;
coords[c++] = (point) {
x2, -y2, a->c[*p].tx, a->c[*p].ty};
coords[c++] = (point) {
x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty};
coords[c++] = (point) {
x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h};
coords[c++] = (point) {
x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty};
coords[c++] = (point) {
x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h};
coords[c++] = (point) {
x2 + w, -y2 - h, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty + a->c[*p].bh / a->h};
}
/* Draw all the character on the screen in one go */
glBufferData(GL_ARRAY_BUFFER, sizeof coords, coords, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, c);
glDisableVertexAttribArray(0);}
Инициация шрифта
bool Util::Font::init()
{
if (FT_Init_FreeType(&ft))
{
std::cout << "Failed to load Freetype!" << std::endl;
return false;
}
if (FT_New_Face(ft, "res/fonts/Ubuntu-R.ttf", 0 , &face))
{
std::cout << "Failed to load font file!" << std::endl;
return false;
}
shaderID = Util::Shader::loadShaders("res/shaders/font.vert", "res/shaders/font.frag");
samplerID = glGetUniformLocation(shaderID, "textureSampler");
colorID = glGetUniformLocation(shaderID, "color");
glGenBuffers(1, &vertexBufferID);
font12px = new Atlas(face, 12);
font24px = new Atlas(face, 24);
font48px = new Atlas(face, 48);
return true;
}
Заголовок шрифта внутри Utils.h
namespace Font {
static FT_Library ft;
static FT_Face face;
static GLuint shaderID;
static GLuint samplerID;
static GLuint colorID;
static GLuint vertexBufferID;
static GLuint coordID;
bool init();
struct point {
GLfloat x;
GLfloat y;
GLfloat s;
GLfloat t;
};
struct Atlas {
GLuint tex; // texture object
int w; // width of texture in pixels
int h; // height of texture in pixels
struct {
float ax; // advance.x
float ay; // advance.y
float bw; // bitmap.width;
float bh; // bitmap.height;
float bl; // bitmap_left;
float bt; // bitmap_top;
float tx; // x offset of glyph in texture coordinates
float ty; // y offset of glyph in texture coordinates
} c[128]; // character information
Atlas(FT_Face face, int height) {
FT_Set_Pixel_Sizes(face, 0, height);
FT_GlyphSlot g = face->glyph;
int roww = 0;
int rowh = 0;
w = 0;
h = 0;
memset(c, 0, sizeof c);
/* Find minimum size for a texture holding all visible ASCII characters */
for (int i = 32; i < 128; i++) {
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
fprintf(stderr, "Loading character %c failed!\n", i);
continue;
}
if (roww + g->bitmap.width + 1 >= 1024) {
w = std::max(w, roww);
h += rowh;
roww = 0;
rowh = 0;
}
roww += g->bitmap.width + 1;
rowh = std::max(rowh, g->bitmap.rows);
}
w = std::max(w, roww);
h += rowh;
/* Create a texture that will be used to hold all ASCII glyphs */
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(samplerID, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
/* We require 1 byte alignment when uploading texture data */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/* Clamping to edges is important to prevent artifacts when scaling */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* Linear filtering usually looks best for text */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* Paste all glyph bitmaps into the texture, remembering the offset */
int ox = 0;
int oy = 0;
rowh = 0;
for (int i = 32; i < 128; i++) {
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
fprintf(stderr, "Loading character %c failed!\n", i);
continue;
}
if (ox + g->bitmap.width + 1 >= 1024) {
oy += rowh;
rowh = 0;
ox = 0;
}
glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
c[i].ax = g->advance.x >> 6;
c[i].ay = g->advance.y >> 6;
c[i].bw = g->bitmap.width;
c[i].bh = g->bitmap.rows;
c[i].bl = g->bitmap_left;
c[i].bt = g->bitmap_top;
c[i].tx = ox / (float)w;
c[i].ty = oy / (float)h;
rowh = std::max(rowh, g->bitmap.rows);
ox += g->bitmap.width + 1;
}
fprintf(stderr, "Generated a %d x %d (%d kb) texture atlas\n", w, h, w * h / 1024);
}
~Atlas() {
glDeleteTextures(1, &tex);
}
};
static Atlas *font48px;
static Atlas *font24px;
static Atlas *font12px;
void render(const char *text, Atlas *atlas, float x, float y, float sx, float sy);
}
Задача ещё не решена.
Других решений пока нет …