好的,我想经过大量研究,我意识到我的思维错误。
首先,有一种方法可以进行 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 将阴影渲染到单独的缓冲区。这可能会对性能产生影响,所以我们将看看它的发展方向。
更新:
好的,我现在有一个可行的解决方案。
奇怪的是,我最终不需要这个解决方案,因为在我的特殊情况下,条带不够明显,不足以保证努力,但这是我想出的解决方案,似乎可以满足我的要求:
首先在整个屏幕上绘制一个 0% 黑色的 alpha png。(我不知道这是否有必要。我不知道屏幕的默认 alpha 是多少)。
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% 黑色。
绘制地板,它将在阴影上方,但使用glBlend( ONE_MINUS_DST_ALPHA, DST_ALPHA )
. 这会产生与使用 将阴影添加到地板上完全相同的结果glBlend( SRC_ALPHA, ONE_MINUS_SRC_ALPHA )
,但是如果您这样做,您将无法将阴影混合在一起(请阅读答案顶部的原因)。
你完成了!这个方法的好处是阴影精灵可以像往常一样被动画化,而不必在单独的 renderTexture 上调用“访问”。
其余的部分:
我还修改了 CocosNode 以允许我向图层添加阴影,该图层链接到另一个 CocosNode。这样,阴影被渲染为地板的子节点,(或用于阴影混合的 0% 黑色背景精灵),但链接到另一个 CocosNode。当精灵移动时,如果它有阴影,它也会更新阴影位置。这允许我在屏幕上的所有对象下方拥有所有阴影,并让阴影自动跟随对象。
对不起,答案很长。也许我的解决方案很笨拙,但似乎效果很好。