Effect framework: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
No edit summary
 
(40 intermediate revisions by 3 users not shown)
Line 1: Line 1:
The effect framework as per version 2019.1
{{forum|47|Effects & Shaders}}
{{Rendering}}
The '''Effect framework''' as per FlightGear version 2020.3


Effects describe the graphical appearance of 3d objects and scenery in
Effects describe the graphical appearance of 3D objects and scenery in
FlightGear. The main motivation for effects is to support OpenGL
FlightGear. The main motivation for effects is to support OpenGL
shaders and to provide different implementations for graphics hardware
shaders and to provide different implementations for graphics hardware
Line 21: Line 23:
FlightGear.  
FlightGear.  


=Default Effects in Terrain Materials and Models=
== Default effects in terrain materials and models ==
Effects for terrain work in this way: for each material type in
Effects for terrain work in this way: for each material type in
materials.xml an effect is created that inherits from a single default
materials.xml an effect is created that inherits from a single default
Line 40: Line 42:
system. The parameters created are:  
system. The parameters created are:  


* material active, ambient, diffuse, specular, emissive,
* material active, ambient, diffuse, specular, emissive, shininess, color mode
shininess, color mode
# blend active, source, destination
* blend active, source, destination
# shade-model
* shade-model
# cull-face
* cull-face
* rendering-hint
* rendering-hint
* texture type, image, filter, wrap-s, wrap-t
* texture type, image, filter, wrap-s, wrap-t


=Specifying Custom Effects=
== Specifying custom effects ==
You can specify the effects that will be used by FlightGear as the
You can specify the effects that will be used by FlightGear as the
base effect when it creates terrain and model effects.
base effect when it creates terrain and model effects.
Line 54: Line 55:
In the terrain materials.xml, an "effect" property specifies the name
In the terrain materials.xml, an "effect" property specifies the name
of the model to use.
of the model to use.
In model .xml files, A richer syntax is supported. [TO BE DETERMINED]


Material animations will be implemented by creating a new effect
Material animations will be implemented by creating a new effect
Line 61: Line 60:
will be animated.
will be animated.


=Examples=
== Examples ==
The Effects directory contains the effects definitions; look there for
The $FGDATA/Effects directory contains the effects definitions; look there for
examples. Effects/crop.eff is a good example of a complex effect.
examples. Effects/crop.eff is a good example of a complex effect.


=Application=
== Application ==
To apply an effect to a model or part of a model use:
To apply an effect to a model or part of a model use:


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<effect>
<effect>
<inherits-from>Effects/light-cone</inherits-from>
  <inherits-from>Effects/light-cone</inherits-from>
<object-name>Cone</object-name>
  <object-name>Cone</object-name>
</effect>
</effect>
</syntaxhighlight>
</syntaxhighlight>


Line 78: Line 77:
The effect does not need the file extension.
The effect does not need the file extension.


Note that effects cannot be applied to groups, the objects must be specified explicit.
=== Parameters in model file ===
 
===Parameters in model file===


Parameters can be put into the model files effect application as well. But only bool, int, float, string can be used there.
Parameters can be put into the model files effect application as well. But only bool, int, float, string can be used there.


===Chrome old usage===
=== Chrome old usage ===


Chrome, although now implemented as an effect, still retains the old method of application:
Chrome, although now implemented as an effect, still retains the old method of application:


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<animation>
<animation>
<type>shader</type>
  <type>shader</type>
<shader>chrome</shader>
  <shader>chrome</shader>
<texture>glass_shader.png</texture>
  <texture>glass_shader.png</texture>
<object-name>windscreen</object-name>
  <object-name>windscreen</object-name>
</animation>
</animation>
</syntaxhighlight>
</syntaxhighlight>


in order to maintain backward compatibility.
in order to maintain backward compatibility.


=The xml tags of an effect=
== Reload effects at runtime ==
To reload an effect applied in a model xml file (e.g. some parameters and what it enherits from) just go into debug menu and select Reload Model.
 
To reload the entire effect framework including eff files, go into menu and debug and configure development extensions and reload shaders. This is broken in 2020.1 though, but works in earlier FG versions.
 
== The XML tags of an effect ==


==name==
=== name ===
The name of the effect
The name of the effect


==inherits-from==
=== inherits-from ===
One feature not fully illustrated in the sample below is that
One feature not fully illustrated in the sample below is that
effects can inherit from each other. The parent effect is listed in
effects can inherit from each other. The parent effect is listed in
Line 127: Line 129:
parameters section.
parameters section.


==Parameters==
=== parameters ===
Custom parameters that controls the effect.
Custom parameters that controls the effect.


Note that parameters can use the <use> tags to enable properties to specify the values.
Note that parameters can use the <use> tags to enable properties to specify the values.


==Technique==
=== generate ===
 
Often shader effects need tangent vectors to work properly. These
tangent vectors, usually called tangent and binormal, are computed
on the CPU and given to the shader as vertex attributes. These
vectors are computed on demand on the geometry using the effect if
the 'generate' clause is present in the effect file.
 
Example :
 
<syntaxhighlight lang="xml">
<generate>
  <tangent type="int">6</tangent>
  <binormal type="int">7</binormal>
  <normal type="int">8</normal>
