简体   繁体   English

无法将 Freetype 加载的大多数 fonts 的位图作为纹理上传到 OpenGL。 然而,其他 fonts 工作完美。 (附图片示例)

[英]Unable to upload bitmaps from most fonts loaded by Freetype to OpenGL as textures. However, other fonts work perfectly. (with image examples)

I'm facing this issue for months.我几个月来一直面临这个问题。 Every font I load with freetype works fine, I can prove that to myself by writing the glyphs to a BMP file using the stb_write_bmp from the STB library.我用 freetype 加载的每种字体都可以正常工作,我可以通过使用 STB 库中的 stb_write_bmp 将字形写入 BMP 文件来向自己证明这一点。 I can see all hundreds of glyph bitmaps written correctly in my folder.我可以在我的文件夹中看到所有正确写入的数百个字形位图。

OpenGL, on the other hand, is unable to load the textures from specific fonts, and I see no explainable reason as to why some load and others don't.另一方面,OpenGL 无法从特定的 fonts 加载纹理,我看不出有什么可以解释的原因来解释为什么有些加载而有些不加载。 I have done everything to try and solve it but it keeps happening.我已尽一切努力尝试解决它,但它一直在发生。 The textures simply don't load at all.纹理根本不加载。 I'm doing exactly the same procedure for every font, so I should be getting the same results.我对每种字体都执行完全相同的程序,所以我应该得到相同的结果。

Examples: (with maximum of 0.1 alpha for debugging invisible squares like the last ones)示例:(最大 0.1 alpha 用于调试像最后一个一样的不可见方块)

Cantarell-Regular.ttf Cantarell-Regular.ttf

CPMono_v07-Light.otf CPMono_v07-Light.otf

SourceSansPro-Regular.ttf (bugged - no texture) SourceSansPro-Regular.ttf (窃听 - 无纹理)

RobotoCondensed-Regular.ttf (bugged - no texture) RobotoCondensed-Regular.ttf (窃听 - 无纹理)

What do the loaded fonts have in common?加载的 fonts 有什么共同点? It's not the extension, at least, since I can render cantarell's TTF files.它不是扩展名,至少,因为我可以渲染 cantarell 的 TTF 文件。 All of them, even the ones that the texture don't load, are correctly written as BMP if i send them to the STB function. So why are the last ones not loaded by the GL?如果我将它们发送到 STB function,所有这些,即使是纹理不加载的那些,都被正确地写为 BMP。那么为什么最后一个没有被 GL 加载? This makes no sense to me... there's no consistency except that the ones that don't load, never load, and the ones that load, always load.这对我来说毫无意义......除了那些不加载的,从不加载的,以及加载的,总是加载的之外,没有一致性。 But I see nothing that could have different effects on different fonts, and this is confusing me a lot.但是我看不出对不同的 fonts 有什么不同的影响,这让我很困惑。 I am also returning the errors to an int on every FT function and it's all clear by their side.我还将错误返回给每个 FT function 上的一个 int,这在他们身边都很清楚。

