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 flug » Tue Mar 21, 2017 10:27 am

Image
Image
Image
Image
Image
Image
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby Thorsten » Tue Mar 21, 2017 11:52 am

Some remarks - you ought to give your shadow plane model some alpha. The fragment shader actually sets alpha, but that won't be used by the GPU unless it starts the draw expecting alpha, so the correct handling needs to be triggered.

Otherwise the shadow will be pitch black.

Code: Select all
float dist = sqrt(deltaxy.x * deltaxy.x + deltaxy.y * deltaxy.y + alt_agl * alt_agl);    //could use function 'distance' instead, might be better?


In GLSL we say length()...


Code: Select all
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.


This isn't fixing distance though, it's fixing altitude to something that's distance dependent. Since there'll be vertices farther away from the origin in the shadow, this fixes near and far parts of the shadow to different altitudes and likely is what tilts your projection from flat.

Main question I guess is - does it cause breakage for existing models?

I actually remember having tested various combinations of pitch and roll (there's a test shot in the wiki) and it worked out okay, so I wonder whether you've just combined two different ways of defining angles/matrices into another correctly working solution.
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: 2D shadow on ground

Postby flug » Tue Mar 21, 2017 10:17 pm

Thorsten wrote in Tue Mar 21, 2017 11:52 am:Some remarks - you ought to give your shadow plane model some alpha. The fragment shader actually sets alpha, but that won't be used by the GPU unless it starts the draw expecting alpha, so the correct handling needs to be triggered.

Aha, that makes sense. Thank you.


Code: Select all
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.


This isn't fixing distance though, it's fixing altitude to something that's distance dependent. Since there'll be vertices farther away from the origin in the shadow, this fixes near and far parts of the shadow to different altitudes and likely is what tilts your projection from flat.


That makes sense as well. The symptom is exactly as you describe--it slopes up the further away it is, which makes perfect sense as you explain it.

Do we know why the model disappears at ~100 meters distance? It might be both simpler and better to just address that directly rather than working on this workaround.

My first guess, that it has something to do with the aircraft model being drawn only in the near camera, is wrong (you can see the rest of the aircraft model in tower view, for example, except the shadow model, which pops into view at just about exactly 100 meters distance from the tower). It acts almost exactly like it has a range set, except that it doesn't. I tried setting a range for the model and it didn't seem to change anything, though possibly I did it wrong somehow. But something in the pipeline has some kind of a range implicitly set, or something along those lines.


Main question I guess is - does it cause breakage for existing models?

I actually remember having tested various combinations of pitch and roll (there's a test shot in the wiki) and it worked out okay, so I wonder whether you've just combined two different ways of defining angles/matrices into another correctly working solution.


It's quite possible it is indeed a different combination that ends in the same place. But I thought I had everything set up exactly as described in the wiki, and the shadow definitely wasn't flat.

There is the possibility it is something JSBSim related, as JSBSim has X & Y axes interchanged? I don't see how that internal JSBSim thing affects the properties this shader uses but the symptoms suggest some problem of that type.

I'll test with a few more aircraft and see how it works there.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby wlbragg » Tue Mar 21, 2017 10:30 pm

One thing I have noticed with the shadow disappearing, right before it does, it appears to speed up its motion away from the aircraft and not necessarily in the appropriate direction.

I too would really like to see this bug figured out, I notice the shadow constantly when flying a float version of any aircraft over water. It is invaluable in assisting to land on water, even though this particular bug doesn't really affect the shadow at the low agl of landing.

I'll help test and debug where I can.
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 flug » Tue Mar 21, 2017 11:02 pm

Checking out the updated shadow-vol-ALS.vert with the Cessna C172, you do need to go into the shadow model.xml file & switch the order of pitch & roll (roll should be first). Once you do that, it works just fine.

A few screen shots showing how well it works with the update--

Shadow flat on the ground always:
Image

From underneath (underground) showing how shadow aligns well with corresponding plane part and the sun:
Image

Below are a couple of screen shots with the behavior I noted with the stock settings for both C172 and shadow-vol-ALS.vert--

Shadow not flat on ground:
Image

Shadow is not flat and also the orientation of the shadow is incorrect:
Image

Note that it looks 'pretty good' until you get to certain specific combinations of roll & pitch. Only then is it really obvious that it is wrong. So, it is easy to miss the problem.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby flug » Tue Mar 21, 2017 11:11 pm

Thorsten wrote in Tue Mar 21, 2017 11:52 am:Main question I guess is - does it cause breakage for existing models?


RE: my tests with the C172 above, it does indeed require the pitch & roll rotation sections of the model.xml file to be reversed, ie roll first, then pitch. So replacing the shadow-vol-ALS.vert file with this version would require all of those .xml files to be edited.

Obviously, this is not the ideal situation. Ideal would be to have a replacement that would simply work with all .xml files that are already using shadow-vol-ALS.vert.

Presumably just applying another rotation at the very end could leave it in the correct state for it to work without any changes to the .xml files.

Another idea that occurred to me is that maybe shadow-vol-ALS.vert could just place the shadow flat on the ground without any further rotations needed in the model.xml file. It would be an end-to-end 'drop-in' solution in that case.

That would still require editing the model.xml files but simply removing the pitch & roll rotations is simpler & more foolproof than trying to change them somehow.

Another approach would be to set some kind of a flag that would signal whether to use the old way where final roll/pitch rotations are needed, or the new way that doesn't require them.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby wlbragg » Tue Mar 21, 2017 11:19 pm

@flug

Is your most current shadow-vol-ALS.vert contained in the current fgaddon Sopwith files? Is that the one I would use if I wanted to test it on both the Cub and the c172p?
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 flug » Tue Mar 21, 2017 11:24 pm

Amending my above comment slightly: I just tried the C172 with the "flug mod" of shadow-vol-ALS.vert along with the existing, unaltered shadow model.xml.

And actually it works just about as well with that (incorrect!) setup as it does with the stock setup. That is to say, you can take off land, go all through a normal flight and not notice anything awry.

Only when you get into those edge cases of certain high roll & pitch attitudes do you notice something going wrong. So in truth, exactly the situation we have with the current shadow-vol-ALS.vert right now.

So I would say we could replace shadow-vol-ALS.vert with this improved version and aircraft designers will have something that works just as well as what they have now. If they want to adjust their model.xml file to reverse the pitch & roll rotations they'll have something even better.

So that is an option.

A better option, perhaps, would be to do what I mentioned above, and pre-emptively apply a counteracting rotation matrix at the end of shadow-vol-ALS.vert so that correct behavior will 'just happen' without any changes to model.xml files required at all.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby flug » Wed Mar 22, 2017 5:24 am

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.


Thanks to Thorsten's comment above, here is the code that fixes the 'slanting shadow > 75 meters' problem.

shadow-vol-ALS.vert:
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);
   
    //experiment
    light_diffuse.b = 1.0;
    light_diffuse.g = 1.0;
    light_diffuse.r = 1.0;
    light_diffuse.a = 1.0;

   //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;  //This is the 'actual' location, taking into a account the full 3-D structure of the aircraft
   
    vec2 deltazeroxy = lightFull.xy * 0.95* (alt_agl + gear_clearance)/lightFull.z; //Instead of using the exact z value of this particularly point to determine the distance of the shadow & reposition & shrink it appropriately, we'll just use the origin (0,0,0) of the model instead.  This avoids a problem below, where varying vertex.z in deltaxy and then using deltaxy to calculate dist caused the shadow to sort of slant upwards, thanks to the varying z values used
   
    float dist = sqrt(deltazeroxy.x * deltazeroxy.x + deltazeroxy.y * deltazeroxy.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 = 75 / dist * pos.xy;  //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;
}


Relevant portions to this fix previously were:

Code: Select all
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);