</generate>
</syntaxhighlight>
 
Valid subnodes of 'generate' are 'tangent', 'binormal' or 'normal'.
The integer value of these subnode is the index of the attribute
that will hold the value of the vec3 vector.
 
Normal is really redundant and should not be used, as that is already generated from loading the mesh.
 
The generate clause is located under PropertyList in the xml file.
 
In order to be available for the vertex shader, these data should
be bound to an attribute in the program clause, like this :
 
<syntaxhighlight lang="xml">
<program>
  <vertex-shader>my_vertex_shader</vertex-shader>
  <attribute>
    <name>my_tangent_attribute</name>
    <index>6</index>
  </attribute>
  <attribute>
    <name>my_binormal_attribute</name>
    <index>7</index>
  </attribute>
</program>
</syntaxhighlight>
 
attribute names are whatever the shader use. The index is the one
declared in the 'generate' clause. So because generate/tangent has
value 6 and my_tangent_attribute has index 6, my_tangent_attribute
holds the tangent value for the vertex.
 
=== technique ===
A certain way of rendering this effect. Different pipelines typically have their own techniques.
A certain way of rendering this effect. Different pipelines typically have their own techniques.


===predicate===
==== scheme ====
Used by the [[Compositor]] to choose which implementation of an Effect to render. For example, if a Compositor scene pass specifies the <code>test-scheme</code> scheme, all techniques that use <code>test-scheme</code> will be used to render the pass. If an Effect doesn't contain a technique that implements this scheme, the object will be ignored and not rendered on that pass. Techniques with no scheme are considered ''default'' and will be used by scene passes when no explicit scheme has been provided.
 
==== predicate ====
A technique can contain a predicate that describes the OpenGL
A technique can contain a predicate that describes the OpenGL
functionality required to support the technique. The first
functionality required to support the technique. The first
Line 152: Line 205:
The proper way to test whether to enable a shader-based technique is:
The proper way to test whether to enable a shader-based technique is:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<predicate>
<predicate>
  <and>
  <and>
<property>/sim/rendering/shader-effects</property>
    <property>/sim/rendering/shader-effects</property>
<less-equal>
    <less-equal>
  <value type="float">1.0</value>
      <value type="float">1.0</value>
  <shader-language/>
      <shader-language/>
</less-equal>
    </less-equal>
  </and>
  </and>
</predicate>
</predicate>
</syntaxhighlight>
</syntaxhighlight>


Line 167: Line 220:
like this :
like this :
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
    <predicate>
<predicate>
      <and>
  <and>
        <property>/sim/rendering/shader-effects</property>
    <property>/sim/rendering/shader-effects</property>
<less-equal>
    <less-equal>
  <value type="float">2.0</value>
      <value type="float">2.0</value>
  <float-property>/sim/rendering/quality-level</float-property>
      <float-property>/sim/rendering/quality-level</float-property>
</less-equal>
    </less-equal>
<!-- other predicate conditions -->
    <!-- other predicate conditions -->
      </and>
  </and>
    </predicate>
</predicate>
</syntaxhighlight>
</syntaxhighlight>
      
      
Line 187: Line 240:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<predicate>
<predicate>
<and>
  <and>
  <property>/sim/rendering/shaders/quality-level</property>
    <property>/sim/rendering/shaders/quality-level</property>
  <property>/sim/rendering/shaders/model</property>
    <property>/sim/rendering/shaders/model</property>
  <or>
    <or>
<less-equal>
      <less-equal>
  <value type="float">2.0</value>
        <value type="float">2.0</value>
  <glversion/>
        <glversion/>
</less-equal>
      </less-equal>
<and>
      <and>
  <extension-supported>GL_ARB_shader_objects</extension-supported>
        <extension-supported>GL_ARB_shader_objects</extension-supported>
  <extension-supported>GL_ARB_shading_language_100</extension-supported>
        <extension-supported>GL_ARB_shading_language_100</extension-supported>
  <extension-supported>GL_ARB_vertex_shader</extension-supported>
        <extension-supported>GL_ARB_vertex_shader</extension-supported>
  <extension-supported>GL_ARB_fragment_shader</extension-supported>
        <extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
      </and>
  </or>
    </or>
</and>
  </and>
  </predicate>
</predicate>
</syntaxhighlight>
</syntaxhighlight>


===pass===
==== pass ====
A technique can consist of several passes. A pass is basically an Open
A technique can consist of several passes. A pass is basically an Open
Scene Graph StateSet. Ultimately all OpenGL and OSG modes and state
Scene Graph StateSet. Ultimately all OpenGL and OSG modes and state
Line 219: Line 272:


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
  <blend>
<blend>
<active><use>blend/active</use></active>
  <active><use>blend/active</use></active>
<source>src-alpha</source>
  <source>src-alpha</source>
<destination>one-minus-src-alpha</destination>
  <destination>one-minus-src-alpha</destination>
  </blend>
</blend>
</syntaxhighlight>
</syntaxhighlight>


Line 234: Line 287:
constant. For example:
constant. For example:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<uniform>
<uniform>
<name>ColorsTex</name>
  <name>ColorsTex</name>
<type>sampler-1d</type>
  <type>sampler-1d</type>
