The current state is now in my github repository: http://github.com/andgi/FlightGear-ZLT-NT.
I'll return to this after work.
<systems>
<property-rule n="100">
<name>gear_agl_m</name>
<path archive="y">Aircraft/c152/Systems/gearAGL.xml</path>
</property-rule>
</systems>
<?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>
<?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>
<model>
<path>Effects/shadow/shadow.xml</path>
</model>
<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>
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);
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 );
}
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 );
}
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
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.
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 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,
It would be both more efficient & more accurate/reliable than what we are doing now.
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.
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.
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.
}
pos.xy = pos.xy * (85/alt_agl);
<!-- 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>
// -*-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;
}
Users browsing this forum: No registered users and 4 guests