Contents

[hide]

Introduction

Most of the rendering system concepts from pre-TGEA 1.8 have been left intact. One system that has changed It shouldn't be a hard transition to use the changes that have been made. The purpose of GFX2 is to allow for more flexibility at runtime within the current structure.


Most of the rendering code has been moved from familiar classes/structs, such as SceneManager and RenderInst. The member variables and functionality have been split across multiple render managers, which you should find quite easy to pick up on.

RenderInst

RenderInst used to be a class that contained all the information needed to render an object. This included sorting information, geometry, textures, vertex and primitive buffers, and so on. When TGEA 1.7 was released, RenderInst became a struct, but still contained nearly all the same information.


TGEA 1.8 strips RenderInst down to a very simple structure. It now acts as a base structure for more task-specific render managers. The current version of RenderInst only contains information on sorting, translucency, and rendering type overrides.

ObjectRenderInst

ObjectRenderInst is a new structure derived from RenderInst, declared directly below the RenderInst structure. It contains variables and functionality used in rendering an object (RIT_OBJECT) instance type. The ObjectRenderInst basically just contains a pointer to to the object to call back into for its rendering function. It does not contain any information about meshes, materials, transforms, etc.


Along with the SceneState of the object, ObjectRenderInst contains a very important element: the Render Delegate.

MeshRenderInst

Derived from RenderInst, a MeshRenderInst object contains the critical information needed for rendering. It is declared directly below ObjectRenderInst. Within this structure, an object's geometry(mesh), lighting information, textures, transforms, and miscellaneous rendering states are kept as internal members.

Some of the most basic GFX classes are used in RenderMeshInt:

  • GFXVertexBufferHandleBase and GFXPrimitiveBufferHandle handle the vertex buffer and primitive buffer (respectively)
  • World and object to world transforms are handled by MatrixF pointers
  • LightInfo pointers retain information for primary and secondary lighting
  • GFXTextureObject pointers also aid in lighting, as well as texturing the object.

RenderBinManager

RenderBinManager is the first manager we are going to cover. This class manages and renders out a list of MainSortElem structures (mElementList). A MainSortElem is a simple struct that wraps a RenderInst object with a key. In essence, RenderBinManager manages and signals a main list of RenderInst objects.


RenderBinManager contains the variables and functions necessary for adding, processing, sorting, and clearing RenderInst objects. To get a closer look at RenderBinManager, open engine/source/renderInstance/renderBinManager.h and renderBinManager.cpp.


Most of the important management functionality is defined in the class, but you should notice a very important chunk of functionality missing: rendering code. RenderBinManager does have a rendering function:

virtual void render(SceneState *){};


But as you can see, we are not going to be directly using a RenderBinManager for rendering. It's important to know how the class's base functionality works, but we will get to the actual rendering code when we look at RenderBinManager's children.


This class lays the ground work, but the tangible rendering sub-managers derive from RenderBinManager: renderMeshMgr, renderObjectMgr, renderTranslucentMgr, and so on. These are detailed further down in the Sub-Managers section.

RenderPassManager

The RenderPassManager could be considered the "top manager" when it comes to GFX2's rendering system. We can actually refer to this class's instantiation: gRenderInstManager. We can do so, since there is only one instantiation of RenderPassManager:


At the bottom of engine/source/renderInstance/renderPassManager.h:

extern RenderPassManager* gRenderInstManager;


As you can see, gRenderInstManager is a global variable. This means we can use our one RenderPassManager anywhere we include the class's header. This necessary considering the responsibilities of this manager:

  • Declaring and organizing the various RIT : "R"ender "I"nstance "T"ypes
  • Allocating a render instance for MeshRenderInst, ObjectRenderInst, and so on.
  • Adding, sorting, and rendering a list of RenderInst's per bin
  • Memory allocation and deallocation for the RenderBinManagers
  • Adding, sorting, and managing the various RenderBinManagers. The importance of this task is best shown in code:


In engine/source/renderInstance/renderPassManager.cpp:

