Blendfunc behaviour CCLayerGradient

Hi,

I am trying to figure out how to change the behaviour of blending when using CCLayerGradient (Cocos2d-x 2.2.6).

I am testing a few different blendfunc combinations, and got stuck on this one:
ccBlendFunc bf = { GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA };

If I create a CCLayerGradient that has an end color alpha of zero, and the above blendfunc, it does not fade out. Instead it will be fully opacque on both ends.

If I instead create a sprite with a gradient texture, that fades out to zero, it works correctly and fades out when using the same blendfunc.

Does anyone know how I can make the CCLayerGradient render the same way as the sprite/textured version? Added an image that shows the problem.

Other blendfunc combinations like (GL_SRC_ALPHA, GL_ONE) works correctly with CCLayerGradient.

An alternative would be to create a shader instead of using LayerGradient.

Anyone know what the performance difference is between using LayerGradient compared to something like this? How to draw this gradient?

Played around a bit and got the correct behaviour after making a change to the shader:

Change the vertex shader from:
v_fragmentColor = a_color;

To:
v_fragmentColor = a_color * a_color.a;

Can anyone explain what is happening here? Some premultiplied alpha thing going on? Can it be optimized? Thanks

Edit:
Doesnt have to be changed in the shader. Adding this at the bottom of updateColor also works:

// Premultiply
for (int i = 0; i < 4; i++)
{
m_pSquareColors[i].r *= m_pSquareColors[i].a;
m_pSquareColors[i].g *= m_pSquareColors[i].a;
m_pSquareColors[i].b *= m_pSquareColors[i].a;
}

Still not sure what is happening here tbh.

1 Like

This seems like a bug to me.

If we look at the updateBlendFunc in Sprite class, it does apply the opacity to the RGB when it is premultiplied.

However, in the LayerColor class (base of LayerGradient), the blendFunc is initialized to non-premultiplied by default, and there is no code that performs the setOpacityModifyRGB like in Sprite class.

Though, think i have read somewhere that the Layer class is old, and it is more or less superseded by the UILayout class. You might want to try that out.
And Cocos2d team, if that is true, you may want to deprecate the old Layer class?

Edit: it seems there’s no function provided to change the blendFunc for UILayout class, so it can’t totally replace the Layer class apparently.