我正在使用 OpenGL 加载位图来纹理 3d 网格。其中一些位图有一些像素的 alpha 通道(透明度),我需要找出最好的方法
- 获取每个像素的透明度值
和
- 使用应用的透明度渲染它们
有没有人有一个很好的例子?OpenGL 支持这个吗?
我正在使用 OpenGL 加载位图来纹理 3d 网格。其中一些位图有一些像素的 alpha 通道(透明度),我需要找出最好的方法
和
有没有人有一个很好的例子?OpenGL 支持这个吗?
首先,通常最好将位图数据转换为 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。
一些使事情(也许)看起来更好的提示:
如果您的像素图是 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 缓冲区算法冲突,因此您必须从后到前对几何图形进行排序,以使事物看起来正确。只要这会影响整个对象,这相当简单,但如果您需要对渲染每一帧的网格面进行排序,这将变得乏味。避免这种情况的一种方法是将网格分解为凸子网格(当然,已经凸的网格不能进一步分解)。然后使用以下方法: