# Atmospheric Scattering problem

This topic is 3660 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi. I have problem implementing optical depth approximation technique from this paper http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html Scale() function doesn't work proper or I don't know how to use it proper ;) When I compute myself optical length to the sun and to the camera it works well. Screenshot: http://screenup.pl/?l=W3UQ8EY http://screenup.pl/?l=0KPOG7O It's a bit inaccurate because of per vertex phase function but it doesn't matter. However, when I use O'Neil's approximation function the sun and atmosphere doesn't go reddish (because of wrong outscattering calculation) and there are artifacts. http://screenup.pl/?l=TI0T6J9 It's probably problem with angle what I am passing, but I really don't know what is wrong. This is my shader code, I have left some garbage before removing previous scattering technique.
#include "common_shader.fxh"

float perezY[5],perezx[5],perezy[5];
float perezFx, perezFy, perezFY;

struct VS_INPUT
{
float4 Position : POSITION0;

};

struct VS_OUTPUT
{
float4 Position : POSITION0;
float3 Color    : COLOR0;
};

/*
float perez(float cosTheta, float cosGamma, float gamma, float coef[5])
{
return (1 + coef[0]*exp(coef[1]/cosTheta)) * (1 + coef[2]*exp(coef[3]*gamma) + coef[4]*cosGamma*cosGamma);
}

float3 perezxyY(float cosSkyZen, float cosSkySun, float SkySun)
{
float3 ret;

ret.x = perezFx * perez(cosSkyZen,cosSkySun,SkySun,perezx);
ret.y = perezFy * perez(cosSkyZen,cosSkySun,SkySun,perezy);
ret.z = perezFY * perez(cosSkyZen,cosSkySun,SkySun,perezY);

return ret;
}

float3 xyYtoRGB(float3 xyY, float expos)
{
float3 rgb;

float X,Y,Z;
X=xyY.z/xyY.y*xyY.x;
Y=xyY.z;
Z=xyY.z/xyY.y*(1-xyY.x-xyY.y);

rgb.x= 3.2404*X - 1.5371*Y - 0.4985*Z;
rgb.y=-0.9692*X + 1.8759*Y + 0.0415*Z;
rgb.z= 0.0556*X - 0.2040*Y + 1.0573*Z;

return float3(1.0-exp(-expos*rgb));
}*/

float g = -0.990;
float ESun = 20;

float3 lambda = float3(0.650,0.570,0.475);

float Kr = 0.0025;
float Km = 0.0010;

float Re = 10.0;
//float atmosphereThickness = 0.025;

float Ra = 10.25;//Re*(1+atmosphereThickness);

float fAtmosphereScale = 4; // 1/(Ra-Re)

float fRayleighScaleDepth = 0.25;

float miePhase(float cosTheta)
{
return 1.5 * ((1.0-g*g) / (2.0 +g*g)) * (1.0 + cosTheta*cosTheta) / pow(1.0+g*g-2*g*cosTheta,1.5);
}

float rayleighPhase(float cosTheta)
{
return 0.75+0.75*cosTheta*cosTheta;
}

/*
float2 GetDensityMR(float height)
{
float alt = (height - Re) * scale;
return exp(-alt / scaleHeightMR);
}*/

float cameraHeight = 10;//Re; // nie wiem jaka powinna dokladnie byc ta wartosc to ustawiam taka

float raySphereIntersection(float3 sphereCenter, float r, float3 rayOrign, float3 rayDir)
{
float3 v = rayOrign - sphereCenter;
float b = dot(v,rayDir);
float delta = b*b - (dot(v,v) - r*r);
float sqrtdelta = sqrt(delta);
float t1 = -b + sqrtdelta;
float t2 = -b - sqrtdelta;

float nearest;
if(t2>0)
{
if(t1>0)
nearest=min(t1,t2);
else
nearest=t2;
}
else
nearest=t1;

return nearest;

}

float atmosphereDensity(float height)
{
return exp((Re - height)*fAtmosphereScale/fRayleighScaleDepth);
}

// oneilScale() * atmosphereDensity(height) = optical length: height -> top of atmosphere
float oneilScale(float fCos)
{
float x = 1.0 - fCos;
return fRayleighScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}

float opticalDepth(float3 A, float3 B)
{
float depth = 0;

float3 dir = B - A;
float len = length(dir);
dir/=len;

float scaledLen = len * fAtmosphereScale;
int numSamples = 10;
float sampleLen = scaledLen / numSamples;

float3 p = A;

for(int i = 0; i<=numSamples; i++)
{
float d = atmosphereDensity(length(p));

depth+=d*sampleLen;

p+= dir*sampleLen;
}

return depth;
}

VS_OUTPUT vs_main( VS_INPUT Input )
{

VS_OUTPUT Output;

Input.Position.xyz*=-5000;

//float cosSkySun = saturate(dot(toSky,vSunDir.xyz));
//float SkySun = acos(cosSkySun); // Y
//float cosSkyZen = saturate(toSky.y);

float3 position = float3(0,Re,0);
float3 rayDir = normalize(Input.Position.xyz);
float positionNormalized = normalize(position);
float rayDist = raySphereIntersection(float3(0,0,0),Ra,position,rayDir);

float cosSkySun = saturate(dot(rayDir,vSunDir.xyz));

int numSamples = 10;

float sampleLen = rayDist/numSamples;

//float totalMie = 0;
float3 totalScattering = 0;

float sampleScaled = sampleLen *fAtmosphereScale;

float3 samplePoint = position;

for(int i=0;i<=numSamples;i++)
{

float height = length(samplePoint);

float density = atmosphereDensity(height);
float sampleNormalized = samplePoint / height;
//float sunDepth = density*oneilScale(dot(sampleNormalized,vSunDir.xyz));
//	- density*oneilScale(dot(sampleNormalized,rayDir));

float3 sunAtm = samplePoint + vSunDir*raySphereIntersection(float3(0,0,0),Ra,samplePoint,vSunDir);

float sunDepth = opticalDepth(samplePoint,sunAtm);

totalScattering+= density*sampleScaled
*exp(
-density*(
oneilScale(dot(sampleNormalized,vSunDir.xyz))
-oneilScale(dot(sampleNormalized,rayDir))
)
*4*Pi*(pow(lambda,-4)*Kr+Km))
;
samplePoint+=rayDir*sampleScaled;
}

Output.Color=
totalScattering
*(1*
miePhase(-cosSkySun)*Km*20
+rayleighPhase(-cosSkySun)
*pow(lambda,-4)*Kr*20//;rayDist
)
;

//float3 xyY = perezxyY(cosSkyZen,cosSkySun,SkySun);
//Output.Color= applyHaze(float3(0,0,0),cosSkySun,rayDist);
//float4(xyYtoRGB(xyY,0.0001),1);

Input.Position.xz+=vViewPosition.xz;
Output.Position = mul( Input.Position, matViewProjection );

return( Output );

}

float4 ps_main(float3 Color    : COLOR0) : COLOR0
{
return float4(Color,1);

}

technique Terrain
{
pass Pass1
{
}
}


Sorry for my English, it's still doesn't well enough, but I hope you can understand my problem ;)

##### Share on other sites
You should check out this thread to see if the answer you are looking for is in there :

http://www.gamedev.net/community/forums/topic.asp?topic_id=461747

1. 1
Rutin
64
2. 2
3. 3
4. 4
5. 5

• 16
• 10
• 29
• 20
• 9
• ### Forum Statistics

• Total Topics
633413
• Total Posts
3011759
• ### Who's Online (See full list)

There are no registered users currently online

×

## Important Information

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!