【深入了解cocos2d-x 3.x】UI树(3)——UI树的渲染机制

前端之家收集整理的这篇文章主要介绍了【深入了解cocos2d-x 3.x】UI树(3)——UI树的渲染机制前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

渲染系统是游戏引擎里面最重要的一个模块之一了,如何遍历UI树,如何将UI合理的渲染在屏幕上,如何选择渲染的顺序,这是渲染系统最需要考虑的。其实遍历的顺序就决定了渲染的顺序。

cocos2d-x的渲染函数是通过Node::visit来进行的,首先看看这个函数干了什么吧

  1. void Node::visit(Renderer* renderer,const Mat4 &parentTransform,uint32_t parentFlags)
  2. {
  3. // quick return if not visible. children won't be drawn.
  4. if (!_visible)
  5. {
  6. return;
  7. }
  8.  
  9. uint32_t flags = processParentFlags(parentTransform,parentFlags);
  10. bool visibleByCamera = isVisitableByVisitingCamera();
  11.  
  12. int i = 0;
  13.  
  14. if(!_children.empty())
  15. {
  16. sortAllChildren();
  17. // draw children zOrder < 0
  18. for( ; i < _children.size(); i++ )
  19. {
  20. auto node = _children.at(i);
  21.  
  22. if (node && node->_localZOrder < 0)
  23. node->visit(renderer,_modelViewTransform,flags);
  24. else
  25. break;
  26. }
  27. // self draw
  28. if (visibleByCamera)
  29. this->draw(renderer,flags);
  30.  
  31. for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
  32. (*it)->visit(renderer,flags);
  33. }
  34. else if (visibleByCamera)
  35. {
  36. this->draw(renderer,flags);
  37. }
  38. }

然后可以开始一步一步分析代码了,首先快速去掉不可见的元素,并且不绘制它的子元素。_visible的判断就干了这件事情。

然后判断子节点是否为空,子节点为空的判断是否在摄像机可视范围内,只有在可视范围内才进行绘制,如下:

  1. else if (visibleByCamera)
  2. {
  3. this->draw(renderer,flags);
  4. }

然后重点就是子节点非空的情况了,子节点非空的时候,先将所有子节点进行排序,根据什么排序呢?走进sortAllChildren函数看一看
  1. void Node::sortAllChildren()
  2. {
  3. if (_reorderChildDirty)
  4. {
  5. std::sort(std::begin(_children),std::end(_children),nodeComparisonLess);
  6. _reorderChildDirty = false;
  7. }
  8. }

还要继续深入nodeComparisonLess函数
  1. bool nodeComparisonLess(Node* n1,Node* n2)
  2. {
  3. return( n1->getLocalZOrder() < n2->getLocalZOrder() ||
  4. ( n1->getLocalZOrder() == n2->getLocalZOrder() && n1->getOrderOfArrival() < n2->getOrderOfArrival() )
  5. );
  6. }

可以看到它是根据LocalZOrder进行排序的,当LocalZOrder相同的情况下,根据加入UI树的顺序排序。那么LocalZOrder就是非常重要的元素了,排序好的子节点是基于LocalZOrder递增的。接下来看看子节点是如何进行绘制的。
  1. // draw children zOrder < 0
  2. for( ; i < _children.size(); i++ )
  3. {
  4. auto node = _children.at(i);
  5.  
  6. if (node && node->_localZOrder < 0)
  7. node->visit(renderer,flags);
  8. else
  9. break;
  10. }

首先绘制_localZOrder小于0的,然后绘制自身 最后绘制大于等于0的
  1. // self draw
  2. if (visibleByCamera)
  3. this->draw(renderer,flags);

下面是一张图便于理解



所以UI树的遍历方法就是中序遍历的深度优先算法。总结如下:

1.遍历左边子节点

2.遍历根节点

3.遍历右边子节点


通过这样的方法,可以保证UI的绘制顺序可以通过_localZOrder 来调节,小于0的将被首先绘制,然后再绘制父节点。然后再绘制大于0的。

所以综上所述,_localZOrder 越小的元素将会被优先绘制。

猜你在找的Cocos2d-x相关文章