Cocos2D-X source code learning from cocos2D-X OpenGL (1) ---- cocos2D-X rendering Structure

Source: Internet
Author: User

Personal Original, welcome to reprint, reprint please indicate the original address http://blog.csdn.net/bill_man

Starting from this article, will analyze cocos2D-X 3.0 source code, the first part is to learn OpenGL from the cocos2D-X, that is, to analyze the rendering code of cocos2D-X 3.0, This article first introduces the rendering structure of cocos2D-X 3.0, the official version 3.0 is used.

Void DisplayLinkDirector: mainLoop () {if (_ purgeDirectorInNextLoop) {// only one situation will be called here, that is, the director class calls the end function _ purgeDirectorInNextLoop = false; // clear the director class purgeDirector ();} else if (! _ Invalid) {// draw drawScene (); // clear the memory PoolManager: getInstance ()-> getCurrentPool ()-> clear ();}}

The starting point of the analysis is the mainLoop function, which is a loop that will be called in the main thread, where the drawScene function is drawn. Let's look at the drawScene function.

Void Director: drawScene () {// calculation interval calculateDeltaTime (); // if the interval is too small, it will be ignored if (_ deltaTime <FLT_EPSILON) {return ;} // empty function, which may be used later. if (_ openGLView) {_ openGLView-> pollInputEvents () ;}// non-paused if (! _ Paused) {_ schedcher-> update (_ deltaTime); _ eventDispatcher-> dispatchEvent (_ eventAfterUpdate);} glClear (GL_COLOR_BUFFER_BIT | second); // switch to the next scene, it must be placed before the logic is drawn. Otherwise, the bug if (_ nextScene) {setNextScene () ;}kmglpushmatrix (); // create the unit matrix kmMat4 identity; kmMat4Identity (& identity ); // draw the scenario if (_ runningScene) {_ runningScene-> visit (_ renderer, identity, false); _ eventDispatcher-> dispatchEvent (_ eventAfterVisit );} // draw observation nodes. if you need to set up observation nodes in the scene, call the setNotificationNode function of the camera if (_ notificationNode) {_ icationicationnode-> visit (_ renderer, identity, false);} // draw the status if (_ displayStats) {showStats ();} // render _ renderer-> render (); // After rendering _ eventDispatcher-> dispatchEvent (_ eventAfterDraw); kmGLPopMatrix (); _ totalFrames ++; if (_ openGLView) {_ openGLView-> swapBuffers ();} // calculate the drawing time if (_ displayStats) {calculateMPF ();}}

Visit calls and render calls are related to the painting. The visit function calls the draw function of the node. In versions earlier than 3.0, the draw function directly calls the drawing code, version 3.0 stores the draw command in the draw function into renderer, and then the renderer function is used for real painting. First, let's look at the draw function of sprite.

Void Sprite: draw (Renderer * renderer, const kmMat4 & transform, bool transformUpdated) {// check whether the border is 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 ); // draw boundaries related to the physical engine # if CC_SPRITE_DEBUG_DRAW _ customDebugDrawCommand. init (_ globalZOrder); // UDF _ customDebugDrawCommand. func = CC_CALLBACK_0 (Sprite: drawDebugData, this); renderer-> addCommand (& _ customDebugDrawCommand); # endif }}

Two different draw commands are used here. After quadCommand is initialized, it can be added to the draw command. customDebugDrawCommand imports a callback function. The specific command types will be described later. The custom customDebugDrawCommand command only imports the global Z axis coordinates during initialization, because all its plotting functions are in the input callback function, and _ quadCommand requires the global Z axis coordinates, texture name, shader, hybrid, coordinate point set, number of coordinate points set, transformation.

Void Renderer: 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 used to draw a real graph. First, sort the graph and draw it from the first group in the list. In the visitRenderQueue function, you can see five different types of drawing command types, which correspond to five classes respectively. These five classes are inherited from the RenderCommand.

QUAD_COMMAND:QuadCommand class rendering genie.

All the commands used to draw images are called here. The code used to process this type of command is the openGL code used to draw textures. This part of the code will be detailed in the next article.

CUSTOM_COMMAND:Custom plotting of the CustomCommand class and custom plotting function. You only need to call the callback function that has been passed in when calling the plotting function. You can crop the nodes and draw the graphic nodes using this function, define the plotting function in your own class.

This type of drawing command does not call any openGL code when processing the command, but calls the drawing function you wrote and set to func, subsequent articles will introduce all custom la s in the engine and implement a custom la S.

BATCH_COMMAND:BatchCommand class batch rendering, batch processing Genie and particles

In fact, it is similar to user-defined rendering, and there will no longer be any openGL function in the render function, it calls a fixed function, this function will be introduced in the next article.

GROUP_COMMAND:GroupCommand class draw group. When a node contains more than two draw commands, store the draw command to the elements in another _ renderGroups, and store the pointer of this element as a node to _ renderGroups [0.

The principle of the entire GROUP_COMMAND should start with addCommand.

Void Renderer: addCommand (RenderCommand * command) {// obtain the index int renderQueue = _ commandGroupStack on the top of the stack. top (); // call the real addCommand (command, renderQueue);} void Renderer: addCommand (RenderCommand * command, int renderQueue) {CCASSERT (! _ IsRendering, "Cannot add command while rendering"); CCASSERT (renderQueue> = 0, "Invalid render queue"); CCASSERT (command-> getType ()! = RenderCommand: Type: UNKNOWN_COMMAND, "Invalid Command Type"); // Add the command to the array _ renderGroups [renderQueue]. push_back (Command );}

AddCommand has two values: true and false. Almost all the places where rendering commands are added call the first "false" addCommand, which is not actually added to _ renderGroups, it obtains the index that needs to add the command to the position of _ renderGroups. This index is obtained from _ commandGroupStack, and _ commandGroupStack is a stack. When we create a GROUP_COMMAND, you need to call the pushGroup function, which is to press the index position of the current command in _ renderGroups to the top of the stack. When addCommand is used, top is called to obtain the position.

_ GroupCommand. init (_ globalZOrder );

Renderer-> addCommand (& _ groupCommand );

Renderer-> pushGroup (_ groupCommand. getRenderQueueID ());

GROUP_COMMAND is generally used to draw more than one draw command on nodes. These commands are organized together without the need to schedule the order between them. They are called as a whole, so remember, the stack corresponds to push and pop. After all the drawing commands on the node are added, call pop to bring up the value from the top of the stack, otherwise, the subsequent commands will be added here.

Next, we can explain why we only need to call

VisitRenderQueue (_ renderGroups [0]); why is it only 0? What about others?

They will be called when processing GROUP_COMMAND

else if(RenderCommand::Type::GROUP_COMMAND == commandType) {            flush();            int renderQueueID = ((GroupCommand*) command)->getRenderQueueID();            visitRenderQueue(_renderGroups[renderQueueID]);}

In case of any errors, please note

Next, we will introduce the openGL code for textures and batch processing.



Related Article

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.