Hi fellow wiki editors!



Difference between revisions of "Compositor"

From FlightGear wiki
Jump to: navigation, search
m (shadow-map)
m (scene)
Line 438: Line 438:
! scope="row"| <tt>cull-mask</tt>
| {{Yes}}
| {{Yes}}
| A 32 bit number. See <tt>simgear/scene/util/RenderConstants.hxx</tt> to know which bits enable what
| A 32 bit number. See {{simgear file|simgear/scene/util/RenderConstants.hxx}} to know which bits enable what
| <tt>0xffffffff</tt>
| <tt>0xffffffff</tt>
| Specifies the cull mask to be used in the underlying <tt>osg::Camera</tt>

Revision as of 09:38, 8 November 2019


This feature is scheduled for FlightGear 2019.2. 100}% completed


Compositor Framework
ALS Compositor pipeline.jpg
Started in 01/2018 (Available since FlightGear 2019.2)
Description Dynamic rendering pipeline configured via the property tree and XML
Contributor(s) Fernando García Liñán
Status Stable

The Compositor aims to bring multi-pass rendering to FlightGear. It encapsulates a rendering pipeline and exposes its parameters to a Property Tree interface. At startup, FlightGear reads the pipeline definition file for each physical viewport defined on the CameraGroup settings. If no Compositor file is specified for a physical camera, the one given by the --compositor= startup command will be used. If such startup option is not used either, FlightGear will look for a valid Compositor file in $FG_ROOT/Compositor/default.xml

The Compositor introduces a new dedicated fgdata directory for new/custom rendering pipelines: fgdata/Compositor.



Back then, this work was considered to look pretty promising [1] and at the time plans were discussed to unify this with the ongoing Rembrandt implementation (no longer maintained).

Adopting Zan's approach would have meant that efforts like Rembrandt (deferred rendering) could have been implemented without requiring C++ space modifications, i.e. purely in Base package space.


Zan's original patches can still be found in his newcameras branches which allow the user to define the rendering pipeline in preferences.xml: FlightGear, SimGear.



Since the early days of Zan's groundwork, providing the (hooks) infrastructure to enable base package developers to prototype, test and develop distinct rendering pipelines without requiring C++ space modifications has been a long-standing idea, especially after the Canvas system became available in early 2012, which demonstrated how RTT-rendering buffers (FBOs) could be set up, created and manipulated procedurally (i.e. at run-time) using XML, the property tree and Nasal scripting. [4]

The new Compositor is an improved re-implementation of Zan's original work using not just XML, but also properties and a handful of Canvas concepts.


  • Fully configurable via an XML interface without compromising performance (ala Effects, using PropertyList files).
  • Flexible, expandable and compatible with modern graphics.
  • Static branching support. Every pipeline element can be enabled/disabled at startup via a <condition> block.

How to enable the Compositor

Currently the Compositor can only be enabled at compile time via the -DENABLE_COMPOSITOR=ON CMake flag in FlightGear. SimGear doesn't require any extra parameters. Once you have a binary with the Compositor enabled and you run it, you will be presented with the default rendering pipeline. At the time of writing, this is the low spec rendering pipeline. If you want to try the ALS pipeline, start FlightGear with the command line argument: --compositor=Compositor/ALS/als

Notes for aircraft developers


The Compositor introduces a new way of defining lights that is renderer agnostic, so every rendering pipeline will be able to access the lights that have been implemented like this. As of 2019/11, the only pipeline that supports dynamic lights is the ALS pipeline. The resulting light volumes can be visualized for debugging purposes by setting the property /sim/debug/show-light-volumes to true.

  • name. An <animation> will be able to reference the light by this name. Most animations will work as expected (rotate, translate, spin etc).
  • type. spot or point.
  • position. The position of the light source in model space and in meters.
  • direction. Only available in spot lights. It indicates the direction of the spotlight. This parameter can be specified in three different ways:
Direction vector Look-at point Rotation angles
A vector in model space that specifies the direction. Doesn't have to be normalized.
The spotlight will calculate its direction by looking at this position from the light position. The point is in model space and in meters.
A three angle rotation in degrees that rotates the spotlight around the three axes. A 0 degree angle in all axes makes the spotlight point downwards (negative Z).
  • ambient, diffuse and specular. Four-component vectors that specify the light color.
  • attenuation. Three-component vector where <c> specifies the constant factor, <l> specifies the linear factor and <q> specifies the quadratic factor. These factors are plugged into the OpenGL light attenuation formula Spotlight attenuation.png where d is the distance of the fragment to the light source. See this table for a list of attenuation values based on the range of the light.
  • range-m. Maximum range from the light source position in meters. This value will be used by the renderers to determine if a fragment is illuminated by this source. Every fragment outside this range isn't guaranteed to be affected by the light, even if the attenuation factor isn't 0 in that particular fragment.
  • cutoff. Only available in spot lights. It specifies the maximum spread angle of a light source. Only values in the range 0 90 are accepted. If the angle between the direction of the light and the direction from the light to the fragment being lighted is greater than the spot cutoff angle, it won't be lit.
  • exponent. Only available in spot lights. Higher spot exponents result in a more focused light source, regardless of the spot cutoff angle.
  • debug-color (Optional). Sets the color of the debug light volume. By default it's red.


