【问题标题】:LibGDX texture blending with OpenGL blending functionLibGDX 纹理混合与 OpenGL 混合功能
【发布时间】:2014-08-25 22:35:44
【问题描述】:

在 libGdx 中,我正在尝试创建形状纹理:获取完全可见的矩形纹理并对其进行遮罩以获得形状纹理,如下所示:

在这里我在矩形上测试它,但我想在任何形状上使用它。我查看了this tutorial 并提出了一个想法,首先绘制纹理,然后绘制具有淡化功能的蒙版:

batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA);
  • GL20.GL_ZERO - 因为我真的不想从蒙版中绘制任何像素
  • GL20.GL_SRC_ALPHA - 从原始纹理中,我只想绘制蒙版可见的那些像素(= 白色)。

测试代码的关键部分:

batch0.enableBlending();
batch0.begin();

batch0.draw(original, 0, 0); //to see the original
batch0.draw(mask, width1, 0); //and the mask

batch0.draw(original, 0, height1); //base for the result

batch0.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA);
batch0.draw(mask, 0, height1); //draw mask on result
batch0.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

batch0.end();

纹理的中心选择得很好,但周围不是透明色,而是黑色:

为什么结果是空白不透明?

(Full code - 警告:非常混乱)

【问题讨论】:

  • 您能否详细说明您的期望是什么?您如何确定结果不透明?我认为您的目标 alpha 将为零,因此从这个意义上说它是透明的。您是否在该区域中还有其他东西现在是黑色的,并且您希望以前的内容仍然存在?
  • 是的,整个应用背景是深红色和绿色的方块,并没有绘制黑色,所以如果纹理是透明的,我会选择方块,对吧?

标签: opengl libgdx textures blender alphablending


【解决方案1】:

您正在尝试做的事情看起来像是非常巧妙地使用了混合。但我相信你应用它的确切方式是“被设计破坏的”。让我们来看看这些步骤:

  1. 您使用红色和绿色方块渲染背景。
  2. 您在背景上渲染了一个不透明的纹理。
  3. 您可以通过应用蒙版擦除在第 2 步中渲染的部分纹理。

问题在于,对于您在第 3 步中擦除的部分,之前的背景不会恢复。实在不行,因为你在第 2 步把它擦掉了。整个纹理区域的背景在第 2 步被替换了,一旦它消失了就无法恢复。

现在的问题当然是如何解决这个问题。我可以想到两种常规方法:

  • 您可以通过将纹理和遮罩渲染到一个离屏帧缓冲区对象 (FBO) 中来组合它们。您像现在一样执行第 1 步和第 2 步,但渲染到带有纹理附件的 FBO。然后,您渲染到的纹理是具有反映您的蒙版的 alpha 值的纹理,您可以使用此纹理通过标准混合渲染到您的默认帧缓冲区中。
  • 您可以使用模板缓冲区。屏蔽部分渲染是模板缓冲区的主要应用,使用模板对于您的用例来说绝对是一个非常好的解决方案。在此答案中,我不会详细说明如何将模板缓冲区准确应用于您的案例。如果您搜索“OpenGL 模板”,您应该能够在网上和书籍中找到大量示例,包括在本网站的其他答案中。例如,最近的这个问题涉及使用模板缓冲区做类似的事情:OpenGL stencil (Clip Entity)

所以这些将是标准解决方案。但是受到您尝试中的想法的启发,我认为实际上可以通过混合来实现它。我想出的方法使用了稍微不同的序列和不同的混合函数。我还没有尝试过,但我认为它应该可以工作:

  1. 您像以前一样渲染背景。
  2. 渲染蒙版。为防止它消除背景,请禁用对帧缓冲区的颜色组件的写入,并且只写入 alpha 组件。这会将掩码留在帧缓冲区的 alpha 组件中。
  3. 渲染纹理,使用帧缓冲区 (DST_ALPHA) 中的 alpha 分量进行混合。

您需要一个带有 alpha 组件的帧缓冲区才能使其工作。确保在设置上下文/表面时为帧缓冲区请求 alpha 位。

代码序列如下所示:

// Draw background.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND);
// Draw mask.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_BLEND);
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
// Draw texture.

【讨论】:

  • 谢谢,我后来意识到这一点(我的原始背景被不透明的纹理反向破坏了),我使用了FrameBuffer,一切都很好。
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多