Implementing moonlight (or not)

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

Re: Implementing moonlight (or not)

Note that the shader (approximately) corrects for the attenuation by the air column above (well, in practice haze and clouds are the dominant players) - so the input value you want to produce is the illumination above the atmosphere.
Thorsten

Posts: 10950
Joined: Mon Nov 02, 2009 8:33 am

Re: Implementing moonlight (or not)

Would this be the skydome shader? And is this ALS specific? Does it take the zenith angle of the sun into account, i.e. the amount of air the light travels through increases with the zenith angle? The Xm equation here models both the Rayleigh and Mie scattering of the atmosphere, and is supposed to be very accurate for zenith angles close to 90 degrees. For angles > 90 degrees, I would have used a value of zero.

Cheers,
Edward
bugman
Moderator

Posts: 1698
Joined: Thu Mar 19, 2015 9:01 am
Version: next

Re: Implementing moonlight (or not)

No, it's really all the shaders which have to do it.

The light reduction by the atmosphere above depends on where the pixel is you're looking at - you might be in the shadow of a cloud, but the pixel you're looking at is on a mountain-top, so it's brilliantly lit. The only place in the rendering pipeline where you know where the pixel is is the vertex shader corresponding to that pixel.

As weird as this sounds, but you should think of light and fog being attached to the surface you're looking at, because that's how they need to be computed. There really is no 'fog' object in the scenegraph, the appearance of fog arises from coloring pixels differently based on where they are relative to you. And there is no light absorbing object in the scenegraph - the light reduction arises from coloring pixels differently based on where they are relative to the light source.

Also, the light reduction by a clear atmosphere is a minor correction to the light absorption by water droplets - there's almost always clouds and haze in a scene. Horizontal visibility in clear air at sea level is in excess of 250 km before scattering on air molecules blues the scene too much. Real visibilities on the ground are more often in the 30-50 km category even on fair days - you will get the predominant light reduction from the cloud layers, the first correction from haze, and only then the atmosphere matters.

What is ALS-specific is that light reduction is computed based on pixel position - Rembrandt and default compute based on your position. So the terrain will appear somewhat gloomy if you're underneath a cloud layer and as soon as you cross the layer and look down through a gap in the clouds, it will be bright in default but remain dark in ALS.
Thorsten

Posts: 10950
Joined: Mon Nov 02, 2009 8:33 am

Re: Implementing moonlight (or not)

What an interesting discussion! I sure hope we'll get to see the results in action! Keep it up!
Don't hesitate to let me know if I'm incorrect or just annoying! As long as you do it gently! :)
Debian testing 64bit - Athlon II 2x2.6GHz - 8GB RAM - GeForce GTS 450
Citation II

chris_blues

Posts: 1533
Joined: Mon May 03, 2010 1:30 pm
Location: claws of real life
Callsign: chris_blues
Version: GIT
OS: Debian 8 64

Re: Implementing moonlight (or not)

Thorsten wrote in Wed Dec 23, 2015 10:29 am:No, it's really all the shaders which have to do it.

The light reduction by the atmosphere above depends on where the pixel is you're looking at - you might be in the shadow of a cloud, but the pixel you're looking at is on a mountain-top, so it's brilliantly lit. The only place in the rendering pipeline where you know where the pixel is is the vertex shader corresponding to that pixel.

As weird as this sounds, but you should think of light and fog being attached to the surface you're looking at, because that's how they need to be computed. There really is no 'fog' object in the scenegraph, the appearance of fog arises from coloring pixels differently based on where they are relative to you. And there is no light absorbing object in the scenegraph - the light reduction arises from coloring pixels differently based on where they are relative to the light source.

Cheers! I had seen a little of this in the Viewer/renderer.cxx and Time/light.cxx code. I guess OSG does most of the pixel work for you. My first experiment might be to set the ambient, diffuse and specular light in the FG renderer for the moon, adding to the sun settings. I will generalise the sun light source so that we can switch from the sun vector to the moon vector once the sun angle is > 90 degrees (plus a small amount), and use the same code paths for setting the ambient, diffuse and specular lighting. This can then be refined to have smooth transitions with the twilight periods between sunset and dusk, and dawn and sunrise (when there should be no directional specular or diffuse lighting), and to have the colour shifted to match the eye response to low light.

