• entries
232
1462
• views
959094

# GLSL, Gas giants, Atmospheric scattering

1521 views

Gas giants:

I started to work the implementation of gas giants. My current approach is to use an outer sphere with atmospheric scattering, similar to the ones used on my Earth-like planets, and a set of layers ( six at the moment ). All of those are generated and displayed with the LOD ( level-of-detail ) algorithm used in the terrain engine, except that the spherical surface is not displaced by a heightmap.

Each layer corresponds to a cloud layer with various colors and transparencies. Each layer is textured with a cube map, so I started to generate a "gas giant style" texture for each layer with random color combinations and turbulence. Here's an example of such a texture:

The upper layers in altitude get a lower transparency while the deeper layers get more and more opaque. The bottom-most layer is fully opaque, a bit like the ground.. but I don't expect anybody to really see it, since so deep in the atmosphere, any spaceship would be dead for long..

The 6-layers idea wouldn't look very good if the layers were individually visible. Fortunately, I am hoping that with good fogging, particle/wheather effects, and good scattering, everything will blend together quite well.

The gas giant texture is procedurally generated by stretching fBm noise with a large non-uniform factor, like ( 1, 30, 1 ). This generates the straight strips. To break the straightness (english?), I am actually using another fBm which returns the amount of stretching to do. In the end, it looks like this:

float res = noise.fBm(ray * (4, 4, 4) );res = noise.fBm(ray * (1, 20 + res * factor, 1));

The first factor, (4, 4, 4), determines the size of the turbulence "features"; while the second factor ( factor ) determines how stretched the atmosphere looks. Gas giants planets are rotating very quickly around themselves, which is why their clouds are so stretched. This factor will later be determined by the astrophysical parameters of the planet like its rotation speed.

The color table at the moment is quite random. I have to study colors of gas giants and how to generate "interesting" colors. The transparency is also a function of the noise value, plugged in a simple formula. I have to tweak it too.

In the future, I will also have to experiment storms like the big red spot on Jupiter, and wheather effects such as those mentioned particles, but also lightning, etc..

Atmospheric scattering:

While working on the shaders for gas giants, I realized that my scattering equations were not giving me the expected results.

I don't know if anybody wondered.. imagine that a gas giant didn't have any cloud - just imagine a huge ball of gas in space. How would it look like ?

Let's say the camera is in the upper atmosphere of the gas giant. The sky would appear like it does on Earth: fading from black to the sky color ( blue on Earth ), with some white haze at the horizon..

But there would be no ground. So what would you see underneath ?

Scattering equations, if I'm doing no mistake, say that it should fade back to black. The exctinction coefficients depend on how much atmosphere is traversed, and underneath the camera.. there's a lot of atmosphere to traverse.. so it should be black.

Unfortunately, in my previous atmospheric scattering implementation, I saw an ocean of... white. Certainly, I was wrong somewhere.

That's pretty much the point I decided to rewrite my atmospheric scattering shaders from scratch, carefully watching the results of all the terms of the equations.. and in GLSL !

GLSL:

Until now, I've been using assembly shaders ( in OpenGL, ARB_vertex_program and ARB_fragment_program ). Usually, it was good enough, as shaders were quite simple ( a few tens of instructions at most ). But scattering shaders are a whole new beast, requiring to intersect rays and spheres, and evaluating complex equations. I was loosing too much time to debug my ASM shaders, so I decided that it was time to switch to GLSL..

I expected the GLSL implementation to be straightforward.. how wrong I was. I spent pretty much my whole last week on it. For some reason, the GLSL interface works in a pretty different way than ASM shaders; in particular, shader constants do not belong to a specific shader ( vertex shader, or pixel shader ); but to a program, which is a pair vertex + pixel shader.

It's probably not clear, but let's take an example. You have a vertex shader called VertexShader1 and a pixel shader called PixelShader1. VertexShader1 uses a constant called AtmosphereParams. To assign a value to this constant, you have to query the location of this constant in the program.. the location is an ID, so maybe it'll return 1.

Now, let's say that you use the same vertex shader but a different pixel shader: PixelShader2. Well, here is the problem: if you query the location of the constant AtmosphereParams in VertexShader1, it might return another location ID.

Fixing the issue required introducing the concepts of "virtual" constant IDs, and "real" constant IDs, and mapping one to another in real-time depending on which pair "vertex shader + pixel shader" is bound..

Once my GLSL implementation was complete, I started to experiment with the GLSL language, and so far no problem with it, it's pretty easy and much easier than coding everything in assembly.

Regarding GLSL uniforms: The solution I used was to simply cache uniform name<->location pairs in real-time per-program. Whenever a program is re-linked, the cache would be emptied.

This has the bonus of allowing me to lookup uniforms by name rather than by location, which makes the code much clearer.

Yes, that's what I ended up doing, too. But it's a bit more complex when you have to maintain the same interface for ASM shaders and HLSL :)

I don't know if anybody wondered.. imagine that a gas giant didn't have any cloud - just imagine a huge ball of gas in space. How would it look like ?

Just like Neptune, I suppose ;)
One big sphere of blue, in that case.

Quote:
 Just like Neptune, I suppose ;) One big sphere of blue, in that case.

I think you're wrong. Neptune is actually the opposite: it's completely made of very thick, opaque clouds.

Neptune aparently has a rock center... not that any spacecraft could make in anywhere near it. It'd probably be crushed by the pressure or gravity or destroyed by the heat long before getting close to it.

http://www.solarviews.com/eng/neptune.htm

Our knowledge of the internal structure of Neptune is inferred from the planet's radius, mass, period of rotation, the shape of its gravitational field and the behavior of hydrogen, helium, and water at high pressure. This cut-away view shows Neptune composed of an outer envelope of molecular hydrogen, helium and methane roughly the mass of one to two Earths. Below this region Neptune appears to be composed of a mantle rich in water, methane, ammonia, and other elements. These elements are under high temperatures and pressures deep within the planet. The mantle is equivalent to 10 to 15 earth masses. Neptune's core is composed of rock and ice, and is likely no more than one Earth mass.

I <3 GLSL

Hello Flavien,

I am an old university's relationship.
I'm fallen on yours articles relating ShaderX2 programing (DirectX9).
If you want to speak about our professional experience, i let you my Email adress: doucets@free.fr
I ll be happy to know what you become today !!!

See you soon

Seb D.