OpenGL (i)-COCOS2D-X rendering structure in COCOS2DX 3.x

Source: Internet
Author: User
Tags flush

Starting from this article, will analyze Cocos2d-x 3.0 source code, the first part is from Cocos2d-x learning OpenGL, that is, analysis Cocos2d-x 3.0 of the rendering code, this chapter first introduces COCOS2D-X 3.0 rendering structure, using 3.0 official version.

Voiddisplaylinkdirector::mainloop ()
{
    if (_purgedirectorinnextloop)
{
    ///Only one case will be called here, That is, the Director class calls the End Function
        _purgedirectorinnextloop = false;
        Clear Director Class
        Purgedirector ();
    }
    ElseIf (! _invalid)
    {
        //Draw
        Drawscene ();
        Clear Memory
        poolmanager::getinstance ()->getcurrentpool ()->clear ();
    }
}



The starting point of the analysis is the Mainloop function, which is the loop that will be called in the main thread, where the Drawscene function is drawn. Then take a closer look at the Drawscene function.

Voiddirector::d rawscene () {//Calculate interval time calculatedeltatime ();
    If the interval is too small it will be ignored if (_deltatime < Flt_epsilon) {return;
    }//null function, which may later have an effect if (_openglview) {_openglview->pollinputevents ();
        }//Non-paused state if (! _paused) {_scheduler->update (_deltatime);
    _eventdispatcher->dispatchevent (_eventafterupdate); } glclear (Gl_color_buffer_bit |
 
    Gl_depth_buffer_bit);
    Switch the next scene, must be placed in the logic after the drawing, otherwise the bug if (_nextscene) {setnextscene ();
    } Kmglpushmatrix ();
    Create a unit matrix KMMAT4 identity;
 
    Kmmat4identity (&identity);
        Draw scene if (_runningscene) {_runningscene->visit (_renderer, identity, false);
    _eventdispatcher->dispatchevent (_eventaftervisit); }//Draw observation nodes, if you need to set up observation nodes in the scene, please use the camera's Setnotificationnode function if (_notificationnode) {_NOTIFICATIONNODE-&G
    T;visit (_renderer, identity, false); }//Draw the status if in the lower left corner of the screen (_diSplaystats) {showstats ();
    }//Render _renderer->render ();
 
    _eventdispatcher->dispatchevent after rendering (_eventafterdraw);
 
    Kmglpopmatrix ();
 
    _totalframes++;
    if (_openglview) {_openglview->swapbuffers ();
    }//Calculate Draw time if (_displaystats) {Calculatempf (); }
}


Where and drawing related is the call of visit and render, where the visit function calls the node's draw function, In versions prior to 3.0, the draw function would call the drawing code directly, and the 3.0 version would put the draw command into renderer in the draw function, and then renderer the function to do the actual drawing, first of all to see the draw function of the sprite.

Voidsprite::d Raw (Renderer *renderer, ConstkmMat4 &transform, booltransformupdated)
{
    //check if bounds are exceeded, auto crop
    _insidebounds = transformupdated? renderer->checkvisibility (Transform, _contentsize): _insidebounds;
 
    if (_insidebounds)
    {
        //Initialize
        _quadcommand.init (_globalzorder, _texture->getname (), _shaderprogram, _ Blendfunc, &_quad, 1, transform);
        Renderer->addcommand (&_quadcommand);
Physics engine related draw boundary
#if cc_sprite_debug_draw
        _customdebugdrawcommand.init (_globalzorder);
        Custom Function
        _customdebugdrawcommand.func = cc_callback_0 (Sprite::d rawdebugdata, this);
        Renderer->addcommand (&_customdebugdrawcommand);
#endif
    }
}


In this case, two different drawing commands are used Quadcommand initialization can be added to the drawing command, Customdebugdrawcommand passed in a callback function, the specific command type will be described later. The Custom Customdebugdrawcommand command only passes in the global z coordinate when initializing, because its drawing functions are all in the incoming callback function, _quadcommand need to pass in the global z coordinate, map name, shader, mix, Sit the punctuation set, sit the number of punctuation sets, transform.

