是否可以实现MAX(As,Ad)openGL混合? [英] Is it possible to achieve MAX(As,Ad) openGL blending?

查看:497
本文介绍了是否可以实现MAX(As,Ad)openGL混合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个游戏,我想在一系列的精灵在网格上创建阴影。

I am working on a game where I want to create shadows under a series of sprites on a grid. The shadows are larger than the sprites themselves and the sprites are animated (i.e. move and rotate).

我不能简单地将它们渲染成sprite png,或者阴影会重叠

I cannot simply render them into the sprite png, or the shadows will overlap adjacent sprites.

我也不能简单地把阴影放在一个较低的层上,因为当它们重叠时,他们会在他们的交叉处创建暗带。

I also cannot simply put shadows on a lower layer by themselves, because when they overlap, they will create dark bands at their intersection.

这些精灵是动画,因此不可能大量渲染这些精灵。

These sprites are animated, so it is not feasible to render these en masse.

基本上,我想要精灵的阴影混合在一起,使得它们以设定的不透明度最大化。示例:

Basically, I want the sprites' shadows to blend together such that they max out at a set opacity. Example:

我相信这相当于(Rs,Gs,Bs,Max(As,Ds))的openGL混合,其中我真的不在乎R,G和B,因为它将在src和dst中总是相同的颜色。

I believe this is equivalent to an openGL blending of (Rs,Gs,Bs,Max(As,Ds)), where I don't really care about R,G, and B, as it will always be the same color in src and dst.

但是,这不是一个有效的openGL混合模式。有没有一个简单的方法来完成这一点,特别是在cocos2d-iphone?

However, this is not a valid openGL blending mode. Is there an easy way to accomplish this, especially in cocos2d-iphone?

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

I would be able to approximate this by making the shadow sprites opaque, then applying them both to a parent sprite, and making the parent sprite 40% opacity. However, the way cocos2d works, this only sets the opacity of each child to 40%, rather than the combined sprite image, which results in the same stripe.

推荐答案

确定,我认为经过多番研究,我意识到我的想法中的错误。

OK, I think after much research, I realize the error in my thinking.

首先,有一种方法来做Max Alpha openGL混合,这是使用glBlendEquations。你必须修改draw方法来做到这一点(并为textureNode做一些新的属性在这些方法之间切换),并使用下面的方法之一:

First, there is a way to do Max Alpha openGL blending, and that is using glBlendEquations. You would have to modify the draw method to do this (and make some new attribute for a textureNode to switch between these methods), and use either of these:

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

第一个使用max()作为RGBA,第二个使用RGB的标准加法,max )for alpha。

The first uses max() for RGBA, while the second uses standard addition for RGB, and max() for alpha.

现在,问题是每个sprite和它的孩子,按z顺序绘制到 em> 。这意味着,在绘制第一个阴影之后,它是主屏幕缓冲区的一部分。换句话说,它的不透明度改变了,并且使用max()混合和一个标准的不透明背景,它现在被绘制在背景上,所以当你绘制下一个阴影时,它会做max(As,1)为1,因为背景是不透明的。所以我不实现我想要的混合。如果我的背景是透明的,它会工作,但是我不能应用任何背景后面,我们只能添加到缓冲区。

Now, the problem is that each sprite, and it's children, in z-order, are drawn to the screen. This means, that after the first shadow is drawn, it is part of the main screen buffer. In other words, its opacity is changed, and with max() blending and a standard opaque background, it's now painted onto the background, so when you draw the next shadow, it will do max(As, 1) which is 1, because the background is opaque. So I don't achieve the blending I want. It would "work" if my background was transparent, but then I could not apply any background "behind" that, we can only add to the buffer.

阴影首先,使用max()混合,然后做一个{ONE_MINUS_DST_ALPHA,DST_ALPHA} glBlend。这是一个好的解决方法,但我有其他问题,使这很难。

I could draw the shadows first, using the max() blend and then do a {ONE_MINUS_DST_ALPHA, DST_ALPHA} glBlend. This is an OK workaround, but I have other issues that make this difficult.

现在,真正的解决方案,我终于意识到,是使用RenderTexture渲染阴影到一个单独的缓冲区,然后将它们应用到背景。

Now, the real solution, I finally realize, is to use a RenderTexture to render the shadows to a separate buffer before applying them to the background. This could have performance implications, so we'll see where this goes.

更新:

好的,我现在有一个工作的解决方案。

OK, I have a working solution now.

奇怪的是,我最终不需要这个解决方案毕竟,因为在我的特殊情况下,但是这是我提出的解决方案似乎是做我想要的解决方案:

Oddly, I ended up not needing this solution after all, because in my particular case, the banding was not noticeable enough to warrant the effort, however this is the solution I came up with that seemed to do what I wanted:


  1. 第一个在整个屏幕上绘制一个0%的黑色alpha png。 (我不知道这是否必要,我不知道屏幕的默认alpha是什么)。

  1. First draw a 0% black alpha png to the entire screen. (I don't know if this is necessary. I don't know what the default alpha of the screen is).

将阴影绘制到屏幕使用 glEquationSeperateOES(GL_ADD,GL_MAX_ENT) glBlend(GL_ONE,GL_ONE)。这将混合所有的阴影在一起,如描述,采取alphas的max()。

Draw the shadows to the screen using glEquationSeperateOES( GL_ADD, GL_MAX_ENT) and glBlend( GL_ONE, GL_ONE ). This will blend all of the shadows together as described, taking the max() of the alphas.


  • 因为您要合成为黑色,所以等效于使用 glBlendEquationOES(GL_MAX_ENT)。 (X + 0 == max(X,0))

  • Because you are compositing to black, it is equivalent to use glBlendEquationOES( GL_MAX_ENT ). (X+0 == max(X,0))

glBlend(GL_ZERO,GL_ONE)将消除对步骤1的需要,或至少该层的要求为0%黑色。 GL_ZERO 本质上会强制它为0%黑色。

glBlend( GL_ZERO, GL_ONE ) will eliminate the need of step 1, or at least the requirement of that layer to be 0% black. GL_ZERO essentially forces it to be 0% black.

绘制地面,这将是超过阴影,但使用 glBlend(ONE_MINUS_DST_ALPHA,DST_ALPHA)。这产生与使用 glBlend(SRC_ALPHA,ONE_MINUS_SRC_ALPHA)将阴影添加到底层的完全相同的结果,但是如果你这样做,你将无法

Draw the floor, which will be over the shadows, but use glBlend( ONE_MINUS_DST_ALPHA, DST_ALPHA ). This results in exactly the same results as if you added the shadows to the floor with glBlend( SRC_ALPHA, ONE_MINUS_SRC_ALPHA ), however if you did it this way, you would not be able to blend the shadows together (read why at top of answer).

你完成了!这个方法的好处是阴影精灵可以照常动画,而不必在单独的renderTexture上调用visit。

You are done! The nice thing about this method is that the shadow sprites can be animated as usual, without having to call "visit" on a separate renderTexture.

其余:

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

I also modified CocosNode to allow me to add a shadow to a layer, which links to another CocosNode. This way, the shadow is rendered as a child of the floor, (or the 0% black background sprite for the shadow blending), but is linked to another CocosNode. When a sprite moves, if it has a shadow, it updates the shadows position as well. This allows me to have all shadows below all objects on the screen, and to have the shadows automatically follow the object.

对不起,答案很长。也许我的解决方案是kludgy,但它似乎工作很好。

Sorry for the long answer. Maybe my solution is kludgy, but it seems to work great.

这篇关于是否可以实现MAX(As,Ad)openGL混合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