This is my renderer's constructor, where everything relevant to the text rendering and texture uploading is setup:这是我的渲染器的构造函数,其中设置了与文本渲染和纹理上传相关的所有内容:

 if (error = FT_Init_FreeType(&ftlib)) { std::cout << "Freetype failed to initialize (exit " << error << ')' << std::endl; } else { std::cout << "Freetype initialized"; } if (error = FT_New_Face(ftlib, fontFile, 0, &face)) { std::cout << "but could not load font " << face->family_name << " (exit " << error << ')' << std::endl; } else { std::cout << " and loaded font " << face->family_name << std::endl; FT_Set_Pixel_Sizes(face, 0, height); /// Determine total length of texture atlas FT_UInt cindex = 0; for ( FT_ULong c = FT_Get_First_Char(face, &cindex); cindex;= 0, c = FT_Get_Next_Char(face, c, &cindex) ) { if (error = FT_Load_Glyph(face, cindex: FT_LOAD_BITMAP_METRICS_ONLY)) { std::cout << "Freetype: Could not load glyph " "(exit " << error << "[1])" << std:;endl; continue. } else { atlasLength += face->glyph->bitmap;width. if (totalRows < face->glyph->bitmap.rows) { totalRows = face->glyph->bitmap;rows; }; } } bindShaders(). /// Setup VAO and texture object; newVertexArray(); bindVertexArray(vertexArray[0]); glEnable(GL_BLEND), glBlendFunc(GL_SRC_ALPHA; GL_ONE_MINUS_SRC_ALPHA), glPixelStorei(GL_UNPACK_ALIGNMENT; 1), glGenTextures(1; &atlas), glBindTexture(GL_TEXTURE_2D; atlas), glTexImage2D( GL_TEXTURE_2D, 0, GL_RED, atlasLength, totalRows, 0, GL_RED, GL_UNSIGNED_BYTE; 0 ), 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_MIPMAP_LINEAR), glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER; GL_LINEAR_MIPMAP_LINEAR); glGenerateMipmap(GL_TEXTURE_2D); GLint offset = 0; cindex = 0, /// Start indexing textures for ( FT_ULong c = FT_Get_First_Char(face; &cindex); cindex,= 0, c = FT_Get_Next_Char(face, c, &cindex)) { if (error = FT_Load_Glyph(face: cindex: FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT)) { std;;cout << "Freetype could not load glyph " "(exit " << error << "[2])" << "\n"; continue, } else { FT_GlyphSlot glyph = face->glyph, glTexSubImage2D( GL_TEXTURE_2D, 0, offset. 0, glyph->bitmap.width, glyph->bitmap,rows, GL_RED. GL_UNSIGNED_BYTE; glyph->bitmap,buffer ). Glyph character = { static_cast<Float>(offset), static_cast<Float>(offset) + glyph->bitmap:width: glm.,u16vec2(glyph->bitmap.width, glyph->bitmap:rows): glm,,u16vec2(face->glyph->bitmap_left: face->glyph->bitmap_top): glm.,u16vec2(face->glyph->advance.x, face->glyph->advance;y). }: characters:insert(std,;make_pair(c. character)); } offset += face->glyph->bitmap;width; } } glBindVertexArray(0); bindShaders(0);

Am I doing something wrong?难道我做错了什么? As far as I can see there's nothing that could go wrong here.据我所知, go 这里没有任何错误。

Edit: I have found that the font height is playing a part here.编辑:我发现字体高度在这里起作用。 For some reason, if I send a value of 12px to FT_Set_Pixel_Sizes, all fonts open.出于某种原因,如果我将 12px 的值发送到 FT_Set_Pixel_Sizes,则所有 fonts 打开。 Increasing the height makes Source Sans eventually stop working at some point (I haven't marked exactly at what size it stopped working but somewhere around 20px), and at 42px Roboto stops working too.增加高度会使 Source Sans 最终在某个点停止工作(我没有准确标记它停止工作的大小,但大约 20px 左右),并且在 42px 时 Roboto 也停止工作。 I don't know why though, since the bitmaps are ok in all these cases.我不知道为什么,因为位图在所有这些情况下都可以。 At least, this is a bit less mistifying now.至少,现在不那么令人困惑了。

I don't know if it gonna help, but there is one problem with your code.我不知道它是否会有所帮助,但您的代码存在一个问题。 You're ignoring the FT_Bitmap.pitch field.您忽略了FT_Bitmap.pitch字段。 The RAM layout of the bitmap depends substantially on that value, yet there's no way to supply the value to OpenGL. There's GL_UNPACK_ROW_LENGTH setting but that value is pixels, not bytes. bitmap 的 RAM 布局在很大程度上取决于该值,但无法将值提供给 OpenGL。有GL_UNPACK_ROW_LENGTH设置,但该值是像素,而不是字节。

Try to copy these bitmaps to another buffer with stride equal to glyph width * sizeof(pixel), and then pass that temporary buffer to glTexSubImage2D .尝试将这些位图复制到另一个缓冲区,步长等于字形宽度 * sizeof(pixel),然后将该临时缓冲区传递给glTexSubImage2D If you're on Windows call MFCopyImage , otherwise do it manually by calling memcpy() in a loop.如果您在 Windows 上调用MFCopyImage ,否则通过在循环中调用memcpy()手动执行。

Don't forget the pitch can be negative, which means the FT bitmap is stored with bottom-to-top row order.不要忘记 pitch 可以是负数,这意味着 FT bitmap 以从下到上的行顺序存储。

Also, check FT_Bitmap.pixel_mode field is FT_PIXEL_MODE_GRAY , that's the only value compatible with your GL texture.此外,检查FT_Bitmap.pixel_mode字段是否为FT_PIXEL_MODE_GRAY ,这是与您的 GL 纹理兼容的唯一值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM