20

我正在开发一款游戏,我想在网格上的一系列精灵下创建阴影。阴影比精灵本身大,并且精灵是动画的(即移动和旋转)。

我不能简单地将它们渲染到精灵 png 中,否则阴影会与相邻的精灵重叠。

我也不能简单地将阴影单独放在较低的图层上,因为当它们重叠时,它们会在它们的交叉处产生暗带。

这些精灵是动画的,因此整体渲染这些精灵是不可行的。

基本上,我希望精灵的阴影混合在一起,以使它们在设定的不透明度下最大化。例子:

在此处输入图像描述

我相信这相当于(Rs,Gs,Bs,Max(As,Ds))的openGL混合,我并不真正关心R,G和B,因为它在src中总是相同的颜色和夏令时。

但是,这不是有效的 openGL 混合模式。有没有一种简单的方法可以做到这一点,尤其是在 cocos2d-iphone 中?

我可以通过使阴影精灵不透明来近似这一点,然后将它们都应用于父精灵,并使父精灵的不透明度为 40%。但是,cocos2d 的工作方式只是将每个孩子的不透明度设置为 40%,而不是组合的精灵图像,这会导致相同的条纹。

4

1 回答 1

22

好的,我想经过大量研究,我意识到我的思维错误。

首先,有一种方法可以进行 Max Alpha openGL 混合,那就是使用 glBlendEquations。您必须修改 draw 方法来执行此操作(并为 textureNode 创建一些新属性以在这些方法之间切换),并使用以下任一方法:

 glBlendEquationOES( GL_MAX_EXT );
 glBlendEquationSeparateOES( GL_FUNC_ADD_OES, GL_MAX_EXT );

第一个对 RGBA 使用 max(),第二个对 RGB 使用标准加法,对 alpha 使用 max()。

现在,问题是每个精灵,以及它的孩子,按照 z 顺序,都被绘制到屏幕上。这意味着,在绘制第一个阴影之后,它是主屏幕缓冲区的一部分。换句话说,它的不透明度发生了变化,并且通过 max() 混合和标准的不透明背景,它现在被绘制到背景上,所以当你绘制下一个阴影时,它会执行 max(As, 1) ,即 1,因为背景不透明。所以我没有达到我想要的混合效果。如果我的背景是透明的,它会“工作”,但是我不能在“后面”应用任何背景,我们只能添加到缓冲区。

我可以先绘制阴影,使用 max() 混合,然后执行 {ONE_MINUS_DST_ALPHA, DST_ALPHA} glBlend。这是一个不错的解决方法,但我还有其他问题使这变得困难。

现在,我终于意识到,真正的解决方案是在将阴影应用到背景之前,使用 RenderTexture 将阴影渲染到单独的缓冲区。这可能会对性能产生影响,所以我们将看看它的发展方向。

更新:

好的,我现在有一个可行的解决方案。

奇怪的是,我最终不需要这个解决方案,因为在我的特殊情况下,条带不够明显,不足以保证努力,但这是我想出的解决方案,似乎可以满足我的要求:

  1. 首先在整个屏幕上绘制一个 0% 黑色的 alpha png。(我不知道这是否有必要。我不知道屏幕的默认 alpha 是多少)。

  2. glEquationSeperateOES( GL_ADD, GL_MAX_ENT)使用和将阴影绘制到屏幕上glBlend( GL_ONE, GL_ONE )。这将按照描述将所有阴影混合在一起,采用 alpha 的 max()。

    • 因为你是在合成黑色,所以相当于使用glBlendEquationOES( GL_MAX_ENT ). (X+0 == 最大值(X,0))

    • glBlend( GL_ZERO, GL_ONE )将消除第 1 步的需要,或者至少不需要该层为 0% 黑色。 GL_ZERO基本上强制它为 0% 黑色。

  3. 绘制地板,它将阴影上方,但使用glBlend( ONE_MINUS_DST_ALPHA, DST_ALPHA ). 这会产生与使用 将阴影添加到地板上完全相同的结果glBlend( SRC_ALPHA, ONE_MINUS_SRC_ALPHA ),但是如果您这样做,您将无法将阴影混合在一起(请阅读答案顶部的原因)。

  4. 你完成了!这个方法的好处是阴影精灵可以像往常一样被动画化,而不必在单独的 renderTexture 上调用“访问”。

其余的部分:

我还修改了 CocosNode 以允许我向图层添加阴影,该图层链接到另一个 CocosNode。这样,阴影被渲染为地板的子节点,(或用于阴影混合的 0% 黑色背景精灵),但链接到另一个 CocosNode。当精灵移动时,如果它有阴影,它也会更新阴影位置。这允许我在屏幕上的所有对象下方拥有所有阴影,并让阴影自动跟随对象。

对不起,答案很长。也许我的解决方案很笨拙,但似乎效果很好。

于 2010-01-27T07:28:17.223 回答