For anyone following, note that moonlight and sunlight are not too different. You can see this with super long night time time-lapse photography:

The difference is in the response of your eye.

Also, the light reduction by a clear atmosphere is a minor correction to the light absorption by water droplets - there's almost always clouds and haze in a scene. Horizontal visibility in clear air at sea level is in excess of 250 km before scattering on air molecules blues the scene too much. Real visibilities on the ground are more often in the 30-50 km category even on fair days - you will get the predominant light reduction from the cloud layers, the first correction from haze, and only then the atmosphere matters.

I hope that most of this will be taken care of by simply hijacking the sun! I'll test if we need to take the light reduction due to changes in air mass with the changing zenith angle (Xm) into account later. For the "illuminance of the moon outside the atmosphere", I'll place this in the simgear ephemeris code, as this is not dependent on the local position. The Xm value cannot be calculated here as it is dependent on the local frame for the zenith angle, so that would go into the flightgear Time/bodysolver.cxx and Time/light.cxx code where the local frame + celestial bodies is handled.

What is ALS-specific is that light reduction is computed based on pixel position - Rembrandt and default compute based on your position. So the terrain will appear somewhat gloomy if you're underneath a cloud layer and as soon as you cross the layer and look down through a gap in the clouds, it will be bright in default but remain dark in ALS.

I still have to work out where ALS kicks in along this pathway. I can see that it is classified as a 'classic' renderer together with the default renderer, and Rembrandt is separate. Anyway, I hope that there won't be much tweaking required for such effects to work with moonlight, especially if we hijack the sun.

Regards,
Edward
bugman
Moderator

Posts: 1698
Joined: Thu Mar 19, 2015 9:01 am
Version: next

Re: Implementing moonlight (or not)

I still have to work out where ALS kicks in along this pathway. I can see that it is classified as a 'classic' renderer together with the default renderer, and Rembrandt is separate. Anyway, I hope that there won't be much tweaking required for such effects to work with moonlight, especially if we hijack the sun.

As I've tried to explain a few times, ALS does most of the work on the graphics card, so you wouldn't see any of its lighting by looking at the C++ code because it's simply not there - or turned the other way round, whatever you define as light on the C++ level is going to be discarded by ALS, and so is whatever you set up as fog there.

Since the horizon is significantly brighter in sunward direction than opposite to it, there is in fact directional light even after sundown, and this is relevant till the sun is 15 deg below the horizon.

I hope that most of this will be taken care of by simply hijacking the sun!

No, not at all. As I tried to explain, ALS doesn't use the light color you set because that's too simplistic - you need to light different parts of the scene with different colors, so the color is computed for every pixel based on sun position on the graphics card.

Which will go wrong if you pretend the sun is the moon.

The difference is in the response of your eye.

That's true, but it doesn't buy you anything - if you illuminate the scene in small_number x (1.0, 1.0, 1.0), it'll appear wrong because the response of the eye isn't properly considered.
Thorsten

Posts: 10950
Joined: Mon Nov 02, 2009 8:33 am

Re: Implementing moonlight (or not)

bugman wrote in Wed Dec 23, 2015 4:52 pm:For anyone following, note that moonlight and sunlight are not too different.

Well of course, moonlight is just sunlight bouncing off the moon.

MIG29pilot

Posts: 1454
Joined: Tue May 19, 2015 4:03 pm
Location: 6 feet under Snow
Callsign: MIG29pilot
Version: 3.7nightly
OS: Windows 10

Re: Implementing moonlight (or not)

Thorsten wrote in Wed Dec 23, 2015 6:19 pm:ALS doesn't use the light color you set because that's too simplistic - you need to light different parts of the scene with different colors, so the color is computed for every pixel based on sun position on the graphics card.

which probably is to say that the ALS framework/shaders contain the implicit assumption about the light source being "the" sun, so the whole "moonlight is reflected sunlight" approach won't work directly, short of adapting the underlying effects/shaders to also teach them about the position of the moon ?
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray

Posts: 11329
Joined: Tue Mar 25, 2008 8:40 am

