在8位位图中处理alpha通道的好方法? - OpenGL - C ++

时间:2011-06-20 04:59:09

标签: c++ opengl alpha-transparency

我正在使用OpenGL加载位图来纹理3d网格。其中一些位图具有某些像素的alpha通道(透明度),我需要找出最佳方法

  1. 获取每个像素的透明度值
    1. 使用透明度
    2. 渲染它们

      有没有人有这方面的好例子? OpenGL是否支持此功能?

2 个答案:

答案 0 :(得分:5)

首先,通常最好将位图数据转换为32位,以便每个通道(R,G,B,A)获得8位。上传纹理时,请指定32位格式。

然后在渲染时,您需要glEnable(GL_BLEND);并设置混合函数,例如:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);。这告诉OpenGL使用纹理的alpha将纹理的RGB与背景的RGB混合。

如果您对3D对象执行此操作,您可能还需要关闭背面剔除(以便通过前面看到对象的背面)并将三角形从后向前排序(以便混合发生在正确的顺序)。

如果您的源位图是8位(即:使用指定为透明蒙版的一种颜色的调色板),那么将其转换为RGBA可能最容易,当颜色与透明度蒙版匹配时将alpha值设置为0

一些提示让事情(也许)看起来更好:

  • 您的Alpha通道将是一个全有或全无的事件(0x00或0xff),因此应用一些模糊算法来获得更柔和的边缘,如果这就是您所追求的。
  • 对于alpha为零(完全透明)的纹素(纹理像素),将RGB颜色替换为最接近的非透明纹理。当插入纹理坐标时,它们不会与BMP中的原始透明度颜色混合。

答案 1 :(得分:1)

如果您的像素图是8位单通道,则它们是灰度或使用调色板。您首先需要做的是将像素图数据转换为RGBA格式。为此,您需要分配一个足够大的缓冲区来容纳原始文件尺寸的4通道像素图。然后,对于像素图的每个像素,使用该像素的值作为调色板(查找表)的索引,并将该颜色值放入RGBA缓冲区中的相应像素中。完成后,使用 glTexImage2D 上传到OpenGL。

如果你的GPU支持片段着色器(非常可能),你可以在着色器中进行LUT转换:将8位pixmal上传为GL_RED或GL_LUMINANCE 2D纹理。并将调色板上传为1D GL_RGBA纹理。然后在片段着色器中:

uniform sampler2D texture;
uniform sampler1D palette_lut;

void main()
{
    float palette_index = texture2D(texture,gl_TexCoord[0].st).r;
    vec4 color = texture1D(palette_lut, palette_index);
    gl_FragColor = color;
}

混合渲染与Z缓冲区算法冲突,因此您必须从后到前对几何体进行排序才能使事物看起来正确。只要这会影响整体上的对象,这很简单,但如果需要对网格的每个帧进行排序,则会变得单调乏味。避免这种情况的一种方法是将网格划分为凸子网格(当然,凸起的网格已经无法进一步细分)。然后使用以下方法:

  • 启用面部剔除
  • 对于sorted(网格,远到近)中的convex_submesh:
    • 将面部剔除设置为面(即背面被渲染)
    • 渲染convex_submesh
    • 将面部剔除设置为后面面孔(即前端渲染)
    • 再次渲染convex_submesh