cocos2d / cocos2d-x

Cocos2d-x is a suite of open-source, cross-platform, game-development tools utilized by millions of developers across the globe. Its core has evolved to serve as the foundation for Cocos Creator 1.x & 2.x.
https://www.cocos.com/en/cocos2d-x
18.23k stars 7.05k forks source link

【BUG】clipnode isnot work in Android #14837

Open 1078559858 opened 8 years ago

1078559858 commented 8 years ago

@xiaofeng11 i hava tested cocos2dx v3.8, v3.10 using Language c++ , it works in pc but not work in android After create a new project and copying the code , you can Repetition of this problem. Thanks

code:

    Size size = Size(250 , 500);
    auto w_bg = size.width;
    auto h_bg = size.height;

    auto w_content = size.width;
    auto h_content = size.height + 90;

    auto pos_content = Vec2(240, 400);

    auto layer_stencil = LayerColor::create(Color4B(0xff, 0xff, 0x00, 255));
    layer_stencil->changeWidthAndHeight(w_bg, h_bg);
    layer_stencil->ignoreAnchorPointForPosition(!true);
    layer_stencil->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
    //this->addChild(layer_stencil);

    auto layer_content = LayerColor::create(Color4B(0xff, 0xff, 0xff, 100));
    layer_content->changeWidthAndHeight(w_content, h_content);
    layer_content->ignoreAnchorPointForPosition(!true);
    layer_content->setAnchorPoint(Vec2::ANCHOR_MIDDLE);

    /////////layer_stencil
    auto stencil = layer_stencil;
    auto clipper = ClippingNode::create();
    clipper->setStencil(stencil);
    clipper->setInverted(!true);
    clipper->setAlphaThreshold(0);
    this->addChild(clipper);

    auto content = layer_content;
    clipper->addChild(content);

    ////
    clipper->setPosition(pos_content);
    content->setPosition(0, (-h_content + h_bg)*0.5f);
xiaofeng11 commented 8 years ago

@liamcindy Please take a look on this issue, Thanks.

Pythians commented 5 years ago

On mobile LayerColor set as stencil,
should setAlphaThreshold(1);
it is work

some source code

void ClippingNode::setAlphaThreshold(GLfloat alphaThreshold)
{
#if CC_CLIPPING_NODE_OPENGLES
    if (alphaThreshold == 1 && alphaThreshold != _stencilStateManager->getAlphaThreshold())
    {
        // should reset program used by _stencil
        if (_stencil)
            setProgram(_stencil, _originStencilProgram);
    }
#endif

    _stencilStateManager->setAlphaThreshold(alphaThreshold);
}

void ClippingNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
{
#if CC_CLIPPING_NODE_OPENGLES
        // since glAlphaTest do not exists in OES, use a shader that writes
        // pixel only if greater than an alpha threshold
        GLProgram *program = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_ALPHA_TEST_NO_MV);
        GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), GLProgram::UNIFORM_NAME_ALPHA_TEST_VALUE);
        // set our alphaThreshold
        program->use();
        program->setUniformLocationWith1f(alphaValueLocation, alphaThreshold);
        // we need to recursively apply this shader to all the nodes in the stencil node
        // FIXME: we should have a way to apply shader to all nodes without having to do this
        setProgram(_stencil, program);
#endif
}

void StencilStateManager::onAfterDrawStencil()
{
    // restore alpha test state
    if (_alphaThreshold < 1)
    {
#if CC_CLIPPING_NODE_OPENGLES
        // FIXME: we need to find a way to restore the shaders of the stencil node and its children
#else
        // manually restore the alpha test state
        glAlphaFunc(_currentAlphaTestFunc, _currentAlphaTestRef);
        if (!_currentAlphaTestEnabled)
        {
            glDisable(GL_ALPHA_TEST);
        }
#endif
    }
}