使用半透明纹理“掩盖”背景的一部分

时间:2012-06-06 07:06:23

标签: java opengl lwjgl stencil-buffer

我试图创造一个“雾中洞”效果。我有一个背景网格图像,重叠到我有一个“雾”纹理,我用来表明某些区域不在视野中。我试图从“雾”中切出一块,这将显示当前正在查看的区域。我试图“屏蔽”屏幕上的一部分雾。

我制作了一些图片来帮助解释我的目标:
背景:

BG

“Mask Image”(完全透明度必须在内部,而不是外边缘,以便我将使用它):

Mask

雾(对不起,很难看到......大部分是透明的):

Fog

我想要的最终产品:

Final Product

我试过了:

  • Stencil-Buffer:除了一个事实之外我完全正常工作......我无法弄清楚如何保留“蒙版”图像的淡化透明度。
  • glBlendFunc:我尝试了许多不同版本的参数和许多其他方法(glColorMask,glBlendEquation,glBlendFuncSeparate)我首先使用了一些我在本网站上找到的参数:here。我使用了“glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_ALPHA);”因为这似乎是我正在寻找的但是......结果最终发生了这样的结果:(很难分辨出这里发生了什么,但......背景中有一层雾覆盖着网格。虽然,当它被认为是雾中的透明部分时,面具最终会变成一个完全不透明的黑色斑点 Result of glBlendFunc

以前的一些代码:

glEnable(GL_BLEND); // This is not really called here... It is called on the init function of the program as it is needed all the way through the rendering cycle.
renderFogTexture(delta, 0.55f); // This renders the fog texture over the background the 0.55f is the transparency of the image. 
glBlendFunc(GL_ZERO, GL11.GL_ONE_MINUS_SRC_ALPHA); // This is the one I tried from one of the many website I have been to today.
renderFogCircles(delta); // This just draws one (or more) of the mask images to remove the fog in key places.

(我会发布更多代码,但在我尝试了很多东西之后,我开始删除一些旧代码,因为它变得非常混乱(我在块注释中“支持它们”))

2 个答案:

答案 0 :(得分:2)

如果您当前没有对帧缓冲区的 alpha 做任何事情,这是可行的。

第1步:确保将帧缓冲区的alpha清除为。所以你的glClearColor调用需要将alpha设置为零。然后正常调用glClear。

第2步:在绘制“雾”之前绘制蒙版图像。正如蒂姆所说,一旦你与雾混合,就无法撤消。所以你首先需要掩码数据。

但是,您还需要专门渲染蒙版。你希望掩码修改帧缓冲区的alpha。你不希望它弄乱RGB颜色。为此,请使用此功能:glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE)。这将关闭对RGB部分颜色的写入;因此,只会修改alpha。

你的面具纹理在可见的地方看起来是零,而在它看不到的地方。但是,算法需要相反,因此您应该修复纹理或使用有效翻转alpha的glTexEnv模式。

在此步骤之后,你的帧缓冲区应该有一个alpha值为0,我们想要看到雾,而alpha值为1,我们不想看到。

另外,在渲染蒙版后,不要忘记撤消glColorMask 调用。你需要恢复这些颜色。

第3步:渲染雾。这很容易;要进行遮罩工作,您需要一种特殊的混合模式。像这样:

glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, GL_ZERO, GL_ONE);

RGB和A混合部分之间的分离很重要。你不想更改帧缓冲区的alpha(以防你想要渲染多层雾)。

你已经完成了。

答案 1 :(得分:1)

你正在采取的方法是行不通的,因为一旦你在整个屏幕上画了雾,就没有办法“抹掉”它。

如果您使用固定管道:

您可以将多纹理(glTexEnv)与固定管道结合使用,在一次通过中组合雾和圆纹理。如果您以前没有使用它,这个功能可能有点令人困惑,您可能不得不花一些时间研究手册页。您将执行类似绑定雾到glActiveTexture 0的操作,并屏蔽到glActiveTexture 1,启用多重纹理,然后将它们与glTexEnv组合。我不记得确切的正确参数。

如果您正在使用着色器:

使用多纹理着色器,将雾alpha与圆形纹理相乘(将圆形区域中的alpha置零),然后在单次传递中将此组合纹理混合到背景中。这可能是一种概念上更简单的方法,但不确定您是否使用着色器。

我不确定你是否有办法在单独的传递中绘制雾和蒙版,因为它们都有自己的alpha值,很难将它们组合起来以获得正确的颜色结果。