The shadow mapping algorithm can be customized entirely by the rendering pipeline. This means that each one will have its own requirements when it comes to shadows. Here are some general recommendations:

  • Use the <noshadow> animation to disable shadows on objects that don't need them. An example would be billboarded lights or really small cockpit elements that don't need shadows and would cause degraded performance.
  • Try to mark as many cockpit objects as possible as interior.
  <path>Aircraft/JA37/Models/ja37-interior.xml</path> <!-- All the objects that should only be seen when inside the cockpit are in this file -->
  • Unlike in Rembrandt, polygons facing the Sun are the ones used to generate the shadow map, so single sided surfaces and non-closed objects should be rendered correctly.


Low-Spec pipeline

A fixed function forward rendering pipeline mainly targeted to low spec systems. It imitates the classic forward pipeline used before multi-pass rendering was introduced by using two near/far cameras rendering directly to the screen.

Screenshot showing OSG stats of the Compositor-based low-spec rendering pipeline.


The ALS pipeline tries to bring multipass rendering to the current ALS framework, effectively combining the best from ALS and Project Rembrandt.

Cascaded shadow mapping

The main issue with shadow mapping in FlightGear is the complexity of the scene graph. Culling times can become huge if we don't carefully select which parts of the scene graph we want to render in the shadow maps. Some possible optimizations:

  • Study the minimum shadow map distance we can get without noticeable light leaking. Select an appropiate amount of cascades (more cascades = more passes over all geometry, and in general we want to keep the amount of forward passes to a minimum). We should have at least three cascades: the first just for cockpit/internal shadows, the second for the whole aircraft and the third for the rest of the scenery geometry. A fourth can be added if the transition between the second and the third is too harsh.
  • Improve the culling masks (simgear/scene/util/RenderConstants.hxx). The CASTSHADOW_BIT flag is present in almost every object in the scene graph. Turning this flag off for trees, random buildings and other geometry intensive objects improves framerates by a very considerable amount. Should the user be able to select which objects cast shadows?
  • Should the terrain cast shadows? The terrain is rarely steep enough to cast shadows. Apart from that, the terrain in FlightGear messes with automatic near/far computations for the shadow passes since the geometry is not tessellated enough. Also, the terrain LOD is not good enough to have decent cull times at far cascades.
  • Adding a "internal only" shadow flag for aircraft developers. This allows farther shadow cascades to cull complex objects that are only visible in the nearest cascades. (Very important optimization for aircrafts with complex cockpit geometry).


Gamma correction, night vision and other ALS filters should happen in a quad pass. The current filter_combined() should be left for post-processing that requires as much precision as possible - e.g. dithering to prevent banding). HDR is not a planned feature for now so ALS will be using rgba8 buffers for most of its features.

Real-time dynamic reflections

Rendering dynamically to a cubemap is possible. As with shadow mapping, minimizing the object count and number of forward passes is vital to get good performance in FlightGear. Rendering to six cubemap faces requires six forward passes, but we can render to a dual paraboloid map instead, reducing this number to two.


When shadows (and multipass rendering in general) come into play, transparent objects have to be treated differently, even when we are dealing with a forward renderer. In OSG there are two ways to separate transparent surfaces:

  • Using RenderBins. After a single scene cull traversal, surfaces which belong to a special RenderBin type (DepthSortedBin) are removed or moved to another camera. This is how Rembrandt does it and it is the most backwards compatible approach since RenderBins can be changed directly inside Effects.
  • Using cull masks. Two separate traversals are done: one for opaque objects and another for translucent objects. This requires offering aircraft developers another way of tagging a surface as transparent. A trivial approach would be to add a new <animation> type called 'transparent', but that wouldn't be backwards compatible. Maybe we can add some kind of system where we can change cull masks inside Effects? Would that be too hacky or out of place?

Creating a custom rendering pipeline

Since the Compositor is completely data-driven, new rendering pipelines can be created by writing a custom XML pipeline definition. This section tries to document most of the available parameters, but the best and most up-to-date resource is the Compositor parsing code in SimGear (simgear/simgear/scene/viewer). See existing pipelines in fgdata/Compositor for practical examples on how to use these parameters.