Re: Implementing moonlight (or not)

which probably is to say that the ALS framework/shaders contain the implicit assumption about the light source being "the" sun, so the whole "moonlight is reflected sunlight" approach won't work directly, short of adapting the underlying effects/shaders to also teach them about the position of the moon ?

Yes, except that it's not an implicit assumption, it's pretty explicit in the code and documentation that the main light source computed is the sun

Which is why I suggested to use the exposed position and phase of the moon as uniforms.
Thorsten

Posts: 10950
Joined: Mon Nov 02, 2009 8:33 am

Re: Implementing moonlight (or not)

The graph above is the scaling factor I'll use for the moon illumination. It is the log of the illumination scaled to be between zero and one, with the formula:

factor = (log(I) - max_loglux) / (max_loglux - min_loglux) + 1.0

This will work for the illumination formulae for both outside and inside the atmosphere. The prototyping Python code for this is:

Code: Select all
`from math import log, pi, sinfrom numpy import array# The zenith angles.Z = array([0, 10, 20, 30, 40, 50, 60, 70, 80, 90]) / 360.0 * 2 * pi# Number of phases to plot.N = 101# Extinction coefficient.k = 0.172# Foot-candles to lux conversion factor.conv = 10.7639def lux(phase=1.0, Z=0.0):    """Calculate the illuminance of the moon inside the atmosphere in lux."""    # Illuminance of the moon outside the atmosphere.    I_star = 10**(-0.4 * (3.84 + 0.026*abs(phase) + 4e-9*phase**4))    # Outside the atmosphere.    if Z == None:        I = I_star    # Inside the atmosphere.    else:        # The optical pathlength to the moon (or air mass along the line of sight).        Xm = (1.0 - 0.96*sin(Z)**2)**-0.5        # Illuminance of the moon inside the atmosphere (equation 7).        I = I_star * 10**(-0.4 * k * Xm)    # Convert from foot-candles to lux.    I *= conv    # Return the illuminance.    return I# Maximum and minimum log lux.min_loglux = log(lux(phase=180.0, Z=pi/2.0))max_loglux = log(lux(phase=0.0, Z=None))print("Log of illuminance of the moon.")print("Minimum: %s" % min_loglux)print("Maximum: %s" % max_loglux)# Output Grace file (https://en.wikipedia.org/wiki/Grace_%28plotting_tool%29).file = open('loglux_factor.agr', 'w')# Loop over the zenith angles.for i in range(len(Z)):    # A new graph.    file.write("@target G0.S%s\n" % i)    file.write("@type xy\n")    # Loop over the different phases.    for j in range(N):        # The phase (from -180 to 180).        phase = 180 * (j - (N-1)/2.0) / ((N-1)/2.0)        # The illuminance of the moon inside the atmosphere.        I = lux(phase=phase, Z=Z[i])        # Log lux factor.        logI = (log(I) - max_loglux) / (max_loglux - min_loglux) + 1.0        # Write the point out to file.        file.write("%s %s\n" % (phase, logI))    # Terminate the graph.    file.write("&\n")`

And the values of max_loglux (outside the atmosphere) and min_loglux (inside the atmosphere) are:

Code: Select all
`Log of illuminance of the moon.Minimum: -10.1305600899Maximum: -1.16057276024`

I might just apply this directly to the simgear ephemeris code to set the "/environment/moonlight" value based on the moon illuminance outside of the atmosphere. The Xm formula could be applied later to decrease the illuminance based on the atmospheric extinction coefficient and the moon's zenith angle.

Regards,
Edward
bugman
Moderator

Posts: 1698
Joined: Thu Mar 19, 2015 9:01 am
Version: next

Re: Implementing moonlight (or not)

hey bugman, i saw something in an astronomy program (stellarium) the other day that i found quite interesting... i was experimenting with their scripts and gathering data on certain objects... in the returned data, there are numerous fields... in two of those fields they calculate the illumination and phase for the object requested... i was quite surprised to find that one is the other multiplied by 100... it kinda makes sense, though... the following numbers are supposedly accurate as of the time of this post...

