• cocos源码分析--绘制顺序LocalZOrder、GlobalZOrder、OrderOfArrival


    使用规则

    节点的渲染顺序跟节点的三个成员变量有关(_localZOrder、_globalZOrder、_orderOfArrival)分别对应三个设置函数setLocalZOrder、setGlobalZOrder、setOrderOfArrival。无论是_localZOrder、_globalZOrder、_orderOfArrival都是越大的越后渲染,越小的越先渲染,而且有_globalZOrder的优先级大于_localZOrder的优先级大于_orderOfArrival的优先级。所以我们判断节点间的渲染(绘制)顺序时应先对比他们的_globalZOrder值,如若相等,再对比他们的_localZOrder值,如若相等,再对比他们的_orderOfArrival值。其中,_orderOfArrival值在调用addChild函数是自动给出,一般我们不调用setOrderOfArrival函数去更改节点间的渲染(绘制)顺序。

    当采用LocalZOrder作为节点渲染(绘制)顺序的判断值时,父节点的LocalZOrder不与子节点的LocalZOrder值作比较。子节点中LocalZOrder值小于0的节点作为以父节点为根节点的树的左子树的根节点,大于0的作为右子树的根节点。所以在中序遍历下,先(渲染)绘制子节点中LocalZOrder值小于0的子节点,再渲染(绘制)父节点,再渲染LocalZOrder值大于0的子节点。

    代码原理

    localZOrder和orderOfArrival在visit里面

    void Node::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags)
    {
        // quick return if not visible. children won't be drawn.
        if (!_visible)
        {
            return;
        }
    
        uint32_t flags = processParentFlags(parentTransform, parentFlags);
    
        // IMPORTANT:
        // To ease the migration to v3.0, we still support the Mat4 stack,
        // but it is deprecated and your code should not rely on it
        /*
         为了便于迁移到v3.0,我们仍然支持Mat4堆栈,
               但它已被弃用,您的代码不应该依赖它
         */
        Director* director = Director::getInstance();
        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
        //把刚生产的模型视图矩阵加入到顶部的modeview【对scene来说,执行下面代码之前,里面已经有3个modelview】
        //这个代码针对2.0的,对3.1没啥意义了
        director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
    
        int i = 0;
    
        if(!_children.empty())
        {
            sortAllChildren();
            // draw children zOrder < 0
            for( ; i < _children.size(); i++ )
            {
                auto node = _children.at(i);
    
                if ( node && node->_localZOrder < 0 )
                    node->visit(renderer, _modelViewTransform, flags);
                else
                    break;
            }
            // self draw
            this->draw(renderer, _modelViewTransform, flags);
    
            for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
                (*it)->visit(renderer, _modelViewTransform, flags);
        }
        else
        {
            this->draw(renderer, _modelViewTransform, flags);
        }
       
        /*
         画完了就退出战,是兼容2.0的时候,现在不需要这个了
         矩阵的转换都在GPU的shader中了
        */
        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
        
        // FIX ME: Why need to set _orderOfArrival to 0??
        // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920
        // reset for next frame
        // _orderOfArrival = 0;
    }
    void Node::sortAllChildren()
    {
        if( _reorderChildDirty ) {
            std::sort( std::begin(_children), std::end(_children), nodeComparisonLess );
            _reorderChildDirty = false;
        }
    }
    bool nodeComparisonLess(Node* n1, Node* n2)
    {
        return( n1->getLocalZOrder() < n2->getLocalZOrder() ||
               ( n1->getLocalZOrder() == n2->getLocalZOrder() && n1->getOrderOfArrival() < n2->getOrderOfArrival() )
               );
    }

    通过排序之后,然后遍历,加入到 command命令中

    globalZOrder在CCRender中进行排序,代码如下:

    void RenderQueue::sort()
    {
        // Don't sort _queue0, it already comes sorted
        //不对queue0的在进行排序,他们是 按照localQueue排序的
        std::sort(std::begin(_queueNegZ), std::end(_queueNegZ), compareRenderCommand);
        std::sort(std::begin(_queuePosZ), std::end(_queuePosZ), compareRenderCommand);
    }

    所以globalZOrder在LocalZOrder之前。

  • 相关阅读:
    webpack之理解loader
    React中需要多个倒计时的问题
    react.js中实现tab吸顶效果问题
    利用浏览器调试APP中的H5页面
    css一长串连续英文字符的换行
    纯css实现移动端横向滑动列表
    javascript数据结构——写一个二叉搜索树
    javascript数据结构——链表
    javascript数组去重
    《正则表达式必知必会(修订版)》笔记
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/9199309.html
Copyright © 2020-2023  润新知