Ogre rendering process

Source: Internet
Author: User

I wanted to write some articles about ogre a long time ago and I never had a chance.
To understand a rendering engine, I think the most important thing is to first grasp its main architecture, its main line, and the rendering process. Otherwise, a rendering engine would have tens of thousands of lines, even hundreds of thousands of lines of code can surprise you by simply opening solution, and ogre also has tens of thousands of lines of code. At the beginning, I couldn't start looking at it, I feel that there are too many codes and I don't know where to start. This class looks at it and the class looks at it. Because I don't have a clear understanding of the entire engine, I'm not very impressed with it. So, finally, we decided to first find out its main line and understand its rendering process so that we could organically connect all parts.

 

This short article also introduces the main rendering process of ogre, and may not introduce the specific implementation details too much for some classes. All the code I use is taken from the latest CVS version of ogre.

You 'd better have a certain understanding of ogre and at least understand its example. Otherwise, it may be difficult to understand some things. Good knowledge of d3d and OpenGL.

If you have read the examples in the d3d SDK, you must know that a simple 3D program will involve at least the following parts:

The first is the data source, including vertex data and texture data. The data can be read from the file or generated when the program is running.

Next, we will create a vertex buffer to store the vertex and create a texture object to represent texture. We will set the coordinates of the vertex in the world coordinate system, set the camera position and viewpoint, set the position and size of the viewport, and then start calling the rendering operation in the rendering loop. After switching between the front buffer and the back buffer, we can see 3D images on the screen. The pseudocode is as follows:

Setupvertexbuffer

Setworldtransform

Setcamera

Setprojectiontransform

Setviewport

Beginframe

Settexture

Drawobject

EndFrame

The following are the main steps for rendering an object. In my opinion, this is the main line of 3D programs. Likewise, no matter how complicated your rendering engine is, you must implement these steps, other effects, such as shadows and light, are attached to this main line. Therefore, if you can see this main line clearly on the rendering engine you are studying, it may be helpful for you to study it in depth. Next, let's find this main line in ogre.

The rendering cycle of ogre is originated from root: renderoneframe. This function is not explicitly called in Example of ogre, because example calls root: startrendering, startrendering calls renderoneframe. If you use ogre to publish a game or an editor, you may need to call renderoneframe in the main message loop. As the name suggests, this function updates the entire ogre frame, including animation, rendering status change, rendering API call, etc. In this function, it includes almost all of the above-mentioned pseudo-code, so it is the focus of this article.

Go to renderoneframe and you can see the two fire functions at the beginning and end. These functions often appear in ogre, generally fire... Start and fire... End appears together. In these functions, some user-defined operations may be processed. For example, _ fireframestarted will process the framelistener. These fire functions can be ignored temporarily, continue to check _ updateallrendertargets. In this function, the current Renderer is assigned to update all created render targets. The render target is the rendering destination. There are generally two types, one is render texture, the other is render buffer, and then enters rendersystem: _ updateallrendertargets. You can see that in the Render system, the created render target is saved using rendertargetprioritymap, in order to update the render target in a certain order, because in the rendering object to the render Buffer The previously rendered render texture is generally used. Therefore, the render target in the render texture form must be updated before the render buffer.

Go to the update of the render target. We can see that it still transmits the update operation and calls the update of all viewports mounted on the render target.

Viewport actually defines a part of the area on the render target to be updated. Therefore, a render target can be mounted with multiple viewports to achieve the effect of multiple people on the wartime split screen or painting in the picture, you can regard viewport in ogre as a combination of camera and rendertarget, and render the scene content displayed by camera in viewport to the render target area defined by viewport.

Another important information of viewport is zorder. We can see that viewportlist in rendertarget has a comparison function. Therefore, in rendertarget: update, the smaller the zorder, the more it is rendered first, if the regions defined by the two viewports overlap with each other and zorder is different, the final result is that the content of the small zorder viewport will be overwritten by the content of the large zorder viewport.

