opengl-escocos2d-xalphablendingcocos2d-x-3.0

Partially transparent, A xor B alpha blending in cocos2d-x?


I'd like to blend two Sprites in cocos2d-x, without having these blending with the underlying Layer. From the Wikipedia article about alpha compositing, we have the following image:

enter image description here

I'm interested in achieving the effect as displayed in the "A xor B" category, second row (partially transparent A and B).

I've experimented with different blending functions, like

Sprite* sprite1 = Sprite::create("image.png");
BlendFunc bf = { GL_ONE, GL_ZERO };
sprite1->setBlendFunc(bf);

Sprite* sprite2 = Sprite::create("image.png");
BlendFunc bf = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
sprite2->setBlendFunc(bf);

// Add sprites to layer here

but I can't imagine what would make this approach work. I believe I need to dive into the rendering pipeline in order to get this right. :/ For instance, I've seen an example over at the OpenGL-forums that claims to do what I want. The author uses the following

//clear depthbuffer and render only planes being further in the background
glClearDepth( 0.0 );
glClear( GL_DEPTH_BUFFER_BIT );
glDepthFunc( GL_GREATER );

//disable blending and render only color of the planes  
glDisable( GL_BLEND );
glColorMask( true, true, true, false );

//--> RENDER CONTENT

//reset depthbuffer
glClearDepth( 1.0 );
glClear( GL_DEPTH_BUFFER_BIT );
glDepthFunc( GL_LESS );

//reset to standard blending
glEnable( GL_BLEND );
glColorMask( true, true, true, true );

//--> RENDER CONTENT

where he/she is rendering the content twice to achieve the desired result. This doesn't seem like a terribly viable path in the cocos2d-x ecosystem. Is there any way to make this happen using the existing cocos2d-x ver. 3.1 rendering pipeline?


Solution

  • Ok, so this is as dirty as it gets. But for the moment, I'll workaround the issue by adding another (identical) sprite. Like so:

    Sprite* sprite0 = Sprite::create("image2.png");     
    // This ensures a lower Z-order than sprite1 and sprite2, 
    // but same image and position as sprite2.
    sprite0->setBlendFunc(cocos2d::BlendFunc::DISABLE);
    Sprite1->setPosition(150.0f, 150.0f);
    
    Sprite* sprite1 = Sprite::create("image1.png");
    sprite1->setBlendFunc(cocos2d::BlendFunc::DISABLE);
    Sprite1->setPosition(100.0f, 100.0f);
    
    Sprite* sprite2 = Sprite::create("image2.png");
    BlendFunc bf = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
    sprite2->setBlendFunc(bf);
    Sprite2->setPosition(150.0f, 150.0f);
    

    Not pretty, but get's the job done.