Ironseed 3D Engine
The 3D engine used by Ironseed uses a rendering method known as a submission model. The 3D engine itself doesn’t understand the organization of data, only how to render primitive types to the screen. This means that the user of the 3D Engine is responsible for maintaining and organizing the 3D objects in a way that makes sense to the user as well as optimizing and controlling which objects are sent down to the rendering engine to be drawn.
To do rendering, the user of the 3D engine needs to implement a Render Listener. The Render Listener is given to the camera to render. As the camera flows through its logic, it periodically makes callbacks to the Listener for data requests. So when the camera begins a render, it notifies the Listener to start adding objects to the camera’s render queues. This is where the Listener has full control over which objects and what order they are rendered in. In the case of Ironseed, the Listener iterates through the actors in the world, culls them by the camera’s view frustum and actor’s bounding box, and adds the resulting visible actors to the queues. After the queues are populated, the camera starts notifying the renderable objects to draw themselves. For Ironseed, this is another chance to apply custom rendering to the objects before Ironseed asks the assets to render. Ironseed will apply shaders and debug drawing as needed.
Many people assume that a 3D program just throws all the triangles at the video card and the hardware does the work. In reality, the video card is fairly stupid and does exactly what you tell it to do, including bad things. The card can do some simple optimizations such as clipping offscreen triangles and backfacing triangles. It’s still better to have the engine decide that a model is off-camera and not even send it to the card. Bounds and camera frustum testing can be expensive and there are many ways to avoid even needing to do the test. For example, the world can be broken up into different areas and each area knows if it can be seen from the current area (this is done in a preprocessing step, not in-game).
The second major issue with letting the card blindly render is transparency. It’s generally better and faster to render front to back. Anything occluded by the objects in front will not even be drawn. For transparency, it is necessary to render back to front so that the transparent object blends with the objects behind it properly. The engine needs to be capable of determining the order to render objects for maximum efficiency. The 3D card will properly determine the depth so that one object is behind another but not the proper order. My 3D engine uses the render queues to group the objects together. The normal objects are rendered first, then the transparent objects sorted by distance, and finally the objects that want to be rendered on top like debug and UI.
