Planet shader and atmosphere scattering

@normen, That’s truly a honor for me. :slight_smile:

While we are at it, you don’t mind if I use it as well for my space game do you?

I might as well get in line too as my game is space themed! :smiley:



But I’m a very long way from having to use that though, but it doesn’t hurt to ask in advance! :slight_smile:

Seems like you are the new super star xD



I have a few questions for my game scene

In the game scene the spaceship “Arche” is flying around the planet.

What value must I change to get a red planet, instead of a blue one (textures are already swapped) and I want to increase the stratos sphere. Should look like an “evil” planet.

Hope you can help! xD

@EmpirePhoenix, @madjack, you are welcome. No need to ask at all guys.



@DarkPhoenix,

There are twekable RGB values in the planet for the atmosphere color. The final color used however is the inverse of these values power of 4, so the lower the Red the more redish it will be.



The default values are the blue earthly color (more or less): Use it as reference: wavelength = new Vector3f(0.731f, 0.612f, 0.455f);



As you see, the blue component is the lowest, maybe just swaping them to make the red the lowest would be a good start. You can tweak them in the demo.



The proportion between the ground and the outer atmosphere radius can’t be changed unfortunatelly. The equations are not ready for that, but if you want to play with it, change the Planet:getOuterRadius method to return a bigger radius for the outer sphere. The very sensible depth function requires that this proportion be 1.025. All you can do safely is to give more or less intensity to the atmosphere, tweaking ESun (sun intensity), and the Rayleigh and Mie scattering constants (Km and Kr), so you can get a lighter, thinner atmosphere or a dense and thicker one, within some constraints.





@normen, just watched the new video. Its awesome! And that “Contact” style cue has no price :D.

jiyarza said:
@EmpirePhoenix, @madjack, you are welcome. No need to ask at all guys.


Nonesense! :P If someone would want part of my code, I hope they would ask for my permission. :)

Thanks! :D I'll take care of your work, although it's possible you won't be able to recognize it when I'm done with it. ;)

I am revisiting this since the shaders stopped working a while ago. I have already corrected some minor details and made it a bit more JME3 friendly I think. But the planet is still just a black hole so the error has to be inside the shader code. Is there any sensible change in the way shaders work that I should be aware of in the last month or so? Any clue will be welcome.



Thanks.

One thing we changed is that you can’t specify “#version 110” in the shader itself anymore, you have to specify it in the material, e.g.:

VertexShader GLSL110 : Common/MatDefs/Misc/SomeShader.vert

Yes, that is one of the things I have corrected already. It failed at compile time so that one was easy.



Other details I have changed:


  • Removed m_ in param names
  • RenderState values are now set within the material definition instead of by code.



    Is there anything different related to uniforms?





    Thanks!

It is working again (also made a few cleanup and improvements).



The solution has been… wierd. I had to change all uniform names to have the “m_” prefix within the shaders (and only within them, the material declaration and the names set from the Java code are without “m_”). I think this behaviour is not intended. But otherwise it does not work.



Also two uses of the WorldViewProjectionMatrix had to be changed to WorldMatrix transformations to work just as before. I think this transformation is now correct and before it made little sense, since it was to be used with other world coordinates (but it didn’t work with WorldMatrix).





@normen, for the welcome screen to work again, you will have to update the shaders code.



EDIT: I will add a link to the repo in the first post.



Cheers.

Coll you got it working again. In fact the m_ prefix is gone except in the shaders, that is correct.

jiyarza said:
The solution has been... wierd. I had to change all uniform names to have the "m_" prefix within the shaders (and only within them, the material declaration and the names set from the Java code are without "m_"). I think this behaviour is not intended. But otherwise it does not work.

Yes it's intended, Material parameters have no m_ anymore, but, when passing them to the shader we add the m_ prefix to them.
The idea is to be consistent with the global parameters that have th g_ prefix.
So any user made uniforms have a m_ prefix and global uniforms passed by the engine has a g_ prefix.
But..the far end user doesn't have to know that so he can use for example material.setColor("Color",color);

