您的位置:首页 > Web前端 > Node.js

利用CCSpriteBatchNode来批量渲染CCSprite的时候无法设置shader的问题

2014-05-28 18:44 344 查看
之前按着网上的设置,已经可以将CCSprite设置成灰色(不知道怎么设置的同学可以随便在X度搜索一下,以下给出随便一个链接http://my.oschina.net/u/1430085/blog/191673,有兴趣的同学可以再看一下),

但是项目中有一个类继承了CCSprite,相当于一个九宫格图片,这些图片的生成是通过CCSpriteBatchNode来批量渲染的,对于这些节点,无法设置shader。代码已经调用,可是不起作用,通过查看CCSpriteBatchNode的代码,看到了原因

bool CCSpriteBatchNode::initWithTexture(CCTexture2D *tex,unsignedint capacity)
{
    m_blendFunc.src =CC_BLEND_SRC;
    m_blendFunc.dst =CC_BLEND_DST;
    m_pobTextureAtlas =
new CCTextureAtlas();

    if (0 == capacity)
    {
        capacity = kDefaultSpriteBatchCapacity;
    }
    
    m_pobTextureAtlas->initWithTexture(tex, capacity);

    updateBlendFunc();

    // no lazy alloc in this node
    m_pChildren = newCCArray();
    m_pChildren->initWithCapacity(capacity);

    m_pobDescendants =
new CCArray();
    m_pobDescendants->initWithCapacity(capacity);

    setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor));
    return true;
}
通过上面的代码,我们可以看到在CCSpriteBatchNode中,已经对shader进行了设置,那么通过这个节点所渲染的CCSprite,再怎么设置也没有用。
我就做了一个实验,将kCCShader_PositionTextureColor换成了ccPositionTextureGray_frag(根据你自己写得不同shader不同不同,这个是引用上面的链接的,我自己项目里写的是kCCShader_PositionTextureGray),然后所有通过CCSpriteBatchNode生成的CCSprite都会变成灰色。那么下面的问题就在于如何让CCSprite设置shader的时候让它的CCSpriteBatchNode也改变,其实就是改变CCSpriteBatchNode的shader。
继续阅读CCSpriteBatchNode的代码:

// draw
void CCSpriteBatchNode::draw(void)
{
    CC_PROFILER_START("CCSpriteBatchNode - draw");

    // Optimization: Fast Dispatch
    if(m_pobTextureAtlas->getTotalQuads() ==0 )
    {
        return;
    }

    CC_NODE_DRAW_SETUP();

    arrayMakeObjectsPerformSelector(m_pChildren,updateTransform,CCSprite*);

    ccGLBlendFunc(
m_blendFunc.src, m_blendFunc.dst );

    m_pobTextureAtlas->drawQuads();

    CC_PROFILER_STOP("CCSpriteBatchNode - draw");
}
在这个函数中我看到CCSpriteBatchNode会调用CCSprite的updateTransform,方法,再进入到CCSprite的updateTransform方法中:

void CCSprite::updateTransform(void)
{
    CCAssert(m_pobBatchNode,"updateTransform is only valid when CCSprite is being rendered using an CCSpriteBatchNode");
噢~原来是这样,只有CCSpriteBatchNode会调用这个方法,那么下一个问题就是如何在这个方法中设置CCSpriteBatchNode的shader。
在利用CCSpriteBatchNode生成CCSprite的时候,CCSpriteBatchNode会对CCSprite设置CCSpriteBatchNode:

void CCSpriteBatchNode::insertChild(CCSprite *pSprite,unsignedint uIndex)
{
    pSprite->setBatchNode(this);
    pSprite->setAtlasIndex(uIndex);
    pSprite->setDirty(true);

    if(m_pobTextureAtlas->getTotalQuads() ==m_pobTextureAtlas->getCapacity())
    {
        increaseAtlasCapacity();
    }

    ccV3F_C4B_T2F_Quad quad = pSprite->getQuad();
    m_pobTextureAtlas->insertQuad(&quad, uIndex);

    ccArray *descendantsData =
m_pobDescendants->data;

    ccArrayInsertObjectAtIndex(descendantsData, pSprite, uIndex);

    // update indices
    unsigned int i = uIndex+1;
    
    CCSprite* pChild = NULL;
    for(; i<descendantsData->num; i++){
        pChild = (CCSprite*)descendantsData->arr[i];
        pChild->setAtlasIndex(pChild->getAtlasIndex() +1);
    }

    // add children recursively
    CCObject* pObj = NULL;
    CCARRAY_FOREACH(pSprite->getChildren(), pObj)
    {
        pChild = (CCSprite*)pObj;
        unsigned int idx =atlasIndexForChild(pChild, pChild->getZOrder());
        insertChild(pChild, idx);
    }
}
这样就可以在CCSprite中获取到生成自己的CCSpriteBatchNode了
最后,在setGray(isGray)  (这个函数需要你自己写,上面的例子也会提到)中对CCSpriteBatchNode进行设置就好了

getBatchNode()->setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureGray));
大功告成~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cocos2dx CCSprite
相关文章推荐