Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to implement atmospheric scattering based on Sean O`Neil algorithm that was published in GPU Gems 2. But I have some trouble getting the shader to work. My latest attempts resulted in: http://img253.imageshack.us/g/scattering01.png/

I've downloaded sample code of O`Neil from: http://http.download.nvidia.com/developer/GPU_Gems_2/CD/Index.html. Made minor adjustments to the shader 'SkyFromAtmosphere' that would allow it to run in AMD RenderMonkey.

In the images it is see-able a form of banding occurs, getting an blueish tone. However it is only applied to one half of the sphere, the other half is completely black. Also the banding appears to occur at Zenith instead of Horizon, and for a reason I managed to get pac-man shape.

I would appreciate it if somebody could show me what I'm doing wrong.

Vertex Shader:

uniform mat4 matView;
uniform vec4 view_position; 
uniform vec3 v3LightPos;      

const int   nSamples = 3;
const float fSamples = 3.0;
const vec3  Wavelength = vec3(0.650,0.570,0.475);

const vec3  v3InvWavelength = 1.0f / vec3( Wavelength.x * Wavelength.x * Wavelength.x * Wavelength.x,
                                           Wavelength.y * Wavelength.y * Wavelength.y * Wavelength.y, 
                                           Wavelength.z * Wavelength.z * Wavelength.z * Wavelength.z);  

const float fInnerRadius = 10;
const float fOuterRadius = fInnerRadius * 1.025;
const float fInnerRadius2 = fInnerRadius * fInnerRadius;
const float fOuterRadius2 = fOuterRadius * fOuterRadius;
const float fScale = 1.0 / (fOuterRadius - fInnerRadius);
const float fScaleDepth = 0.25;
const float fScaleOverScaleDepth = fScale / fScaleDepth;
const vec3  v3CameraPos = vec3(0.0, fInnerRadius * 1.015, 0.0);
const float fCameraHeight = length(v3CameraPos);
const float fCameraHeight2 = fCameraHeight * fCameraHeight;

const float fm_ESun  = 150.0;
const float fm_Kr    = 0.0025;
const float fm_Km    = 0.0010;
const float fKrESun = fm_Kr * fm_ESun;
const float fKmESun = fm_Km * fm_ESun;
const float fKr4PI = fm_Kr * 4 * 3.141592653;
const float fKm4PI = fm_Km * 4 * 3.141592653;

varying vec3 v3Direction;
varying vec4 c0, c1;


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))));
}


void main( void )
{           
   // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere)
   vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
   vec3 v3Pos = normalize(gl_Vertex.xyz) * fOuterRadius;
   vec3 v3Ray = v3CameraPos - v3Pos;
   float fFar = length(v3Ray);
   v3Ray = normalize(v3Ray);

   // Calculate the ray's starting position, then calculate its scattering offset
   vec3 v3Start = v3CameraPos;
   float fHeight = length(v3Start);
   float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fCameraHeight));
   float fStartAngle = dot(v3Ray, v3Start) / fHeight;
   float fStartOffset = fDepth*scale(fStartAngle);

   // Initialize the scattering loop variables
   float fSampleLength = fFar / fSamples;
   float fScaledLength = fSampleLength * fScale;
   vec3 v3SampleRay = v3Ray * fSampleLength;
   vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;       

   // Now loop through the sample rays 
   for(int i=0; i<nSamples; i++)
   {      
      float fHeight = length(v3SamplePoint);
      float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));      
      float fLightAngle =  dot(normalize(v3LightPos), v3SamplePoint) / fHeight;
      float fCameraAngle = dot(normalize(v3Ray), v3SamplePoint) / fHeight;              
      float fScatter = (-fStartOffset + fDepth*( scale(fLightAngle) - scale(fCameraAngle)))/* 0.25f*/;                         
      vec3 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

   vec4 newPos = vec4( (gl_Vertex.xyz + view_position.xyz), 1.0);          
   gl_Position = gl_ModelViewProjectionMatrix * vec4(newPos.xyz, 1.0);
   gl_Position.z = gl_Position.w * 0.99999;   
   c1 = vec4(v3FrontColor * fKmESun, 1.0);
   c0 = vec4(v3FrontColor * (v3InvWavelength * fKrESun), 1.0);      
   v3Direction = v3CameraPos - v3Pos;                   
}

Fragment Shader:

uniform vec3 v3LightPos; 
varying vec3 v3Direction;
varying vec4 c0;
varying vec4 c1;

const float g =-0.90f;
const float g2 = g * g;
const float Exposure =2;       

void main(void){          
   float fCos = dot(normalize(v3LightPos), v3Direction) / length(v3Direction);
   float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
   gl_FragColor = c0 + fMiePhase * c1;   
   gl_FragColor.a = 1.0;   
}
share|improve this question
6  
It is difficult to help you since the problem is very specific and what you need is basically a debugger. –  FxIII Jul 5 '11 at 10:35
    
the sky from atmosphere shader is meant to be used when the camera is positioned inside the atmosphere, you should be using the ***fromSpace shaders in this scenario. The ***fromAtmosphere shaders might simply not work for this point of view. Check if these issues are apparent at low altitudes, if they aren't, I'd say the shader is working fine EDIT: asked 1 year ago...guess I'm a bit late –  melak47 Apr 30 '12 at 15:10
add comment

1 Answer

You might want to take a look at this source code which does the same thing for osgEarth.

share|improve this answer
    
I've nicened a bit your link and added one to the osgEarth home page. You can have a look here to give your answers the look they deserve ;) Welcome to gamedev-SA! –  Laurent Couvidou May 14 '12 at 19:20
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.