Board index FlightGear Development Effects and shaders

2D shadow on ground

An exciting "new" option in FlightGear, that includes reflections, lightmaps, the particle system etc.. A lot is yet to be discovered/implemented!

Re: 2D shadow on ground

Postby AndersG » Wed May 13, 2015 8:50 am

The current state is now in my github repository: http://github.com/andgi/FlightGear-ZLT-NT.

I'll return to this after work.
Callsign: SE-AG
Aircraft (uhm...): Submarine Scout, Zeppelin NT, ZF Navy free balloon, Nordstern, Hindenburg, Short Empire flying-boat, ZNP-K, North Sea class, MTB T21 class, U.S.S. Monitor, MFI-9B, Type UB I submarine, Gokstad ship, Renault FT.
AndersG
 
Posts: 2524
Joined: Wed Nov 29, 2006 10:20 am
Location: Göteborg, Sweden
Callsign: SE-AG
OS: Debian GNU Linux

Re: 2D shadow on ground

Postby Thorsten » Wed May 13, 2015 5:57 pm

After spending 1 1/2 hours with this, I know a few things which it is not:

* I checked it's not clipping with the terrain by adding a variable offset and lifting the shadow well off the ground
* I checked it's not z-buffer clipping itself by removing the depth buffer write
* I checked it's not division by zero by putting a minimum value for the scaling factor
* I checked it's not too agressive squishing by doing modest squishing of the volume

What I see is that in low light, a part of the shadow model under some view angle (about 45 degrees pitch, looking sunward) becomes fuzzy, i.e. the shape wobbles and moves, and if I move the view further that part disappears. A dark line sometimes marks the part that is about to disappear. The issue disappears once the sun rises and the shadow moves more beneath the airship. It also disappears if I don't do lateral projection and keep the shadow underneath the airship at all times.

The only tangible clue I see is the wobble, which would typically indicate a numerical issue, so I suspect that there's some freak coincidence of transformations interacting in a bad way.

I'm not sure there's anything you can do at this point, certainly the origin of this is a bit shadowy (if I may use the pun...). I need to think about this further...
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: 2D shadow on ground

Postby AndersG » Wed May 13, 2015 10:29 pm

Thanks! Then it is not just an issue with my rather outdated graphics card. No worries, I can live with the oddities and hope we can eventually figure out what goes wrong.
Callsign: SE-AG
Aircraft (uhm...): Submarine Scout, Zeppelin NT, ZF Navy free balloon, Nordstern, Hindenburg, Short Empire flying-boat, ZNP-K, North Sea class, MTB T21 class, U.S.S. Monitor, MFI-9B, Type UB I submarine, Gokstad ship, Renault FT.
AndersG
 
Posts: 2524
Joined: Wed Nov 29, 2006 10:20 am
Location: Göteborg, Sweden
Callsign: SE-AG
OS: Debian GNU Linux

Re: 2D shadow on ground

Postby awall86 » Wed Sep 28, 2016 9:35 pm

My apologies to reactivate this thread, because it has more than a year elapsed since the last post.

I'm developing a GNU/GPL Cessna 152 II, while I'm trying to learn FlightGear development philosophy. It is a long way in which I took almost a year of work and learn. In other words, I'm a newbie in Flightgear Development word. Gilberto (gsagostinho) helps me a lot during this time.

At this moment I'm trying to make 3D ALS shadow for the Cessna. I follow all steps based on excelent development of default C172p, and reading information in the forum and wiki.

Shadow look like this:

Image

Works fine when time of day is changed, and when aircraft changes roll or pitch attitude, but when aircraft is in the air, the shadow continues in the same location, near landing gear base, and not in the ground.

Image

The xml code i have is:

In the c152-set.xml file:
Code: Select all
       
<systems>         
            <property-rule n="100">
                <name>gear_agl_m</name>
                <path archive="y">Aircraft/c152/Systems/gearAGL.xml</path>
            </property-rule>
           
</systems>


In the Systems/gearAGL.xml file:

Code: Select all
<?xml version="1.0"?>
<PropertyList>
    <filter>
        <type>gain</type>
        <gain>0.3048</gain>
        <input>/position/altitude-agl-ft</input>
        <reference>4</reference>
        <output>/position/gear-agl-m</output>
    </filter>
</PropertyList>


