OpenGL单通道可见性转多通道优化:避免CPU内存分配开销
不用CPU复制,直接在OpenGL里用单通道字体纹理
嘿,我太懂你这种烦恼了——为了让单通道的字体可见性数据能用,在CPU上硬生生把单通道复制成四通道,既占内存又浪费时间,完全是没必要的开销!其实OpenGL原生就支持直接使用单通道纹理,咱们直接在GPU层面搞定就行,根本不用碰CPU的内存复制。
下面给你一步步说怎么实现:
1. 创建纹理时直接指定单通道格式
生成纹理的时候,别再想着把数据转成RGBA了,直接告诉OpenGL你传入的是单通道数据:
GLuint fontTexture; glGenTextures(1, &fontTexture); glBindTexture(GL_TEXTURE_2D, fontTexture); // 先设置好纹理的过滤和环绕参数,按需调整 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // 关键就在这一行:内部格式和数据格式都用GL_RED,直接传入你的单通道bitmap glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, bitmap);
这里的GL_RED表示单通道的红色分量,OpenGL会把你的unsigned char数组直接当成这个通道的数据存储,完全不需要额外复制。如果想要更明确的8位单通道,可以用GL_R8代替GL_RED作为内部格式,效果是一样的。
2. 在着色器里直接采样单通道数据
接下来在片段着色器里,你只需要取出纹理的红色通道值,就能用它来控制字体的透明度或者颜色了:
#version 330 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D fontTexture; void main() { // 取出单通道的可见性数据 float visibility = texture(fontTexture, TexCoords).r; // 如果你要做带透明度的白色字体,就这么写 FragColor = vec4(1.0, 1.0, 1.0, visibility); // 要是想做灰度字体,直接把visibility赋值给所有颜色通道就行 // FragColor = vec4(visibility, visibility, visibility, 1.0); }
一些额外注意事项
- 如果你的OpenGL版本比较老(低于3.0),
GL_RED可能不被支持,这时候可以用GL_LUMINANCE替代——不过这个枚举已经被废弃了,建议尽量升级到现代核心配置文件的OpenGL版本。 - 这样改完之后,你完全可以删掉CPU端那些复制单通道到四通道的代码,不用再分配
width*height*4的内存,也省掉了 memcpy 的时间,性能和内存占用都会好很多。
内容的提问来源于stack exchange,提问作者Steven Venham
相关产品推荐
相关产品推荐