<value type="int">2</value>
  <value type="int">2</value>
</uniform>
</uniform>
</syntaxhighlight>
</syntaxhighlight>
* The name of a property in the parameters section can be
* The name of a property in the parameters section can be
Line 244: Line 297:
section:
section:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<material>
<material>
<ambient><use>material/ambient</use></ambient>
  <ambient><use>material/ambient</use></ambient>
</material>
</material>
</syntaxhighlight>
</syntaxhighlight>
Then, in the parameters section of the effect:
Then, in the parameters section of the effect:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<parameters>
<parameters>
<material>
  <material>
<ambient type="vec4d">0.2 0.2 0.2 1.0</ambient>
    <ambient type="vec4d">0.2 0.2 0.2 1.0</ambient>
</material>
  </material>
</parameters>
</parameters>
</syntaxhighlight>
</syntaxhighlight>
It's worth pointing out that the "material" property in a
It's worth pointing out that the "material" property in a
Line 270: Line 323:
YET]. For example:
YET]. For example:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<parameters>
<parameters>
<chrome-light><use>/rendering/scene/chrome-light</use></chrome-light>
  <chrome-light><use>/rendering/scene/chrome-light</use></chrome-light>
</parameters>
</parameters>
</syntaxhighlight>
</syntaxhighlight>
The type is determined by what is expected by the technique
The type is determined by what is expected by the technique
Line 281: Line 334:
changes.
changes.


====lighting====
===== lighting =====
true or false
true or false


====material====
===== material =====
children: active, ambient, ambient-front, ambient-back, diffuse,
children: active, ambient, ambient-front, ambient-back, diffuse,
diffuse-front, diffuse-back, specular, specular-front,
diffuse-front, diffuse-back, specular, specular-front,
Line 290: Line 343:
shininess-front, shininess-back, color-mode
shininess-front, shininess-back, color-mode


====blend====
===== blend =====
Children: active, source, destination, source-rgb, source-alpha, destination-rgb, destination-alpha
Children: active, source, destination, source-rgb, source-alpha, destination-rgb, destination-alpha


Children values: dst-alpha, dst-color, one, one-minus-dst-alpha, one-minus-dst-color, one-minus-src-alpha, one-minus-src-color, src-alpha, src-alpha-saturate, src-color, constant-color, one-minus-constant-color, constant-alpha, one-minus-constant-alpha, zero
Children values: dst-alpha, dst-color, one, one-minus-dst-alpha, one-minus-dst-color, one-minus-src-alpha, one-minus-src-color, src-alpha, src-alpha-saturate, src-color, constant-color, one-minus-constant-color, constant-alpha, one-minus-constant-alpha, zero


====shade-model====
Example:
<syntaxhighlight lang="xml">
<blend>
  <active>true</active>
  <source>one-minus-dst-alpha</source>
  <destination>src-alpha-saturate</destination>
</blend>
</syntaxhighlight>
 
===== blend (simple) =====
A blend tag with 0 will do nothing.
A blend tag with 1 will do the same as source-alpha: one-minus-dst-alpha, in other words it will enable z transparency using alpha from the fragment shader.
 
Example:
<syntaxhighlight lang="xml">
<blend>1</blend>
</syntaxhighlight>
 
===== shade-model =====
flat or smooth
flat or smooth


====cull-face====
===== cull-face =====
front, back, front-back, off
front, back, front-back, off


====texture-unit====
===== texture-unit =====
unit: integer denoting which unit it is
 
image: the texture path
 
images: multiple texture paths
 
type: 2d, noise, cubemap, 3d (3d was added in 2020.1 and is used for layers of 2d textures defining a volumetric 3d texture)
 
filter: linear, linear-mipmap-linear, linear-mipmap-nearest", nearest, nearest-mipmap-linear, nearest-mipmap-nearest
 
mag-filter: linear, linear-mipmap-linear, linear-mipmap-nearest", nearest, nearest-mipmap-linear, nearest-mipmap-nearest
 
wrap: repeat, clamp-to-edge, clamp-to-border, clamp, mirror
 
internal-format: normalized
 
environment: mode, color
:mode: add,blend,decal,modulate,replace
:color: rgba
 
texenv-combine: replace, modulate, add, add-signed, interpolate, subtract, dot3-rgb, dot3-rgba
 
texenv-combine: combine-rgb, combine-alpha, source0-rgb, source1-rgb, source2-rgb, source0-alpha, source1-alpha,source2-alpha,operand0-rgb,operand1-rgb,operand2-rgb,operand0-alpha,operand1-alpha,operand2-alpha,scale-rgb,scale-alpha
 
point-sprite: true, false
 
mipmap-control functions: auto, average, sum, product, min, max
 
texgen:
:mode: object-linear, eye-linear, sphere-map, normal-map, reflection-map
:planes: s, t, r, q as doubles
 
Example:
Example:


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
                <texture-unit>
<texture-unit>
                        <unit>3</unit>
  <unit>3</unit>
<image>Textures/Terrain/void.png</image>
  <image>Textures/Terrain/void.png</image>
<type>2d</type>
  <type>2d</type>