Parameter Name Optional Value Default Value Description
name No string Passes will be able to address the buffer by this name
type No 1d, 2d, 2d-array, 2d-multisample, 3d, rect, cubemap Any texture type allowed by OpenGL
width No Any unsigned integer or screen to use the physical viewport width. The <property> tag can also be used to use a property value Texture width
screen-width-scale Yes float 1.0 If screen was used, this controls the width scaling factor
height No Any unsigned integer or screen to use the physical viewport height. The <property> tag can also be used to use a property value Texture height
screen-height-scale Yes float 1.0 If screen was used, this controls the height scaling factor
depth No Any unsigned integer. The <property> tag can also be used to use a property value Texture depth
format Yes See simgear/simgear/scene/viewer/CompositorBuffer.cxx for the latest available values rgba8 Specifies the texture format. It corresponds to the internalformat, format and type arguments of the OpenGL function glTexImage2D
min-filter, mag-filter Yes linear, linear-mipmap-linear, linear-mipmap-nearest, nearest, nearest-mipmap-linear, nearest-mipmap-nearest linear Change the minification and magnification filtering respectively
wrap-s, wrap-t, wrap-r Yes clamp, clamp-to-edge, clamp-to-border, repeat, mirror clamp-to-border They change the wrap mode for each coordinate
anisotropy Yes float 1.0
border-color Yes vec4 (0.0f, 0.0f, 0.0f, 0.0f)
shadow-comparison Yes bool true
shadow-texture-mode Yes luminance, intensity, alpha luminance
shadow-compare-func Yes never, less, equal, lequal, greater, notequal, gequal, always lequal


A pass wraps around an osg::Camera. Passes all have some common parameters:

Parameter Name Optional Value Default Value Description
clear-color, clear-accum, clear-depth and clear-stencil Yes vec4 black, black, 1.0, 0 respectively Pass clear colors
clear-mask Yes color, stencil, depth, accum color depth Pass clear mask
effect-scheme Yes Valid effect scheme name None The pass will try to use the specified effect scheme to draw every object.

Passes can render to a buffer (Render to Texture), to several buffers (Multiple Render Targets) or directly to the framebuffer. This is accomplished by the <attachment> tag. Possible parameters of an attachment are:

Parameter Name Optional Value Default Value Description
buffer No Valid buffer name The name of the buffer to output to
component No color, color0 to color15, depth, stencil, depth-stencil FBO attachment point
level Yes int 0 Mipmap level of the texture that is attached
face Yes int 0 Face of cube map texture or z-level of 3d texture
mipmap-generation Yes bool false Whether mipmap generation should be done for texture
multisample-samples Yes int 0 Multisample anti-aliasing (MSAA) samples
multisample-color-samples Yes int 0 Multisample anti-aliasing (MSAA) color samples

Passes can also receive buffers as input and use them in their shaders. This is accomplished by the <binding> tag, which has the following parameters:

Parameter Name Optional Value Default Value Description
buffer No Valid buffer name The name of the buffer to bind
unit No int The texture unit to place the texture on. Effects will be able to access the buffer on this texture unit

There are specific pass types, each with their own set of custom parameters.



Parameter Name Optional Value Default Value Description
cull-mask Yes A 32 bit number. See simgear/simgear/scene/util/RenderConstants.hxx to know which bits enable what 0xffffffff Specifies the cull mask to be used in the underlying osg::Camera
z-near, z-far Yes int Default Z range in the CameraGroup They change the depth range to be used
cubemap-face Yes int -1 (don't use cubemap) Ignores the given view and projection matrices and uses a custom one that renders the scene as if it was seen from inside a cubemap looking towards the specified face



Parameter Name Optional Value Default Value Description
geometry Yes float values for <x>, <y>, <width>, <height> 0.0, 0.0, 1.0, 1.0 respectively Size of the fullscreen quad inside the viewport using normalized coordinates.
effect Yes Valid Effect file None This Effect will be applied to the quad geometry


Renders the scene from a light's point of view.

Parameter Name Optional Value Default Value Description
light-name No Valid light name that exists in the scene graph The name of the osg::LightSource to use for this shadow map
near-m, far-m No Valid Effect file They specify the depth range of the shadow map


  • Bring back distortion correction.
  • Bring back Canvas integration so aircraft devs have access to the rendering pipeline. This allows to render exterior views in cockpit displays etc.
  • Automatically calculate light source attenuation based on radius and radius based on attenuation.

Known Issues

  • Clustered shading crashes FG if compiled under OSG 3.6. This is related to osg::TextureBuffer changing definition from OSG 3.4 to OSG 3.6 (Images vs BufferData).