Cocos场景遍历与渲染
来源:互联网 发布:抢票软件原理 编辑:程序博客网 时间:2024/06/03 23:37
Cocos场景遍历与渲染
声明:本文主要分析cocos2d-x-3.12的代码,该部分代码在后续版本有一些变化
场景遍历
Cocos在绘制场景时,会遍历当前运行的场景runningScene场景中的所有元素,遍历完成后会生成一个OpenGL绘制命令的队列,然后调用Renderer::render()函数绘制所有元素。遍历场景的调用栈如下。
Node::visit函数
voidNode::visit(Renderer* renderer, constMat4 &parentTransform, uint32_tparentFlags){ // quick return if not visible. children won't be drawn. if (!_visible) { return; } uint32_tflags = processParentFlags(parentTransform, parentFlags); // IMPORTANT: // To ease the migration to v3.0, we still support theMat4 stack, // but it is deprecated and your code should not rely onit _director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); _director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform); boolvisibleByCamera = isVisitableByVisitingCamera(); inti = 0; if(!_children.empty()) { sortAllChildren(); // draw children zOrder < 0 for( ; i < _children.size(); i++ ) { autonode = _children.at(i); if (node && node->_localZOrder < 0) node->visit(renderer, _modelViewTransform, flags); else break; } // self draw if (visibleByCamera) this->draw(renderer, _modelViewTransform, flags); for(autoit=_children.cbegin()+i; it!=_children.cend(); ++it) (*it)->visit(renderer, _modelViewTransform, flags); } elseif (visibleByCamera) { this->draw(renderer, _modelViewTransform, flags); } _director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); // FIX ME: Why need to set _orderOfArrival to 0?? // Please refer tohttps://github.com/cocos2d/cocos2d-x/pull/6920 // reset for next frame // _orderOfArrival = 0;}
该函数主要步骤:
1. 判断几点是否可见,如果不可见则直接退出。所以如果节点不可见,则子节点也不可见。
2. 判断元素是否有孩子节点,
如果没有则调用Node::draw函数生成绘制命令。
如果存在子节点,则会先对所有子节点排序,然后先遍历_localZOrder小于0的子节点,在调用自己的draw函数,最后遍历localZOrder大于等于0的节点。
所以如果localZOrder的值小于0,则会绘制在父节点的下面,如果localZOrder大于等于0,则会绘制在父节点的上面。
子节点排序
排序函数
voidNode::sortAllChildren(){ if (_reorderChildDirty)//只有当子节点有改变时才会排序 { std::sort(std::begin(_children), std::end(_children), nodeComparisonLess); _reorderChildDirty = false; }}
排序比较方式
boolnodeComparisonLess(Node* n1, Node* n2){ return( n1->getLocalZOrder() < n2->getLocalZOrder() || ( n1->getLocalZOrder() == n2->getLocalZOrder() && n1->getOrderOfArrival() < n2->getOrderOfArrival() ) );}
排序会先比较localZOrder的值,小值排在前面。如果localZOrder的值相等,则会比较OrderOfArrival的值。OrderOfArrival是节点插入父节点的顺序,越先插入的节点值会更小,后插入的节点值会更大。所以localZOrder相等时后插入的节点会显示在先插入节点的前面。
OrderOfArrival的生成
Node::addChild函数内部会让子节点调用setOrderOfArrival(s_globalOrderOfArrival++)函数
s_globalOrderOfArrival是一个全局共享的值,起始为0,每次调用addChild,该值都会增加,越后面调用值越大。
场景绘制
在Scene::render函数中,调用visit函数遍历完节点生成所有节点的绘制命令后,会调用renderer->render()函数,在Renderer::render函数内部,会先对绘制命令进行排序,依据Node::_globalZOrder的值从小到达排序,然后再将命令传给OpenGL绘制图像。具体流程如下:
因为OpenGL执行绘制命令,会根据接的的globalZOrder排序,所以globalZOrder也可以控制节点的层级。且globalZOrder是调整节点在整个场景中的层级。
节点层级的控制
影响节点层级一共有三个值globalZOrder、localZOrder、orderOfArrival,都是值越大越靠前。三个值的对层级影响的优先顺序为globalZOrder、localZOrder、orderOfArrival。当globalZOrder的值大时,则会忽略localZOrder和orderOfArrival,globalZOrder值大则排在前面。
orderOfArrival
orderOfArrival是节点添加到父节点时会被设置,child->setOrderOfArrival(s_globalOrderOfArrival++)。所有节点的orderOfArriva都是通过s_globalOrderOfArrival值累加得到的。s_globalOrderOfArrival是Node节点的一个静态变量,初始值为1(intNode::s_globalOrderOfArrival = 1;)。每次有调用addChild函数,则该值会加1,所以所有节点的该值都不一样。
localZOrder
localZOrder在节点的构造函数中设置为0,默认值为0。可以通过函数
voidNode::_setLocalZOrder(intz)设置。
localZOrder和orderOfArrival都只是在遍历子节点时排序使用,排序比较时会先比价LocalZOrder的值,如过不相等则返回相应的比较结果,如果相等则会比较orderOfArrival的值。因为两个值都只是用在子节点排序上,所以localZOrder和orderOfArrival只会影响子节点之间的排序,所以如果两个节点的父节点不同则无法通过localZOrder和orderOfArrival控制层级。
对于子节点和父节点的遍历顺序:
LocalZOrder小于0的子节点à父节点à LocalZOrder大于等于0的子节点。
所以LocalZOrder小于0会绘制在父节点下面。
globalZOrder
globalZOrder在节点的构造函数中设置为0,默认值为0。globalZOrder可以通过函数voidNode::setGlobalZOrder(floatglobalZOrder)设置。
globalZOrder是在场景绘制命令生成后,会根据globalZOrder对节点的绘制命令排序。所以globalZOrder是对场景全局节点的层级进行控制的,不管节点的父节点是谁,只要globalZOrder的值大,则绘制会更靠前。globalZOrder只是控制一个场景的节点,不可跨场景。
层级控制流程
- Cocos场景遍历与渲染
- cocos场景跳转与坐标系
- cocos studio 加载json文件到场景后重新渲染纹理失败
- cocos渲染过程
- cocos Creat 添加场景
- COCOS学习笔记--Cocos引擎渲染流程
- cocos-lua中pairs与ipairs遍历的区别
- 室外大场景渲染技术研究与实现 游戏地图加载
- Cocos进度条和批处理渲染
- cocos入门2:场景切换
- cocos-lua 场景切换动画
- cocos场景管理器-自己用
- 大型场景裁剪渲染
- cocos简单的3d渲染
- cocos 3.2 ListView渲染bug解决办法
- cocos-2dx OPENGL渲染(1)
- cocos-2dx 渲染(2)
- cocos-2dx 渲染(3)
- lost in the city(枚举)
- Javascript闭包(Closure)简化精简版
- 字符编码 ASCII,Unicode 和 UTF-8 概念扫盲
- Zookeeper(三)ZAB协议的两种基本模式:崩溃恢复和广播消息
- C 练习实例28
- Cocos场景遍历与渲染
- CSS预处理器--Sass
- mapreduce标准过程
- IntelliJ IDEA 永久破解的方法
- Node.js 基于socket.io聊天室的BUG解决经过
- 自定义CSDN博客中图片上的水印内容
- vb.net总结
- 宾夕法尼亚大学Coursera运动规划公开课学习有感
- 利用 MSYS2 及osgEarth 构建三维地球模型(1) 软件配置