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.