...

    pos.z = (-0.9*75)*alt_agl/dist + 0.05 * vertex.z;


And now are changed to:

Code: Select all
vec2 deltaxy = lightFull.xy * 0.95* (alt_agl + vertex.z + gear_clearance)/lightFull.z; 
   
    vec2 deltazeroxy = lightFull.xy * 0.95* (alt_agl + gear_clearance)/lightFull.z;
   
    float dist = sqrt(deltazeroxy.x * deltazeroxy.x + deltazeroxy.y * deltazeroxy.y + alt_agl * alt_agl);

...

    pos.z = (-0.9*75)*alt_agl/dist + 0.05 * vertex.z;


The trick is to just use the origin as the basis to determine the location of the overall shadow model (or one single point consistently for the whole model--the origin just happens to be easy), rather than relying on each individual z value, which varies with each point in the model and caused the kind of slanting that I mentioned.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby wlbragg » Wed Mar 22, 2017 6:47 am

@flug

The shader works great.

Only problem is I'm not sure if the shadow has ever been correctly sized as you gain altitude. It is really noticeable now that it scales so small. Doesn't a shadow actually grow in size as the object responsible for the shadow gets farther away from the shadow and closer to the light source? I know getting closer to the sun is a relative thing, but the shadow should be getting more diffuse and actually should be getting larger, only appearing to get smaller because of the viewers distance to it. It just doesn't quite seem proportioned right.

