Programmers: Adding new Content

Oct 22, 2008 at 9:56 PM
We have started to refactor some of the code (written initially with C# 1.1), to use well defined interfaces. The key interfaces in the system are IMaterial, IDrawable, IAssetManaged, IManipulator and IShader. There are several other more specific interfaces for lighting, render targets, textures, etc. In addition, most objects have light-weight proxy implementations that can be shared within a single application or even across machines. This is achieved through the IAssetManaged interface and a base class implementation called SharedAsset. Most proxy classes derive from this class and are in the project OSU_Graphics. An IDrawable in this project are fly-weights and not drawn directly. As such there is no OpenGL or DirectX calls within any of the classes and many can be used on even a cell phone. Currently, actual drawing is handled by the classes in the project OSU_OpenGL. Within this project there are two types of classes, Handlers responsible for the synchronization with the properties of the IAssetManaged instance, and OpenGL primitive classes responsible for drawing themselves. Hence, for many drawables there are actually three classes used to manage and implement the rendering, a proxy class, a handler class and an OpenGL class). Additionally, there may also be a separate GUI classes for a complex drawable. This is complex, but provides a nice separation of control. Think of the proxies as a part of a database, the OpenGL classes as self-contained clean implementations of the IDrawable interface and the handlers as mediators between the two.

The rendering hierarchy is composed of views (IView), which contains a list of layers (ILayer), and a compositing camera (ICamera) used to project the layers on top of each other. Each layer contains a list of drawables (IDrawable), a viewing camera (ICamera) used to project each drawable, and a material (IMaterial) which controls how the current layer is composited on top of the underlying layers. If any of the drawables or the camera changes in a layer, then that layer will need to be updated (re-rendered). If not, then the layer can simply be recomposited into the image. The LayerHandler checks if the layer needs to be regenerated and if so regenerates the Frame-Buffer-Object associated with the layer. The LayerGL is really just an view aligned quad, rendered to the screen. By default, the layer's material is a simple material that samples a texture across the quad. OK, so if a drawable is updated, it sends out an event indicating it has changed. The associated handler sees this and sets a flag indicating that it needs to be updated before it is rendered again. If a layer proxy contains this drawable proxy, it also will receive the event signal and will re-fire the signal letting its subscribers know that it too has changed. The corresponding LayerHandler will receive this signal and also sets a flag. Finally, the ViewProxy (or ViewProxies) containing this layer will also receive the event and pass it along to its subscribers. The ViewHandler will also set a flag indicating that it needs to be updated. For the application, we also subscribe to the ViewProxy event at the Form level, once we receive this signal we tell the OpenGL panel to Invalidate itself. This will cause the rendering thread to redraw the window (repainted).

So let me quickly talk about how something is drawn. For the volume renderer included, when the main viewing pane needs to be repainted, it asks a ViewHandler to recomposite the layers. We set up this initial ViewHandler to keep synchronized with a ViewProxy created in the constructor of the Form. The ViewHandler will see if it needs to update its data and if so will copy the properties (the list of layers, compositing camera and compositing material) from the ViewProxy. Each layer will then be composited to the view. If the layer needs to be updated, it will render each of its drawables, if a drawable needs to be updated, it will update its data before re-rendering. Once a layer has been updated it will be composited into the view.