Hey, I am trying to use the atmosphere project like a library for the jMP WelcomeScreen instead of “hacking” it in but I have a problem: The planet AppState uses a static reference to the application instance. Do you think its possible replacing these with references to assetManager and sun location passed to the constructor of the AppState?

Cheers,

Normen

Created a patch for that:

[patch]

This patch file was generated by NetBeans IDE

Following Index: paths are relative to: /Users/normenhansen/jMonkeyProjects/atmosphere/src/atmosphere

This patch can be applied using context Tools: Patch action on respective folder.

It uses platform neutral UTF-8 encoding and n newlines.

Above lines and this line are ignored by the patching process.

Index: PlanetRendererState.java

— PlanetRendererState.java Base (BASE)

+++ PlanetRendererState.java Locally Modified (Based On LOCAL)

@@ -3,10 +3,12 @@

import com.jme3.app.Application;

import com.jme3.app.state.AppState;

import com.jme3.app.state.AppStateManager;

+import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.queue.RenderQueue.Bucket;

+import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.texture.Texture;

import com.jme3.util.TangentBinormalGenerator;

@@ -22,7 +24,6 @@

private static final String MAT_GROUND_FROM_ATMOSPHERE ="MatDefs/GroundFromAtmosphere.j3md";

private static final String MAT_SKY_FROM_SPACE ="MatDefs/SkyFromSpace.j3md";

private static final String MAT_SKY_FROM_ATMOSPHERE ="MatDefs/SkyFromAtmosphere.j3md";

  • private Prototype prototype;

    private Planet planet;

    // Ground sphere

    private Spatial ground;

    @@ -37,9 +38,11 @@

    private Material mGroundFromAtmosphere, mSkyFromAtmosphere;

    // time acc for rotation

    private float time;
  • private Application prototype;
  • private DirectionalLight sun;


  • public PlanetRendererState(Planet planet) {
  •    this.prototype = Prototype.getInstance();<br />
    
  • public PlanetRendererState(Planet planet, DirectionalLight sun) {
  •    this.sun = sun;<br />
    

this.planet = planet;

this.time = 0.0f;

}

@@ -50,7 +53,7 @@

Vector3f cameraLocation = prototype.getCamera().getLocation();

Vector3f planetToCamera = cameraLocation.subtract(planet.getPosition());

float cameraHeight = planetToCamera.length();

  •    Vector3f lightPosNormalized = prototype.sun.getDirection();<br />
    
  •    Vector3f lightPosNormalized = sun.getDirection();<br />
    

// easy collision detection
float r = planet.getInnerRadius();
@@ -59,11 +62,11 @@
}

// change speed if necessary
- if (cameraHeight < (r * 1.025)) {
- prototype.atmosphericSpeed();
- } else {
- prototype.outerSpaceSpeed();
- }
+// if (cameraHeight < (r * 1.025)) {
+// prototype.atmosphericSpeed();
+// } else {
+// prototype.outerSpaceSpeed();
+// }


