cocos2d3.2 Rendering Learning Article 1

Source: Internet
Author: User
Tags addchild

Long time no blog, but also this year are mixed in the project, there is not a moment to learn other things, just recently idle down, began to study cocos2d. Recently learned the next its rendering mode, and share with you, in fact, the specific process of online tutorials a lot, I just use a few examples to analyze.

Example one:

<span style= "FONT-SIZE:18PX;" >for (int i=0;i<100;i++) {sprite* sprite1 = sprite::create ("Closenormal.png"); Sprite1->setposition (origin.x +sprite1->getcontentsize (). WIDTH/2 * (i%10), Origin.y+sprite1->getcontentsize (). height/2* (i%10));this-> AddChild (sprite1);} </span>

Results:


The number of renders is only 1 (and then it should be two, perhaps not the rendering of those several tags in, but this is not the focus of today), we have drawn 100 sprites, we have only called a rendering command. This is an optimization feature for versions after 3.0 .

starting with cocos2d-x3.0, Cocos2d-x introduced a new rendering process, unlike the 2.x version, which directly invokes OpenGL code in the draw function in each node to render graphically, but is encapsulated by various rendercommand and then added to a COM Mandqueue queue inside, and now the function of the draw function is to set the corresponding Rendercommand parameter in this function, and then Add this rendercommand to Commandqueue. Finally, the renderer function is called at the end of each frame to render, and the Rendercommand is sorted by ID in the renderer function before rendering. (Enjoy copy!!! )。 Probably is to visit each node first, the node determines how to render, plus what commands to decide, put in the render queue, when the end of all the nodes, and then start a real rendering-the execution of the various nodes to join the command.

The rendering command Rendercommand is divided into the following types: Trianglescommand,quadcommand,meshcommand,groupcommand,batchcommand,primitivecommand. What is really drawn to the elves is just quadcommand this rendering command.

When the command that is accessed is quadcommand, how is it handled? Look at the source bar.