Voidrenderer::render ()
{
    _isrendering = true;
     
    if (_glviewassigned)
    {
        //clear
        _drawnbatches = _drawnvertices = 0;
 
        Sort for
        (auto &renderqueue: _rendergroups)
        {
            renderqueue.sort ();
        }
        Draw
        Visitrenderqueue (_rendergroups[0]);
        Flush ();
    }
    Clean ();
    _isrendering = false;
}


The render function in the render class is actually drawn, sorted first, then drawn, and drawn from the first group in the list. You can see five different types of drawing command types in the Visitrenderqueue function, corresponding to five classes, each of which inherits from Rendercommand.

Quad_command: Quadcommand Class Drawing Wizard and so on. All commands to draw pictures are called here, the code that handles this type of command is the OpenGL code that paints the map, and the next article details this part of the code.

Custom_command: Customcommand class custom drawing, its own definition of the drawing function, in the invocation of the drawing can only call the callback function has been passed in, the clipping node, drawing the graph node all use this drawing, the drawing function is defined in its own class.

This type of drawing command does not invoke any of the OpenGL code at the time of processing the command, but instead invokes the drawing function that you have written and set to Func, which describes all the custom drawing in the engine and implements a custom drawing on its own.


Batch_command: Batchcommand class batch drawing, batch Sprite and particle
In fact, it is similar to custom drawing, and no more OpenGL function appears in the Render function, it calls a fixed function, this function will be described in the next article.

Group_command: Groupcommand class Drawing Group, when a node consists of more than two drawing commands, store this drawing command in an element in another _rendergroups and store the pointer of this element as a node in _ Rendergroups[0].

The whole Group_command principle needs to start from the AddCommand.

Voidrenderer::addcommand (rendercommand* command)
{
    //Gets the index of the top of the stack
    intrenderqueue =_commandgroupstack.top ( );
    Call the real addcommand
    addcommand (command, renderqueue);
}
 
Voidrenderer::addcommand (rendercommand* command, Intrenderqueue)
{
    Ccassert (!_isrendering, "Cannot add Command while rendering ");
    Ccassert (Renderqueue >=0, "Invalid render queue");
    Ccassert (Command->gettype ()! = Rendercommand::type::unknown_command, "Invalid command Type");
    Add commands to the array
    _rendergroups[renderqueue].push_back (command);
}


AddCommand has "true and false" two, almost all add rendering command place, call is the first "false".

AddCommand, it's actually not really adding the command to the _rendergroups, it's getting an index that needs to add the command to the _rendergroups location, which is obtained from _commandgroupstack, _ Commandgroupstack is a stack, when we create a group_command, we need to call the Pushgroup function, it is the current command at the _rendergroups index position to the top of the stack, when AddCommand, call the top , get this position:

_groupcommand.init (_globalzorder);
Renderer->addcommand (&_groupcommand);
Renderer->pushgroup (_groupcommand.getrenderqueueid ());


Group_command generally used to draw the nodes have more than one drawing command, put these commands together, do not need to schedule the order between them, they as a whole is called, so be sure to remember that the stack is push,pop corresponding, all the drawing commands about this node are added after the completion , call the pop and eject the value from the top of the stack, or the subsequent command will be added here.

Next you can explain why the invocation starts with just calling Visitrenderqueue (_rendergroups[0]);

They will be called in the processing Group_command:

ElseIf (Rendercommand::type::group_command = = CommandType) {
            flush ();
            Intrenderqueueid = ((groupcommand*) command)->getrenderqueueid ();
            Visitrenderqueue (_rendergroups[renderqueueid]);
}


If there are errors, please indicate

Next section on the OpenGL code for texturing and batching

Source URL: http://blog.csdn.net/bill_man/article/details/35839499

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.