ALS technical notes: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
m (→‎Rain: Formatting)
m (→‎Rain: Added that vector should be inverted if normals are pointing inwards.)
Line 358: Line 358:
By default, the rain splashes impact from above (more precisely the +z direction in model coordinates). This may be inadequate if the aircraft is moving. However, the shader can not know what the airstream at the glass will be, so the impact vector of rain splashes has to be modeled aircraft-side and set via <code>environment/aircraft-effects/splash-vector-x</code> (<code>splash-vector-y</code>, <code>splash-vector-z</code>). These are likewise in model coordinates.
By default, the rain splashes impact from above (more precisely the +z direction in model coordinates). This may be inadequate if the aircraft is moving. However, the shader can not know what the airstream at the glass will be, so the impact vector of rain splashes has to be modeled aircraft-side and set via <code>environment/aircraft-effects/splash-vector-x</code> (<code>splash-vector-y</code>, <code>splash-vector-z</code>). These are likewise in model coordinates.


As long as the length of the splash vector is less than 1, just the impact angle will change, as the length of the vector increases to 2, droplets will also be visibly moving. This allows fine control of the visuals dependent on any number of factors desired. A simple Nasal snipped varying the splash vector with airspeed for the F-16 is given below (but ''do not mindlessly copy and expect to work for any aircraft — it won't!'')
As long as the length of the splash vector is less than 1, just the impact angle will change, as the length of the vector increases to 2, droplets will also be visibly moving. This allows fine control of the visuals dependent on any number of factors desired. A simple Nasal snipped varying the splash vector with airspeed for the F-16 is given below (but ''do not mindlessly copy and expect to work for any aircraft — it won't!''). This example is for normals pointing outwards, if the normals are pointing inwards the vector needs to be inverted.


<syntaxhighlight lang="nasal">
<syntaxhighlight lang="nasal">

Revision as of 20:06, 25 November 2015

Quality level mapping

The rendering quality of ALS effects is controlled by two main sliders, landmass effects and transition effects. Transition effects regulate overlay texturing quality whereas landmass effects regulate all other aspects of procedural texturing like pixel color postprocessing (dust, snow or wet terrain effects) and apparent terrain roughness (bump and parallax mapping).

In addition, specific effects for certain terrain types (water, urban, forest, agriculture...) and models in the scene can be switched on separately. In some cases this may be needed for a consistent visual impression: If a dust effect is used on the terrain, water needs to be rendered using a separate water shader, otherwise it will appear dusty as well. Likewise, if the Rayleigh haze is used in the highest quality terrain effect, then the highest quality water effect needs to be used to see the same Rayleigh scattering effect on the water.

For technical reasons (landmass and transition control the same shader code) the settings are sometimes mutually dependent, i.e. transition quality level 6 won't have any effect unless landmass quality is also level 6.

Transition

The mapping of quality to visuals of the transition slider is

1:

  • Base texture scheme

2:

  • Alternative hires airport keep effect

3:

  • Base and overlay texture, runway effect (if landmass > 4)
  • Supports secondary lights on runway and airport keep

4:

  • Base, overlay and hires texture

6:

  • Base, overlay, hires, detail, grain, dot and rock texture (if landmass > 6)

Landmass

(Quality levels 1 and 2 are reserved to represent fixed pipeline rendering and the classic FG default renderer in an eventually merged rendering GUI, currently however ALS is switched on per checkbox and not by quality level, so they do not have a function).

3:

  • ALS-rendered position-differential haze and light, moonlight

4:

  • Procedural snow cover on terrain
  • Procedural dust and vegetation effects
  • Wet terrain effect with approximate reflection half vector
  • Patchy fog distribution

5:

  • Noise bump-mapping and parallax mapping of terrain

6: (requires transition 6 as well)

  • Wet terrain effect with correct reflection half vector
  • Hires bump mapping and snow patchiness
  • Variable upper haze layer surface
  • Rayleigh haze
  • Secondary lights on all terrain types
  • Slope line and strata effects

ALS secondary lights

The ALS framework supports a generic implementation of landing lights and a searchlight which are based on a framerate friendly computation in screen coordinates, i.e. the lights project correctly only if the light is close to the viewer (typically, that'd be from cockpit view). In other words, this is not a full (rather expensive) computation of light volumes as Rembrandt does it but a much faster test of illuminated screen areas.

Cessna 172 p using generic ALS landing lights

Two landing lights and a searchlight are supported. The landing lights have a fixed position with respect to the aircraft axis (technically, with respect to the default view axis as defined in the respective view), whereas the searchlight follows any offset of the view axis in view mode, i.e. when using the mouse to look around, the searchlight will follow the motion, the landing lights will not. The lights require ALS to run above basic quality level and work on runway and airport keep above transition setting 3 and everywhere else only at highest quality setting. All lights are controlled via properties in /sim/rendering/als-secondary-lights/.

The names of the properties should be self-explanatory, if for instance if use-searchlight=true then the searchlight (which always follows the current view axis) is used.

The properties landing-light1-offset-deg and landing-light2-offset-deg allow to specify angular offsets for the landing light which are then not centered on the view axis. This can be used to simulate one or two landing lights set in the wings.

Secondary lights vertical offset demo

A third offset landing-light3-offset-deg is available which allows for a vertical offset. Especially useful for tail dagger aircraft.

Secondary lights vertical offset settings

The lights can be switched on and off from the property browser for any aircraft without any modifications to the aircraft definition. Implementing them correctly aircraft side thus just involves linking the landing light switches to the ALS control properties and setting the correct angular offsets. Additionally, it is recommended to switch the lights off unless in a cockpit view, as they don't project correctly for any external view.

Range, color, light cone opening angle or intensity of the lights can currently not be configured, and there are no plans to support such a feature in the near future.

All three lights will illuminate fog (if dense enough) and precipitation.

ALS generic lights illuminating dense fog


The grain texture and the rain effect

ALS supports a grain texture for models. This is a semi-transparent overlay texture that works just as its equivalent for terrain texturing and provides the option of generating cm-scale details such as rust or discoloration on a surface without having to use huge textures. An example of a surface rendered with grain texture is the Vinson flightdeck below:

Grain and rain effects on Vinson's flightdeck

This is done using the following effect declaration inheriting from model-combined-deferred.eff as

<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
    <name>flightdeck</name>
    <inherits-from>Effects/model-combined-deferred</inherits-from>
    <parameters>
        <grain-texture-enabled type="int">2</grain-texture-enabled>
        <grain-magnification type="float">0.1</grain-magnification>
        <rain-enabled type="int">2</rain-enabled>
        <texture n="7">
            <image>Models/Geometry/Nimitz/rust_texture.png</image>
            <type>2d</type>
            <filter>linear-mipmap-linear</filter> 
            <wrap-s>repeat</wrap-s>
            <wrap-t>repeat</wrap-t>
            <internal-format>normalized</internal-format>
        </texture>
    </parameters>
</PropertyList>

The grain texture has the number 7 and needs to be enabled by

<grain-texture-enabled type="int">2</grain-texture-enabled>

If the value is set to 1, the grain texture uses the uv-mapping of the underlying surface. If that is very irregular (as in the case of the Vinson flightdeck), alternatively the grain can be mapped in xy-model coordinates if the parameter is set to 2, the uv-mapping of the base texture layer is then discarded.

The resolution of the grain texture with respect to the base coordinate layer is specified by

<grain-magnification type="float">0.1</grain-magnification>

If the number is < 0, the grain resolution is lower than the base layer, if the parameter is > 0, it is higher (note that in the above case, the grain is mapped to (xy) rather than (uv), hence the base size is 1 m, so the grain texture is mapped on a 10x10 m patch on the flightdeck), for which a 1024x1024 pixel texture provides ~1 cm sized details).

Finally, any number greater than 0 passed to

<rain-enabled type="int">2</rain-enabled>

enables the splash effect of raindrops on the surface if it points upward. The surface does not have to be flat for this to work, the effect checks for the surface normal automatically, see the rain enabled for the Citation Bravo.

Thorsten noted about rain splashes: "Works fine here - runway needs to get really wet though before you see them (put the environment slider to max to achieve this quickly, it will take some waiting with just rain on)."

Rain effect on the Citation Bravo


The exhaust flame effect

Rendering proper flames of e.g. afterburners or rocket thrusters with diffuse edges is notoriously difficult - all solutions based on textured models tend to have unnaturally sharp edges. Usually the particle system is used in such cases, however at high velocities this has other issues - particles become easily separated, making flames look disrupted and detached from the exhaust.

ALS includes a dedicated procedural effect in which the flame is rendered by numerically integrating a 3-dim distribution of glowing emitters inside a bounding box (i.e. re-creates the process by which a real flame would be seen). The function which determines the emitter distribution is partially user-controlled so that a wide range of shapes can be generated.

To use the effect, first the bounding box has to be defined. Note that the shape and alignment of the bounding box needs to be standardized for the effect to work, i.e. you need to use either the default bounding box under Aircraft/Generic/Effects/Thruster/ or make a custom one which fits inside the default box at the same location in model coordinates.

To change position, size and orientation of the bounding box to match with the airplane model, translate, scale and rotate animations or model offsets can later be used.

<?xml version="1.0"?>
<PropertyList>
 
	<path>Aircraft/Generic/Effects/Thruster/thrust_flame.ac</path>
	<nopreview/>
 
	 <animation>
  		<type>scale</type>
  		<x-offset>8.0</x-offset>
  		<y-offset>4.0</y-offset>
 		<z-offset>4.0</z-offset>
 	</animation>
 
	<effect>
		<inherits-from>Aircraft/MyAircraft/Models/Effects/my-flame</inherits-from>
		<object-name>Bounding_box</object-name>
	</effect>
 
</PropertyList>



Then, a derived effect (my-flame.eff in the above example) has to be created. Here the parameters for the flame are specified. For instance,

<?xml version="1.0" encoding="utf-8"?>

<PropertyList>
  <name>AB-flame</name>
  <inherits-from>Effects/thrust-flame</inherits-from>
  <parameters>
    <flame_color_low_r type="float">0.95</flame_color_low_r>
    <flame_color_low_g type="float">0.55</flame_color_low_g>
    <flame_color_low_b type="float">0.1</flame_color_low_b>
    <flame_color_high_r type="float">1.0</flame_color_high_r>
    <flame_color_high_g type="float">1.0</flame_color_high_g>
    <flame_color_high_b type="float">1.0</flame_color_high_b>
    <use_shocks type="int">1</use_shocks>
    <use_noise type="int">1</use_noise>
    <thrust_collimation type="float">0.1</thrust_collimation>   
    <thrust_density type="float">1.0</thrust_density>
    <base_flame_density type="float">0.1</base_flame_density>
    <noise_strength type="float">0.2</noise_strength>
    <noise_scale type="float">0.3</noise_scale>
    <deflection_coeff type="float">0.</deflection_coeff>
    <flame_radius_fraction type="float">0.8</flame_radius_fraction>
  </parameters>
</PropertyList>

creates the F-15 afterburner flame shown below:

F-15 afterburner flames


The meaning of the parameter is as follows:

    <use_shocks type="int">1</use_shocks>
    <use_noise type="int">1</use_noise>

are configuration parameters determining whether random noise should be used for the flame and whether shock diamonds should be rendered. Both are modestly expensive, i.e. if they're not used it's better to switch them off (i.e. set to zero).

    <flame_color_low_r type="float">0.95</flame_color_low_r>
    <flame_color_high_r type="float">1.0</flame_color_high_r>
    <base_flame_r type="float">0.8</base_flame_r>

(same for the (g,b) channels) set the color. base_flame refers to the part of the flame which is directly attached to the thruster and usually brightest. flame_color_high refers to the high density part of the flame, flame_color_low refers to the low density parts of the flame. (rgb) values always need to be [0:1]

   <thrust_density type="float">1.0</thrust_density>
   <base_flame_density type="float">0.1</base_flame_density>

determine the overall emitter density in the flame and in the base directly at the thruster respectively. There's no formal upper limit for the parameters, but a flame with density 1 already appears fairly opaque.

    <flame_radius_fraction type="float">0.8</flame_radius_fraction>

governs how much of the bounding box the flame radius at the exhaust nozzle fills. If the flame needs to expand (as for the plume of a thruster operating in vacuum) or needs to bend (as for a flame deflected by the airstream) this parameter needs to be small, if the flame is essentially cylindrical the paramater can be chosen close to 1 to minimize clipping errors. Note that this determines the size of the flame relative to the bounding box - the overall size of the flame should be adjusted by using a scale animation on the bounding box

    <noise_strength type="float">0.2</noise_strength>
    <noise_scale type="float">0.3</noise_scale>

determined how turbulent the flame looks. noise_strength [0:1] determines how prominently the noise influences the flame and noise_scale (in meters relative to the original bounding box) determines how large the visible patches of turbulence are (given that the original bounding box is not larger than 5 m in the longest direction, the parameter should probably kept between 0.1 and 5).

    <shock_frequency>1.0</shock_frequency>

influences at what distance shock diamonds appear in the flame. Useful values are perhaps between 0.2 and 5.

    <thrust_collimation type="float">0.1</thrust_collimation>

should take a value [0:1] and determines how collimated the flame is. For values > 0, the flame is widened - note that this requires a sufficiently small flame radius fraction to avoid clipping errors. For widened flames, the density is automatically lowered and shock diamonds are removed.

    <deflection_coeff type="float">0.</deflection_coeff>

should be somewhere between [0:0.06] and gives a lateral deflection (such as by an airstream) to the flame. Note that this re-positions the origin of the flame in the bounding box to better utilize the bounding box volume, i.e. if you need a dynamical deflection, you also need a translate animation for the bounding box.

Any of those parameters can be adjusted runtime by replacing the value with <use>/my-property</use>. Dependent on how /my-property is created it might be tied though (in particular JSBSim-computed properties are) in which case it is not picked up by the effect framework - you need to copy it via property rule to an untied property then. This allows to render dynamical changes of the flame.

For instance the Space Shuttle main engines use

<?xml version="1.0" encoding="utf-8"?>

<PropertyList>
  <name>ssme-flame</name>
  <inherits-from>Effects/thrust-flame</inherits-from>
  <parameters>
    <flame_color_low_r>0.9</flame_color_low_r>
    <flame_color_low_g>0.7</flame_color_low_g>
    <flame_color_low_b>0.5</flame_color_low_b>
    <flame_color_high_r>0.7</flame_color_high_r>
    <flame_color_high_g>0.7</flame_color_high_g>
    <flame_color_high_b>1.0</flame_color_high_b>
    <base_flame_r type="float">0.8</base_flame_r>
    <base_flame_g type="float">1.0</base_flame_g>
    <base_flame_b type="float">1.0</base_flame_b>
    <use_shocks type="int">1</use_shocks>
    <use_noise type="int">1</use_noise>
    <thrust_collimation><use>/sim/systems/various/ssme-flame-collimation</use></thrust_collimation>   
    <thrust_density><use>/sim/systems/various/ssme-flame-density</use></thrust_density>
    <base_flame_density type="float">1.0</base_flame_density>
    <shock_frequency>1.0</shock_frequency>
    <noise_strength>0.3</noise_strength>
    <noise_scale>0.1</noise_scale>
  </parameters>
</PropertyList>

to simulate the change of flame geometry in the thin upper atmosphere during ascent:

Space Shuttle main engine flames during early ascent Space Shuttle main engine flames during late ascent

Using the deflection parameter, the curved SRB separation motor flames are rendered using

<?xml version="1.0" encoding="utf-8"?>

<PropertyList>
  <name>SRBsep-flame</name>
  <inherits-from>Effects/thrust-flame</inherits-from>
  <parameters>
    <flame_color_low_r type="float">0.95</flame_color_low_r>
    <flame_color_low_g type="float">0.55</flame_color_low_g>
    <flame_color_low_b type="float">0.1</flame_color_low_b>
    <flame_color_high_r type="float">1.0</flame_color_high_r>
    <flame_color_high_g type="float">1.0</flame_color_high_g>
    <flame_color_high_b type="float">1.0</flame_color_high_b>
    <use_shocks type="int">0</use_shocks>
    <use_noise type="int">1</use_noise>
    <thrust_collimation type="float">0.4</thrust_collimation>   
    <thrust_density type="float">1.0</thrust_density>
    <base_flame_density type="float">0.0</base_flame_density>
    <noise_strength type="float">0.7</noise_strength>
    <noise_scale type="float">0.4</noise_scale>
    <deflection_coeff type="float">-0.06</deflection_coeff>
    <flame_radius_fraction type="float">0.1</flame_radius_fraction>
  </parameters>
</PropertyList>


Space Shuttle SRB separation motor flames

Application of the effect is not limited to flames, it can also do heat blur (think a very transparent, high-noise dark emitter distribution) or vapour trails and other smoke.

By itself, the effect does however not compute ambient and diffuse light channels, i.e. for non-emissive distributions lighting is the responsibility of the user. One quick way of obtaining a correct fading of color with light in the scene is to create an untied property based on

/rendering/scene/diffuse/red

and used this to scale all color values.

Important note: Do not use the full (rgb) information in the property tree for ALS, it will produce pronounced color mismatches with the rest of the scene as ALS determines light inside the shader and never uses the properties.

ALS glass effect

As of FlightGear version 3.5, ALS supports a glass effect with dynamic response to the environment which can render, for instance, the splashes of raindrops on the canopy, frost or fogging.

Frost effect Raindrop splashes

The base effect properties are controlled via inheritance and the environment response run-time via properties residing in /environment/aircraft-effects. Derived effects should inherit from Effects/glass. Any surface using the glass effect will automatically register itself as transparent for use in Rembrandt.

The glass effect is primarily intended for interior views. In particular, no external fog or haze is rendered for the glass, i.e. if the effect is used in an outside view, it is the responsibility of the aircraft modeler to take care (e.g. with LOD settings or range animations) that no problems in bad visibility occur.

Why a separate effect for glass seen from inside?

Basically because the two situations are rather different. Slight dirt on the glass against the background of the sky from inside is rather prominent, against the background of the cockpit seen from outside it is not. Visuals from inside are dominated by Mie forward scattering of light, leading to a bright glare effect when looking at dirt, frost, fog or scratches close to the sun. From outside, reflected light rather than transmitted light is dominant. The reflection of any external object on the outside of the glass changes as the aircraft moves, this is not the case for the reflection of the cockpit in the glass seen from the inside.

The viewing situation is also different. From the inside, we usually do not focus the eyes on the plane of the glass but look through it, from the outside the focus of the eyes is often close to the glass surface. For something half a meter before the eye, we also need to apply a lot more resolution and details than for an object typically seen from 10+ meters from the outside.

Add to this that atmospheric fog is never relevant for glass seen from inside but for glass seen from outside, and it suddenly makes sense to use a different effect.

The recommended effect for glass surfaces seen from outside is model-combined-transparent.eff.


Rain

Rain splashes will render automatically when the weather system reports rain via environment/rain-norm. In addition, the user can set rain splashes to render via environment/aircraft-effects/ground-splash-norm (this is intended to allow splashes to be rendered e.g., for water landings of aircraft equipped with floats).

By default, the rain splashes impact from above (more precisely the +z direction in model coordinates). This may be inadequate if the aircraft is moving. However, the shader can not know what the airstream at the glass will be, so the impact vector of rain splashes has to be modeled aircraft-side and set via environment/aircraft-effects/splash-vector-x (splash-vector-y, splash-vector-z). These are likewise in model coordinates.

As long as the length of the splash vector is less than 1, just the impact angle will change, as the length of the vector increases to 2, droplets will also be visibly moving. This allows fine control of the visuals dependent on any number of factors desired. A simple Nasal snipped varying the splash vector with airspeed for the F-16 is given below (but do not mindlessly copy and expect to work for any aircraft — it won't!). This example is for normals pointing outwards, if the normals are pointing inwards the vector needs to be inverted.

var splash_vec_loop = func(){
    var airspeed = getprop("/velocities/airspeed-kt");

    # f16
    var airspeed_max = 120;

    if (airspeed > airspeed_max) {
        airspeed = airspeed_max;
    }

    airspeed = math.sqrt(airspeed / airspeed_max);

    var splash_x = -0.1 - 2 * airspeed;
    var splash_y = 0.0;
    var splash_z = 1.0 - 1.35 * airspeed;

    setprop("/environment/aircraft-effects/splash-vector-x", splash_x);
    setprop("/environment/aircraft-effects/splash-vector-y", splash_y);
    setprop("/environment/aircraft-effects/splash-vector-z", splash_z);

    settimer(func(){
        splash_vec_loop();
    }, 1);
}

Note the timing constant of the loop — running the update per-frame leads to a spurious movement of the coordinate system in which rain is rendered and spoils the effect.

Frost and fogging

Frost on the canopy is rendered when environment/aircraft-effects/frost-level is set in the range from 0 to 1. Again, it is up to the aircraft developer to decide at what exterior conditions frosting should happen and whether the aircraft is equipped with heating to remove the frost again.

Fogging is controlled by environment/aircraft-effects/fog-level in the range 0 to 1. Unless a mask is used, fogging is homogeneous across the whole surface (it is really intended to be used with a mask).

Tint

Tinted glass can be easily created by changing

<glass-tint type="vec4d" n="0"> 1.0 1.0 1.0 1.0</glass-tint>

to any value desired. This will affect all effects assumed outside of the glass layer (frost and rain splashes) but not fogging inside the glass. Use primarily for development and quick tests, don't misuse the alpha value available here, it has odd side effects.

Functional masks

If the glass surface is uv-mapped and textured, it is possible to switch on a mask functionality in the inheritance via

<texture n="2">
	<image>my_mask.png</image>
	<type>2d</type>
	<filter>linear-mipmap-linear</filter>
	<wrap-s>clamp</wrap-s>
	<wrap-t>clamp</wrap-t>
	<internal-format>normalized</internal-format>
</texture>
<use-mask type="int">1</use-mask>
<overlay-color type="vec3d" n="0">1.0 1.0 1.0</overlay-color>

The red channel in my_mask.png controls the strength of fogging, full red corresponds to maximal fogging, no red to zero fogging. This allows to selectively model the position of heaters in the cockpit. Use /environment/aircraft-effects/fog-level to adjust the actual amount of fog runtime.

The green channel of my_mask.png is the amount of reduction of rain in an area. This is intended for airplanes equipped with windshield wipers to partially clear the wiped area of the rain. Whether the windshield wiper is actually on or not is controlled runtime via /environent/aircraft-effects/use-wipers (1 sets wipers to on).

The blue channel of my_mask.png is reserved for an overlay pattern which will be drawn in an optionally specified <overlay-color> vector (white in the example xml above) - the primary function is to render damage on the glass, but with a different color, also dirt or an alternative more finely controlled frost pattern can be used. The strength of the pattern can be adjusted runtime via /environment/aircraft-effects/overlay-alpha, allowing dynamical accumulation of dirt or sudden appearance of damage.

Examples for the result of a fog mask and a damage mask are shown below:

Crack pattern using a damage mask Partial fogging using a mask texture

Note that by default all the runtime switches for the mask are off / set to zero! Remember to to switch them on when testing the effect!

Mie scattering

Most glass effects show prominent Mie forward scattering as in reality, i.e. frost patterns or fogging will appear much more prominent when looking almost towards the sun than under any other angle. While the frost pattern is normally not very prominent and one is able to look through unhindered, this changes substantially when looking into the sun, at which point it almost obscures the view.

Mie scattering of low light on frost Morning sun Mie scattering on fog

For frost and fog, the strength of the effect is set automatically, but for the damage/dirt layer it is under user control at effect design time. Changing the parameter

<overlay-glare type="float">0.5</overlay-glare>

from its default value allows to adjust the strength of the glare when looking through the overlay layer close to the sun.

Internal cockpit reflection

There is support for a reflection of the cockpit interior.

Internal glass cube map reflection


This needs to be provided as a cubemap specific for the airplane and switched on via the flag <use-reflection> set to 1. The relative strength of the reflection can be optionally via <reflection-strength>. The strength of the reflection in the cockpit is dynamically adjusted for a number of factors, among them balance of direct to indirect light, the approximate amount of light falling on the surface seen in the reflection and the amount of direct sunlight falling into the eye.

If the six cubemap faces are called my_cube_map_??.png, then using an effect file called c172p-reflect.eff the inheritance looks like this:

<?xml version="1.0" encoding="utf-8"?>

<PropertyList>
  <name>c172-reflect</name>
  <inherits-from>Effects/glass</inherits-from>
  <parameters>
    <texture n="3">
      <type>cubemap</type>
      <images>
        <positive-x>my_cube_map_px.png</positive-x>
        <negative-x>my_cube_map_nx.png</negative-x>
        <positive-y>my_cube_map_py.png</positive-y>
        <negative-y>my_cube_map_ny.png</negative-y>
        <positive-z>my_cube_map_pz.png</positive-z>
        <negative-z>my_cube_map_nz.png</negative-z>
        </images>
    </texture>
    <use-reflection type="int">1</use-reflection>
    <reflection-strength type="float">1.0</reflection-strength>
  </parameters>
</PropertyList>

The inheritance call includes all surface objects that use the effect.

<effect>
   <inherits-from>Aircraft/c172p/Models/Effects/c172p-reflect</inherits-from>
   <object-name>glas</object-name>
   <object-name>rightwindow</object-name>
   <object-name>leftwindow</object-name>
</effect>


See below (Interior shading), for details on cube_map creation and orientation.

Lightmaps for internal cockpit reflection

If the cockpit is illuminated at night, the reflection map will not show this change by default. However,the glass effect supports a lightmap for the reflection, which can be used in parallel with the lightmap for the panels to show the reflection of a lit panel at night.

Since the reflection map is a cube map, the lightmap for it has to be as well, the syntax is hence

<use-reflection-lightmap type="int">1</use-reflection-lightmap>
<texture n="4">
     <type>cubemap</type>
     <images>
          <positive-x>Models/Effects/interior/reflection/light-px.png</positive-x>     
          <negative-x>Models/Effects/interior/reflection/light-nx.png</negative-x>   
          <positive-y>Models/Effects/interior/reflection/light-py.png</positive-y>     
          <negative-y>Models/Effects/interior/reflection/light-ny.png</negative-y>    
          <positive-z>Models/Effects/interior/reflection/light-pz.png</positive-z>      
          <negative-z>Models/Effects/interior/reflection/light-nz.png</negative-z>      
      </images>
</texture>

The control parameters of the lightmap otherwise parallel those of the Model-combined_effect or the model interior effect described below, i.e. up to four channels can be independently specified on the lightmap.

Troubleshooting

By default, rain and frost are mapped to the shape of the canopy using coordinate systems that adapts to the splash vector and the canopy shape. This requires no particular action aircraft-side except to provide the bare geometry of a canopy/windshield, but may not be satisfactory in all instances - in particular for near vertical cockpit side windows the scheme does poorly.

There are two alternative coordinate maps available in this case, controlled by the parameter

<surface-mapping-scheme type="int">0</surface-mapping-scheme>

If the parameter is changed to 1, the uv-mapping of the surface is used (it has to exist of course). For this to work properly, the uv-mapping needs to be sufficiently regular and roughly preserve the mapped area.

If the parameter is changed to 2, a local orthonormal system based on the normals of the surface is constructed. This no longer takes the splash vector consistently into account and works poorly for surfaces which are flat in the (xy)-plane, but gives decent result for side windows.

The ALS interior model effect

Since the interior of a cockpit is a large part of what a pilot gets to see in-flight, but this interior represents a rather special situation (light is reduced as it falls through windows, it may have artificial light, there is never any fog or haze,...) ALS offers a separate effect to specifically render the interior of a plane.

This effect also includes optional features which will be available at higher quality settings of the model shader.

Interior shadows and tinted glass effect

With FlightGear version 3.5 and above, ALS now supports interior shading; i.e. the sun shining through the windows and casting shadows on the panel.

Interior shading effect

This effect is based on an opacity map - a cube map of textures which tells the renderer where the cockpit is transparent and where not. The opacity map has to be created beforehand, which allows to make it quite detailed. In this map, white stands for a completely transparent surface, black for an opaque surface, colors for tinted glass which will create a colored light spot in the cockpit, grey hues for partial shadowing allowing to paint dirt effects onto the windows, and caustics can be drawn using the alpha channel: (1-alpha) will be used as an enhancement of the light at a certain spot.

The effect is typically declared as derived by inheritance using an effect file such as c172-interior.eff which looks like this

<?xml version="1.0" encoding="utf-8"?>

<PropertyList>
  <name>c172-interior-glass</name>
  <inherits-from>Effects/model-interior</inherits-from>
  <parameters>
	<texture n="4">
	  <type>cubemap</type>
	  <images>
		 <positive-x>Models/Effects/interior/clr_px.png</positive-x>
		 <negative-x>Models/Effects/interior/clr_nx.png</negative-x>
		 <positive-y>Models/Effects/interior/clr_py.png</positive-y>
		 <negative-y>Models/Effects/interior/clr_ny.png</negative-y>
		 <positive-z>Models/Effects/interior/clr_pz.png</positive-z>
		 <negative-z>Models/Effects/interior/clr_nz.png</negative-z>
	  </images>
	</texture>
	<opacity-cube-center type="vec3d" n="0"> 0.5 0.0 0.3</opacity-cube-center>
	<opacity-cube-scale type="vec3d" n="0"> 1.5 0.5 0.7</opacity-cube-scale>
	<opacity-cube-angle type="float">0.0</opacity-cube-angle>
  </parameters>
</PropertyList>

which is called by inheritance in the model.xml file.

Imagine the opacity map as a box surrounding the cockpit and trying to closely follow its contours. The origin in the box needs to be placed into the center of the cockpit, which is what <opacity-cube-center> does. Each of the three dimensions then needs to be stretched to roughly fit the layout of the canopy, this is done by <opacity-cube-scale>.

If opacity map center and scale are wrong, you will still see shadows, but they won't match the real cockpit layout (the lightspot of a window will be seen displaced and at a different size of the real window). Thus, carefully measuring the best box layout in a 3d tool is moderately important.


Aircraft-side the effect is called as

<effect>
   <inherits-from>Aircraft/c172p/Models/Effects/c172p-interior</inherits-from>
   <object-name>Plane.010_0</object-name>
   <object-name>Plane.010_1</object-name>
   <object-name>PilotSeat</object-name>
   <object-name>CopilotSeat</object-name>
   <object-name>panel_1_1</object-name>
   <object-name>InstrumentCover.001</object-name>
   <object-name>doorint_right</object-name>
   <object-name>doorint_left</object-name>
   <object-name>doorhandleint_right</object-name>
   <object-name>doorhandleint_left</object-name>
   <object-name>Panel_0</object-name>
   <object-name>Throttle</object-name>
   <object-name>Mixture</object-name>
   <object-name>Pedestal</object-name>
   <object-name>TrimWheel</object-name>
   <object-name>ParkingBrake</object-name>
   <object-name>BackSeat</object-name>
   <object-name>FuelSelectorFace</object-name>
 </effect>

Each object that you want the shadow effect to fall on must be included in the inheritance.

Unless you supply a path, the cube_.png's need to reside in the same directory as the model.xml where you added the <effect> tag pair that calls c172-interior.eff, not where you put the aircraft_interior.eff.


The orientation of the faces of each cube have to be adjusted based on the positive and negative axis of the model.

For example, using the c172p model as a reference.

The tail, right wing and top on the model are positive inside Blender. So the cube faces are laid out as follows.

Note: Depending on the image's orientation when photographed the rotation direction will vary. This is assuming the images are being taken from the center of the cockpit looking out. Using compass headings to describe how to rotate the images.

px (tail) rotate 90 deg from N or S to W

nx (nose) rotate 90 deg from N or S to E

py (starboard/right) from N do not rotate

ny (port/left) from N rotate 180 deg to S

pz (top) rotate 90 deg from N or S to W

nz (bottom) rotate 90 deg from N or S to W

Cube map layout of the c172p


With Blender, it's pretty easy to create the cubemap.

1. Add a camera where the cubemap will be. Set the FOV to 90 degrees. 2. Set the resolution to 1024x1024 (or any other square, power-of-two size). 3. Hide all lights and windows; disable ambient lighting (set it to black) and turn off ambient occlusion. 4. Set the world color to white. 5. Enable the compositor and add an invert node. 6. Render and save the six views as you would normally. 7. Add dirt, tinted glass color and caustics by hand

This process depends on the model setup but it should work for most aircraft with a few tweaks.

See flightgear-interior-shadow-cubemap-kit for a premade kit to create the cubemap and the .eff sample file to use it.


Important note: Currently (May 2015) the effect does not deal gracefully with child models included into the main model with offsets and/or rotations because these introduce a different coordinate system in which the shadow does not match. The general idea of a code solution is known, but not implemented. Right now this can only be addressed by explicitly positioning child models in the *.ac file and not using any offsets when including them.

ALS flashlight

This effect is meant to imitate a hand held flashlight for use in getting instruments in the cockpit turned on in dark conditions. It is almost identical in nature to ALS searchlight only it is applied using interior-model.eff. It has two user defined light color filters that can be applied and also a user defined light radius setting.

ALS flashlight effect

To implement this effect use

<inherits-from>Effects/model-interior</inherits-from>

A full definition looks like this

<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
  <name>c172-interior</name>
  <inherits-from>Effects/model-interior</inherits-from>
  <parameters>
	<light-filter-one type="vec3d">0.5 0.5 0.5</light-filter-one>
	<light-filter-two type="vec3d">0.9 0.2 0.2</light-filter-two>
	<light-radius type="float">13</light-radius>
  </parameters>
</PropertyList>

In the example above light-filter-one is soft white light and light-filter-two is a soft red light.

After defining as above you can turn it on using the following property

/sim/rendering/als-secondary-lights/use-flashlight = 1 is light-filter-one

/sim/rendering/als-secondary-lights/use-flashlight = 2 is light-filter-two

Implicit lightmap

At lowest quality level, the effect supports an implicit lightmap, i.e. a color range of the basic texture can be selected and declared to act as a lightmap. This is specifically useful to render panel backlighting as in the example below:

An implicit lightmap used to simulate a backlit panel

The effect is off by default and switched on by setting

<implicit-lightmap-enabled type="int">1</implicit-lightmap-enabled>

The following parameters are available:

<implicit-lightmap-tag-color type="vec3d">1.0 1.0 1.0</implicit-lightmap-tag-color>

This sets the base color to be tagged, i.e. if the panel labels to be illuminated at night are white, the color needs to be set to white.

<implicit-lightmap-threshold-low type="float">0.5</implicit-lightmap-threshold-low>
<implicit-lightmap-threshold-high type="float">1.5</implicit-lightmap-threshold-high>

The thresholds determine how similar a color may be to the base color in order to be still illuminated. The measure is the Euklidean distance of the color vectors. The lower thresholds determines when illumination will start to fade, the higher threshold at what distance in color space illumination will no longer take place. The thresholds have to be adapted to the specific situation - the technique works best for high-contrast panels (white labels on black background) and may not work at all for low contrast panels.

<implicit-lightmap-emit-color type="vec3d">1.0 1.0 1.0</implicit-lightmap-emit-color>

The emit color specifies at which color the pixel will show if it is tagged (see above) and the implicit lightmap is on (see below) - set this to the color of the backlight.

<implicit-lightmap-intensity type="float">0.0</implicit-lightmap-intensity>

Finally, the intensity determines how brightly the illuminated pixel will shine.

Irradiance maps

Note: This effect requires higher than minimum model shader quality setting.

In the simplest rendering schemes, diffuse and specular light are assumed to be highly directional (i.e. it illuminates lit surfaces only) while ambient light is taken to be omnidirectional.

In reality, that is hardly ever true. In a typical outside location, ambient light is mainly coming from the sky above (which is why the ground underneath a car is dark even in the absence of directional light when the sky is overcast and the sun is not visible). In an enclosed space (like a room, or an aircraft cockpit), ambient light has to fall through the windows, i.e. is mainly not coming above but falling in horizontally.

The directional dependence is not very strong though, yet it leaves measurable effects. In rendering, this can be accounted for by irradiance maps. In the following, the interior of the C-172p is rendered in the first case using omnidirectional ambient light, in the second case using an irradiance map giving the ambient light the directionality of the cabin windows, i.e. the light falls in predominantly horizontally (in addition, a grain map is superimposed to provide structure). Note how the spatial structure of the roof, looking bland when rendered in omnidirectional light is brought out by the irradiance map.

C-172p cabin interior rendered without irradiance and grain map C-172p cabin interior rendered with irradiance and grain map

Irradiance mapping is configured by the following parameters:

<irradiance-map-type type="int">2</irradiance-map-type>
<irradiance-map-strength type="float">0.5</irradiance-map-strength>

There are several pre-configured irradiance map functions which can be chosen by map type.

0: (default) omndirectional light 1: light predominantly coming from above (most appropriate for fighter cockpits) 2: light predominantly coming from the horizon (most appropriate for GA aircraft)

The strength of the irradiance map regulates how pronounced the asymmetry of the map will be. A strength of zero always makes the light omnidirectional, whereas a strength of 1 implies that no light is coming from any direction 90 degree to the main direction (i.e. for the option 2, a strength of 1.0 means that no ambient light will fall in from above or below and that hence horizontal surfaces will appear pitch black unless direct light falls on them).

Explicit lightmap

Note: This effect requires higher than minimum model shader quality setting.

In addition to the implicit lightmap, it is also possible to explicitly specify a lightmap. The syntax for this exactly parallels the syntax of the Model-combined_effect which supplies lightmaps for the exterior.

For example

<texture n="3">
<image>Aircraft/MyAircraft/Effects/my_lightmap.png</image>
<type>2d</type>
<filter>linear-mipmap-linear</filter>
<wrap-s>clamp</wrap-s>
<wrap-t>clamp</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<lightmap-enabled type="int">1</lightmap-enabled>
<lightmap-multi type="int">0</lightmap-multi>
<lightmap-factor type="float" n="0">1.0</lightmap-factor>
<lightmap-color type="vec3d" n="0"> 1.0 1.0 1.0 </lightmap-color>

sets up a single channel lightmap in which pixel color times the lightmap color provides the illumination. Using the multi-channel function, up to four different maps can be specified in which the (rgba) values of a pixel encode where the light falls and the associated lightmap color what color the illumination takes. Each of these maps can be switched on and off or dimmed in intensity independently.

Grain map

Note: This effect requires higher than minimum model shader quality setting.

The grain map sets a repeating hires overlay texture which can supply a very credible illusion of structure to a surface for cheap. The syntax exactly parallels that of the Model-combined_effect ALS grain feature described above.

For instance, the following

<texture n="7">
<image>Aircraft/Effects/MyGrainmap.png</image>
<type>2d</type>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<grain-texture-enabled type="int">1</grain-texture-enabled>
<grain-magnification type="float">10</grain-magnification>

sets up a grain overlay with a 10-time higher resolution over the base texture layer.

ALS fuselage shadow effect

ALS supports the manipulation of a (simplified) ground shadow. This effect uses an existing simplified shadow animation configuration and by default uses the gear-agl-m property to calculate the ground placement of that simplified shadow.

ALS Shadow

The effect can be applied easily in any aircraft that report the gear-agl-m property by simply adding a declaration inheriting from shadow.eff.

If the aircraft does not support the gear-agl-m property, (notably JSBSim), you need to create a Property Rule to pass a supported AGL data to the gear-agl-m property. In this case we use altitude-agl-ft converted to meters using a property rule configuration file.

For the first example we'll use the "supported gear-agl-m" method for aircraft that don't require a property rule.

Simply add the following inheritance declaration after you declare your shadow animation statement.

<effect>
    <inherits-from>Effects/shadow</inherits-from>
    <object-name>name_of_the_shadow_object</object-name>
</effect>

In the non-ALS simplified shadow code you normally use a "translate" animation to position the shadow on the ground. When using the ALS method you must either remove, comment out, or apply a condition to restrict its use to non ALS shadow applications, because ALS is responsible for computing the shadows ground position.

Here is how we apply a condition to the translation to limit it effect to non-ALS application only.

<!--Translate to ground level  -->
  <animation>
   <type>translate</type>
   <object-name>shadow</object-name>
   <condition>
    <not>
      <property>/sim/rendering/shaders/skydome</property>
    </not>
   </condition>
   <property>/position/altitude-agl-ft</property>
   <factor>-0.3048</factor>
   <center>
     <x-m>0</x-m>
     <y-m>0</y-m>
     <z-m>0</z-m>
   </center>
   <axis>
     <x>0</x>
     <y>0</y>
     <z>1</z>
   </axis>
 </animation>

A complete shadow animation block looks like this.

<PropertyList>

  <animation>
    <!-- opaque objects -->
    <!-- transparent objects -->
    <object-name>shadow</object-name>
    <type>select</type>
    <condition>
      <not>
        <property>/sim/rendering/rembrandt/enabled</property>
      </not>
    </condition>
  </animation>
  
  <effect>
    <inherits-from>Effects/shadow</inherits-from>
    <object-name>shadow</object-name>
  </effect>

  <animation>
    <type>noshadow</type>
    <object-name>shadow</object-name>
  </animation>

  <!-- pitch -->
  <animation>
    <type>rotate</type>
    <object-name>shadow</object-name>
    <property>/orientation/pitch-deg</property>
    <factor>-1.0</factor>
    <center>
      <x-m>0</x-m>
      <y-m>0</y-m>
      <z-m>0</z-m>
    </center>
    <axis>
      <x>0</x>
      <y>1</y>
      <z>0</z>
    </axis>
  </animation>

  <!-- roll -->
  <animation>
    <type>rotate</type>
    <object-name>shadow</object-name>
    <property>/orientation/roll-deg</property>
    <factor>1.0</factor>
    <center>
      <x-m>0</x-m>
      <y-m>0</y-m>
      <z-m>0</z-m>
    </center>
    <axis>
      <x>1</x>
      <y>0</y>
      <z>0</z>
    </axis>
  </animation>

  <!--Translate to ground level  -->
  <animation>
   <type>translate</type>
   <object-name>shadow</object-name>
   <condition>
    <not>
      <property>/sim/rendering/shaders/skydome</property>
    </not>
   </condition>
   <property>/position/altitude-agl-ft</property>
   <factor>-0.3048</factor>
   <center>
     <x-m>0</x-m>
     <y-m>0</y-m>
     <z-m>0</z-m>
   </center>
   <axis>
     <x>0</x>
     <y>0</y>
     <z>1</z>
   </axis>
  </animation>

</PropertyList>

For aircraft requiring a Property Rule there are a couple extra steps.

In aircraft-set.xml you add the property rule call to the "configuration file" in between the PropertyList/sim/systems tag pairs.

	
<property-rule n="101">
  <name>gear_agl-m</name>
  <path>Aircraft/c172p/Systems/gearAGL.xml</path>
</property-rule>

Note: the n="101" needs to be =+100 as -100 is reserved for system wide property rules. In the above example 101 was used because 100 was already being used by a previous property rule definition.

The "configuration file" normally goes in /Systems. In this example we named the configuration file /Systems/gearAGL.xml.

Here is the complete /Systems/gearAGL.xml configuration file.

<?xml version="1.0"?>

<PropertyList>
  <filter>
    <type>gain</type>
    <gain>0.3048</gain>
    <input>/position/altitude-agl-ft</input>
    <reference>6</reference>
    <output>/position/gear-agl-m</output>
  </filter>
</PropertyList>

What the configuration file does is convert the input of altitude-agl-ft to the output of (((altitude-agl-ft)-6)*0.3048) or (convert ft-6 to m) and pass it to /position/gear-agl-m.

See Input and reference properties or values <input> and <reference>.


General comments from forum discussion

Cquote1.png A few aircraft have a fake shadow, in essence a flat silhouette of the aircraft floating maybe a feet above ground. The silhouette get there using a few properties, possibly driving some calculations and basically the same kind of animations as is used to for example animate the control surfaces. I do not remember having seen a list with aircraft using a fake shadow, but I think that for example Helijah's Diamond twin has one. The big drawback with a fake shadow is that it has to float to not get broken through by even the slightest undulations in the ground, while still will not work as soon as there is a slope.
— Johan G (Mon Dec 15). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png As the tree shadow code has shown, it's near-trivial to do the projective geometry not by an animation but in the vertex shader, i.e. fake shadows can be placed where the sun casts them, stretched by the projection, depth adjusted to weather condition and if the current terrain normal is passed, they can even be put co-planar with the local triangle, i.e. they'd project correctly even on sloped runways and terrain. At a computational cost of almost zero, because you just process the four vertices of the shadow quad, and four is a number which isn't even a warm-up exercise for a GPU used to crunch millions of vertices. But of course, it wouldn't be a real shadow, in particular it wouldn't project correctly onto trees and buildings as a stencil buffer or shadow map solution would.
— Thorsten (Mon Dec 15). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png Having said that, it is fairly simple to do. Here's an implementation for the EC-130 which comes with an animation based fake shadow out of the box, switching the shadow projection to a GLSL shader:

The animation just puts the shadow onto the ground. The GLSL code can do some projection of the shadow, i.e. it magnifies a bit for low sun and changes position: The shader can do a full light calculation of the surrounding scene, so the depth of the shadow can be varied according to the ambient to diffuse light balance: Also, once the aircraft is in the air, it projects the shadow along the light ray rather than underneath the aircraft: And of course, all that means shadow depth adjusts to weather conditions - no shadows in overcast skies:

Implementation (using current git) - make the quads displaying the fake shadow inherit from Effects/shadow.eff, don't translate the shadow (the shader expects it to be correctly positioned for the sun in the zenith for an aircraft standing on the runway), don't try to correct for low sun or to adjust shadow texture transparency, the shader just uses the texture alpha channel.
— Thorsten (Tue Dec 16). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png
Where should I put this? Into one of the *.eff files of any aircraft?

-you need the shadow itself as a model (a textured quad). In ac3d (blender,...) that has an object name - in my example shadow_fuselage. You can give it any you want.

-in the aircraft-set.xml (or files included there), animations, effects, sounds,... are declared and models included. In the scope where your shadow quad is included, you declare shadow.eff as your effect. What wlbragg has has done (inheriting a copy of the shadow effect under the aircraft effect directory) is probably more by the book, but not strictly necessary unless you want to pass parameters to the effect.
— Thorsten (Sat Jan 17). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png It works with anything that sets a property how far the gear is off the ground - it works with your home-made Nasal FDM if you like...
— Thorsten (Sat Feb 14). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png
wlbragg wrote in Sat Feb 14, 2015 1:14 am:
 After looking at how slow altitude-agl-ft update is, I don't think it would work very well anyway.
 I'll try the "property rule".
 But now I am curious why I couldn't get altitude-agl-ft to work at all?

If altitude-agl-ft seems to update slowly in the property browser it might be a tied property that can't be listened to so instead it is polled at a lower rate - but the property will actually be updated for each frame or FDM iteration.

This might also explain why you have problems getting its value into the effect - the effect system might also rely on listeners to get updates (I don't know).
— AndersG (Sat Feb 14). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png Yes - you can't pass tied properties to effects. Learned that one the hard way (took me a while to figure out...) That's probably the problem here as well. Okay, then we need an aircraft-side property rule in any case. It doesn't need to be AP (they're updated at FDM rate), we only need it at framerate. I vaguely remember there was a catch that you had to give an index to airplane-side property rules to avoid overriding the system-wide which do e.g. weather - there's documentation on the wiki somewhere, I think in the AP howto.
— Thorsten (Sat Feb 14). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png After setting up two separate aircraft with the simplified shadow effect, here is what I found to work best.

Simply put I used a property rule for for both YSim and JSBSim aircraft and override gear-agl-m with a filter passing altitude-agl-ft to gear-agl-m in both aircraft. The reason for this is to accommodate all the shadow AGL adjustment needed for both ASL-shadows and non-ALS-shadows.

My Cub has two configurations for tire size and thus two different altitude-agl-ft starting points. The c172p also has its own altitude-agl-ft starting point. I guess they would be dependent upon where and how the model designer created the center point of the aircraft.

To accommodate this variability you need to do an offset in the shadow.xml to place the shadow's AGL where you want it. But when using ALS-shadow method it has a tendency to put it where it thinks it needs to go based on the hard code. So you use the offset to position the initial shadow. Then you use the property rule configuration to position the shadow when ALS method takes control of the shadow's AGL.
— wlbragg (Sun Feb 15). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png

ALS 3d shadow volume effect

What might be considered the next level of realism using a relatively "cheap" shadow effect is to use a 3d volume shadow.

ALS 3d Shadow Volume

The procedure to implement the ALS shadow volume is similar to the ALS-shadow above with a few modifications.

First you have to have a 3d shadow volume model of the aircraft you are applying the effect to. This model should be a low poly model that is optimized to be as little of a footprint as possible.

A property rule is required, same as above. This is used to generate the above ground altitude in meters, (altitude-agl-m). The "altitude-agl-m" is used to place the shadow close to the ground in real time at an FDM rate of execution. NOTE: Do not confuse "altitude-agl-m" with the other type of non-3d ALS-shadow property of "gear-agl-m". The shaders involved use these two different properties respectively for the two different effect. They are not interchangeable.

<?xml version="1.0"?>
<PropertyList>
   <filter>
      <type>gain</type>
      <gain>0.3048</gain>
      <input>/position/altitude-agl-ft</input>
      <reference>1.0</reference>
      <output>/position/altitude-agl-m</output>
   </filter>
</PropertyList>

The other difference from the ALS-shadow above is that it uses a different inherited effect. Instead of

<effect>
    <inherits-from>Effects/shadow</inherits-from>
    <object-name>shadow</object-name>
 </effect>

you use

<effect>
    <inherits-from>Effects/shadow-vol</inherits-from>
    <object-name>shadow</object-name>
  </effect>


General comments from forum discussion

Cquote1.png In real-time 3d rendering in general. To be very fast, all tasks are parallelized, so the GPU can crunch every vertex and every pixel independent of what the others do. The price for that to work is that you track only the ray from light (L) to object (O) to eye(E), so if that's the relevant geometry, you don't need to know anything else of the scene, you can get all the reflection angles at the object in one go.

To place a shadow, you want to know whether the ray L-O intersects somewhere else before it illuminates, i.e. evaluate L-O-O-E - and that's no longer factorizable - now at one vertex, you need to know all the others. I.e. a GPU can't evaluate this (raytracing still can easily, but that doesn't run in real time...) - which is where we need various tricks. Which range from very cheap (fake shadows) to very expensive (additional shadow camera or shadow volume creation and stencil buffer passes over the whole scene).


— Thorsten (Tue Feb 17). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png Not an issue - shadow alpha is set by the fragment shader anyway based on time of the day and cloud cover (if there's lots of clouds, you get very faint shadows).

I think the issue is simple - multiple layers are visible where only one should be, so I need to do a first pass over just the shadow to fill the depth buffer and then draw the uppermost layer of the shadow in the second pass. If the shadow volume really is a low poly version of the model, that should be really cheap (on the other hand, if it's a full multi-million poly replica, then... let's say you will notice...). Anyway, I didn't touch fragment work at all yesterday, I just wanted to sort out the geometry.


— Thorsten (Thu Mar 05). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png It's not a shadow, it's a squished volume flat on the ground. Don't fall into the trap of thinking of it as a shadow while developing.

Don't need it. Volume and texture shadow are only different at the vertex stage only - to determine the pixel color, we can follow precisely the same steps.


— Thorsten (Thu Mar 05). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png You have to make it.

It is the same thing as the 3d model of the aircraft except it is (hopefully) low poly. Meaning it has only what is needed to make a 3 dimensional shadow that looks like the original model without all the details (no interior, etc). This is something that really should have been considered back at the beginning of the FG project. Modelers should have by default make LOD versions of their aircraft for various reasons. You can't use the effect without it.


— wlbragg (Thu Mar 05). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png "I guess the effect cannot handle moving gear or tilting nacelles?"

I suspect right now no - animations seem to all go into the gl_ModelViewMatrix and currently the projection generating the shadow is applied before the matrix is multiplied. In principle, it's just a question of sorting the math out to do the projection in eye space, i.e. after applying gl_ModeViewMatrix - then the shadow reflects the state of the model after all animation have been carried out - and then do the projection transformation to screen space separately. I suspect it's ugly though, since the up-direction along which we determine where the ground is needs to be rotated as well, then we may have to do the roll/pitch transformations which make the shadow flat by hand,...

I have a suspicion it's more trouble than it's worth - it's the sort of thing you'll only notice if you go looking for it.


"IIRC in OpenGL it's not that necessary to create low poly LODs for your 3D model, someone correct me if I'm wrong here, but I recall this being mentioned more than once."

I think the definition of 'low poly' depends on your hardware. My current graphics card will happily crunch six million scenery vertices at a decent framerate, so it won't even notice whether you add a model with 1000 or 10.000 polygons. However, I assure you that you will feel the effect of adding a 3 million polygon shadow model to the scene.

So you shouldn't waste a lot of time in desperately driving polygon count down, but you should strip down the shadow model from the original where this is feasible, especially if the original has excessive polygon count.

It actually requires a depth buffer fill followed by a depth equality test, that renders one layer only.


— Thorsten (Thu Mar 06). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png Let me re-iterate that the shader does not use the transparency you set for the material - the rasterizer and z-buffer however may, leading to unexpected and difficult to track behavior. For the texture shadow, you should use texture alpha only to draw the outline of the shadow, and for the shadow volume you should for the moment not use material or texture alpha at all (at a later stage, I can add support for texture alpha). The shader should determine the correct alpha of the shadow output pixel on its own.
— Thorsten (Thu Mar 08). Re: 2D shadow on ground?.
(powered by Instant-Cquotes)
Cquote2.png

Related content