From: Tim M. <tim...@gm...> - 2018-04-13 14:16:38
|
Practicing some thread necromancy here... but I have my head back inside this code, so I thought I'd add what I remember. On Sat, Nov 4, 2017 at 5:21 PM, James Turner <jam...@kd...> wrote: > > > On 13 Oct 2017, at 15:16, James Turner <jam...@kd...> wrote: > > I’ll try to write something up in the next week, unfortunately there are > some names which overlap or are used differently in FLightgear vs > OpenSceneGraph vs OpenGL. But there is nothing especially terrible in the > code, hopefully with some explanation it will mostly make sense! > > > Okay, this is the summary I have so far. I’ve assumed familiarly with > OpenGL terminology, to avoid this become a ‘how to write a 3D engine from > nothing’ essay. I expect some questions of course. > > Kind regards, > James > I hope this is on the Wiki somewhere. > > = Basic update-render cycle = > > OSG has a piece called the viewer which we use (as most OSG apps do, but > technically it’s entirely optional). The viewer is something like a global > application object for OSG, it manages the window (or several in a > multi-window setup), and proves a ‘frame()’ call which draws an entire OSG > frame. This includes event handling (mouse, keyboard input, window system > events), updating OSG state (animations, etc), culling and finally > submitting OpenGL drawing calls. > > Because FlightGear already had a "Viewer," I created something called a "CameraGroup" to model the configuration of the OSG viewer. You can read how to configure multiple cameras, windows, screens, etc. in docs-mini/README.multiscreen. > Depending on which threading mode is active, some of the culling and / or > drawing may happen on different threads; frame() is always called on the > main thread. The event and update traversals always run on the main thread, > so hopefully they are quick. When ‘frame()’ returns control, in a > multi-threaded scenario, culling and OpenGL drawing are probably proceeding > in parallel; thus we need to do some other work before we call frame() > again, to see much benefit from multi-threading. > > The work we do is to call the subsystem manager’s update() function. Due > to some long-term refactoring, this does pretty much everything else in the > main loop - the FDM, joystick input, networking, Nasal and so on. There’s > some mechanisms OSG uses to ensure that changes we make to the scene-graph > in this phase (keeping in mind culling and drawing may be happening > concurrently) don’t cause races. > Actually, OSG's frame() doesn't return in the main thread until the rendering thread is finished with dynamic elements. That's the mechanism. > > = Scene hierarchy = > > There’s a global scene root defined in FGRenderer, which has some > interesting direct children, such as the splash screen. Beneath this are > various cameras (osg::Camera). These correspond to render-passes in some > other 3D engines, but tied to a projection and with an ordering. So for > example there’s a GUI camera which is drawn last, and displays the HUD, PUI > and canvas. > While cameras can be attached to the scene root (e.g., the cameras that render Canvas objects), the viewer's cameras are outside of the main scene graph. > > In a normal rendering setup, besides the GUI camera we have one main > camera drawing the scene; by using a custom view configuration, additional > cameras can be defined. However, to work-around depth (Z-buffer) precisions > issues, for every main camera we attach a slave camera for distant > rendering, and we draw the scene twice, with different near/far planes. > Both the near and far cameras are slaves of the viewer. In a simple OSG application a slave camera would usually be aimed at a fixed offset from the main camera, but we dynamically update the slaves with their own view matrix every frame. > > (We don’t actually draw everything twice, because OSG does frustum > culling, so the ‘near’ camera basically culls out 95% of the scene with a > bounding box check) > > In theory :) > Beneath the scene root, various subsystems insert some groups, for example > for the scenery, main aircraft model or AI models. Some special nodes such > as the sky are also inserted. All this structure is somewhat delicate, but > we can and do make changes sometimes. We also have to be careful about > ordering here to ensure we don’t run out of precision on the transform > matrices, going from the earth-centric to camera-local coordinates. > > I'm not sure what you mean here. We don't really need to do anything because OSG keeps the transform matrices in double precision until they are transmitted to OpenGL. Thanks so much for taking the time to write this! Tim |