zoukankan      html  css  js  c++  java
  • 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之前。

  • 相关阅读:
    根据一个class,对改class 建一个内表
    将一个内表中的数据,读取到structure中。不用loop循环.
    sap gui中打断点,进入不了断点
    使用python 写一个 股票涨跌提醒功能
    windows使用方法
    mathType插入公式编号,及对公式编号的字体进行修改。调整公式上下间距。
    notefirst使用
    word自动导入目录
    杀死正在运行的进程: linux
    win10系统电脑调节屏幕亮度选项无法显示
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/9199309.html
Copyright © 2011-2022 走看看