Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Implementing GPU Gems shaders into Unity?

Discussion in 'Shaders' started by mbdev, Mar 14, 2013.

  1. mbdev

    mbdev

    Joined:
    Feb 10, 2013
    Posts:
    12
    Hey there,

    Really new to shader programming, generally avoided it like the plague, but here I am, wanting realistic skies so... I was hoping to get some advice on how and where to learn how to convert cg shaders like the ones in GPU Gems into Unity. I know you can input cg shaders between tags, but it seems like in the case of GPU Gems 16 (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), there's some specific OpenGL code that doesn't translate, like gl_vertex and such. I just would like to be able to better understand the shader itself, and hopefully be able to port it. Is this possible? Is it really difficult? Any pointers on where to go to begin achieving this would be awesome.
     
  2. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Hi, Unity does use cg so this should be quite easy to port over. There is only some small differences mostly to do with the way Unity requires you to set up your shader so check out the manual first. Just set up your vert and frag shader the same way as the examples.

    Had a look at the code. All GPU gems shaders Ive seen are in cg. So is this one, there is no openGL code in there. You cant mix the two. There are some variables with gl_ at the front of there name but this is just they way they have named them, its not openG code. Looks like who ever wrote that article was used to working in openGL and kept some of there habits.

    This is quite a advanced shader to start off with but give it a go.

    Unity is a little more restrictive than working directly in cg but most problems can be solved by using a higher shader model or stating some pragma.

    PS - If you want a even better looking (but way more complex) sky shader check out this.
     
  3. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    gl_Vertex will translate, but only directly in a GLSL shader - I don't think it does that automatically. By default, Unity uses CG (for most purposes, that's the same thing as HLSL) and then it uses that shader code to build DirectX and OpenGL versions.


    Most of the attributes should be easy enough to work out...
    gl_Vertex is v.vertex
    gl_Normal is v.normal
    etc...

    And for other things Unity has built-in values...
    gl_ModelViewProjectionMatrix
    or the Model x View x Projection Matrix, is known in Unity as
    UNITY_MATRIX_MVP


    So, this vertex shader line that outputs the position of the vertex (from the shader you mentioned)...
    OUT.pos = mul(gl_ModelViewProjectionMatrix, gl_Vertex);
    becomes (following Unity's standard in/out naming)...
    o.pos = mul(UNITY_MATRIX_MVP), v.vertex);

    There are also built-in functions that will handle things for you in a consistent manner. Most of them - and the built-in values - are documented here and in the subsections of this page;
    http://docs.unity3d.com/Documentation/Components/SL-ShaderPrograms.html

    But it's also worth checking out the contents of UnityCG.cginc and AutoLight.cginc that come with Unity. Most of it's commented and helpful.


    I'd recommend - before you start trying to put different shader languages into Unity - to play with Unity's own shaders and see how they're written. It should be a bit clearer how to port things after you're more familiar with how shaders work within Unity and what built-in values are what.
     
    Last edited: Mar 14, 2013
  4. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,864
    Try this original from sean oneil, download the sandbox, all the code you need is there.
    And very easy to convert to unity.
    EDIT: Good luck with the HDR rendering though :p
     
    Last edited: Mar 14, 2013
  5. Acey195

    Acey195

    Joined:
    Mar 13, 2013
    Posts:
    10
  6. mbdev

    mbdev

    Joined:
    Feb 10, 2013
    Posts:
    12
    Hey guys! Thanks for the response, you guys are great. Couple of questions if you guys don't mind me troubleshooting... Um. I've converted the SkyFromAtmosphere shader from 16 into a unity shader, but what values I should pass to it? I know that's beyond a simple shader question but I figured you guys understood this code a little better than myself. Also, when I try and pass an int variable in the for loop, as in
    It breaks the code and says the for loop is not supported?

    Any help would be lovely, thanks.

    EDIT: And I know I'm sounding very give-me here, so I apologize. I'm not looking for you to code for me, just directions on where to look haha.
     
    Last edited: Mar 14, 2013
  7. mbdev

    mbdev

    Joined:
    Feb 10, 2013
    Posts:
    12
    Wait. I'm not crazy or something here, like this atmospheric scattering can be used for inside a sky dome for a sky, right? That's what the SkyFromAtmosphere is for?

    EDIT: Also I found this quote relevant to the for loop.
    Seems like it's an AMD issue?
     
    Last edited: Mar 15, 2013
  8. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Hey, I thought you might have a issue with that for loop.

    Its not a AMD issue. Unity requires that for loops are unrolled when the shader is compiled. That means the nSamples has to be defined in the shader. There maybe a way to enable this in Unity but I dont know of it.

    I dont know what all the values passed to the shader are meant to be but a few people have posted links to working code so I would try and get one of those projects and have a look at what they used.

    Im guessing you mean can this shader be used to create a material and then attach that material to a skydome? Yes you can do this.Its how I would go about it. Just disable depth write on you skydome and make sure it renders first.
     
  9. mbdev

    mbdev

    Joined:
    Feb 10, 2013
    Posts:
    12
    So. I converted the script and used the other's threads help to feed it variables. Doesn't work. Just displays white on the atmosphere... I'm wondering what I'm doing wrong. Here's my code for the shader:
    Code (csharp):
    1. Shader "Sky" {
    2. Properties {
    3. v3CameraPos ("Camera Position", Vector) = (0,0,0,0)
    4. v3LightPos ("Light Position", Vector) = (0,0,0,0)
    5. v3InvWavelength ("Inverted WaveLength", Color) = (0,0,0,0)
    6. fCameraHeight ("Camera Height", Float) = 0
    7. fCameraHeight2 ("Camera Height 2", Float) = 0
    8. fOuterRadius ("Outer Radius", Float) = 0
    9. fOuterRadius2 ("Outer Radius 2", Float) = 0
    10. fInnerRadius ("Inner Radius", Float) = 0
    11. fInnerRadius2 ("Inner Radius 2", Float) = 0
    12. fKrESun ("KrESun", Float) = 0
    13. fKmESun ("KmESun", Float) = 0
    14. fKr4PI ("Kr4PI", Float) = 0
    15. fKm4PI ("Km4PI", Float) = 0
    16. fScale ("Scale", Float) = 0
    17. fScaleDepth ("Scale Depth", Float) = 0
    18. fSamples ("Samples", Float) = 0
    19. g ("g", Float) = 0
    20. g2 ("g2", Float) = 0
    21. }
    22. SubShader {
    23.     Cull Front
    24.     Pass {
    25.  
    26. CGPROGRAM
    27. #pragma vertex vert
    28. #pragma fragment frag
    29. #include "UnityCG.cginc"
    30.  
    31. float3 v3CameraPos;     // The camera's current position
    32. float3 v3LightPos;      // The direction vector to the light source
    33. float3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
    34. float fCameraHeight;    // The camera's current height
    35. float fCameraHeight2;   // fCameraHeight^2
    36. float fOuterRadius;     // The outer (atmosphere) radius
    37. float fOuterRadius2;    // fOuterRadius^2
    38. float fInnerRadius;     // The inner (planetary) radius
    39. float fInnerRadius2;    // fInnerRadius^2
    40. float fKrESun;          // Kr * ESun
    41. float fKmESun;          // Km * ESun
    42. float fKr4PI;           // Kr * 4 * PI
    43. float fKm4PI;           // Km * 4 * PI
    44. float fScale;           // 1 / (fOuterRadius - fInnerRadius)
    45. float fScaleDepth;      // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
    46. float fScaleOverScaleDepth; // fScale / fScaleDepth
    47. float fSamples;
    48. float g;
    49. float g2;
    50.  
    51. struct v2f {
    52.     float4 position : POSITION;
    53.     float3 c0 : COLOR0;
    54.     float3 c1 : COLOR1;
    55.     float3 t0 : TEXCOORD0;
    56. };
    57.  
    58.  
    59. float scale(float fCos)
    60. {
    61.     float x = 1.0 - fCos;
    62.     return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
    63. }
    64.  
    65. v2f vert (float4 vertex : POSITION)
    66. {
    67.     // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere)
    68.     float3 v3Pos = vertex.xyz;
    69.     float3 v3Ray = v3Pos - v3CameraPos;
    70.     float fFar = length(v3Ray);
    71.     v3Ray /= fFar;
    72.  
    73.     // Calculate the ray's starting position, then calculate its scattering offset
    74.     float3 v3Start = v3CameraPos;
    75.     float fHeight = length(v3Start);
    76.     float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fCameraHeight));
    77.     float fStartAngle = dot(v3Ray, v3Start) / fHeight;
    78.     float fStartOffset = fDepth*scale(fStartAngle);
    79.  
    80.     // Initialize the scattering loop variables
    81.     //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
    82.     float fSampleLength = fFar / fSamples;
    83.     float fScaledLength = fSampleLength * fScale;
    84.     float3 v3SampleRay = v3Ray * fSampleLength;
    85.     float3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
    86.  
    87.     // Now loop through the sample rays
    88.     float3 v3FrontColor = float3(0.0, 0.0, 0.0);
    89.     for(int i=0; i<2; i++)
    90.     {
    91.         float fHeight = length(v3SamplePoint);
    92.         float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
    93.         float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;
    94.         float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;
    95.         float fScatter = (fStartOffset + fDepth*(scale(fLightAngle) - scale(fCameraAngle)));
    96.         float3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
    97.         v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
    98.         v3SamplePoint += v3SampleRay;
    99.     }
    100.  
    101.     // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
    102.     v2f o;
    103.     o.position = mul (UNITY_MATRIX_MVP, vertex);
    104.     o.c0.rgb = v3FrontColor * fKmESun;
    105.     o.c1.rgb = v3FrontColor * (v3InvWavelength * fKrESun);
    106.     o.t0 = v3CameraPos - v3Pos;
    107.     return o;
    108. }
    109.  
    110. float4 frag (v2f i) : COLOR
    111. {
    112.     float fCos = dot(v3LightPos, i.t0) / length(i.t0);
    113.     float fRayleighPhase = 0.75 * (1.0 + fCos*fCos);
    114.     float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
    115.     float4 FragColor;
    116.     FragColor.xyz = fRayleighPhase * i.c0 + fMiePhase * i.c1;
    117.     FragColor.w = FragColor.z;
    118.     return FragColor;
    119. }
    120. ENDCG
    121.  
    122.     }
    123. }
    124. Fallback "VertexLit"
    125. }
    And here's the code to feed it variables.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Sky : 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.             outerRadius = transform.localScale.y;//100f;//6530.28f;
    39.             outerRadius2 = outerRadius * outerRadius;
    40.             innerRadius = outerRadius * 0.975f;//6371f;
    41.         innerRadius2 = innerRadius * innerRadius;
    42.         ESun = 15f;
    43.         Kr = 0.0025f;
    44.         Km = 0.0015f;
    45.         KrESun = Kr * ESun;
    46.         KmESun = Km * ESun;
    47.         Kr4PI = Kr * 4.0f * Mathf.PI;
    48.         Km4PI   = Km * 4.0f * Mathf.PI;
    49.         scale = 1f / (outerRadius - innerRadius);
    50.         scaleDepth = 0.25f;
    51.         scaleOverScaleDepth = scale / scaleDepth;
    52.         samples = 4f;
    53.         g = -0.95f;
    54.         g2 = g*g;
    55.     }
    56.    
    57.     //void OnGUI() {
    58.       //if (debug) {
    59.         //waveLength = DebugUtility.RGBSlider (new Rect (10,10,100,20), waveLength);
    60.         //ESun = DebugUtility.LabelSlider(new Rect (10,70,100,20), ESun, 50,"ESun: " + ESun );
    61.         //Kr = DebugUtility.LabelSlider(new Rect (10,90,100,20), Kr, 0.01f,"Kr: " + Kr);
    62.         //Km = DebugUtility.LabelSlider(new Rect (10,110,100,20), Km, 0.01f,"Km: " + Km);
    63.         //scaleDepth = DebugUtility.LabelSlider(new Rect (10,130,100,20), scaleDepth, 1.0f,"Scale Depth: " + scaleDepth);
    64.         //g = DebugUtility.LabelSlider(new Rect (10,150,100,20), g, -1.0f,"G: " + g);
    65.       //}
    66.     //}
    67.    
    68.     // Update is called once per frame
    69.     void LateUpdate () {
    70.         sunLightDirection = sunLight.transform.TransformDirection (-Vector3.forward);
    71.  
    72.         invWaveLength = new Color(pow(waveLength[0], 4), pow(waveLength[1], 4), pow(waveLength[2], 4), 0.5f);
    73.  
    74.         cameraHeight = mainCamera.position.magnitude;
    75.         cameraHeight2 = cameraHeight * cameraHeight;
    76.  
    77.         outerRadius2 = outerRadius * outerRadius;
    78.         innerRadius2 = innerRadius * innerRadius;
    79.         KrESun = Kr * ESun;
    80.         KmESun = Km * ESun;
    81.         Kr4PI = Kr * 4.0f * Mathf.PI;
    82.         Km4PI = Km * 4.0f * Mathf.PI;
    83.         scale = 1 / (outerRadius - innerRadius);
    84.         scaleOverScaleDepth = scale / scaleDepth;
    85.         g2 = g * g;
    86.  
    87.         // Pass in variables to the Shader
    88.         renderer.material.SetVector("v3CameraPos",new Vector4(mainCamera.position[0],mainCamera.position[1],mainCamera.position[2], 0));
    89.      
    90.         renderer.material.SetVector("v3LightDir", new Vector4(sunLightDirection[0],sunLightDirection[1],sunLightDirection[2],0));
    91.         renderer.material.SetColor("v3InvWavelength", invWaveLength);
    92.         renderer.material.SetFloat("fCameraHeight", cameraHeight);
    93.         renderer.material.SetFloat("fCameraHeight2", cameraHeight2);
    94.         renderer.material.SetFloat("fOuterRadius", outerRadius);
    95.         renderer.material.SetFloat("fOuterRadius2", outerRadius2);
    96.         renderer.material.SetFloat("fInnerRadius", innerRadius);
    97.         renderer.material.SetFloat("fInnerRadius2", innerRadius2);
    98.         renderer.material.SetFloat("fKrESun",KrESun);
    99.         renderer.material.SetFloat("fKmESun",KmESun);
    100.         renderer.material.SetFloat("fKr4PI",Kr4PI);
    101.         renderer.material.SetFloat("fKm4PI",Km4PI);
    102.         renderer.material.SetFloat("fScale",scale);
    103.         renderer.material.SetFloat("fScaleDepth",scaleDepth);
    104.         renderer.material.SetFloat("fScaleOverScaleDepth",scaleOverScaleDepth);
    105.         renderer.material.SetFloat("Samples",samples);
    106.         renderer.material.SetFloat("g",g);
    107.         renderer.material.SetFloat("g2",g2);
    108.     }
    109.    
    110.     float pow(float f, int p) {
    111.         return 1f / Mathf.Pow(f,p);
    112.     }
    113. }
    114.  
    I use a sphere that's around 6839.29, 6839.28, 6839.28, and assign my normal camera and just a basic directional light to it. No successes. What's going wrong? I've tried re-doing this script several times, no luck.
     
  10. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,864
    I havent checked your code, but with this specific shader, the numbers you feed in must be precise. Slight offsets break the visuals.
    So, try to stick with the exact float numbers in original shaders to see if your shader works, then move on to change values.
     
  11. mbdev

    mbdev

    Joined:
    Feb 10, 2013
    Posts:
    12
    Just tried that. Positioned the Camera outside the sphere like it is in all the demos, set the original values, and still just an all white dome.
     
  12. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,864
    Good start, now check your code all over for tiny mistakes.
     
  13. Josh707

    Josh707

    Joined:
    Jul 12, 2012
    Posts:
    68
    Hi everyone, I found an old Unity 2.something compatible atmospheric scattering shader from the ground that does not seem to be written correctly for recent use, but it was based off of the same article. Looking in the documentation it seems like it should work perfectly. If I comment out #pragma vertex vert then there are no errors but it will not work. If I uncomment it, I get roughly 30 syntax errors and expected '}'s or commas. Would somebody be kind enough to take a peek and point me in the right direction to convert the code?

    Code (csharp):
    1.  
    2.     // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    3.      
    4.      
    5.     Shader "atmScatteringTest" {
    6.      
    7.             Properties{
    8.                     DirectionalityFactor("DirectionalityFactor",float) = 0
    9.                     SunColorIntensity("SunColorIntensity",float) = 0
    10.                     tint("tint",float) = 1
    11.                     LightDir("LightDir",Vector) = (0,0,0)
    12.                     vBetaRayleigh("vBetaRayleigh",Vector) = (0,0,0)
    13.                     BetaRayTheta("BetaRayTheta",Vector) = (0,0,0)
    14.                     vBetaMie("vBetaMie",Vector) = (0,0,0)
    15.                     BetaMieTheta("BetaMieTheta",Vector) = (0,0,0)
    16.                     g_vEyePt("g_vEyePt",Vector) = (0,0,0)
    17.                     g_vSunColor("g_vSunColor",Vector) = (0,0,0)
    18.             }
    19.            
    20.             SubShader{
    21.                     Pass{
    22.            
    23.                             Cull Front
    24.                            
    25.                             CGPROGRAM
    26.                             #pragma exclude_renderers gles
    27.                             #pragma vertex vert
    28.                             float3 g_vEyePt;
    29.                             float3 vBetaRayleigh;
    30.                             float3 BetaRayTheta;
    31.                             float3 vBetaMie;      
    32.                             float3 BetaMieTheta;
    33.                             float3 LightDir;
    34.                             float3 g_vSunColor;
    35.                             float DirectionalityFactor;
    36.                             float SunColorIntensity;
    37.                            
    38.                             struct vertex_output{
    39.                                     float4 position : POSITION;
    40.                                     float4 color : COLOR;
    41.                             }
    42.                            
    43.                            
    44.                             float3 BetaR(float Theta){
    45.                                     return BetaRayTheta*(3.0f+0.5f*Theta*Theta);
    46.                             }
    47.                            
    48.                             float3 BetaM(float Theta){
    49.                                     float g = DirectionalityFactor;
    50.                                     return (BetaMieTheta*pow(1.0f-g, 2.0f))/(pow(1+g*g-2*g*Theta, 1.5f));
    51.                             }
    52.                             float3 Lin(float Theta, float SR, float SM){
    53.                                     return ((BetaR(Theta)+BetaM(Theta))*(1.0f-exp(-(vBetaRayleigh*SR+vBetaMie*SM))))/(vBetaRayleigh + vBetaMie );
    54.                             }
    55.                            
    56.                             vertex_output vert(appdata_base i){
    57.                                     vertex_output o;
    58.                                     float3 vPosWorld = Input.vertex;
    59.                                     float3 ray = vPosWorld - g_vEyePt;
    60.                                     float far = length(ray) ;
    61.                                     ray = normalize(ray);
    62.                                     float Theta = dot(ray, LightDir);
    63.                                     float SR =(1.05f-pow(ray.y,0.3f)) * 2000;
    64.                                     float SM=far*0.05f;
    65.                                     float3 L=Lin(Theta, SR, SM );
    66.                                    
    67.                                     o.position = mul(UNITY_MATRIX_MVP, i.vertex);
    68.                                     o.color.rgb = L*g_vSunColor*SunColorIntensity;
    69.                                     o.color.a = 1.0f;
    70.                                     return o;
    71.                             }
    72.                            
    73.                            
    74.                            
    75.                             ENDCG
    76.                     }
    77.            
    78.             }      
    79.                    
    80.     }
    81.  
    82.  
    This isn't the entire shader, I took out some unneeded stuff for cloud planes, but I don't know why it is giving so many errors. I would have made a new post but it seems to be better to ask in one that's already on the same topic.
     
    Last edited: Mar 15, 2013
  14. mbdev

    mbdev

    Joined:
    Feb 10, 2013
    Posts:
    12
    This should compile without errors.

    You were missing a ; after the struct and there was a couple of incorrect casts, like input instead of I. But you'll need a fragment shader for it to work properly, I would think.

    Code (csharp):
    1. Shader "atmScatteringTest" {
    2.  Properties
    3.  {
    4.     DirectionalityFactor("DirectionalityFactor",float) = 0
    5.     SunColorIntensity("SunColorIntensity",float) = 0
    6.     tint("tint",float) = 1
    7.     LightDir("LightDir",Vector) = (0,0,0)
    8.     vBetaRayleigh("vBetaRayleigh",Vector) = (0,0,0)
    9.     BetaRayTheta("BetaRayTheta",Vector) = (0,0,0)
    10.     vBetaMie("vBetaMie",Vector) = (0,0,0)
    11.     BetaMieTheta("BetaMieTheta",Vector) = (0,0,0)
    12.     g_vEyePt("g_vEyePt",Vector) = (0,0,0)
    13.     g_vSunColor("g_vSunColor",Vector) = (0,0,0)
    14.     }
    15.  SubShader{
    16.  Cull Front
    17.  Pass{
    18.  
    19.  
    20.  CGPROGRAM
    21.  #pragma exclude_renderers gles
    22.  #pragma vertex vert
    23.  #include "UnityCG.cginc"
    24.  
    25.     float3 g_vEyePt;
    26.     float3 vBetaRayleigh;
    27.     float3 BetaRayTheta;
    28.     float3 vBetaMie;      
    29.     float3 BetaMieTheta;
    30.     float3 LightDir;
    31.     float3 g_vSunColor;
    32.     float DirectionalityFactor;
    33.     float SunColorIntensity;
    34.     struct vertex_output
    35.     {
    36.         float4 position : POSITION;
    37.         float4 color : COLOR;
    38.     };
    39.     float3 BetaR(float Theta)
    40.     {
    41.         return BetaRayTheta*(3.0f+0.5f*Theta*Theta);
    42.     }
    43.     float3 BetaM(float Theta)
    44.     {
    45.         float g = DirectionalityFactor;
    46.         return (BetaMieTheta*pow(1.0f-g, 2.0f))/(pow(1+g*g-2*g*Theta, 1.5f));
    47.     }
    48.     float3 Lin(float Theta, float SR, float SM)
    49.     {
    50.         return ((BetaR(Theta)+BetaM(Theta))*(1.0f-exp(-(vBetaRayleigh*SR+vBetaMie*SM))))/(vBetaRayleigh + vBetaMie );
    51.     }
    52.     vertex_output vert(appdata_base i)
    53.     {
    54.         vertex_output o;
    55.         float3 vPosWorld = i.vertex.xyz;
    56.         float3 ray = vPosWorld - g_vEyePt;
    57.         float far = length(ray) ;
    58.         ray = normalize(ray);
    59.         float Theta = dot(ray, LightDir);
    60.         float SR =(1.05f-pow(ray.y,0.3f)) * 2000;
    61.         float SM=far*0.05f;
    62.         float3 L=Lin(Theta, SR, SM );
    63.         o.position = mul(UNITY_MATRIX_MVP, i.vertex);
    64.         o.color.rgb = L*g_vSunColor*SunColorIntensity;
    65.         o.color.a = 1.0f;
    66.         return o;
    67.     }
    68.     ENDCG
    69.     }
    70.     }      
    71. }
    72.  
    73.  
     
  15. Josh707

    Josh707

    Joined:
    Jul 12, 2012
    Posts:
    68
    Ah, thank you. I did take a chunk of the shader out so it wouldn't be messy on here and it does use a fragment shader. I'll try to write the rest keeping what you said in mind and If I can get this thing to work properly then I will update on here.
     
  16. mbdev

    mbdev

    Joined:
    Feb 10, 2013
    Posts:
    12
    Yeah let me know. Your approach seems to be the Hoffman/Preetham approach, which might be more conducive towards ground rendering then mine.. The heights are really messing me up with this one... This is what my latest attempts have gotten...
    $renderingissue2.jpg
     

    Attached Files:

  17. Josh707

    Josh707

    Joined:
    Jul 12, 2012
    Posts:
    68
    Edit:

    Okay well I got bored and decided to try again and I seem to have gotten closer, the shader has no errors anymore but a few warnings and for some reason my graphics card does not support it. Would you mind looking at this again and see if there is anything wrong? If I ever get it working I will be glad to provide the rest of the assets as you need a few, like an inverted normal sphere and scripts.

    Code (csharp):
    1.     Shader "atmScatteringTest" {
    2.      Properties
    3.      {
    4.         DirectionalityFactor("DirectionalityFactor",float) = 0
    5.         SunColorIntensity("SunColorIntensity",float) = 0
    6.         tint("tint",float) = 1
    7.         fade("Cloud fade height",float) = 0
    8.         cloudSpeed1("cloudSpeed1",float)=1
    9.         cloudSpeed2("cloudSpeed2",float)=1
    10.         plane_height1("cloud plane height 1",float)=1
    11.         plane_height2("cloud plane height 2",float)=1
    12.         noisetex ("noise texture", 2D) = "white" {}
    13.         starTexture ("starTexture", 2D) = "white" {}
    14.         LightDir("LightDir",Vector) = (0,0,0)
    15.         vBetaRayleigh("vBetaRayleigh",Vector) = (0,0,0)
    16.         BetaRayTheta("BetaRayTheta",Vector) = (0,0,0)
    17.         vBetaMie("vBetaMie",Vector) = (0,0,0)
    18.         BetaMieTheta("BetaMieTheta",Vector) = (0,0,0)
    19.         g_vEyePt("g_vEyePt",Vector) = (0,0,0)
    20.         g_vSunColor("g_vSunColor",Vector) = (0,0,0)
    21.         wind_direction("winddirection",Vector) = (0,0,0,0)
    22.         }
    23.      SubShader{
    24.      Cull Front
    25.      Pass{
    26.      
    27.      
    28.      CGPROGRAM
    29.      //#pragma exclude_renderers gles
    30.      #pragma vertex vert
    31.      #pragma fragment frag
    32.      #include "UnityCG.cginc"
    33.      
    34.         float3 g_vEyePt;
    35.         float3 vBetaRayleigh;
    36.         float3 BetaRayTheta;
    37.         float3 vBetaMie;   
    38.         float3 BetaMieTheta;
    39.         float3 LightDir;
    40.         float3 g_vSunColor;
    41.         float DirectionalityFactor;
    42.         float SunColorIntensity;
    43.         float cloudSpeed1;
    44.         float cloudSpeed2;
    45.         float tint;
    46.         float plane_height1;
    47.         float plane_height2;
    48.         float fade;
    49.         float4 wind_direction;
    50.         float4 cloudProperties;
    51.         sampler2D noisetex;
    52.         sampler2D starTexture;
    53.        
    54.         struct vertex_output
    55.         {
    56.             float4 position : POSITION;
    57.             float4 color    : COLOR;
    58.             float2 uvcoords1 : TEXCOORD0;// Cloud layer01
    59.             float intensity     : TEXCOORD1;// Cloud intensity
    60.             float2 uvcoords2    : TEXCOORD2;// Cloud layer02
    61.             float2 skydomecoluv : TEXCOORD3;// UV for the cloud layer
    62.             float orgposz       : TEXCOORD4;
    63.             float2 starUV       : TEXCOORD5;
    64.         };
    65.         float3 BetaR(float Theta)
    66.         {
    67.             return BetaRayTheta*(3.0f+0.5f*Theta*Theta);
    68.         }
    69.         float3 BetaM(float Theta)
    70.         {
    71.             float g = DirectionalityFactor;
    72.             return (BetaMieTheta*pow(1.0f-g, 2.0f))/(pow(1+g*g-2*g*Theta, 1.5f));
    73.         }
    74.         float3 Lin(float Theta, float SR, float SM)
    75.         {
    76.             return ((BetaR(Theta)+BetaM(Theta))*(1.0f-exp(-(vBetaRayleigh*SR+vBetaMie*SM))))/(vBetaRayleigh + vBetaMie );
    77.         }
    78.         vertex_output vert(appdata_base i)
    79.         {
    80.            
    81.            
    82.             vertex_output o;
    83.  
    84.             float3 vPosWorld = i.vertex.xyz;
    85.             float3 ray = vPosWorld - g_vEyePt;
    86.             float far = length(ray);
    87.             ray = normalize(ray);
    88.             float Theta = dot(ray, LightDir);
    89.             float SR =(1.05f-pow(ray.y,0.3f)) * 2000;
    90.             float SM=far*0.05f;
    91.             float3 L=Lin(Theta, SR, SM );
    92.            
    93.             //cloud stuff
    94.             float3 normVect=normalize(i.vertex.xyz);
    95.             o.orgposz=abs(i.vertex.y);
    96.             float2 vectLength1=float2(normVect.z,normVect.x)*plane_height1;
    97.             float2 vectLength2=float2(normVect.z,normVect.x)*plane_height2;
    98.             float t1=_Time*cloudSpeed1;
    99.             float t2=_Time*cloudSpeed2;
    100.             o.uvcoords1.xy=0.9*vectLength1+t1/10*wind_direction.xy*o.orgposz;
    101.             o.uvcoords2.xy=0.4*vectLength2+t2/10*wind_direction.zw*o.orgposz;
    102.             float fadeheight=fade/64;
    103.             o.starUV=i.texcoord * 20;
    104.             o.position=mul(UNITY_MATRIX_MVP,i.vertex);
    105.             o.intensity=max(normVect.y-fadeheight,0);
    106.             o.color.rgb=L*g_vSunColor*SunColorIntensity;
    107.             o.color.a=1.0f;
    108.             return o;
    109.         }
    110.        
    111.         float4 frag (vertex_output i) : COLOR {
    112.             float4 newColor:COLOR;
    113.             float4 noise1=tex2D(noisetex,i.uvcoords1.xy/i.orgposz);
    114.             float4 noise2=tex2D(noisetex,i.uvcoords2.xy/i.orgposz);
    115.             float4 stars=tex2D(starTexture,i.starUV.xy);
    116.             float4 cloud_color=(noise1*noise2);
    117.             float intensity=1-exp(-512*pow(i.intensity,1));
    118.             stars*=1-saturate(g_vSunColor.z* 4 + cloud_color.a*2);
    119.             float cloud_alpha = max(noise1.a, noise2.a);
    120.             stars*= cloud_alpha *2;
    121.             newColor=stars;
    122.             newColor+=(g_vSunColor.z+tint)*cloud_color.z*(intensity)*cloud_color;
    123.             newColor+=i.color;
    124.             newColor.a=1.0;
    125.             return newColor;
    126.         }
    127.        
    128.        
    129.         ENDCG
    130.         }
    131.         }    
    132.        
    133.       Fallback "None"  
    134.     }
    Just in case here are the other 2 scripts needed:
    http://pastebin.com/EK4tG7p2 - Sun.cs
    http://pastebin.com/jCSE8Nat - atmosphereHandler.cs

    It's a little complex to set up though.
     
    Last edited: Mar 15, 2013
  18. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    GreenCore likes this.
  19. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,785
  20. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    The shaders are ported to Unity from whats found in the GPU GEMS article not from what mbdev and josh707 have posted. I know they were having some issues with getting it to work. Im not sure what was the cause of the problems they were having.
     
  21. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,785
    Ah i see so you port the code to unity, alright then....cool :D
     
  22. Luckymouse

    Luckymouse

    Joined:
    Jan 31, 2010
    Posts:
    484
    @scrawk

    Your Atmospheric Scattering Demo works great in Unity4, thanks for sharing.
     
  23. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Well, it would be awesome to do this, but my planet's too small... and scaling it up ruins it!