美文网首页
cocos creator 2.4.0 渲染流程详解(三:Ren

cocos creator 2.4.0 渲染流程详解(三:Ren

作者: vectorZ | 来源:发表于2020-08-08 22:37 被阅读0次

全文共5000+字,分为8个章节,由本人历时一周整理而来。由于篇幅问题,将本文分为8个章节分开发布。全文 () 详细描述了cocoscreator 引擎的2.40版本中,web平台的js部分引擎的渲染流程。请将文章配合源码一起食用!

​由于我尚在学习引擎源码中,文章可能有不正确的部分,所以我会不断更新内容。如有错误或补充,请留言交流!


全部章节链接:

一:渲染流程中用到的核心类

二 : 渲染流程详解

三: RenderFlow 的运行逻辑

四: Assembler 的作用

五: ModelBatcher 数据合批

六: 材质系统

七: ForwardRender


三 RenderFlow 的运行逻辑

RenderFlow : 渲染流,用以遍历场景下所有节点,根据每个节点的_renderFlag , 处理节点的位置,颜色,透明度,更新并渲染。

3.1 性能优化

在v1.x版本中,每次渲染都会进行很多动态判断,需要去判断每个节点是否需要更新位置矩阵,是否需要渲染,在这些过程中会有很多无用分支判断,消耗性能。
所以在v2.x版本中,RenderFlow根据渲染过程中调用的频繁度划分出多个渲染状态,比如 Transform,Render,Children 等,而每个渲染状态都对应了一个函数。在 RenderFlow 的初始化过程中,会预先根据这些状态创建好对应的渲染分支,这些分支会把对应的状态依次链接在一起。在渲染前会更新该节点的_renderFlag ,在渲染该节点时就可以直接根据 _renderFlag的值,进行相应分支的处理,不用进行多余的状态判断。
例如一个节点在当前帧需要更新矩阵,以及需要渲染自己,那么这个节点会更新他的 flag 为
node._renderFlag = RenderFlow.FLAG_TRANSFORM | RenderFlow.FLAG_RENDER。

更加详细的内容可见文末的相关链接中 : RenderFlow的性能优化.

3.2 RenderFlow 内的链式方法的创建与调用

RenderFlow中根据 _renderFlag 获取渲染流的代码如下:

function getFlow (flag) {
    let flow = null;
    let tFlag = FINAL;
    while (tFlag > 0) {
        if (tFlag & flag)// 如果flag标识匹配,则添加新的渲染流
            flow = createFlow(tFlag, flow);// 需要把上一步创建flow传入,作为子流
        tFlag = tFlag >> 1;// 标志右移一位
    }
    return flow;
}

createFlow() 中会根据flag创建对应的渲染流,并加入链中,代码如下:

function createFlow (flag, next) {
    let flow = new RenderFlow();
    flow._next = next || EMPTY_FLOW;// 将本次创建的flow加入链表首部
    // 根据不同的flag设置不同的处理方法
    switch (flag) {
        case DONOTHING: flow._func = flow._doNothing; break;
        case BREAK_FLOW: flow._func = flow._doNothing; break;
        case LOCAL_TRANSFORM: flow._func = flow._localTransform; break;
        case WORLD_TRANSFORM: flow._func = flow._worldTransform; break;
        case OPACITY: flow._func = flow._opacity; break;
        case COLOR: flow._func = flow._color; break;
        case UPDATE_RENDER_DATA: flow._func = flow._updateRenderData; break;
        case RENDER: flow._func = flow._render; break;
        case CHILDREN: flow._func = flow._children; break;
        case POST_RENDER: flow._func = flow._postRender; break;
    }
    return flow;
}

RenderFlow是根据node节点上的_renderFlag 来进行不同的渲染流程,所以当node节点上的位置,颜色,透明度等参数改变后,需要同步修改_renderFlag。这样在渲染时会去根据flag处理对应的流程。

3.3 详解 RenderFlow 的不同操作

RenderFlow根据 _renderFlag 创建了链式渲染流,但各个不同的FLAG对应的方法,都做了些什么,下面会详细说明。

  • _localTransform 方法
    更新本地坐标矩阵。(Tips:节点的位置通过本地坐标矩阵和世界坐标矩阵管理,通过矩阵叉乘来进行高效的坐标转换,具体内容待继续学习了解。。。)
  • _worldTransform 方法
    更新世界坐标矩阵。
  • _opacity 方法
    处理透明度。
  • _color 方法
    更新 renderCompent 的颜色
  • _updateRenderData 方法
    更新渲染数据,调用 Assembler 里的 updateRenderData 方法,主要是更新uv和顶点数据。
  • _render 方法
_proto._render = function (node) {
    let comp = node._renderComponent;
    comp._checkBacth(_batcher, node._cullingMask);
    comp._assembler.fillBuffers(comp, _batcher);
    this._next._func(node);
};

调用 RenderComponent 的 _checkBacth 检测合批。
调用 Assembler 的 fillBuffers 填充数据。

  • _children 方法
    遍历子节点进行子节点的渲染流程。
  • _postRender 方法
    (暂时不理解 todo)

相关链接

  1. 自定义渲染https://docs.cocos.com/creator/manual/zh/advanced-topics/custom-render.html#%E8%87%AA%E5%AE%9A%E4%B9%89-assembler

  2. RenderFlow的性能优化http://docs.cocos.com/creator/manual/zh/advanced-topics/render-flow.html#

  3. 自定义渲染合批之自定义顶点格式https://forum.cocos.org/t/demo/95087

  4. 自定义RenderFlow,处理背包等场景下drawcall过多:https://forum.cocos.org/t/ui/80026

  5. 材质系统https://docs.cocos.com/creator3d/manual/zh/material-system/overview.html

相关文章

网友评论

      本文标题:cocos creator 2.4.0 渲染流程详解(三:Ren

      本文链接:https://www.haomeiwen.com/subject/cakqdktx.html