Cocos creator rendering component source code analysis

  In the cocos engine, all rendering components are inherited from cc.RenderComponent, such as cc.Sprite, cc.Label, etc. The Assembler of the component is mainly responsible for the update processing and filling of the component data. Since different rendering components are also different in data content and filling, each rendering component will have its own Assembler object, and all Assembler objects are inherited Since cc.Assembler. Material as a resource mainly records the rendering state of the rendering component, the texture and shader used.

First, first analyze the Assembler, the main code is as follows:

  

// renderCompCtor component class

// assembler component assembly class

Assembler.register = function (renderCompCtor, assembler) { renderCompCtor.__assembler__ = assembler; }; Assembler.init = function (renderComp) { let renderCompCtor = renderComp.constructor; let assemblerCtor = renderCompCtor.__assembler__; while (!assemblerCtor) { renderCompCtor = renderCompCtor.$super; if (!renderCompCtor) { cc.warn(`Can not find assembler for render component : [${cc.js.getClassName(renderComp)}]`); return; } assemblerCtor = renderCompCtor.__assembler__; } if (assemblerCtor.getConstructor) { assemblerCtor = assemblerCtor.getConstructor(renderComp); } if (!renderComp._assembler || renderComp._assembler.constructor !== assemblerCtor) { let assembler = assemblerPool.get(assemblerCtor); assembler.init(renderComp); renderComp._assembler = assembler; } };

 

  The rendering component is registered in the engine through Assembler.register. For example, the registration code of the graphics rendering component is Assembler.register (cc.Graphics, GraphicsAssembler), cc.Graphics is the graphics class, GraphicsAssembler inherits from the Assembler class, and the rendering component holds_assembler,_assembler持有_renderData,_renderDataInputAssembler都是数据容器,_assembler是数据操作,_assembler可以创建和updateRenderData,更新verts,InputAssembler是在渲染时用到的,用于组织传入GPU的数据.

  

  In v2.x, RenderFlow divides multiple rendering states according to the frequency of calls during the rendering process, such as Transform, Render, Children, etc., and each rendering state corresponds to a function. During the RenderFlow initialization process, corresponding rendering branches will be created according to these states in advance, and these branches will link the corresponding states in turn. For example, if a node needs to update the matrix in the current frame and needs to render itself, then this node will update its flag to node._renderFlag = RenderFlow.FLAG_TRANSFORM | RenderFlow.FLAG_RENDER. When rendering this node, RenderFlow will node._renderFlag enter the transform => render branch according to the state of the node  , without the need for extra state judgment.

  The cc.renderer object is a global object, a renderer object that provides a basic rendering interface. It contains some rendering-related class definitions and some global attributes such as device, InputAssembler, Pass, etc. The core is two attributes, one is _froward is _ flow. _ flow is a cc.RenderFlow class. During the initialization process, an instance of RenderFlow is created and passed into the _flow.init method

initWebGL (canvas, opts) {
        require('./webgl/assemblers');
        const ModelBatcher = require('./webgl/model-batcher');

        this.Texture2D = gfx.Texture2D;
        this.canvas = canvas;
        this._flow = cc.RenderFlow;
        
        if (CC_JSB && CC_NATIVERENDERER) {
            // native codes will create an instance of Device, so just use the global instance.
            this.device = gfx.Device.getInstance();
            this.scene = new renderer.Scene();
            let builtins = _initBuiltins(this.device);
            this._forward = new renderer.ForwardRenderer(this.device, builtins);
            let nativeFlow = new renderer.RenderFlow(this.device, this.scene, this._forward);
            this._flow.init(nativeFlow);
        }
        else {
            let Scene = require('../../renderer/scene/scene');
            let ForwardRenderer = require('../../renderer/renderers/forward-renderer');
            this.device = new gfx.Device(canvas, opts);
            this.scene = new Scene();
            let builtins = _initBuiltins(this.device);
            this._forward = new ForwardRenderer(this.device, builtins);
            this._handle = new ModelBatcher(this.device, this.scene);
            this._flow.init(this._handle, this._forward);
        }
        config.addStage('shadowcast');
        config.addStage('opaque');
        config.addStage('transparent');
    },

 

render (ecScene, dt) {
        this.device.resetDrawCalls();
        if (ecScene) {
            // walk entity component scene to generate models
            this._flow.render(ecScene, dt);
            this.drawCalls = this.device.getDrawCalls();
        }
    },
RenderFlow.render = function (scene, dt) {
    _batcher.reset();
    _batcher.walking = true;

    RenderFlow.visitRootNode(scene);

    _batcher.terminate();
    _batcher.walking = false;

    _forward.render(_batcher._renderScene, dt);
};

  

 






Guess you like

Origin www.cnblogs.com/kundij/p/12712502.html