void RenderPassManager::_initBins()
{
   _uninitBins();

   addManager(new RenderObjectMgr(RIT_Sky, 0.1f, 0.1f));
   addManager(new RenderObjectMgr(RIT_Begin, 0.2f, 0.2f));
   addManager(new RenderMeshMgr(RIT_Interior, 0.3f, 0.3f));
   addManager(new RenderMeshDynamicLightingMgr(RIT_InteriorDynamicLighting, 0.4f, 0.4f));
   addManager(new RenderMeshMgr(RIT_Mesh, 0.5f, 0.5f));
   addManager(new RenderMeshDynamicLightingMgr(RIT_MeshDynamicLighting, 0.55f, 0.55f));
   addManager(new RenderObjectMgr(RIT_Object, 0.6f, 0.6f));
   addManager(new RenderObjectMgr(RIT_Shadow, 0.7f, 0.7f));
   addManager(new RenderObjectMgr(RIT_Decal, 0.8f, 0.8f));
   addManager(new RenderRefractMgr(0.9f, 0.9f));
   addManager(new RenderObjectMgr(RIT_Water, 1.0f, 1.0f));
   addManager(new RenderObjectMgr(RIT_Foliage, 1.1f, 1.1f));
   addManager(new RenderTranslucentMgr(1.2f, 0.01f));
   addManager(new RenderGlowMgr(1.3f, 1.3f));
}


Even if you are not yet a master of GFX2, the premise behind this chunk of code is simple. RenderPassManager has a function called _initBins. This is called as soon as our SceneGraph's rendering is initialized.


An internal list of RenderBinManagers is stored within RenderPassManager. We have managers for Sky, Interiors, Lighting, Mesh, Objects, Shadows, and so on. Those managers get stored in the internal bin list. Calling gRenderInstManager "the manager of managers" seems appropriate.


If you read the class from top to bottom, the layout of the code and accompanying comments will provide you with a few more details as how the RenderPassManager performs is duties and what other classes are involved.

Sub-Managers

As mentioned previously, the actual rendering managers are children of RenderBinManager. We are calling them sub-managers, since the RenderPassManager manages and maintains them. Each of these rendering sub-managers contains rendering code unique to its purpose, though multiple instantiations do occur to handle our various renderable Torque objects.


Let's go down a simplified list of these classes and their main purpose:

  • RenderObjectMgr - This class is used for rendering more than any of the other sub-managers. This manager is responsible for rendering common objects that do not have a standard mesh.
    • Sky
    • Shadows
    • Decals
    • terrain chunks
    • fxSunLight
    • waterblocks
    • foliage
    • shapebase.
  • RenderMeshMgr - This class is used for rendering mesh based objects such as interiors and TSMesh. Additionally, RenderMeshMgr has children. One such class, RenderMeshDynamicLightingMgr, is described next.
  • RenderMeshDynamicLightingMgr - As the name describes, this class manages the rendering dynamic lighting on a mesh. This is primarily used with the SG lighting kit additions to TGEA which provide dynamic lighting on meshes and interiors.
  • RenderRefractMgr - Stock TGEA uses only one RenderRefractMgr. The name of the manager describes it well. This manager takes in RenderInst elements and checks to see if they have a refraction custom material. If this check succeeds, the element is maintained by the manager and makes use of the refraction rendering code.
  • RenderTranslucentMgr - Stock TGEA uses only one RenderTranslucentMgr. This manager is a bit more complex than the previous ones described. A RenderInst element must meet a strict set of requirements to be managed by this class. If you look at RenderTranslucentMgr::addElement(...), you can see there are 3 main if statements checking for translucent properties and appropriate render instance type. Additionally, RenderTranslucentMgr must setup/modify the scene graph data and stateblocks before it can render its elements. The actual render function is quite clean, and you can gain more insight about the class by reading through it.
  • RenderGlowMgr - Just like the previous two managers, there is only one instance of RenderGlowMgr in stock TGEA 1.8. The name is pretty self-descriptive. This manager is responsible for accepting RenderInst elements that require rendering with a properly set up glow buffer.

Conclusion

The purpose of this doc was to provide you with a basic understanding of the rendering management system used by TGEA's GFX2 (introduced in version 1.8). There is still much to be explained in the way of rendering flow, extending the system, and specific examples.


We've covered the basic renderable object instances, base class render managers, specialized rendering manager classes, and touched on some new subjects such as the RenderDelegate. If you would like a more concrete example of GFX2's changes and how render management works, read through the RenderDelegate doc and Sky Comparison Guide. (TODO: links here).