Physically Accurate "fog" for simulating how light travels underwater.
moultano
Creator of ns_shiva. Join Date: 2002-12-14 Member: 10806Members, NS1 Playtester, Contributor, Constellation, NS2 Playtester, Squad Five Blue, Reinforced - Shadow, WC 2013 - Gold, NS2 Community Developer, Pistachionauts
I got inspired by the alpha shot to do a little research on how light travels under water, and I decided to work out the math of how you could render something physically accurate as an exercise. It was a lot of fun! Thought y'all would be interested. Here are my sources:
http://en.wikipedia.org/wiki/Color_of_water#Color_of_lakes_and_oceans
http://archimer.ifremer.fr/doc/00087/19819/17502.pdf
http://www.mip.informatik.uni-kiel.de/tiki-download_file.php?fileId=1682
Two different physical processes contribute to the way light behaves underwater, absorption and scattering. I’m going to start by defining them in terms of “slices” of water, where x is the term for light that originates further from the camera than the current slice. Finally we’ll integrate this into a single lighting model. The resulting math is quite different from what you get by just using fog naively.
Scattering: this is the reason the tips of waves, snow, clouds, and fog all appear white. Tiny particles throw specular reflections in all directions, and there are so many of them that the result appears uniformly white.
There are two components. One is the attenuation of the reflected light coming from the object as a result of those photons being scattered away from the eye. The other is proportional to the incident light directly from the light source as a result of those photons being scattered towards the eye.(For instance, the sunlight filtering down from the surface.)
Per “slice” of water parallel to the image plane, we can describe this as
where incident_light is a color and intensity (and potentially a specular-like angle dependent term), particle_color is the coefficient for reflection of the color, scatter is a coefficient < 1, and x is the light transmitted towards the eye from the next plane further away. For typical underwater scenes in clear water, the particle color is likely to be white, because what we’re seeing is specular reflection. If the water has silt, ash, algae or other stuff in it that reflects light differently, the particle color could be something other than white.
Absorption: Water absorbs light that passes through it, and in particular it absorbs red light 100x more than blue light. This is why things underwater appear blue.
http://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water#Visible_region
This is much simpler than the effects of scattering, in that it’s just a flat multiplier on all light that is coming from further from the camera.
Per “slice” of water parallel to the image plane, we can describe this as.
where absorption is an rgb coefficient with each component less than 1, and the r and g components are much smaller than the b which can be close to 1.
Now that we have this set up lets see what happens if we accumulate this over the slices of distance from the camera. Let d be the distance to the object, and o be its color.
A couple of things come out of this formula to give an intuitive sense of what’s going on. I’ll rearrange it factoring out terms that depend on d.
There’s some equilibrium background color at infinite distance that is determined by all of the coefficients. The color of an object at a given distance is a linear interpolation between its color and that equilibrium color, where the interpolation is proportional to a^d. The interesting thing is that the rate of interpolation is distinct for each color channel, so the rate at which red arrives at the equilibrium color can be much different than the rate for blue.
Many of these terms might be things that you could vary in space to produce even better effects, for instance, the incident_light should vary with depth, both in intensity and color. The absorption coefficient should be the same regardless of the water composition, but the color of the particles could vary greatly (suppose you are in a murky silty area, or an algae filled area, or an area full of volcanic ash particulates.) In addition, things like caustic god-rays filtering down will integrate perfectly if you apply this function to their depth just like any other object.
I had a lot of fun reading about this and working through it. Thought it might be helpful.
http://en.wikipedia.org/wiki/Color_of_water#Color_of_lakes_and_oceans
http://archimer.ifremer.fr/doc/00087/19819/17502.pdf
http://www.mip.informatik.uni-kiel.de/tiki-download_file.php?fileId=1682
Two different physical processes contribute to the way light behaves underwater, absorption and scattering. I’m going to start by defining them in terms of “slices” of water, where x is the term for light that originates further from the camera than the current slice. Finally we’ll integrate this into a single lighting model. The resulting math is quite different from what you get by just using fog naively.
Scattering: this is the reason the tips of waves, snow, clouds, and fog all appear white. Tiny particles throw specular reflections in all directions, and there are so many of them that the result appears uniformly white.
There are two components. One is the attenuation of the reflected light coming from the object as a result of those photons being scattered away from the eye. The other is proportional to the incident light directly from the light source as a result of those photons being scattered towards the eye.(For instance, the sunlight filtering down from the surface.)
Per “slice” of water parallel to the image plane, we can describe this as
lncident_light * particle_color * (1-scatter) + scatter * x
where incident_light is a color and intensity (and potentially a specular-like angle dependent term), particle_color is the coefficient for reflection of the color, scatter is a coefficient < 1, and x is the light transmitted towards the eye from the next plane further away. For typical underwater scenes in clear water, the particle color is likely to be white, because what we’re seeing is specular reflection. If the water has silt, ash, algae or other stuff in it that reflects light differently, the particle color could be something other than white.
Absorption: Water absorbs light that passes through it, and in particular it absorbs red light 100x more than blue light. This is why things underwater appear blue.
http://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water#Visible_region
This is much simpler than the effects of scattering, in that it’s just a flat multiplier on all light that is coming from further from the camera.
Per “slice” of water parallel to the image plane, we can describe this as.
absorption * x
where absorption is an rgb coefficient with each component less than 1, and the r and g components are much smaller than the b which can be close to 1.
Now that we have this set up lets see what happens if we accumulate this over the slices of distance from the camera. Let d be the distance to the object, and o be its color.
(scatter * absorption) ^ d * o + integral_0^d (scatter * absorption) ^ i * lncident_light * particle_color * (1-scatter) di (scatter * absorption)^d * o + incident_light * particle_color * (1-scatter) * ((scatter * absorption) ^ d - 1)/log(scatter * absorption)
A couple of things come out of this formula to give an intuitive sense of what’s going on. I’ll rearrange it factoring out terms that depend on d.
o * (scatter * absorption)^d + equilibrium_color_at_infinity * (1 - (scatter * absorption) ^d)
There’s some equilibrium background color at infinite distance that is determined by all of the coefficients. The color of an object at a given distance is a linear interpolation between its color and that equilibrium color, where the interpolation is proportional to a^d. The interesting thing is that the rate of interpolation is distinct for each color channel, so the rate at which red arrives at the equilibrium color can be much different than the rate for blue.
Many of these terms might be things that you could vary in space to produce even better effects, for instance, the incident_light should vary with depth, both in intensity and color. The absorption coefficient should be the same regardless of the water composition, but the color of the particles could vary greatly (suppose you are in a murky silty area, or an algae filled area, or an area full of volcanic ash particulates.) In addition, things like caustic god-rays filtering down will integrate perfectly if you apply this function to their depth just like any other object.
I had a lot of fun reading about this and working through it. Thought it might be helpful.
Comments
http://imgur.com/a/gGiwP
This is what shallow water would look like.
This is what deep water would look like.
The main difference between this and conventional fog is how things change color well before they start to disappear. Notice how the reds turn to blacks before they start to fade to the blue background. This is because the red wavelengths get absorbed independently of the scattering effect that causes the water in the distance to glow blue.
I haven't done graphics programming since college, but I think you could implement it as a pixel shader with just the rgb and z buffer available. The key bit to making it look good is just to make sure that the red channel changes faster than the green channel, and the green channel changes faster than the blue channel. That produces the key effect of red->black, yellow->green, in the middle distance before everything fades to blue.
It might be worth thinking about this a bit in the art design, because it effects the gameplay. Basically, don't make things red if they should be seen from a long distance away.
I think it would be cool if we used this as a base and then tweaked it to fit the art vision. It's an alien planet, after all.
Yeah, there are a lot of parameters you could tweak depending on the circumstances. I would expect for instance that you'd want the absorption values to be lower than the physical ones across the board even if the ratios between the different colors are the same just so that the player can see farther.
Mostly though, you can keep the math the same and just change the equilibrium color to get different effects. I used blue with a hint of green for the shallow water, and black for the deep water, but you could use whatever color you like. Lots of suspended algae would make the equilibrium color greenish for instance. Very shallow water would make it teal. Maybe somewhere in the ocean it's magenta due to phosphorescent alien bacteria!
....
oh sorry just drooling at the posibility of this in a game.. just.... move along... leave me alone.
Yeah, the important thing here isn't the particular color, but instead just that there are two different processes involved, absorption and scattering. You can pick any coefficients for the two that you like, so you can have any sort of colors, but you need both effects to convince the viewer that you are under water.
This is quite different from the way fog works on the surface. Air absorbs light only minimally, so you don't see the effect until you are looking out across a mountain range. This makes it really important to avoid the standard "fog" effect that we're used to seeing. It's designed for situations on land where scattering is the only issue, and absorption is non-existent. This is why it looks so bad for simulating conditions under water. When you're in any thick medium, the way the medium absorbs light really matters.
I believe this could make the light not only change by depth, but also be largely dependent on time of day, not only with less light entering the body of water, but the incident angle making it able to reflect against certain layers to greater extent than before. Naturally depending on wavelength too.
In shallow water the bottom reflects light back to the surface.
The water (and the dissolved stuff and particulates in it) scatters in all directions.
Light doesn't change color (exception inelastic scattering); colors are removed (absorbed).
Pink doesn't turn into pink blue then blue. Red, orange, and yellow are quickly removed, then green, leaving blue.
Getting the light "right" will prove to be quite a challenge.
On of the key tenets of diving/snorkeling is to not stir-up the particulate matter too much that exists all over the surfaces underwater. This causes reduced visibility that can persist for quite a while. I think this has the potential to be an interesting element of gameplay as well.
Combined with some player controlled lighting capabilities (lights and underwater flares?), there's some real potential for a very deep visual character in SN.
I'm excited to see where it goes!
Volumetric lighting is extremely important.
Does it have to be all water? Does it have to be homogeneous. Does it have to only have light coming from above? Nope...and if done in a believable way, the sky (or rather, the depths) are the limit.
Nice pun.