将 FreeType GlyphSlot 位图转换为 Vulkan BGRA
Convert FreeType GlyphSlot Bitmap To Vulkan BGRA
我正在尝试将 FreeType GlyphSlot 位图转换为 Vulkan BGRA 格式。
void DrawText(const std::string &text) {
// WIDTH & HEIGHT == dst image dimensions
FT_GlyphSlot Slot = face->glyph;
buffer.resize(WIDTH*HEIGHT*4);
int dst_Pitch = WIDTH * 4;
for (auto c : text) {
FT_Error error = FT_Load_Char(face, c, FT_LOAD_RENDER);
if (error) {
printf("FreeType: Load Char Error\n");
continue;
}
auto char_width = Slot->bitmap.width;
auto char_height = Slot->bitmap.rows;
uint8_t* src = Slot->bitmap.buffer;
uint8_t* startOfLine = src;
for (int y = 0; y < char_height; ++y) {
src = startOfLine;
for (int x = 0; x < char_width; ++x) {
// y * dst_Pitch == Destination Image Row
// x * 4 == Destination Image Column
int dst = (y*dst_Pitch) + (x*4);
// Break if we have no more space to draw on our
// destination texture.
if (dst + 4 > buffer.size()) { break; }
auto value = *src;
src++;
buffer[dst] = 0xff; // +0 == B
buffer[dst+1] = 0xff; // +1 == G
buffer[dst+2] = 0xff; // +2 == R
buffer[dst+3] = value; // +3 == A
}
startOfLine += Slot->bitmap.pitch;
}
}
}
这给我乱码输出。我不确定我需要做什么才能正确转换为 Vulkan B8G8R8A8
。我觉得在我们写入 Vulkan 纹理的缓冲区中从左向右移动是不正确的,也许 Vulkan 期望我以不同的方式将像素添加到缓冲区中?
我明白这段代码会把每个字母写在另一个上面,我会在至少能正确绘制一个字母后利用Slot->advance
实现。
一个问题是你调整每个字符的大小buffer
(这将在新分配的 space 的开头留下以前的数据)但是当存储新字符的数据时 c
你覆盖缓冲区的开始,因为 dst
是 0。你可能想在 resize
调用之前设置 dst
buffer.size()
。
int dst = /*previous buffer size*/;
问题是因为我将 VkImageCreateInfo
tiling
设置为 VK_IMAGE_TILING_OPTIMAL
。将其更改为 VK_IMAGE_TILING_LINEAR
后,我收到了正确的输出。
直接取自https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkImageTiling.html
VK_IMAGE_TILING_OPTIMAL specifies optimal tiling (texels are laid out
in an implementation-dependent arrangement, for more optimal memory
access).
VK_IMAGE_TILING_LINEAR specifies linear tiling (texels are laid out in
memory in row-major order, possibly with some padding on each row).
虽然我现在可能不会渲染垃圾,但我的字母仍然是倒着的,而且看起来是从右到左绘制的,而不是从左到右绘制的。
可以看到右上角的绿色'the'
我正在尝试将 FreeType GlyphSlot 位图转换为 Vulkan BGRA 格式。
void DrawText(const std::string &text) {
// WIDTH & HEIGHT == dst image dimensions
FT_GlyphSlot Slot = face->glyph;
buffer.resize(WIDTH*HEIGHT*4);
int dst_Pitch = WIDTH * 4;
for (auto c : text) {
FT_Error error = FT_Load_Char(face, c, FT_LOAD_RENDER);
if (error) {
printf("FreeType: Load Char Error\n");
continue;
}
auto char_width = Slot->bitmap.width;
auto char_height = Slot->bitmap.rows;
uint8_t* src = Slot->bitmap.buffer;
uint8_t* startOfLine = src;
for (int y = 0; y < char_height; ++y) {
src = startOfLine;
for (int x = 0; x < char_width; ++x) {
// y * dst_Pitch == Destination Image Row
// x * 4 == Destination Image Column
int dst = (y*dst_Pitch) + (x*4);
// Break if we have no more space to draw on our
// destination texture.
if (dst + 4 > buffer.size()) { break; }
auto value = *src;
src++;
buffer[dst] = 0xff; // +0 == B
buffer[dst+1] = 0xff; // +1 == G
buffer[dst+2] = 0xff; // +2 == R
buffer[dst+3] = value; // +3 == A
}
startOfLine += Slot->bitmap.pitch;
}
}
}
这给我乱码输出。我不确定我需要做什么才能正确转换为 Vulkan B8G8R8A8
。我觉得在我们写入 Vulkan 纹理的缓冲区中从左向右移动是不正确的,也许 Vulkan 期望我以不同的方式将像素添加到缓冲区中?
我明白这段代码会把每个字母写在另一个上面,我会在至少能正确绘制一个字母后利用Slot->advance
实现。
一个问题是你调整每个字符的大小buffer
(这将在新分配的 space 的开头留下以前的数据)但是当存储新字符的数据时 c
你覆盖缓冲区的开始,因为 dst
是 0。你可能想在 resize
调用之前设置 dst
buffer.size()
。
int dst = /*previous buffer size*/;
问题是因为我将 VkImageCreateInfo
tiling
设置为 VK_IMAGE_TILING_OPTIMAL
。将其更改为 VK_IMAGE_TILING_LINEAR
后,我收到了正确的输出。
直接取自https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkImageTiling.html
VK_IMAGE_TILING_OPTIMAL specifies optimal tiling (texels are laid out in an implementation-dependent arrangement, for more optimal memory access).
VK_IMAGE_TILING_LINEAR specifies linear tiling (texels are laid out in memory in row-major order, possibly with some padding on each row).
虽然我现在可能不会渲染垃圾,但我的字母仍然是倒着的,而且看起来是从右到左绘制的,而不是从左到右绘制的。