# Atmospheric Scattering

## Recommended Posts

Thergothon    160
I'm trying to implement atmospheric scattering from the Nielsons paper: "Real Time Rendering of Atmospheric Scattering Effects for Flight Simulators", and there is a couple of things I don't understand. In appendix e.2, he uses a rayleigh and mie multiplier and applies that to both the rayleigh and mie coefficients. I'm assuming that it is some xyz to rgb conversion multiplier as the xyz values for the rayleigh and mie constants are extremely small and would explain why my sky is black, but I can't find anywhere in the paper that describes where he gets these constants from. Also, I can't find where he gets the density values that are uploaded into the shader in appendix e.2, which are then used to calculate the particle and molecular optical depth used in the extinction calculation. I'm assuming that they are from equations 5.9 and 5.10, but where does the value c come from? Is that the constant used to calculate the mie coefficient?

##### Share on other sites
Sark7    122
Did you check the Preetham's "A Practical Analytic Model for Daylight"?
It may contain some of formulas you need.

##### Share on other sites
Thergothon    160
That paper didn't help me much, it seems to use a different approach using constant tables to provide a pretty good approximation. I also checked out the ATI paper and all their formulas match the ones in the paper I mentioned above. I decided to drop the altitude density stuff from the simulation to simplify it, so I could at least get it looking good from ground level first. I'll post source snippets, and maybe somebody can point out where I am going wrong.

Coefficient calculations:

	float r = 1.0f/650e-9f; //red - 650nm	float g = 1.0f/610e-9f; //green - 610nm	float b = 1.0f/475e-9f; //blue - 475nm	float r2 = r*r;	float g2 = g*g;	float b2 = b*b;	float r4 = r2*r2;	float g4 = g2*g2;	float b4 = b2*b2;		//calculate rayleigh scattering coefficient	//br = (8pi^3(n^2 - 1)^2)/(3Nw^4)	//n = refractive index of air	//N = molecular density	//w = wavelength of light	float n = 1.0002926f;	float N = 2.545e25f;	float temp = 8.0f*D3DX_PI*D3DX_PI*D3DX_PI/(3.0f*N);	float temp2 = (n*n - 1.0f)*(n*n - 1.0f);	m_rayleigh.x = temp*temp2*r4;	m_rayleigh.y = temp*temp2*g4;	m_rayleigh.z = temp*temp2*b4;	//calculate mie scattering coefficient	//bm = 0.424*c*pi*(4pi^2/w^2)*K	//c = (0.6544*T - 0.6510)*10^-16	//	T = turbidity	//w = wavelength of light	//K ~ 0.67 (varies with colour)	float T = 555e-9f;	float c = (0.6544f*T - 0.6510f)*1e-16f;	temp = 0.67f*0.424f*c*D3DX_PI;	m_mie.x = temp*(4.0f*D3DX_PI*D3DX_PI*r2);	m_mie.y = temp*(4.0f*D3DX_PI*D3DX_PI*g2);	m_mie.z = temp*(4.0f*D3DX_PI*D3DX_PI*b2);	//store henyey greenstein constants	//HG = (1 - g^2)/(4pi(1 + g^2 - 2g*cos(theta)^3/2)	//g = directionality constant	g = 0.55f;	m_hg.x = 1.0f - g*g;	m_hg.y = 1.0f + g*g;	m_hg.z = 2.0f*g;	m_hg.w = 4.0f*D3DX_PI;	//store scaled scattering coefficients for phase functions	m_rayleigh2 = m_rayleigh * 3.0f/(16.0f*D3DX_PI);	m_mie2 = m_mie/(4.0f*D3DX_PI);		//store constant in inscattering function	m_inscatter.x = 1.0f/(m_rayleigh.x + m_mie.x);	m_inscatter.y = 1.0f/(m_rayleigh.y + m_mie.y);	m_inscatter.z = 1.0f/(m_rayleigh.z + m_mie.z);

float4x4 world;float4x4 viewProj;float4 sun; //sunlight colour + intensityfloat3 lightDir; //sunlight directionfloat3 rayleigh; //rayleigh coefficientfloat3 rayleigh2; //rayleigh * phase coefficientfloat3 mie; //mie coefficientfloat3 mie2; //mie * phase coefficientfloat4 hg; //henyey greenstein phase function constantsfloat3 inscatter; //inscattering coefficientstruct vsin{    float3 pos : POSITION;    float3 norm: NORMAL;    float2 tex : TEXCOORD0; //optical depth in y};struct vsout {    float4 final : POSITION;    float4 colour : COLOR0;};void VS(in vsin input, out vsout output) {    //transform to world space    output.final = mul(float4(input.pos, 1.0), world);    //transform to homogenous view space    output.final = mul(output.final, viewProj);    //transform norm to world space    input.norm = mul(input.norm, (float3x3) world);    //calculate angle between view vector and sun direction    //viewer at centre of dome, so view vector = norm    float2 viewAngle;    viewAngle.x = dot(-lightDir, input.norm);    //calculate scaled viewing angle for rayleigh scattering function    //3/16pi * rayleigh * (2 + 0.5*cos2(theta))    viewAngle.y = 2.0 + 0.5*(viewAngle.x * viewAngle.x);    //calculate extinction terms    //1.0f - e^(-(rayleigh + mie) * ray length)    float3 extinction = 1.0 - exp((-rayleigh + mie)*input.tex.y);    //calculate henyey greenstein mie scattering approximation    //m = (1 - g^2)/(4pi(1 + g^2 + 2gcos(theta))^(3/2))    //hg = {1 - g^2, 1 + g^2, 2g, 4pi};    float temp = hg.x/(hg.w*pow(hg.y + hg.z*viewAngle.x, 1.5));    //calculate inscattering    //(r(theta) + m(theta))/(r + m)*sun*extinction;    float3 r = rayleigh2 * viewAngle.y;    float3 m = mie2 * temp;        float3 i = (r + m)*inscatter*sun.xyz*extinction;    i *= sun.w; //multiply by sun intensity    //output the final colour    float4 colour = {i.x, i.y, i.z, 1.0};    output.colour = colour;}struct psin {    float4 colour : COLOR0;};float4 PS(in psin input) : COLOR {    return input.colour;}technique sky {    pass P0 {        VertexShader = compile vs_2_0 VS();        PixelShader = compile ps_1_1 PS();    }}