I wonder if maybe we should be fading it out at a certain point?
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 Thorsten » Wed Mar 22, 2017 7:44 am

Another idea that occurred to me is that maybe shadow-vol-ALS.vert could just place the shadow flat on the ground without any further rotations needed in the model.xml file


If I remember correctly, the reason it's structured in the weird way it is is that I wanted the math to be organized in model space so that the projection plane is simply normal to z. But that requires gl_ModelViewProjectionMatrix to be fed accordingly to not rotate things again, which is what the animations do.

The alternative would be to organize it all in eye coordinate space, but the math is quite a bit more messy because all projection planes change with the view. It can be done I think, the expressions just get more involved.

I wonder if maybe we should be fading it out at a certain point?


Yes - you ought to be able to pass a varying alpha_correction to the fragment shader to fade it based on distance (note that the fragment shader is shared with the simple shadow, so if you do, it's vertex shader also needs to be adjusted).

Do we know why the model disappears at ~100 meters distance? It might be both simpler and better to just address that directly rather than working on this workaround.


I don't think we do. You could investigate whether it's a z-buffer accuracy issue (we are always trying to place it close to the ground) and whether a 'draw always' keeps it. But I really don't have any bright ideas.

Actually, what happens if you just move the eye point 100 m away - does it also disappear, or is it related to the projection distance?

It could be some clipping issue - moving things in the vertex shader sometimes does odd things.

Unfortunately this shadow effect is something I've never really been interested in (that must be the one example of a shader I wrote on request, and I've regretted doing this a dozen times since), and I also have no time to cram this into my ToDo list again, so while I can give you hints and comments, I won't do any actual testing/integration/implementation - you'll have to hammer it into something tested and ready to merge if it's supposed to go to FGData, including a solution for existing implementations that doesn't make things worse.
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

Re: 2D shadow on ground

Postby erik » Wed Mar 22, 2017 3:22 pm

Tested it with the PC-9M and flug's code works great. The only thing is, like Wayne said, that it seems to scale down too fast. Maybe length is factored in twice?

Erik
Last edited by erik on Wed Mar 22, 2017 10:53 pm, edited 1 time in total.
Current: Parachutist, Paraglider, Pterosaur, Pilatus PC-9M and variants, ERCO Ercoupe, Fokker Dr.1, Fokker 50, Fokker 100
Less active: Cessna T-37, T-38, Santa Claus. Previous: General Dynamics F-16. Worked on: Wright Flyer
erik
 
Posts: 2245
Joined: Thu Nov 01, 2007 2:41 pm

Re: 2D shadow on ground

Postby flug » Wed Mar 22, 2017 4:35 pm

wlbragg wrote in Tue Mar 21, 2017 11:19 pm:@flug

Is your most current shadow-vol-ALS.vert contained in the current fgaddon Sopwith files? Is that the one I would use if I wanted to test it on both the Cub and the c172p?


No, I've just been testing on my own computer so far & haven't uploaded anywhere except in this thread.
flug
 
Posts: 219
Joined: Wed Jun 17, 2009 2:06 am

Re: 2D shadow on ground

Postby erik » Thu Mar 23, 2017 3:22 pm

Would there be any objections to pushing the current version to git flug?

Erik
Current: Parachutist, Paraglider, Pterosaur, Pilatus PC-9M and variants, ERCO Ercoupe, Fokker Dr.1, Fokker 50, Fokker 100
Less active: Cessna T-37, T-38, Santa Claus. Previous: General Dynamics F-16. Worked on: Wright Flyer
erik
 
Posts: 2245
Joined: Thu Nov 01, 2007 2:41 pm

Re: 2D shadow on ground

Postby Thorsten » Thu Mar 23, 2017 5:37 pm

Can the fading issue sorted out first? This shouldn't be difficult to do.
Thorsten
 
Posts: 12490
Joined: Mon Nov 02, 2009 9:33 am

PreviousNext

Return to Effects and shaders

Who is online

Users browsing this forum: No registered users and 3 guests