Making the pipeline simpler

Started by
4 comments, last by L. Spiro 10 years, 5 months ago

Hey guys. wink.png

So I've been having some serious considerations about the design of my engine, making it simpler and more flexible (Well, that's the dream, right?). So far so good, but, I'd like to share a thought (or a consideration) about the render ques (Just a list of objects needed to be rendered). So I've thought that I would have a class called: RenderModule, which can be instanced by the user, or by the engine itself, consider the following example:


class RenderModule
{
....
}

class Surface
{
    RenderModule mRenderModule;
    void Create()... // Initialises and creates the render module and the e.g. vertices/indices
    RenderModule* GetRenderModule()...
}

int main()
{
    Surface s;
    s.Create(..);
    
    // Now when it's added, the engine will render what's inside of this this render module
    pEngine->AddRenderModule(s.GetRenderModule()); // or some other names...
}

Nothing fancy, trying to keep things simple. Now, each model (or what it would be) would require different sets of data, such as time. So could I go ahead and make a structure called, e.g. DataPackage which contains pointers to all the data that you could ever possibly imagine, and then share a pointer to this Package to all models/rendermodules/etc... Which wouldn't be any problem in terms of performance, I hope.

Is this a terrible way of approaching the issue? Or is it actually ok?

What do you do, how do you keep the simplicity and flexibility?

Thanks, as usual. smile.png

-MIGI0027

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

Advertisement

A render queue (I assume this is what you meant) is not just a list of objects that need to be rendered. It is a list of object parts that have survived the culling phase and are to be sorted (the job of the render queue itself).

I suggest you stick to what is most logical in terms of component interactions and avoid terms that are too abstract in either name or functionality.

For example, what is a “render module”? What should it contain or do? It is very abstract, and it sounds as though it is going to lead to tight coupling between certain modules that do not need to be coupled. For example, it seems to be heading in the direction where the graphics module knows what a model is when it should be entirely the other way around.

The same holds for “DataPackage”. What is it? What does it contain or do?

What you describe it as being is a monolithic container of all kinds of data for all kinds of objects, which again is just inviting a tightly coupled design and unnecessary dependencies.

You are thinking more from a top-down approach.

Why not try a bottom-up approach?

A foundation layer provides typedefs and things you need throughout the engine. Optimized string compares etc., if you want. A timer class. A random number generator. Things you know you will need and depend on nothing else.

Then build a graphics layer on top which at first is just a wrapper for graphics functionality. Wrappers for state commands, vertex buffers, textures, etc.

Maybe it will later do more (such as render queues), but don’t confuse yourself by getting ahead of yourself.

Next up (and remember, each “step up” means the upper layers know about the lower ones but not the other way around) you have a model module which knows what graphics commands and vertex buffers are. The graphics module on the other hand does not know what a model is. At the same level you would have terrain.

This illustrates perfectly the point that the way in which a model renders itself and how GeoClipmap terrain renders itself are totally different, and far too monolithic to be held and managed by one module (the graphics module in your case).

Giving objects the ability to render themselves using a graphics module as a simple tool for doing so ensures you can add any kind of object, from models and imposters to water and GeoMipmap/GeoClipmap terrain. Each type of object can be self-contained within its own module without the need to create a mega-structure such as DataPackage to handle all possible sets of data.

Above that, the primary game-engine module knows about all of these things and inside it there exists a “scene” or “3DSceneManager” and “2DSceneManager”, as well as instances of models and things that can be scattered around the world.

The manager of the scene knows how to partition objects for efficient culling and collision detection, and it knows how to do rendering passes over the objects, or rather orchestrate the overall rendering pipeline while still letting each object handle its own rendering.

The scene manager culls objects, puts them into multiple render queues, sorts opaque and alpha render queues separately, sorts the render queues for shadow-casting lights separately, etc., and basically pulls all the things that need to be to pulled to make everything render in a happy tree friends way.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


Is this a terrible way of approaching the issue? Or is it actually ok?
Seconding LSpiro's notes, given the 10,000 ft abstraction here I have no idea what you're really doing and thus cannot really tell.

Personally, I haven't embraced the "render queue" design. My renderer is pretty high-level and still evolving so I couldn't figure out a decent design for the queue information itself. Since I am focusing on something else, I left this out. Maybe you should do the same?

Previously "Krohm"

Thank you both for your inputs and thoughts.

Spiro:

Actually my current design has something (I hope) to do with what you mentioned, an example:

Material ---------\

Buffers ---------- Mesh / Terrain / Volume ---- System

Minor things __/

So I have some independent classes such as Material, Buffer (etc...), which are used by several other classes such as Meshes, Terrains and Volumes, which are all used by the System class. Now I'm not entirely sure whether my system class is well organised or just stupid in design, here's what it does (In itself):

  • Creates DX (11)
  • Manages scene
    Containers of pointers to meshes/terrains/volumes/etc...
  • Basically uses wraps it all up to something usable.

Should I split the system class up into the low level (deferred, dx11, etc...) and a high level component which utilizes the low level class? Or not?

The previous thoughts that I've shared with you was just an idea, that I'd like to discuss before trying to implement it, as it might be stupid, as it probably is.

Krohm:

I might have gotten the definition of render ques wrong, sorry about that confusion. My version is basically a simple Group (a class inheriting vectors with additional functionalists) containing pointers to meshes/terrains/volumes/etc... needed to be rendered, maybe this clears it up. smile.png

Thank you.

-MIGI0027

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

Im doing something similar:

In my "engine" I have Meshes, Materials, ect.

Later on I have a Scene with nodes each node is containing Mesh/Ligth/... with material(almost anytime). Also there are some attrubutes that are somethimes needed like render priority, flags like draw always... ect.

A Scene know the hierarchy of the nodes.

Later I batch the scene(something like *someBatcherInstance.Batch(pScene, ...)).
The scene batcher produces render bins. Render bin is something like yours "render ques". A batcher can produce more than one render bin.

Each render bin contain *visible objects that share *similar(by some rule) materials sorted by the render priority/meshes/ect.

Later I pass the ordered data from the render bins to the *BinRenderer who knows how to reander the contents of the bin.

The hierarchy is something like this :

Meshes
Renderer - Buffers/States/..... - - Nodes - Scene - RenderBIn - Batcher
Materials

* means "by some user defined rules"

so I couldn't figure out a decent design for the queue information itself. Since I am focusing on something else, I left this out. Maybe you should do the same?

You are in luck. Since the topic of render queues has been appearing so frequently on these boards lately it will be the subject of my next post on my site.

For the rest, I am not ignoring the follow-up question but I have to go soon and will edit it into this reply when I get back.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement