# Atmospheric Scattering XNA 4.0

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

## Recommended Posts

Hello

Anyone out there who could help me..

 float4x4 World; float4x4 View; float4x4 Projection; float seaLevel; float Km = 0.0025f; float Kr = 0.0015f; float ESun = 20.0f; float3 v3InvWavelength = float3( 1.0f / pow(0.650f, 4), 1.0f / pow(0.570f, 4), 1.0f / pow(0.475f, 4) ); // The number of sample points taken along the ray static const int nSamples = 2; static const float fSamples = (float)nSamples; // Gravity static const float g = -0.99f; static const float g2 = 0.81f; // Shader Constants float3 v3CameraPos; // The camera's current position float3 v3LightPos; // The direction vector to the light source //float3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels float fCameraHeight; // The camera's current height float fCameraHeight2; // fCameraHeight^2 float fOuterRadius= 1.4f; // The outer (atmosphere) radius float fOuterRadius2 = (1.4f * 1.4f); // fOuterRadius^2 float fInnerRadius = 1.0f; // The inner (planetary) radius float fInnerRadius2 = (1.0f * 1.0f); // fInnerRadius^2 float fKrESun = (0.0015f * 10.0f); // Kr * ESun float fKmESun = (0.0025f * 10.0f);; // Km * ESun float fKr4PI = 0.0015f * 4.0f * 3.14159265; float fKm4PI = 0.0025f * 4 * 3.14159265; // Km * 4 * PI float fScaleDepth = 0.25f; // The scale depth (the altitude at which the average atmospheric density is found) float fInvScaleDepth = 1.0f / 0.25f; // 1 / fScaleDepth float fScale = 1.0f / (1.4f - 1.0f); float fScaleOverScaleDepth = (1.0f) / ( 1.0f / 0.25f); // fScale / fScaleDepth float scale(float fCos) { float x = 1.0 - fCos; return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); } // Calculates the Mie phase function float getMiePhase(float fCos, float fCos2, float g, float g2) { return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(abs(1.0 + g2 - 2.0*g*fCos), 1.5); } // Calculates the Rayleigh phase function float getRayleighPhase(float fCos2) { //return 1.0; return 0.75 + 0.75*fCos2; } // Returns the near intersection point of a line and a sphere float getNearIntersection(float3 v3Pos, float3 v3Ray, float fDistance2, float fRadius2) { float B = 2.0 * dot(v3Pos, v3Ray); float C = fDistance2 - fRadius2; float fDet = max(0.0, B*B - 4.0 * C); return 0.5 * (-B - sqrt(fDet)); } // Returns the far intersection point of a line and a sphere float getFarIntersection(float3 v3Pos, float3 v3Ray, float fDistance2, float fRadius2) { float B = 2.0 * dot(v3Pos, v3Ray); float C = fDistance2 - fRadius2; float fDet = max(0.0, B*B - 4.0 * C); return 0.5 * (-B + sqrt(fDet)); } struct VertexShaderInput { float4 Position : POSITION0; float3 PositionWS : TEXCOORD0; }; struct VertexShaderOutput { float4 Position : POSITION0; float3 PositionWS : TEXCOORD0; }; //############# VERTEX SHADER ############# VertexShaderOutput VertexShaderFunction(VertexShaderInput input) { VertexShaderInput output; output.PositionWS = input.Position; float4 worldPosition = mul(input.Position, World); worldPosition = float4( normalize(worldPosition.xyz) * 6918.75f, 1); float4 viewPosition = mul(worldPosition, View); output.Position = mul(viewPosition, Projection); return output; } //############# PIXEL SHADER ############# float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 { // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) float3 v3Pos = input.PositionWS; float3 v3Ray = v3Pos - v3CameraPos; float fFar = length(v3Ray); v3Ray /= fFar; // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere) float fNear = getNearIntersection(v3CameraPos, v3Ray, fCameraHeight2, fOuterRadius2); // Calculate the ray's start and end positions in the atmosphere, then calculate its scattering offset float3 v3Start = v3CameraPos + v3Ray * fNear; fFar -= fNear; float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius; float fStartDepth = exp(-fInvScaleDepth); float fStartOffset = fStartDepth*scale(fStartAngle); // Initialize the scattering loop variables float fSampleLength = fFar / fSamples; float fScaledLength = fSampleLength * fScale; float3 v3SampleRay = v3Ray * fSampleLength; float3 v3SamplePoint = v3Start + v3SampleRay * 0.5; // Now loop through the sample rays float3 v3FrontColor = float3(0.0, 0.0, 0.0); for(int i=0; i<nSamples; i++) { float fHeight = length(v3SamplePoint); float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight; float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight; float fScatter = (fStartOffset + fDepth*(scale(fLightAngle) - scale(fCameraAngle))); float3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI)); v3FrontColor += v3Attenuate * (fDepth * fScaledLength); v3SamplePoint += v3SampleRay; } // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader float3 c0 = v3FrontColor * (v3InvWavelength * fKrESun); float3 c1 = v3FrontColor * fKmESun; float3 v3Direction = v3CameraPos - v3Pos; float fCos = dot(v3LightPos, v3Direction) / length(v3Direction); float fCos2 = fCos*fCos; float3 color = getRayleighPhase(fCos2) * c0 + getMiePhase(fCos, fCos2, g, g2) * c1; float4 AtmoColor = float4(color, color.b); return AtmoColor; } //############# Technik ############# technique Technique1 { pass Pass1 { CullMode = ccw; VertexShader = compile vs_3_0 VertexShaderFunction(); PixelShader = compile ps_3_0 PixelShaderFunction(); } } 

