Skip to content

Instantly share code, notes, and snippets.

@bzgeb
Created August 2, 2012 17:46
Show Gist options
  • Save bzgeb/3239074 to your computer and use it in GitHub Desktop.
Save bzgeb/3239074 to your computer and use it in GitHub Desktop.
///////////////////////////////////////////////////////////////////////////////
// ATMOSPHERIC SCATTERING
// Viewing the sky from within the atmosphere.
//
// Based on OGRE Forum user HexiDave's Atmospheric Scattering demo
// http://www.ogre3d.org/forums/viewtopic.php?t=37072
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// VARIABLES FROM OGRE
///////////////////////////////////////////////////////////////////////////////
// automatic from OGRE
uniform vec3 g_cameraPosition;
uniform vec4 g_lightPosition;
// manual from application
uniform vec3 g_invWavelengths;
uniform float g_globeRadius;
uniform float g_atmosphereRadius;
uniform float g_atmosphereRadiusSq;
uniform float g_Kr4PI;
uniform float g_Km4PI;
uniform float g_KrESun;
uniform float g_KmESun;
uniform float g_scale;
uniform float g_scaleDepth;
uniform float g_invScaleDepth;
uniform float g_scaleOverScaleDepth;
///////////////////////////////////////////////////////////////////////////////
// VARYINGS
///////////////////////////////////////////////////////////////////////////////
varying vec4 v_rayleighColour;
varying vec4 v_mieColour;
///////////////////////////////////////////////////////////////////////////////
// HELPERS
///////////////////////////////////////////////////////////////////////////////
// Returns the near intersection point of a line and a sphere
float getNearIntersection(vec3 v3Pos, vec3 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));
}
// The scale equation calculated by Vernier's Graphical Analysis
float scale(float fCos) {
float x = 1.0 - fCos;
return g_scaleDepth * 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 v3Pos = (gl_Vertex.xyz);
vec3 v3Ray = v3Pos - g_cameraPosition;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = g_cameraPosition;
float fDepth = exp((g_globeRadius - g_atmosphereRadius) * g_invScaleDepth);
float fCameraAngle = dot(-v3Ray, v3Pos) / length(v3Pos);
float fLightAngle = dot(g_lightPosition, v3Pos) / length(v3Pos);
float fCameraScale = scale(fCameraAngle);
float fLightScale = scale(fLightAngle);
float fCameraOffset = fDepth*fCameraScale;
float fTemp = (fLightScale + fCameraScale);
// initialize the scattering loop variables
float fSampleLength = fFar / 3.0;
float fScaledLength = fSampleLength * g_scale;
vec3 v3SampleRay = v3Ray * fSampleLength;
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
// now loop through the sample rays
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
vec3 v3Attenuate;
for(int i=0; i<3; i++) {
float fHeight = length(v3SamplePoint);
float fDepth = exp(g_scaleOverScaleDepth * (g_globeRadius - fHeight));
float fScatter = fDepth * fTemp - fCameraOffset;
v3Attenuate = exp(-fScatter * (g_invWavelengths * g_Kr4PI + g_Km4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
gl_Position = ftransform();
v_rayleighColour = vec4(v3FrontColor * (g_invWavelengths * g_KrESun + g_KmESun), 1.0);
v_mieColour = vec4(v3Attenuate, 1.0);
gl_TexCoord[0].xyz = g_cameraPosition.xyz - v3Pos.xyz;
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment