使用单通道纹理(OpenGL 2)?

Posted

技术标签:

【中文标题】使用单通道纹理(OpenGL 2)?【英文标题】:Using single channel texture (OpenGL 2)? 【发布时间】:2016-10-09 12:09:22 【问题描述】:

短篇小说:

当我使用像这样加载的纹理渲染任何东西时

glTexImage2D   ( GL_TEXTURE_2D, 0, GL_R8, width,  height, 0, GL_RED,   GL_UNSIGNED_BYTE, pixels );

我只有黑色


长篇大论:

我可以获得带有 alpha 通道的 RGBA 纹理(例如,使用此代码具有透明背景的文本):

此代码有效:

// === load
#define GL_ABGR 0x8000
SDL_Surface * surf = SDL_LoadBMP( "common_resources/dejvu_sans_mono_RGBA.bmp" );
glGenTextures  ( 1, &itex );
glBindTexture  ( GL_TEXTURE_2D, itex );
glTexImage2D   ( GL_TEXTURE_2D, 0, GL_RGBA, surf->w,  surf->h, 0, GL_ABGR,   GL_UNSIGNED_BYTE, surf->pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// ....
// === render
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, itex );
glColor3f(1.0f,1.0f,1.0f);
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
drawString ( caption,             xmin, ymin+12, 6 );

呈现像

但我试图只使用一个通道(8 位;灰度)图像/纹理而不是 RGBA。无论有没有透明度,我都无法渲染这些。无论我做什么,我都只会得到黑色图像。

这不是

// === load
#define GL_ABGR 0x8000
SDL_Surface * surf = SDL_LoadBMP( "common_resources/dejvu_sans_mono_Alpha.bmp" );
glGenTextures  ( 1, &itex );
glBindTexture  ( GL_TEXTURE_2D, itex );
glTexImage2D   ( GL_TEXTURE_2D, 0, GL_R8, surf->w,  surf->h, 0, GL_RED,   GL_UNSIGNED_BYTE, surf->pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// ....
// === render
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, itex );
glColor3f(1.0f,1.0f,1.0f);
//glEnable(GL_BLEND);
//glEnable(GL_ALPHA_TEST);
//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
drawString ( caption,             xmin, ymin+12, 6 );

呈现像

注意事项:

    我知道我应该以某种方式使用 glTexEnv 根据例如here 但我的主要问题是显然 单色纹理根本不渲染 我还尝试了其他GL_LUMINANCEGL_INTENSITY 而不是glTexImage2D 中的GL_RED 没有区别 还有其他问题,例如 here 和 here,但主要是 OpenGL>3.0 和片段着色器

另外,我的显卡或驱动程序是否可能不支持这个?我在 ubuntu 16.04

GL_VENDOR:     Intel Open Source Technology Center
GL_RENDERER:   Mesa DRI Intel(R) HD Graphics 530 (Skylake GT2) 
GL_VERSION:    3.0 Mesa 11.2.0

为了完整性 - 虽然这并不重要,但 drawString 看起来像这样:

drawString ( caption,             xmin, ymin+12, 6 )
  const int nchars = 95;
  float persprite = 1.0f/nchars;
  glBegin(GL_QUADS);
  for(int i=0; i<65536; i++)
    if( str[i] == 0 ) break; // 0-terminated string
    int isprite = str[i] - 33; // 33 is offset of meaningfull ASCII characters
    float offset  = isprite*persprite+(persprite*0.57);
    float xi = i*sz + x;
    glTexCoord2f( offset          , 1.0f ); glVertex3f( xi,    y,    3.0f );
    glTexCoord2f( offset+persprite, 1.0f ); glVertex3f( xi+sz, y,    3.0f );
    glTexCoord2f( offset+persprite, 0.0f ); glVertex3f( xi+sz, y+sz*2, 3.0f );
    glTexCoord2f( offset          , 0.0f ); glVertex3f( xi,    y+sz*2, 3.0f );
  
  glEnd();

【问题讨论】:

【参考方案1】:

我想尽力帮助你。在我的项目中,我使用此参数从灰度源图像生成纹理:

glTexImage2D(GL_TEXTURE_2D, 0, 1, width, height, 0, GL_RED,
             GL_UNSIGNED_BYTE, pixels);

正如documentation 中所写,第三个参数 - 颜色分量的数量(在我们的例子中为 1)。需要检查GL_R8的整数值或显式替换。

GL_RED 表示您将亮度放置在红色通道中(而不是像灰度图像那样在每个红色、绿色、蓝色通道中)。

【讨论】:

谢谢,我试过glTexImage2D( GL_TEXTURE_2D, 0, 1, surf-&gt;w, surf-&gt;h, 0, GL_RED, GL_UNSIGNED_BYTE, surf-&gt;pixels );,但结果还是一样......也许真的英特尔GPU不支持它(?) @ProkopHapala ,你有命令glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 吗?我通常打电话给glBindTexture->glPixelStorei->x2 glTexParameteri->glTexImage2D 你不应该使用裸数字作为纹理的内部格式。始终使用尺寸大小的图像格式,即使是灰度图像。 现在我尝试添加 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 但没有帮助 @ProkopHapala ,我认为内存中生成的纹理在 alpha 通道处为零(我们正在将强度加载为红色)。

以上是关于使用单通道纹理(OpenGL 2)?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL中的调色板动画

我的OpenGL学习进阶之旅解决OpenGL绘制带透明通道的png纹理时出现黑边问题,并彻底了解其原理

我的OpenGL学习进阶之旅解决OpenGL绘制带透明通道的png纹理时出现黑边问题,并彻底了解其原理

如何显示带有opengl纹理的灰度图像

OpenGL:渲染具有大量纹理透明度的模型,没有绘制顺序?

OpenGL:禁用纹理颜色?