cocos2d3.2 渲染队列的结构和执行流程分析
2015-08-22 19:21
447 查看
在一开始看Render里面代码的时候对render方法有点疑惑:
这里对每个渲染队列进行了排序,然后访问第一个渲染队列,那么其他的渲染队列怎么去访问呢?还有什么时候会去增加一个渲染队列呢?
带着这个疑问我们进入今天的正题。
首先_renderGroups中的每个元素都是一个渲染队列RenderQueue,在Render构造出来的时候会有一个默认的渲染队列放入到_renderGroups中。渲染队列中保存数据的是一个数组_commands,根据放入到这个渲染队列中的命令属性(globalZorder,is3D,isTransparent)决定到底把这个命令放入到_commands中的那个位置中。这个其实在将渲染机制的时候就已经提到过了。很简单,不用赘述。
在访问一个队列的时候,无非就是把其中的每个位置中所有的命令拿出来处理,processRenderCommand 就是对命令的具体处理方式:
RenderCommand::Type::TRIANGLES_COMMAND 和RenderCommand::Type::QUAD_COMMAND的命令很类似,它们采用了批量渲染,超过了VBO的大小就触发批量渲染。
当看到RenderCommand::Type::GROUP_COMMAND类型的命令时,会触发去访问其它渲染队列。具体是哪个渲染队列要看这个groupCommand的renderQueueID。
所以如果我们知道了groupCommand的创建过程就应该能解决文章开始的疑惑了。
在创建一个groupCommand的时候,会去向groupcommandmanager申请一个id,如果没有id,那么会创建一个新的id,并且Render会创建一个渲染队列。初始化完成之后,放加入到Render的_renderGroups中去,
注意组命令 还是会放到当前渲染队列的末尾,_commandGroupStack存放着所有加入到_renderGroups中的组命令的id。
组命令加入之后,才会把它的id放入到_commandGroupStack中,这意味着所有后来加入的命令会放到下一个渲染队列中去。当执行到这个组命令的时候,会根据它的id去执行id对应的渲染队列。
总结:每个渲染队列的末尾总会是一个组命令(如果有的话),这个组命令执行的时候触发了下一个渲染队列的执行。
OVER!!!
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, "VBO for vertex is not big enough, 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!!!
相关文章推荐
- Cocos2d-X 程序是如何开始运行与结束的
- Cocos2d基础学习
- 谈论quick-cocos2d-x和cocos2d-x lua了解差异
- Cocos2d—android 中常用的工具类
- cocos2d-x简单绘图(DrawNode)
- cocos2d-js 2048带动画实现
- 【cocos2d-x】3.0使用cocos-console创建,编,部署游戏
- cocos2dx 3.7中 AppDelegate.h的class TestController;这种写法的具体意思不太明白,只能猜是类似于外部定义的东西。
- 初识Cocos2D-X
- android cocos2dx游戏-加入截图和分享微博功能
- 五、触摸事件的吞噬和传递
- 第一篇 cocos2d-x学习总结
- 2.cocos2dx 3.2在语法的差异,lambada使用表达式和function和bind使用功能
- 火云开发课堂 - 《使用Cocos2d-x 开发3D游戏》系列 第六节:VS基础:树木的摇动
- c++11特性与cocos2d-x 3.0之std::bind与std::function
- quick - cocos2d 本地数据存储
- c++11特性与cocos2d-x 3.0之std::bind与std::function
- cocos2dx 3.1.1移植安卓apk (lua交叉编译器项目 mac环境)
- cocos2d-js导弹跟踪算法(一边追着目标移动一边旋转角度)
- cocos2dx-3.1加入cocosStudio参考库 libCocosStudio