LibGDX纹理混合与OpenGL混合功能

kgqe7b3p  于 2022-11-29  发布在  其他
关注(0)|答案(2)|浏览(188)

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

这里我在矩形上测试它,但我想在任何形状上使用它。我已经研究了this tutorial,并提出了一个想法,首先绘制纹理,然后用blanding功能的遮罩:

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-警告:非常凌乱)

ct2axkht

ct2axkht1#

你尝试做的看起来像是一个非常聪明的混合应用。但我相信你应用它的确切方式是“被设计破坏”。让我们来看看这些步骤:
1.使用红色和绿色方块渲染背景。
1.在背景顶部渲染不透明纹理。
1.通过应用遮罩,可以擦除在步骤2中渲染的部分纹理。
问题是,对于在第3步中擦除的部分,先前的背景无法恢复。它确实无法恢复,因为您在第2步中将其擦除。整个纹理区域的背景在第2步中被替换,一旦它消失,就无法恢复。
现在的问题当然是如何解决这个问题。我可以想到两种传统的方法:

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

所以这些就是标准的解决方案。但是受到你的启发,我认为仅仅通过混合就可以做到这一点。我提出的方法使用了一个稍微不同的序列和不同的混合函数。我还没有尝试过这个方法,但是我认为它应该可以工作:
1.像以前一样渲染背景。
1.渲染遮罩。为了防止遮罩消除背景,请禁用对帧缓冲区的颜色组件的写入,而只写入Alpha组件。这会将遮罩保留在帧缓冲区的Alpha组件中。
1.渲染纹理,使用帧缓冲区(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.
ryoqjall

ryoqjall2#

这是一个很晚才有的答案,但在当前版本中,这是非常简单的。你只需要绘制蒙版,设置混合模式,使用源颜色到目标颜色,然后绘制原始图像。你只会在蒙版所在的位置看到原始图像。

//create batch with blending
SpriteBatch maskBatch = new SpriteBatch();
maskBatch.enableBlending();
maskBatch.begin();

//draw the mask
maskBatch.draw(mask);

//store original blending and set correct blending
int src = maskBatch.getBlendSrcFunc();
int dst = maskBatch.getBlendDstFunc();
maskBatch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);

//draw original
maskBatch.draw(original);

//reset blending
maskBatch.setBlendFunction(src, dst);

//end batch
maskBatch.end();

如果您需要更多关于混合选项的信息,请选中How to do blending in LibGDX

相关问题