<filter>linear-mipmap-linear</filter>
  <filter>linear-mipmap-linear</filter>
                        <mag-filter>linear-mipmap-linear</mag-filter>
  <mag-filter>linear-mipmap-linear</mag-filter>
<wrap-s>repeat</wrap-s>
  <wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
  <wrap-t>repeat</wrap-t>
                        <wrap-r>repeat</wrap-r>
  <wrap-r>repeat</wrap-r>
<internal-format>normalized</internal-format>
  <internal-format>normalized</internal-format>
                        <mipmap-control>
  <mipmap-control>
                            <function-r>average</function-r>
    <function-r>average</function-r>
    <function-g>min</function-g>
    <function-g>min</function-g>
                            <function-b>sum</function-b>
    <function-b>sum</function-b>
    <function-a>product</function-a>
    <function-a>product</function-a>
                        </mitmap-control>
  </mipmap-control>
</texture-unit>
  <environment>
    <mode>decal</mode>
    <color>0.0 0.1 0.6 1.0</color>
  </environment>
  <point-sprite>true</point-sprite>
  <texenv-combine>operand0-rgb</texenv-combine>
  <texgen>
    <mode>S</mode>
    <planes>0.075, 0.0, 0.0, 0.5</planes>
  </texgen>
</texture-unit>
</syntaxhighlight>
</syntaxhighlight>


