14
$\begingroup$

I'm trying to create a photorealistic Earth Atmosphere. Several papers written on the topic of atmospheric scattering state that our atmosphere's density has an exponential fall off, with most of it in the 25% of the roughly 100km of its visible height.

How can I implement exponential fall off into the density of the volume scatter node? ColorRamp node doesn't seem to have exponential gradation. RGB Curves might not be precise enough. Is there a way to implement an exponential math function?

EDIT: This is the relationship between height (altitude from Earth's surface) and atmospheric density:

$$\text{density} = \exp\left(\frac{-h}{8000\text{m}}\right)$$

or

$$\text{density} = e^\frac{-h}{8000}$$

where $h$ is the altitude in meters

Is it possible to implement this math function?

EDIT2 : I see a grid like pattern appear in my atmosphere, from the edges of the UV sphere mesh, no matter how much I subdivide (it fades near the poles). Also, if I make the sphere much bigger than Earth, I get really weird patterns in my volume. Here's a link to my blend file

$\endgroup$
  • $\begingroup$ If you know the relationship between altitude and density then you should be able to use Math nodes to calculate the density and feed that into the Scatter node. $\endgroup$ – Rich Sedman Oct 13 '17 at 22:26
  • $\begingroup$ So something like: spherical gradient plugged into a linear color ramp, which is then plugged into the math nodes, and into the volume scatter node? $\endgroup$ – CPLTarun Oct 14 '17 at 2:43
  • $\begingroup$ Yes - that should do the trick. I'm guessing this is for the Earth atmosphere as viewed from space - with sunlight scattering through the atmosphere? $\endgroup$ – Rich Sedman Oct 14 '17 at 8:21
  • $\begingroup$ I think using Scatter may be a bit impractical - you’d need a really low step size for the volumetrics and many many samples to get convincing results. How about faking with Emission volumetrics and some vector maths? I’m sure that would be much more efficient and easier to tune. $\endgroup$ – Rich Sedman Oct 14 '17 at 21:22
  • $\begingroup$ Posted an incomplete answer to see if this helps - the bottom branch (with the Multiply and Power nodes) is the exponential bit - the top branches deal with the shadow (with it being emission rather than true scatter). Let me know if this is along the right track. So far, the emission does seem far more practical for ‘distant’ views - it also seems to give pleasing results from the point of view of the planet’s surface. Faster to render too. I’ll add more detail and tidy it up when I can. $\endgroup$ – Rich Sedman Oct 15 '17 at 8:05
20
+500
$\begingroup$

You can use Vector maths and Maths nodes to calculate the 'altitude' above the planet and from there the atmospheric density and use this to control the density of the Volumetric Scatter.

To achieve this, add a mesh around your planet to act as a domain for the scattering. The domain's centre should correspond with the centre of the spherical 'planet'.

scene

Create the following material :

material

This uses vector maths to determine the distance from the centre of the planet. The Planet Radius value node determines where the atmosphere starts - it should correspond to the radius of the 'planet' object.

The 'Falloff Factor' determines how quickly the density of the atmosphere falls off - it should be negative and values closer to zero will provide a 'deeper' atmosphere (extending further from the surface of the planet).

The RGB node controls the 'color' of the atmosphere and the Multiply just prior to the scatter controls its 'thickness' at sea-level.

(Don't forget to increase the number of Volumetric bounces in the Cycles Light Paths settings.)

This can produce the following result :

animated result

Blend file attached

Note : I've also created a material using and Emission shader instead of scatter - faking the planetary shadow - and this is far more efficient than using Scatter. The vector maths are far more complicated than in the above material so I've omitted it here for simplicity. I can provide additional details if it would be of interest.


Breaking down the nodes to explain this a little, we're starting with two coordinates - the centre of the planet (which is the same as the centre of the domain mesh) is provided by the Object Info node, and the point in space (where we want to determine the density) is provided by the Geometry node. Both of these are in 'World Space' coordinates (points relative to the centre of the world).

distance from centre

By subtracting one from the other we get the vector between the two points. The length of that vector represents the distance from the centre of the planet to the point in space and the Dot Product and Power nodes convert this into an absolute distance (rather than a vector). [Using the Dot product in this way (with the same vector connected to both inputs) produces the square of the distance of the vector. The Power(0.5) performs a square root, generating the actual distance.]

Next we subtract the radius of the planet. This will result in the actual altitude above the surface.

altitude

For the exponential falloff we need to use a Power node with the the first input set to the exponent (in this case '2') and the other input set to the altitude. For a 'falloff' we need a negative value and the Multiply node provides this as well as allowing the effect to be scaled. The final Multiply allows the overall density of the atmosphere to be adjusted.

falloff

As an example, if the Multiply node is set to $-1$, at the surface of the planet (0 altitude) the density would be :

$2 ^ 0 = 1$ (since anything to the power of 0 is 1)

At 1 blender unit above the surface,

$2 ^ {-1} = 0.5$

At 2 blender units above the surface,

$2 ^ {-2} = 0.25$

At 3 blender units above the surface,

$2 ^ {-3} = 0.125$

ie, The density falls off exponentially.

Adjusting the Falloff Factor to larger negative values will give a faster falloff.


EDIT: With your sample Blend file the patterns you are seeing are a result of rounding errors in the exponential falloff being amplified by the 250 multiplication factor (you have an atmosphere that is dropping off very sharply conflicting with it being very dense). Using your sample Blend file as a start point, perform the following steps :

  • Scale the Earth Atmo mesh by a factor of 2
  • Remove the unnecessary Subdivision Surface modifier
  • In the Earth Atmo shader, change the Multiply factor from 250 to 2
  • Change the division factor from 0.0012557 to 0.012557
  • In the Render settings change from Path Tracing to Branched Path Tracing (this renders the volumetrics better)

This should then produce the following result :

result from amended blend file

$\endgroup$
  • $\begingroup$ Just a note, it might be less cumbersome implementing complex calculations like this using OpenShadingLanguage scripts rather than lots of Cycles nodes. $\endgroup$ – Lawrence D'Oliveiro Oct 18 '17 at 6:22
  • 2
    $\begingroup$ @LawrenceD'Oliveiro and losing ability to use GPU rendering... $\endgroup$ – cgslav Oct 19 '17 at 2:14
  • $\begingroup$ Wow, thank you so much Rich! This is the best method I've seen yet and the closest to what I'm trying to achieve. The only thing I don't understand is: why isn't the density going all the way to 0 in a spherical shape around the planet sphere? Why does it need to go all the way to the edge of the domain and cutoff abruptly? $\endgroup$ – CPLTarun Oct 21 '17 at 4:07
  • $\begingroup$ This is the equation I've been trying to implement: density = exp(-h/8000m) or density = e^(-h/8000), where h is the altitude in meters So I implemented your vector math to get the altitude. From there, I multiplied it by -1 (to get -h), divided by 0.0012557 (which I think is 8km compared to the planet diameter of 2 units in blender). I then plugged in the output to the second input of a power node, the first value being e (2.718...). I get a weird artifact where the atmosphere gets more and more transparent near the poles of the Earth. I'm not sure why. My atmosphere is a sphere. $\endgroup$ – CPLTarun Oct 21 '17 at 5:32
  • 1
    $\begingroup$ Many thanks for the bounty @cegaton - very much appreciated. $\endgroup$ – Rich Sedman Oct 24 '17 at 22:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.