// choose correct material according to camera position
@@ -140,7 +143,7 @@
mat.setTexture("Diffuse1", t_diffuse1);
mat.setTexture("Diffuse2", t_diffuse2);
mat.setFloat("Speed", planet.getRotationSpeed());
- mat.setVector3("v3LightPos", prototype.sun.getDirection().normalize());
+ mat.setVector3("v3LightPos", sun.getDirection().normalize());
mat.setVector3("v3InvWavelength", planet.getInvWavelength4());
mat.setFloat("fKrESun", planet.getKrESun());
mat.setFloat("fKmESun", planet.getKmESun());
@@ -162,7 +165,7 @@
* @param mat
*/
private void setupSkyMaterial(Material mat) {
- mat.setVector3("v3LightPos", prototype.sun.getDirection().normalize());
+ mat.setVector3("v3LightPos", sun.getDirection().normalize());
mat.setVector3("v3InvWavelength", planet.getInvWavelength4());
mat.setFloat("fKrESun", planet.getKrESun());
mat.setFloat("fKmESun", planet.getKmESun());
@@ -209,6 +212,7 @@

public void initialize(AppStateManager stateManager, Application app) {
this.time = 0.0f;
+ this.prototype = app;

// x2048
// t_diffuse1 = prototype.getAssetManager().loadTexture("Textures/world.topo.bathy.200404.3x5400x2700.jpg");
@@ -233,8 +237,9 @@
update(0);

// draw
- prototype.getRootNode().attachChild(ground);
- prototype.getRootNode().attachChild(atmosphere);
+ Node rootNode=(Node)app.getViewPort().getScenes().get(0);
+ rootNode.attachChild(ground);
+ rootNode.attachChild(atmosphere);
}

public boolean isInitialized() {
@@ -252,6 +257,8 @@
}

public void stateDetached(AppStateManager stateManager) {
+ ground.removeFromParent();
+ atmosphere.removeFromParent();
}

public void render(RenderManager rm) {
[/patch]
[patch]# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /Users/normenhansen/jMonkeyProjects/atmosphere/src/atmosphere
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and n newlines.
# Above lines and this line are ignored by the patching process.
Index: Prototype.java
--- Prototype.java Base (BASE)
+++ Prototype.java Locally Modified (Based On LOCAL)
@@ -41,7 +41,7 @@
// Singleton
private static Prototype instance;

- public DirectionalLight sun;
+ private DirectionalLight sun;
private Planet planet;
public final static Vector3f PLANET_POSITION = new Vector3f(0.0f, 0.0f, 0.0f);
public final static float PLANET_RADIUS = 200f; // Km
@@ -79,7 +79,7 @@
setupLights();

planet = new Planet(PLANET_RADIUS, PLANET_POSITION);
- stateManager.attach(new PlanetRendererState(planet));
+ stateManager.attach(new PlanetRendererState(planet, sun));
stateManager.attach(new PlanetUIState(planet));
stateManager.attach(new JukeboxState());
}
[/patch]
nehon said:
Yes it's intended, Material parameters have no m_ anymore, but, when passing them to the shader we add the m_ prefix to them.
The idea is to be consistent with the global parameters that have th g_ prefix.
So any user made uniforms have a m_ prefix and global uniforms passed by the engine has a g_ prefix.
But..the far end user doesn't have to know that so he can use for example material.setColor("Color",color);


Ah, ok then. Thanks for the explanation, now it's clear.


@normen, of course, thanks for the patch.

Hi,



I noticed that the shader only works in specific conditions. For example it works for me only if the planet stay on position 0,0,0. If I translate the planet the atmosphere disapear or looks very odd. Same seems to be valid for scaling. I think the original implementaion from o’neil have the same problems.

I tried to look into it but my grasp of shaders i somewhat limeted ;).



Anybody an idea what might be wrong? Maybe somthing with the supplied projectionmatrix?



milchmann

Yes that’s right.



I had this in my to-do list, but have had not time yet. My guess is that all the shader parameters should be in object coordinates and so should be all calculations, and currently that’s not true. It is cooked for 0,0,0.





Cheers.

this is awesome …

I investigate !

@jiyarza said:
Yes that's right.

I had this in my to-do list, but have had not time yet. My guess is that all the shader parameters should be in object coordinates and so should be all calculations, and currently that's not true. It is cooked for 0,0,0.


is there any progress solving this issue?

Hi monkeys,

I’m trying to keep this thread alive even if it is a while from jiyarza last post. Looking around I found this

Planets 9 Atmospheric Scattering - The home of Stainless

The interesting part is the very last one

Some people have had a lot of problems using this code in a game situation.
This is because the shader requires the planet to be at (0,0,0), so when you move the planet in your scene, the atmosphere will screw up.
The solution to this is simple.
Pass in another matrix which does not include a translation and use this to calculate v3pos.

I'm not a shader expert, I'm still studing it (and I haven't so much time), but maybe someone who is more confortable with GLSL and already took a look into jiyarza and original Sean O'Neill code could better understand the proposed solution.

Cheers :)