I tried diferent values for reference parameter but the results was the same.

In the shadow.xml file:

Code: Select all
<?xml version="1.0" encoding="UTF-8"?>

<PropertyList>

    <path>shadow.ac</path>

    <offsets>
        <z-m>-1.18</z-m>
    </offsets>

    <animation>
        <object-name>shadow</object-name>
        <type>select</type>
        <condition>
            <not>
                <property>/sim/rendering/rembrandt/enabled</property>
            </not>
        </condition>
    </animation>

    <effect>
        <inherits-from>Effects/shadow-vol</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>

    <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>


And finally in the Model/c152.xml

Code: Select all
    <model>
        <path>Effects/shadow/shadow.xml</path>
    </model>


I try a lot of changes in the files, with the same results. FG version is the latest 2016.3.1. I'm frustrated. I can't realize I'm doing wrong :(

Browsing properties values in the sim, I observed that the value of /position/altitude-agl-ft is (none) all the time, while /position/altitude-agl-m have a valid value.

My sincerest apologies for my bad English level. I needed the help of a translator to write this post. :cry:

Thanks a lot for your help
awall86
 
Posts: 63
Joined: Thu Oct 08, 2015 6:28 pm
Location: Madrid, Spain
Version: 2020.3.1
OS: Ubuntu 20.04

Re: 2D shadow on ground

Postby wlbragg » Wed Sep 28, 2016 10:57 pm

First, your doing a 3dshadow, you don't use the translation code block, the shader handles the altitude.
<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>


and in the filter, you have to name the output "/position/altitude-agl-m", not "/position/gear-agl-m", the shader is expecting it.
Code: Select all
 <filter>
        <type>gain</type>
        <gain>0.3048</gain>
        <input>
            <property>/position/altitude-agl-ft</property>
        </input>
        <output>
            <property>/position/altitude-agl-m</property>
        </output>
    </filter>
Kansas and Ohio/Midwest scenery development.
KEQA, 3AU, KRCP Airport Layout
Intel i7/GeForce RTX 2070/Max-Q
User avatar
wlbragg
 
Posts: 7588
Joined: Sun Aug 26, 2012 12:31 am
Location: Kansas (Tornado Alley), USA
Callsign: WC2020
Version: next
OS: Win10/Linux/RTX 2070

Re: 2D shadow on ground

Postby awall86 » Thu Sep 29, 2016 8:03 am

Thanks a lot, wlbragg !! It's work fine now.

Image