Draw if we have batched other commands which is not quad command   flush off all drawing commands before        flush3d ();        Flushtriangles ();                Process Quad command        auto cmd = static_cast<quadcommand*> (command);                Draw batched Quads If necessary is drawn immediately if the number of vertices exceeds the number of vertices limited by VBO.        if (cmd->isskipbatching () | | | (_numberquads + cmd->getquadcount ()) * 4 > Vbo_size)        {            Ccassert (cmd->getquadcount () >= 0 && Cmd->getquadcount () * 4 < Vbo_size, "VBO for vertex isn't big enough, please break the data down or use customized Render command ");            Draw batched Quads If VBO is full            drawbatchedquads ();        }                Batch Quads        _batchquadcommands.push_back (cmd);                Fillquads (cmd);                if (cmd->isskipbatching ())        {            drawbatchedquads ();//actually performs the manipulation of the drawing sprite        }

So let's see how drawbatchedquads is performing.

<span style= "FONT-SIZE:14PX;" >void Renderer::d rawbatchedquads () {//..... Omit part of the code ... Some of the OpenGL operations that are omitted here are probably the binding of some vertex data and vertex index data, not the Vao way//start drawing verties in batch for (const auto& cmd: _BATC        Hquadcommands) {Auto Newmaterialid = Cmd->getmaterialid ();            if (_lastmaterialid! = Newmaterialid | | newmaterialid = = material_id_do_not_batch) {//draw quads if (Indextodraw > 0) {gldrawelements (Gl_triangles, (Glsizei) Indextodraw, Gl_unsigned_sho                RT, (glvoid*) (startindex*sizeof (_indices[0)));                _drawnbatches++;                                _drawnvertices + = Indextodraw;                StartIndex + = Indextodraw;            Indextodraw = 0;            }//use new material cmd->usematerial ();        _lastmaterialid = Newmaterialid;    } Indextodraw + = Cmd->getquadcount () * 6; }    //.......... Omit part of the code ...} </span>
Here we are very happy to see _lastmaterialid and newmaterialid; this is just to see if the "render texture" of multiple commands is the same, then put them together to render, call only once gldrawelements command,

So is the "render texture" of the command the same as it depends on what? Let's see how Quadcommand generates Materialid.

int glprogram = (int) _glprogramstate->getglprogram ()->getprogram (); int intarray[4] = {glprogram, (int) _ Textureid, (int) _blendtype.src, (int) _blendtype.dst};_materialid = XXH32 ((const void*) intarray, sizeof (Intarray), 0);
It turns out to be a hash of the shader, texture ID, mixed mode, so the materialid of the two commands should be the same, and they must be guaranteed to be the same.


So it's easy to understand why the example is 1 now.

Example Two
for (int i=0;i<100;i++) {<span style= "white-space:pre" ></span>sprite* sprite1 = Sprite::create (" Closenormal.png "), <span style=" White-space:pre "></span>sprite* sprite2 = Sprite::create (" Closeselected.png "); <span style=" White-space:pre "></span>sprite1->setposition (origin.x+sprite1- >getcontentsize (). WIDTH/2 * (i%10), Origin.y+sprite1->getcontentsize (). height/2* (i%10)); <span style= " White-space:pre "></span>spite2->setposition (Origin.x+sprite2->getcontentsize (). WIDTH/2 * (I%10), Origin.y+visiblesize.height-sprite2->getcontentsize (). height/2* (i%10)) <span style= "White-space:pre" > </span>this->addchild (sprite1); <span style= "White-space:pre" ></span>this->addchild ( SPRITE2);}

Results:

What???? Feel no More love ...

How did it become 200, not 2? The previous conclusion is that the "render texture" of successive commands is the same, then it is put together for rendering, so how do command queue commands be added at once? Now to start with the scene rendering, the scene's render is always called in the program loop, and all the nodes ' access starts here.

void Scene::render (renderer* Renderer) {Auto Director = Director::getinstance ();    camera* Defaultcamera = nullptr;    Const auto& transform = Getnodetoparenttransform ();        if (_cameraorderdirty) {Stable_sort (_cameras.begin (), _cameras.end (), camera_cmp);    _cameraorderdirty = false;                } for (const auto& Camera: _cameras) {if (!camera->isvisible ()) continue;        Camera::_visitingcamera = camera; if (camera::_visitingcamera->getcameraflag () = = Cameraflag::D efault) {Defaultcamera = Camera::_visit        Ingcamera;        } director->pushmatrix (Matrix_stack_type::matrix_stack_projection); Director->loadmatrix (Matrix_stack_type::matrix_stack_projection, camera::_visitingcamera->                Getviewprojectionmatrix ());        Visit the scene visit (renderer, transform, 0);                Renderer->render (); Director->popmatrix (Matrix_stack_type::matriX_stack_projection); } Camera::_visitingcamera = nullptr;}

Visit (renderer, transform, 0); Is to access all nodes and their child nodes, and join the Rendercommand. Renderer->render () is to execute these rendercommand queues. There is a sentence in visit:

Sortallchildren ()
All nodes are sorted before accessing the node and child nodes, and the rules for sorting are:

BOOL Nodecomparisonless (node* N1, node* n2) {    return (N1->getlocalzorder () < N2->getlocalzorder () | |           (N1->getlocalzorder () = = N2->getlocalzorder () && n1->getorderofarrival () < n2-> Getorderofarrival ())           );}
The depth (priority) and time of arrival in the node.

Knowing this can explain the example two. In the next two times with the same picture to create the wizard inserted another picture to create the wizard, because we do not specify Localzorder, so all the elves are the default Localzorder, and the arrival time is split open, so you can not use the optimized scheme to draw the wizard. We can change the code a little bit to make the number of draws 2 immediately: (The Localzorder of the sprite that specifies the same picture).

for (int i=0;i<100;i++) {sprite* sprite1 = sprite::create ("Closenormal.png"); sprite* Sprite2 = sprite::create ("Closeselected.png"); Sprite1->setposition (origin.x+sprite1->getcontentsize (). WIDTH/2 * (i%10), Origin.y+sprite1->getcontentsize (). height/2* (i%10)); Sprite2->setposition (origin.x+ Sprite2->getcontentsize (). WIDTH/2 * (i%10), Origin.y+visiblesize.height-sprite2->getcontentsize (). height/2* (i%10)); This->addchild (sprite1,0); This->addchild (sprite2,1);}

Example 3:
Spriteframecache::getinstance ()->addspriteframeswithfile ("Close.plist"); for (int i=0;i<100;i++) {<span Style= "White-space:pre" ></span>sprite* sprite1 = Sprite::createwithspriteframename ("CloseNormal.png"); <span style= "White-space:pre" ></span>sprite* sprite2 = Sprite::createwithspriteframename (" Closeselected.png "); <span style=" White-space:pre "></span>sprite1->setposition (origin.x+sprite1- >getcontentsize (). WIDTH/2 * (i%10), Origin.y+sprite1->getcontentsize (). height/2* (i%10)); <span style= " White-space:pre "></span>sprite2->setposition (Origin.x+sprite2->getcontentsize (). WIDTH/2 * (I%10), Origin.y+visiblesize.height-sprite2->getcontentsize (). height/2* (i%10)) <span style= "White-space:pre" > </span>this->addchild (SPRITE2); <span style= "White-space:pre" ></span>this->addchild ( SPRITE1); <span style= "White-space:pre" ></SPAN>}
Results:the number of renders becomes 1. This is the way to create sprites using sprite frames. People are already familiar with it. I will closenormal.png and closeselected.png and together to generate a close.plist file and close.png, this estimate everyone will, plist The document describes the position and size of the previous two images in this large image. Sprites created using sprite frames use this large image as a texture, where the sprites of different pictures are just using the same texture location, so there is no need for texture switching, only one render, all the rendering commands are put together .
OVER !!!





Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

cocos2d3.2 Rendering Learning Article 1

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.