I was quite gratified to read this post on Wolfgang Engel’s blog, in which he refers to some other posts discussing the recommended categorisation & nomenclature for the various stages / structures of scene rendering. If you read it and you’re an OGRE user, you’ll find them all rather familiar concepts, because OGRE has been based around these principles for years 🙂
“SpatialGraph: used for finding out what is visible and should be drawn. Should make culling fast”
That’s our SceneManager and it’s subclasses. One of the core tenets of my design for OGRE from day 1 was that the mechanism for performing fast culling should be customisable based on the scene type independent of the scene content, and therefore be able to be divorced from, but derived from, the primary scene structure (the SceneTree, see below). While other engines either tended to hardcode their culling strategy, or retrofit it into the ‘main’ scene graph as custom node types (which tends to encourage the ‘parallel inheritance hierarchy’ anti-pattern, because you mostly specialise nodes for other reasons too, and also makes macro-level decisions difficult), specialised SceneManagers build separate and derived culling structures which are entirely theirs to own.
“SceneTree: used for hierarchical animations, e.g. skeletal animation or a sword held in a character’s hand”
That’s easy – that’s our Node and all it’s subclasses like Bone and SceneNode. It’s rare for an engine not to have this concept, but too many engines make these nodes do too much IMO – like holding material state, being derived for custom culling routines, etc. I’ve always liked the idea of keeping the focus of a class tight (the principle of cohesion), it tends to work better long-term.
“RenderQueue: is filled by the SpatialGraph. Renders visible stuff fast. It sorts sub arrays per key, each key holding data such as depth, shaderID etc.”
Yep, we have exactly this structure and unsurprisingly it’s called RenderQueue 🙂 We have the concept of queue groups for user-customisable ‘fire breaks’ between rendered objects, and the ability to sort by pass, by distance, or via a custom RenderQueueInvocationSequence.
It’s nice to read posts like this – makes me think we’ve been doing things the right way 🙂