Ingenu's website

OctoPort / Design

My original design, years ago, before I decided to work full time on the engine, was to have a RenderTree, back then, most engines were rendering Meshs as they were encountered in the SceneGraph, which was clearly suboptimal, and would be even worse with Shaders coming (at the time they weren't available just yet). This feature was basically the soul & heart of my engine, the reason why it would perform better than the open-source engine I saw at the time, and which all suffered from severe weaknesses, inheriting from software rendering limitations. (Basically I didn't like the design of the Open Sourcce engines at the time and thought I could do better...)

Please note that OctoPort is not my latest engine, the FlExtEngine is, and has a different architecture.

SceneGraph

This is an "uber"-scenegraph. It provides a uniform way to access data, and also a way to compute visibility from a camera point of view. The SceneGraph allows transparent access to each and every of its Node in the engine, such as GeoMipmap, ChunkLODTerrain, Object, Light, ParticleEmitter...
The SceneGraph is a hierarchical structure that handles both spatial locality (an Octree divides space and Objects can be inserted in its Nodes) and logical relationship (a Skeleton linked to an animated figure).

OctoPort allows both, it's behavior is a bit "weird" in that it's a Graph for Spatial Division structures, but only a Tree (one Parent per Node) for other structures, due to the Transform inheritance. (Spatial Division Structures having no Transform.)
OctoPort's SceneGraph also have a Bounding Volume Hierarchy, along with PlaneSet marking allowing fast visibility tests. (Only Planes intersecting with parent agglomerated Bounding Volume are tested by Children Bounding Volumes)

OctoPort provides basic class and "services", and can be easily extended to whatever spatial subdivision scheme the user might want.
(kDTree, Octree, QuadTree, BSP,...)

RenderTree

The RenderTree is the part of the engine that does all the "heavy work". My original RenderTree was sorting by Shader then by TextureSet, the new version is somewhat different though.

The RenderPass is the first sorting parameter, it basically controls the order in which operations occur, it's usefull to make sure you're rendering the ShadowMap before using it, and stuff like that...
The Transparent RenderPass does also depth sort back to front and render once backfacing polygons, once frontfacing polygons, in order to have correct blending.

After the RenderPass (except for the Transparent being depth sorted), there's the Effect sorting (the Effect is described later, you can consider it a Shader for now).

I'm considering adding another sorting parameter (after those two), and using the "diffusemap"/"colormap" texture as the parameter, it would basically add Texture Sorting to the mechanism.

One everything is sorted, states change are minimized, and the RenderTree is considered optimal. (The smallest states change set to render what's visible.)
[As a matter of fact, the engine never really/actively sorts anything (but the Transparent Back to Front RenderPass)]

Effects and RenderPaths

It's common to call a given rendering path optimised for a given 3D chip the "chip name" path, Doom III have several of these paths, so I took the idea and made it a name the "RenderPath", I tried to use Shader at a time, but it was confusing because Shaders are programs for the graphic chip, and my RenderPaths are just not that.

Effects encapsulate RenderPaths on 1:1 ratio, Effects are created, and each selected RenderPath is the one being hardware compatible with the highest priority.
Say your Effect is "Bump Mapping", and you have two RenderPath, the first is for old hardware using the DOT3 extension, and the new one is for programmable hardware using Shaders, the first have a lower priority than the second. OctoPort will check (at init) which RenderPath are doing "Bump Mapping", ask them whether they are hardware compatible, and then select the one RenderPath having gone through those tests which have the highest priority, so that, no matter the hardware, the Effect is the best compatible code possible.

So the RenderPath is a DLL containing code to perform an Effect, resolved at engine initialisation. Because they are DLLs the engine is easy to extend, to add new effect, just use an Effect ID which isn't alreay in use, and code the appropriate RenderPath, put them in the right directory, and it's done !
You're game/demo/project is now capable of one more Effect w/o any need to recompile it :)

Engine Caches

A good engine wouldn't be that good w/o a cache, although my cache isn't really a cache, sometimes.
OctoPort have what I call a RAM cache (or Level 1 cache), which behaves much like a real cache, since it's used to fill the VRAM cache (or Level 2 cache), which isn't that much of a cache itself, rather a VRAM partitionning scheme.
RAM slots are loaded on demand, via an IOModule which have a PlugIn mechanism allowing easy extension and addition of new file formats to the engine, VRAM slots are also loaded on need from the RAM slot.

The Adaptative Cache

That cache uses a memory chunk subdivided into slots of given size (which range is specified in the engine init file), which (kudos to Yann) can slide; and is using a LRU scheme.
Slots miss and use are monitored by the cache to choose which slots to merge/split in order to have a cache that is a better fitt for the scene. This adaptation happen every n ms. (also specified in the engine init file)

Both the Index & Vertex slots are managed by such a cache.

The Memory Pool Cache

That cache is more conventional, although the name varies for such a structure, it's basically a system that manages slots of any size/type inside a memory pool of a given size; this cache uses a LRU mechanism too.

The Textures are managed by that kind of a cache.

Model Instancing

In OctoPort, Objects are in fact Model instances.
A Model contains all the basic structure and the VertexArray & IndexArray data, so that many instances (objects) can be made out of a given at little cost.
Models are not SceneGraph nodes, whereas Objects are.

All Objects have a pointer to their "parent" Model and have their own data (called MeshTags) which can be strings (path to texture file required), vectors & matrices (for shaders)...
Objects have their own skeleton (hierarchy of bones which are SceneGraph nodes), might have their own Vertex & Index data (in case of software animation, or Continuous LOD...), and have their own set of Animations.

The whole purpose of this design is to reduce memory consumption by sharing as much as possible, while still allowing each Object to have its own appearance through the MeshTags and Animation set.

IOModule

The IOModule is a Virtual File System managing I/O access, using PlugIns for file formats support, making it very easy to extend.
It also is responsible of finding files, and can read lone files, archives and compressed archives; with multi-threading support.
(The IOModule is using zlib for decompression.)

Renderer Interface

OctoPort don't use an API, it uses an abstract layer in order to be API independant, and so let it to be used on any platform. (Just code the appropriate Renderer for your API.) It's designed with both DX9 & OpenGL in mind, and so should be usable on say... PS3. (using OpenGL ES)
Currently, an OpenGL 2.0 renderer is available, a DirectX8 renderer was coded but is out of date, and a DirectX9 is being worked on.
Also, a Direct3D10 version is in the work, and the Renderer Interface has been update to support D3D10.

Last Updated : 07/07/08

 

About Me | Contact Me | ©2006 Pierre Rodéric Vicaire (Ingenu)