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



我正在用OpenGL加载位图,以对三维网格进行纹理处理。其中一些位图的某些像素具有alpha通道(透明度),我需要找出的最佳方法

  1. 获得每个像素的透明度值

  1. 使用应用的透明度进行渲染

有人有这样的好例子吗?OpenGL支持这一点吗?

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

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

如果对三维对象执行此操作,则可能还需要禁用背面剔除(以便通过正面看到对象的背面),并将三角形前后排序(以便按正确顺序进行混合)。

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

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

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

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

如果GPU支持片段着色器(很可能),则可以在着色器中执行LUT转换:将8位像素上载为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缓冲区算法冲突,因此必须将几何体前后排序,以使其看起来正确。只要这在整体上影响对象,这就相当简单,但如果需要对渲染每一帧的网格的面进行排序,则会变得乏味。避免这种情况的一种方法是将网格分解为凸子网格(当然,已经是凸的网格无法进一步分解)。然后使用以下方法:

  • 启用人脸剔除
  • 对于排序中的convex_submesh(网格,从远到近):
    • 将面剔除设置为面(即渲染背面)
    • 渲染凸面_子网格
    • 将面剔除设置为背面面(即正面渲染)
    • 再次渲染convex_submesh

最新更新