Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Atmospheric Scattering help

Discussion in 'Shaders' started by PRD, Jul 29, 2008.

  1. Sbach

    Sbach

    Joined:
    May 18, 2010
    Posts:
    9
    If you want to make a SkyFromAtmosphere shader you can try what i've made using Sean O'Neil's shaders and the scripts form the forum.

    It's really like what you've made, gonza, but there are 3 places where i got different things after copying form O'Neil's shaders.

    Edit: Diffs:

    float cameraAngle = dot(-v3Ray,dot(v3Ray, samplePoint) / height;

    float v3StartDepth = exp (_fScaleOverScaleDepth * (_fInnerRadius( - _fInnerRadius + _fCameraHeight));

    float3 v3Start = v3Pos _v4CameraPos.xyz;


    Hope it will help.

    Screenshots :








    Code :


    Code (csharp):
    1.  
    2. Shader "NewShader" {
    3.    Properties {
    4.      _v4CameraPos("Camera Position",Vector) = (0,0,0,0)
    5.      _v4LightDir("Light Direction",Vector) = (0,0,0,0)
    6.      _cInvWaveLength("Inverse WaveLength",Color) = (0,0,0,0)
    7.      _fCameraHeight("Camera Height",Float) = 0
    8.      _fCameraHeight2("Camera Height2",Float) = 0
    9.      _fOuterRadius("Outer Radius",Float) = 0
    10.      _fOuterRadius2("Outer Radius 2",Float) = 0
    11.      _fInnerRadius("Inner Radius",Float) = 0
    12.      _fInnerRadius2("Inner Radius 2",Float) = 0
    13.      _fKrESun("KrESun",Float) = 0
    14.      _fKmESun("KmESun",Float) = 0
    15.      _fKr4PI("Kr4PI",Float) = 0
    16.      _fKm4PI("Km4PI",Float) = 0
    17.      _fScale("Scale",Float) = 0
    18.      _fScaleDepth("Scale Depth",Float) = 0
    19.      _fScaleOverScaleDepth("Scale Over Scale Depth",Float) = 0
    20.      _Samples("Samples",Float) = 0
    21.      _G("G",Float) = 0
    22.      _G2("G2",Float) = 0
    23.    }
    24.    SubShader {
    25.      Tags {"Queue" = "Transparent" }
    26.       Pass {
    27.          Cull Front
    28.          Blend One One
    29.          
    30. CGPROGRAM
    31. #pragma vertex vert
    32. #pragma fragment frag
    33. #include "UnityCG.cginc"
    34.  
    35. float4 _v4CameraPos;
    36. float4 _v4LightDir;
    37. float4 _cInvWaveLength;
    38. float _fCameraHeight;
    39. float _fCameraHeight2;    
    40. float _fOuterRadius;
    41. float _fOuterRadius2;    
    42. float _fInnerRadius;
    43. float _fInnerRadius2;
    44. float _fKrESun;
    45. float _fKmESun;
    46. float _fKr4PI;
    47. float _fKm4PI;
    48. float _fScale;
    49. float _fScaleDepth;
    50. float _fScaleOverScaleDepth;
    51. float _Samples;
    52. float _G;
    53. float _G2;
    54.  
    55. struct v2f {
    56.   float4 position : POSITION;
    57.   float3 c0 : COLOR0;
    58.   float3 c1 : COLOR1;
    59.   float3 t0 : TEXCOORD0;
    60. };
    61.  
    62. float expScale (float cos) {
    63.    float x = 1 - cos;
    64.    return _fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
    65. }
    66.  
    67. v2f vert (float4 vertex : POSITION) {
    68.   float3 v3Pos = vertex.xyz;
    69.   float3 v3Ray = v3Pos - _v4CameraPos.xyz;
    70.   float fFar = length(v3Ray);
    71.   v3Ray /= fFar;  
    72.  
    73. float3 v3Start = _v4CameraPos.xyz;
    74.  
    75.  
    76.   float v3StartAngle = dot(v3Ray,v3Start) / length(v3Start);
    77.  
    78.   float v3StartDepth = exp (_fScaleOverScaleDepth * ( - _fInnerRadius + _fCameraHeight));
    79.  
    80.   float v3StartOffset = v3StartDepth * expScale(v3StartAngle);
    81.  
    82.   float fSampleLength = fFar / _Samples;
    83.   float fScaledLength = fSampleLength * _fScale;
    84.   float3 sampleRay = v3Ray * fSampleLength;
    85.   float3 samplePoint = v3Start + sampleRay * 0.5f;
    86.  
    87.   float3 frontColor = float3(0,0,0);
    88.   float3 attenuate;
    89.  
    90.   for (int i = 0; i < 1; i++) {
    91.     float height = length (samplePoint);
    92.     float depth = exp(_fScaleOverScaleDepth * (_fInnerRadius - height));
    93.     float lightAngle = dot(_v4LightDir.xyz, samplePoint) / height;
    94.     float cameraAngle = dot(v3Ray, samplePoint) / height;
    95.     float scatter = (v3StartOffset + depth * (expScale (lightAngle) - expScale (cameraAngle)));
    96.  
    97.     attenuate = exp(-scatter * (_cInvWaveLength.xyz * _fKr4PI + _fKm4PI));
    98.     frontColor += attenuate * (depth * fScaledLength);
    99.     samplePoint += sampleRay;
    100.   }
    101.  
    102.   v2f OUT;
    103.   OUT.position = mul( glstate.matrix.mvp, vertex);
    104.   OUT.t0 = _v4CameraPos.xyz - vertex.xyz;
    105.   OUT.c0.rgb = frontColor * (_cInvWaveLength.xyz * _fKrESun);
    106.   OUT.c1.rgb = frontColor * _fKmESun;
    107.   return OUT;
    108. }
    109.  
    110. float4 frag (v2f INPUT) : COLOR {
    111.   float cos = dot(_v4LightDir.xyz, INPUT.t0) / length(INPUT.t0);
    112.   float cos2 = cos * cos;
    113.   float miePhase = 1.5 * ((1.0 - _G2) / (2.0 + _G2)) * (1.0 + cos2) / pow(1.0 + _G2 - 2.0*_G*cos, 1.5);
    114.   float rayleighPhase = 0.75 * (1.0 + cos2);
    115.  
    116.   //fmiePhase *= 0.0015 * 15;
    117.   //rayleighPhase *= 0.0025 * 15;
    118.  
    119.   float4 fragColor;
    120.  
    121.   fragColor.xyz = (rayleighPhase * INPUT.c0) + (miePhase * INPUT.c1);
    122.   fragColor.w = fragColor.z;
    123.  
    124.   if(fragColor.x > 1.0){ fragColor.x = 1.0;}
    125.   if(fragColor.y > 1.0){ fragColor.y = 1.0;}
    126.   if(fragColor.z > 1.0){ fragColor.z = 1.0;}
    127.  
    128.   return fragColor;  
    129. }
    130.  
    131. ENDCG  
    132.       }
    133.    }
    134.    FallBack "None"
    135. }
    136.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class NewShader : MonoBehaviour {
    6.  
    7.     public Transform mainCamera;
    8.     public GameObject sunLight;
    9.     private Vector3 sunLightDirection;
    10.     private Color waveLength;
    11.     private Color invWaveLength;
    12.     private float cameraHeight;
    13.     private float cameraHeight2;
    14.     private float outerRadius;
    15.     private float outerRadius2;
    16.     private float innerRadius;
    17.     private float innerRadius2;
    18.     public float ESun;
    19.     public float Kr;
    20.     public float Km;
    21.     private float KrESun;
    22.     private float KmESun;
    23.     private float Kr4PI;
    24.     private float Km4PI;
    25.     private float scale;
    26.     private float scaleDepth;
    27.     private float scaleOverScaleDepth;
    28.     private float samples;
    29.     private float g;
    30.     private float g2;
    31.    
    32.     void Start() {
    33.       sunLight = GameObject.Find("Sun");
    34.       mainCamera = GameObject.Find("Main Camera").transform;
    35.       sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    36.       waveLength = new Color(0.650f, 0.570f, 0.475f, 0.5f);
    37.       invWaveLength = new Color (pow(waveLength[0],4),pow(waveLength[1],4),pow(waveLength[2],4),0.5f);
    38.       cameraHeight = mainCamera.position.magnitude;
    39.       outerRadius = 6530.28f;
    40.       outerRadius2 = outerRadius * outerRadius;
    41.       innerRadius = 6371;
    42.       innerRadius2 = innerRadius * innerRadius;
    43.       ESun = 15;
    44.       Kr = 0.0025f;
    45.       Km = 0.0015f;
    46.       KrESun = Kr * ESun;
    47.       KmESun = Km * ESun;
    48.       Kr4PI = Kr * 4.0f * Mathf.PI;
    49.       Km4PI = Km * 4.0f * Mathf.PI;
    50.       scale = 1 / (outerRadius - innerRadius);
    51.       scaleDepth = 0.25f;
    52.       scaleOverScaleDepth = scale / scaleDepth;
    53.       samples = 4;
    54.       g = -0.85f;
    55.       g2 = g*g;
    56.     }
    57.    
    58.     //void OnGUI() {
    59.       //if (debug) {
    60.         //waveLength = DebugUtility.RGBSlider (new Rect (10,10,100,20), waveLength);
    61.         //ESun = DebugUtility.LabelSlider(new Rect (10,70,100,20), ESun, 50,"ESun: " + ESun );
    62.         //Kr = DebugUtility.LabelSlider(new Rect (10,90,100,20), Kr, 0.01f,"Kr: " + Kr);
    63.         //Km = DebugUtility.LabelSlider(new Rect (10,110,100,20), Km, 0.01f,"Km: " + Km);
    64.         //scaleDepth = DebugUtility.LabelSlider(new Rect (10,130,100,20), scaleDepth, 1.0f,"Scale Depth: " + scaleDepth);
    65.         //g = DebugUtility.LabelSlider(new Rect (10,150,100,20), g, -1.0f,"G: " + g);
    66.       //}
    67.     //}
    68.    
    69.     // Update is called once per frame
    70.     void LateUpdate () {
    71.        
    72.       KrESun = Kr * ESun;
    73.       KmESun = Km * ESun;
    74.       Kr4PI = Kr * 4.0f * Mathf.PI;
    75.       Km4PI = Km * 4.0f * Mathf.PI;
    76.        
    77.       sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    78.       cameraHeight = mainCamera.position.magnitude;
    79.       cameraHeight2 = cameraHeight * cameraHeight;
    80.      
    81.       // Pass in variables to the Shader
    82.       renderer.material.SetVector("_v4CameraPos",new Vector4(mainCamera.position[0],mainCamera.position[1],mainCamera.position[2], 0));
    83.      
    84.       renderer.material.SetVector("_v4LightDir", new Vector4(sunLightDirection[0],sunLightDirection[1],sunLightDirection[2],0));
    85.       renderer.material.SetColor("_cInvWaveLength", invWaveLength);
    86.       renderer.material.SetFloat("_fCameraHeight", cameraHeight);
    87.       renderer.material.SetFloat("_fCameraHeight2", cameraHeight2);
    88.       renderer.material.SetFloat("_fOuterRadius", outerRadius);
    89.       renderer.material.SetFloat("_fOuterRadius2", outerRadius2);
    90.       renderer.material.SetFloat("_fInnerRadius", innerRadius);
    91.       renderer.material.SetFloat("_fInnerRadius2", innerRadius2);
    92.       renderer.material.SetFloat("_fKrESun",KrESun);
    93.       renderer.material.SetFloat("_fKmESun",KmESun);
    94.       renderer.material.SetFloat("_fKr4PI",Kr4PI);
    95.       renderer.material.SetFloat("_fKm4PI",Km4PI);
    96.       renderer.material.SetFloat("_fScale",scale);
    97.       renderer.material.SetFloat("_fScaleDepth",scaleDepth);
    98.       renderer.material.SetFloat("_fScaleOverScaleDepth",scaleOverScaleDepth);
    99.       renderer.material.SetFloat("_Samples",samples);
    100.       renderer.material.SetFloat("_G",g);
    101.       renderer.material.SetFloat("_G2",g2);
    102.     }
    103.    
    104.     float pow(float f, int p) {
    105.       return 1 / Mathf.Pow(f,p);
    106.     }
    107. }
    108.  
     
  2. qtsohg

    qtsohg

    Joined:
    Oct 11, 2010
    Posts:
    4
    Hey all,

    I was just wondering if anyone has tried these Shaders in Unity 3.0?

    The reason I ask is that, try as I might, I cannot get them to work and hence was wondering if anyone else has these problems. I hooked them up to my own scene and subsequently downloaded the example provided by PRD, but no luck.

    Any suggestions would be welcome!

    q
     
  3. Sbach

    Sbach

    Joined:
    May 18, 2010
    Posts:
    9
    I also tried to rewrite the shaders for Unity 3.0 but it's not working.
    If someone can give hints to how to convert the shaders to 3.0, he' ll be welcome.

    [Edit] I think i found the solution with surface shaders, i'm on my way, starting with SkyFromGround...
     
    Last edited: Nov 7, 2010
  4. PRD

    PRD

    Joined:
    Jan 31, 2008
    Posts:
    29
    I am going to try to rewrite these as surface shaders as well. I will post them when we finish moving our project into Unity3. This will include SkyFromGround, SkyFromSpace and GroundFromSpace.
     
  5. the_gnoblin

    the_gnoblin

    Joined:
    Jan 10, 2009
    Posts:
    722
    If these shaders do not need to react to Unity's lighting, then there's no need for implementing them as a surface shader, afaik.
     
  6. nickfourtimes

    nickfourtimes

    Joined:
    Oct 13, 2010
    Posts:
    219
    Hm. Not to bump this pre-emptively, but has there been any motion on this, PRD? I'm looking at your prior example in Unity 3, and I still can't seem to make it work (for one thing, the vertex shader gets unrolled by CG and shatters the instruction limit).

    Any thoughts?
     
  7. nikko

    nikko

    Joined:
    Mar 20, 2009
    Posts:
    436
    I am in the process to make something similar. I got the GroundFromSpace shader with day/night and some kind of custom bump mapping but I had to partially change the Neil algorithm and use a gradient to get a good visual result it took me weeks to get it to work...

    For the atmosphere I have sent a bug report (case #388467) with several example of what I think makes this shader not compatible with Unity 3.
    Logically there is no need to use surface shader, because there is no interaction with the light or the shadows. I think there is maybe a bug in the blending system that prevent this shader to work? I have submitted the source code with the bug report, hopefully I will get some interesting answer soon. Still working on it when I have some free time.
     

    Attached Files:

    Last edited: Jan 17, 2011
  8. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    Sorry to resurrect this post, but I'm in real need of an atmospheric scattering setup, and my knowledge of shader programming is really not up to the task (to say the least)...

    So, I've downloaded the package from page 2 and imported into my project, but it doesn't look at all like the screenshots... tweaking the shader parameters I sometimes get a grayish gradient, that looks real bad, and that's as far as I got...

    I also created shaders from pretty much all the code posted on this thread, but that worked even less, since the shader needs a script to keep it updated, and that requires knowing what values to give to those parameters... regardless, even tweaking up a looks-good-from-one-angle situation by pure trial-and-error, I can't get anything that looks even remotely similar to the shots here...

    I notice scale has a big impact on the shaders... but I'm at a loss as to how to figure out those values...

    Also, I'm on Unity 3.2... Are the shaders completely incompatible?
    (None of the webplayer previews posted seem to work for me... the player crashes every time)

    (GPU is Nvidia GTX460... more recent than the original shader itself ;) )

    So, can anyone offer any help on this?

    As always, thanks in advance!!

    Cheers
     
    Last edited: Mar 8, 2011
  9. kflint8@gmail.com

    kflint8@gmail.com

    Joined:
    Mar 30, 2011
    Posts:
    2
    Tried PRD's atmospheric scattering example but the atmosphere doesn't work. I tried fixing it myself but I'm horrible when it comes to math + programming. Is this because of Unity 3? Do you need pro for this to work? Help?
     
  10. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    Ok, I got the shaders to work on Unity 3. (Pro, but shouldn't matter)...

    It really wasn't easy... took me a few days of trying...

    I could only get it to work after reading Sean O'Neil's article some 4 or 5 times... and understanding exactly what each parameter is and how it's calculated.
    Then I got a sphere, and gave it the AtmosphereFromSpace shader, without the controller script, and tweaked the values until I saw something change... then I went about changing and unchanging things until I saw that it did in fact work.

    I then had to modify the controller scripts a little to allow for experimenting and tweaking... this script is feeding the shader it's values, so it'll lock the editor controls...

    First thing I did was to make every single variable public, and comment out some arbitrary values that are fed into it on Start(), so I could tweak them in the editor... then I put some code in the update function to keep the values that are derived from others updated... and got to tweaking...

    So here's what I've found:

    Scale does NOT actually matter... what matters is that OuterRadius and InnerRadius are in proportion to the world radius of the sphere object.
    For the sphere object, I highly recommend using a sphere that is 1 unit in radius... this way, it's scale property will also be it's world radius and you'll save yourself a big headache. The atmosphere_100 mesh that comes included works fine for that.

    Outer Radius must be exactly the sphere's radius.
    Inner radius must be Outer Radius * 0.975... 2.5% less than the atmosphere's radius. This is the most important thing... the atmosphere only works with real-world proportions, so if your world is 100 units in radius, your atmosphere should be 102.5 units.
    The paper says if you would tweak that proportion, you must also account for the hard-coded density and depth equations there... those were hardcoded in, since the shader was much too heavy with the original calculations... I actually tried to modify the scale depth equation, but if you (like me) aren't really good at calculus and numerical analysis, I'd say don't go there...

    The shader can also fail if the sphere is perfectly round... (don't ask)... what I did to solve this was to give it a little nudge on it's x scale, from 100 to 100.1... pretty unnoticeable by eye, and it made the shader work... I guess these shaders account for the oblateness of Earth? Or it may just be a bug...

    One more thing... the controller scripts have public fields for the sun light and the target camera, and you might me inclined to drag and drop yours in... then you get an error... turns out that despite having a public reference to those objects, the scripts are trying to find them by name on Start()... I just commented those lines out, so I could have my own objects with whatever names I wished them to have.

    BTW, if you're trying (like me) to make some kind of accurate scale model of a planet with this, Unity will wrong you when you try to make your sphere a few dozen km wide... unity is no good with very large objects, and floats will lose precision and actually cause framerate losses when they're too small (really small numbers happen a lot on really big scales)... what I did was have 2 'scenes' within the scene...

    One is the main game scene, where 1 unit = 1 meter, so as to not upset physX and it's rigid scaling thing. The other has the planet as a 100 unit radius sphere (actually, one for each shader), and a camera with a controller script that will have it follow the motions of the main camera, but on a proportional scale... this camera renders behind the main one, and that worked quite well :) ...This approach will also work for planets that should be somewhere other than world 0,0,0... just have your scaled 'subscene' there, and the actual planet somewhere else.

    I also strongly suggest writing or grabbing a Sun script to control your sun light's position (there's one in the Wiki, IIRC). This will make it easier (and awesomer) to test out different values and see how that affects every phase of the day, without having to pan around to be on different 'time zones' and see the effect from there.

    Well, that's about all the help I can offer at this point. I'm still trying to tweak it so it looks more realistic... right now it looks pretty much as the screenshots from the previous pages... I'm trying to make the atmosphere seem thicker... right now it looks way to tenuous, which might be good for a NASA web app (which was it's original purpose I believe), but doesn't really cut it for a game taking place on a planet's surface...

    Has anyone been able to tweak the apparent atmospheric density, without screwing up other things? This shader is VERY finnicky, and all tweaks must be done with the greatest caution... Some values will range from 0.000something to 0.001something... and unity's inspector will very easily overrun those values as you drag them about, which makes it really hard to fine-tune it...
    What I'm trying to achieve is an almost white horizon line, and a dark-ish blue zenith at surface level.... right now it's more like a darkish blue at horizon and a pitch black zenith, as if the atmosphere was actually 100x thinner than what it's supposed to be... I heard PRD (or Nikko, can't remember) toned it down for his purpose, so I wonder if the shaders included here are the toned down versions...

    Thanks in advance for any help on this ;)

    Cheers
     
  11. kflint8@gmail.com

    kflint8@gmail.com

    Joined:
    Mar 30, 2011
    Posts:
    2
    Hey, I tried plugging in HarvesteR's values and I finally got something to happen with the atmosphere but its not at all what an atmosphere looks like. Its always white and it seems to be flipped; you can see what I mean in the picture below.

    $Untitled.png

    I can't figure this out for my life.
    What am I doing wrong???
    This is the C sharp script i'm using:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AtmosphereFromSpace : MonoBehaviour {
    5.  
    6.     public Transform mainCamera;
    7.     public GameObject sunLight;
    8.     public Vector3 sunLightDirection;
    9.     public Color waveLength;
    10.     public Color invWaveLength;
    11.     public float cameraHeight;
    12.     public float cameraHeight2;
    13.     public float outerRadius;
    14.     public float outerRadius2;
    15.     public float innerRadius;
    16.     public float innerRadius2;
    17.     public float ESun;
    18.     public float Kr;
    19.     public float Km;
    20.     public float KrESun;
    21.     public float KmESun;
    22.     public float Kr4PI;
    23.     public float Km4PI;
    24.     public float scale;
    25.     public float scaleDepth;
    26.     public float scaleOverScaleDepth;
    27.     public float samples;
    28.     public float g;
    29.     public float g2;
    30.    
    31.     void Start() {
    32.       sunLight = GameObject.Find("Sun");
    33.       mainCamera = GameObject.Find("Main Camera").transform;
    34.       sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    35.       waveLength = new Color(0.650f, 0.570f, 0.475f, 0.5f);
    36.       invWaveLength = new Color (pow(waveLength[0],4),pow(waveLength[1],4),pow(waveLength[2],4),0.5f);
    37.       cameraHeight = mainCamera.position.magnitude;
    38.       ESun = 15;
    39.       Kr = 0.0025f;
    40.       Km = 0.0015f;
    41.       KrESun = Kr * ESun;
    42.       KmESun = Km * ESun;
    43.       Kr4PI = Kr * 4.0f * Mathf.PI;
    44.       Km4PI    = Km * 4.0f * Mathf.PI;
    45.       scale = 1 / (outerRadius - innerRadius);
    46.       scaleDepth = 0.25f;
    47.       scaleOverScaleDepth = scale / scaleDepth;
    48.       samples = 4;
    49.       g = -0.95f;
    50.       g2 = g*g;
    51.     }
    52.    
    53.     //void OnGUI() {
    54.       //if (debug) {
    55.         //waveLength = DebugUtility.RGBSlider (new Rect (10,10,100,20), waveLength);
    56.         //ESun = DebugUtility.LabelSlider(new Rect (10,70,100,20), ESun, 50,"ESun: " + ESun );
    57.         //Kr = DebugUtility.LabelSlider(new Rect (10,90,100,20), Kr, 0.01f,"Kr: " + Kr);
    58.         //Km = DebugUtility.LabelSlider(new Rect (10,110,100,20), Km, 0.01f,"Km: " + Km);
    59.         //scaleDepth = DebugUtility.LabelSlider(new Rect (10,130,100,20), scaleDepth, 1.0f,"Scale Depth: " + scaleDepth);
    60.         //g = DebugUtility.LabelSlider(new Rect (10,150,100,20), g, -1.0f,"G: " + g);
    61.       //}
    62.     //}
    63.    
    64.     // Update is called once per frame
    65.     void LateUpdate () {
    66.       sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    67.       cameraHeight = mainCamera.position.magnitude;
    68.       cameraHeight2 = cameraHeight * cameraHeight;
    69.      
    70.       // Pass in variables to the Shader
    71.       renderer.material.SetVector("_v4CameraPos",new Vector4(mainCamera.position[0],mainCamera.position[1],mainCamera.position[2], 0));
    72.      
    73.       renderer.material.SetVector("_v4LightDir", new Vector4(sunLightDirection[0],sunLightDirection[1],sunLightDirection[2],0));
    74.       renderer.material.SetColor("_cInvWaveLength", invWaveLength);
    75.       renderer.material.SetFloat("_fCameraHeight", cameraHeight);
    76.       renderer.material.SetFloat("_fCameraHeight2", cameraHeight2);
    77.       renderer.material.SetFloat("_fOuterRadius", outerRadius);
    78.       renderer.material.SetFloat("_fOuterRadius2", outerRadius2);
    79.       renderer.material.SetFloat("_fInnerRadius", innerRadius);
    80.       renderer.material.SetFloat("_fInnerRadius2", innerRadius2);
    81.       renderer.material.SetFloat("_fKrESun",KrESun);
    82.       renderer.material.SetFloat("_fKmESun",KmESun);
    83.       renderer.material.SetFloat("_fKr4PI",Kr4PI);
    84.       renderer.material.SetFloat("_fKm4PI",Km4PI);
    85.       renderer.material.SetFloat("_fScale",scale);
    86.       renderer.material.SetFloat("_fScaleDepth",scaleDepth);
    87.       renderer.material.SetFloat("_fScaleOverScaleDepth",scaleOverScaleDepth);
    88.       renderer.material.SetFloat("_Samples",samples);
    89.       renderer.material.SetFloat("_G",g);
    90.       renderer.material.SetFloat("_G2",g2);
    91.     }
    92.    
    93.     float pow(float f, int p) {
    94.       return 1 / Mathf.Pow(f,p);
    95.     }
    96. }
    97.  
    I tweaked it a little bit so I could insert manual values for the inner and outer radius.
    For the shader script i'm just using PDR's; the one that came with the example project he posted on page 2.

    Can someone solve me this?

    Possibly post an example project that works in Unity 3?
     
  12. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    I was going to post a large list of ideas, but I think it's best to just post the script I'm using here.

    I have it set for a 1-unit radius sphere... So, with a sphere mesh 1 unit large, give it a localScale of X:100.1, Y:100.0, Z:100.0... the outer radius will be automatically gleaned from it's Y scale, and the InnerRadius from the outer one... not exactly optimal, but convenient... You can give it other scales if you want though... just remember to set X to .1 higher than the others.

    And give it this script (this is for AtmosphereFromSpace):

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class AtmosphereFromSpace : MonoBehaviour {
    6.  
    7.     public Transform mainCamera;
    8.     public GameObject sunLight;
    9.     public Vector3 sunLightDirection;
    10.     public Color waveLength;
    11.     public Color invWaveLength;
    12.     public float cameraHeight;
    13.     public float cameraHeight2;
    14.     public float outerRadius;
    15.     public float outerRadius2;
    16.     public float innerRadius;
    17.     public float innerRadius2;
    18.     public float ESun;
    19.     public float Kr;
    20.     public float Km;
    21.     public float KrESun;
    22.     public float KmESun;
    23.     public float Kr4PI;
    24.     public float Km4PI;
    25.     public float scale;
    26.     public float scaleDepth;
    27.     public float scaleOverScaleDepth;
    28.     public float samples;
    29.     public float g;
    30.     public float g2;
    31.    
    32.     void Start() {
    33.         //sunLight = GameObject.Find("Sun");
    34.         //mainCamera = GameObject.Find("Main Camera").transform;
    35.         sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    36.         waveLength = new Color(0.650f, 0.570f, 0.475f, 0.5f);
    37.         invWaveLength = new Color (pow(waveLength[0],4),pow(waveLength[1],4),pow(waveLength[2],4),0.5f);
    38.         cameraHeight = mainCamera.position.magnitude;
    39.             outerRadius = transform.localScale.y;//100f;//6530.28f;
    40.             outerRadius2 = outerRadius * outerRadius;
    41.             innerRadius = outerRadius * 0.975f;//6371f;
    42.         innerRadius2 = innerRadius * innerRadius;
    43.         ESun = 15f;
    44.         Kr = 0.0025f;
    45.         Km = 0.0015f;
    46.         KrESun = Kr * ESun;
    47.         KmESun = Km * ESun;
    48.         Kr4PI = Kr * 4.0f * Mathf.PI;
    49.         Km4PI   = Km * 4.0f * Mathf.PI;
    50.         scale = 1f / (outerRadius - innerRadius);
    51.         scaleDepth = 0.25f;
    52.         scaleOverScaleDepth = scale / scaleDepth;
    53.         samples = 4f;
    54.         g = -0.95f;
    55.         g2 = g*g;
    56.     }
    57.    
    58.     //void OnGUI() {
    59.       //if (debug) {
    60.         //waveLength = DebugUtility.RGBSlider (new Rect (10,10,100,20), waveLength);
    61.         //ESun = DebugUtility.LabelSlider(new Rect (10,70,100,20), ESun, 50,"ESun: " + ESun );
    62.         //Kr = DebugUtility.LabelSlider(new Rect (10,90,100,20), Kr, 0.01f,"Kr: " + Kr);
    63.         //Km = DebugUtility.LabelSlider(new Rect (10,110,100,20), Km, 0.01f,"Km: " + Km);
    64.         //scaleDepth = DebugUtility.LabelSlider(new Rect (10,130,100,20), scaleDepth, 1.0f,"Scale Depth: " + scaleDepth);
    65.         //g = DebugUtility.LabelSlider(new Rect (10,150,100,20), g, -1.0f,"G: " + g);
    66.       //}
    67.     //}
    68.    
    69.     // Update is called once per frame
    70.     void LateUpdate () {
    71.         sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    72.  
    73.         invWaveLength = new Color(pow(waveLength[0], 4), pow(waveLength[1], 4), pow(waveLength[2], 4), 0.5f);
    74.  
    75.         cameraHeight = mainCamera.position.magnitude;
    76.         cameraHeight2 = cameraHeight * cameraHeight;
    77.  
    78.         outerRadius2 = outerRadius * outerRadius;
    79.         innerRadius2 = innerRadius * innerRadius;
    80.         KrESun = Kr * ESun;
    81.         KmESun = Km * ESun;
    82.         Kr4PI = Kr * 4.0f * Mathf.PI;
    83.         Km4PI = Km * 4.0f * Mathf.PI;
    84.         scale = 1 / (outerRadius - innerRadius);
    85.         scaleOverScaleDepth = scale / scaleDepth;
    86.         g2 = g * g;
    87.  
    88.         // Pass in variables to the Shader
    89.         renderer.material.SetVector("_v4CameraPos",new Vector4(mainCamera.position[0],mainCamera.position[1],mainCamera.position[2], 0));
    90.      
    91.         renderer.material.SetVector("_v4LightDir", new Vector4(sunLightDirection[0],sunLightDirection[1],sunLightDirection[2],0));
    92.         renderer.material.SetColor("_cInvWaveLength", invWaveLength);
    93.         renderer.material.SetFloat("_fCameraHeight", cameraHeight);
    94.         renderer.material.SetFloat("_fCameraHeight2", cameraHeight2);
    95.         renderer.material.SetFloat("_fOuterRadius", outerRadius);
    96.         renderer.material.SetFloat("_fOuterRadius2", outerRadius2);
    97.         renderer.material.SetFloat("_fInnerRadius", innerRadius);
    98.         renderer.material.SetFloat("_fInnerRadius2", innerRadius2);
    99.         renderer.material.SetFloat("_fKrESun",KrESun);
    100.         renderer.material.SetFloat("_fKmESun",KmESun);
    101.         renderer.material.SetFloat("_fKr4PI",Kr4PI);
    102.         renderer.material.SetFloat("_fKm4PI",Km4PI);
    103.         renderer.material.SetFloat("_fScale",scale);
    104.         renderer.material.SetFloat("_fScaleDepth",scaleDepth);
    105.         renderer.material.SetFloat("_fScaleOverScaleDepth",scaleOverScaleDepth);
    106.         renderer.material.SetFloat("_Samples",samples);
    107.         renderer.material.SetFloat("_G",g);
    108.         renderer.material.SetFloat("_G2",g2);
    109.     }
    110.    
    111.     float pow(float f, int p) {
    112.         return 1f / Mathf.Pow(f,p);
    113.     }
    114. }
    115.  
    116.  

    Hope it helps!!

    Oh, one thing... I'm having some trouble coordinating the transition between surface and space... The Atmosphere from ground shader works really well down on the surface, and falls away (below the horizon) quite quickly as one ascends out into space... Then the AtmosphereFromSpace shader should take up the job... which it does rather well, when one is out of the actual atmosphere radius...

    I thought it'd be simple enough to just turn off the 'FromSpace' shaders while one is inside the atmosphere, but that doesn't work as expected.

    The problem lies when you're half way there... the atmosphereFromGround shader has already fallen away, so there is a black horizon where the atmosphere should have been thickest... I reckon the AtmosphereFromSpace shader should be there then...

    So I turn it back on, but the atmosphere from space shader has issues when you're inside it's sphere... It does draw a cool horizon and all, but it also draws another 'horizon' somewhere between the actual one and zenith, creating a 'ring' of atmosphere that is most unrealistic... this 'ring' stays there until the camera is out of the sphere, where it goes away and works as expected...

    I reckon that is the reason why there are FromSpace and FromGround shaders... but how to coordinate the transition?

    Cheers
     
  13. Eux86

    Eux86

    Joined:
    Dec 3, 2010
    Posts:
    2
    Thanks for the work you are doing, it's very interesting to me because I really don't understand nothing about shaders :p
    Could you post a sample test scene where I can try your script?
    I tried to build up one following your instructions, but i can't get it work and I don't understand why :/

    Thank you :)
     
  14. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    I'll post a working scene as soon as I can get one myself ;)

    It takes a great deal of tweaking... it could be a while...

    Cheers
     
  15. Eux86

    Eux86

    Joined:
    Dec 3, 2010
    Posts:
    2
    I will be grateful even if it will take time!
    You're doing a great job! Thanks!!
     
  16. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    Last edited: May 20, 2011
  17. kev42100

    kev42100

    Joined:
    Apr 17, 2010
    Posts:
    61
    Very nice atmosphere ! Does it from to Nvidia atmospheric scattering publication ?
     
  18. ant001

    ant001

    Joined:
    Dec 15, 2010
    Posts:
    116
  19. Cork

    Cork

    Joined:
    Jun 13, 2011
    Posts:
    2
    Bumpity bump :)

    Some "Why" questions:

    1) Why (i write as novice) these shaders works correctly on oldest version only?
    2) Why somebody mentally sane should spend 69$ for some shaders, even if works fine on newest version?
    3) Why someone write things like "I'll post a working scene as soon as I can" then the "total darkness"?
     
  20. Cork

    Cork

    Joined:
    Jun 13, 2011
    Posts:
    2
    Oh well, got it now...
     

    Attached Files:

  21. dtsps1990

    dtsps1990

    Joined:
    Sep 3, 2011
    Posts:
    1
    Hi,

    I'm trying to implement the scattering terms by hoffman/preetham in Rendermonkey with GLSL. But my output is...well it's just white and has holes!

    it's "SkyFromSpace.vertex" GLSL code:

    uniform vec3 v3LightPos;
    uniform vec3 v3CameraPos;
    const int nSamples = 2;
    const float fSamples = 2.0;
    uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
    uniform float fCameraHeight; // The camera's current height
    uniform float fCameraHeight2; // fCameraHeight^2
    uniform float fOuterRadius; // The outer (atmosphere) radius
    uniform float fOuterRadius2; // fOuterRadius^2
    uniform float fInnerRadius; // The inner (planetary) radius
    uniform float fInnerRadius2; // fInnerRadius^2
    uniform float fKrESun; // Kr * ESun
    uniform float fKmESun; // Km * ESun
    uniform float fKr4PI; // Kr * 4 * PI
    uniform float fKm4PI; // Km * 4 * PI
    uniform float fScale; // 1 / (fOuterRadius - fInnerRadius)
    uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
    uniform float fScaleOverScaleDepth; // fScale / fScaleDepth
    varying vec3 v3Direction;


    float scale(float fCos)
    {
    float x = 1.0 - fCos;
    return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
    }

    void main( void )
    {
    // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
    vec3 v3Pos = gl_Vertex.xyz;
    vec3 v3Ray = v3Pos - v3CameraPos;
    float fFar = length(v3Ray);
    v3Ray /= fFar;

    // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)
    float B = 2.0 * dot(v3CameraPos, v3Ray);
    float C = fCameraHeight2 - fOuterRadius2;
    float fDet = max(0.0, B*B - 4.0 * C);
    float fNear = 0.5 * (-B - sqrt(fDet));

    // Calculate the ray's starting position, then calculate its scattering offset
    vec3 v3Start = v3CameraPos + v3Ray * fNear;
    fFar -= fNear;
    float fDepth = exp((fInnerRadius - fOuterRadius) / fScaleDepth);
    float fCameraAngle = dot(-v3Ray, v3Pos) / length(v3Pos);
    float fLightAngle = dot(v3LightPos, v3Pos) / length(v3Pos);
    float fCameraScale = scale(fCameraAngle);
    float fLightScale = scale(fLightAngle);
    float fCameraOffset = fDepth*fCameraScale;
    float fTemp = (fLightScale + fCameraScale);

    // Initialize the scattering loop variables
    float fSampleLength = fFar / fSamples;
    float fScaledLength = fSampleLength * fScale;
    vec3 v3SampleRay = v3Ray * fSampleLength;
    vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;

    // Now loop through the sample rays
    vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
    vec3 v3Attenuate;
    for(int i=0; i<nSamples; i++)
    {
    float fHeight = length(v3SamplePoint);
    float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
    float fScatter = fDepth*fTemp - fCameraOffset;
    v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
    v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
    v3SamplePoint += v3SampleRay;
    }

    gl_FrontColor.rgb = v3FrontColor * (v3InvWavelength * fKrESun + fKmESun);

    // Calculate the attenuation factor for the ground
    gl_FrontSecondaryColor.rgb = v3FrontColor * fKmESun;

    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    v3Direction = v3CameraPos - v3Pos;

    }

    it's "SkyFromSpace.fragment" GLSL code:

    uniform vec3 v3LightPos;
    varying vec3 v3Direction;
    varying vec4 c0;
    varying vec4 c1;

    const float g = -0.95;
    const float g2 = g * g;

    void main(void)
    {
    float fCos = dot(normalize(v3LightPos), v3Direction) / length(v3Direction);
    float fRayleighPhase = 0.75 * (1.0 + fCos*fCos);
    float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
    gl_FragColor = normalize(fRayleighPhase * gl_Color + fMiePhase * gl_SecondaryColor);
    }

    I don't know why?

    Please help me .......thank you.
     
  22. roamcel

    roamcel

    Joined:
    Sep 15, 2011
    Posts:
    17
    These only work with unity pro apparently. Wasted a lot of time trying to get them to work, to no avail, on indie.

    Edit: i stand corrected. Cork's assets produce a correctly working effect.

    Thanks Cork.
     
    Last edited: Oct 21, 2011
  23. sladuh

    sladuh

    Joined:
    Aug 29, 2011
    Posts:
    7
    A note for all the would be atmospheric scattering folks...

    There is an error in the script I see posted and reposted 10 times over...

    outerRadius and innerRadius BOTH need to be a radius, not the diameter! A 1 unit sphere that Unity comes standard with has a DIAMETER of 1 (ie: a single unity unit) and a RADIUS of 0.5. So if you set outerRadius and innerRadius as 1.025 and 1.0 respectively it will not work...because these values are the diameter.

    I discovered this when I did everything according to what everyone has been posting to no avail... then I increased and decreased the scale of all the spheres and it worked at precisely 2X the scale I input into the parameters... Diameter = 2 x Radius...

    Also, credit to Harvester who stated:
    - the shader fails if you have a perfectly spherical atmosphere... as he said, bump the x scale up or down by a fraction.
    - outerRadius = innerRadius X 1.025. Ie: atmosphere is 2.5% bigger than the planet.



    To correct this, either enter the radius (world scale / 2) or if you are afraid to change the scripts but want a quick fix...

    AtmospherefromSpace.cs
    line 38, type the following before the ;
    / 2f

    GroundFromSpace.cs
    line 39, enter the radius of your atmosphere here
    line 41, enter the radius of your planet here

    I have half a mind to post up the a fixed unity package that WILL work out of the box with an explanation on how it all works... if this is something people want I can do it...

    Also I am going to look into modifying the thickness of the atmosphere beyond 2.5%
     
  24. Rembo

    Rembo

    Joined:
    Mar 13, 2012
    Posts:
    6
    I've got the shaders working and it looks great, thanks to all the people who have put so much effort into helping others with less know how!

    The only problem I am still facing is moving the planet away from origin (0,0,0). When i set the planet at (0,0,10000) for example, the effect changes and disappears.

    Can anyone help with this problem of moving the planet away from origin?

    Thanks
     
  25. Sephi

    Sephi

    Joined:
    Mar 13, 2012
    Posts:
    1
    Same for me, after some days i've all the 3 shaders working (on unity 3.5 with harversteR settings), but's seam to be impossible to make a real rotation (not by change tex coord for some reason...)
    when i rotate earth and shaders, the effect follow rotation(if is near 180°, the effect is opposite to the light)
    i've try to rotate only earth and some artefact appears between earth and especially ground shader because triangles doesn't correspond when moving...
    otherwise, sladuh i'm interessed by your fixed package, can you post it?

    Rembo: Harverster also evoque a solution to fix some issues with a 2 scene tip but i don't see how to load 2 scenes in 1 ?
     
    Last edited: Mar 13, 2012
  26. Rembo

    Rembo

    Joined:
    Mar 13, 2012
    Posts:
    6
    I've read the solution by Harvester and I'm with you Sephi, I don't know how to show two scenes simultaneously.

    So it seems that the following problems are still an issue, does anyone know how to fix the following:

    1) We can't move the planet away from origin.

    2) We can't rotate the planet.

    I think a few people are having these problems, can anyone help?

    Thanks
     
  27. Rembo

    Rembo

    Joined:
    Mar 13, 2012
    Posts:
    6
    Hi All,

    Just wondered if anyone had a solution to the above. Really need help with this one.

    Thanks
     
  28. Rembo

    Rembo

    Joined:
    Mar 13, 2012
    Posts:
    6
    Hi All,

    I contacted Sean O'Neil and it is possible to move the planet away from origin (0,0,0). However, as I'm very new to games development, I'm struggling to work out how to implement his answer. Can anyone help.

    Here is what Sean said...

    The best help I can give you right now is to remind you that positions are all relative (in space as well as in 3D rendering). The planet can be anywhere you want in your "world space", but when you go to render it, you can pretend it's at the origin by tweaking the view and model matrices. In other words, before you render the planet, calculate the camera's position relative to the planet (e.g. subtract the planet's position from it), set your view matrix using that relative position, and then render the planet as if it's at (0,0,0).

    If you don't do something like that, you'll run into huge precision problems with single-precision floats when you try to render the planet. (Even with the planet at the origin, you'll probably run into smaller precision problems, but fixing that is a good bit harder.) My third GamaSutra article explains some of this:

    http://www.gamasutra.com/view/feature/2984/a_realtime_procedural_universe_.php

    Sean
     
  29. einfopedia

    einfopedia

    Joined:
    Apr 4, 2012
    Posts:
    28
    the second code is the right.this code is running on my camera so it looks great.and prd issue are solved now.mi idea is I am trying to code up an atmospheric scattering effect in an HLSL pixel shader. The math is really painful for me, so imagine my delight when this intermediate result showed up:601906It's only a very, very rough implementation, with lots of pieces missing, but I was surprised to see it Just Work. I'll continue to drudge away with this math, implement all the pieces, and hopefully get something very pretty for my Elite-like game.Nothing much to see, really, but it was so much mind-bending math that I wanted to post the picture out of a slight bit of self-satisfaction. I will gladly share the shader code once I'm done. The gold standard is O'Neil's work [sponeil.net], except his shader is vertex pixel based, written in GLSL, and has thus far been very difficult to port to my game. So I'm just writing my own version and hoping for the best.
     
  30. why789

    why789

    Joined:
    Sep 23, 2011
    Posts:
    184
    do we have the atmosphere from ground script/shader up? I'm not quite sure if that was posted for Unity 3?

    If anyone has it I would be very appreciative if they could post it :)

    thank you!
    why789
     
  31. sladuh

    sladuh

    Joined:
    Aug 29, 2011
    Posts:
    7
    I have the shader working in a solar system. ie: planets with orbital and rotational periods.

    What Sean said is true about relativity, if you are unsure how to work this out it may be worth learning a bit of Vector Maths.
    eg: If vector a = blah, and vector b = bleh...
    ab = b - a = bleh - blah.

    (I am paraphrasing code here as an example)
    planet.transform.position = Vector3(0,1,0)
    MainCamera.transform.position = Vector3(0,0,0)

    The relative vector from the camera to the planet would be.
    (planet.transform.position - MainCamera.transform.position)

    If you can write a script that updates the shaders with the relative positions of the planet, light source and camera (as has been provided in this topic) then each frame should render the Atmospheric scattering properly.

    PM me if you have any questions.
     
  32. Rembo

    Rembo

    Joined:
    Mar 13, 2012
    Posts:
    6
    Hi,

    Solution found for moving the planet away from origin (0,0,0)

    I'm sure many people reading this will already know this but as a newcomer to games programming, it took me a while to get it sorted.

    I have finally, after a little help from Sean O'Neil and Sladuh managed to move the planet away from origin but still have the atmosphere scattering work perfectly. I've read many comments from people saying that one of the rules to making this shader work is that the planet has to be at origin... it doesn't.

    Below are the code fragments that make it work, thanks to Sean and Sladuh for pointing me in the right direction.

    Make this change in your script, not the shader, to pass through the relative positions of the camera and light source.

    void LateUpdate () {
    Vector3 PlanetPosition = transform.position;
    Vector3 CameraPosition = (mainCamera.transform.position - PlanetPosition);
    cameraHeight = CameraPosition.magnitude;
    cameraHeight2 = cameraHeight * cameraHeight;
    Vector3 SunPosition = sunLight.transform.position;
    Vector3 SunLightDirection = (SunPosition - PlanetPosition).normalized;

    // Pass in variables to the Shader
    renderer.material.SetVector("_v4CameraPos",new Vector4(CameraPosition[0],CameraPosition[1],CameraPosition[2], 0));
    renderer.material.SetVector("_v4LightDir", new Vector4(SunLightDirection[0],SunLightDirection[1],SunLightDirection[2],0));
     
  33. Rembo

    Rembo

    Joined:
    Mar 13, 2012
    Posts:
    6
    Hi,

    I'm having trouble getting the GroundFromSpace shader to work and I'm not sure how it should look. There is an image posted by Freelanzer on page 2 of this topic but when I disable the AtmosphereFromSpace shader I don't see anything from the GroundFromSpace shader!? The project I'm working from is the package posted here on page 4 of this topic by Cork but it doesn't seem to work. I've included the code I'm using below, can anyone help me get this working, am I missing something?

    This is what I have so far from the AtmosphereFromSpace shader, does this look correct?



    Any ideas why the GroundFromSpace shader isn't working?

    Thanks

    SCRIPT
    -----------

    using UnityEngine;
    using System.Collections;

    public class GroundFromSpace : MonoBehaviour {

    public Transform mainCamera;
    public GameObject sunLight;
    private Vector3 sunLightDirection;
    private Color waveLength;
    private Color invWaveLength;
    private float cameraHeight;
    private float cameraHeight2;
    private float outerRadius;
    private float outerRadius2;
    private float innerRadius;
    private float innerRadius2;
    private float ESun;
    private float Kr;
    private float Km;
    private float KrESun;
    private float KmESun;
    private float Kr4PI;
    private float Km4PI;
    private float scale;
    private float scaleDepth;
    private float scaleOverScaleDepth;
    private float samples;
    private float g;
    private float g2;
    private bool debug;

    void Start() {
    sunLight = GameObject.Find("Sun");
    mainCamera = GameObject.Find("Main Camera").transform;
    sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    waveLength = new Color(0.650f, 0.570f, 0.475f, 1);
    invWaveLength = new Color (pow(waveLength[0],4),pow(waveLength[1],4),pow(waveLength[2],4),1);
    cameraHeight = mainCamera.position.magnitude;
    outerRadius = 6530.28f;
    outerRadius2 = outerRadius * outerRadius;
    innerRadius = 6371;
    innerRadius2 = innerRadius * innerRadius;
    ESun = 12;
    Kr = 0.0025f;
    Km = 0.0015f;
    KrESun = Kr * ESun;
    KmESun = Km * ESun;
    Kr4PI = Kr * 4.0f * Mathf.PI;
    Km4PI = Km * 4.0f * Mathf.PI;
    scale = 1 / (outerRadius - innerRadius);
    scaleDepth = 0.25f;
    scaleOverScaleDepth = scale / scaleDepth;
    samples = 2;
    g = -0.95f;
    g2 = g*g;
    debug = false;
    }

    //void OnGUI() {
    //if (debug) {
    //waveLength = DebugUtility.RGBSlider (new Rect (10,10,100,20), waveLength);
    //ESun = DebugUtility.LabelSlider(new Rect (10,70,100,20), ESun, 50,"ESun: " + ESun );
    //Kr = DebugUtility.LabelSlider(new Rect (10,90,100,20), Kr, 0.01f,"Kr: " + Kr);
    //Km = DebugUtility.LabelSlider(new Rect (10,110,100,20), Km, 0.01f,"Km: " + Km);
    //scaleDepth = DebugUtility.LabelSlider(new Rect (10,130,100,20), scaleDepth, 1.0f,"Scale Depth: " + scaleDepth);
    //g = DebugUtility.LabelSlider(new Rect (10,150,100,20), g, -1.0f,"G: " + g);
    //}
    //}

    // Update is called once per frame
    void LateUpdate () {
    if (Input.GetKey("z")) debug = !debug;
    sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    cameraHeight = mainCamera.position.magnitude;
    cameraHeight2 = cameraHeight * cameraHeight;

    // Pass in variables to the Shader
    renderer.material.SetVector("_CameraPosition",new Vector4(mainCamera.position[0],mainCamera.position[1],mainCamera.position[2], 0));

    renderer.material.SetVector("_LightDir", new Vector4(sunLightDirection[0],sunLightDirection[1],sunLightDirection[2],0));
    renderer.material.SetColor("_InvWaveLength", invWaveLength);
    renderer.material.SetFloat("_CameraHeight", cameraHeight);
    renderer.material.SetFloat("_CameraHeight2", cameraHeight2);
    renderer.material.SetFloat("_OuterRadius", outerRadius);
    renderer.material.SetFloat("_OuterRadius2", outerRadius2);
    renderer.material.SetFloat("_InnerRadius", innerRadius);
    renderer.material.SetFloat("_InnerRadius2", innerRadius2);
    renderer.material.SetFloat("_KrESun",KrESun);
    renderer.material.SetFloat("_KmESun",KmESun);
    renderer.material.SetFloat("_Kr4PI",Kr4PI);
    renderer.material.SetFloat("_Km4PI",Km4PI);
    renderer.material.SetFloat("_Scale",scale);
    renderer.material.SetFloat("_ScaleDepth",scaleDepth);
    renderer.material.SetFloat("_ScaleOverScaleDepth",scaleOverScaleDepth);
    renderer.material.SetFloat("_Samples",samples);
    renderer.material.SetFloat("_G",g);
    renderer.material.SetFloat("_G2",g2);
    }

    float pow(float f, int p) {
    return 1 / Mathf.Pow(f,p);
    }
    }

    SHADER
    -------------

    Shader "GroundFromSpace" {
    Properties {
    _CameraPosition("Camera Position",Vector) = (0,0,0,0)
    _LightDir("Light Direction",Vector) = (0,0,0,0)
    _InvWaveLength("Inverse WaveLength",Color) = (0,0,0,0)
    _CameraHeight("Camera Height",Float) = 0
    _CameraHeight2("Camera Height2",Float) = 0
    _OuterRadius("Outer Radius",Float) = 0
    _OuterRadius2("Outer Radius 2",Float) = 0
    _InnerRadius("Inner Radius",Float) = 0
    _InnerRadius2("Inner Radius 2",Float) = 0
    _KrESun("KrESun",Float) = 0
    _KmESun("KmESun",Float) = 0
    _Kr4PI("Kr4PI",Float) = 0
    _Km4PI("Km4PI",Float) = 0
    _Scale("Scale",Float) = 0
    _ScaleDepth("Scale Depth",Float) = 0
    _ScaleOverScaleDepth("Scale Over Scale Depth",Float) = 0
    _Samples("Samples",Float) = 0
    _G("G",Float) = 0
    _G2("G2",Float) = 0
    }
    SubShader {
    Pass {
    Cull Back
    Blend SrcAlpha OneMinusSrcAlpha

    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #include "UnityCG.cginc"

    float4 _CameraPosition;
    float4 _LightDir;
    float4 _InvWaveLength;
    float _CameraHeight;
    float _CameraHeight2;
    float _OuterRadius;
    float _OuterRadius2;
    float _InnerRadius;
    float _InnerRadius2;
    float _KrESun;
    float _KmESun;
    float _Kr4PI;
    float _Km4PI;
    float _Scale;
    float _ScaleDepth;
    float _ScaleOverScaleDepth;
    float _Samples;
    float _G;
    float _G2;

    struct v2f {
    float4 position : POSITION;
    float3 c0 : COLOR0;
    float3 c1 : COLOR1;
    };

    float expScale (float cos) {
    float x = 1 - cos;
    return _ScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
    }

    v2f vert (float4 vertex : POSITION) {
    float3 pos = vertex.xyz;
    float3 ray = pos - _CameraPosition.xyz;
    float far = length(ray);

    ray /= far;

    float B = 2.0 * dot(_CameraPosition.xyz, ray);
    float C = _CameraHeight2 - _OuterRadius2;
    float det = max(0.0, B*B - 4.0 * C);
    float near = 0.5 * (-B - sqrt(det));

    float3 start = _CameraPosition.xyz + ray * near;
    far -= near;

    float startAngle = dot(ray,start) / _OuterRadius;
    float startDepth = exp ((_InnerRadius - _OuterRadius) / _ScaleDepth);
    float cameraAngle = dot(-ray, pos) / length(pos);
    float lightAngle = dot(_LightDir.xyz, pos) / length(pos);
    float cameraScale = expScale(cameraAngle);
    float lightScale = expScale(lightAngle);
    float cameraOffset = startDepth*cameraScale;
    float temp = (lightScale + cameraScale);

    float sampleLength = far / _Samples;
    float scaledLength = sampleLength * _Scale;
    float3 sampleRay = ray * sampleLength;
    float3 samplePoint = start + sampleRay * 0.5;

    float3 frontColor = float3(0.0, 0.0, 0.0);
    float3 attenuate;

    for(int i=0; i<2; i++) {
    float height = length(samplePoint);
    float depth = exp(_ScaleOverScaleDepth * (_InnerRadius - height));
    float scatter = depth*temp - cameraOffset;
    attenuate = exp(-scatter * (_InvWaveLength.xyz * _Kr4PI + _Km4PI));
    frontColor += attenuate * (depth * scaledLength);
    samplePoint += sampleRay;
    }

    v2f OUT;
    OUT.position = mul(UNITY_MATRIX_MVP, vertex);
    OUT.c0.rgb = frontColor * (_InvWaveLength.xyz * _KrESun + _KmESun);
    OUT.c1.rgb = attenuate;

    return OUT;
    }

    float4 frag (v2f INPUT) : COLOR {
    float4 fragColor;

    fragColor.xyz = INPUT.c0 + 0.075 * INPUT.c1;
    fragColor.w = fragColor.z;
    return fragColor;
    }

    ENDCG
    }
    }
    FallBack "None"
    }
     
  34. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
  35. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    Last edited: May 30, 2012
  36. Rembo2

    Rembo2

    Joined:
    Jan 29, 2013
    Posts:
    1
    Hi everyone,

    I hope someone can help, I got the code above working on the GroundFromSpace shader and script but since I upgraded to Unity 4, it has now stopped working. I use 3 spheres, 1 for the atmosphere, one for the ground shader and one for the planet material using a diffuse bump shader to display the texture. The atmosphereFromSpace shader is working fine but if the planet sphere with the texture on it is enabled, the ground shader disappears. If I disable the texture sphere, the GroundFromSpace shader shows and is working fine. It's almost like the planet sphere is hiding the sphere with the GroundFromSpace shader as they are both the same sized spheres. It also behaves strangely when the skybox is enabled???

    As I said, it was all working beautifully in the previous version of Unity, does anyone know what might have changed or how I might fix the problem?

    Thanks
     
  37. Josh707

    Josh707

    Joined:
    Jul 12, 2012
    Posts:
    71
    Same here, I have tried to convert the AtmosphereFromGround shader so I can have a nice sky follow the player, and am having no luck. I am getting no errors, all the values seem to be correct but absolutely nothing shows up on my sphere. Has anybody had any luck implementing the AtmosphereFromGround shader in Unity 4? Here is the code I am using.

    Code (csharp):
    1.  // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    2.  
    3.     Shader "atmScatter" {
    4.        Properties {
    5.          _v4CameraPos("Camera Position",Vector) = (0,0,0,0)
    6.          _v4LightDir("Light Direction",Vector) = (0,0,0,0)
    7.          _cInvWaveLength("Inverse WaveLength",Color) = (0,0,0,0)
    8.          _fCameraHeight("Camera Height",Float) = 0
    9.          _fCameraHeight2("Camera Height2",Float) = 0
    10.          _fOuterRadius("Outer Radius",Float) = 0
    11.          _fOuterRadius2("Outer Radius 2",Float) = 0
    12.          _fInnerRadius("Inner Radius",Float) = 0
    13.          _fInnerRadius2("Inner Radius 2",Float) = 0
    14.          _fKrESun("KrESun",Float) = 0
    15.          _fKmESun("KmESun",Float) = 0
    16.          _fKr4PI("Kr4PI",Float) = 0
    17.          _fKm4PI("Km4PI",Float) = 0
    18.          _fScale("Scale",Float) = 0
    19.          _fScaleDepth("Scale Depth",Float) = 0
    20.          _fScaleOverScaleDepth("Scale Over Scale Depth",Float) = 0
    21.          _Samples("Samples",Float) = 0
    22.          _G("G",Float) = 0
    23.          _G2("G2",Float) = 0
    24.        }
    25.        SubShader {
    26.          Tags {"Queue" = "Transparent" }
    27.           Pass {
    28.              Cull Front
    29.              Blend One One
    30.              
    31.     CGPROGRAM
    32.     #pragma vertex vert
    33.     #pragma fragment frag
    34.     #include "UnityCG.cginc"
    35.      
    36.     float4 _v4CameraPos;
    37.     float4 _v4LightDir;
    38.     float4 _cInvWaveLength;
    39.     float _fCameraHeight;
    40.     float _fCameraHeight2;    
    41.     float _fOuterRadius;
    42.     float _fOuterRadius2;    
    43.     float _fInnerRadius;
    44.     float _fInnerRadius2;
    45.     float _fKrESun;
    46.     float _fKmESun;
    47.     float _fKr4PI;
    48.     float _fKm4PI;
    49.     float _fScale;
    50.     float _fScaleDepth;
    51.     float _fScaleOverScaleDepth;
    52.     float _Samples;
    53.     float _G;
    54.     float _G2;
    55.      
    56.     struct v2f {
    57.       float4 position : POSITION;
    58.       float3 c0 : COLOR0;
    59.       float3 c1 : COLOR1;
    60.       float3 t0 : TEXCOORD0;
    61.     };
    62.      
    63.     float expScale (float cos) {
    64.        float x = 1 - cos;
    65.        return _fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
    66.     }
    67.      
    68.     v2f vert (float4 vertex : POSITION) {
    69.       float3 v3Pos = vertex.xyz;
    70.       float3 v3Ray = v3Pos - _v4CameraPos.xyz;
    71.       float fFar = length(v3Ray);
    72.       v3Ray /= fFar;  
    73.      
    74.     float3 v3Start = _v4CameraPos.xyz;
    75.      
    76.      
    77.       float v3StartAngle = dot(v3Ray,v3Start) / length(v3Start);
    78.      
    79.       float v3StartDepth = exp (_fScaleOverScaleDepth * ( - _fInnerRadius + _fCameraHeight));
    80.      
    81.       float v3StartOffset = v3StartDepth * expScale(v3StartAngle);
    82.      
    83.       float fSampleLength = fFar / _Samples;
    84.       float fScaledLength = fSampleLength * _fScale;
    85.       float3 sampleRay = v3Ray * fSampleLength;
    86.       float3 samplePoint = v3Start + sampleRay * 0.5f;
    87.      
    88.       float3 frontColor = float3(0,0,0);
    89.       float3 attenuate;
    90.      
    91.       for (int i = 0; i < 1; i++) {
    92.         float height = length (samplePoint);
    93.         float depth = exp(_fScaleOverScaleDepth * (_fInnerRadius - height));
    94.         float lightAngle = dot(_v4LightDir.xyz, samplePoint) / height;
    95.         float cameraAngle = dot(v3Ray, samplePoint) / height;
    96.         float scatter = (v3StartOffset + depth * (expScale (lightAngle) - expScale (cameraAngle)));
    97.      
    98.         attenuate = exp(-scatter * (_cInvWaveLength.xyz * _fKr4PI + _fKm4PI));
    99.         frontColor += attenuate * (depth * fScaledLength);
    100.         samplePoint += sampleRay;
    101.       }
    102.      
    103.       v2f o;
    104.       o.position = mul( UNITY_MATRIX_MVP, vertex);
    105.       o.t0 = _v4CameraPos.xyz - vertex.xyz;
    106.       o.c0.rgb = frontColor * (_cInvWaveLength.xyz * _fKrESun);
    107.       o.c1.rgb = frontColor * _fKmESun;
    108.       return o;
    109.     }
    110.      
    111.     float4 frag (v2f i) : COLOR {
    112.       float cos = dot(_v4LightDir.xyz, i.t0) / length(i.t0);
    113.       float cos2 = cos * cos;
    114.       float miePhase = 1.5 * ((1.0 - _G2) / (2.0 + _G2)) * (1.0 + cos2) / pow(1.0 + _G2 - 2.0*_G*cos, 1.5);
    115.       float rayleighPhase = 0.75 * (1.0 + cos2);
    116.      
    117.      
    118.       float4 fragColor;
    119.      
    120.       fragColor.xyz = (rayleighPhase * i.c0) + (miePhase * i.c1);
    121.       fragColor.w = fragColor.z;
    122.      
    123.       if(fragColor.x > 1.0){ fragColor.x = 1.0;}
    124.       if(fragColor.y > 1.0){ fragColor.y = 1.0;}
    125.       if(fragColor.z > 1.0){ fragColor.z = 1.0;}
    126.      
    127.       return fragColor;  
    128.     }
    129.      
    130.     ENDCG  
    131.           }
    132.        }
    133.        FallBack "None"
    134.     }
     
  38. WalterEspinar

    WalterEspinar

    Joined:
    Aug 23, 2011
    Posts:
    83
    Bump!
     
  39. Luckymouse

    Luckymouse

    Joined:
    Jan 31, 2010
    Posts:
    484
    There is a working unity 4 sample on other topic in forum by scrawk , click Here.
     
  40. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Here is what i did with Scrawk's scattering method that Luckymouse pointed out:
    $Epic Planet Screenie.png
    For those using scrawk's shaders and wondering why their epic planet looks greyed out, check the scale: this is what happened to me, and changing the scale fixed it. Just letting you guys know to save you hours of pain and suffering like what happened to me... ;)
     
    Last edited: Mar 10, 2014
  41. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    I should give all these a go, the only one i've had a poke at is the one Scrawk ported from Brunetons work