Unifying the 2D rendering backend via canvas

From FlightGear wiki
Jump to navigation Jump to search

1rightarrow.png See FlightGear and OpenGL ES for the main article about this subject.

We have some many reasons to unify on as few rendering backends as possible: ideally just Canvas for everything 2D, so that as we improve how Canvas itself renders, those users automatically get faster.[1]


Cquote1.png the reason we still havent moved to opengl 3.x+ has been due to supporting OSX. If we wish to support OSX, we need to completely abandon the fixed function pipeline. Some of our dependencies (plib) are no longer maintained , so must be replaced with something that supports shaders (canvas, etc).

Apple has made app developers to move on or stay in fixed fn. We aren't there yet.

Almost every feature in fg needs a maintainer.

— psadro_gm (Sat Oct 18). Re: Orbital Makes the Sky Black.
(powered by Instant-Cquotes)
Cquote1.png the other issue is that there's still legacy GL code running in the main/rendering loop that prevents us from using a more recent OpenGL version, such as the panel/HUD and GUI code - those things are in the process of being unified, and re-implemented, on top of modern OSG code using a shared back-end via Canvas.
— Hooray (Sat Oct 18). Re: Orbital Makes the Sky Black.
(powered by Instant-Cquotes)

Cquote1.png In contrast to using some hardcoded GUI system (PUI, osgWidget, etc.) this approach would give much more flexibility and also the means of modifying and creating new widgets without the need to touch any core code.

With the Canvas system every type of widget would be possible, so that also things like submenus can be realized.

Another advantage of the Canvas approach is that it is heavily using the property tree and therefore is already fully accessible from Nasal code and also configurable with the existing xml formats.
Cquote1.png using the Canvas also for the GUI would give us the advantage of a unified rendering backend for any type of GUI/text rendering and also the ability to use the same widgets everywhere - eg. use them also inside aircrafts for CDU GUIs or other displays...
Cquote1.png I'm even more convinced now that we should move the 2D panel and HUD rendering over to this approach, since that would get rid of all the legacy OpenGL code besides the GUI.
Cquote1.png The long term idea is to eventually port some other 2D elements to this backend (eg the HUD and 2D panels) so they use OSG (and osgText) natively, and hence reduce the amount of C++ code we have for these jobs. (And increase our chances of working with newer OpenGL versions that forbid old style GL calls) Long-term here means 'after 2.8 at least'.
Cquote1.png Moving the HUD to use the Canvas would be a great step from my point of view, since it and 2D panels (which I am happy to write the convert for!) are the last places besides the UI which make raw OpenGL calls, and hence would benefit from moving to the Canvas (and thus, to use OSG internally)
Cquote1.png One solution would be to port the HUD to use osgText : that’s actually somewhat doable because it’s already centralised, but rather high risk close to release.
— James Turner (Jan 15th, 2016). Re: [Flightgear-devel] Corrupted HUD / 2D panel text.
(powered by Instant-Cquotes)


For the HUD, the question is if the Canvas-HUD could gain a Nasal glue layer, to replicate the C++ HUD?

This would then allow the C++ HUD code to be removed entirely, which would be a GoodThing(TM) since it does archaic OpenGL rendering. If Nasal is more your thing than C++, that might be another way to help hasten the death of PLIB [1]

There is no conceptual limitation in the Canvas that prevents us doing everything the built-in HUD does.[2]

If we are to move beyond the legacy C++ code, we need a layer (in Nasal or C++) that parses the existing HUID XML, and looks/works close-to-identical to the current version.

We could for example just add some more parseXXX functions (like parsesvg) which parse a dialog/hud/whathever file and create a canvas from it. So we would just have to modify eg. the show-dialog command to create a canvas and call the parser.[3]

Replace the HUD (HUD.cxx and related code) with a Canvas implementation. This is a confusing scheme, since we have ‘old’ and ‘new’ C++ HUDs (but I recall I unified their rendering some years ago), and some aircraft already using ‘custom Canvas HUDs’, i.e totally independent of the ‘built-in’ HUD.

To be clear, this is the HUD you get by pressing ‘h’ key in the sim. It’s configured by an XML file: FG_DATA/Huds/default.xml - and you can see in that directory, other configs are possible - the ‘new C++ HUD’ layer allows arbitrary placement of HUD elements defined by these XML.

