希望这是一个简单的问题:我有一个 OpenGL 纹理并且希望能够改变它的不透明度,我该怎么做?纹理已经有一个 alpha 通道并且混合效果很好,但我希望能够降低整个纹理的不透明度,使其淡入背景。我已经摆弄了glBlendFunc
,但没有运气 - 似乎我需要类似的东西GL_SRC_ALPHA_MINUS_CONSTANT
,这是不可用的。我正在使用 OpenGL ES 开发 iPhone。
8 回答
我不知道 OpenGL ES,但在标准 OpenGL 中,您可以通过在使用之前为纹理声明颜色来设置不透明度:
// R, G, B, A
glColor4f(1.0, 1.0, 1.0, 0.5);
该示例将为您提供 50% 的 alpha,而不会影响纹理的颜色。通过调整其他值,您也可以改变纹理颜色。
使用纹理组合器。设置纹理阶段以GL_MODULATE
在纹理和恒定颜色之间进行操作。glTexEnv
然后从您的代码 ( , GL_TEXTURE_ENV_COLOR
) 中更改常量颜色。
就性能而言,这应该是“免费的”。在大多数(如果不是全部)图形芯片上,组合器操作需要相同数量的 GPU 周期(通常为 1),因此仅使用纹理与执行调制操作(或任何其他操作)的成本完全相同。
基本上你有两个选择:使用 glTexEnv 为你的纹理使用 GL_MODULATE 并使用 glColor4* 指定颜色并为 alpha 通道使用非不透明级别。请注意,当您第一次加载纹理时,glTexEnv 应该只发出一次。但是,如果您在顶点属性中指定颜色,这种情况将不起作用。这些将覆盖您可以设置的任何 glColor4* 颜色。在这种情况下,您可能需要使用 2 个选项之一:使用纹理组合器(高级主题,不适合在固定管道中使用),或“手动”更改每个单独顶点的顶点颜色属性(对于更大的网格)。
谢谢大家的想法。我玩过 glColor4f 和 glTexEnv,最后强迫自己仔细阅读 glTexEnv 手册页。手册页说,在 GL_MODULATE 纹理模式下,结果颜色是通过将传入片段乘以纹理颜色 (C=Cf×Ct) 来计算的,对于 alpha 也是如此。我尝试了 glColor4f(1, 1, 1, opacity) 并且没有用,但是将所需的不透明度传递给调用的所有四个参数就可以了。(但仍然不确定为什么。)
如果您使用的是现代 OpenGL ..
您可以在片段着色器中执行此操作:
void main()
{
color = vec4(1.0f, 1.0f, 1.0f, OPACITY) * texture(u_Texture, TexCoord);
}
这允许您在不中断混合的情况下将不透明度值应用于纹理。
最直接的方法是动态更改纹理的 alpha 值。由于您在某个时候告诉 OpenGL 有关纹理的信息,因此您将在内存中拥有位图。所以只需将纹理重新绑定到相同的纹理 ID。如果内存中没有它(由于空间限制,因为您在 ES 上),您可以使用glGetTexImage()再次将纹理检索到缓冲区。这就是干净的解决方案。
不过,保存/检索操作的成本有点高,因此您可能需要另一种解决方案。考虑一下,您可能能够使用几何图形背后的几何图形来显示纹理,或者简单地处理包含纹理的几何图形的材质/颜色。您可能希望对背面几何进行一些附加混合。使用 glBlendFunc
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA),
您可能能够“轻松”并且 - 更重要的是,更便宜 - 达到预期的效果。
很可能您正在使用 cg 将图像转换为纹理。当您使用 cg 时,alpha 是预乘的,因此您必须将 alpha 用于 color4f 函数的 rgba。
我怀疑您的背景是黑色的,因此通过减少每种颜色的数量,您实际上是在将颜色淡化为黑色。