579
edits
(Created page WIP) |
(→Uniforms passed to shaders outside the xml effect framework: Some new info from Icecode) |
||
(39 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{forum|47|Effects & Shaders}} | |||
{{Rendering}} | |||
The effect framework as per version 2019.1 | The effect framework as per version 2019.1 | ||
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= | =Default Effects in Terrain Materials and Models= | ||
Line 20: | Line 42: | ||
system. The parameters created are: | system. The parameters created are: | ||
* material active, ambient, diffuse, specular, emissive, shininess, color mode | |||
# blend active, source, destination | |||
# shade-model | |||
# cull-face | |||
* rendering-hint | |||
* texture type, image, filter, wrap-s, wrap-t | |||
=Specifying Custom Effects= | =Specifying Custom Effects= | ||
Line 34: | 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. | ||
Material animations will be implemented by creating a new effect | Material animations will be implemented by creating a new effect | ||
Line 42: | Line 61: | ||
=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. | ||
Line 48: | Line 67: | ||
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"> | |||
<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> | |||
where <inherits-from> </inherits-from> contains the path to the effect you want to apply. | where <inherits-from> </inherits-from> contains the path to the effect you want to apply. | ||
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 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: | Chrome, although now implemented as an effect, still retains the old method of application: | ||
<syntaxhighlight lang="xml"> | |||
<animation> | <animation> | ||
<type>shader</type> | <type>shader</type> | ||
Line 66: | Line 94: | ||
<object-name>windscreen</object-name> | <object-name>windscreen</object-name> | ||
</animation> | </animation> | ||
</syntaxhighlight> | |||
in order to maintain backward compatibility. | in order to maintain backward compatibility. | ||
Line 99: | Line 128: | ||
==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. | |||
==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. Exemple : | |||
<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. | |||
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== | ==Technique== | ||
Line 104: | Line 179: | ||
===predicate=== | ===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: | |||
<syntaxhighlight lang="xml"> | |||
<predicate> | |||
<and> | |||
<property>/sim/rendering/shader-effects</property> | |||
<less-equal> | |||
<value type="float">1.0</value> | |||
<shader-language/> | |||
</less-equal> | |||
</and> | |||
</predicate> | |||
</syntaxhighlight> | |||
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 : | |||
<syntaxhighlight lang="xml"> | |||
<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> | |||
</syntaxhighlight> | |||
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: | |||
<syntaxhighlight lang="xml"> | |||
<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> | |||
</syntaxhighlight> | |||
===pass=== | ===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: | |||
<syntaxhighlight lang="xml"> | |||
<blend> | |||
<active><use>blend/active</use></active> | |||
<source>src-alpha</source> | |||
<destination>one-minus-src-alpha</destination> | |||
</blend> | |||
</syntaxhighlight> | |||
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: | |||
<syntaxhighlight lang="xml"> | |||
<uniform> | |||
<name>ColorsTex</name> | |||
<type>sampler-1d</type> | |||
<value type="int">2</value> | |||
</uniform> | |||
</syntaxhighlight> | |||
* The name of a property in the parameters section can be | |||
referenced using a "use" clause. For example, in the technique | |||
section: | |||
<syntaxhighlight lang="xml"> | |||
<material> | |||
<ambient><use>material/ambient</use></ambient> | |||
</material> | |||
</syntaxhighlight> | |||
Then, in the parameters section of the effect: | |||
<syntaxhighlight lang="xml"> | |||
<parameters> | |||
<material> | |||
<ambient type="vec4d">0.2 0.2 0.2 1.0</ambient> | |||
</material> | |||
</parameters> | |||
</syntaxhighlight> | |||
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: | |||
<syntaxhighlight lang="xml"> | |||
<parameters> | |||
<chrome-light><use>/rendering/scene/chrome-light</use></chrome-light> | |||
</parameters> | |||
</syntaxhighlight> | |||
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==== | ====lighting==== | ||
Line 123: | Line 337: | ||
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 | ||
Example: | |||
<syntaxhighlight lang="xml"> | |||
<blend> | |||
<active>true</active> | |||
<source>one-minus-dst-alpha</source> | |||
<destination>src-alpha-saturate</destination> | |||
</blend> | |||
</syntaxhighlight> | |||
====shade-model==== | ====shade-model==== | ||
Line 130: | Line 353: | ||
front, back, front-back, off | front, back, front-back, off | ||
==== | ====texture-unit==== | ||
Example: | |||
= | <syntaxhighlight lang="xml"> | ||
<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> | |||
</mitmap-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> | |||
</syntaxhighlight> | |||
====vertex-program-two-side==== | ====vertex-program-two-side==== | ||
true or false | true or false | ||
====polygon-mode==== | |||
children: front, back | |||
Valid values: fill, line, point | |||
====vertex-program-point-size==== | ====vertex-program-point-size==== | ||
Line 145: | Line 399: | ||
====uniform==== | ====uniform==== | ||
Data accessible by shaders. | Data accessible by shaders. | ||
name: the name | |||
bool, int, float, float-vec3, float-vec4, sampler-1d, sampler-2d, sampler-3d, sampler-1d-shadow, sampler-2d-shadow, sampler-cube | |||
type: bool, int, float, float-vec3, float-vec4, sampler-1d, sampler-2d, sampler-3d, sampler-1d-shadow, sampler-2d-shadow, sampler-cube | |||
====alpha-test==== | ====alpha-test==== | ||
active: true, false | |||
true, false | |||
comparison: never, less, equal, lequal, greater, notequal, gequal, always | |||
never, less, equal, lequal, greater, notequal, gequal, always | |||
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: 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 | ||
====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 | |||
example: | |||
<syntaxhighlight lang="xml"> | |||
<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> | |||
</syntaxhighlight> | |||
See this page for more about shaders: [[Howto:Shader programming in FlightGear]] | |||
=Uniforms passed to shaders outside the xml effect framework= | |||
{| class="wikitable" | |||
!Name | |||
!Type | |||
!Purpose | |||
|- | |||
|<tt>fg_ViewMatrix</tt> | |||
|<tt>mat4</tt> | |||
|In fullscreen pass only, view matrix used to transform from world to view space. Same as osg_ViewMatrix, but for fullscreen pass. | |||
|- | |||
|<tt>fg_ViewMatrixInverse</tt> | |||
|<tt>mat4</tt> | |||
|In fullscreen pass only, view matrix inverse used to transform from view to world space. Same as osg_ViewMatrixInverse but for fullscreen pass. | |||
|- | |||
|<tt>fg_ProjectionMatrixInverse</tt> | |||
|<tt>mat4</tt> | |||
|In fullscreen pass only, projection matrix inverse | |||
|- | |||
|<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> | |||
|For fullscreen pass only, sun information as lightsource[0] is not available in fullscreen pass. | |||
|- | |||
|<tt>fg_SunDiffuseColor</tt> | |||
|<tt>vec4</tt> | |||
|For fullscreen pass only, sun information as lightsource[0] is not available in fullscreen pass. | |||
|- | |||
|<tt>fg_SunSpecularColor</tt> | |||
|<tt>vec4</tt> | |||
|For fullscreen pass only, sun information as lightsource[0] is not available in fullscreen pass. | |||
|- | |||
|<tt>fg_SunDirection</tt> | |||
|<tt>vec3</tt> | |||
|For fullscreen pass only, sun information as lightsource[0] is not available in fullscreen pass. | |||
|- | |||
|<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. Transforms from world to view space. | |||
|- | |||
|<tt>osg_ViewMatrixInverse</tt> | |||
|<tt>mat4</tt> | |||
|Defined by OSG, used only when working on actual geometry. Transforms from view to world space. | |||
|- | |||
|<tt>osg_SimulationTime</tt> | |||
|<tt>float</tt> | |||
|Defined by OSG | |||
|- | |||
|<tt>osg_FrameTime</tt> | |||
|<tt>float</tt> | |||
|Defined by OSG | |||
|- | |||
|<tt>osg_DeltaFrameTime</tt> | |||
|<tt>float</tt> | |||
|Defined by OSG | |||
|- | |||
|<tt>osg_FrameTime</tt> | |||
|<tt>float</tt> | |||
|Defined by OSG | |||
|- | |||
|<tt>osg_FrameNumber</tt> | |||
|<tt>int</tt> | |||
|Defined by OSG | |||
|} | |||
[[Category:Shader development]] | |||
edits