cocos2d3.2 渲染队列的结构和执行流程分析

cocos2d3.2 渲染队列的结构和执行流程分析,第1张

概述在一开始看Render里面代码的时候对render方法有点疑惑: void Renderer::render(){ _isRendering = true; if (_glViewAssigned) { //Process render commands //1. Sort render commands based on ID

在一开始看Render里面代码的时候对render方法有点疑惑:

voID Renderer::render(){    _isRendering = true;       if (_glVIEwAssigned)    {        //Process render commands        //1. Sort render commands based on ID        for (auto &renderqueue : _renderGroups)        {            renderqueue.sort();        }        visitRenderQueue(_renderGroups[0]);    }    clean();    _isRendering = false;}

这里对每个渲染队列进行了排序,然后访问第一个渲染队列,那么其他的渲染队列怎么去访问呢?还有什么时候会去增加一个渲染队列呢?

带着这个疑问我们进入今天的正题。

首先_renderGroups中的每个元素都是一个渲染队列RenderQueue,在Render构造出来的时候会有一个默认的渲染队列放入到_renderGroups中。渲染队列中保存数据的是一个数组_commands,根据放入到这个渲染队列中的命令属性(globalZorder,is3D,istransparent)决定到底把这个命令放入到_commands中的那个位置中。这个其实在将渲染机制的时候就已经提到过了。很简单,不用赘述。

在访问一个队列的时候,无非就是把其中的每个位置中所有的命令拿出来处理,processRenderCommand 就是对命令的具体处理方式:

voID Renderer::processRenderCommand(RenderCommand* command){    auto commandType = command->getType();    if( RenderCommand::Type::TRIANGLES_COMMAND == commandType)    {        //Draw if we have batched other commands which are not triangle command        flush3D();        flushQuads();                //Process triangle command        auto cmd = static_cast<TrianglesCommand*>(command);                //Draw batched Triangles if necessary        if(cmd->isSkipBatching() || _filledVertex + cmd->getVertexCount() > VBO_SIZE || _filledindex + cmd->getIndexCount() > INDEX_VBO_SIZE)        {            CCASSERT(cmd->getVertexCount()>= 0 && cmd->getVertexCount() < VBO_SIZE,"VBO for vertex is not big enough,please break the data down or use customized render command");            CCASSERT(cmd->getIndexCount()>= 0 && cmd->getIndexCount() < INDEX_VBO_SIZE,"VBO for index is not big enough,please break the data down or use customized render command");            //Draw batched Triangles if VBO is full            drawBatchedTriangles();        }                //Batch Triangles        _batchedCommands.push_back(cmd);                fillVerticesAndindices(cmd);                if(cmd->isSkipBatching())        {            drawBatchedTriangles();        }            }    else if ( RenderCommand::Type::QUAD_COMMAND == commandType )    {        //Draw if we have batched other commands which are not quad command        flush3D();        flushTriangles();                //Process quad command        auto cmd = static_cast<QuadCommand*>(command);                //Draw batched quads if necessary        if(cmd->isSkipBatching()|| (_numberQuads + cmd->getQuadCount()) * 4 > VBO_SIZE )        {            CCASSERT(cmd->getQuadCount()>= 0 && cmd->getQuadCount() * 4 < VBO_SIZE,please break the data down or use customized render command");            //Draw batched quads if VBO is full            drawBatchedQuads();        }                //Batch Quads        _batchQuadCommands.push_back(cmd);                fillQuads(cmd);                if(cmd->isSkipBatching())        {            drawBatchedQuads();        }    }    else if (RenderCommand::Type::MESH_COMMAND == commandType)    {        flush2D();        auto cmd = static_cast<MeshCommand*>(command);                if (cmd->isSkipBatching() || _lastBatchedMeshCommand == nullptr || _lastBatchedMeshCommand->getMaterialID() != cmd->getMaterialID())        {            flush3D();                        if(cmd->isSkipBatching())            {                cmd->execute();            }            else            {                cmd->preBatchDraw();                cmd->batchDraw();                _lastBatchedMeshCommand = cmd;            }        }        else        {            cmd->batchDraw();        }    }    else if(RenderCommand::Type::GROUP_COMMAND == commandType)    {        flush();        int renderQueueID = ((GroupCommand*) command)->getRenderQueueID();        visitRenderQueue(_renderGroups[renderQueueID]);    }    else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)    {        flush();        auto cmd = static_cast<CustomCommand*>(command);        cmd->execute();    }    else if(RenderCommand::Type::BATCH_COMMAND == commandType)    {        flush();        auto cmd = static_cast<BatchCommand*>(command);        cmd->execute();    }    else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType)    {        flush();        auto cmd = static_cast<PrimitiveCommand*>(command);        cmd->execute();    }    else    {        cclOGERROR("UnkNown commands in renderQueue");    }}

RenderCommand::Type::TRIANGLES_COMMAND 和RenderCommand::Type::QUAD_COMMAND的命令很类似,它们采用了批量渲染,超过了VBO的大小就触发批量渲染。

当看到RenderCommand::Type::GROUP_COMMAND类型的命令时,会触发去访问其它渲染队列。具体是哪个渲染队列要看这个groupCommand的renderQueueID。

int renderQueueID = ((GroupCommand*) command)->getRenderQueueID(); visitRenderQueue(_renderGroups[renderQueueID]);

所以如果我们知道了groupCommand的创建过程就应该能解决文章开始的疑惑了。

在创建一个groupCommand的时候,会去向groupcommandmanager申请一个ID,如果没有ID,那么会创建一个新的ID,并且Render会创建一个渲染队列。初始化完成之后,放加入到Render的_renderGroups中去,

voID Renderer::addCommand(RenderCommand* command){    int renderQueue =_commandGroupStack.top();    addCommand(command,renderQueue);}voID Renderer::addCommand(RenderCommand* command,int renderQueue){    CCASSERT(!_isRendering,"Cannot add command while rendering");    CCASSERT(renderQueue >=0,"InvalID render queue");    CCASSERT(command->getType() != RenderCommand::Type::UNKNowN_COMMAND,"InvalID Command Type");    _renderGroups[renderQueue].push_back(command);}

注意组命令 还是会放到当前渲染队列的末尾,_commandGroupStack存放着所有加入到_renderGroups中的组命令的ID。

组命令加入之后,才会把它的ID放入到_commandGroupStack中,这意味着所有后来加入的命令会放到下一个渲染队列中去。当执行到这个组命令的时候,会根据它的ID去执行ID对应的渲染队列。


总结:每个渲染队列的末尾总会是一个组命令(如果有的话),这个组命令执行的时候触发了下一个渲染队列的执行。


OVER!!!

总结

以上是内存溢出为你收集整理的cocos2d3.2 渲染队列的结构和执行流程分析全部内容,希望文章能够帮你解决cocos2d3.2 渲染队列的结构和执行流程分析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1069100.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存