Some aircraft, but I don’t know how many, use the C++ HUD system, but replace the default HUD with their own - see the F16 example file also in FG_DATA/Huds for example.

The aim would be to replace the C++ code with a Nasal HUD layer, likely in FG_DATA/Canvas/Hud - with one Canvas HUD item per each of the current C++ HUD items (ladder, tape, dial etc). Each one should be fairly easy to build with some path, text and group commands.

Then we need to write an XML loader in Nasal, possibly one line of C++ to trigger loading, and we can remove the C++ HUD code in favour of the Canvas implementation.

Of course, probably it’s not so simple but this is the concept!

Oh, and there is some complexity I guess about how the Canvas-for-the-HUD is positioned, since right now the HUD moves when the view is rotated. I guess / hope the existing Canvas HUDs can show how to handle that correctly.[4]

If the new impl defines each HUD component with the same features as the C++ implementation, it should work as a drop-in replacement for the old system. (Honestly it may be the case that some features supported in C++ are not used by any aircraft out there, but as ever with FG, we have no way to capture the set of in-use features).

If you look at say HUD_tape.cxx - which is one of the more complex ones - it’s some fairly ‘simple’ (but verbose) code to draw either a horizontal or vertical tape. Mostly it comes down to many draw_line calls which ultimately do the OpenGL - you can replace the draw_line calls in a Nasal version with appending a moveTo,lineTo onto a Canvas path.

And the constructor for HUD::Tape::Tape shows you the XML config properties for the tape which are supported.[5]

Of course, developing some Canvas HUDs for particular aircraft is a great way to get comfortable with writing Canvas code in general, and HUD display concepts. I just want to explain, that making fifty different Canvas HUDs for our aircraft, still won’t ever let us drop the legacy C++ code - we need a generic (XML driven) HUD for that.[6]

About making the specific HUD, I’d suggest to follow the Shuttle approach (procedurally generated geometry) more than the F-14 or F-15 - for a generic HUD using SVG elements will not work, the Shuttle HUD is already 100% defined via Nasal and hence closer to what you need.[7]

Canvas-HUD-that-replaces-the-C++-one would appear the same way Canvas tooltips / popups do. (or Canvas dialogs, or…)[8]

2D Panels



at some point we need to convert the generic HUD to sue the canvas - not a job I'm looking forward too - so I'm likely to steal any ideas and pieces I can to make my life easier. If anyone who actually uses HUDs wants to help with such an effort, please get in touch with TheTom and/or Zakalawe[1].

The Canvas subsystem is flexible enough to re-implement existing 2D rendering related features, such as the HUD system or the 2D panel system, in scripting space, so that legacy C++ code can be incrementally replaced with a more accessible and more maintainable version in scripting space, i.e. as part of the base package - while ensuring that the 2D rendering backend is increasingly unified, using the Canvas subsystem as the common rendering backend. Once a standalone mode for the canvas system has been implemented, all systems making use of the canvas backend will automatically support standalone (FGPanel-analogous) rendering.

The idea is to provide Nasal wrappers for these systems, which implement the existing behavior using the canvas system, so that the old C++ code can be eventually phased out. In particular, this means that wrappers for the following systems will be added:

Note that the API-requirements will be pretty much identical for GUI widgets and MFD-screens with touch screen functionality, both features will need a way to deal with keyboard/mouse input.

Initially, the main focus will be on providing the infrastructure to enable people to develop widgets entirely in Nasal space. Once that is working, it will be possible to increasingly re-implement native PUI widgets in Canvas/Nasal space, so that PUI usage is increasingly reduced.

To ensure that the Canvas/GUI wrapper is flexible enough, we need to take a look at existing hard coded PUI dialogs/widgets, and make sure that these can be theoretically reimplemented using Canvas/Nasal, and add any missing hooks as required:

Also, the Canvas subsystem should be powerful enough to allow re-implementing existing hard-coded od_gauge instruments, such as:

We need to take a look at these instruments and their C++ code, to ensure that the Canvas API is sufficiently customizable to implement these and similar instruments purely in scripting space.

As of 07/2012 the navdb (including airports, runways etc) is fully exposed as part of the NasalPositioned module in $FG_SRC/Scripting: https://sourceforge.net/p/flightgear/flightgear/ci/next/tree/src/Scripting/NasalPositioned.cxx.