Compositor
The FlightGear forum has a subforum related to: Effects & Shaders |
Started in | 01/2018 (Available since FlightGear 2020.4) |
---|---|
Description | Dynamic rendering pipeline configured via the Property tree and XML |
Contributor(s) | Fernando García Liñán [1] |
Status | Stable (merged and actively maintained) |
Folders | |
Changelog | https://sourceforge.net/u/fgarlin/profile/feed.rss |
Rendering |
---|
Rendering Pipeline |
Effects and Shaders |
Ongoing Efforts |
Standalone Tools |
IPC/Networking |
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.
Background
First discussed in 03/2012 during the early Rembrandt days, Zan (Lauri Peltonen) came up with a set of patches demonstrating how to create an XML-configurable rendering pipeline. Back then, this work was considered to look pretty promising [2] 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. Rembrandt's developer (FredB) suggested to extend the format to avoid duplicating the stages when you have more than one viewport, i.e. specifying a pipeline as a template, with conditions like in effects, and have the current camera layout refer the pipeline that would be duplicated, resized and positioned for each declared viewport [3]
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. At that point, it didn't have everything Rembrandt's pipeline needs, but most likely could be easily enhanced to support those things. Basically, the original version added support for multiple camera passes, texture targets, texture formats, passing textures from one pass to another etc, while preserving the standard rendering line if user wants that. [4]
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. [5]
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.
Features
- Completely independent of other parts of the simulator, i.e. it's part of SimGear and can be used in a standalone fashion if needed, ala Canvas.
- Although independent, its aim is to be fully compatible with the current rendering framework in FG. This includes the Effects system, CameraGroup, Rembrandt, ALS and Canvas.
- Its functionality overlaps Rembrandt: what can be done with Rembrandt can be done with the Compositor, but not vice versa.
- Fully configurable via an XML interface without compromising performance (ala Effects, using PropertyList files).
- Flexible, expandable and compatible with modern graphics.
- It doesn't increase the hardware requirements, it expands the hardware range FG can run on. People with integrated GPUs (Intel HD etc) can run a Compositor with a single pass that renders directly to the screen like before, while people with more powerful cards can run a Compositor that implements deferred rendering, for example.
- Static branching support. Every pipeline element can be enabled/disabled at startup via a <condition> block.
- The entire rendering pipeline can be reloaded via an fgcommand (reload-compositor).
How to enable the Compositor
The Compositor is now the default renderer framework in FlightGear since 2020/11/17. It will be included as part of version 2020.4 onwards.
If you compile FlightGear from source, you can already try the Compositor. Make sure you are pulling the latest version of the 'next' branch. You can also try out the latest nightly build from the FlightGear build server.
Notes for aircraft developers
Lights
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. The resulting light volumes can be visualized for debugging purposes by setting the property /sim/debug/show-light-volumes to true.
You can edit existing lights with the Illuminator, but you have to define them first e.g. in your aircraft. The Illuminator add-on is meant for fine-tuning the light parameters.
Project Rembrandt light definitions are also read by the Compositor for backwards compatibility reasons. However, it is not recommended to use the old syntax for new/updated projects.
<light>
<name>my-spotlight</name>
<type>spot</type>
<position>
<x-m>-7.7476</x-m>
<y-m>0</y-m>
<z-m>-1.7990</z-m>
</position>
<direction>
<x>-1.0</x>
<y>0</y>
<z>-0.013</z>
</direction>
<ambient>
<r>0.03</r>
<g>0.03</g>
<b>0.03</b>
<a>1</a>
</ambient>
<diffuse>
<r>0.95</r>
<g>0.9</g>
<b>0.9</b>
<a>1</a>
</diffuse>
<specular>
<r>0.95</r>
<g>0.9</g>
<b>0.9</b>
<a>1</a>
</specular>
<attenuation>
<c>1.0</c>
<l>0.09</l>
<q>0.032</q>
</attenuation>
<spot-exponent>5</spot-exponent>
<spot-cutoff>40</spot-cutoff>
<range-m>50</range-m>
<dim-factor>
<property>controls/lighting/instruments-norm</property>
</dim-factor>
</light>
|
Important: The following parameters are only available in the HDR Pipeline.
|
Shadows
The shadow mapping algorithm can be customized entirely by the rendering pipeline. This means that each pipeline 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 (light sprites) or really small cockpit elements that don't need shadows and would cause degraded performance.
If the casted aircraft shadow appears blocky then there probably are some objects which need the noshadow animation applied. Most notably are billboarded lights which include ALS procedural lights.
- Try to mark as many cockpit objects as possible as interior.
<model>
<name>interior</name>
<usage>interior</usage>
<path>Aircraft/JA37/Models/ja37-interior.xml</path> <!-- All the objects that should only be seen when inside the cockpit are in this file -->
</model>
- 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.
Effects and Shaders
Schemes
Effects can have different implementations depending on the Compositor pipeline being used. For example, a grass Effect implemented for a high quality pipeline might have much more detail than one that targets low specification machines. Still, they both implement the "look" of grass, so they share the same Effect file (grass.eff).
The Compositor chooses which implementation of an Effect to render based on the <scheme> of the techniques.
<technique n="15">
<scheme>test-scheme</scheme>
[...]
</technique>
In this case the technique will be chosen if the Compositor pipeline <scene> pass uses the test-scheme Effect scheme. Consequently, porting an Effect to a Compositor pipeline will require knowing which Effect schemes it uses and writing a technique for each one. The only exception to this is the Classic/default pipeline, which uses techniques with no scheme.
Built-in uniforms
The Compositor provides a set of built-in uniforms that are passed along to every shader. These uniforms must not be defined in the Effect file, as they are defined and updated in C++.
Name | Type | Description |
---|---|---|
fg_TextureMatrix | mat4 | Texture matrix that replaces the old fixed-function behaviour. If no texture animations are present it corresponds to the identity matrix. |
fg_Viewport | vec4 | Viewport geometry for the current pass (x, y, width, height). |
fg_PixelSize | vec2 | Inverse of the width and height of the viewport. |
fg_ViewMatrix | mat4 | View matrix given by CameraGroup for this Compositor. |
fg_ViewMatrixInverse | mat4 | Inverse of the view matrix given by CameraGroup for this Compositor. |
fg_ProjectionMatrix | mat4 | Projection matrix given by CameraGroup for this Compositor. |
fg_ProjectionMatrixInverse | mat4 | Inverse of the projection matrix given by CameraGroup for this Compositor. |
fg_PrevViewMatrix | mat4 | Previous frame view matrix given by CameraGroup for this Compositor. |
fg_PrevViewMatrixInverse | mat4 | Previous frame inverse of the view matrix given by CameraGroup for this Compositor. |
fg_PrevProjectionMatrix | mat4 | Previous frame projection matrix given by CameraGroup for this Compositor. |
fg_PrevProjectionMatrixInverse | mat4 | Previous frame inverse of the projection matrix given by CameraGroup for this Compositor. |
fg_CameraPositionCart | vec3 | Position of the camera in world space, expressed in cartesian coordinates. |
fg_CameraPositionGeod | vec3 | Position of the camera in world space, expressed in geodesic coordinates (longitude in radians, latitude in radians, elevation in meters). |
fg_CameraDistanceToEarthCenter | float | Distance from the camera to the center of the Earth in meters. |
fg_CameraWorldUp | vec3 | Camera up vector in world space. |
fg_CameraViewUp | vec3 | Camera up vector in view space. |
fg_EarthRadius | float | Earth radius right below the camera position in meters. |
fg_NearFar | vec2 | Near and far clipping planes in meters. x component is the near plane, y component is the far plane. |
fg_Fcoef | float | Used by logarithmic depth. |
fg_FOVScale | vec2 | Used by logarithmic depth. |
fg_SunDirection | vec3 | Normalized Sun (directional light) direction in view space. |
fg_SunDirectionWorld | vec3 | Normalized Sun (directional light) direction in world space. |
fg_SunZenithCosTheta | float | Dot product between the Sun direction and the up vector at the camera position. |
fg_MoonDirection | vec3 | Normalized Moon (directional light) direction in view space. |
fg_MoonDirectionWorld | vec3 | Normalized Moon (directional light) direction in world space. |
fg_MoonZenithCosTheta | float | Dot product between the Moon direction and the up vector at the camera position. |
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.
Also keep in mind that every pipeline element can be enabled/disabled through a <condition> block. This allows for dynamic rendering pipelines that have toggleable features. However, the pipeline can't be updated in real-time: the simulator has to be restarted or the Compositor has to be reloaded through the reload-compositor fgcommand.
Buffers
A buffer represents a texture or, more generically, a region of GPU memory.
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 |
Passes
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.
scene
Renders the scene from the point of view given by the CameraGroup.
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 | float | 0.0 uses the value given by the CameraGroup | Sets a custom near and far values. Useful for implementing depth partition and limiting the depth range on cubemap passes |
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 |
use-shadow-pass | Yes | string | Empty | Name of a shadow mapping pass. Exposes shadow mapping related uniforms to the shaders of the current pass |
Scene passes can also use the tag <clustered-shading>
to enable clustered shading (lights). The following parameters are available:
Parameter Name | Optional | Value | Default Value | Description |
---|---|---|---|---|
max-pointlights | Yes | int | 1024 | Maximum amount of point light sources allowed on the entire scene |
max-spotlights | Yes | int | 1024 | Maximum amount of spot light sources allowed on the entire scene |
max-light-indices | Yes | int | 256 | Size of the light indices texture. Keep in mind that it is a 2D texture, so the total size will be e.g. 256x256 |
tile-size | Yes | int | 128 | Size of each clustered shading tile |
num-threads | Yes | int | 1 | Number of threads to use during the light culling process. Keep in mind that a high thread count when there aren't many lights will worsen performance due to the thread creation overhead |
depth-slices | Yes | int | 1 | Number of slices to partition the view frustum in the Z axis. Higher numbers will cull lights more aggressively, increasing performance if there are many lights further out that don't contribute much to the overall scene's lighting |
quad
Renders a fullscreen quad with an optional effect applied. Useful for screen space shaders (like SSAO, Screen Space Reflections or bloom) and deferred rendering.
Parameter Name | Optional | Value | Default Value | Description |
---|---|---|---|---|
geometry | Yes | float values for <x>, <y>, <width>, <height>, <scale>
|
0.0, 0.0, 1.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 |
csm
Implements Cascaded Shadow Mapping by rendering the scene from a light's point of view (the Sun by default). For now it only supports directional light sources. There has to be one csm pass for each cascade.
Parameter Name | Optional | Value | Default Value | Description |
---|---|---|---|---|
light-name | Yes | Valid light name that exists in the scene graph | FGLightSource (Sun) | The name of the osg::LightSource to use for this shadow map |
render-at-night | Yes | bool | true | Whether to render the shadows at night or not |
near-m, far-m | No | float (meters) | They specify the range of the shadow map |
References
References
|
Related content
Wiki articles
- HDR Pipeline
- glTF
- Canvas View Camera Element
- CompositeViewer Support
- Uniform Buffer Objects
- FlightGear CIGI Support (Common Image Generator Interface)