При реализации рендеринга текста в моем игровом движке с использованием FreeType (2.10.1) я сталкиваюсь со странно выглядящими глифами, в которых буква повторяется четыре раза, отражается по оси x и переворачивается вверх ногами.
Вверху над нужной буквой, кажется, находится соседняя память, интерпретируемая как глиф, который меняет каждый запуск и вызывает сбой при некоторых запусках.
Это то, что я получаю, когда пытаюсь отобразитьслово "сфинкс" .
Вот пример полного предложения "сфинкс из черного кварца, суди мою клятву" перевернул горизонтальнои повернул на 180 градусов.
Я скомпилировал этот код , чтобы исключить моя среда MinGW ошибочна .
Я уверен, что мое использование OpenGL не является проблемой, так как мой код загрузки текстур и рендеринга работает для других изображений.
В настоящее время я упаковываю важные биты FT_Glyph_Slot
в структуру с именем Letter
и кеширую эту структуру. Удаление обтекания и кэширования не устранило ошибку.
Вот соответствующие фрагменты кода:
Инициализация FreeType.
// src/library/services/graphics/font/FreeType.cpp
void FreeType::initialize() {
Logger::info("Initializing FreeType");
if (FT_Init_FreeType(&m_library)) {
Logger::error("Could not initialize FreeType");
return;
}
}
void FreeType::useFont(const std::string& fontName, const unsigned int fontSize = 42) {
Logger::info("Loading font " + fontName);
if (FT_New_Face(m_library, fontName.c_str(), 0, &m_currentFace)) {
Logger::error("Could not open font " + fontName);
return;
}
FT_Set_Pixel_Sizes(m_currentFace, 0, fontSize);
}
Код, использующий FreeType длясоздать Letter
.
// src/library/services/graphics/font/FreeType.cpp
std::shared_ptr<Letter> FreeType::getLetter(unsigned long character) {
// Try loading from cache
if (std::shared_ptr<Letter> letter = m_letters.get(std::to_string(character))) {
return letter;
}
return loadLetter(character);
}
std::shared_ptr<Letter> FreeType::loadLetter(unsigned long character) {
if (FT_Load_Char(m_currentFace, character, FT_LOAD_RENDER)) {
Logger::error("Could not load character " + std::string(1, character));
return std::shared_ptr<Letter>();
}
FT_GlyphSlot& glyph = m_currentFace->glyph;
Letter letter = {
.id = character,
.textureId = 0,
.bitmap = {
.buffer = glyph->bitmap.buffer,
.width = glyph->bitmap.width,
.height = glyph->bitmap.rows
},
.offset = {
.x = glyph->bitmap_left,
.y = glyph->bitmap_top
},
.advance = {
.x = glyph->advance.x,
.y = glyph->advance.y
}
};
std::shared_ptr<Letter> sharedLetter = std::make_shared<Letter>(letter);
cache(sharedLetter);
return sharedLetter;
}
void FreeType::cache(std::shared_ptr<Letter> letter) {
m_letters.add(std::to_string(letter->id), letter);
}
Графическая система, инициализирующая FreeType
// src/library/services/graphics/opengl/OpenGLGraphics.cpp
void OpenGLGraphics::initialize(int windowWidth, int windowHeight) {
// ... OpenGL initialization
m_freeType.initialize();
m_freeType.useFont("../../../src/library/assets/fonts/OpenSans-Regular.ttf");
}
Код, получающий Letter
в текстовом редакторе.
// src/library/services/graphics/opengl/OpenGLGraphics.cpp
void OpenGLGraphics::drawText(const std::string &text, Vector2f location) {
for (auto iterator = text.begin(); iterator < text.end(); ++iterator) {
std::shared_ptr<Letter> letter = m_freeType.getLetter(*iterator);
if (!letter->textureId) {
std::shared_ptr<Texture> tex =
ImageLoader::loadFromCharArray(
letter->bitmap.buffer,
letter->bitmap.width,
letter->bitmap.height
);
letter->textureId = tex->id;
m_freeType.cache(letter);
}
// ... OpenGL text rendering
}
}
Код для генерации Texture
из bitmap->buffer
.
// src/library/services/graphics/opengl/util/ImageLoader.cpp
std::shared_ptr<Texture>
ImageLoader::loadFromCharArray(const unsigned char *image, const unsigned int width, const unsigned int height) {
std::shared_ptr<Texture> texture = std::make_shared<Texture>();
texture->width = width;
texture->height = height;
glGenTextures(1, &texture->id);
glBindTexture(GL_TEXTURE_2D, texture->id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
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_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
return texture;
}
Если предоставленных фрагментов кода не должно быть достаточно, я с удовольствием добавлю еще. Этот проект с открытым исходным кодом и доступен здесь, на GitHub .