The landing light ground illumination spot in the stock implementation is treated the same no matter the cloud height above the surface upon which the illuminated spot is created. While I don't know the mechanism by which a low cloud can be illuminated when this light spot is near the maximum projection distance but strangely reduced or absent for near projection distances, I have concluded the following from experimentation.
First, the maximum distance over which the illuminated spot has been cast is a rather restrictive 1,000m. I'm certain this is a measure to reduce the odd cloud illumination when the spot lies farther from the plane. I have had this distance increased to 3,000m for a few years now, but this simple change really causes horrendous cloud lighting, as though there's a massive floodlight located at the point of the ground spot and shining upward, making the cloud light up like daytime. And as the plane banks, this cloud illumination can sweep across a considerable distance, very like a reflection from a beam sweeping across a huge mirror on the ground.
The lower the cloud base the worse this cloud lighting. In my experimentation I've discovered that the radius value applied to the light point actor is the culprit. The intensity appears to have no effect whatever; even when the intensity is barely above zero at nearly the farthest spot distance, it's the radius which is responsible.
And so I've developed a new scheme by which to alter the radius value as a function of the height difference between the terrain height and the cloud height. This permits to double the projection distance, from 1km to 2. I won't go into the nitty gritty, as the code below (with my notes) tells the tale. In a nutshell, as the vertical distance between the ground elevation and the cloud base height decreases, the radius value is dynamically reduced. If flying over hilly terrain, as the light spot is cast upon ground of varying height and hence with a varying distance below the cloud, the radius will be altered to suit. The radius value I've limited to is 1/2 the vertical separation, The largest radius applied is 1,000m, and so for a vertical height difference of > 2,000m a fixed radius is used.
This works both ways, in that the dynamic adjustment is applied whether the cloud is higher or the light spot is higher. The latter would apply for a low cloud height with the airfield high up in the mountains, such as we have for some New Guinea interior strips on the Green Hell map.
The aim is to eliminate or at least reduce the awful cloud illumination when the cloud base is not very different from the airfield height, and at the same time allow a longer projection distance.
Stock Aircraft.updateLLights()
public void updateLLights()
{
pos.getRender(_tmpLoc);
if(lLight == null)
{
if(_tmpLoc.getX() < 1.0D)
return;
lLight = (new LightPointWorld[] {
null, null, null, null
});
for(int i = 0; i < 4; i++)
{
lLight[i] = new LightPointWorld();
lLight[i].setColor(0.49411765F, 0.9098039F, 0.9607843F);
lLight[i].setEmit(0.0F, 0.0F);
try
{
lLightHook[i] = new HookNamed(this, "_LandingLight0" + i);
}
catch(Exception exception) { }
}
return;
}
for(int j = 0; j < 4; j++)
{
if(FM.AS.astateLandingLightEffects[j] != null)
{
lLightLoc1.set(0.0D, 0.0D, 0.0D, 0.0F, 0.0F, 0.0F);
lLightHook[j].computePos(this, _tmpLoc, lLightLoc1);
lLightLoc1.get(lLightP1);
lLightLoc1.set(1000D, 0.0D, 0.0D, 0.0F, 0.0F, 0.0F);
lLightHook[j].computePos(this, _tmpLoc, lLightLoc1);
lLightLoc1.get(lLightP2);
Engine.land();
if(Landscape.rayHitHQ(lLightP1, lLightP2, lLightPL))
{
lLightPL.z++;
lLightP2.interpolate(lLightP1, lLightPL, 0.95F);
lLight[j].setPos(lLightP2);
float f = (float)lLightP1.distance(lLightPL);
float f1 = f * 0.5F + 30F;
float f2 = 0.5F - (0.5F * f) / 1000F;
lLight[j].setEmit(f2, f1);
} else
{
lLight[j].setEmit(0.0F, 0.0F);
}
continue;
}
if(lLight[j].getR() != 0.0F)
lLight[j].setEmit(0.0F, 0.0F);
}
}
My modded Aircraft.updateLLights()
public void updateLLights()
{
pos.getRender(_tmpLoc);
if(lLight == null)
{
if(_tmpLoc.getX() < 1.0D)
return;
lLight = (new LightPointWorld[] {
null, null, null, null
});
for(int i = 0; i < 4; i++)
{
lLight[i] = new LightPointWorld();
lLight[i].setColor(0.96F, 0.98F, 0.8F); //originally (0.49411765F, 0.9098039F, 0.9607843F);
lLight[i].setEmit(0.0F, 0.0F);
try
{
lLightHook[i] = new HookNamed(this, "_LandingLight0" + i);
}
catch(Exception exception) { }
}
return;
}
for(int j = 0; j < 4; j++)
{
if(FM.AS.astateLandingLightEffects[j] != null)
{
lLightLoc1.set(0.0D, 0.0D, 0.0D, 0.0F, 0.0F, 0.0F);
lLightHook[j].computePos(this, _tmpLoc, lLightLoc1);
lLightLoc1.get(lLightP1);
lLightLoc1.set(2000D, 0.0D, 0.0D, 0.0F, 0.0F, 0.0F); //originally 1000
lLightHook[j].computePos(this, _tmpLoc, lLightLoc1);
lLightLoc1.get(lLightP2);
Engine.land();
if(Landscape.rayHitHQ(lLightP1, lLightP2, lLightPL))
{
lLightPL.z++;
lLightP2.interpolate(lLightP1, lLightPL, 0.95F);
lLight[j].setPos(lLightP2);
float f = (float)lLightP1.distance(lLightPL);
double gndHeight = lLightPL.z; //terrain height at light spot; needed for non-level topography, as a spot on higher ground gets closer to the cloud base and hence causes cloud illumination
if(gndHeight < 0.0D)
gndHeight = 0.0D;
EffClouds effclouds = Main.cur().clouds;
float cldHeight; //cloud base ASL
if(effclouds != null)
cldHeight = effclouds.height(); //stand-in cloud base height ASL if low clouds not present or height unspecified
else
cldHeight = 2000F;
float cldDelta = Math.abs(cldHeight - (float) gndHeight); //absolute value of the difference in ground and cloud height (always positive if not zero)
float CldHtFactor; //variable based on both cloud height above projected spot AND distance currently projected from plane
float f1 = 0.0F; //initilizing the actual projected spot radius
CldHtFactor = cldDelta * 0.00025F - 0.055F; //for 0m delta threshold, -0.055 to 0.445; for 300m delta threshold, 0.02 to 0.445
if(CldHtFactor > 0.445F) //if cld base > 2000m AGL above or below light spot
CldHtFactor = 0.445F;
if(cldDelta >= 220F) //at >220m height delta, radius at nearer projection distances decreases (when < 220m calculated radius INCREASES! Hence below...)
f1 = f * CldHtFactor + 110F; //f1 = radius based on cloud base height (when spot at 0m distance from plane, radius is always 110m)
else
if(cldDelta < 220F && cldDelta >= 0F) //in the delta height range 0 - 220m, fix the radius at all distances to the far value (@ 2000m)
f1 = 2000F * CldHtFactor + 110F;
float f2 = 0.5F - (0.5F * f) / 2000F; //intensity; @2000m, f2=0, @1000m, f2=0.25, @500m, f2=0.375, @0m, f2=0.5; newer, with reduced maximum projection distance of 2km
lLight[j].setEmit(f2, f1);
} else
{
lLight[j].setEmit(0.0F, 0.0F);
}
continue;
}
if(lLight[j].getR() != 0.0F)
lLight[j].setEmit(0.0F, 0.0F);
}
}