【问题标题】:Change texture opacity in OpenGL在 OpenGL 中更改纹理不透明度
【发布时间】:2008-11-03 14:21:55
【问题描述】:

希望这是一个简单的问题:我有一个 OpenGL 纹理并且希望能够更改它的不透明度,我该怎么做?纹理已经有一个 alpha 通道并且混合效果很好,但我希望能够降低整个纹理的不透明度,使其淡入背景。我曾摆弄过glBlendFunc,但没有运气——似乎我需要GL_SRC_ALPHA_MINUS_CONSTANT 之类的东西,但它不可用。我正在使用 OpenGL ES 开发 iPhone。

【问题讨论】:

    标签: iphone opengl-es


    【解决方案1】:

    我不知道 OpenGL ES,但在标准 OpenGL 中,您可以通过在使用纹理之前声明颜色来设置不透明度:

    //          R,   G,   B,   A
    glColor4f(1.0, 1.0, 1.0, 0.5);
    

    该示例将为您提供 50% 的 Alpha,而不会影响纹理的颜色。通过调整其他值,您也可以改变纹理颜色。

    【讨论】:

    • glBlendFunc 有什么样的设置?
    • 这取决于应用程序,但我通常会使用:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    • 这是因为默认纹理环境设置为 GL_MODULATE
    【解决方案2】:

    使用纹理组合器。设置纹理阶段以在纹理和常量颜色之间进行GL_MODULATE 操作。然后更改代码中的常量颜色(glTexEnvGL_TEXTURE_ENV_COLOR)。

    就性能而言,这应该是“免费的”。在大多数(如果不是全部)图形芯片上,组合器操作需要相同数量的 GPU 周期(通常为 1),因此仅使用纹理与执行调制操作(或任何其他操作)的成本完全相同。

    【讨论】:

    • 嗯.. 一个非常优雅+简单的解决方案,NeARAZ。
    【解决方案3】:

    基本上你有两个选择:使用 glTexEnv 为你的纹理使用 GL_MODULATE 并使用 glColor4* 指定颜色,并为 alpha 通道使用非透明级别。请注意,当您第一次加载纹理时,glTexEnv 应该只发出一次。但是,如果您在顶点属性中指定颜色,这种情况将不起作用。这些将覆盖您可以设置的任何 glColor4* 颜色。在这种情况下,您可能需要使用 2 个选项之一:使用纹理组合器(高级主题,不适合在固定管道中使用),或“手动”更改每个单独顶点的顶点颜色属性(对于更大的网格)。

    【讨论】:

      【解决方案4】:

      感谢大家的想法。我玩过 glColor4f 和 glTexEnv,最后强迫自己仔细阅读 glTexEnv 手册页。手册页说在 GL_MODULATE 纹理模式下,结果颜色是通过将传入片段乘以纹理颜色 (C=Cf×Ct) 来计算的,对于 alpha 也是如此。我尝试了 glColor4f(1, 1, 1, opacity) 并且没有用,但是将所需的不透明度传递给调用的所有四个参数就可以了。 (但仍然不确定为什么。)

      【讨论】:

      • 这让您决定将自己的“答案”标记为已接受的答案?
      • 是的,因为它解决了我的问题。随意不同意:)
      • 您设置的纹理有问题。丹回答的有效且有意义,您的“解决方案”是一个黑客。
      • 这是正常的,如果您将生成的颜色 alphablend 到背景中或使用 GL_ONE 参数作为源 alpha 的 alphablend,而不是 GL_SRC_ALPHA。在这种情况下,您不需要更改所有颜色组件。
      【解决方案5】:

      如果您使用的是现代 OpenGL..

      您可以在片段着色器中执行此操作:

      void main()
      {
           color = vec4(1.0f, 1.0f, 1.0f, OPACITY) * texture(u_Texture, TexCoord);
      }
      

      这允许您在不中断混合的情况下将不透明度值应用于纹理。

      【讨论】:

        【解决方案6】:

        最直接的方法是动态更改纹理的 alpha 值。由于您在某个时候告诉 OpenGL 有关纹理的信息,因此您将在内存中拥有位图。所以只需将纹理重新绑定到相同的纹理 ID。如果内存中没有它(由于空间限制,因为您在 ES 上),您可以使用 glGetTexImage() 再次将纹理检索到缓冲区。这就是干净的解决方案。

        不过,保存/检索操作的成本有点高,因此您可能需要另一种解决方案。考虑一下,您可能能够使用几何图形背后的几何图形来显示纹理,或者简单地处理包含纹理的几何图形的材质/颜色。您可能希望对背面几何进行一些加法混合。使用 glBlendFunc 的

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA),
        

        您也许能够“轻松”并且 - 更重要的是,更便宜 - 达到预期的效果。

        【讨论】:

        • 一个纹理通常用于多个对象,更改它会更改所有对象的透明度。此外,在许多系统上,由于内部格式转换,纹理上传比简单的复制操作要慢得多。
        【解决方案7】:

        您很可能正在使用 cg 将图像转换为纹理。当您使用 cg 时,alpha 是预乘的,因此为什么您必须将 alpha 用于 color4f 函数的 rgba。

        【讨论】:

          【解决方案8】:

          我怀疑您的背景是黑色的,因此通过减少每种颜色的数量,您实际上是在将颜色淡化为黑色。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-04-03
            • 2015-03-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多