Continue to viewport: update. As mentioned above, it calls the camera It references to render the entire scenario. In camera: _ renderscene, it calls scenemanager :: _ renderscene (Camera * camera, viewport * VP, bool includeoverlays ). Scenemanager: _ renderscene is the specific rendering process. You can also see from the function name and parameters that the function is used to take advantage of the specified camera and viewport, to render the content in the scenario to a region of the render target specified by viewport. According to camera, we can determine the view matrix and projection matrix. We can also remove the cone to render only visible objects. Note: Here we only look at the standard scenemanager method, not the method of the bspscenemanager derived class, and we will leave the content irrelevant to the main line, such as the setup of shadow, play the skeleton animation and pass the shader parameter, because we only focus on the rendering of the main process.

In scenemanager: _ renderscene, the first important function to be viewed is _ updatescenegraph. Ogre organizes the scenario through the node tree, one node, you can think of it as a combination of some transformations in the space, such as location, scaling, rotation, etc. These transformations will affect the information of specific objects attached to these nodes, that is, the node stores the world Transform. Positioning a specific object, such as a person, in a space is done by operating nodes. At the same time, the node also saves an aabb of the world coordinates, which can accommodate the size of all the objects it is attached to, and is mainly used for Cone Cutting, if the current camera does not see the AABB of a node, it means that the camera does not see all the objects attached to the node, so you can ignore this node during rendering.

_ Updatescenegraph's internal processing is cumbersome. We only need to know that after _ updatescenegraph, every node in the scene node tree has been updated, including location, scaling, and orientation, there is also a node box.

Continue to return to scenemanager: _ renderscene. Next, you should see setviewport. It will call the setviewport operation of the specific Renderer and set the render target attached to the viewport to be the current rendering target, the area in viewport is the area in the target to be rendered.

Next we will encounter an important concept in the Ogre rendering process, render queue. This is actually a lot of content, or you may have the opportunity to propose it separately in the future. You can simply think of it as a container, and the element in it is renderable, each renderable can be viewed as an object rendered by calling the drawprimitive function each time. It can be a model or a part of the model. In renderqueue, It groups the renderable by material and sorts the renderable.

Each time scenemanager ::_ renderscene is called, scenemanager: preparerenderqueue is called to clear the renderqueue, and then scenemanager :: __findvisibleobjects: add all the objects visible to the renderqueue.

Scenemanager ::__ findvisibleobjects is a recursive processing process starting from the root node of the scenario, first, check whether the camera can see the surrounding box of this node (the surrounding box has been calculated when _ updatescenegraph is used). If not, then this node and Its subnodes will not be taken care. If you can see it, check all the movableobjects attached to this node. If the detected movableobject is visible, the _ updaterenderqueue method of it will be called, in this method, you can send the renderable related to the movableobject to the renderqueue.

Here we will talk about movableobject. movableobject is mainly used to represent discrete objects in the scene, such as entity, which, as the name suggests, can be moved, however, the ability to "move" is implemented through scenenode. Therefore, to display movableobject, you must first attach it to a scene node and locate it through the scene node. You can control certain attributes of movableobject, such as whether a movableobject is to be displayed or hidden. All attributes can be implemented through the movableobject: setvisible method.

After checking the movableobject on the node, the _ findvisibleobjects method of all child nodes will be called and Recursion will continue. In this way, all the renderable to be rendered in the scenario can be added to the renderqueue.

So far, we have the information of the objects to be rendered, and the next step is to render these objects. You will find calls similar to d3d or OpenGL code:

Mdestrendersystem-> clearframebuffer

Mdestrendersystem-> _ beginframe

Mdestrendersystem-> _ setprojectionmatrix

Mdestrendersystem-> _ setviewmatrix

_ Rendervisibleobjects ();

Mdestrendersystem-> _ EndFrame ();

The functions of these APIs are similar to those of similar calls in d3d. Here we will talk about _ rendervisibleobjects (). In this function, each renderqueue's renderable will be rendered, the visitor mode is used to traverse and operate each renderable. Finally, the vertex, index, world matrix, and other information stored by each renderable are retrieved in scenemanager: rendersingleobject for rendering. This also involves operations such as finding the light source closest to the renderable, which is complicated.

Here, the scenemanager: _ renderscene process is basically completed. That is to say, the rendering process in the Ogre frame is almost over. You should also find that, this process is basically the same as the process for writing a simple program with d3d. Based on this process, let's look at the specific implementation, such as how to set the texture, it is much easier to call the familiar d3d or OpenGL APIs to render objects.

The introduction to the ogre rendering process is also over, and many details are not involved. You will have the opportunity to write it later.

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.