2012-06-06 49 views
1

我试图在“雾中创建洞”效果。我有一个背景网格图像,叠加到我有一个“雾”纹理,我用它来显示某些区域不在视野内。我正试图从“雾”中剪下一块,以显示当前正在查看的区域。我试图“屏蔽”屏幕上的一部分雾。使用半透明纹理“掩盖”出背景的一部分

我做了一些图像,以帮助解释我是什么后:
背景:

BG

“掩模图像”(全透明必须是在里面,而不是为了外缘什么我将用它来):

Mask

雾(对不起,很难看到..几乎透明):

Fog

我想,作为最终产品是什么:

Final Product

我曾尝试:

  • 模板缓冲液:我这只是一个事实完全工作..我无法弄清楚如何保留“蒙版”图像的褪色透明度。我试过很多不同版本的参数和许多其他方法(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. 

(我会发布更多的代码但是在我尝试了很多东西之后,我开始删除一些旧代码,因为它变得非常混乱(我在块注释中将其备份)

回答

1

这是可行的,只要你没有对帧缓冲区当前的alpha做任何事情。

步骤1:确保帧缓冲区的alpha值清零为。所以你的glClearColor调用需要将alpha设置为零。然后像平常一样调用glClear。

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

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

你的面具纹理似乎有零,它是可见的,一个它不是。然而,该算法需要相反的,所以你应该修复你的纹理或使用glTexEnv模式,这将有效地翻转阿尔法。

经过这一步后,你的framebuffer应该有一个我们想要看到雾的alpha值,而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混合部分之间的分隔很重要。你不想改变 framebuffer的阿尔法(以防万一你想渲染一层以上的雾)。

你完成了。

+0

如果您使用RGB混合方程(ONE_MINUS_DST_ALPHA,DST_ALPHA),并且正如您所说“alpha在我们想要看到雾的地方是0”,则结果颜色将为((1-0) * fog_rgb + 0 * dst_rgb)。这将使雾完全不透明,不是吗?在RGB计算中不需要使用雾层的Alpha值吗? – Tim

+0

虽然我即将对此进行测试,但我相信颠倒面具可能对我无效。 renderFogCircles()渲染多个圆,它们可能重叠也可能不重叠。这会不会以alpha倒置的奇怪图形问题结束?无论如何...我会尽快测试以确保。 – Zachar543

+0

目前的面具(但白色而不是黑色)似乎能够产生理想的效果。在上面的面具上反转alpha似乎给出了完全相反的效果。 (边框是透明的)尽管如此,仍然存在一些问题......无论我用什么透明度值,这段代码都有可能将所有的雾都变成不透明的白色。 http://img707.imageshack.us/img707/751/screenshot2012060615012.png(我用我在其他地方使用的参数撤消上面的glBlendFunc“glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);”)雾似乎不再与背景。 – Zachar543

1

您目前所采用的方法将不起作用,因为一旦您在整个屏幕上画雾,就无法“擦除”它。

如果您使用固定的管道:

您可以使用固定的管道多纹理(glTexEnv)的雾和圆纹理单程结合起来。如果你之前没有使用过这个函数,那么这个函数可能会让你感到困惑,你可能不得不花一些时间来学习这个手册页。你会做一些像bind fog到glActiveTexture 0,以及mask到glActiveTexture 1,启用multitexturing,然后将它们与glTexEnv结合起来。我不记得完全正确的参数。

如果您使用的着色器:

使用多重纹理着色器,你与圆的纹理乘雾α(零出在圈内区域的alpha),然后混合该组合的质地为背景在一次通过。这可能是一个更概念上更简单的方法,但不确定是否使用着色器。

我不确定有什么办法可以做到这一点,因为它们都具有自己的alpha值,因此它们在单独的通道中绘制雾和蒙版时很难将它们组合以获得正确的颜色结果。

+0

multitexturing是否允许我移动mask实时?它是否允许多个蒙版图像? – Zachar543

+1

如果你想使用很多的面具,我可能会尝试渲染所有的面具到一个FBO纹理,然后用它来代替。用任意数量的texcoords来使用多纹理将会很困难。你可以放弃一两个,但更重要的是我认为这不是真的可行。 – Tim

+0

@NicolBolas我将我的系统转换为将面具预渲染为FBO。虽然,我似乎有一些问题。 http://img204.imageshack.us/img204/6534/screenshot2012060621210。PNG是在我的屏幕上绘制FBO的结果。 (只有红色通道和alpha打开)如果我关闭alpha通道,通过“glColorMask”,奇怪的重叠不再存在。然后我留下一张不透明的图像。虽然,当我打开alpha时,我在上图中找到了问题。第二个绘制的掩码似乎覆盖已经吸入FBO的alpha。混合似乎不起作用 – Zachar543