And here the Sphere.cs:

 public class ScatteringSphere { private GraphicsDevice device; private VertexBuffer vb; private IndexBuffer ib; private Effect effect; private static int size = 128; Matrix[] rotation = new Matrix[6]; Vector3 lightPos; public ScatteringSphere(GraphicsDevice device) { this.device = device; effect = Manager.cManager.Load<Effect>("Effekte\\SpaceToSky"); CreateSphere(); rotation[0] = Matrix.CreateRotationX(MathHelper.ToRadians(180)) * Matrix.CreateTranslation(Vector3.Down); rotation[1] = Matrix.CreateTranslation(Vector3.Up); rotation[2] = Matrix.CreateRotationX(MathHelper.ToRadians(90)) * Matrix.CreateTranslation(Vector3.Backward); rotation[3] = Matrix.CreateRotationX(MathHelper.ToRadians(270)) * Matrix.CreateTranslation(Vector3.Forward); rotation[4] = Matrix.CreateRotationZ(MathHelper.ToRadians(270)) * Matrix.CreateTranslation(Vector3.Right); rotation[5] = Matrix.CreateRotationZ(MathHelper.ToRadians(90)) * Matrix.CreateTranslation(Vector3.Left); } private void CreateSphere() { VertexPositionColor[] vertices = new VertexPositionColor[size * size]; for (int z = 0; z < size; z++) for (int x = 0; x < size; x++) vertices[x + z * size] = new VertexPositionColor(new Vector3(MathHelper.Lerp(-1, 1, (float)x / (size - 1)), 0, MathHelper.Lerp(-1, 1, (float)z / (size - 1))), Color.Aquamarine); vb = new VertexBuffer(device, typeof(VertexPositionColor), size * size, BufferUsage.WriteOnly); vb.SetData<VertexPositionColor>(vertices); ushort[] indices = new ushort[(size - 1) * (size - 1) * 6]; int i = 0; for (int z = 0; z < size - 1; z++) for (int x = 0; x < size - 1; x++) { ushort upperleft = (ushort)(z * size + x); ushort upperright = (ushort)(upperleft + 1); ushort lowerleft = (ushort)(upperleft + size); ushort lowerright = (ushort)(lowerleft + 1); indices[i++] = upperleft; indices[i++] = upperright; indices[i++] = lowerleft; indices[i++] = lowerleft; indices[i++] = upperright; indices[i++] = lowerright; } ib = new IndexBuffer(device, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly); ib.SetData<ushort>(indices); } public void Draw(FreeCam cam) { device.SetVertexBuffer(vb); device.Indices = ib; lightPos = new Vector3(0.5f, 0.5f, -0.5f); lightPos.Normalize(); effect.Parameters["seaLevel"].SetValue(6750); effect.Parameters["View"].SetValue(Manager.cam.View); effect.Parameters["Projection"].SetValue(Manager.cam.Projection); effect.Parameters["v3CameraPos"].SetValue(Manager.cam.Position); effect.Parameters["v3LightPos"].SetValue(lightPos); effect.Parameters["fCameraHeight"].SetValue(Manager.cam.Position.Length()); effect.Parameters["fCameraHeight2"].SetValue(Manager.cam.Position.LengthSquared()); effect.Parameters["World"].SetValue(rotation[0]); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, size * size, 0, (size - 1) * (size - 1) * 6 / 3); } effect.Parameters["World"].SetValue(rotation[1]); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, size * size, 0, (size - 1) * (size - 1) * 6 / 3); } effect.Parameters["World"].SetValue(rotation[2]); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, size * size, 0, (size - 1) * (size - 1) * 6 / 3); } effect.Parameters["World"].SetValue(rotation[3]); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, size * size, 0, (size - 1) * (size - 1) * 6 / 3); } effect.Parameters["World"].SetValue(rotation[4]); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, size * size, 0, (size - 1) * (size - 1) * 6 / 3); } effect.Parameters["World"].SetValue(rotation[5]); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, size * size, 0, (size - 1) * (size - 1) * 6 / 3); } } } 

AA Edited by montify

Job Done

1. 1
2. 2
Rutin
18
3. 3
4. 4
5. 5

• 26
• 11
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633701
• Total Posts
3013442
×