Freetype加载的部分字体位图无法作为纹理上传至OpenGL问题求助
问题根因及修复方案
1. 错误的Mipmap生成时机与放大过滤参数
你当前在glTexImage2D初始化空纹理后立刻调用glGenerateMipmap,此时纹理base level全为0值,生成的所有下级mip层级也都是空值。后续仅通过glTexSubImage2D更新了base level的纹理数据,没有重新生成mipmap,采样时使用GL_LINEAR_MIPMAP_LINEAR会读取到空的下级mip层级,导致显示异常。
另外纹理放大过滤参数GL_LINEAR_MIPMAP_LINEAR是非法值,OpenGL规范明确规定GL_TEXTURE_MAG_FILTER仅支持GL_NEAREST和GL_LINEAR两个枚举值,传入mipmap相关参数会触发GL错误,导致纹理处于未完成状态无法采样。
修复代码如下:
// 修正放大过滤参数 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 不要使用MIPMAP相关枚举 // 删掉原glTexImage2D之后的glGenerateMipmap调用 // 移到所有glTexSubImage2D上传完成之后再调用 } // 字符遍历上传的for循环结束后 glGenerateMipmap(GL_TEXTURE_2D);
2. 未校验纹理尺寸是否超出GPU限制
字号增大时,所有字符宽度累加得到的atlasLength会线性增长,当该值超出当前GPU支持的最大2D纹理宽度(可通过glGetIntegerv(GL_MAX_TEXTURE_SIZE, &val)查询,常见下限为2048/4096)时,glTexImage2D会直接失败,后续所有纹理操作都无效。小字号下总宽度未超出限制所以正常,正好符合你观察到的字号关联现象。
修复方案:
- 纹理图集改用二维排列(比如每行固定宽度,超出就换行),不要用单行长条形排列,避免宽度超出限制
- 初始化纹理后增加GL错误校验,排查API调用失败问题:
glTexImage2D(...); GLenum err = glGetError(); if (err != GL_NO_ERROR) { std::cout << "Texture init failed: " << gluErrorString(err) << std::endl; }
3. 补充建议
增加每一步OpenGL调用的错误校验,可以快速定位API调用失败的位置,你当前只校验了Freetype的返回值,完全没有校验OpenGL的错误,很多异常场景会被忽略。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

