GroupCommand

这个类不包含具体的绘制命令,主要是cocos2dx提供用来完成分组绘制的功能。比如你有一批绘制命令他们可能类型不同,有的是BatchCommand,有的是QuadCommand类,但这些命令必须依次被执行,中间不能插入其他来源的命令。就比如RenderTexture动态创建纹理。举个例子

 		RenderTexture* tex = RenderTexture::create(s.width, s.height, Texture2D::PixelFormat::RGBA8888);
		tex->retain();

		tex->begin();
		Sprite* pTempSprite1 = Sprite::createWithSpriteFrame(pOldSprite1->getDisplayFrame());
		pTempSprite1->visit();
		Sprite* pTempSprite2 = Sprite::createWithSpriteFrame(pOldSprite2->getDisplayFrame());
		pTempSprite2->visit();
		tex->end();


上面这段代码调用了两个精灵的Visit,应该对应着两个绘制命令,执行这两个命令的时候中间不能执行其他任何命令,顺序也不能变,否则得到的结果就可能不是我们想要的了。

而Render中绘制命令的执行顺序跟加入的顺序没有必然关系,有可能排个序就把这两个命令分散了。但是有了GroupCommand就能完成这个功能。

那么GroupCommand是怎么实现的呢。拿RenderTexture上没那段举例,在跟代码看看。。

void GroupCommand::init(float globalOrder)
{
    _globalOrder = globalOrder;
    auto manager = Director::getInstance()->getRenderer()->getGroupCommandManager();
    manager->releaseGroupID(_renderQueueID);
    _renderQueueID = manager->getGroupID();
}
int GroupCommandManager::getGroupID()
{
    //Reuse old id
    for(auto it = _groupMapping.begin(); it != _groupMapping.end(); ++it)
    {
        if(!it->second)
        {
            _groupMapping[it->first] = true;
            return it->first;
        }
    }

    //Create new ID
//    int newID = _groupMapping.size();
    int newID = Director::getInstance()->getRenderer()->createRenderQueue();
    _groupMapping[newID] = true;

    return newID;
}
int Renderer::createRenderQueue()
{
    RenderQueue newRenderQueue;
    _renderGroups.push_back(newRenderQueue);
    return (int)_renderGroups.size() - 1;
}


 

GroupCommand在初始化的时候会在Render里_renderGroups栈顶创建一个RenderQueue,renderGroups是一个RenderQueue容器。

在RenderTexture的begin里就会调用GroupCommand的初始化函数

void RenderTexture::begin()
{
    Director* director = Director::getInstance();
    CCASSERT(nullptr != director, "Director is null when seting matrix stack");
    
    director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
    _projectionMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
    
    director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    _transformMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    
    if(!_keepMatrix)
    {
        director->setProjection(director->getProjection());
        
        const Size& texSize = _texture->getContentSizeInPixels();
        
        // Calculate the adjustment ratios based on the old and new projections
        Size size = director->getWinSizeInPixels();
        
        float widthRatio = size.width / texSize.width;
        float heightRatio = size.height / texSize.height;
        
        Mat4 orthoMatrix;
        Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1, 1, &orthoMatrix);
        director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);
    }

    _groupCommand.init(_globalZOrder);

    Renderer *renderer =  Director::getInstance()->getRenderer();
    renderer->addCommand(&_groupCommand);
    renderer->pushGroup(_groupCommand.getRenderQueueID());

    _beginCommand.init(_globalZOrder);
    _beginCommand.func = CC_CALLBACK_0(RenderTexture::onBegin, this);

    Director::getInstance()->getRenderer()->addCommand(&_beginCommand);
}


于是我们就在renderGroups栈顶创建了一个新的RenderQueue,而之后的在RenderTexture调用end之前的命令全部会按顺序加入到这个新的RenderQueue,如果这些命令的

_globalOrder没有进行特殊赋值,那他们的绘制顺序也不会改变。最后调用RenderTexture的end,弹出栈顶。

void RenderTexture::end()
{
    _endCommand.init(_globalZOrder);
    _endCommand.func = CC_CALLBACK_0(RenderTexture::onEnd, this);

    Director* director = Director::getInstance();
    CCASSERT(nullptr != director, "Director is null when seting matrix stack");
    
    Renderer *renderer = director->getRenderer();
    renderer->addCommand(&_endCommand);
    renderer->popGroup();
    
    director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
    director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);

}


 

之后非这个RenderTexture的绘制命令将不会进入这个RenderQueue,也就不会影响他的渲染。

 

 

如果有新的RenderTexture开始创建动态纹理会怎样呢?

Render里面有一个stack<int> _commandGroupStack,每次GroupCommand初始化之后创建完RenderQueue,压入renderGroups栈顶,当加入这个GroupCommand命令的时候renderGroups栈顶应该是原先的值,所以GroupCommand不会被加入到新建的RenderQueue中,等加入完之后,RenderTexture就将新的RenderQueue的索引加入到

commandGroupStack中

  _groupCommand.init(_globalZOrder);

    Renderer *renderer =  Director::getInstance()->getRenderer();
    renderer->addCommand(&_groupCommand);
    renderer->pushGroup(_groupCommand.getRenderQueueID());


接下来的非GroupCommand就都会放在心的RenderQueue中,RenderTexture的end,将索引弹出栈顶,而GroupCommand中保存着新RenderQueue的索引,当执行到

GroupCommand时,它会找到对应的RenderQueue,然后执行这个RenderQueue里面的命令

 

以下是添加了20个Sprite后有用同一个RenderTexture进行了两次纹理创建后_renderGroups的结构图

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值