I get a lot of questions about scene graphs and 3D development. Many people either aren’t sure what they are or have misconceptions about them. For this article I will explain the concept of scene graphs from the standpoint of OpenSceneGraph, an amazing open-source scene graph inspired by the granddaddy of the modern scene graph – SGI’s Performer. For purposes of this article I will use the terms OpenSceneGraph and scenegraph interchangeably in many places. It is beyond the scope of this article to explain all possible permutations of the scene graph concept.
Standard graphics objects and a spatial graph
At their heart, scene graphs are nothing more than a graph of nodes representing the spatial layout of a 3D scene while encapsulating primitive graphic characteristics in objects. This sums up the two greatest strengths of the scene graph – spatial organization for culling and encapsulating graphics characteristics in a data format.
Standard graphics objects
Why is this such a great thing?
When model data is read into memory to be utilized in OpenGL or Direct 3D using non-scenegraph solutions, proprietary formats are often used that are suited to the exact needs of the application. While this isn’t a bad thing in many respects, it makes it difficult to impossible to grab libraries and pieces of code you need from sources and use them without significant modification. Many times graphics programmers will see a technique they like and be forced to dig into the code and rewire things to work with their data structures. Scene graphics enable users to create code that works with the basic object primitives out of the box. This can quickly lead to a huge amount of code that is available for just about any graphics technique or purpose, ready to use out of the box.
Many ask, “What if you choose the wrong data format for these objects? Why is one superior to another? Scene graphs choose a format that encapsulates the lowest level graphics primitives and states into unique objects. These objects are combined in the graph to visualize anything that can be procedurally generated in a lower level graphics API. Various graphics states such as material attributes, blend modes, textures, etc. each have a corresponding object that is applied when the scene graph itself is drawn. Because of this flexible “standardizing” of basic graphics operations it is both possible to represent most anything the graphics sub-system can create as well as allowing new objects to be built to utilize them in a standard way.
Culling of the scene, optimization, transform stacking, billboards, LOD management, texturing are all able to have powerful, simple and standard code to manage them.
A spatial graph
By setting up the scene graph as a spatial non-acyclic graph culling can be more easily managed as well as graphics state. A node with children can set the state for the children without the need to redundantly specify it in the children. A scene graph is traversed as it is drawn and state is popped and pushed to both minimize setting state without need and to simply the organization and management of the scene as a whole. Scene graphs are often used in a complimentary fashion to other more “automatic” and hardboiled culling and spatializing strategies such as bsp nodes. I have seen many scene graph systems over the years that use bsp structures at various levels in the scene graph strictly for collision detection. The main thing about this approach is flexibility. Scene graphs can build very sophisticated scenes in a way that is logically consistent, as simple as possible and easy for the (relative novice) to learn and understand.
What scene graphs don’t do
Scene graphs are very powerful but not much easier to learn than the underlying graphics API’s themselves such as OpenGL or Direct 3D. They are not “game engines” that the novice can pick up and with little understanding create 3D scenes from.
You may ask yourself what the point is. The point is to not reinvent the wheel. The is so flexible a tool because it doesn’t try to hide capabilities or oversimplify them. However, it mirrors the kind of system one would generally have to write themselves through much trial and error to achieve the same functionality. Many of these concepts are “classic” at this point. OpenSceneGraph, for example, is chocked full of appropriate and useful design patterns. Performer used these design patterns long before the term became a buzzword. SGI spent a lot of time and money developing Performer, and like OpenGL, the results were impressive. Most modern scene graphs are directly influenced by Performer and can be seen at their core to be “Performer-clones”. Those who try to build fast and flexible graphics solutions will eventually come to something close to a scene graph on their own eventually. But why reinvent the wheel. With solutions like OpenSceneGraph already waiting……
The choice seems obvious
Use an existing scene graph solution. You wouldn’t try to write your own graphics API in today’s world. In just the same respect you shouldn’t try to think you’ll create a better scene graph. If you need a fast, flexible graphics solution and use one of the scene graphs out there today. I personally prefer OpenSceneGraph, something I mention often. It has a huge user base and an unmatched set of features for an open-source project. Other commercial options include Gamebryo or Renderware.
In short the benefits of using a scene graph are numerous. A reusable, flexible and fast object system and a graph structure for hierarchy give it a strong user base and an ever-expanding collection of useful code.
The next time you think about doing a project coding in a low-level graphics API think about bumping up to a scene graph. They sit nicely on top of the underlying graphics API’s and make your job much simpler at the end of the day by allowing you to focus on the problem at hand and avoid reinventing the wheel.