eg:
Code: Select all
`---------Mercury Data---------phase        : 0.5772908329963684illumination : 57.72908329963684---------Venus Data---------phase        : 0.7649145126342773illumination : 76.49145126342773---------Moon Data---------phase        : 0.8053301572799683illumination : 80.53301572799683---------Mars Data---------phase        : 0.9147176742553711illumination : 91.47176742553711---------Jupiter Data---------phase        : 0.9922244548797607illumination : 99.22244548797607---------Saturn Data---------phase        : 0.9995062351226807illumination : 99.95062351226807---------Uranus Data---------phase        : 0.9994080066680908illumination : 99.94080066680908---------Neptune Data---------phase        : 0.9997990131378174illumination : 99.97990131378174---------Pluto Data---------phase        : 0.9999963045120239illumination : 99.99963045120239`
"You get more air close to the ground," said Angalo. "I read that in a book. You get lots of air low down, and not much when you go up."
"Why not?" said Gurder.
"Dunno. It's frightened of heights, I guess."

wkitty42

Posts: 5634
Joined: Fri Feb 20, 2015 3:46 pm
Location: central NC, USA
Callsign: wk42
Version: git next
OS: Kubuntu 14.04.5

Re: Implementing moonlight (or not)

It's wrong to simply take the illuminated area of the Moon (i.e. phase) as proxy for brightness. The reason is that the reflectivity of moon surface dust has a strong angular dependence, the dust reflects much better when the incident light angle is large.

It may work better for, say, Venus, since here the reflection is mainly on clouds.
Thorsten

Posts: 10950
Joined: Mon Nov 02, 2009 8:33 am

Re: Implementing moonlight (or not)

Like Thorsten said, this is not right. Actually, that multiplication by 100 is wrong on so many levels, I don't know where to start. I guess this is used as an extremely rough rule of thumb. The moon is a little like a mirror, it reflects far more light back at the sun than it does sideways. But all solar system bodies do this to some extent. Think of the sun lighting around you just before sunset. There will be longer and more shadows, and it's not as bright as when the sun is directly overhead, so the amount of light reflected out to space will be a lot less at the edges of the illuminated surface of any solar system body.

For the moon itself, the reflected light is modelled as:

-12.73 + 0.026*abs(phase) + 4e-9*phase**4

You'll see this in the equations I used (see the prototyping code above). This is directly from the astronomer's bible, specifically page 144 of the first edition of:

If you look at the table on page 144, note the variation of V with phase column (deltaV). This shows that the multiplication by 100 is wrong, very wrong. The correct formula is given in that column together with the V column, as V + deltaV.

Regards,
Edward

Edit: Fixes for the equations.
bugman
Moderator

Posts: 1698
Joined: Thu Mar 19, 2015 9:01 am
Version: next

Re: Implementing moonlight (or not)

bugman wrote in Tue Dec 29, 2015 5:59 pm:And the values of max_loglux (outside the atmosphere) and min_loglux (inside the atmosphere) are:

Code: Select all
`Log of illuminance of the moon.Minimum: -10.1305600899Maximum: -1.16057276024`

For reference, as these will be hardcoded into the simgear code, the base 10 log values are:

Code: Select all
`Log of illuminance of the moon.Minimum: -4.39964634562Maximum: -0.504030345621`

Regards,
Edward
bugman
Moderator

Posts: 1698
Joined: Thu Mar 19, 2015 9:01 am
Version: next

Re: Implementing moonlight (or not)

i don't know if those numbers i posted are being used as a proxy for brightness or not... perhaps more likely to be the lit area of a circle... i thought it was interesting and possibly helpful but perhaps not as much as i had thought... like i said, it is an astronomy program... AFAICT what it shows on screen for my location looks very accurate compared to what i see in RL when i step outside and look at the same object(s)...
"You get more air close to the ground," said Angalo. "I read that in a book. You get lots of air low down, and not much when you go up."
"Why not?" said Gurder.
"Dunno. It's frightened of heights, I guess."

wkitty42

Posts: 5634
Joined: Fri Feb 20, 2015 3:46 pm
Location: central NC, USA
Callsign: wk42
Version: git next
OS: Kubuntu 14.04.5

PreviousNext