Sky scattering shader

This is a discussion on Sky scattering shader within the Game Programming forums, part of the General Programming Boards category; I need some help from you math gurus out there. These sky scatter shader formulas were taken from a GDC ...

  1. #1
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584

    Sky scattering shader

    I need some help from you math gurus out there. These sky scatter shader formulas were taken from a GDC conference and I'm not sure how to implement the math portion.


    Namely the e^-(B.R+B.M)s.

    B.R is Rayleigh scattering and B.M is Mie scattering.


    I can compute B.R and B.M rather easily. They are a function of a constant and an angle. Essentially the constant changes as the angle changes as well as optical length and other factors.

    Computing L(in) which is in-scattering, however, looks quite complex.

    Computing F(ex) which is extinction also has the e raised to -(B.R+B.M)s. How do i represent this in code? Is it

    Code:
    float value=exp(-(DoRayleigh())+(DoMie())*s);
    Last edited by VirtualAce; 03-12-2011 at 10:42 AM.

  2. #2
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Quote Originally Posted by Bubba
    How do i represent this in code? Is it
    Code:
    float value=exp(-(DoRayleigh())+(DoMie())*s);
    Yes, that's correct.

    PS: What is E_sun?
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  3. #3
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    A 4d vector representing the tri-stimulus values of sun emissivity. Lots of big wordies there but I dunno how else to explain it.

    I found the source for a good shader in a Master's thesis and I'm going to tinker with it and figure it out. So far I was close, except that the GDC powerpoint did not explain which items were vectors and which one's were not. Usually vectors are upper case letters, but ya never know.

    Also the GDC version assumes:

    1. Low camera level - as in FPS
    2. Constant atmospheric density.
    3. Constant particle size.

    This one I found actually simulates the first 2. The good thing about this is when I change the sun angle, the horizon will have the correct RGB values - no hacks or anything - just pure math.

  4. #4
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Well here is an update on the sky scattering shader. After attempting to get everyone else's implementation working, I ran through the GDC article again and just coded the shader myself.

    I'm quite happy with it so far. Here is a screenshot of it in action.

    The trees have been disabled in this shot because I don't want to apply diffuse shading to the trees and so to apply the sky scatter shader w/o diffuse is going to require a bit more work.
    Last edited by VirtualAce; 03-12-2011 at 10:42 AM.

  5. #5
    ---
    Join Date
    May 2004
    Posts
    1,379
    very impressive
    well done

  6. #6
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    Thanks. I guess in the end copying other people's code gets you nowhere fast. I just thought I'd trust them since they knew more, but eventually my own code got it working.

    Other people were using vectors to hold values used in the equations and were not using the vector as a vector per se. Good idea but very obfuscated when a noob like me is attempting to learn the stuff.

    Next up is procedural texturing. I'm looking at several sources and deciding on whether or not to use octaves of Perlin noise or some other noise functions.

    A very interesting link to some cool noise effects:

    http://www.noisemachine.com/talk1/index.html

    This is the final effect file for the sky scattering shader. Diffuse lighting is computed in this shader but I'm going to move it to another shader as well as specular.

    If I change the turbidity of the atmosphere and the directional quality of the light (scattered or focused) I will get a very bright spot on the terrain where the sun would be. Using the same shader on a skydome I would then be able to simulate a very bright sun w/o using any billboards and it would look much better.
    Last edited by VirtualAce; 08-21-2006 at 10:52 PM.

  7. #7
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    >> I guess in the end copying other people's code gets you nowhere fast. I just thought I'd trust them since they knew more, but eventually my own code got it working.

    That one crept up on me too. I figured that "hey now I've got this book full of examples I'll just copy most of it and it'll give me a good headstart"... Um, nope, no sale!

    At first I was more reorganising than rewriting the examples but eventually I realised that I didn't fully understand some parts of it or just didn't like the way they worked at all - coding my own from scratch certainly paid off.

    Anyways the shader's looking neat, man
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  8. #8
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    The shader has some problems. Namely the directional component seems to have no effect on the color and yet it should.

    The source:

    Code:
    //Not used
    //static const float log2_e = 1.0f/log(2.0f);
    
    //Eye position
    float4 vEye;
    
    //Sun direction
    float4 vSunDirection;
    
    //Henyey/Greenstein phase function eccentricity approx
    float fHG;
    
    //Sun angle
    float fSunTheta;
    
    //Rayleigh coef
    float4 vBetaRayleigh;
    
    //Mie coef
    float4 vBetaMie;
    
    //Rayleigh+Mie coefs added
    float4 vBetaRM;
    
    //Sun color and intensity
    float4 vSunIntensity;
    
    //Diffuse color and intensity - (diffuse * intensity) component-wise multiply
    float4 vDIC;
    
    //Matrices
    float4x4 matWorldView;
    float4x4 matWorldViewProj;
    float4x4 matWorld;
    
    //Samplers
    sampler Terrain;   //0
    sampler Detail;    //1
    
    
    //Input Struct
    struct SkyInput 
    {
      float3 Position : POSITION;
      float3 Normal : NORMAL;
      float2 TerrainUV: TEXCOORD0;
      float2 DetailUV:TEXCOORD1;
    };
    
    //Vertex shader output struct
    struct VS_OUTPUT
    {
      float4 Position : POSITION;
      float3 Normal : TEXCOORD0;
      float2 TerrainUV : TEXCOORD1;
      float2 DetailUV: TEXCOORD2;
      float4 Extinction : COLOR0;
      float4 InScatter : COLOR1;
    };
    
    //Compute rayleigh scattering
    float4 DoRayleigh(float theta)
    {
      //(3/16)*PI
      float PI316=3.0f/(16.0f*3.141592f);
      
      //(1+(cos(theta)^2))
      float theta2=theta*theta;
      return vBetaRayleigh*(1.0f+theta2)*PI316;
    }
    
    //Compute Mie scattering
    float4 DoMie(float theta)
    {
      //1/4*PI
      float PI14=1.0f/(4*3.141592);
      
      
      float4 fHG2=fHG*fHG;
      float4 numerator=(1-fHG)*(1-fHG);
      float4 denom=pow(1+fHG2-2*fHG*theta,3.0/2.0);
      return (numerator/denom)*vBetaMie*PI14;
    }
    
    //Compute extinction
    float4 DoExtinction(float s)
    {
      float4 temp=exp(-vBetaRM*s);
      return temp;
    }
      
    //Compute inscattering
    float4 DoInscatter(float theta,float4 vExtinction)
    {
      float4 vBetaDashRM=DoRayleigh(theta)+DoMie(theta);
      float4 vValue1=vBetaDashRM/vBetaRM;
      
      return vValue1*vSunIntensity*(1.0-vExtinction);
    }
    
    //Vertex shader main
    VS_OUTPUT MainVS(SkyInput IN)
    {
      VS_OUTPUT outParams=(VS_OUTPUT)0;  
      
      //Convert IN.Position to D3DXVECTOR4
      float4 vPos=float4(IN.Position,1.0f);
      
      //Vertex position transform
      outParams.Position=mul(vPos,matWorldViewProj);
      
      //View position
      float4 ViewPos=mul(vPos,matWorldView);
      
      //World position
      float4 vWorldPos=mul(vPos,matWorld);
      
      //Normalize the normal passed to vertex shader
      float4 norm=float4(IN.Normal,1.0f);
      norm=normalize(norm);
      
      //Cosing of angle between sun and surface normal
      float theta=dot(norm,vSunDirection);
        
      //Just pass terrain u,v tex coords onto pixel shader
      outParams.TerrainUV=IN.TerrainUV;
      
      //Check for distance - no need for detail texture at large Z distances
      //Only works on cards that support Pixel shader 3.0
      //If we pass on detail tex coords, the pixel shader will use them
      //If we don't pass them on, we effectively turn off the detail texture
      //ViewPos has been correctly transformed so that Z comparisons are very simple
      if (ViewPos.z<1000)
      {
    	outParams.DetailUV=IN.DetailUV;
      }	
      
      //Pass normal to pixel shader
      outParams.Normal=IN.Normal;
      
      //Compute extinction and pass to pixel shader
      outParams.Extinction=DoExtinction(ViewPos.z);
      
      //Compute inscatter and pass to pixel shader
      outParams.InScatter=DoInscatter(theta,outParams.Extinction);
      
      //Pass entire structure to pixel shader
      return outParams;
    }
    
    //Pixel shader main
    float4 MainPS(VS_OUTPUT IN):COLOR
    {
      //Get texture colors
      float4 LandColor=tex2D(Terrain,IN.TerrainUV);
      float4 DetailColor=tex2D(Detail,IN.DetailUV);
      
      //Normalize normal
      float3 Normal=normalize(IN.Normal);
      
      //Compute diffuse lighting coefficient
      float DiffCoef=dot(Normal,vSunDirection);
      
      //Modulate land and detail textures
      float4 MixColor=(LandColor*DetailColor);
      
      //Compute final diffuse color and intensity
      float4 Diffuse=DiffCoef*vDIC;
      
      //Final land color is terrain mix color modulated with diffuse
      float4 FinalLandColor=MixColor*Diffuse;
      
      //Ensure alphas are 1 
      FinalLandColor.a=1;
      
      //Now apply scattering
      //L(s,theta)=(StartColor*Extinction(dist))+InScatter(dist,theta)
      float4 FinalColor=(FinalLandColor*IN.Extinction)+IN.InScatter;
      
      //Ensure alphas are 1
      FinalColor.a=1;
      
      //Finally we are done with this mess
      return FinalColor;
      
    }
    
    //Techniques
    technique SkyScatter30
    {
        //3.0 VS/PS pass
        //Only works on pixel and vertex shader model 3.0
        pass P0
        {
           VertexShader=compile vs_3_0 MainVS();
           PixelShader=compile ps_3_0 MainPS();
        }
    }
    The only change I'm going to make is the detail texturing. I'll gradually blend it out using alpha instead of just turning it off or on.
    Last edited by VirtualAce; 08-23-2006 at 05:20 AM.

  9. #9

    Join Date
    May 2005
    Posts
    1,041
    I may have found some potential problems. The equations you've implemented are not the same as what you said they should be in some of your comments, in particular the DoRayleigh func:

    //(3/16)*PI
    float PI316=3.0f/(16.0f*3.141592f);
    (3/16)*PI is not the same as what you've assigned to PI316

    and in the second part of dorayleigh:

    //(1+(cos(theta)^2))
    float theta2=theta*theta;
    return vBetaRayleigh*(1.0f+theta2)*PI316;
    1 + cos(theta) ^ 2, or 1 + cos(theta^2)? [I don't see a cos in there to begin with, is that an approximation to cos?]

    Note I only checked against your comments, not the paper.

    What exactly is a 'technique' supposed to be? Is that just how you compile the frag/vert programs?


    Looks very good on the whole, keep up the good work!
    I'm not immature, I'm refined in the opposite direction.

  10. #10
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,584
    (3/16)*PI is not the same as what you've assigned to PI316
    Even though my comment says (3/16)PI it is actually (3/16PI).

    1 + cos(theta) ^ 2, or 1 + cos(theta^2)?
    Theta in my example is the dot product between the normal and the sun or light vector.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Rayleigh scattering shader
    By psychopath in forum Game Programming
    Replies: 18
    Last Post: 07-07-2009, 04:01 PM
  2. Shaders and parameters
    By VirtualAce in forum Game Programming
    Replies: 2
    Last Post: 12-06-2006, 06:33 AM
  3. Shader hell
    By VirtualAce in forum Game Programming
    Replies: 4
    Last Post: 08-18-2006, 09:21 PM
  4. Critique my lighting model.
    By psychopath in forum Game Programming
    Replies: 4
    Last Post: 08-12-2006, 06:23 PM
  5. Replies: 6
    Last Post: 11-12-2005, 10:57 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21