====vertex-program-two-side====
Textures of type 3d has to be packed on the x axis. Here is an example: [https://raw.githubusercontent.com/sebh/TileableVolumeNoise/master/Examples/noiseErosionPacked.jpg noiseErosionPacked.jpg]
 
===== vertex-program-two-side =====
true or false
true or false


====polygon-mode====
===== polygon-mode =====
children: front, back
children: front, back


Valid values:  fill, line, point
Valid values:  fill, line, point


====vertex-program-point-size====
===== vertex-program-point-size =====
true, false
true, false


====uniform====
===== uniform =====
Data accessible by shaders.
Data accessible by shaders.
=====name=====


=====type=====
name: the name
bool, int, float, float-vec3, float-vec4, sampler-1d, sampler-2d, sampler-3d, sampler-1d-shadow, sampler-2d-shadow, sampler-cube


====alpha-test====
type: bool, int, float, float-vec3, float-vec4, sampler-1d, sampler-2d, sampler-3d, sampler-1d-shadow, sampler-2d-shadow, sampler-cube


=====active=====
===== alpha-test =====
true, false
 
active: true, false


=====comparison=====
comparison: never, less, equal, lequal, greater, notequal, gequal, always
never, less, equal, lequal, greater, notequal, gequal, always


=====reference=====
reference: 0 to 1
?


====render-bin====
===== render-bin =====
Sent to OSG.
Sent to OSG.
=====bin-number=====
This is an integer defining the order stuff will be rendered in, it can be negative also.


=====bin-name=====
bin-number: This is an integer defining the order stuff will be rendered in, it can be negative also.
RenderBin, DepthSortedBin


====rendering-hint====
bin-name: RenderBin, DepthSortedBin
 
===== rendering-hint =====
Sent to OSG.
Sent to OSG.


Line 374: Line 485:
default = inherit renderbin details from parent node
default = inherit renderbin details from parent node


====program====
===== depth =====
 
* function: Specifies the depth comparison function. Equivalent to [https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDepthFunc.xhtml <tt>glDepthFunc</tt>].
* near, far: Specify the mapping of depth values from normalized device coordinates to window coordinates. Equivalent to [https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDepthRange.xhtml <tt>glDepthRange</tt>]
* write-mask: Whether to write to the depth buffer or not.
* enabled: Whether depth testing is enabled or not.
 
===== define =====
 
Injects a <tt>#define</tt> preprocessor directive into the shaders used in this pass. It is then possible to create logic around this define using conventional preprocessor directives like <tt>#ifdef</tt>, <tt>#endif</tt>, etc. Keep in mind that shaders must import the define before being able to use it. For example, for a define named <tt>USE_TEXTUREMAPPING</tt>, the following GLSL code must be placed right after the <tt>#version</tt> directive:
<syntaxhighlight lang="glsl">
#pragma import_defines(USE_TEXTUREMAPPING)
</syntaxhighlight>
 
* name: Name of the define.
* value: Value of the define (optional).
 
===== program =====
* vertex-shader
* vertex-shader
* geometry-shader
* geometry-shader
Line 380: Line 508:
* attribute
* attribute
* geometry-vertices-out: integer, max number of vertices emitted by geometry shader
* geometry-vertices-out: integer, max number of vertices emitted by geometry shader
* geometry-input-type - points, lines, lines-adjacency, triangles, triangles-adjacency
* geometry-input-type: points, lines, lines-adjacency, triangles, triangles-adjacency
* geometry-output-type - points, line-strip, triangle-strip
* geometry-output-type: points, line-strip, triangle-strip
 
* uniform-block-binding: has name and index (since 2020.1)
===Generate===


Often shader effects need tangent vectors to work properly. These
example:
tangent vectors, usually called tangent and binormal, are computed
on the CPU and given to the shader as vertex attributes. These
vectors are computed on demand on the geometry using the effect if
the 'generate' clause is present in the effect file. Exemple :


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<generate>
<program>
<tangent type="int">6</tangent>
  <vertex-shader n="0">Shaders/lcd.vert</vertex-shader>
<binormal type="int">7</binormal>
  <fragment-shader n="0">Shaders/lcd.frag</fragment-shader>
<normal type="int">8</normal>
  <fragment-shader n="1">Shaders/noise.frag</fragment-shader>
</generate>
  <fragment-shader n="2">Shaders/filters-ALS.frag</fragment-shader>
</program>
</syntaxhighlight>
</syntaxhighlight>


Valid subnodes of 'generate' are 'tangent', 'binormal' or 'normal'.
See this page for more about shaders: [[Howto:Shader programming in FlightGear]]
The integer value of these subnode is the index of the attribute
that will hold the value of the vec3 vector.


The generate clause is located under PropertyList in the xml file.
== Uniforms passed to shaders outside the XML effect framework ==
 
In order to be available for the vertex shader, these data should
be bound to an attribute in the program clause, like this :
 
<syntaxhighlight lang="xml">
<program>
<vertex-shader>my_vertex_shader</vertex-shader>
<attribute>
<name>my_tangent_attribute</name>
<index>6</index>
</attribute>
<attribute>
<name>my_binormal_attribute</name>
<index>7</index>
</attribute>
</program>
</syntaxhighlight>
 
attribute names are whatever the shader use. The index is the one
declared in the 'generate' clause. So because generate/tangent has
value 6 and my_tangent_attribute has index 6, my_tangent_attribute
holds the tangent value for the vertex.


=Uniforms passed to shaders outside the xml effect framework=
Some uniforms are passed from C++ directly by the [[Compositor]], [[WS 3.0]], and others. See [[Compositor#Built-in uniforms|Compositor built-in uniforms]].


{| class="wikitable"
== Related content ==
!Name
=== Forum topics ===
!Type
* {{forum link|t=37364|title=Application of effects}} - Testing which kind of groups an effect can be applied to and when
!Purpose
|-
|<tt>fg_ViewMatrix</tt>
|<tt>mat4</tt>
|In fullscreen pass only, view matrix used to transform the screen position to view direction
|-
|<tt>fg_ViewMatrixInverse</tt>
|<tt>mat4</tt>
|In fullscreen pass only, view matrix inverse used to transform the screen position to view direction
|-
|<tt>fg_ProjectionMatrixInverse</tt>
|<tt>mat4</tt>
|In fullscreen pass only, projection matrix inverse used to transform the screen position to view direction
|-
|<tt>fg_CameraPositionCart</tt>
|<tt>vec3</tt>
|Position of the camera in world space, expressed in cartesian coordinates
|-
|<tt>fg_CameraPositionGeod</tt>
|<tt>vec3</tt>
|Position of the camera in world space, expressed in geodesic coordinates (longitude in radians, latitude in radians, elevation in meters)
|-
|<tt>fg_SunAmbientColor</tt>
|<tt>vec4</tt>
|
|-
|<tt>fg_SunDiffuseColor</tt>
|<tt>vec4</tt>
|
|-
|<tt>fg_SunSpecularColor</tt>
|<tt>vec4</tt>
|
|-
|<tt>fg_SunDirection</tt>
|<tt>vec3</tt>
|
|-
|<tt>fg_FogColor</tt>
|<tt>vec4</tt>
|
|-
|<tt>fg_FogDensity</tt>
|<tt>float</tt>
|
|-
|<tt>fg_ShadowNumber</tt>
|<tt>int</tt>
|
|-
|<tt>fg_ShadowDistances</tt>
|<tt>vec4</tt>
|
|-
|<tt>fg_DepthInColor</tt>
|<tt>bool</tt>
|Tells if the depth is stored in a depth texture or a color texture
|-
|<tt>fg_Planes</tt>
|<tt>vec3</tt>
|Used to convert the value of the depth buffer to a depth that can be used to compute the eye space position of the fragment
|-
|<tt>fg_BufferSize</tt>
|<tt>vec2</tt>
|Dimensions of the buffer, used to convert gl_FragCoord into the range [0..1][0..1]
|-
|<tt>osg_ViewMatrix</tt>
|<tt>mat4</tt>
|Defined by OSG, used only when working on actual geometry
|-
|<tt>osg_ViewMatrixInverse</tt>
|<tt>mat4</tt>
|Defined by OSG, used only when working on actual geometry
|-
|<tt>osg_SimulationTime</tt>
|<tt>float</tt>
|Defined by OSG
|}


[[Category:Shader development]]
[[Category:Shader development]]

Latest revision as of 13:43, 7 February 2024

The Effect framework as per FlightGear version 2020.3

Effects describe the graphical appearance of 3D objects and scenery in FlightGear. The main motivation for effects is to support OpenGL shaders and to provide different implementations for graphics hardware of varying capabilities. Effects are similar to DirectX effects files and Ogre3D material scripts.

An effect is a property list. The property list syntax is extended with new "vec3d" and "vec4d" types to support common computer graphics values. Effects are read from files with a ".eff" extension or can be created on-the-fly by FlightGear at runtime. An effect consists of a "parameters" section followed by "technique" descriptions. The "parameters" section is a tree of values that describe, abstractly, the graphical characteristics of objects that use the effect. Techniques refer to these parameters and use them to set OpenGL state or to set parameters for shader programs. The names of properties in the parameter section can be whatever the effects author chooses, although some standard parameters are set by FlightGear itself. On the other hand, the properties in the techniques section are all defined by the FlightGear.

Default effects in terrain materials and models

Effects for terrain work in this way: for each material type in materials.xml an effect is created that inherits from a single default terrain effect, Effects/terrain-default.eff. The parameters section of the effect is filled in using the ambient, diffuse, specular, emissive, shininess, and transparent fields of the material. The parameters image, filter, wrap-s, and wrap-t are also initialized from the material xml. Seperate effects are created for each texture variant of a material.

Model effects are created by walking the OpenSceneGraph scene graph for a model and replacing nodes (osg::Geode) that have state sets with node that uses an effect instead. Again, a small effect is created with parameters extracted from OSG objects; this effect inherits, by default, from Effects/model-default.eff. A larger set of parameters is created for model effects than for terrain because there is more variation possible from the OSG model loaders than from the terrain system. The parameters created are:

  • material active, ambient, diffuse, specular, emissive, shininess, color mode
  1. blend active, source, destination
  2. shade-model
  3. cull-face
  • rendering-hint
  • texture type, image, filter, wrap-s, wrap-t

Specifying custom effects

You can specify the effects that will be used by FlightGear as the base effect when it creates terrain and model effects.

In the terrain materials.xml, an "effect" property specifies the name of the model to use.

Material animations will be implemented by creating a new effect that inherits from one in a model, overriding the parameters that will be animated.

Examples

The $FGDATA/Effects directory contains the effects definitions; look there for examples. Effects/crop.eff is a good example of a complex effect.

Application

To apply an effect to a model or part of a model use:

<effect>
  <inherits-from>Effects/light-cone</inherits-from>
  <object-name>Cone</object-name>
</effect>

where <inherits-from> </inherits-from> contains the path to the effect you want to apply. The effect does not need the file extension.

Parameters in model file

Parameters can be put into the model files effect application as well. But only bool, int, float, string can be used there.

Chrome old usage

Chrome, although now implemented as an effect, still retains the old method of application:

<animation>
  <type>shader</type>
  <shader>chrome</shader>
  <texture>glass_shader.png</texture>
  <object-name>windscreen</object-name>
</animation>

in order to maintain backward compatibility.

Reload effects at runtime

To reload an effect applied in a model xml file (e.g. some parameters and what it enherits from) just go into debug menu and select Reload Model.

To reload the entire effect framework including eff files, go into menu and debug and configure development extensions and reload shaders. This is broken in 2020.1 though, but works in earlier FG versions.

The XML tags of an effect

name

The name of the effect

inherits-from

One feature not fully illustrated in the sample below is that effects can inherit from each other. The parent effect is listed in the "inherits-from" form. The child effect's property tree is overlaid over that of the parent. Nodes that have the same name and property index -- set by the "n=" attribute in the property tag -- are recursively merged. Leaf property nodes from the child have precedence. This means that effects that inherit from the example effect below could be very short, listing just new parameters and adding nothing to the techniques section; alternatively, a technique could be altered or customized in a child, listing (for example) a different shader program. An example showing inheritance Effects/crop.eff, which inherits some if its values from Effects/terrain-default.eff.

FlightGear directly uses effects inheritance to assign effects to 3D models and terrain. As described below, at runtime small effects are created that contain material and texture values in a "parameters" section. These effects inherit from another effect which references those parameters in its "techniques" section. The derived effect overrides any default values that might be in the base effect's parameters section.

parameters

Custom parameters that controls the effect.

Note that parameters can use the <use> tags to enable properties to specify the values.

generate

Often shader effects need tangent vectors to work properly. These tangent vectors, usually called tangent and binormal, are computed on the CPU and given to the shader as vertex attributes. These vectors are computed on demand on the geometry using the effect if the 'generate' clause is present in the effect file.

Example :

<generate>
  <tangent type="int">6</tangent>
  <binormal type="int">7</binormal>
  <normal type="int">8</normal>
</generate>

Valid subnodes of 'generate' are 'tangent', 'binormal' or 'normal'. The integer value of these subnode is the index of the attribute that will hold the value of the vec3 vector.

Normal is really redundant and should not be used, as that is already generated from loading the mesh.

The generate clause is located under PropertyList in the xml file.

In order to be available for the vertex shader, these data should be bound to an attribute in the program clause, like this :

<program>
  <vertex-shader>my_vertex_shader</vertex-shader>
  <attribute>
    <name>my_tangent_attribute</name>
    <index>6</index>
  </attribute>
  <attribute>
    <name>my_binormal_attribute</name>
    <index>7</index>
  </attribute>
</program>

attribute names are whatever the shader use. The index is the one declared in the 'generate' clause. So because generate/tangent has value 6 and my_tangent_attribute has index 6, my_tangent_attribute holds the tangent value for the vertex.

technique

A certain way of rendering this effect. Different pipelines typically have their own techniques.

scheme

Used by the Compositor to choose which implementation of an Effect to render. For example, if a Compositor scene pass specifies the test-scheme scheme, all techniques that use test-scheme will be used to render the pass. If an Effect doesn't contain a technique that implements this scheme, the object will be ignored and not rendered on that pass. Techniques with no scheme are considered default and will be used by scene passes when no explicit scheme has been provided.

predicate

A technique can contain a predicate that describes the OpenGL functionality required to support the technique. The first technique with a valid predicate in the list of techniques is used to set up the graphics state of the effect. A technique with no predicate is always assumed to be valid. The predicate is written in a little expression language that supports the following primitives:

and, or, equal, less, less-equal glversion - returns the version number of OpenGL extension-supported - returns true if an OpenGL extension is supported property - returns the boolean value of a property float-property - returns the float value of a property, useful inside equal, less or less-equal nodes shader-language - returns the version of GLSL supported, or 0 if there is none.

The proper way to test whether to enable a shader-based technique is:

<predicate>
  <and>
    <property>/sim/rendering/shader-effects</property>
    <less-equal>
      <value type="float">1.0</value>
      <shader-language/>
    </less-equal>
  </and>
</predicate>

There is also a property set by the user to indicate what is the level of quality desired. This level of quality can be checked in the predicate like this :

<predicate>
  <and>
    <property>/sim/rendering/shader-effects</property>
    <less-equal>
      <value type="float">2.0</value>
      <float-property>/sim/rendering/quality-level</float-property>
    </less-equal>
    <!-- other predicate conditions -->
  </and>
</predicate>

The range of /sim/rendering/quality-level is [0..5]

* 2.0 is the threshold for relief mapping effects,
* 4.0 is the threshold for geometry shader usage.

Example:

<predicate>
  <and>
    <property>/sim/rendering/shaders/quality-level</property>
    <property>/sim/rendering/shaders/model</property>
    <or>
      <less-equal>
        <value type="float">2.0</value>
        <glversion/>
      </less-equal>
      <and>
        <extension-supported>GL_ARB_shader_objects</extension-supported>
        <extension-supported>GL_ARB_shading_language_100</extension-supported>
        <extension-supported>GL_ARB_vertex_shader</extension-supported>
        <extension-supported>GL_ARB_fragment_shader</extension-supported>
      </and>
    </or>
  </and>
</predicate>

pass

A technique can consist of several passes. A pass is basically an Open Scene Graph StateSet. Ultimately all OpenGL and OSG modes and state attributes will be accessable in techniques. State attributes -- that is, technique properties that have children and are not just boolean modes -- have an <active> parameter which enables or disables the attribute. In this way a technique can declare parameters it needs, but not enable the attribute at all if it is not needed; the decision can be based on a parameter in the parameters section of the effect. For example, effects that support transparent and opaque geometry could have as part of a technique:

<blend>
  <active><use>blend/active</use></active>
  <source>src-alpha</source>
  <destination>one-minus-src-alpha</destination>
</blend>

So if the blend/active parameter is true blending will be activated using the usual blending equation; otherwise blending is disabled.

Values are assigned to technique properties in several ways:

* They can appear directly in the techniques section as a constant. For example:

<uniform>
  <name>ColorsTex</name>
  <type>sampler-1d</type>
  <value type="int">2</value>
</uniform>

* The name of a property in the parameters section can be referenced using a "use" clause. For example, in the technique section:

<material>
  <ambient><use>material/ambient</use></ambient>
</material>

Then, in the parameters section of the effect:

<parameters>
  <material>
    <ambient type="vec4d">0.2 0.2 0.2 1.0</ambient>
  </material>
</parameters>

It's worth pointing out that the "material" property in a technique specifies part of OpenGL's state, whereas "material" in the parameters section is just a name, part of a hierarchical namespace.

* A property in the parameters section doesn't need to contain a constant value; it can also contain a "use" property. Here the value of the use clause is the name of a node in an external property tree which will be used as the source of a value. If the name begins with '/', the node is in FlightGear's global property tree; otherwise, it is in a local property tree, usually belonging to a model [NOT IMPLEMENTED YET]. For example:

<parameters>
  <chrome-light><use>/rendering/scene/chrome-light</use></chrome-light>
</parameters>

The type is determined by what is expected by the technique attribute that will ultimately receive the value. [There is no way to get vector values out of the main property system yet; this will be fixed shortly.] Values that are declared this way are dynamically updated if the property node changes.

lighting

true or false

material

children: active, ambient, ambient-front, ambient-back, diffuse, diffuse-front, diffuse-back, specular, specular-front, specular-back, emissive, emissive-front, emissive-back, shininess, shininess-front, shininess-back, color-mode

blend

Children: active, source, destination, source-rgb, source-alpha, destination-rgb, destination-alpha

Children values: dst-alpha, dst-color, one, one-minus-dst-alpha, one-minus-dst-color, one-minus-src-alpha, one-minus-src-color, src-alpha, src-alpha-saturate, src-color, constant-color, one-minus-constant-color, constant-alpha, one-minus-constant-alpha, zero

Example:

<blend>
  <active>true</active>
  <source>one-minus-dst-alpha</source>
  <destination>src-alpha-saturate</destination>
</blend>
blend (simple)

A blend tag with 0 will do nothing. A blend tag with 1 will do the same as source-alpha: one-minus-dst-alpha, in other words it will enable z transparency using alpha from the fragment shader.

Example:

<blend>1</blend>
shade-model

flat or smooth

cull-face

front, back, front-back, off

texture-unit

unit: integer denoting which unit it is

image: the texture path

images: multiple texture paths

type: 2d, noise, cubemap, 3d (3d was added in 2020.1 and is used for layers of 2d textures defining a volumetric 3d texture)

filter: linear, linear-mipmap-linear, linear-mipmap-nearest", nearest, nearest-mipmap-linear, nearest-mipmap-nearest

mag-filter: linear, linear-mipmap-linear, linear-mipmap-nearest", nearest, nearest-mipmap-linear, nearest-mipmap-nearest

wrap: repeat, clamp-to-edge, clamp-to-border, clamp, mirror

internal-format: normalized

environment: mode, color

mode: add,blend,decal,modulate,replace
color: rgba

texenv-combine: replace, modulate, add, add-signed, interpolate, subtract, dot3-rgb, dot3-rgba

texenv-combine: combine-rgb, combine-alpha, source0-rgb, source1-rgb, source2-rgb, source0-alpha, source1-alpha,source2-alpha,operand0-rgb,operand1-rgb,operand2-rgb,operand0-alpha,operand1-alpha,operand2-alpha,scale-rgb,scale-alpha

point-sprite: true, false

mipmap-control functions: auto, average, sum, product, min, max

texgen:

mode: object-linear, eye-linear, sphere-map, normal-map, reflection-map
planes: s, t, r, q as doubles

Example:

<texture-unit>
  <unit>3</unit>
  <image>Textures/Terrain/void.png</image>
  <type>2d</type>
  <filter>linear-mipmap-linear</filter>
  <mag-filter>linear-mipmap-linear</mag-filter>
  <wrap-s>repeat</wrap-s>
  <wrap-t>repeat</wrap-t>
  <wrap-r>repeat</wrap-r>
  <internal-format>normalized</internal-format>
  <mipmap-control>
    <function-r>average</function-r>
    <function-g>min</function-g>
    <function-b>sum</function-b>
    <function-a>product</function-a>
  </mipmap-control>
  <environment>
    <mode>decal</mode>
    <color>0.0 0.1 0.6 1.0</color>
  </environment>
  <point-sprite>true</point-sprite>
  <texenv-combine>operand0-rgb</texenv-combine>
  <texgen>
    <mode>S</mode>
    <planes>0.075, 0.0, 0.0, 0.5</planes>
  </texgen>
</texture-unit>

Textures of type 3d has to be packed on the x axis. Here is an example: noiseErosionPacked.jpg

vertex-program-two-side

true or false

polygon-mode

children: front, back

Valid values: fill, line, point

vertex-program-point-size

true, false

uniform

Data accessible by shaders.

name: the name

type: bool, int, float, float-vec3, float-vec4, sampler-1d, sampler-2d, sampler-3d, sampler-1d-shadow, sampler-2d-shadow, sampler-cube

alpha-test

active: true, false

comparison: never, less, equal, lequal, greater, notequal, gequal, always

reference: 0 to 1

render-bin

Sent to OSG.

bin-number: This is an integer defining the order stuff will be rendered in, it can be negative also.

bin-name: RenderBin, DepthSortedBin

rendering-hint

Sent to OSG.

default, opaque, transparent

This basically just sets Renderbin:

opaque = bin 10, depthsortedbin

transparent = bin 0, renderbin

default = inherit renderbin details from parent node

depth
  • function: Specifies the depth comparison function. Equivalent to glDepthFunc.
  • near, far: Specify the mapping of depth values from normalized device coordinates to window coordinates. Equivalent to glDepthRange
  • write-mask: Whether to write to the depth buffer or not.
  • enabled: Whether depth testing is enabled or not.
define

Injects a #define preprocessor directive into the shaders used in this pass. It is then possible to create logic around this define using conventional preprocessor directives like #ifdef, #endif, etc. Keep in mind that shaders must import the define before being able to use it. For example, for a define named USE_TEXTUREMAPPING, the following GLSL code must be placed right after the #version directive:

#pragma import_defines(USE_TEXTUREMAPPING)
  • name: Name of the define.
  • value: Value of the define (optional).
program
  • vertex-shader
  • geometry-shader
  • fragment-shader
  • attribute
  • geometry-vertices-out: integer, max number of vertices emitted by geometry shader
  • geometry-input-type: points, lines, lines-adjacency, triangles, triangles-adjacency
  • geometry-output-type: points, line-strip, triangle-strip
  • uniform-block-binding: has name and index (since 2020.1)

example:

<program>
  <vertex-shader n="0">Shaders/lcd.vert</vertex-shader>
  <fragment-shader n="0">Shaders/lcd.frag</fragment-shader>
  <fragment-shader n="1">Shaders/noise.frag</fragment-shader>
  <fragment-shader n="2">Shaders/filters-ALS.frag</fragment-shader>
</program>

See this page for more about shaders: Howto:Shader programming in FlightGear

Uniforms passed to shaders outside the XML effect framework

Some uniforms are passed from C++ directly by the Compositor, WS 3.0, and others. See Compositor built-in uniforms.

Related content

Forum topics