When the texture process of the model is finished (I'm working on it) I will update the Github repository. The plane has many changes in the .blend model since the las commit.

Thanks, again.
awall86
 
Posts: 63
Joined: Thu Oct 08, 2015 6:28 pm
Location: Madrid, Spain
Version: 2020.3.1
OS: Ubuntu 20.04

Re: 2D shadow on ground

Postby flug » Sun Mar 19, 2017 1:45 pm

Thorsten wrote in Tue May 12, 2015 6:06 am:
What does the shader do with this altitude information? It must be used for computing the vertical and lateral displacement - but what is its default expectation w.r.t. the shadow object?


It starts by establishing the 'up' direction relative to the terrain (assumed to be flat) underneath - for this it needs pitch and roll information because otherwise 'up' is always in model coords. Then it squishes the volume down to the given ground level, not quite flat (to avoid z-fighting) but reducing the z-extension quite drastically. Then it does the (xy)-displacement along the light direction. And finally it uses the ModelViewProjectionMatrix to get everything into the screen space used by the fragment shader. Here's the relevant part of shadow-vol-ALS.vert:

Code: Select all
//prepare rotation matrix
   mat4 RotMatPR;

   float _roll = roll;


   if (_roll>90.0 || _roll < -90.0)
   {_roll = -_roll;}
   float cosRx = cos(radians(_roll));
   float sinRx = sin(radians(_roll));
   float cosRy = cos(radians(-pitch));
   float sinRy = sin(radians(-pitch));

   rotationMatrixPR(sinRx, cosRx, sinRy, cosRy, RotMatPR);

I was looking at this today, & noticed what appears to be an important typo in this matrix in Shaders/shadow-vol-ALS.vert. Here the code as of 2016.4.4:
Code: Select all
void rotationMatrixPR(in float sinRx, in float cosRx, in float sinRy, in float cosRy, out mat4 rotmat )
{
   rotmat = mat4(   cosRy ,   sinRx * sinRy ,   cosRx * sinRy ,   0.0,
                    0.0   ,   cosRx         ,   -sinRx * cosRx ,   0.0,
              -sinRy,   sinRx * cosRy ,   cosRx * cosRy ,   0.0,
               0.0   ,   0.0           ,   0.0           ,   1.0 );
                                                                                             
}

Here is what I think should be the correct version (based on typical rotation matrices):

Code: Select all
void rotationMatrixPR(in float sinRx, in float cosRx, in float sinRy, in float cosRy, out mat4 rotmat )
{
   rotmat = mat4(   cosRy ,   sinRx * sinRy ,   cosRx * sinRy ,   0.0,
                    0.0   ,   cosRx         ,   -sinRx        ,   0.0,
              -sinRy,   sinRx * cosRy ,   cosRx * cosRy ,   0.0,
               0.0   ,   0.0           ,   0.0           ,   1.0 );
                                                                                             
}


Difference is in the 2nd row 3rd column, -sinRx * cosRx vs -sinRx.

FYI I've got a version of this going for the Sopwith Camel. I finally settled on just projecting a shadow straight down, as though from the noonday sun. It isn't quite realistic, but straight below the a/c is the one single place we actually know the elevation of the ground. So if you want to put the shadow anywhere else, you have to accurately know the elevation of that spot, or lift it quite a bit off the ground just to be safe, or put up with it disappearing at random moments.

Code is in the /Models/Effects/shadow folder here if anyone wants to have a look:

https://github.com/bhugh/SopwithCamel-J ... 0delta.zip

FYI it still has some glitches, particularly when pitch is above 45 or so degrees, or below -45 or so. But even there it is at least convincingly wrong--you have to stare at it for quite a while before you figure out that no, the shadow actually couldn't be quite like that.

When you land or crash land sometimes the shadow disappears briefly depending on exact attitude of the aircraft etc. But 95% of the time it is visually OK and quite helpful to the pilot.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby flug » Sun Mar 19, 2017 1:57 pm

Thorsten wrote in Wed May 13, 2015 5:57 pm:After spending 1 1/2 hours with this, I know a few things which it is not:

* I checked it's not clipping with the terrain by adding a variable offset and lifting the shadow well off the ground
* I checked it's not z-buffer clipping itself by removing the depth buffer write
* I checked it's not division by zero by putting a minimum value for the scaling factor
* I checked it's not too agressive squishing by doing modest squishing of the volume


I think what is happening is the shadow is getting out of range of the 'near camera'. That is what it looks like anyway (though I confess I don't have a complete understanding of how the various cameras work).

The only way I can think of to get around this would be to continue to render the shadow at the max visible distance (whatever that is) but just scale it down smaller & smaller to simulate it being further away. This will only be effective from one viewpoint, of course, but that might be enough for some purposes.

On a somewhat related note, I'm wondering if there is a way to force the shadow to render on top of just about everything else. I tried achieve that via render-bin settings but that was unsuccessful. Does anyone know if there is a way to do this?

What would be ideal is if (for example) the shadow happens to be rendered 2.4 inches below the surface of the ground, but there could be some setting on the shadow model that tells the renderer to render the shadow on top of the ground regardless of where it happens to fall in the z sort.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby flug » Sun Mar 19, 2017 2:22 pm

Thorsten wrote in Mon Mar 09, 2015 7:30 am:
Would it be possible to align the shadow with the ground normal to prevent wing clipping? Is that something that should be done XML model side?


It is trivial to tilt the shadow with the ground normal (that's what I mean when I use the words 'co-planar with the triangle') - the tree shadows exemplify that. What's not trivial is getting the normal in the first place, because you don't need it underneath the plane, you need it at the position of the shadow - but that in turn depends on terrain elevation at that position.

So it's a ray intersection problem between aircraft and terrain along the light to find the position at which you want the normal - and they're not cheap to do. In any case, yes, this needs to be done model-side, because the shader doesn't have the information to do the ray intersection problem because it only knows the local mesh (current vertex or pixel).


One way the current shader is fairly wasteful is that it is forced to recalculate the rotation matrix for every individual vertex. It does this because some of the relevant information for the transform is figured out within the shader itself--too late to pre-calculate the rotation matrix. (In the Camel version I just put together, I actually had the shader do all the transforms, so no further rotations are needed in the shadow_model.xml file. But . . . this is even more expensive of GPU than the current shadow-vol-ALS.vert. It would be better to pre-calculate the matrix (or more likely, matrices) & pass them along to the shader, rather than recalculating it for each & every vertex that is rotated--if we can figure out how to do it.

I'm bringing this up because a possibly profitable approach here would be to include a bit of wrapper code somewhere that:

- Calculates the line between the sun (or other major light source) and the aircraft and figures out where that line intersects the ground (ie, the exact spot where the shadow should be drawn)

- Also gets the position/elevation of 3 points in the area where the shadow should lie so that you have the 3 points of the triangle that determines the plane the shadow should be in

- As mentioned above, location of Center of Gravity of the aircraft is really not stable or accurate enough for this kind of work. We really need to know the exact location of the origin (0,0,0) of the aircraft model frame within the world frame. The ground elevation points where the shadow will be located will be given to the shader in terms of this aircraft model frame origin. Putting all that together, very accurate placement of the shadow shouldn't be difficult and we shouldn't have the 'disappearing shadow' problem happen too much (perhaps in very rough territory, or on the edge of terrain polygons once in a while).

- Also uses the above necessary info to pre-calculate the transformation matrices that the shader will need to rotate & project the shadow model down to that spot, with the correct 3-d projection of the shadow aircraft model and the correct angle for the shadow to lie on the ground without going 'under water'.

- We could include a setting somewhere on the property tree for how high off the ground you want the shadow model to be placed, how 'thin' you want your shadow-model compressed, and perhaps a few more such customization settings that would be useful for aircraft designers using the shadow system.

Then the shader could pick up those values from somewhere (the property tree?) and just render the shadow.

It would be both more efficient & more accurate/reliable than what we are doing now.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby Thorsten » Sun Mar 19, 2017 2:46 pm

One way the current shader is fairly wasteful is that it is forced to recalculate the rotation matrix for every individual vertex.


True - but the number of aircraft maintainers who can set up property rules to compute a rotation matrix and encode it as properties is fairly small.

You can look into the Shuttle's pointing code to get into the mood:

https://sourceforge.net/p/fgspaceshuttl ... inting.xml

On the other hand, graphics cards are actually made to deal with this kind of problem, so they can actually do it much faster than the CPU, which makes it not quite as bad as it seems.

Calculates the line between the sun (or other major light source) and the aircraft and figures out where that line intersects the ground (ie, the exact spot where the shadow should be drawn)


That's the fairly expensive bit, because you need to run an intersection finder. The urban effect heightmap intersection finder needs some 20 iterative queries on the heightmap texture - assuming you want to run on the same quality, you'd need 20 terrain queries per frame, which last time I tested this is a big no - terrain queries are among the most expensive operations we can do.

Also gets the position/elevation of 3 points in the area where the shadow should lie so that you have the 3 points of the triangle that determines the plane the shadow should be in


See above.

- As mentioned above, location of Center of Gravity of the aircraft is really not stable or accurate enough for this kind of work.


You can use any reference point you like aircraft side.

- We could include a setting somewhere on the property tree for how high off the ground you want the shadow model to be placed, how 'thin' you want your shadow-model compressed,


The first one exists (it's an offset), the second is imo a bad idea.

It would be both more efficient & more accurate/reliable than what we are doing now.


More accurate yes, more efficient certainly not. Making the GPU compute rotation matrices for a low-poly model is actually not expensive - a single terrain query is probably more costly than all these matrix assembly.
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: 2D shadow on ground

Postby Thorsten » Sun Mar 19, 2017 2:55 pm

On a somewhat related note, I'm wondering if there is a way to force the shadow to render on top of just about everything else.


Disable the z-buffer test and replace it by 'always'.

Might have side effects because you will also see the shadow through the aircraft (remember, it's rendered on top of everything else).
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: 2D shadow on ground

Postby flug » Mon Mar 20, 2017 2:21 am

Hmm, yeah that might not be too useful. But thanks for the info--I will definitely experiment with this some.
Last edited by Johan G on Mon Mar 20, 2017 4:23 pm, edited 1 time in total.
Reason: No need to quote the entire preceding post
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby flug » Mon Mar 20, 2017 2:29 am

flug wrote in Sun Mar 19, 2017 1:57 pm:
The only way I can think of to get around this would be to continue to render the shadow at the max visible distance (whatever that is) but just scale it down smaller & smaller to simulate it being further away. This will only be effective from one viewpoint, of course, but that might be enough for some purposes.


I implemented this today and I have to say I was actually very pleased with the results. From the cockpit or anywhere near the aircraft it is visually indistinguishable from the real thing. It actually looks pretty great!

You might happen to spot the 'flying shadow' from say a tower view or something but honestly by the time it is 75 meters away it is generally a small (and very thin) thing that is pretty unnoticeable unless you are looking at from more or less right above or below, as you are from the aircraft itself. From tower view, for example, you likely wouldn't even notice it unless you knew to look.

I was drawing the shadow at 0.9*alt_agl below the aircraft, and under that system that shadow stopped rendering at about 85 meters. 0.9*85 = 76.5 meters distant from the aircraft. Near camera renders up to 100 meters so the 76.5 meters may come from the fact that looking down on the aircraft in (say) model view you are probably 20 or 25 meters above the aircraft.

The relevant code bit is:

Code: Select all
    if ( alt_agl >= 85 ) 
    {
         pos.z = mult * ( -76.5) + 0.05 * pos.z ; //above ~85 meters AGL (at a factor of 0.9*AGL) it disappears so we are going to just keep it there & make it smaller. -76.5 = 85*-0.9
         pos.xy = pos.xy * (7225/alt_agl/alt_agl); //This shrinks the size of the shadow to make it appear as though it is further away than the 76.6 m. that FG will render it at. 85*85=7225, creates a seamless transition from the method (above) for handling between 2 m & 85 m.  At 85 m. the shadow was rendered at 100% size so we start with 85^2/85^2 or 100% and scale down from there.
    }
   


Edit: Note that 'proper' code here for making an object reduce in size by distance would be:

Code: Select all
         pos.xy = pos.xy * (85/alt_agl);


That reduces both x & y linearly by distance.

I decided to reduce by square of distance instead, making the shadow get smaller & disappear sooner for two reasons:

1. Mainly I was looking for a way to make the shadow disappear gracefully after 75 or 85 meters height, rather than just vanish suddenly and abruptly. So I was looking more for a way to transition the shadow out of there in a visually nice way than actually exactly modeling the shadow.

2. We're not really modeling the ways that shadows become more attenuated the more distant the aircraft gets from the ground, because of general light scattering and also the fact that the 'umbra' part of the shadow becomes smaller or even disappears altogether by some height, while the penumbra and antumbra portions become larger and also less distinct. In short, the shadow becomes more fuzzy and less dark as the aircraft becomes more distant from the ground, and just making the black shadow shape extra small is a simple/cheap, though inexact, way of indicating that.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby flug » Tue Mar 21, 2017 7:54 am

I've spent quite a bit of time over the weekend taking a look at the ALS 3d shadow volume effect. It is so close to being really good, but had a few glitches I noticed:

1. The shadow is not always exactly parallel to the ground. Sometimes it slopes up or down, making the shadow partly disappear under the ground, with the remainder sticking up out of the ground at an unnatural angle.

2. The shadow looks great if you are doing pitch alone or roll alone. But if your aircraft is in an attitude where there is some pitch and some roll, the shadow is just . . . wrong. Like it's at the wrong angle.

3. The shadow disappears suddenly when it is approx 80 meters distant from the aircraft (about 100 meters distant from the viewpoint).

So I've been fiddling and found solutions to all three problems. With these problems solved the ALS 3d shadow volume effect actually looks pretty awesome.

Solutions:

1. Non-flat shadow: In the shadow model animations .xml, the roll must come FIRST, followed by the pitch. Yes, order is important.

2. Wrong shadow angle when the aircraft has both roll & pitch: The rotation matrix used in shadow-vol-ALS.vert has one typo (mentioned upthread) but also, for whatever reason that I don't totally understand, it turns out that we need to use transpose of the rotation matrix currently in shadow-vol-ALS.vert. Maybe because that matrix is designed to be used as vector * RotMatrix & we are doing RotMatrix * vector instead. Anyway, regardless of the reason, the transposed matrix works perfectly.

3. I implemented the solution mentioned upthread for keeping the shadow model within about 75 meters of the aircraft and just shrinking its size to simulate a more distant location. There were a couple of tweaks necessary because I was projecting my shadows straight down before, so distance of shadow and AGL were synomous. Using the shadow-vol-ALS.vert system the shadow can be projected off to the side etc so you have to consider XYZ distance, not just altitude.

Anyway, those are details. The main point is, it all works.

Here are the code samples & updates:

Use this code in the shadow-model.xml file--make sure your roll is BEFORE your pitch (the order is important)

Code: Select all
<!-- roll -->
  <animation>
    <type>rotate</type>
    <object-name>camel_shadow</object-name>   
    <property>/orientation/roll-deg</property> 
    <!--
    <condition>
      <not>
        <property>/sim/rendering/shaders/skydome</property>
      </not>
    </condition>
    -->     
    <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>
 
  <!-- pitch -->
  <animation>
    <type>rotate</type>
    <object-name>camel_shadow</object-name>
    <property>/orientation/pitch-deg</property>
    <!-- <condition>
      <not>
        <property>/sim/rendering/shaders/skydome</property>
      </not>
    </condition>
    -->   
 
    <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>


Updated shadow-vol-ALS.vert code that implements the three fixes mentioned above (fixed typo in rotation matrix, uses transpose of rotation matrix, implements fix to allow shadows more than 75-100 meters distant):

Code: Select all
// -*-C++-*-


#version 120

uniform float hazeLayerAltitude;
uniform float terminator;
uniform float terrain_alt;
uniform float overcast;
uniform float ground_scattering;
uniform float eye_alt;
uniform float moonlight;
uniform float alt_agl;
uniform   float pitch;
uniform   float roll;
uniform float gear_clearance;



const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;

void rotationMatrixPR(in float sinRx, in float cosRx, in float sinRy, in float cosRy, out mat4 rotmat)
{
   rotmat = mat4(   cosRy ,   sinRx * sinRy ,   cosRx * sinRy,   0.0,
                           0.0   ,   cosRx        ,   -sinRx      ,   0.0,
                           -sinRy,   sinRx * cosRy,   cosRx * cosRy ,   0.0,
                           0.0   ,   0.0          ,   0.0           ,   1.0 );
}

/*

//Experimental - not used for now.  Seems to work functionally the same as rotationMatrixPR 
void rotationMatrixRP(in float sinRx, in float cosRx, in float sinRy, in float cosRy, out mat4 rotmat)
{
   rotmat = mat4(   cosRy ,   sinRx * sinRy ,   -cosRx * sinRy,   0.0,
                           0.0   ,   cosRx        ,   sinRx      ,   0.0,
                           sinRy,   -sinRx * cosRy,   cosRx * cosRy ,   0.0,
                           0.0   ,   0.0          ,   0.0           ,   1.0 );
}
*/

float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{

if (x < -15.0) {return 0.0;}

return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}

void main()
{

   
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

    vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
    vec3 relPos = gl_Vertex.xyz - ep.xyz;


    // compute the strength of light
    float vertex_alt = max(gl_Vertex.z,100.0);
    float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
    vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
    vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
    float yprime = -dot(relPos, lightHorizon);
    float yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt);
    float earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4;
    float lightArg = (terminator-yprime_alt)/100000.0;
    vec4 light_diffuse;
    light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
    light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
    light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
    light_diffuse.a = 1.0;
    light_diffuse = light_diffuse * scattering;
    float shade_depth =  1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smoothstep(0.1,0.5,overcast)) * smoothstep(0.4,1.5,earthShade);

    light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);


   //prepare rotation matrix
   mat4 RotMatPR;
   mat4 RotMatPR_tr;

   float _roll = roll;


   //if (_roll>90.0 || _roll < -90.0) //making roll=-roll when >90 is no longer necessary thanks to fix with transpose of rotation matrix.
    //{_roll = -_roll;}
   float cosRx = cos(radians(-_roll));
   float sinRx = sin(radians(-_roll));
   float cosRy = cos(radians(pitch));
   float sinRy = sin(radians(pitch));

   rotationMatrixPR(sinRx, cosRx, sinRy, cosRy, RotMatPR);
   //rotationMatrixRP(sinRx, cosRx, sinRy, cosRy, RotMatPR);
   
   RotMatPR_tr=transpose(RotMatPR); //RotMatPR works fine if pitch =0 or roll=0 but if say pitch=35 and roll=60 the rotation is all wrong. transpose(RotMatPR) however works perfectly.


    // project the shadow onto the ground
    //vec4 vertex =   RotMatPR * gl_Vertex;
    vec4 vertex =   RotMatPR_tr * gl_Vertex;
    vec4 pos = vertex;

    vec2 deltaxy = lightFull.xy * 0.95* (alt_agl + vertex.z + gear_clearance)/lightFull.z;
   
    float dist = sqrt(deltaxy.x * deltaxy.x + deltaxy.y * deltaxy.y + alt_agl * alt_agl);    //could use function 'distance' instead, might be better?
   
   
    if (dist < 75)
    {
   
         pos.z = -0.9 * alt_agl + 0.05 * vertex.z;
         //pos.z  = 0.05 * (vertex.z + gear_clearance);
         
         pos.xy -= deltaxy;
   
    }   
    else 
    {
         //The code below to shrink the shadow while keeping it 75 m. away has some issues that need to be fixed. Making the shadow shrink at x^2 rate partly to cover up this problem until it can be solved . . .
         //The problem is that the aircraft isn't flat/parallel to the ground any more, but it appears to be at an angle to the ground.
         //The various shrinkages perhaps mess with the angles somehow, meaning that when the animations apply the roll & pitch corrections they just don't quite work as they should
         pos.z = (-0.9*75)*alt_agl/dist + 0.05 * vertex.z ; //if the shadow is more than about 75 meters from the aircraft it disappears so we are going to just keep it right at 75 m. & make it smaller to simulate greater distance.
         //(-0.9*75) is the same factor for altitude we were using above when dist=75.  *alt_agl/dist keeps it at the right height proportionally to simulate the location at a further distance, while actually just keeping it at 75 m. distance.
         
         //pos.z = 0.05 * vertex.z ; //if the shadow is more than about 75 meters from the aircraft it disappears so we are going to just keep it right at 75 m. & make it smaller to simulate greater distance.
         
         
         
         //shrink the size FIRST, THEN move where it needs to be.  If you shrink later you're also shrinking the deltaxy distance moved, which doesn't work well
         pos.xy = pos.xy * 75 /dist;  //shrinking the size of the shadow to simulate further distance.  Should be linear shrinkage but doing it ^2 for now to help ucover up the issues in code above.
         
         pos.xy -= 75 * deltaxy/dist; // Similarly to above, * deltaxy/dist; keeps it at the right XY position proportionally to simulate the location at a further distance, while actually just keeping it at 75 m. distance.         
                   
    }
   

   // pos.z = pos.z - offset;         
   
   //if (dist>=75) pos = pos * 30/dist; //not sure why this doesn't work/ perhaps an overflow of some kind?
   
    gl_Position =  gl_ModelViewProjectionMatrix * pos;

    gl_FrontColor = light_diffuse;
    //light_diffuse.a=0;
    gl_BackColor = gl_FrontColor;
    //gl_BackColor = light_diffuse;
}


This does have one problem that I can't solve right now: When the shadow is more distant than 75 meters and the 'keep at 75 m. but shrink the size' illusion kicks in, the shadow is no longer parallel with the ground. This is quite noticeable in e.g. Tower View, where you see the real aircraft and then a small black copy of it zooming around below. (If this were working right you would see at most a black line parallel to the ground.) There is likely some way to fix this, but I don't know quite what right now..

UPDATE: Thanks to Thorsten's feedback, the slanting issue is solved. Updated shadow-vol-ALS.vert code here:

viewtopic.php?f=47&t=24859&p=307404#p307404
Last edited by flug on Wed Mar 22, 2017 5:28 am, edited 2 times in total.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby flug » Tue Mar 21, 2017 8:13 am

FYI testing procedure for the shadows is:

1. Spawn in on runway.

2. Set time speed-up to 1/16 or 1/32

3. Use property browser /position to set position about 20 feet above ground.

4. Use property browser /orientation to set pitch & roll to various angles; Time settings to change sun position to various angles

Make sure to test 'odd' attitudes that combine roll & pitch etc.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

PreviousNext

Return to Effects and shaders

Who is online

Users browsing this forum: No registered users and 4 guests