gpt4 book ai didi

c++ - 从包含内存段的 FreeType 生成的字形

转载 作者:行者123 更新时间:2023-12-01 14:49:43 24 4
gpt4 key购买 nike

使用 FreeType (2.10.1) 在我的游戏引擎中实现文本渲染,我遇到了奇怪的字形,包含重复四次的字母,在 x 轴上镜像并颠倒。

在所需的字母上方似乎有被解释为字形的相邻内存,它在每次运行时都会改变并在某些启动时导致段错误。

这就是我尝试渲染“狮身人面像”这个词时得到的结果。

The word 'sphinx'

这是水平翻转并旋转 180 度的完整例句“黑色 quartz 的狮身人面像,判断我的誓言”。

Example sentence, flipped horizontally and rotated 180 degrees

我已编译this code排除 my MinGW environment being erroneous .

我很确定我对 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;
}

如果提供的代码片段不够用,我很乐意添加更多。
这个项目是开源的,可用 here on GitHub .

最佳答案

您假设 FreeType 始终生成每 channel 8 位的 RGBA 图像,但事实并非如此。

您需要查看 bitmap.pixel_mode看看你得到了什么图像格式。

通常是 FT_PIXEL_MODE_GRAY ,表示每像素 8 位灰度,或 FT_PIXEL_MODE_MONO ,表示每像素 1 位单色。

the manual更多细节。

关于c++ - 从包含内存段的 FreeType 生成的字形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58790715/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com