1

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

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

  1. 使用应用的透明度渲染它们

有没有人有一个很好的例子?OpenGL 支持这个吗?

4

2 回答 2

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 中的原始透明度颜色混合。
于 2011-06-20T05:09:06.357 回答
1

如果您的像素图是 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
于 2011-06-20T07:30:10.287 回答