I calculate the scattering in my shader.
Here it is if it is useful
#include "ShaderVariables.inc"
struct appdata {
float3 Position : POSITION;
float4 Normal : NORMAL;
float2 UV0 : TEXCOORD0;
half4 Tangent : TANGENT0;
half4 Binormal : BINORMAL0;
};
struct vertexOutput {
float4 HPosition : POSITION;
float3 WorldLightVec : TEXCOORD0;
float3 WorldNormal : TEXCOORD1;
float3 WorldEyeDirection : TEXCOORD2;
half3 WorldTangent : TEXCOORD3;
half3 WorldBinorm : TEXCOORD4;
float2 UV : TEXCOORD5;
half Fog : TEXCOORD6;
half2 Altitudes : TEXCOORD7;
};
float4 LightDirection = {100.0f, 100.0f, 100.0f, 1.0f};
float4 LightColor = {1.0f, 1.0f, 1.0f, 1.0f};
float4 LightColorAmbient = {0.0f, 0.0f, 0.0f, 1.0f};
float4 FogColor = {1.0f, 1.0f, 1.0f, 1.0f};
float fDensity ;
bool isSkydome;
float SunLightness = 0.2;
float sunRadiusAttenuation = 256;
float largeSunLightness = 0.2;
float largeSunRadiusAttenuation = 3;
float dayToSunsetSharpness = 1.5;
float hazeTopAltitude = 20;
texture DiffuseTexture;
sampler SurfSamplerDiffuse = sampler_state
{
Texture = <DiffuseTexture>;
MinFilter = Linear;
MipFilter = Linear;
MagFilter = Linear;
};
texture SkyTextureNight;
sampler SurfSamplerSkyTextureNight = sampler_state
{
Texture = <SkyTextureNight>;
MinFilter = Linear;
MipFilter = Linear;
MagFilter = Linear;
AddressU = mirror;
AddressV = mirror;
};
texture SkyTextureSunset;
sampler SurfSamplerSkyTextureSunset = sampler_state
{
Texture = <SkyTextureSunset>;
MinFilter = Linear;
MipFilter = Linear;
MagFilter = Linear;
AddressU = mirror;
AddressV = mirror;
};
texture SkyTextureDay;
sampler SurfSamplerSkyTextureDay = sampler_state
{
Texture = <SkyTextureDay>;
MinFilter = Linear;
MipFilter = Linear;
MagFilter = Linear;
AddressU = mirror;
AddressV = mirror;
};
vertexOutput mainVS (appdata IN)
{
vertexOutput OUT;
float4 Po = float4(IN.Position.xyz,1);
OUT.HPosition = mul( Po, WorldViewProjection);
OUT.WorldNormal = mul( IN.Normal, WorldInverseTranspose).xyz;
OUT.WorldTangent = mul(IN.Tangent, WorldInverseTranspose).xyz;
OUT.WorldBinorm = mul(IN.Binormal, WorldInverseTranspose).xyz;
OUT.WorldLightVec = -LightDirection.xyz;
float3 Pw = mul( Po, World).xyz;
OUT.WorldEyeDirection = ViewInverse[3].xyz - Pw;
OUT.Altitudes.x = ViewInverse[3].y;
float4 pos = mul( IN.Position, World);
float dist = length(OUT.WorldEyeDirection);
OUT.Fog = (1.f/exp(pow(dist * fDensity, 2)));
OUT.Altitudes.y = Pw.y;
OUT.UV = IN.UV0;
return OUT;
}
float4 mainPS(vertexOutput IN) : COLOR0
{
float4 colorOutput = float4(0,0,0,1);
float4 DiffuseColor = tex2D( SurfSamplerDiffuse, float2( IN.UV.x, 1-IN.UV.y));
float4 colorAmbient = DiffuseColor;
// Calculate light/eye/normal vectors
float eyeAlt = IN.Altitudes.x;
float3 eyeVec = normalize(IN.WorldEyeDirection);
float3 normal = normalize(IN.WorldNormal);
float3 lightVec = normalize(IN.WorldLightVec);
// Calculate the amount of direct light
float NdotL = max( dot( normal, -lightVec), 0);
float4 colorDiffuse = DiffuseColor * (NdotL * LightColor) + LightColorAmbient * DiffuseColor;
colorOutput += colorDiffuse;
colorOutput.a = 1.0f;
// Calculate sun highlight...
float sunHighlight = pow(max(0, dot(lightVec, -eyeVec)), sunRadiusAttenuation) * SunLightness;
// Calculate a wider sun highlight
float largeSunHighlight = pow(max(0, dot(lightVec, -eyeVec)), largeSunRadiusAttenuation) * largeSunLightness;
// Calculate 2D angle between pixel to eye and sun to eye
float3 flatLightVec = normalize(float3(lightVec.x, 0, lightVec.z));
float3 flatEyeVec = normalize(float3(eyeVec.x, 0, eyeVec.z));
float diff = dot(flatLightVec, -flatEyeVec);
// Based on camera altitude, the haze will look different and will be lower on the horizon.
// This is simulated by raising YAngle to a certain power based on the difference between the
// haze top and camera altitude.
// This modification of the angle will show more blue sky above the haze with a sharper separation.
// Lerp between 0.25 and 1.25
float val = lerp(0.25, 1.25, min(1, hazeTopAltitude / max(0.0001, eyeAlt)));
// Apply the power to sharpen the edge between haze and blue sky
float YAngle = pow(max(0, -eyeVec.y), val);
// Fetch the 3 colors we need based on YAngle and angle from eye vector to the sun
float4 fogColorDay = tex2D( SurfSamplerSkyTextureDay, float2( 1 - (diff + 1) * 0.5, 1-YAngle));
float4 fogColorSunset = tex2D( SurfSamplerSkyTextureSunset, float2( 1 - (diff + 1) * 0.5, 1-YAngle));
float4 fogColorNight = tex2D( SurfSamplerSkyTextureNight, float2( 1 - (diff + 1) * 0.5, 1-YAngle));
float4 fogColor;
// If the light is above the horizon, then interpolate between day and sunset
// Otherwise between sunset and night
if (lightVec.y > 0)
{
// Transition is sharpened with dayToSunsetSharpness to make a more realistic cut
// between day and sunset instead of a linear transition
fogColor = lerp(fogColorDay, fogColorSunset, min(1, pow(abs(1 - lightVec.y), dayToSunsetSharpness)));
}
else
{
// Slightly different scheme for sunset/night.
fogColor = lerp(fogColorSunset, fogColorNight, min(1, -lightVec.y * 4));
}
// Add sun highlights
fogColor += sunHighlight + largeSunHighlight;
// Apply fog on output color
colorOutput = lerp(fogColor, colorOutput, IN.Fog);
// Make sun brighter for the skybox...
//if (isSkydome)
colorOutput = fogColor + sunHighlight;
return colorOutput;
}
technique SkyDome
{
pass p0
{
CullMode = None;
VertexShader = compile VS_SHADERMODEL mainVS();
PixelShader = compile PS_SHADERMODEL mainPS();
}
}